Initialize Tizen 2.3 tizen_2.3 2.3a_release submit/tizen_2.3/20140531.092559 submit/tizen_2.3/20150202.070022 tizen_2.3_release
authorSehong Na <sehong.na@samsung.com>
Sat, 31 May 2014 03:49:18 +0000 (12:49 +0900)
committerSehong Na <sehong.na@samsung.com>
Sat, 31 May 2014 03:49:18 +0000 (12:49 +0900)
30 files changed:
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README [new file with mode: 0644]
configure.ac [new file with mode: 0644]
include/X11/extensions/XKBbells.h [new file with mode: 0644]
include/X11/extensions/XKBconfig.h [new file with mode: 0644]
include/X11/extensions/XKBfile.h [new file with mode: 0644]
include/X11/extensions/XKBrules.h [new file with mode: 0644]
include/X11/extensions/XKM.h [new file with mode: 0644]
include/X11/extensions/XKMformat.h [new file with mode: 0644]
packaging/libxkbfile.spec [new file with mode: 0755]
src/Makefile.am [new file with mode: 0644]
src/XKBfileInt.h [new file with mode: 0644]
src/cout.c [new file with mode: 0644]
src/magic [new file with mode: 0644]
src/maprules.c [new file with mode: 0644]
src/srvmisc.c [new file with mode: 0644]
src/xkbatom.c [new file with mode: 0644]
src/xkbbells.c [new file with mode: 0644]
src/xkbconfig.c [new file with mode: 0644]
src/xkbdraw.c [new file with mode: 0644]
src/xkberrs.c [new file with mode: 0644]
src/xkbmisc.c [new file with mode: 0644]
src/xkbout.c [new file with mode: 0644]
src/xkbtext.c [new file with mode: 0644]
src/xkmout.c [new file with mode: 0644]
src/xkmread.c [new file with mode: 0644]
xkbfile.pc.in [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d013932
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,66 @@
+Copyright (c) 1994-1996 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Copyright 1987, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..f8aed80
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,589 @@
+commit 5e3da29093ff5d5b6b8805467a523d5cb7663965
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Wed Mar 7 20:37:20 2012 -0800
+
+    libxkbfile 1.0.8
+
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 7b6123644fe23c2eb9816cf00729253b2dd53b23
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Wed Sep 28 18:17:15 2011 -0700
+
+    Add const attributes to fix gcc -Wwrite-strings warnings
+
+    Does not fix all of them, as some affect the API and thus need more analysis.
+
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+    Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit 0c2c504819b8788075115f848343bd45a3bb6605
+Author: Jeremy Huddleston <jeremyhu@apple.com>
+Date:   Fri Nov 11 10:37:49 2011 -0800
+
+    Include strings.h for strcasecmp
+
+    Our minimum requirement for X11 is currently Unix98.  Unix98 provides
+    strcasecmp in <strings.h>.  This commit fixes implicit declarations
+    of this function on systems that closely adhere to the standard.
+
+    Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit 9ffdecdfa0a832a129a97735eaf1d22ec6defc13
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Fri Sep 16 22:45:06 2011 -0700
+
+    Strip trailing whitespace
+
+    Performed with: find * -type f | xargs perl -i -p -e 's{[ \t]+$}{}'
+    git diff -w & git diff -b show no diffs from this change
+
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit cfc92c9b8e5f511010a2e406b147dec3ce64c6fd
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Wed Feb 2 11:43:46 2011 -0500
+
+    config: comment, minor upgrade, quote and layout configure.ac
+
+    Group statements per section as per Autoconf standard layout
+    Quote statements where appropriate.
+    Autoconf recommends not using dnl instead of # for comments
+
+    Use AC_CONFIG_FILES to replace the deprecated AC_OUTPUT with parameters.
+    Add AC_CONFIG_SRCDIR([Makefile.am])
+    Remove redundant AC_SUBST(*_CFLAGS) and/or *_LIBS
+    Update minimum version of util-macros to at least 1.8.
+    No functional configuration changes
+
+    This helps automated maintenance and release activities.
+    Details can be found in http://wiki.x.org/wiki/NewModuleGuidelines
+
+commit f83b3bda908cd6d0e15287d15739344620f12d27
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Fri Jan 28 19:41:37 2011 -0500
+
+    config: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS
+
+    Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit edc2a2beea14adef6c833bef456474039e2afab2
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Thu Jan 27 18:50:15 2011 -0500
+
+    config: remove AC_PROG_CC as it overrides AC_PROG_C_C99
+
+    XORG_STRICT_OPTION from XORG_DEFAULT_OPTIONS calls
+    AC_PROG_C_C99. This sets gcc with -std=gnu99.
+    If AC_PROG_CC macro is called afterwards, it resets CC to gcc.
+
+    Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 5eea77b2c35c10baf899d2b03a85a462fdcf8f93
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Fri Oct 29 18:16:00 2010 -0700
+
+    libxkbfile 1.0.7
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit ce593fce1f7930135d1c52711ef1945a3e7418b0
+Author: Jesse Adkins <jesserayadkins@gmail.com>
+Date:   Tue Sep 28 13:30:04 2010 -0700
+
+    Purge cvs tags.
+    
+    Signed-off-by: Jesse Adkins <jesserayadkins@gmail.com>
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 57c03e52e6b4e3ed54df5fdd778865467d08e119
+Author: Fernando Carrijo <fcarrijo@yahoo.com.br>
+Date:   Thu Jul 1 06:59:48 2010 -0300
+
+    Purge macro NEED_EVENTS
+    
+    Signed-off-by: Fernando Carrijo <fcarrijo@yahoo.com.br>
+    Acked-by: Tiago Vignatti <tiago.vignatti@nokia.com>
+    Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+
+commit 2db176bf5c644cf974f9137bda19e997500d04b1
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Mon Mar 29 16:50:34 2010 -0400
+
+    config: update AC_PREREQ statement to 2.60
+    
+    Unrelated to the previous patches, the new value simply reflects
+    the reality that the minimum level for autoconf to configure
+    all x.org modules is 2.60 dated June 2006.
+    
+    ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz
+    
+    Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit bce9d460a8759c866908c945ceb609de6bf03921
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Mon Mar 29 14:53:49 2010 -0400
+
+    config: remove the pkgconfig pc.in file from EXTRA_DIST
+    
+    Automake always includes it in the tarball.
+    
+    Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+
+commit 79cb4add177bee5dd451a8d459cb344451ea04a8
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Fri Nov 27 20:56:05 2009 -0500
+
+    Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES
+    
+    Now that the INSTALL file is generated.
+    Allows running make maintainer-clean.
+
+commit 8f2565e71d91a81ab0fe11ac7052c9f4bdfcd8fa
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Wed Oct 28 14:09:11 2009 -0400
+
+    INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206
+    
+    Add missing INSTALL file. Use standard GNU file on building tarball
+    README may have been updated
+    Remove AUTHORS file as it is empty and no content available yet.
+    Remove NEWS file as it is empty and no content available yet.
+
+commit 6e0c505690db8bedc6cbce726bc02b049e1dafa6
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Tue Oct 27 15:07:25 2009 -0400
+
+    Deploy the new XORG_DEFAULT_OPTIONS #24242
+    
+    This macro aggregate a number of existing macros that sets commmon
+    X.Org components configuration options. It shields the configuration file from
+    future changes.
+
+commit 5b797b80804946573313e1202c0ef89ce8980bf8
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Mon Oct 26 22:08:43 2009 -0400
+
+    Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432
+    
+    ChangeLog filename is known to Automake and requires no further
+    coding in the makefile.
+
+commit fd0dd9539d3bb2471c26187c96b55a542d754c30
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Thu Oct 22 12:34:20 2009 -0400
+
+    .gitignore: use common defaults with custom section # 24239
+    
+    Using common defaults will reduce errors and maintenance.
+    Only the very small or inexistent custom section need periodic maintenance
+    when the structure of the component changes. Do not edit defaults.
+
+commit 2ce3061947dfaf113d6c324efb2b82be2fae028e
+Author: Jeremy Huddleston <jeremyhu@freedesktop.org>
+Date:   Wed Oct 21 12:47:27 2009 -0700
+
+    This is not a GNU project, so declare it foreign.
+    
+    On Wed, 2009-10-21 at 13:36 +1000, Peter Hutterer wrote:
+    > On Tue, Oct 20, 2009 at 08:23:55PM -0700, Jeremy Huddleston wrote:
+    > > I noticed an INSTALL file in xlsclients and libXvMC today, and it
+    > > was quite annoying to work around since 'autoreconf -fvi' replaces
+    > > it and git wants to commit it.  Should these files even be in git?
+    > > Can I nuke them for the betterment of humanity and since they get
+    > > created by autoreconf anyways?
+    >
+    > See https://bugs.freedesktop.org/show_bug.cgi?id=24206
+    
+    As an interim measure, replace AM_INIT_AUTOMAKE([dist-bzip2]) with
+    AM_INIT_AUTOMAKE([foreign dist-bzip2]). This will prevent the generation
+    of the INSTALL file. It is also part of the 24206 solution.
+    
+    Signed-off-by: Jeremy Huddleston <jeremyhu@freedesktop.org>
+
+commit fa9520d5a63e181c05dd850223a1916e37e71a13
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Tue Oct 6 17:08:58 2009 -0700
+
+    libxkbfile 1.0.6
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit a3d95aedf3a6d1859387fb08b46cd66cd61cec83
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Tue Oct 6 17:05:00 2009 -0700
+
+    Migrate to xorg macros 1.3 & XORG_DEFAULT_OPTIONS
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit d36a99d961c6649ca1b0319c2aadc6763edb07ad
+Author: Adam Jackson <ajax@redhat.com>
+Date:   Fri May 8 14:15:21 2009 -0400
+
+    Semi-revert 33b839e16fe681ba915658f824ceb1b252084ea4
+    
+    _XkbDupString() checks for NULL, strdup doesn't.  Still, implement in
+    terms of real strdup and skip the calloc.
+
+commit 29f27b16dbe511a27a0e953b32913f9d9bf24f2d
+Author: Adam Jackson <ajax@redhat.com>
+Date:   Thu May 7 16:59:59 2009 -0400
+
+    Use flockfile if available.
+    
+    Not really a huge improvement, but we might as well.
+
+commit 33b839e16fe681ba915658f824ceb1b252084ea4
+Author: Adam Jackson <ajax@redhat.com>
+Date:   Thu May 7 16:31:39 2009 -0400
+
+    s/_XkbDupString/strdup/
+    
+    Super special bonus lols edition: _XkbDupString would allocate the new
+    string with calloc, just to be extra sure.
+
+commit 4f8dd1aa10a36700bf1f2b05931cd29151b9fee4
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Mon Feb 2 20:34:39 2009 -0800
+
+    Add README with pointers to mailing list, bugzilla & git repos
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
+
+commit d17cd6e80f1ec78b69ba11ee55465420e6d7e9a9
+Author: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>
+Date:   Thu Jan 29 19:52:34 2009 -0200
+
+    Janitor: distcheck, compiler warnings, .gitignore.
+
+commit dd9514fe714d81b881a1bd6bd88d4287adc5fc7e
+Author: Kees Cook <kees.cook@canonical.com>
+Date:   Tue Jan 13 15:40:37 2009 -0800
+
+    Fix static buffer overflow in "xkbcomp -C :0"
+    
+    This patch uses dynamically allocated strings instead of the fixed-length
+    buffers to avoid stack overflows.
+    
+    https://bugs.freedesktop.org/show_bug.cgi?id=19490
+    https://bugs.launchpad.net/ubuntu/+source/x11-xkb-utils/+bug/309013
+    
+    Signed-off-by: Kees Cook <kees.cook@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+
+commit e695be2ab7eb1361b204f98c3da872eff58ad6b5
+Author: Alexey Ten <alexeyten+github@gmail.com>
+Date:   Thu Jan 15 01:39:01 2009 +0300
+
+    Apply partial matches for option (#19563)
+    
+    Rules which match star (*) and option, like one below, should be applied
+    
+    layout[2] option    = symbols
+    *         misc:typo = +typo(base)
+    
+    X.Org bug 19563 <http://bugs.freedesktop.org/show_bug.cgi?id=19563>
+    
+    Signed-off-by: Sergey V. Udaltsov <svu@gnome.org>
+
+commit 415a513387748e1763a477a486a9789f88784ec5
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Mon Mar 17 19:44:07 2008 -0700
+
+    Version bump: 1.0.5
+
+commit 4505577c4d6b5d32c276366ce6bc3eda1cd59ad7
+Author: James Cloos <cloos@jhcloos.com>
+Date:   Thu Dec 6 16:38:53 2007 -0500
+
+    Replace static ChangeLog with dist-hook to generate from git log
+
+commit 492cd9bfc642443d92f419964334f59b89329a36
+Author: Daniel Drake <ddrake@brontes3d.com>
+Date:   Tue May 29 12:51:00 2007 -0800
+
+    Bug #11094: libxkbfile COPYING file
+    
+    X.Org Bugzilla #11094 <https://bugs.freedesktop.org/show_bug.cgi?id=11094>
+
+commit 360c792528d614a8aa90ad665081d5bd6ae6197c
+Author: Adam Jackson <ajax@benzedrine.nwnk.net>
+Date:   Fri Oct 13 16:19:53 2006 -0400
+
+    Bump to 1.0.4
+
+commit f587c01ee30c2814d199d3782b53834161cfa2b7
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Thu Sep 28 11:12:11 2006 -0700
+
+    Do not have to have "have have" in config.h comment if we don't have strcasecmp
+
+commit 62c3534debc688a39ccf34e60f7bf4d56fef0c11
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Thu Sep 28 11:10:16 2006 -0700
+
+    Add *~ to gitignore to skip over emacs droppings
+
+commit 1ea09901056ecc74e8554a4225366a7ba633e834
+Author: Alan Coopersmith <alan.coopersmith@sun.com>
+Date:   Thu Jul 13 14:59:19 2006 -0700
+
+    renamed: .cvsignore -> .gitignore
+
+commit b221428cfe5ca036398571372b88cf07da7c58d8
+Author: Adam Jackson <ajax@nwnk.net>
+Date:   Thu Apr 27 00:16:37 2006 +0000
+
+    Bump to 1.0.3
+
+commit 5e5bd096ba38294f43a071def16f8a397e22eb79
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Wed Apr 12 11:29:43 2006 +0000
+
+    Fix offline operation.
+
+commit 5f400a68ee489a1d9206605870b8d4306236170e
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Mon Apr 10 10:11:35 2006 +0000
+
+    Really fix typos.
+
+commit 3885559f436ed4ee84ebf90bf3d39648e16f5b3b
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Mon Apr 10 08:47:40 2006 +0000
+
+    Fix stupid typos. (Shang-Feng Yang)
+
+commit c3bc59c223ce4de8d6cce98c005a8f44bfa600c6
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sun Apr 9 13:45:31 2006 +0000
+
+    Coverity #265: Fix potential NULL dereference.
+
+commit 816a8db3264bc0752a8befd865b802ac4a2382ce
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sun Apr 9 13:16:44 2006 +0000
+
+    Coverity #776, #777: Fix memory leaks.
+
+commit 405ef7f445a41eb9995304b4c68b1c966a16bc20
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Fri Apr 7 16:19:02 2006 +0000
+
+    Coverity #787, 788: Fix memory leaks.
+
+commit d173f9d6561b223de0bf79603d303427da668a98
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Fri Apr 7 16:01:03 2006 +0000
+
+    Coverity #979, #980, #981: Avoid potential NULL dereferences.
+
+commit bf3fad9eff30bba4587548303dd3d96f3da5d494
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Fri Apr 7 15:58:58 2006 +0000
+
+    Coverity #982: Fix potential NULL dereference.
+
+commit 25e8b874b9f58e5e8035957465252539df13a85d
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Fri Apr 7 15:44:40 2006 +0000
+
+    Fix signed vs unsigned char hilarity. (Bill Crawford)
+
+commit 47dfc83937ed98e964716345cb4c8d817ae13e61
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Mon Mar 27 21:11:01 2006 +0000
+
+    Bug #3819: Fix serious botching of _XkbStrCaseCmp commit.
+
+commit e61dfbf6c72369f83a833d3a5a04c306a6b289f8
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sat Mar 25 23:15:58 2006 +0000
+
+    Bug #3819: Change open-coded _XkbStrCaseCmp to strcmp + tolower.
+
+commit 4b0ad25354d5807fc9e77fda3397ee78332502c1
+Author: Adam Jackson <ajax@nwnk.net>
+Date:   Tue Feb 28 22:44:54 2006 +0000
+
+    Bump to 1.0.2.
+
+commit 514262ec90db007dfce2c1523b2bc67988f395f1
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Tue Feb 28 16:55:26 2006 +0000
+
+    Bug #5216: Allow options to appear with other components.
+
+commit 46a7219986b402cb2ad4cfef2aa69d27f5508b6f
+Author: Kevin E Martin <kem@kem.org>
+Date:   Wed Dec 21 02:30:06 2005 +0000
+
+    Update package version for X11R7 release.
+
+commit 4949a1f5d3de102195033e5f6513a595c06326cd
+Author: Adam Jackson <ajax@nwnk.net>
+Date:   Mon Dec 19 16:28:28 2005 +0000
+
+    Stub COPYING files
+
+commit 8e69b154d42e77f91135382047b9df668406a972
+Author: Kevin E Martin <kem@kem.org>
+Date:   Thu Dec 15 00:24:36 2005 +0000
+
+    Update package version number for final X11R7 release candidate.
+
+commit fa100dc7f5ee32ae37afc0323d72ff521bd5371a
+Author: Kevin E Martin <kem@kem.org>
+Date:   Sat Dec 3 05:49:46 2005 +0000
+
+    Update package version number for X11R7 RC3 release.
+
+commit 26d800bab72f25e0088bf048b220eb96d6d1cf3f
+Author: Kevin E Martin <kem@kem.org>
+Date:   Sat Nov 19 07:15:48 2005 +0000
+
+    Update pkgconfig files to separate library build-time dependencies from
+        application build-time dependencies, and update package deps to work
+        with separate build roots.
+
+commit b6e194b20a83f9f059037aa17fbb00a6d34e53a6
+Author: Kevin E Martin <kem@kem.org>
+Date:   Wed Oct 19 02:48:13 2005 +0000
+
+    Update package version number for RC1 release.
+
+commit da83a9c6e3a85adcd30949f3c1ccd0d57a6a2bfa
+Author: Kevin E Martin <kem@kem.org>
+Date:   Mon Oct 3 15:20:29 2005 +0000
+
+    magic lives in src, so add it to EXTRA_DIST there instead
+
+commit 8b1f515abc3e5c54103ea04ce1de856dcf0a2865
+Author: Alan Coopersmith <Alan.Coopersmith@sun.com>
+Date:   Sat Oct 1 06:22:01 2005 +0000
+
+    Add magic to EXTRA_DIST
+
+commit 2baa710ffb0cb1567df8740e52477228e251a990
+Author: Adam Jackson <ajax@nwnk.net>
+Date:   Wed Aug 3 03:28:04 2005 +0000
+
+    Do PKG_CHECK_MODULES on a unique token instead of on "DEP", so builds with
+        a global configure cache don't get confused.
+
+commit cb43c4a949dc657abd9b0f52d4d6307e00a72ddf
+Author: Kevin E Martin <kem@kem.org>
+Date:   Fri Jul 29 21:22:54 2005 +0000
+
+    Various changes preparing packages for RC0:
+    - Verify and update package version numbers as needed
+    - Implement versioning scheme
+    - Change bug address to point to bugzilla bug entry form
+    - Disable loadable i18n in libX11 by default (use --enable-loadable-i18n to
+        reenable it)
+    - Fix makedepend to use pkgconfig and pass distcheck
+    - Update build script to build macros first
+    - Update modular Xorg version
+
+commit 494e792dc3328787fd7a4598454dc19115aac856
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sat Jul 16 07:52:50 2005 +0000
+
+    Set soversion to 1.0.0 using -version-number.
+
+commit c0b9196c7148715dde385d2f0d41d56d23839825
+Author: Keith Packard <keithp@keithp.com>
+Date:   Sat Jul 9 21:20:35 2005 +0000
+
+    Add .cvsignore files Switch _la_CFLAGS for AM_CFLAGS to clean up directory
+
+commit bf6ca6fc3ef9bd61284dc48059d10a560e5c1f28
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sun Jul 3 07:37:33 2005 +0000
+
+    Fix more include paths; add dix-config.h to XKB code.
+
+commit 70a39df3be6fcfea3746e0e127f3cde03a538869
+Author: Daniel Stone <daniel@fooishbar.org>
+Date:   Sun Jul 3 07:01:01 2005 +0000
+
+    Add Xtrans definitions (FONT_t, TRANS_CLIENT) to clean up warnings.
+    Add XSERV_t, TRANS_SERVER, TRANS_REOPEN to quash warnings.
+    Add #include <dix-config.h> or <xorg-config.h>, as appropriate, to all
+        source files in the xserver/xorg tree, predicated on defines of
+        HAVE_{DIX,XORG}_CONFIG_H. Change all Xfont includes to
+        <X11/fonts/foo.h>.
+
+commit abca6e76c667a201bf23b73bd681a8c4da892e62
+Author: Kevin E Martin <kem@kem.org>
+Date:   Sat Jul 2 06:35:04 2005 +0000
+
+    Add appropriate lib*_CFLAGS to Makefile.am's -- fixes build problems
+
+commit e5ddd6b3020045b7d8426618fd2515bc02ca045d
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date:   Mon Jun 13 22:54:28 2005 +0000
+
+    Makefile.am: Add $(top_srcdir)/include to INCLUDES
+
+commit 019fc282d476d3dd8f79e0472d3868f6a0785a56
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date:   Mon Jun 13 21:51:46 2005 +0000
+
+    Add xkbfile to symlink.sh, conditionally include "config.h" in
+        xc/lib/xkbfile
+
+commit 43a2d4898c64c11101b500ab12466570d747ce5f
+Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk>
+Date:   Mon Jun 13 21:49:05 2005 +0000
+
+    - Add xkbfile build system
+
+commit adef71d31514413062d20858b270801627e32cad
+Author: Egbert Eich <eich@suse.de>
+Date:   Fri Apr 23 18:44:26 2004 +0000
+
+    Merging XORG-CURRENT into trunk
+
+commit 33f9904e1895629319e58ac55da537771cf5bfa5
+Author: Egbert Eich <eich@suse.de>
+Date:   Sun Mar 14 08:32:39 2004 +0000
+
+    Importing vendor version xf86-4_4_99_1 on Sun Mar 14 00:26:39 PST 2004
+
+commit 672fe3b619cec43314adff06401e83046f4bc59f
+Author: Egbert Eich <eich@suse.de>
+Date:   Wed Mar 3 12:11:45 2004 +0000
+
+    Importing vendor version xf86-4_4_0 on Wed Mar 3 04:09:24 PST 2004
+
+commit ca6597857e417ee89ca15889e87211421b0df842
+Author: Egbert Eich <eich@suse.de>
+Date:   Thu Feb 26 13:35:36 2004 +0000
+
+    readding XFree86's cvs IDs
+
+commit 084119505a1927600985675a54b40316edd50c63
+Author: Egbert Eich <eich@suse.de>
+Date:   Thu Feb 26 09:22:54 2004 +0000
+
+    Importing vendor version xf86-4_3_99_903 on Wed Feb 26 01:21:00 PST 2004
+
+commit 91ac80641f0e04536ffe9d4168a19ba3d7ee050d
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date:   Tue Nov 25 19:28:21 2003 +0000
+
+    XFree86 4.3.99.16 Bring the tree up to date for the Cygwin folks
+
+commit cb45b671537b25c832428c0a75cb7d7712dea3e5
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date:   Fri Nov 14 16:48:50 2003 +0000
+
+    XFree86 4.3.0.1
+
+commit 52a8406aaba4ed1f9fa5e78bfa5da7af659bce01
+Author: Kaleb Keithley <kaleb@freedesktop.org>
+Date:   Fri Nov 14 15:54:40 2003 +0000
+
+    R6.6 is the Xorg base-line
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..c9fd2c0
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,290 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008 Free Software Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  6. Often, you can also type `make uninstall' to remove the installed
+     files again.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *Note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..ae1edc1
--- /dev/null
@@ -0,0 +1,37 @@
+#
+#  Copyright 2005  Red Hat, Inc.
+#
+#  Permission to use, copy, modify, distribute, and sell this software and its
+#  documentation for any purpose is hereby granted without fee, provided that
+#  the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation, and that the name of Red Hat not be used in
+#  advertising or publicity pertaining to distribution of the software without
+#  specific, written prior permission.  Red Hat makes no
+#  representations about the suitability of this software for any purpose.  It
+#  is provided "as is" without express or implied warranty.
+#
+#  RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+#  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+#  EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+#  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+#  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+#  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+#  PERFORMANCE OF THIS SOFTWARE.
+
+SUBDIRS = src
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xkbfile.pc
+
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+       $(INSTALL_CMD)
+
+ChangeLog:
+       $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..84be6b3
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+
+All questions regarding this software should be directed at the
+Xorg mailing list:
+
+        http://lists.freedesktop.org/mailman/listinfo/xorg
+
+Please submit bug reports to the Xorg bugzilla:
+
+        https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+
+The master development code repository can be found at:
+
+        git://anongit.freedesktop.org/git/xorg/lib/libxkbfile
+
+        http://cgit.freedesktop.org/xorg/lib/libxkbfile
+
+For patch submission instructions, see:
+
+       http://www.x.org/wiki/Development/Documentation/SubmittingPatches
+
+For more information on the git code manager, see:
+
+        http://wiki.x.org/wiki/GitPage
+
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..1efaaeb
--- /dev/null
@@ -0,0 +1,55 @@
+
+#  Copyright 2005 Red Hat, Inc.
+#
+#  Permission to use, copy, modify, distribute, and sell this software and its
+#  documentation for any purpose is hereby granted without fee, provided that
+#  the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation, and that the name of Red Hat not be used in
+#  advertising or publicity pertaining to distribution of the software without
+#  specific, written prior permission.  Red Hat makes no
+#  representations about the suitability of this software for any purpose.  It
+#  is provided "as is" without express or implied warranty.
+#
+#  RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+#  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+#  EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+#  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+#  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+#  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+#  PERFORMANCE OF THIS SOFTWARE.
+#
+
+# Initialize Autoconf
+AC_PREREQ([2.60])
+AC_INIT([libxkbfile], [1.0.8],
+        [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libxkbfile])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+# Initialize libtool
+AC_PROG_LIBTOOL
+
+# Require X.Org macros 1.8 or later for AC_PROG_INSTALL
+m4_ifndef([XORG_MACROS_VERSION],
+          [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.8)
+XORG_DEFAULT_OPTIONS
+
+# Checks for library functions.
+AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1,
+                                        [Do not have 'strcasecmp'.]))
+AC_CHECK_FUNC(getc_unlocked, AC_DEFINE([HAVE_UNLOCKED_STDIO], 1,
+                                      ['Unlocked stdio']), [])
+
+# Obtain compiler/linker options for depedencies
+PKG_CHECK_MODULES(XKBFILE, x11 kbproto)
+
+AC_CONFIG_FILES([Makefile
+               src/Makefile
+               xkbfile.pc])
+AC_OUTPUT
diff --git a/include/X11/extensions/XKBbells.h b/include/X11/extensions/XKBbells.h
new file mode 100644 (file)
index 0000000..585b36a
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef _XKBBELLS_H_
+#define        _XKBBELLS_H_ 1
+
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#define        XkbBN_Info                      "Info"
+#define        XkbBN_Warning                   "Warning"
+#define        XkbBN_MinorError                "MinorError"
+#define        XkbBN_MajorError                "MajorError"
+#define        XkbBN_BadValue                  "BadValue"
+#define        XkbBN_InvalidLocation           "InvalidLocation"
+#define        XkbBN_Question                  "Question"
+#define        XkbBN_Start                     "Start"
+#define        XkbBN_End                       "End"
+#define        XkbBN_Success                   "Success"
+#define        XkbBN_Failure                   "Failure"
+#define        XkbBN_Wait                      "Wait"
+#define        XkbBN_Proceed                   "Proceed"
+#define        XkbBN_Ignore                    "Ignore"
+#define        XkbBN_Iconify                   "Iconify"
+#define        XkbBN_Deiconify                 "Deconify"
+#define        XkbBN_Open                      "Open"
+#define        XkbBN_Close                     "Close"
+#define        XkbBN_TerminalBell              "TerminalBell"
+#define        XkbBN_MarginBell                "MarginBell"
+#define        XkbBN_CursorStuck               "CursorStuck"
+#define        XkbBN_NewMail                   "NewMail"
+#define        XkbBN_LaunchApp                 "LaunchApp"
+#define        XkbBN_AppDeath                  "AppDeath"
+#define        XkbBN_ImAlive                   "ImAlive"
+#define        XkbBN_ClockChimeHour            "ClockChimeHour"
+#define        XkbBN_ClockChimeHalf            "ClockChimeHalf"
+#define        XkbBN_ClockChimeQuarter         "ClockChimeQuarter"
+#define        XkbBN_RepeatingLastBell         "RepeatingLastBell"
+#define XkbBN_ComposeFail              "ComposeFail"
+#define        XkbBN_AX_FeatureOn              "AX_FeatureOn"
+#define        XkbBN_AX_FeatureOff             "AX_FeatureOff"
+#define        XkbBN_AX_FeatureChange          "AX_FeatureChange"
+#define        XkbBN_AX_IndicatorOn            "AX_IndicatorOn"
+#define        XkbBN_AX_IndicatorOff           "AX_IndicatorOff"
+#define        XkbBN_AX_IndicatorChange        "AX_IndicatorChange"
+#define        XkbBN_AX_SlowKeysWarning        "AX_SlowKeysWarning"
+#define        XkbBN_AX_SlowKeyPress           "AX_SlowKeyPress"
+#define        XkbBN_AX_SlowKeyAccept          "AX_SlowKeyAccept"
+#define        XkbBN_AX_SlowKeyReject          "AX_SlowKeyReject"
+#define        XkbBN_AX_SlowKeyRelease         "AX_SlowKeyRelease"
+#define        XkbBN_AX_BounceKeyReject        "AX_BounceKeyReject"
+#define        XkbBN_AX_StickyLatch            "AX_StickyLatch"
+#define        XkbBN_AX_StickyLock             "AX_StickyLock"
+#define        XkbBN_AX_StickyUnlock           "AX_StickyUnlock"
+
+#define        XkbBI_Info                      0
+#define        XkbBI_Warning                   1
+#define        XkbBI_MinorError                2
+#define        XkbBI_MajorError                3
+#define        XkbBI_BadValue                  4
+#define        XkbBI_InvalidLocation           5
+#define        XkbBI_Question                  6
+#define        XkbBI_Start                     7
+#define        XkbBI_End                       8
+#define        XkbBI_Success                   9
+#define        XkbBI_Failure                   10
+#define        XkbBI_Wait                      11
+#define        XkbBI_Proceed                   12
+#define        XkbBI_Ignore                    13
+#define        XkbBI_Iconify                   14
+#define        XkbBI_Deiconify                 15
+#define        XkbBI_Open                      16
+#define        XkbBI_Close                     17
+#define        XkbBI_TerminalBell              18
+#define        XkbBI_MarginBell                19
+#define        XkbBI_CursorStuck               20
+#define        XkbBI_NewMail                   21
+#define        XkbBI_LaunchApp                 22
+#define        XkbBI_AppDeath                  23
+#define        XkbBI_ImAlive                   24
+#define        XkbBI_ClockChimeHour            25
+#define        XkbBI_ClockChimeHalf            26
+#define        XkbBI_ClockChimeQuarter         27
+#define        XkbBI_RepeatingLastBell         28
+#define        XkbBI_ComposeFail               29
+#define        XkbBI_AX_FeatureOn              30
+#define        XkbBI_AX_FeatureOff             31
+#define        XkbBI_AX_FeatureChange          32
+#define        XkbBI_AX_IndicatorOn            33
+#define        XkbBI_AX_IndicatorOff           34
+#define        XkbBI_AX_IndicatorChange        35
+#define        XkbBI_AX_SlowKeysWarning        36
+#define        XkbBI_AX_SlowKeyPress           37
+#define        XkbBI_AX_SlowKeyAccept          38
+#define        XkbBI_AX_SlowKeyReject          39
+#define        XkbBI_AX_SlowKeyRelease         40
+#define        XkbBI_AX_BounceKeyReject        41
+#define        XkbBI_AX_StickyLatch            42
+#define        XkbBI_AX_StickyLock             43
+#define        XkbBI_AX_StickyUnlock           44
+#define        XkbBI_NumBells                  45
+
+_XFUNCPROTOBEGIN
+
+extern Bool XkbStdBell(
+       Display *       /* dpy */,
+       Window          /* win */,
+       int             /* percent */,
+       int             /* bellDef */
+);
+
+extern Bool XkbStdBellEvent(
+       Display *       /* dpy */,
+       Window          /* win */,
+       int             /* percent */,
+       int             /* bellDef */
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XKBBELLS_H_ */
diff --git a/include/X11/extensions/XKBconfig.h b/include/X11/extensions/XKBconfig.h
new file mode 100644 (file)
index 0000000..668a358
--- /dev/null
@@ -0,0 +1,278 @@
+#ifndef _XKBCONFIG_H_
+#define        _XKBCONFIG_H_ 1
+
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+
+typedef struct _XkbConfigRtrn  *XkbConfigRtrnPtr;
+typedef struct _XkbConfigField *XkbConfigFieldPtr;
+typedef struct _XkbConfigFields        *XkbConfigFieldsPtr;
+
+typedef Bool (*XkbConfigParseFunc)(
+       FILE *                          /* file */,
+       XkbConfigFieldsPtr              /* fields */,
+       XkbConfigFieldPtr               /* field */,
+       XkbDescPtr                      /* xkb */,
+       XkbConfigRtrnPtr                /* rtrn */
+);
+
+#define        XkbCF_Check     0
+#define        XkbCF_Apply     1
+#define        XkbCF_CleanUp   2
+#define        XkbCF_Destroy   3
+
+typedef        Bool (*XkbConfigFinishFunc)(
+       XkbConfigFieldsPtr              /* fields */,
+       XkbDescPtr                      /* xkb */,
+       XkbConfigRtrnPtr                /* rtrn */,
+       int                             /* what */
+);
+
+typedef struct _XkbConfigRtrnPriv {
+       int                             cfg_id;
+       XPointer                        priv;
+       struct _XkbConfigRtrnPriv *     next;
+} XkbConfigRtrnPrivRec,*XkbConfigRtrnPrivPtr;
+
+typedef struct _XkbConfigModInfo {
+       Bool                    replace;
+       unsigned char           mods;
+       unsigned char           mods_clear;
+       unsigned short          vmods;
+       unsigned short          vmods_clear;
+} XkbConfigModInfoRec,*XkbConfigModInfoPtr;
+
+typedef struct _XkbConfigUnboundMod {
+       unsigned char           what;
+       unsigned char           mods;
+       unsigned short          vmods;
+       short                   merge;
+       char *                  name;
+} XkbConfigUnboundModRec,*XkbConfigUnboundModPtr;
+
+#define        XkbCF_MergeSet                  0
+#define        XkbCF_MergeAdd                  1
+#define        XkbCF_MergeRemove               2
+
+#define        XkbCF_InitialMods               (1L<<0)
+#define        XkbCF_InternalMods              (1L<<1)
+#define        XkbCF_IgnoreLockMods            (1L<<2)
+#define        XkbCF_InitialCtrls              (1L<<3)
+#define        XkbCF_AccessXTimeout            (1L<<4)
+#define        XkbCF_AccessXTimeoutCtrlsOn     (1L<<5)
+#define        XkbCF_AccessXTimeoutCtrlsOff    (1L<<6)
+#define        XkbCF_AccessXTimeoutOptsOn      (1L<<7)
+#define        XkbCF_AccessXTimeoutOptsOff     (1L<<8)
+#define        XkbCF_GroupsWrap                (1L<<9)
+#define        XkbCF_InitialOpts               (1L<<10)
+
+typedef struct _XkbConfigRtrn {
+       unsigned                defined;
+       int                     error;
+       int                     line;
+
+       int                     click_volume;
+       int                     bell_volume;
+       int                     bell_pitch;
+       int                     bell_duration;
+       int                     repeat_delay;
+       int                     repeat_interval;
+
+       char *                  rules_file;
+       char *                  model;
+       char *                  layout;
+       char *                  variant;
+       char *                  options;
+
+       char *                  keymap;
+       char *                  keycodes;
+       char *                  geometry;
+       char *                  phys_symbols;
+       char *                  symbols;
+       char *                  types;
+       char *                  compat;
+
+       Bool                    replace_initial_ctrls;
+       unsigned long           initial_ctrls;
+       unsigned long           initial_ctrls_clear;
+
+       Bool                    replace_initial_opts;
+       unsigned short          initial_opts;
+       unsigned short          initial_opts_clear;
+
+       XkbConfigModInfoRec     initial_mods;
+       XkbConfigModInfoRec     internal_mods;
+       XkbConfigModInfoRec     ignore_lock_mods;
+
+       short                   num_unbound_mods;
+       short                   sz_unbound_mods;
+       XkbConfigUnboundModPtr  unbound_mods;
+
+       int                     groups_wrap;
+       int                     slow_keys_delay;
+       int                     debounce_delay;
+       int                     mk_delay;
+       int                     mk_interval;
+       int                     mk_time_to_max;
+       int                     mk_max_speed;
+       int                     mk_curve;
+       int                     ax_timeout;
+
+       Bool                    replace_axt_ctrls_on;
+       Bool                    replace_axt_ctrls_off;
+       unsigned long           axt_ctrls_on;
+       unsigned long           axt_ctrls_off;
+       unsigned long           axt_ctrls_ignore;
+
+       Bool                    replace_axt_opts_off;
+       Bool                    replace_axt_opts_on;
+       unsigned short          axt_opts_off;
+       unsigned short          axt_opts_on;
+       unsigned short          axt_opts_ignore;
+       XkbConfigRtrnPrivPtr    priv;
+} XkbConfigRtrnRec;
+
+typedef struct _XkbConfigField {
+       char *          field;
+       unsigned char   field_id;
+} XkbConfigFieldRec;
+
+typedef struct _XkbConfigFields {
+       unsigned short          cfg_id;
+       unsigned short          num_fields;
+       XkbConfigFieldPtr       fields;
+       XkbConfigParseFunc      parser;
+       XkbConfigFinishFunc     finish;
+       XPointer                priv;
+       struct _XkbConfigFields *next;
+} XkbConfigFieldsRec;
+
+#define        XkbCF_EOF                       -1
+#define        XkbCF_Unknown                    0
+#define        XkbCF_EOL                        1
+#define        XkbCF_Semi                       2
+#define        XkbCF_Equals                     3
+#define        XkbCF_PlusEquals                 4
+#define        XkbCF_MinusEquals                5
+#define        XkbCF_Plus                       6
+#define        XkbCF_Minus                      7
+#define        XkbCF_String                    10
+#define        XkbCF_Ident                     11
+#define        XkbCF_Integer                   12
+
+#define        XkbCF_UnterminatedString        100
+#define        XkbCF_BadAlloc                  101
+#define        XkbCF_MissingIdent              102
+#define        XkbCF_MissingEquals             103
+#define        XkbCF_ExpectedEOS               104
+#define        XkbCF_ExpectedBoolean           105
+#define        XkbCF_ExpectedInteger           106
+#define        XkbCF_ExpectedString            107
+#define        XkbCF_ExpectedModifier          108
+#define        XkbCF_ExpectedControl           109
+#define        XkbCF_ExpectedAXOption          110
+#define        XkbCF_ExpectedOperator          111
+#define        XkbCF_ExpectedOORGroupBehavior  112
+
+typedef union {
+       int             ival;
+       char *          str;
+} XkbCFScanResultRec,*XkbCFScanResultPtr;
+
+extern XkbConfigFieldsPtr      XkbCFDflts;
+
+_XFUNCPROTOBEGIN
+
+extern int XkbCFScan(
+       FILE *                  /* file */,
+       XkbCFScanResultPtr      /* val_rtrn */,
+       XkbConfigRtrnPtr        /* rtrn */
+);
+
+extern XkbConfigFieldsPtr XkbCFDup(
+       XkbConfigFieldsPtr      /* fields */
+);
+
+extern XkbConfigFieldsPtr XkbCFFree(
+       XkbConfigFieldsPtr      /* fields */,
+       Bool                    /* all */
+);
+
+extern XkbConfigUnboundModPtr XkbCFAddModByName(
+       XkbConfigRtrnPtr        /* rtrn */,
+       int                     /* what */,
+       char *                  /* name */,
+       Bool                    /* merge */,
+       XkbConfigUnboundModPtr  /* last */
+);
+
+extern Bool XkbCFBindMods(
+       XkbConfigRtrnPtr        /* rtrn */,
+       XkbDescPtr              /* xkb */
+);
+
+extern Bool XkbCFApplyMods(
+       XkbConfigRtrnPtr        /* rtrn */,
+       int                     /* what */,
+       XkbConfigModInfoPtr     /* info */
+);
+
+extern Bool XkbCFApplyRtrnValues(
+       XkbConfigRtrnPtr        /* rtrn */,
+       XkbConfigFieldsPtr      /* fields */,
+       XkbDescPtr              /* xkb */
+);
+
+extern XkbConfigRtrnPrivPtr XkbCFAddPrivate(
+       XkbConfigRtrnPtr        /* rtrn */,
+       XkbConfigFieldsPtr      /* fields */,
+       XPointer                /* ptr */
+);
+
+extern void XkbCFFreeRtrn(
+       XkbConfigRtrnPtr        /* rtrn */,
+       XkbConfigFieldsPtr      /* fields */,
+       XkbDescPtr              /* xkb */
+);
+
+extern Bool XkbCFParse(
+       FILE *                  /* file */,
+       XkbConfigFieldsPtr      /* fields */,
+       XkbDescPtr              /* xkb */,
+       XkbConfigRtrnPtr        /* rtrn */
+);
+
+extern void XkbCFReportError(
+       FILE *                  /* file */,
+       char *                  /* name */,
+       int                     /* error */,
+       int                     /* line */
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XKBCONFIG_H_ */
diff --git a/include/X11/extensions/XKBfile.h b/include/X11/extensions/XKBfile.h
new file mode 100644 (file)
index 0000000..0d2f52b
--- /dev/null
@@ -0,0 +1,492 @@
+
+#ifndef _XKBFILE_H_
+#define        _XKBFILE_H_ 1
+
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+/***====================================================================***/
+
+#define        XkbXKMFile      0
+#define        XkbCFile        1
+#define        XkbXKBFile      2
+#define        XkbMessage      3
+
+#define        XkbMapDefined           (1<<0)
+#define        XkbStateDefined         (1<<1)
+
+typedef struct _XkbFileInfo {
+    unsigned           type;
+    unsigned           defined;
+    XkbDescPtr         xkb;
+} XkbFileInfo,*XkbFileInfoPtr;
+
+typedef void   (*XkbFileAddOnFunc)(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    int                        /* fileSection */,
+    void *             /* priv */
+);
+
+/***====================================================================***/
+
+#define        _XkbSuccess                     0
+#define        _XkbErrMissingNames             1
+#define        _XkbErrMissingTypes             2
+#define        _XkbErrMissingReqTypes          3
+#define        _XkbErrMissingSymbols           4
+#define        _XkbErrMissingVMods             5
+#define        _XkbErrMissingIndicators        6
+#define        _XkbErrMissingCompatMap         7
+#define        _XkbErrMissingSymInterps        8
+#define        _XkbErrMissingGeometry          9
+#define        _XkbErrIllegalDoodad            10
+#define        _XkbErrIllegalTOCType           11
+#define        _XkbErrIllegalContents          12
+#define        _XkbErrEmptyFile                13
+#define        _XkbErrFileNotFound             14
+#define        _XkbErrFileCannotOpen           15
+#define        _XkbErrBadValue                 16
+#define        _XkbErrBadMatch                 17
+#define        _XkbErrBadTypeName              18
+#define        _XkbErrBadTypeWidth             19
+#define        _XkbErrBadFileType              20
+#define        _XkbErrBadFileVersion           21
+#define        _XkbErrBadFileFormat            22
+#define        _XkbErrBadAlloc                 23
+#define        _XkbErrBadLength                24
+#define        _XkbErrXReqFailure              25
+#define        _XkbErrBadImplementation        26
+
+extern const char *    _XkbErrMessages[];
+extern unsigned                _XkbErrCode;
+extern const char *    _XkbErrLocation;
+extern unsigned                _XkbErrData;
+
+/***====================================================================***/
+
+_XFUNCPROTOBEGIN
+
+extern char *  XkbIndentText(
+    unsigned   /* size */
+);
+
+extern char *  XkbAtomText(
+    Display *  /* dpy */,
+    Atom       /* atm */,
+    unsigned   /* format */
+);
+
+extern char *  XkbKeysymText(
+    KeySym     /* sym */,
+    unsigned   /* format */
+);
+
+extern char *  XkbStringText(
+    char *     /* str */,
+    unsigned   /* format */
+);
+
+extern char *  XkbKeyNameText(
+    char *     /* name */,
+    unsigned   /* format */
+);
+
+extern char *
+XkbModIndexText(
+    unsigned   /* ndx */,
+    unsigned   /* format */
+);
+
+extern char *
+XkbModMaskText(
+    unsigned   /* mask */,
+    unsigned   /* format */
+);
+
+extern char *  XkbVModIndexText(
+    Display *  /* dpy */,
+    XkbDescPtr /* xkb */,
+    unsigned   /* ndx */,
+    unsigned   /* format */
+);
+
+extern char *  XkbVModMaskText(
+    Display *  /* dpy */,
+    XkbDescPtr /* xkb */,
+    unsigned   /* modMask */,
+    unsigned   /* mask */,
+    unsigned   /* format */
+);
+
+extern char *  XkbConfigText(
+    unsigned   /* config */,
+    unsigned   /* format */
+);
+
+extern char *  XkbSIMatchText(
+    unsigned   /* type */,
+    unsigned   /* format */
+);
+
+extern char *  XkbIMWhichStateMaskText(
+    unsigned   /* use_which */,
+    unsigned   /* format */
+);
+
+extern char *  XkbAccessXDetailText(
+    unsigned   /* state */,
+    unsigned   /* format */
+);
+
+extern char *  XkbNKNDetailMaskText(
+    unsigned   /* detail */,
+    unsigned   /* format */
+);
+
+extern char *  XkbControlsMaskText(
+    unsigned   /* ctrls */,
+    unsigned   /* format */
+);
+
+extern char *  XkbGeomFPText(
+    int                /* val */,
+    unsigned   /* format */
+);
+
+extern char *  XkbDoodadTypeText(
+    unsigned   /* type */,
+    unsigned   /* format */
+);
+
+extern char *  XkbActionTypeText(
+    unsigned   /* type */,
+    unsigned   /* format */
+);
+
+extern char *  XkbActionText(
+    Display *  /* dpy */,
+    XkbDescPtr /* xkb */,
+    XkbAction *        /* action */,
+    unsigned   /* format */
+);
+
+extern char *  XkbBehaviorText(
+    XkbDescPtr                 /* xkb */,
+    XkbBehavior *      /* behavior */,
+    unsigned           /* format */
+);
+
+/***====================================================================***/
+
+#define        _XkbKSLower     (1<<0)
+#define        _XkbKSUpper     (1<<1)
+
+#define        XkbKSIsLower(k)         (_XkbKSCheckCase(k)&_XkbKSLower)
+#define        XkbKSIsUpper(k)         (_XkbKSCheckCase(k)&_XkbKSUpper)
+#define XkbKSIsKeypad(k)       (((k)>=XK_KP_Space)&&((k)<=XK_KP_Equal))
+#define        XkbKSIsDeadKey(k)       \
+               (((k)>=XK_dead_grave)&&((k)<=XK_dead_semivoiced_sound))
+
+extern unsigned _XkbKSCheckCase(
+   KeySym      /* sym */
+);
+
+extern int      XkbFindKeycodeByName(
+    XkbDescPtr /* xkb */,
+    char *     /* name */,
+    Bool       /* use_aliases */
+);
+
+extern Bool    XkbLookupGroupAndLevel(
+    XkbDescPtr /* xkb */,
+    int                /* key */,
+    int        *       /* mods_inout */,
+    int *      /* grp_inout */,
+    int        *       /* lvl_rtrn */
+);
+
+/***====================================================================***/
+
+#ifndef XKB_IN_SERVER
+
+extern Bool    XkbLookupCanonicalRGBColor(
+    char *     /* def */,
+    XColor *   /* color */
+);
+
+#endif
+
+/***====================================================================***/
+
+extern char *  XkbAtomGetString(
+    Display *  /* dpy */,
+    Atom       /* atm */
+);
+
+extern Atom    XkbInternAtom(
+    Display *  /* dpy */,
+    char *     /* name */,
+    Bool       /* onlyIfExists */
+);
+
+extern Status  XkbChangeKbdDisplay(
+    Display *          /* newDpy */,
+    XkbFileInfo *      /* result */
+);
+
+extern Atom    XkbChangeAtomDisplay(
+    Display *  /* oldDpy */,
+    Display *  /* newDpy */,
+    Atom       /* atm */
+);
+
+extern void    XkbInitAtoms(
+    Display *  /* dpy */
+);
+
+/***====================================================================***/
+
+#ifdef _XKBGEOM_H_
+
+#define        XkbDW_Unknown   0
+#define        XkbDW_Doodad    1
+#define        XkbDW_Section   2
+typedef struct _XkbDrawable {
+       int             type;
+       int             priority;
+       union {
+           XkbDoodadPtr        doodad;
+           XkbSectionPtr       section;
+       } u;
+       struct _XkbDrawable *   next;
+} XkbDrawableRec,*XkbDrawablePtr;
+
+extern XkbDrawablePtr
+XkbGetOrderedDrawables(
+    XkbGeometryPtr     /* geom */,
+    XkbSectionPtr      /* section */
+);
+
+extern void
+XkbFreeOrderedDrawables(
+    XkbDrawablePtr     /* draw */
+);
+
+#endif
+
+/***====================================================================***/
+
+extern unsigned        XkbConvertGetByNameComponents(
+    Bool               /* toXkm */,
+    unsigned           /* orig */
+);
+
+extern unsigned        XkbConvertXkbComponents(
+    Bool               /* toXkm */,
+    unsigned           /* orig */
+);
+
+extern Bool    XkbDetermineFileType(
+    XkbFileInfo *      /* xkb */,
+    int                        /* format */,
+    int *              /* opts_missing */
+);
+
+extern Bool    XkbNameMatchesPattern(
+    char *             /* name */,
+    char *             /* pattern */
+);
+
+/***====================================================================***/
+
+extern Bool    XkbWriteXKBKeycodes(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBKeyTypes(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBCompatMap(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBSymbols(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBGeometry(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBSemantics(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBLayout(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBKeymap(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteXKBFile(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+);
+
+extern Bool    XkbWriteCFile(
+    FILE *             /* file */,
+    char *             /* name */,
+    XkbFileInfo *      /* info */
+);
+
+extern Bool    XkbWriteXKMFile(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */
+);
+
+extern Bool    XkbWriteToServer(
+    XkbFileInfo *      /* result */
+);
+
+extern void    XkbEnsureSafeMapName(
+    char *             /* name */
+);
+
+extern Bool    XkbWriteXKBKeymapForNames(
+    FILE *                     /* file */,
+    XkbComponentNamesPtr       /* names */,
+    Display *                  /* dpy */,
+    XkbDescPtr                 /* xkb */,
+    unsigned                   /* want */,
+    unsigned                   /* need */
+);
+
+extern Status  XkbMergeFile(
+    XkbDescPtr                 /* xkb */,
+    XkbFileInfo                        /* finfo */
+);
+
+/***====================================================================***/
+
+extern Bool    XkmProbe(
+    FILE *             /* file */
+);
+
+extern unsigned XkbReadFromServer(
+    Display *          /* dpy */,
+    unsigned           /* need */,
+    unsigned           /* want */,
+    XkbFileInfo *      /* result */
+);
+
+extern unsigned        XkmReadFile(
+    FILE *             /* file */,
+    unsigned           /* need */,
+    unsigned           /* want */,
+    XkbFileInfo *      /* result */
+);
+
+#ifdef _XKMFORMAT_H_
+
+extern Bool    XkmReadTOC(
+    FILE *              /* file */,
+    xkmFileInfo *       /* file_info */,
+    int                 /* max_toc */,
+    xkmSectionInfo *    /* toc */
+);
+
+extern xkmSectionInfo *XkmFindTOCEntry(
+    xkmFileInfo *       /* finfo */,
+    xkmSectionInfo *    /* toc */,
+    unsigned            /* type */
+);
+
+extern Bool    XkmReadFileSection(
+    FILE *              /* file */,
+    xkmSectionInfo *    /* toc */,
+    XkbFileInfo *       /* result */,
+    unsigned *          /* loaded_rtrn */
+);
+
+extern char *  XkmReadFileSectionName(
+    FILE *             /* file */,
+    xkmSectionInfo *   /* toc */
+);
+
+#endif /* _XKMFORMAT_H  */
+
+_XFUNCPROTOEND
+
+#endif /* _XKBFILE_H_ */
diff --git a/include/X11/extensions/XKBrules.h b/include/X11/extensions/XKBrules.h
new file mode 100644 (file)
index 0000000..2832e67
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef _XKBRULES_H_
+#define        _XKBRULES_H_ 1
+
+/************************************************************
+ Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+/***====================================================================***/
+
+typedef struct _XkbRF_VarDefs {
+       char *                  model;
+       char *                  layout;
+       char *                  variant;
+       char *                  options;
+       unsigned short          sz_extra;
+       unsigned short          num_extra;
+       char *                  extra_names;
+       char **                 extra_values;
+} XkbRF_VarDefsRec,*XkbRF_VarDefsPtr;
+
+typedef struct _XkbRF_VarDesc {
+       char *                  name;
+       char *                  desc;
+} XkbRF_VarDescRec, *XkbRF_VarDescPtr;
+
+typedef struct _XkbRF_DescribeVars {
+       int                     sz_desc;
+       int                     num_desc;
+       XkbRF_VarDescPtr        desc;
+} XkbRF_DescribeVarsRec,*XkbRF_DescribeVarsPtr;
+
+typedef struct _XkbRF_Rule {
+       int                     number;
+        int                    layout_num;
+        int                    variant_num;
+       char *                  model;
+       char *                  layout;
+       char *                  variant;
+       char *                  option;
+       /* yields */
+       char *                  keycodes;
+       char *                  symbols;
+       char *                  types;
+       char *                  compat;
+       char *                  geometry;
+       char *                  keymap;
+       unsigned                flags;
+} XkbRF_RuleRec,*XkbRF_RulePtr;
+
+typedef struct _XkbRF_Group {
+       int                     number;
+       char *                  name;
+       char *                  words;
+} XkbRF_GroupRec, *XkbRF_GroupPtr;
+
+#define        XkbRF_PendingMatch      (1L<<1)
+#define        XkbRF_Option            (1L<<2)
+#define        XkbRF_Append            (1L<<3)
+#define        XkbRF_Normal            (1L<<4)
+#define        XkbRF_Invalid           (1L<<5)
+
+typedef struct _XkbRF_Rules {
+       XkbRF_DescribeVarsRec   models;
+       XkbRF_DescribeVarsRec   layouts;
+       XkbRF_DescribeVarsRec   variants;
+       XkbRF_DescribeVarsRec   options;
+       unsigned short          sz_extra;
+       unsigned short          num_extra;
+       char **                 extra_names;
+       XkbRF_DescribeVarsPtr   extra;
+
+       unsigned short          sz_rules;
+       unsigned short          num_rules;
+       XkbRF_RulePtr           rules;
+       unsigned short          sz_groups;
+       unsigned short          num_groups;
+        XkbRF_GroupPtr         groups;
+} XkbRF_RulesRec, *XkbRF_RulesPtr;
+
+/***====================================================================***/
+
+_XFUNCPROTOBEGIN
+
+extern Bool    XkbRF_GetComponents(
+    XkbRF_RulesPtr             /* rules */,
+    XkbRF_VarDefsPtr           /* var_defs */,
+    XkbComponentNamesPtr       /* names */
+);
+
+extern XkbRF_RulePtr   XkbRF_AddRule(
+    XkbRF_RulesPtr     /* rules */
+);
+
+extern XkbRF_GroupPtr XkbRF_AddGroup(XkbRF_RulesPtr  rules);
+
+extern Bool    XkbRF_LoadRules(
+    FILE *             /* file */,
+    XkbRF_RulesPtr     /* rules */
+);
+
+extern Bool XkbRF_LoadRulesByName(
+    char *             /* base */,
+    char *             /* locale */,
+    XkbRF_RulesPtr     /* rules */
+);
+
+/***====================================================================***/
+
+extern XkbRF_VarDescPtr        XkbRF_AddVarDesc(
+    XkbRF_DescribeVarsPtr      /* vars */
+);
+
+extern XkbRF_VarDescPtr        XkbRF_AddVarDescCopy(
+    XkbRF_DescribeVarsPtr      /* vars */,
+    XkbRF_VarDescPtr           /* copy_from */
+);
+
+extern XkbRF_DescribeVarsPtr XkbRF_AddVarToDescribe(
+    XkbRF_RulesPtr             /* rules */,
+    char *                     /* name */
+);
+
+extern Bool    XkbRF_LoadDescriptions(
+    FILE *             /* file */,
+    XkbRF_RulesPtr     /* rules */
+);
+
+extern Bool XkbRF_LoadDescriptionsByName(
+    char *             /* base */,
+    char *             /* locale */,
+    XkbRF_RulesPtr     /* rules */
+);
+
+extern XkbRF_RulesPtr XkbRF_Load(
+    char *             /* base */,
+    char *             /* locale */,
+    Bool               /* wantDesc */,
+    Bool               /* wantRules */
+);
+
+extern XkbRF_RulesPtr XkbRF_Create(
+    int                        /* sz_rules */,
+    int                        /* sz_extra */
+);
+
+/***====================================================================***/
+
+extern void XkbRF_Free(
+    XkbRF_RulesPtr     /* rules */,
+    Bool               /* freeRules */
+);
+
+
+/***====================================================================***/
+
+#define        _XKB_RF_NAMES_PROP_ATOM         "_XKB_RULES_NAMES"
+#define        _XKB_RF_NAMES_PROP_MAXLEN       1024
+
+#ifndef XKB_IN_SERVER
+
+extern Bool XkbRF_GetNamesProp(
+   Display *           /* dpy */,
+   char **             /* rules_file_rtrn */,
+   XkbRF_VarDefsPtr    /* var_defs_rtrn */
+);
+
+extern Bool XkbRF_SetNamesProp(
+   Display *           /* dpy */,
+   char *              /* rules_file */,
+   XkbRF_VarDefsPtr    /* var_defs */
+);
+
+#endif
+
+_XFUNCPROTOEND
+
+#endif /* _XKBRULES_H_ */
diff --git a/include/X11/extensions/XKM.h b/include/X11/extensions/XKM.h
new file mode 100644 (file)
index 0000000..da272e0
--- /dev/null
@@ -0,0 +1,69 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+#ifndef XKM_H
+#define        XKM_H 1
+
+#define        XkmFileVersion          15
+
+#define        XkmIllegalFile          -1
+#define        XkmSemanticsFile        20
+#define        XkmLayoutFile           21
+#define        XkmKeymapFile           22
+#define        XkmGeometryFile         23
+
+#define        XkmTypesIndex           0
+#define        XkmCompatMapIndex       1
+#define        XkmSymbolsIndex         2
+#define        XkmIndicatorsIndex      3
+#define        XkmKeyNamesIndex        4
+#define        XkmGeometryIndex        5
+#define        XkmVirtualModsIndex     6
+#define        XkmLastIndex            XkmVirtualModsIndex
+
+#define        XkmTypesMask            (1<<0)
+#define        XkmCompatMapMask        (1<<1)
+#define        XkmSymbolsMask          (1<<2)
+#define        XkmIndicatorsMask       (1<<3)
+#define        XkmKeyNamesMask         (1<<4)
+#define        XkmGeometryMask         (1<<5)
+#define        XkmVirtualModsMask      (1<<6)
+#define        XkmLegalIndexMask       (0x7f)
+#define        XkmAllIndicesMask       (0x7f)
+
+#define        XkmSemanticsRequired    (XkmCompatMapMask)
+#define        XkmSemanticsOptional    (XkmTypesMask|XkmVirtualModsMask|XkmIndicatorsMask)
+#define        XkmSemanticsLegal       (XkmSemanticsRequired|XkmSemanticsOptional)
+#define        XkmLayoutRequired       (XkmKeyNamesMask|XkmSymbolsMask|XkmTypesMask)
+#define        XkmLayoutOptional       (XkmVirtualModsMask|XkmGeometryMask)
+#define        XkmLayoutLegal          (XkmLayoutRequired|XkmLayoutOptional)
+#define        XkmKeymapRequired       (XkmSemanticsRequired|XkmLayoutRequired)
+#define        XkmKeymapOptional       ((XkmSemanticsOptional|XkmLayoutOptional)&(~XkmKeymapRequired))
+#define        XkmKeymapLegal          (XkmKeymapRequired|XkmKeymapOptional)
+
+#define        XkmLegalSection(m)      (((m)&(~XkmKeymapLegal))==0)
+#define        XkmSingleSection(m)     (XkmLegalSection(m)&&(((m)&(~(m)+1))==(m)))
+
+#endif /* XKM_H */
diff --git a/include/X11/extensions/XKMformat.h b/include/X11/extensions/XKMformat.h
new file mode 100644 (file)
index 0000000..8dae18f
--- /dev/null
@@ -0,0 +1,299 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifndef _XKMFORMAT_H_
+#define        _XKMFORMAT_H_ 1
+
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBproto.h>
+#include <X11/extensions/XKM.h>
+
+typedef        struct _xkmFileInfo {
+       CARD8           type;
+       CARD8           min_kc;
+       CARD8           max_kc;
+       CARD8           num_toc;
+       CARD16          present B16;
+       CARD16          pad B16;
+} xkmFileInfo;
+#define        sz_xkmFileInfo  8
+
+typedef        struct _xkmSectionInfo {
+       CARD16          type B16;
+       CARD16          format B16;
+       CARD16          size B16;
+       CARD16          offset B16;
+} xkmSectionInfo;
+#define        sz_xkmSectionInfo       8
+
+typedef struct _xkmKeyTypeDesc {
+       CARD8           realMods;
+       CARD8           numLevels;
+       CARD16          virtualMods B16;
+       CARD8           nMapEntries;
+       CARD8           nLevelNames;
+       CARD8           preserve;
+       CARD8           pad;
+} xkmKeyTypeDesc;
+#define        sz_xkmKeyTypeDesc       8
+
+typedef struct _xkmKTMapEntryDesc {
+       CARD8           level;
+       CARD8           realMods;
+       CARD16          virtualMods B16;
+} xkmKTMapEntryDesc;
+#define        sz_xkmKTMapEntryDesc    4
+
+typedef struct _xkmModsDesc {
+       CARD8           realMods;
+       CARD8           pad;
+       CARD16          virtualMods B16;
+} xkmModsDesc;
+#define        sz_xkmModsDesc  4
+
+typedef struct _xkmVModMapDesc {
+       CARD8           key;
+       CARD8           pad;
+       CARD16          vmods B16;
+} xkmVModMapDesc;
+#define        sz_xkmVModMapDesc       4
+
+typedef struct _xkmSymInterpretDesc {
+       CARD32          sym B32;
+       CARD8           mods;
+       CARD8           match;
+       CARD8           virtualMod;
+       CARD8           flags;
+       CARD8           actionType;
+       CARD8           actionData[7];
+} xkmSymInterpretDesc;
+#define        sz_xkmSymInterpretDesc  16
+
+typedef struct _xkmBehaviorDesc {
+       CARD8           type;
+       CARD8           data;
+       CARD16          pad B16;
+} xkmBehaviorDesc;
+#define        sz_xkmBehaviorDesc      4
+
+typedef struct _xkmActionDesc {
+       CARD8           type;
+       CARD8           data[7];
+} xkmActionDesc;
+#define        sz_xkmActionDesc        8
+
+#define        XkmKeyHasTypes          (0x0f)
+#define        XkmKeyHasGroup1Type     (1<<0)
+#define        XkmKeyHasGroup2Type     (1<<1)
+#define        XkmKeyHasGroup3Type     (1<<2)
+#define        XkmKeyHasGroup4Type     (1<<3)
+#define        XkmKeyHasActions        (1<<4)
+#define        XkmKeyHasBehavior       (1<<5)
+#define        XkmRepeatingKey         (1<<6)
+#define        XkmNonRepeatingKey      (1<<7)
+
+typedef struct _xkmKeySymMapDesc {
+       CARD8           width;
+       CARD8           num_groups;
+       CARD8           modifier_map;
+       CARD8           flags;
+} xkmKeySymMapDesc;
+#define sz_xkmKeySymMapDesc    4
+
+typedef struct _xkmIndicatorMapDesc {
+       CARD8           indicator;
+       CARD8           flags;
+       CARD8           which_mods;
+       CARD8           real_mods;
+       CARD16          vmods B16;
+       CARD8           which_groups;
+       CARD8           groups;
+       CARD32          ctrls B32;
+} xkmIndicatorMapDesc;
+#define sz_xkmIndicatorMapDesc 12
+
+typedef struct _xkmGeometryDesc {
+       CARD16          width_mm B16;
+       CARD16          height_mm B16;
+       CARD8           base_color_ndx;
+       CARD8           label_color_ndx;
+       CARD16          num_properties B16;
+       CARD16          num_colors B16;
+       CARD16          num_shapes B16;
+       CARD16          num_sections B16;
+       CARD16          num_doodads B16;
+       CARD16          num_key_aliases B16;
+       CARD16          pad1 B16;
+} xkmGeometryDesc;
+#define        sz_xkmGeometryDesc      20
+
+typedef struct _xkmPointDesc {
+       INT16           x B16;
+       INT16           y B16;
+} xkmPointDesc;
+#define        sz_xkmPointDesc         4
+
+typedef        struct _xkmOutlineDesc {
+       CARD8           num_points;
+       CARD8           corner_radius;
+       CARD16          pad B16;
+} xkmOutlineDesc;
+#define        sz_xkmOutlineDesc       4
+
+typedef struct _xkmShapeDesc {
+       CARD8           num_outlines;
+       CARD8           primary_ndx;
+       CARD8           approx_ndx;
+       CARD8           pad;
+} xkmShapeDesc;
+#define        sz_xkmShapeDesc 4
+
+typedef struct _xkmSectionDesc {
+       INT16           top B16;
+       INT16           left B16;
+       CARD16          width B16;
+       CARD16          height B16;
+       INT16           angle B16;
+       CARD8           priority;
+       CARD8           num_rows;
+       CARD8           num_doodads;
+       CARD8           num_overlays;
+       CARD16          pad2 B16;
+} xkmSectionDesc;
+#define        sz_xkmSectionDesc       16
+
+typedef struct _xkmRowDesc {
+       INT16           top B16;
+       INT16           left B16;
+       CARD8           num_keys;
+       BOOL            vertical;
+       CARD16          pad B16;
+} xkmRowDesc;
+#define        sz_xkmRowDesc           8
+
+typedef struct _xkmKeyDesc {
+       CARD8           name[XkbKeyNameLength];
+       INT16           gap B16;
+       CARD8           shape_ndx;
+       CARD8           color_ndx;
+} xkmKeyDesc;
+#define        sz_xkmKeyDesc           8
+
+typedef struct _xkmOverlayDesc {
+       CARD8           num_rows;
+       CARD8           pad1;
+       CARD16          pad2 B16;
+} xkmOverlayDesc;
+#define        sz_xkmOverlayDesc       4
+
+typedef struct _xkmOverlayRowDesc {
+       CARD8           row_under;
+       CARD8           num_keys;
+       CARD16          pad B16;
+} xkmOverlayRowDesc;
+#define        sz_xkmOverlayRowDesc    4
+
+typedef struct _xkmOverlayKeyDesc {
+       char            over[XkbKeyNameLength];
+       char            under[XkbKeyNameLength];
+} xkmOverlayKeyDesc;
+#define sz_xkmOverlayKeyDesc   8
+
+typedef struct _xkmShapeDoodadDesc {
+       CARD8           type;
+       CARD8           priority;
+       INT16           top B16;
+       INT16           left B16;
+       INT16           angle B16;
+       CARD8           color_ndx;
+       CARD8           shape_ndx;
+       CARD16          pad B16;
+       CARD32          pad1 B32;
+} xkmShapeDoodadDesc;
+#define        sz_xkmShapeDoodadDesc   16
+
+typedef struct _xkmTextDoodadDesc {
+       CARD8           type;
+       CARD8           priority;
+       INT16           top B16;
+       INT16           left B16;
+       INT16           angle B16;
+       CARD16          width B16;
+       CARD16          height B16;
+       CARD8           color_ndx;
+       CARD8           pad1;
+       CARD16          pad2 B16;
+} xkmTextDoodadDesc;
+#define        sz_xkmTextDoodadDesc    16
+
+typedef struct _xkmIndicatorDoodadDesc {
+       CARD8           type;
+       CARD8           priority;
+       INT16           top B16;
+       INT16           left B16;
+       CARD8           shape_ndx;
+       CARD8           on_color_ndx;
+       CARD8           off_color_ndx;
+       CARD8           pad1;
+       CARD16          pad2 B16;
+       CARD32          pad3 B32;
+} xkmIndicatorDoodadDesc;
+#define        sz_xkmIndicatorDoodadDesc       16
+
+typedef struct _xkmLogoDoodadDesc {
+       CARD8           type;
+       CARD8           priority;
+       INT16           top B16;
+       INT16           left B16;
+       INT16           angle B16;
+       CARD8           color_ndx;
+       CARD8           shape_ndx;
+       CARD16          pad B16;
+       CARD32          pad1 B32;
+} xkmLogoDoodadDesc;
+#define        sz_xkmLogoDoodadDesc    16
+
+typedef struct _xkmAnyDoodadDesc {
+       CARD8           type;
+       CARD8           priority;
+       INT16           top B16;
+       INT16           left B16;
+       CARD16          pad1 B16;
+       CARD32          pad2 B32;
+       CARD32          pad3 B32;
+} xkmAnyDoodadDesc;
+#define        sz_xkmAnyDoodadDesc             16
+
+typedef union _xkmDoodadDesc {
+       xkmAnyDoodadDesc        any;
+       xkmShapeDoodadDesc      shape;
+       xkmTextDoodadDesc       text;
+       xkmIndicatorDoodadDesc  indicator;
+       xkmLogoDoodadDesc       logo;
+} xkmDoodadDesc;
+#define        sz_xkmDoodadDesc                16
+
+#endif /* _XKMFORMAT_H_ */
diff --git a/packaging/libxkbfile.spec b/packaging/libxkbfile.spec
new file mode 100755 (executable)
index 0000000..97f282d
--- /dev/null
@@ -0,0 +1,70 @@
+Summary: X.Org X11 libxkbfile runtime library
+Name: libxkbfile
+Version: 1.0.8
+Release: 1
+License: MIT
+Group: System Environment/Libraries
+URL: http://www.x.org
+
+Source0: %{name}-%{version}.tar.gz
+
+BuildRequires: pkgconfig(xproto) pkgconfig(x11)
+BuildRequires: pkgconfig(xorg-macros)
+
+%description
+X.Org X11 libxkbfile runtime library
+
+%package devel
+Summary: X.Org X11 libxkbfile development package
+Group: Development/Libraries
+Provides: libxkbfile-devel 
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+X.Org X11 libxkbfile development package
+
+%prep
+%setup -q
+
+%build
+# FIXME: We use -fno-strict-aliasing, to work around the following bug:
+# maprules.c:1373: warning: dereferencing type-punned pointer will break strict-aliasing rules)
+export CFLAGS="${CFLAGS} $RPM_OPT_FLAGS -fno-strict-aliasing"
+%reconfigure --disable-static \
+              LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed"
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p %{buildroot}/usr/share/license
+cp -af COPYING %{buildroot}/usr/share/license/%{name}
+make install DESTDIR=$RPM_BUILD_ROOT
+
+# We intentionally don't ship *.la files
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+
+%remove_docs
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+/usr/share/license/%{name}
+%doc COPYING ChangeLog
+%{_libdir}/libxkbfile.so.1
+%{_libdir}/libxkbfile.so.1.0.2
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/X11/extensions/XKBbells.h
+%{_includedir}/X11/extensions/XKBconfig.h
+%{_includedir}/X11/extensions/XKBfile.h
+%{_includedir}/X11/extensions/XKBrules.h
+%{_includedir}/X11/extensions/XKM.h
+%{_includedir}/X11/extensions/XKMformat.h
+%{_libdir}/libxkbfile.so
+%{_libdir}/pkgconfig/xkbfile.pc
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..98e1614
--- /dev/null
@@ -0,0 +1,36 @@
+lib_LTLIBRARIES = libxkbfile.la
+
+libxkbfile_la_SOURCES = \
+         cout.c \
+         maprules.c \
+         srvmisc.c \
+         xkbatom.c \
+         xkbbells.c \
+         xkbconfig.c \
+         xkbdraw.c \
+         xkberrs.c \
+         XKBfileInt.h \
+         xkbmisc.c \
+         xkbout.c \
+         xkbtext.c \
+         xkmout.c \
+         xkmread.c
+
+INCLUDES = -I$(top_srcdir)/include/ -I$(top_srcdir)/include/X11/extensions/
+
+
+libxkbfile_la_LIBADD = @XKBFILE_LIBS@
+AM_CFLAGS = $(CWARNFLAGS) @XKBFILE_CFLAGS@
+
+libxkbfile_la_LDFLAGS = -version-number 1:0:2 -no-undefined
+
+libxkbfileincludedir = $(includedir)/X11/extensions
+libxkbfileinclude_HEADERS = \
+    $(top_srcdir)/include/X11/extensions/XKM.h\
+    $(top_srcdir)/include/X11/extensions/XKBrules.h\
+    $(top_srcdir)/include/X11/extensions/XKBbells.h\
+    $(top_srcdir)/include/X11/extensions/XKBconfig.h\
+    $(top_srcdir)/include/X11/extensions/XKMformat.h\
+    $(top_srcdir)/include/X11/extensions/XKBfile.h
+
+EXTRA_DIST = magic
diff --git a/src/XKBfileInt.h b/src/XKBfileInt.h
new file mode 100644 (file)
index 0000000..e810e61
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _XKBFILEINT_H_
+#define        _XKBFILEINT_H_ 1
+
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#include "XKBfile.h"
+#include <string.h>
+
+#ifdef DEBUG
+#define        _XkbLibError(c,l,d) \
+       { fprintf(stderr,"xkbfile: %s in %s\n",_XkbErrMessages[c],(l)); \
+        _XkbErrCode= (c); _XkbErrLocation= (l); _XkbErrData= (d); }
+#else
+#define        _XkbLibError(c,l,d) \
+       { _XkbErrCode= (c); _XkbErrLocation= (l); _XkbErrData= (d); }
+#endif
+
+#ifndef XKB_IN_SERVER
+
+#define        _XkbAlloc(s)            malloc((s))
+#define        _XkbCalloc(n,s)         calloc((n),(s))
+#define        _XkbRealloc(o,s)        realloc((o),(s))
+#define        _XkbTypedAlloc(t)       ((t *)malloc(sizeof(t)))
+#define        _XkbTypedCalloc(n,t)    ((t *)calloc((n),sizeof(t)))
+#define        _XkbTypedRealloc(o,n,t) \
+       ((o)?(t *)realloc((o),(n)*sizeof(t)):_XkbTypedCalloc(n,t))
+#define        _XkbClearElems(a,f,l,t) bzero(&(a)[f],((l)-(f)+1)*sizeof(t))
+#define        _XkbFree(p)             free(p)
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+#endif
+
+_XFUNCPROTOBEGIN
+
+static inline
+char *_XkbDupString(const char *s)
+{
+    return s ? strdup(s) : NULL;
+}
+
+#define _XkbStrCaseEqual(s1,s2)        (_XkbStrCaseCmp(s1,s2)==0)
+
+#ifdef NEED_STRCASECMP
+extern int _XkbStrCaseCmp(char *s1, char *s2);
+#else
+#define _XkbStrCaseCmp strcasecmp
+#include <strings.h>
+#endif
+
+_XFUNCPROTOEND
+
+#endif /* _XKBFILEINT_H_ */
diff --git a/src/cout.c b/src/cout.c
new file mode 100644 (file)
index 0000000..399512f
--- /dev/null
@@ -0,0 +1,1050 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+#define        lowbit(x)       ((x) & (-(x)))
+
+static Bool
+WriteCHdrVMods(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register int i,nOut;
+
+    if ((!xkb)||(!xkb->names)||(!xkb->names->vmods))
+       return False;
+    for (i=nOut=0;i<XkbNumVirtualMods;i++) {
+       if (xkb->names->vmods[i]!=None) {
+           fprintf(file,"%s#define     vmod_%s %d\n",(nOut<1?"\n":""),
+                               XkbAtomText(dpy,xkb->names->vmods[i],XkbCFile),
+                               i);
+           nOut++;
+       }
+    }
+    for (i=nOut=0;i<XkbNumVirtualMods;i++) {
+       if (xkb->names->vmods[i]!=None) {
+           fprintf(file,"%s#define     vmod_%sMask     (1<<%d)\n",
+                               (nOut<1?"\n":""),
+                               XkbAtomText(dpy,xkb->names->vmods[i],XkbCFile)
+                               ,i);
+           nOut++;
+       }
+    }
+    if (nOut>0)
+       fprintf(file,"\n");
+    return True;
+}
+
+static Bool
+WriteCHdrKeycodes(FILE *file,XkbDescPtr xkb)
+{
+Atom                   kcName;
+register unsigned      i;
+char                   buf[8];
+
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
+       _XkbLibError(_XkbErrMissingNames,"WriteCHdrKeycodes",0);
+       return False;
+    }
+    kcName= xkb->names->keycodes;
+    buf[4]= '\0';
+    if (xkb->names->keycodes!=None)
+        fprintf(file,"/* keycodes name is \"%s\" */\n",
+                               XkbAtomText(xkb->dpy,kcName,XkbMessage));
+    fprintf(file,"static XkbKeyNameRec keyNames[NUM_KEYS]= {\n");
+    for (i=0;i<=xkb->max_key_code;i++) {
+       sprintf(buf,"\"%s\"",XkbKeyNameText(xkb->names->keys[i].name,XkbCFile));
+       if (i!=xkb->max_key_code)  {
+           fprintf(file,"    {  %6s  },",buf);
+           if ((i&3)==3)
+               fprintf(file,"\n");
+       }
+       else {
+           fprintf(file,"    {  %6s  }\n",buf);
+       }
+    }
+    fprintf(file,"};\n");
+    return True;
+}
+
+static void
+WriteTypePreserve(     FILE *          file,
+                       Display *       dpy,
+                       char *          prefix,
+                       XkbDescPtr      xkb,
+                       XkbKeyTypePtr   type)
+{
+register unsigned      i;
+XkbModsPtr             pre;
+
+    fprintf(file,"static XkbModsRec preserve_%s[%d]= {\n",prefix,
+                                                       type->map_count);
+    for (i=0,pre=type->preserve;i<type->map_count;i++,pre++) {
+       if (i!=0)
+           fprintf(file,",\n");
+       fprintf(file,"    {   %15s, ",XkbModMaskText(pre->mask,XkbCFile));
+       fprintf(file,"%15s, ",XkbModMaskText(pre->real_mods,XkbCFile));
+       fprintf(file,"%15s }",XkbVModMaskText(dpy,xkb,0,pre->vmods,XkbCFile));
+    }
+    fprintf(file,"\n};\n");
+    return;
+}
+
+static void
+WriteTypeInitFunc(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register unsigned      i,n;
+XkbKeyTypePtr          type;
+Atom *                 names;
+char *                 prefix = NULL;
+
+    fprintf(file,"\n\nstatic void\n");
+    fprintf(file,"initTypeNames(DPYTYPE dpy)\n");
+    fprintf(file,"{\n");
+    for (i=0,type=xkb->map->types;i<xkb->map->num_types;i++,type++) {
+       if (!(prefix = strdup(XkbAtomText(dpy,type->name,XkbCFile)))) {
+               _XkbLibError(_XkbErrBadAlloc,"WriteTypeInitFunc",0);
+               fprintf(file,"#error XkbErrBadAlloc WriteTypeInitFunc\n");
+               break;
+       }
+       if (type->name!=None)
+           fprintf(file,"    dflt_types[%d].name= GET_ATOM(dpy,\"%s\");\n",i,
+                                       XkbAtomText(dpy,type->name,XkbCFile));
+       names= type->level_names;
+       if (names!=NULL) {
+           char *tmp;
+           for (n=0;n<type->num_levels;n++) {
+               if (names[n]==None)
+                   continue;
+               tmp= XkbAtomText(dpy,names[n],XkbCFile);
+               if (tmp==NULL)
+                   continue;
+               fprintf(file,"    lnames_%s[%d]=        ",prefix,n);
+               fprintf(file,"GET_ATOM(dpy,\"%s\");\n",tmp);
+           }
+       }
+       free(prefix);
+       prefix = NULL;
+    }
+    fprintf(file,"}\n");
+    return;
+}
+
+static Bool
+WriteCHdrKeyTypes(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register unsigned      i,n;
+XkbClientMapPtr                map;
+XkbKeyTypePtr          type;
+char *                         prefix = NULL;
+
+    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
+       _XkbLibError(_XkbErrMissingTypes,"WriteCHdrKeyTypes",0);
+       return False;
+    }
+    if (xkb->map->num_types<XkbNumRequiredTypes) {
+       _XkbLibError(_XkbErrMissingReqTypes,"WriteCHdrKeyTypes",0);
+       return 0;
+    }
+    map= xkb->map;
+    if ((xkb->names!=NULL)&&(xkb->names->types!=None)) {
+       fprintf(file,"/* types name is \"%s\" */\n",
+                               XkbAtomText(dpy,xkb->names->types,XkbCFile));
+    }
+    for (i=0,type=map->types;i<map->num_types;i++,type++) {
+       if (!(prefix = strdup(XkbAtomText(dpy,type->name,XkbCFile)))) {
+               _XkbLibError(_XkbErrBadAlloc,"WriteCHdrKeyTypes",0);
+               return False;
+       }
+
+       if (type->map_count>0) {
+           XkbKTMapEntryPtr    entry;
+           entry= type->map;
+           fprintf(file,"static XkbKTMapEntryRec map_%s[%d]= {\n",prefix,
+                                                       type->map_count);
+           for (n=0;n<(unsigned)type->map_count;n++,entry++) {
+               if (n!=0)
+                   fprintf(file,",\n");
+               fprintf(file,"    { %d, %6d, { %15s, %15s, %15s } }",
+                       entry->active,
+                       entry->level,
+                       XkbModMaskText(entry->mods.mask,XkbCFile),
+                       XkbModMaskText(entry->mods.real_mods,XkbCFile),
+                       XkbVModMaskText(dpy,xkb,0,entry->mods.vmods,XkbCFile));
+           }
+           fprintf(file,"\n};\n");
+
+           if (type->preserve)
+               WriteTypePreserve(file,dpy,prefix,xkb,type);
+       }
+       if (type->level_names!=NULL) {
+           fprintf(file,"static Atom lnames_%s[%d];\n",prefix,
+                                                        type->num_levels);
+       }
+       fprintf(file,"\n");
+       free(prefix);
+       prefix = NULL;
+    }
+    fprintf(file,"static XkbKeyTypeRec dflt_types[]= {\n");
+    for (i=0,type=map->types;i<(unsigned)map->num_types;i++,type++) {
+       if (!(prefix = strdup(XkbAtomText(dpy,type->name,XkbCFile)))) {
+               _XkbLibError(_XkbErrBadAlloc,"WriteCHdrKeyTypes",0);
+               return False;
+       }
+       if (i!=0)       fprintf(file,",\n");
+       fprintf(file,"    {\n   { %15s, %15s, %15s },\n",
+                       XkbModMaskText(type->mods.mask,XkbCFile),
+                       XkbModMaskText(type->mods.real_mods,XkbCFile),
+                       XkbVModMaskText(dpy,xkb,0,type->mods.vmods,XkbCFile));
+       fprintf(file,"  %d,\n",type->num_levels);
+       fprintf(file,"  %d,",type->map_count);
+       if (type->map_count>0)
+            fprintf(file,"     map_%s,",prefix);
+       else fprintf(file,"     NULL,");
+       if (type->preserve)
+            fprintf(file,"     preserve_%s,\n",prefix);
+       else fprintf(file,"     NULL,\n");
+       if (type->level_names!=NULL)
+            fprintf(file,"     None,   lnames_%s\n    }",prefix);
+       else fprintf(file,"     None,   NULL\n    }");
+       free(prefix);
+       prefix = NULL;
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"#define num_dflt_types (sizeof(dflt_types)/sizeof(XkbKeyTypeRec))\n");
+    WriteTypeInitFunc(file,dpy,xkb);
+    return True;
+}
+
+static Bool
+WriteCHdrCompatMap(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register unsigned      i;
+XkbCompatMapPtr                compat;
+XkbSymInterpretPtr     interp;
+
+    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
+       _XkbLibError(_XkbErrMissingSymInterps,"WriteCHdrInterp",0);
+       return False;
+    }
+    compat= xkb->compat;
+    if ((xkb->names!=NULL)&&(xkb->names->compat!=None)) {
+       fprintf(file,"/* compat name is \"%s\" */\n",
+                               XkbAtomText(dpy,xkb->names->compat,XkbCFile));
+    }
+    fprintf(file,"static XkbSymInterpretRec dfltSI[%d]= {\n",
+                                               compat->num_si);
+    interp= compat->sym_interpret;
+    for (i=0;i<compat->num_si;i++,interp++) {
+       XkbAction *act;
+       act= (XkbAction *)&interp->act;
+       if (i!=0)       fprintf(file,",\n");
+       fprintf(file,"    {    %s, ",XkbKeysymText(interp->sym,XkbCFile));
+       fprintf(file,"0x%04x,\n",interp->flags);
+       fprintf(file,"         %s, ",XkbSIMatchText(interp->match,XkbCFile));
+       fprintf(file,"%s,\n",XkbModMaskText(interp->mods,XkbCFile));
+       fprintf(file,"         %d,\n",interp->virtual_mod);
+       fprintf(file,"       %s }",XkbActionText(dpy,xkb,act,XkbCFile));
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,
+          "#define num_dfltSI (sizeof(dfltSI)/sizeof(XkbSymInterpretRec))\n");
+    fprintf(file,"\nstatic XkbCompatMapRec compatMap= {\n");
+    fprintf(file,"    dfltSI,\n");
+    fprintf(file,"    {   /* group compatibility */\n        ");
+    for (i=0;i<XkbNumKbdGroups;i++) {
+       XkbModsPtr gc;
+       gc= &xkb->compat->groups[i];
+       fprintf(file,"%s{ %12s, %12s, %12s }",
+                       ((i==0)?"":",\n        "),
+                       XkbModMaskText(gc->mask,XkbCFile),
+                       XkbModMaskText(gc->real_mods,XkbCFile),
+                       XkbVModMaskText(xkb->dpy,xkb,0,gc->vmods,XkbCFile));
+    }
+    fprintf(file,"\n    },\n");
+    fprintf(file,"    num_dfltSI, num_dfltSI\n");
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteCHdrSymbols(FILE *file,XkbDescPtr xkb)
+{
+register unsigned i;
+
+    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
+       _XkbLibError(_XkbErrMissingSymbols,"WriteCHdrSymbols",0);
+       return False;
+    }
+    fprintf(file,"#define NUM_SYMBOLS  %d\n",xkb->map->num_syms);
+    if (xkb->map->num_syms>0) {
+       register KeySym *sym;
+       sym= xkb->map->syms;
+       fprintf(file,"static KeySym     symCache[NUM_SYMBOLS]= {\n");
+       for (i=0;i<xkb->map->num_syms;i++,sym++) {
+           if (i==0)           fprintf(file,"    ");
+           else if (i%4==0)    fprintf(file,",\n    ");
+           else                fprintf(file,", ");
+           fprintf(file,"%15s",XkbKeysymText(*sym,XkbCFile));
+       }
+       fprintf(file,"\n};\n");
+    }
+    if (xkb->max_key_code>0) {
+       register XkbSymMapPtr   map;
+       map= xkb->map->key_sym_map;
+       fprintf(file,"static XkbSymMapRec       symMap[NUM_KEYS]= {\n");
+       for (i=0;i<=xkb->max_key_code;i++,map++) {
+           if (i==0)           fprintf(file,"    ");
+           else if ((i&3)==0)  fprintf(file,",\n    ");
+           else                        fprintf(file,", ");
+           fprintf(file, "{ %2d, 0x%x, %3d }",
+                   map->kt_index[0], map->group_info, map->offset);
+       }
+       fprintf(file,"\n};\n");
+    }
+    return True;
+}
+
+static Bool
+WriteCHdrClientMap(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
+       _XkbLibError(_XkbErrMissingSymbols,"WriteCHdrClientMap",0);
+       return False;
+    }
+    if (!WriteCHdrKeyTypes(file,dpy,xkb))
+       return False;
+    if (!WriteCHdrSymbols(file,xkb))
+       return False;
+    fprintf(file,"static XkbClientMapRec clientMap= {\n");
+    fprintf(file,"    NUM_TYPES,   NUM_TYPES,   types, \n");
+    fprintf(file,"    NUM_SYMBOLS, NUM_SYMBOLS, symCache, symMap\n");
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteCHdrServerMap(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register unsigned i;
+
+    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
+       _XkbLibError(_XkbErrMissingSymbols,"WriteCHdrServerMap",0);
+       return False;
+    }
+    if (xkb->server->num_acts>0) {
+       register XkbAnyAction *act;
+       act= (XkbAnyAction *)xkb->server->acts;
+       fprintf(file,"#define NUM_ACTIONS       %d\n",xkb->server->num_acts);
+       fprintf(file,"static XkbAnyAction       actionCache[NUM_ACTIONS]= {\n");
+       for (i=0;i<xkb->server->num_acts;i++,act++) {
+           if (i==0)   fprintf(file,"    ");
+           else        fprintf(file,",\n    ");
+           fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)act,XkbCFile));
+       }
+       fprintf(file,"\n};\n");
+    }
+    fprintf(file,"static unsigned short        keyActions[NUM_KEYS]= {\n");
+    for (i=0;i<=xkb->max_key_code;i++) {
+       if (i==0)               fprintf(file,"    ");
+       else if ((i&0xf)==0)    fprintf(file,",\n    ");
+       else                    fprintf(file,", ");
+       fprintf(file,"%2d",xkb->server->key_acts[i]);
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"static XkbBehavior behaviors[NUM_KEYS]= {\n");
+    for (i=0;i<=xkb->max_key_code;i++) {
+       if (i==0)               fprintf(file,"    ");
+       else if ((i&0x3)==0)    fprintf(file,",\n    ");
+       else                    fprintf(file,", ");
+       if (xkb->server->behaviors) {
+            fprintf(file,"%s",
+               XkbBehaviorText(xkb,&xkb->server->behaviors[i],XkbCFile));
+       }
+       else fprintf(file,"{    0,    0 }");
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"static unsigned char explicit_parts[NUM_KEYS]= {\n");
+    for (i=0;i<=xkb->max_key_code;i++) {
+       if (i==0)               fprintf(file,"    ");
+       else if ((i&0x7)==0)    fprintf(file,",\n    ");
+       else                    fprintf(file,", ");
+       if ((xkb->server->explicit==NULL)||(xkb->server->explicit[i]==0))
+            fprintf(file,"   0");
+       else fprintf(file,"0x%02x",xkb->server->explicit[i]);
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"static unsigned short vmodmap[NUM_KEYS]= {\n");
+    for (i=0;i<xkb->max_key_code;i++) {
+       if (i==0)               fprintf(file,"    ");
+       else if ((i&0x7)==0)    fprintf(file,",\n    ");
+       else                    fprintf(file,", ");
+       if ((xkb->server->vmodmap==NULL)||(xkb->server->vmodmap[i]==0))
+            fprintf(file,"     0");
+       else fprintf(file,"0x%04x",xkb->server->vmodmap[i]);
+    }
+    fprintf(file,"};\n");
+    fprintf(file,"static XkbServerMapRec serverMap= {\n");
+    fprintf(file,"    %d, %d, (XkbAction *)actionCache,\n",
+                               xkb->server->num_acts,xkb->server->num_acts);
+    fprintf(file,"    behaviors, keyActions, explicit_parts,\n");
+    for (i=0;i<XkbNumVirtualMods;i++) {
+       if (i==0)       fprintf(file,"    { ");
+       else if (i==8)  fprintf(file,",\n      ");
+       else            fprintf(file,", ");
+       fprintf(file,"%3d",xkb->server->vmods[i]);
+    }
+    fprintf(file," },\n");
+    fprintf(file,"    vmodmap\n");
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteCHdrIndicators(FILE *file,Display *dpy,XkbDescPtr xkb)
+{
+register int           i,nNames;
+XkbIndicatorMapPtr     imap;
+
+    if (xkb->indicators==NULL)
+       return True;
+    fprintf(file, "static XkbIndicatorRec indicators= {\n");
+    fprintf(file, "    0x%lx,\n    {\n",
+           (long)xkb->indicators->phys_indicators);
+    for (imap=xkb->indicators->maps,i=nNames=0;i<XkbNumIndicators;i++,imap++) {
+       fprintf(file,"%s        { 0x%02x, %s, 0x%02x, %s, { %s, ",
+                       (i!=0?",\n":""),
+                       imap->flags,
+                       XkbIMWhichStateMaskText(imap->which_groups,XkbCFile),
+                       imap->groups,
+                       XkbIMWhichStateMaskText(imap->which_mods,XkbCFile),
+                       XkbModMaskText(imap->mods.mask,XkbCFile));
+       fprintf(file," %s, %s }, %s }",
+                       XkbModMaskText(imap->mods.real_mods,XkbCFile),
+                       XkbVModMaskText(dpy,xkb,0,imap->mods.vmods,XkbCFile),
+                       XkbControlsMaskText(imap->ctrls,XkbCFile));
+       if (xkb->names && (xkb->names->indicators[i]!=None))
+           nNames++;
+    }
+    fprintf(file,"\n    }\n};\n");
+    if (nNames>0) {
+       fprintf(file,"static void\n");
+       fprintf(file,"initIndicatorNames(DPYTYPE dpy,XkbDescPtr xkb)\n");
+       fprintf(file,"{\n");
+       for (i=0;i<XkbNumIndicators;i++) {
+           Atom name;
+           if (xkb->names->indicators[i]==None)
+               continue;
+           name= xkb->names->indicators[i];
+           fprintf(file,"    xkb->names->indicators[%2d]=      ",i);
+           fprintf(file,"GET_ATOM(dpy,\"%s\");\n",
+                                               XkbAtomText(dpy,name,XkbCFile));
+       }
+       fprintf(file,"}\n");
+    }
+    return True;
+}
+
+static Bool
+WriteCHdrGeomProps(FILE *file,XkbDescPtr xkb,XkbGeometryPtr geom)
+{
+    if (geom->num_properties>0) {
+       register int i;
+       fprintf(file,"\nstatic XkbPropertyRec g_props[%d]= {\n",
+                                                       geom->num_properties);
+       for (i=0;i<geom->num_properties;i++) {
+           fprintf(file,"%s    {       \"%s\", \"%s\"  }",(i==0?"":",\n"),
+                       XkbStringText(geom->properties[i].name,XkbCFile),
+                       XkbStringText(geom->properties[i].value,XkbCFile));
+       }
+       fprintf(file,"\n};\n");
+    }
+    return True;
+}
+
+static Bool
+WriteCHdrGeomColors(FILE *file,XkbDescPtr xkb,XkbGeometryPtr geom)
+{
+    if (geom->num_colors>0) {
+       register int i;
+       fprintf(file,"\nstatic XkbColorRec g_colors[%d]= {\n",geom->num_colors);
+       for (i=0;i<geom->num_colors;i++) {
+           fprintf(file,"%s    {       %3d, \"%s\"     }",(i==0?"":",\n"),
+                       geom->colors[i].pixel,
+                       XkbStringText(geom->colors[i].spec,XkbCFile));
+       }
+       fprintf(file,"\n};\n");
+    }
+    return True;
+}
+
+static Bool
+WriteCHdrGeomOutlines(FILE *file,int nOL,XkbOutlinePtr ol,int shapeNdx)
+{
+register int o,p;
+
+
+    for (o=0;o<nOL;o++) {
+       fprintf(file,"\nstatic XkbPointRec pts_sh%02do%02d[]= {\n",shapeNdx,o);
+       for (p=0;p<ol[o].num_points;p++) {
+           if (p==0)                   fprintf(file,"  ");
+           else if ((p&0x3)==0)        fprintf(file,",\n       ");
+           else                        fprintf(file,", ");
+           fprintf(file,"{ %4d, %4d }",
+                               ol[o].points[p].x,ol[o].points[p].y);
+       }
+       fprintf(file,"\n};");
+    }
+    fprintf(file,"\n\nstatic XkbOutlineRec ol_sh%02d[]= {\n",shapeNdx);
+    for (o=0;o<nOL;o++) {
+       fprintf(file,"%s        { %d,   %d,     %d,     pts_sh%02do%02d }",
+                                       (o==0?"":",\n"),
+                                       ol[o].num_points,ol[o].num_points,
+                                       ol[o].corner_radius,shapeNdx,o);
+    }
+    fprintf(file,"\n};\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomShapes(FILE *file,XkbDescPtr xkb,XkbGeometryPtr geom)
+{
+register int           s;
+register XkbShapePtr   shape;
+
+    for (s=0,shape=geom->shapes;s<geom->num_shapes;s++,shape++) {
+       WriteCHdrGeomOutlines(file,shape->num_outlines,shape->outlines,s);
+    }
+    fprintf(file,"\n\nstatic XkbShapeRec g_shapes[%d]= {\n",geom->num_shapes);
+    for (s=0,shape=geom->shapes;s<geom->num_shapes;s++,shape++) {
+       fprintf(file,"%s        { None, %3d, %3d, ol_sh%02d, ",
+                                       (s==0?"":",\n"),shape->num_outlines,
+                                       shape->num_outlines,s);
+       if (shape->approx) {
+           fprintf(file,"&ol_sh%02d[%2d],      ",s,
+                                       XkbOutlineIndex(shape,shape->approx));
+       }
+       else fprintf(file,"        NULL,        ");
+       if (shape->primary) {
+           fprintf(file,"&ol_sh%02d[%2d],\n",s,
+                                       XkbOutlineIndex(shape,shape->primary));
+       }
+       else fprintf(file,"        NULL,\n");
+       fprintf(file,"                                  { %4d, %4d, %4d, %4d } }",
+                                       shape->bounds.x1,shape->bounds.y1,
+                                       shape->bounds.x2,shape->bounds.y2);
+    }
+    fprintf(file,"\n};\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomDoodads(  FILE *          file,
+                       XkbDescPtr      xkb,
+                       XkbGeometryPtr  geom,
+                       XkbSectionPtr   section,
+                       int             section_num)
+{
+int            nd,d;
+XkbDoodadPtr   doodad;
+Display *      dpy;
+
+    dpy= xkb->dpy;
+    if (section==NULL) {
+       if (geom->num_doodads>0) {
+           fprintf(file,"static XkbDoodadRec g_doodads[%d];\n",
+                                                       geom->num_doodads);
+       }
+       fprintf(file,"static void\n");
+       fprintf(file,"_InitGeomDoodads(DPYTYPE dpy,XkbGeometryPtr geom)\n");
+       fprintf(file,"{\n");
+       fprintf(file,"register XkbDoodadPtr doodads;\n\n");
+       fprintf(file,"    doodads= geom->doodads;\n");
+       nd= geom->num_doodads;
+       doodad= geom->doodads;
+    }
+    else {
+       if (section->num_doodads>0) {
+           fprintf(file,"static XkbDoodadRec doodads_s%02d[%d];\n",
+                                       section_num,section->num_doodads);
+       }
+       fprintf(file,"static void\n");
+       fprintf(file,"_InitS%02dDoodads(",section_num);
+       fprintf(file,"    DPYTYPE               dpy,\n");
+       fprintf(file,"    XkbGeometryPtr        geom,\n");
+       fprintf(file,"    XkbSectionPtr         section)\n");
+       fprintf(file,"{\n");
+       fprintf(file,"register XkbDoodadPtr doodads;\n\n");
+       fprintf(file,"    doodads= section->doodads;\n");
+       nd= geom->num_doodads;
+       doodad= geom->doodads;
+    }
+    for (d=0;d<nd;d++,doodad++) {
+       if (d!=0)       fprintf(file,"\n");
+       fprintf(file,"    doodads[%d].any.name= GET_ATOM(dpy,\"%s\");\n",d,
+                       XkbAtomText(dpy,doodad->any.name,XkbCFile));
+       fprintf(file,"    doodads[%d].any.type= %s;\n",d,
+                       XkbDoodadTypeText(doodad->any.type,XkbCFile));
+       fprintf(file,"    doodads[%d].any.priority= %d;\n",d,
+                       doodad->any.priority);
+       fprintf(file,"    doodads[%d].any.top= %d;\n",d,doodad->any.top);
+       fprintf(file,"    doodads[%d].any.left= %d;\n",d,doodad->any.left);
+       fprintf(file,"    doodads[%d].any.angle= %d;\n",d,doodad->any.angle);
+       switch (doodad->any.type) {
+           case XkbOutlineDoodad:
+           case XkbSolidDoodad:
+               fprintf(file,"    doodads[%d].shape.color_ndx= %d;\n",d,
+                                       doodad->shape.color_ndx);
+               fprintf(file,"    doodads[%d].shape.shape_ndx= %d;\n",d,
+                                       doodad->shape.shape_ndx);
+               break;
+           case XkbTextDoodad:
+               fprintf(file,"    doodads[%d].text.width= %d;\n",d,
+                                       doodad->text.width);
+               fprintf(file,"    doodads[%d].text.height= %d;\n",d,
+                                       doodad->text.height);
+               fprintf(file,"    doodads[%d].text.color_ndx= %d;\n",d,
+                                       doodad->text.color_ndx);
+               fprintf(file,"    doodads[%d].text.text= \"%s\";\n",d,
+                               XkbStringText(doodad->text.text,XkbCFile));
+               fprintf(file,"    doodads[%d].text.font= \"%s\";\n",d,
+                               XkbStringText(doodad->text.font,XkbCFile));
+               break;
+           case XkbIndicatorDoodad:
+               fprintf(file,"    doodads[%d].indicator.shape_ndx= %d;\n",d,
+                                       doodad->indicator.shape_ndx);
+               fprintf(file,"    doodads[%d].indicator.on_color_ndx= %d;\n",d,
+                                       doodad->indicator.on_color_ndx);
+               fprintf(file,"    doodads[%d].indicator.off_color_ndx= %d;\n",d,
+                                       doodad->indicator.off_color_ndx);
+               break;
+           case XkbLogoDoodad:
+               fprintf(file,"    doodads[%d].logo.color_ndx= %d;\n",d,
+                                       doodad->logo.color_ndx);
+               fprintf(file,"    doodads[%d].logo.shape_ndx= %d;\n",d,
+                                       doodad->logo.shape_ndx);
+               fprintf(file,"    doodads[%d].logo.logo_name= \"%s\";\n",d,
+                               XkbStringText(doodad->logo.logo_name,XkbCFile));
+               break;
+       }
+    }
+    fprintf(file,"}\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomOverlays( FILE *          file,
+                       XkbDescPtr      xkb,
+                       XkbSectionPtr   section,
+                       int             section_num)
+{
+register int           o,r,k;
+XkbOverlayPtr          ol;
+XkbOverlayRowPtr       row;
+XkbOverlayKeyPtr       key;
+
+    if (section->num_overlays<1)
+       return True;
+    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
+       for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
+           fprintf(file,"static XkbOverlayKeyRec olkeys_s%02dr%02d[%d]= {\n",
+                                               section_num,r,row->num_keys);
+           for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+               fprintf(file,"%s        { {\"%s\"},     {\"%s\"}        }",
+                               (k==0?"":",\n"),
+                               XkbKeyNameText(key->over.name,XkbCFile),
+                               XkbKeyNameText(key->under.name,XkbCFile));
+           }
+           fprintf(file,"\n};\n");
+       }
+       fprintf(file,"static XkbOverlayRowRec olrows_s%02d[%d]= {\n",
+                                               section_num,section->num_rows);
+       for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
+           fprintf(file,"%s    { %4d, %4d, %4d, olkeys_s%02dr%02d }",
+                               (r==0?"":",\n"),
+                               row->row_under,row->num_keys,row->num_keys,
+                               section_num,r);
+       }
+       fprintf(file,"\n};\n");
+    }
+    fprintf(file,"static XkbOverlayRec overlays_s%02d[%d]= {\n",section_num,
+                                                       section->num_overlays);
+    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
+       fprintf(file,"%s        {\n",(o==0?"":",\n"));
+       fprintf(file,"      None,       /* name */\n");
+       fprintf(file,"      NULL,       /* section_under */\n");
+       fprintf(file,"      %4d,        /* num_rows */\n",ol->num_rows);
+       fprintf(file,"      %4d,        /* sz_rows */\n",ol->num_rows);
+       fprintf(file,"      olrows_s%02d,\n",section_num);
+       fprintf(file,"      NULL        /* bounds */\n");
+       fprintf(file,"  }");
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"static void\n");
+    fprintf(file,"_InitS%02dOverlay(",section_num);
+    fprintf(file,"    DPYTYPE          dpy,\n");
+    fprintf(file,"    XkbGeometryPtr   geom,\n");
+    fprintf(file,"    XkbSectionPtr    section)\n");
+    fprintf(file,"{\n");
+    fprintf(file,"XkbOverlayPtr        ol;\n\n");
+    fprintf(file,"    ol= section->overlays;\n");
+    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
+       fprintf(file,"    ol[%2d].name= GET_ATOM(dpy,\"%s\");\n",o,
+                               XkbAtomText(xkb->dpy,ol->name,XkbCFile));
+       fprintf(file,"    ol[%2d].section_under= section;\n",o);
+    }
+    fprintf(file,"}\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomRows(     FILE *          file,
+                       XkbDescPtr      xkb,
+                       XkbSectionPtr   section,
+                       int             section_num)
+{
+register int           k,r;
+register XkbRowPtr     row;
+register XkbKeyPtr     key;
+
+    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
+       fprintf(file,"static XkbKeyRec keys_s%02dr%02d[]= {\n",section_num,r);
+       for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+           fprintf(file,"%s    { { \"%s\" },   %4d, %4d, %4d }",
+                               (k==0?"":",\n"),
+                               XkbKeyNameText(key->name.name,XkbCFile),
+                               key->gap,key->shape_ndx,key->color_ndx);
+       }
+       fprintf(file,"\n};\n");
+    }
+    fprintf(file,"static XkbRowRec rows_s%02d[]= {\n",section_num);
+    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
+       fprintf(file,"%s        { %4d, %4d, %2d, %2d, %1d, keys_s%02dr%02d, ",
+                               (r==0?"":",\n"),
+                               row->top,row->left,row->num_keys,row->num_keys,
+                               (row->vertical!=0),
+                               section_num,r);
+       fprintf(file," { %4d, %4d, %4d, %4d } }",
+                               row->bounds.x1,row->bounds.y1,
+                               row->bounds.x2,row->bounds.y2);
+    }
+    fprintf(file,"\n};\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomSections(FILE *file,XkbDescPtr xkb,XkbGeometryPtr geom)
+{
+register int           s;
+register XkbSectionPtr section;
+
+    for (s=0,section=geom->sections;s<geom->num_sections;s++,section++) {
+       WriteCHdrGeomRows(file,xkb,section,s);
+#ifdef NOTYET
+       if (section->num_doodads>0)
+           WriteCHdrGeomDoodads(file,xkb,geom,section,s);
+#endif
+       if (section->num_overlays>0)
+           WriteCHdrGeomOverlays(file,xkb,section,s);
+    }
+    fprintf(file,"\nstatic XkbSectionRec g_sections[%d]= {\n",
+                                                       geom->num_sections);
+    for (s=0,section=geom->sections;s<geom->num_sections;s++,section++) {
+       if (s!=0) fprintf(file,",\n");
+       fprintf(file,"  {\n         None, /* name */\n");
+       fprintf(file,"      %4d, /* priority */\n",section->priority);
+       fprintf(file,"      %4d, /* top */\n",section->top);
+       fprintf(file,"      %4d, /* left */\n",section->left);
+       fprintf(file,"      %4d, /* width */\n",section->width);
+       fprintf(file,"      %4d, /* height */\n",section->height);
+       fprintf(file,"      %4d, /* angle */\n",section->angle);
+       fprintf(file,"      %4d, /* num_rows */\n",section->num_rows);
+       fprintf(file,"      %4d, /* num_doodads */\n",section->num_doodads);
+       fprintf(file,"      %4d, /* num_overlays */\n",section->num_overlays);
+       fprintf(file,"      %4d, /* sz_rows */\n",section->num_rows);
+       fprintf(file,"      %4d, /* sz_doodads */\n",section->num_doodads);
+       fprintf(file,"      %4d, /* sz_overlays */\n",section->num_overlays);
+       if (section->num_rows>0)
+            fprintf(file,"         rows_s%02d,\n",s);
+       else fprintf(file,"         NULL, /* rows */\n");
+       if (section->num_doodads>0)
+            fprintf(file,"         doodads_s%02d,\n",s);
+       else fprintf(file,"         NULL, /* doodads */\n");
+       fprintf(file,"      { %4d, %4d, %4d, %4d }, /* bounds */\n",
+                                       section->bounds.x1,section->bounds.y1,
+                                       section->bounds.x2,section->bounds.y2);
+       if (section->num_overlays>0)
+            fprintf(file,"         overlays_s%02d\n",s);
+       else fprintf(file,"         NULL /* overlays */\n");
+       fprintf(file,"  }");
+    }
+    fprintf(file,"\n};\n");
+    fprintf(file,"\nstatic Bool\n");
+    fprintf(file,"_InitSections(DPYTYPE dpy,XkbGeometryPtr geom)\n");
+    fprintf(file,"{\nXkbSectionPtr     sections;\n\n");
+    fprintf(file,"    sections= geom->sections;\n");
+    for (s=0,section=geom->sections;s<geom->num_sections;s++,section++) {
+       if (section->num_doodads>0) {
+           fprintf(file,"    _InitS%02dDoodads(dpy,geom,&sections[%d]);\n",
+                                                                       s,s);
+       }
+       if (section->num_overlays>0) {
+           fprintf(file,"    _InitS%02dOverlays(dpy,geom,&sections[%d]);\n",
+                                                                       s,s);
+       }
+    }
+    fprintf(file,"}\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomAliases(FILE *file,XkbDescPtr xkb,XkbGeometryPtr geom)
+{
+    if (geom->num_key_aliases>0) {
+       register int i;
+       fprintf(file,"\nstatic XkbKeyAliasRec g_aliases[%d]= {\n",
+                                               geom->num_key_aliases);
+       for (i=0;i<geom->num_key_aliases;i++) {
+           fprintf(file,"%s    {       \"%s\", \"%s\"  }",(i==0?"":",\n"),
+                       XkbKeyNameText(geom->key_aliases[i].real,XkbCFile),
+                       XkbKeyNameText(geom->key_aliases[i].alias,XkbCFile));
+       }
+       fprintf(file,"\n};\n");
+    }
+    return True;
+}
+
+static Bool
+WriteCHdrGeometry(FILE *file,XkbDescPtr xkb)
+{
+XkbGeometryPtr geom;
+register int   i;
+
+    if ((!xkb)||(!xkb->geom)) {
+       _XkbLibError(_XkbErrMissingGeometry,"WriteCHdrGeometry",0);
+       return False;
+    }
+    geom= xkb->geom;
+    WriteCHdrGeomProps(file,xkb,geom);
+    WriteCHdrGeomColors(file,xkb,geom);
+    WriteCHdrGeomShapes(file,xkb,geom);
+    WriteCHdrGeomSections(file,xkb,geom);
+    WriteCHdrGeomDoodads(file,xkb,geom,NULL,0);
+    WriteCHdrGeomAliases(file,xkb,geom);
+    fprintf(file,"\nstatic XkbGeometryRec      geom= {\n");
+    fprintf(file,"     None,                   /* name */\n");
+    fprintf(file,"     %d, %d,         /* width, height */\n",geom->width_mm,
+                                                       geom->height_mm);
+    if (geom->label_font) {
+        fprintf(file," \"%s\",/* label font */\n",
+                               XkbStringText(geom->label_font,XkbCFile));
+    }
+    else fprintf(file,"        NULL,           /* label font */\n");
+    if (geom->label_color) {
+       fprintf(file,"  &g_colors[%d],          /* label color */\n",
+                               XkbGeomColorIndex(geom,geom->label_color));
+    }
+    else fprintf(file,"        NULL,                   /* label color */\n");
+    if (geom->base_color) {
+       fprintf(file,"  &g_colors[%d],          /* base color */\n",
+                               XkbGeomColorIndex(geom,geom->base_color));
+    }
+    else fprintf(file,"        NULL,                   /* base color */\n");
+    fprintf(file,"     %d,     %d,     %d,     /*  sz: props, colors, shapes */\n",
+                               geom->num_properties,geom->num_colors,
+                               geom->num_shapes);
+    fprintf(file,"     %d,     %d,     %d,     /*  sz: sections, doodads, aliases */\n",
+                               geom->num_sections,geom->num_doodads,
+                               geom->num_key_aliases);
+    fprintf(file,"     %d,     %d,     %d,     /* num: props, colors, shapes */\n",
+                               geom->num_properties,geom->num_colors,
+                               geom->num_shapes);
+    fprintf(file,"     %d,     %d,     %d,     /* num: sections, doodads, aliases */\n",
+                               geom->num_sections,geom->num_doodads,
+                               geom->num_key_aliases);
+    fprintf(file,"     %s,     %s,     %s,\n",
+                               (geom->num_properties>0?"g_props":"NULL"),
+                               (geom->num_colors>0?"g_colors":"NULL"),
+                               (geom->num_shapes>0?"g_shapes":"NULL"));
+    fprintf(file,"     %s,     %s,     %s\n",
+                               (geom->num_sections>0?"g_sections":"NULL"),
+                               (geom->num_doodads>0?"g_doodads":"NULL"),
+                               (geom->num_key_aliases>0?"g_aliases":"NULL"));
+    fprintf(file,"};\n\n");
+    fprintf(file,"static Bool\n");
+    fprintf(file,"_InitHdrGeom(DPYTYPE dpy,XkbGeometryPtr geom)\n");
+    fprintf(file,"{\n");
+    if (geom->name!=None) {
+       fprintf(file,"    geom->name= GET_ATOM(dpy,\"%s\");\n",
+                               XkbAtomText(xkb->dpy,geom->name,XkbCFile));
+    }
+    for (i=0;i<geom->num_shapes;i++) {
+       fprintf(file,"    geom->shapes[%2d].name= GET_ATOM(dpy,\"%s\");\n",i,
+                       XkbAtomText(xkb->dpy,geom->shapes[i].name,XkbCFile));
+    }
+    if (geom->num_doodads>0)
+       fprintf(file,"    _InitGeomDoodads(dpy,geom);\n");
+    fprintf(file,"    _InitSections(dpy,geom);\n");
+    fprintf(file,"}\n\n");
+    return True;
+}
+
+static Bool
+WriteCHdrGeomFile(FILE *file,XkbFileInfo *result)
+{
+Bool           ok;
+
+    ok= WriteCHdrGeometry(file,result->xkb);
+    return ok;
+}
+
+static Bool
+WriteCHdrLayout(FILE *file,XkbFileInfo *result)
+{
+Bool           ok;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    ok= WriteCHdrVMods(file,xkb->dpy,xkb);
+    ok= WriteCHdrKeycodes(file,xkb)&&ok;
+    ok= WriteCHdrSymbols(file,xkb)&&ok;
+    ok= WriteCHdrGeometry(file,xkb)&&ok;
+    return ok;
+}
+
+static Bool
+WriteCHdrSemantics(FILE *file,XkbFileInfo *result)
+{
+Bool           ok;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    ok= WriteCHdrVMods(file,xkb->dpy,xkb);
+    ok= WriteCHdrKeyTypes(file,xkb->dpy,xkb)&&ok;
+    ok= WriteCHdrCompatMap(file,xkb->dpy,xkb)&&ok;
+    ok= WriteCHdrIndicators(file,xkb->dpy,xkb)&&ok;
+    return ok;
+}
+
+static Bool
+WriteCHdrKeymap(FILE *file,XkbFileInfo *result)
+{
+Bool           ok;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    ok= WriteCHdrVMods(file,xkb->dpy,xkb);
+    ok= ok&&WriteCHdrKeycodes(file,xkb);
+    ok= ok&&WriteCHdrClientMap(file,xkb->dpy,xkb);
+    ok= ok&&WriteCHdrServerMap(file,xkb->dpy,xkb);
+    ok= ok&&WriteCHdrCompatMap(file,xkb->dpy,xkb);
+    ok= WriteCHdrIndicators(file,xkb->dpy,xkb)&&ok;
+    ok= ok&&WriteCHdrGeometry(file,xkb);
+    return ok;
+}
+
+Bool
+XkbWriteCFile(FILE *out,char *name,XkbFileInfo *result)
+{
+Bool                   ok;
+XkbDescPtr             xkb;
+Bool                   (*func)(
+       FILE *          /* file*/,
+       XkbFileInfo *   /* result */
+);
+
+    switch (result->type) {
+       case XkmSemanticsFile:
+           func= WriteCHdrSemantics;
+           break;
+       case XkmLayoutFile:
+           func= WriteCHdrLayout;
+           break;
+       case XkmKeymapFile:
+           func= WriteCHdrKeymap;
+           break;
+        case XkmGeometryIndex:
+        case XkmGeometryFile:
+           func= WriteCHdrGeomFile;
+           break;
+       default:
+           _XkbLibError(_XkbErrIllegalContents,"XkbWriteCFile",result->type);
+           return False;
+    }
+    xkb= result->xkb;
+    if (out==NULL) {
+       _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteCFile",0);
+       ok= False;
+    }
+    else {
+       char *tmp,*hdrdef;
+       tmp= (char *)strrchr(name,'/');
+       if (tmp==NULL)
+            tmp= name;
+       else tmp++;
+       hdrdef= (char *)_XkbCalloc(strlen(tmp)+1,sizeof(char));
+       if (hdrdef) {
+           strcpy(hdrdef,tmp);
+           tmp= hdrdef;
+           while (*tmp) {
+               if (islower(*tmp))              *tmp= toupper(*tmp);
+               else if (!isalnum(*tmp))        *tmp= '_';
+               tmp++;
+           }
+           fprintf(out,"/* This file generated automatically by xkbcomp */\n");
+           fprintf(out,"/* DO  NOT EDIT */\n");
+           fprintf(out,"#ifndef %s\n",hdrdef);
+           fprintf(out,"#define %s 1\n\n",hdrdef);
+       }
+       fprintf(out,"#ifndef XKB_IN_SERVER\n");
+       fprintf(out,"#define GET_ATOM(d,s)      XInternAtom(d,s,0)\n");
+       fprintf(out,"#define DPYTYPE    Display *\n");
+       fprintf(out,"#else\n");
+       fprintf(out,"#define GET_ATOM(d,s)      MakeAtom(s,strlen(s),1)\n");
+       fprintf(out,"#define DPYTYPE    char *\n");
+       fprintf(out,"#endif\n");
+       fprintf(out,"#define NUM_KEYS   %d\n",xkb->max_key_code+1);
+       ok= (*func)(out,result);
+       if (hdrdef)
+           fprintf(out,"#endif /* %s */\n",hdrdef);
+    }
+
+    if (!ok) {
+       return False;
+    }
+    return True;
+}
diff --git a/src/magic b/src/magic
new file mode 100644 (file)
index 0000000..9c433ad
--- /dev/null
+++ b/src/magic
@@ -0,0 +1,11 @@
+# $Xorg: magic,v 1.3 2000/08/17 19:46:43 cpqbld Exp $
+# Here are some lines you can add to /etc/magic
+# to identify XKM (compiled X keymap) files
+# and determine their version and the byte ordering
+# with which they were compiled
+1      string  mkx                             Compiled XKB Keymap: lsb,
+>0     byte    >0                              version %d
+>0     byte    =0                              obsolete
+0      string  xkm                             Compiled XKB Keymap: msb,
+>3     byte    >0                              version %d
+>0     byte    =0                              obsolete
diff --git a/src/maprules.c b/src/maprules.c
new file mode 100644 (file)
index 0000000..81102a3
--- /dev/null
@@ -0,0 +1,1485 @@
+/************************************************************
+ Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#define X_INCLUDE_STRING_H
+#define XOS_USE_NO_LOCKING
+#include <X11/Xos_r.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+#include "XKBrules.h"
+
+#else
+
+#include <X11/Xproto.h>
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+
+#endif
+
+#ifdef DEBUG
+#define PR_DEBUG(s)            fprintf(stderr,s)
+#define PR_DEBUG1(s,a)         fprintf(stderr,s,a)
+#define PR_DEBUG2(s,a,b)       fprintf(stderr,s,a,b)
+#else
+#define PR_DEBUG(s)
+#define PR_DEBUG1(s,a)
+#define PR_DEBUG2(s,a,b)
+#endif
+
+/***====================================================================***/
+
+#define DFLT_LINE_SIZE 128
+
+typedef struct {
+       int     line_num;
+       int     sz_line;
+       int     num_line;
+       char    buf[DFLT_LINE_SIZE];
+       char *  line;
+} InputLine;
+
+static void
+InitInputLine(InputLine *line)
+{
+    line->line_num= 1;
+    line->num_line= 0;
+    line->sz_line= DFLT_LINE_SIZE;
+    line->line=        line->buf;
+    return;
+}
+
+static void
+FreeInputLine(InputLine *line)
+{
+    if (line->line!=line->buf)
+       _XkbFree(line->line);
+    line->line_num= 1;
+    line->num_line= 0;
+    line->sz_line= DFLT_LINE_SIZE;
+    line->line= line->buf;
+    return;
+}
+
+static int
+InputLineAddChar(InputLine *line,int ch)
+{
+    if (line->num_line>=line->sz_line) {
+       if (line->line==line->buf) {
+           line->line= (char *)_XkbAlloc(line->sz_line*2);
+           memcpy(line->line,line->buf,line->sz_line);
+       }
+       else {
+           line->line=(char *)_XkbRealloc((char *)line->line,line->sz_line*2);
+       }
+       line->sz_line*= 2;
+    }
+    line->line[line->num_line++]= ch;
+    return ch;
+}
+
+#define        ADD_CHAR(l,c)   ((l)->num_line<(l)->sz_line?\
+                               (int)((l)->line[(l)->num_line++]= (c)):\
+                               InputLineAddChar(l,c))
+
+#ifdef HAVE_UNLOCKED_STDIO
+#undef getc
+#define getc(x) getc_unlocked(x)
+#else
+#define flockfile(x) do {} while (0)
+#define funlockfile(x) do {} while (0)
+#endif
+
+static Bool
+GetInputLine(FILE *file,InputLine *line,Bool checkbang)
+{
+int    ch;
+Bool   endOfFile,spacePending,slashPending,inComment;
+
+     endOfFile= False;
+     flockfile(file);
+     while ((!endOfFile)&&(line->num_line==0)) {
+       spacePending= slashPending= inComment= False;
+       while (((ch=getc(file))!='\n')&&(ch!=EOF)) {
+           if (ch=='\\') {
+               if ((ch=getc(file))==EOF)
+                   break;
+               if (ch=='\n') {
+                   inComment= False;
+                   ch= ' ';
+                   line->line_num++;
+               }
+           }
+           if (inComment)
+               continue;
+           if (ch=='/') {
+               if (slashPending) {
+                   inComment= True;
+                   slashPending= False;
+               }
+               else {
+                   slashPending= True;
+               }
+               continue;
+           }
+           else if (slashPending) {
+               if (spacePending) {
+                   ADD_CHAR(line,' ');
+                   spacePending= False;
+               }
+               ADD_CHAR(line,'/');
+               slashPending= False;
+           }
+           if (isspace(ch)) {
+               while (isspace(ch)&&(ch!='\n')&&(ch!=EOF)) {
+                   ch= getc(file);
+               }
+               if (ch==EOF)
+                   break;
+               if ((ch!='\n')&&(line->num_line>0))
+                   spacePending= True;
+               ungetc(ch,file);
+           }
+           else {
+               if (spacePending) {
+                   ADD_CHAR(line,' ');
+                   spacePending= False;
+               }
+               if (checkbang && ch=='!') {
+                   if (line->num_line!=0) {
+                       PR_DEBUG("The '!' legal only at start of line\n");
+                       PR_DEBUG("Line containing '!' ignored\n");
+                       line->num_line= 0;
+                       inComment= 0;
+                       break;
+                   }
+
+               }
+               ADD_CHAR(line,ch);
+           }
+       }
+       if (ch==EOF)
+            endOfFile= True;
+/*     else line->num_line++;*/
+     }
+     funlockfile(file);
+     if ((line->num_line==0)&&(endOfFile))
+       return False;
+      ADD_CHAR(line,'\0');
+      return True;
+}
+
+/***====================================================================***/
+
+#define        MODEL           0
+#define        LAYOUT          1
+#define        VARIANT         2
+#define        OPTION          3
+#define        KEYCODES        4
+#define SYMBOLS                5
+#define        TYPES           6
+#define        COMPAT          7
+#define        GEOMETRY        8
+#define        KEYMAP          9
+#define        MAX_WORDS       10
+
+#define        PART_MASK       0x000F
+#define        COMPONENT_MASK  0x03F0
+
+static const char *    cname[MAX_WORDS] = {
+       "model", "layout", "variant", "option",
+       "keycodes", "symbols", "types", "compat", "geometry", "keymap"
+};
+
+typedef        struct _RemapSpec {
+       int                     number;
+       int                     num_remap;
+       struct  {
+               int     word;
+               int     index;
+                }              remap[MAX_WORDS];
+} RemapSpec;
+
+typedef struct _FileSpec {
+       char *                  name[MAX_WORDS];
+       struct _FileSpec *      pending;
+} FileSpec;
+
+typedef struct {
+       char *                  model;
+       char *                  layout[XkbNumKbdGroups+1];
+       char *                  variant[XkbNumKbdGroups+1];
+       char *                  options;
+} XkbRF_MultiDefsRec, *XkbRF_MultiDefsPtr;
+
+#define NDX_BUFF_SIZE  4
+
+/***====================================================================***/
+
+static char*
+get_index(char *str, int *ndx)
+{
+   char ndx_buf[NDX_BUFF_SIZE];
+   char *end;
+
+   if (*str != '[') {
+       *ndx = 0;
+       return str;
+   }
+   str++;
+   end = strchr(str, ']');
+   if (end == NULL) {
+       *ndx = -1;
+       return str - 1;
+   }
+   if ( (end - str) >= NDX_BUFF_SIZE) {
+       *ndx = -1;
+       return end + 1;
+   }
+   strncpy(ndx_buf, str, end - str);
+   ndx_buf[end - str] = '\0';
+   *ndx = atoi(ndx_buf);
+   return end + 1;
+}
+
+static void
+SetUpRemap(InputLine *line,RemapSpec *remap)
+{
+char *         tok,*str;
+unsigned       present, l_ndx_present, v_ndx_present;
+register int   i;
+int            len, ndx;
+_Xstrtokparams strtok_buf;
+#ifdef DEBUG
+Bool           found;
+#endif
+
+
+   l_ndx_present = v_ndx_present = present= 0;
+   str= &line->line[1];
+   len = remap->number;
+   bzero((char *)remap,sizeof(RemapSpec));
+   remap->number = len;
+   while ((tok=_XStrtok(str," ",strtok_buf))!=NULL) {
+#ifdef DEBUG
+       found= False;
+#endif
+       str= NULL;
+       if (strcmp(tok,"=")==0)
+           continue;
+       for (i=0;i<MAX_WORDS;i++) {
+            len = strlen(cname[i]);
+           if (strncmp(cname[i],tok,len)==0) {
+               if(strlen(tok) > len) {
+                   char *end = get_index(tok+len, &ndx);
+                   if ((i != LAYOUT && i != VARIANT) ||
+                       *end != '\0' || ndx == -1)
+                       break;
+                    if (ndx < 1 || ndx > XkbNumKbdGroups) {
+                       PR_DEBUG2("Illegal %s index: %d\n", cname[i], ndx);
+                       PR_DEBUG1("Index must be in range 1..%d\n",
+                                  XkbNumKbdGroups);
+                       break;
+                    }
+                } else {
+                   ndx = 0;
+                }
+#ifdef DEBUG
+               found= True;
+#endif
+               if (present&(1<<i)) {
+                   if ((i == LAYOUT && l_ndx_present&(1<<ndx)) ||
+                       (i == VARIANT && v_ndx_present&(1<<ndx)) ) {
+                       PR_DEBUG1("Component \"%s\" listed twice\n",tok);
+                       PR_DEBUG("Second definition ignored\n");
+                       break;
+                   }
+               }
+               present |= (1<<i);
+                if (i == LAYOUT)
+                    l_ndx_present |= 1 << ndx;
+                if (i == VARIANT)
+                    v_ndx_present |= 1 << ndx;
+               remap->remap[remap->num_remap].word= i;
+               remap->remap[remap->num_remap++].index= ndx;
+               break;
+           }
+       }
+#ifdef DEBUG
+       if (!found) {
+           fprintf(stderr,"Unknown component \"%s\" ignored\n",tok);
+       }
+#endif
+   }
+   if ((present&PART_MASK)==0) {
+#ifdef DEBUG
+       unsigned mask= PART_MASK;
+       fprintf(stderr,"Mapping needs at least one of ");
+       for (i=0; (i<MAX_WORDS); i++) {
+           if ((1L<<i)&mask) {
+               mask&= ~(1L<<i);
+               if (mask)       fprintf(stderr,"\"%s,\" ",cname[i]);
+               else            fprintf(stderr,"or \"%s\"\n",cname[i]);
+           }
+       }
+       fprintf(stderr,"Illegal mapping ignored\n");
+#endif
+       remap->num_remap= 0;
+       return;
+   }
+   if ((present&COMPONENT_MASK)==0) {
+       PR_DEBUG("Mapping needs at least one component\n");
+       PR_DEBUG("Illegal mapping ignored\n");
+       remap->num_remap= 0;
+       return;
+   }
+   if (((present&COMPONENT_MASK)&(1<<KEYMAP))&&
+                               ((present&COMPONENT_MASK)!=(1<<KEYMAP))) {
+       PR_DEBUG("Keymap cannot appear with other components\n");
+       PR_DEBUG("Illegal mapping ignored\n");
+       remap->num_remap= 0;
+       return;
+   }
+   remap->number++;
+   return;
+}
+
+static Bool
+MatchOneOf(char *wanted,char *vals_defined)
+{
+char   *str,*next;
+int    want_len= strlen(wanted);
+
+    for (str=vals_defined,next=NULL;str!=NULL;str=next) {
+       int len;
+       next= strchr(str,',');
+       if (next) {
+           len= next-str;
+           next++;
+       }
+       else {
+           len= strlen(str);
+       }
+       if ((len==want_len)&&(strncmp(wanted,str,len)==0))
+           return True;
+    }
+    return False;
+}
+
+/***====================================================================***/
+
+static Bool
+CheckLine(     InputLine *             line,
+               RemapSpec *             remap,
+               XkbRF_RulePtr           rule,
+               XkbRF_GroupPtr          group)
+{
+char *         str,*tok;
+register int   nread, i;
+FileSpec       tmp;
+_Xstrtokparams strtok_buf;
+Bool           append = False;
+
+    if (line->line[0]=='!') {
+        if (line->line[1] == '$' ||
+            (line->line[1] == ' ' && line->line[2] == '$')) {
+            char *gname = strchr(line->line, '$');
+            char *words = strchr(gname, ' ');
+            if(!words)
+                return False;
+            *words++ = '\0';
+            for (; *words; words++) {
+                if (*words != '=' && *words != ' ')
+                    break;
+            }
+            if (*words == '\0')
+                return False;
+            group->name = _XkbDupString(gname);
+            group->words = _XkbDupString(words);
+            for (i = 1, words = group->words; *words; words++) {
+                 if ( *words == ' ') {
+                     *words++ = '\0';
+                     i++;
+                 }
+            }
+            group->number = i;
+            return True;
+        } else {
+           SetUpRemap(line,remap);
+           return False;
+        }
+    }
+
+    if (remap->num_remap==0) {
+       PR_DEBUG("Must have a mapping before first line of data\n");
+       PR_DEBUG("Illegal line of data ignored\n");
+       return False;
+    }
+    bzero((char *)&tmp,sizeof(FileSpec));
+    str= line->line;
+    for (nread= 0;(tok=_XStrtok(str," ",strtok_buf))!=NULL;nread++) {
+       str= NULL;
+       if (strcmp(tok,"=")==0) {
+           nread--;
+           continue;
+       }
+       if (nread>remap->num_remap) {
+           PR_DEBUG("Too many words on a line\n");
+           PR_DEBUG1("Extra word \"%s\" ignored\n",tok);
+           continue;
+       }
+       tmp.name[remap->remap[nread].word]= tok;
+       if (*tok == '+' || *tok == '|')
+           append = True;
+    }
+    if (nread<remap->num_remap) {
+       PR_DEBUG1("Too few words on a line: %s\n", line->line);
+       PR_DEBUG("line ignored\n");
+       return False;
+    }
+
+    rule->flags= 0;
+    rule->number = remap->number;
+    if (tmp.name[OPTION])
+        rule->flags|= XkbRF_Option;
+    else if (append)
+        rule->flags|= XkbRF_Append;
+    else
+        rule->flags|= XkbRF_Normal;
+    rule->model= _XkbDupString(tmp.name[MODEL]);
+    rule->layout= _XkbDupString(tmp.name[LAYOUT]);
+    rule->variant= _XkbDupString(tmp.name[VARIANT]);
+    rule->option= _XkbDupString(tmp.name[OPTION]);
+
+    rule->keycodes= _XkbDupString(tmp.name[KEYCODES]);
+    rule->symbols= _XkbDupString(tmp.name[SYMBOLS]);
+    rule->types= _XkbDupString(tmp.name[TYPES]);
+    rule->compat= _XkbDupString(tmp.name[COMPAT]);
+    rule->geometry= _XkbDupString(tmp.name[GEOMETRY]);
+    rule->keymap= _XkbDupString(tmp.name[KEYMAP]);
+
+    rule->layout_num = rule->variant_num = 0;
+    for (i = 0; i < nread; i++) {
+        if (remap->remap[i].index) {
+           if (remap->remap[i].word == LAYOUT)
+               rule->layout_num = remap->remap[i].index;
+           if (remap->remap[i].word == VARIANT)
+               rule->variant_num = remap->remap[i].index;
+        }
+    }
+    return True;
+}
+
+static char *
+_Concat(char *str1,char *str2)
+{
+int len;
+
+    if ((!str1)||(!str2))
+       return str1;
+    len= strlen(str1)+strlen(str2)+1;
+    str1= _XkbTypedRealloc(str1,len,char);
+    if (str1)
+       strcat(str1,str2);
+    return str1;
+}
+
+static void
+squeeze_spaces(char *p1)
+{
+   char *p2;
+   for (p2 = p1; *p2; p2++) {
+       *p1 = *p2;
+       if (*p1 != ' ') p1++;
+   }
+   *p1 = '\0';
+}
+
+static Bool
+MakeMultiDefs(XkbRF_MultiDefsPtr mdefs, XkbRF_VarDefsPtr defs)
+{
+
+   bzero((char *)mdefs,sizeof(XkbRF_MultiDefsRec));
+   mdefs->model = defs->model;
+   mdefs->options = _XkbDupString(defs->options);
+   if (mdefs->options) squeeze_spaces(mdefs->options);
+
+   if (defs->layout) {
+       if (!strchr(defs->layout, ',')) {
+           mdefs->layout[0] = defs->layout;
+       } else {
+           char *p;
+           int i;
+           mdefs->layout[1] = _XkbDupString(defs->layout);
+          if (mdefs->layout[1] == NULL)
+             return False;
+           squeeze_spaces(mdefs->layout[1]);
+           p = mdefs->layout[1];
+           for (i = 2; i <= XkbNumKbdGroups; i++) {
+              if ((p = strchr(p, ','))) {
+                 *p++ = '\0';
+                 mdefs->layout[i] = p;
+              } else {
+                 break;
+              }
+           }
+           if (p && (p = strchr(p, ',')))
+              *p = '\0';
+       }
+   }
+
+   if (defs->variant) {
+       if (!strchr(defs->variant, ',')) {
+           mdefs->variant[0] = defs->variant;
+       } else {
+           char *p;
+           int i;
+           mdefs->variant[1] = _XkbDupString(defs->variant);
+          if (mdefs->variant[1] == NULL)
+             return False;
+           squeeze_spaces(mdefs->variant[1]);
+           p = mdefs->variant[1];
+           for (i = 2; i <= XkbNumKbdGroups; i++) {
+              if ((p = strchr(p, ','))) {
+                 *p++ = '\0';
+                 mdefs->variant[i] = p;
+              } else {
+                 break;
+              }
+           }
+           if (p && (p = strchr(p, ',')))
+              *p = '\0';
+       }
+   }
+   return True;
+}
+
+static void
+FreeMultiDefs(XkbRF_MultiDefsPtr defs)
+{
+  if (defs->options) _XkbFree(defs->options);
+  if (defs->layout[1])  _XkbFree(defs->layout[1]);
+  if (defs->variant[1])  _XkbFree(defs->variant[1]);
+}
+
+static void
+Apply(char *src, char **dst)
+{
+    if (src) {
+        if (*src == '+' || *src == '!') {
+           *dst= _Concat(*dst, src);
+        } else {
+            if (*dst == NULL)
+               *dst= _XkbDupString(src);
+        }
+    }
+}
+
+static void
+XkbRF_ApplyRule(       XkbRF_RulePtr           rule,
+                       XkbComponentNamesPtr    names)
+{
+    rule->flags&= ~XkbRF_PendingMatch; /* clear the flag because it's applied */
+
+    Apply(rule->keycodes, &names->keycodes);
+    Apply(rule->symbols,  &names->symbols);
+    Apply(rule->types,    &names->types);
+    Apply(rule->compat,   &names->compat);
+    Apply(rule->geometry, &names->geometry);
+    Apply(rule->keymap,   &names->keymap);
+}
+
+static Bool
+CheckGroup(    XkbRF_RulesPtr          rules,
+               char *                  group_name,
+               char *                  name)
+{
+   int i;
+   char *p;
+   XkbRF_GroupPtr group;
+
+   for (i = 0, group = rules->groups; i < rules->num_groups; i++, group++) {
+       if (! strcmp(group->name, group_name)) {
+           break;
+       }
+   }
+   if (i == rules->num_groups)
+       return False;
+   for (i = 0, p = group->words; i < group->number; i++, p += strlen(p)+1) {
+       if (! strcmp(p, name)) {
+           return True;
+       }
+   }
+   return False;
+}
+
+static int
+XkbRF_CheckApplyRule(  XkbRF_RulePtr           rule,
+                       XkbRF_MultiDefsPtr      mdefs,
+                       XkbComponentNamesPtr    names,
+                       XkbRF_RulesPtr          rules)
+{
+    Bool pending = False;
+
+    if (rule->model != NULL) {
+        if(mdefs->model == NULL)
+            return 0;
+        if (strcmp(rule->model, "*") == 0) {
+            pending = True;
+        } else {
+            if (rule->model[0] == '$') {
+               if (!CheckGroup(rules, rule->model, mdefs->model))
+                  return 0;
+            } else {
+              if (strcmp(rule->model, mdefs->model) != 0)
+                 return 0;
+           }
+       }
+    }
+    if (rule->option != NULL) {
+       if (mdefs->options == NULL)
+           return 0;
+       if ((!MatchOneOf(rule->option,mdefs->options)))
+           return 0;
+    }
+
+    if (rule->layout != NULL) {
+       if(mdefs->layout[rule->layout_num] == NULL ||
+          *mdefs->layout[rule->layout_num] == '\0')
+           return 0;
+        if (strcmp(rule->layout, "*") == 0) {
+            pending = True;
+        } else {
+            if (rule->layout[0] == '$') {
+               if (!CheckGroup(rules, rule->layout,
+                               mdefs->layout[rule->layout_num]))
+                  return 0;
+           } else {
+              if (strcmp(rule->layout, mdefs->layout[rule->layout_num]) != 0)
+                  return 0;
+           }
+       }
+    }
+    if (rule->variant != NULL) {
+       if (mdefs->variant[rule->variant_num] == NULL ||
+           *mdefs->variant[rule->variant_num] == '\0')
+           return 0;
+        if (strcmp(rule->variant, "*") == 0) {
+            pending = True;
+        } else {
+            if (rule->variant[0] == '$') {
+               if (!CheckGroup(rules, rule->variant,
+                               mdefs->variant[rule->variant_num]))
+                  return 0;
+            } else {
+              if (strcmp(rule->variant,
+                          mdefs->variant[rule->variant_num]) != 0)
+                  return 0;
+           }
+       }
+    }
+    if (pending) {
+        rule->flags|= XkbRF_PendingMatch;
+       return rule->number;
+    }
+    /* exact match, apply it now */
+    XkbRF_ApplyRule(rule,names);
+    return rule->number;
+}
+
+static void
+XkbRF_ClearPartialMatches(XkbRF_RulesPtr rules)
+{
+register int   i;
+XkbRF_RulePtr  rule;
+
+    for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
+       rule->flags&= ~XkbRF_PendingMatch;
+    }
+}
+
+static void
+XkbRF_ApplyPartialMatches(XkbRF_RulesPtr rules,XkbComponentNamesPtr names)
+{
+int            i;
+XkbRF_RulePtr  rule;
+
+    for (rule = rules->rules, i = 0; i < rules->num_rules; i++, rule++) {
+       if ((rule->flags&XkbRF_PendingMatch)==0)
+           continue;
+       XkbRF_ApplyRule(rule,names);
+    }
+}
+
+static void
+XkbRF_CheckApplyRules( XkbRF_RulesPtr          rules,
+                       XkbRF_MultiDefsPtr      mdefs,
+                       XkbComponentNamesPtr    names,
+                       int                     flags)
+{
+int            i;
+XkbRF_RulePtr  rule;
+int            skip;
+
+    for (rule = rules->rules, i=0; i < rules->num_rules; rule++, i++) {
+       if ((rule->flags & flags) != flags)
+           continue;
+       skip = XkbRF_CheckApplyRule(rule, mdefs, names, rules);
+       if (skip && !(flags & XkbRF_Option)) {
+           for ( ;(i < rules->num_rules) && (rule->number == skip);
+                 rule++, i++);
+           rule--; i--;
+       }
+    }
+}
+
+/***====================================================================***/
+
+static char *
+XkbRF_SubstituteVars(char *name, XkbRF_MultiDefsPtr mdefs)
+{
+char   *str, *outstr, *orig, *var;
+int    len, ndx;
+
+    orig= name;
+    str= index(name,'%');
+    if (str==NULL)
+       return name;
+    len= strlen(name);
+    while (str!=NULL) {
+       char pfx= str[1];
+       int   extra_len= 0;
+       if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
+           extra_len= 1;
+           str++;
+       }
+       else if (pfx=='(') {
+           extra_len= 2;
+           str++;
+       }
+       var = str + 1;
+       str = get_index(var + 1, &ndx);
+       if (ndx == -1) {
+           str = index(str,'%');
+           continue;
+        }
+       if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx])
+           len+= strlen(mdefs->layout[ndx])+extra_len;
+       else if ((*var=='m')&&mdefs->model)
+           len+= strlen(mdefs->model)+extra_len;
+       else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx])
+           len+= strlen(mdefs->variant[ndx])+extra_len;
+       if ((pfx=='(')&&(*str==')')) {
+           str++;
+       }
+       str= index(&str[0],'%');
+    }
+    name= (char *)_XkbAlloc(len+1);
+    str= orig;
+    outstr= name;
+    while (*str!='\0') {
+       if (str[0]=='%') {
+           char pfx,sfx;
+           str++;
+           pfx= str[0];
+           sfx= '\0';
+           if ((pfx=='+')||(pfx=='|')||(pfx=='_')||(pfx=='-')) {
+               str++;
+           }
+           else if (pfx=='(') {
+               sfx= ')';
+               str++;
+           }
+           else pfx= '\0';
+
+           var = str;
+           str = get_index(var + 1, &ndx);
+           if (ndx == -1) {
+               continue;
+            }
+           if ((*var=='l') && mdefs->layout[ndx] && *mdefs->layout[ndx]) {
+               if (pfx) *outstr++= pfx;
+               strcpy(outstr,mdefs->layout[ndx]);
+               outstr+= strlen(mdefs->layout[ndx]);
+               if (sfx) *outstr++= sfx;
+           }
+           else if ((*var=='m')&&(mdefs->model)) {
+               if (pfx) *outstr++= pfx;
+               strcpy(outstr,mdefs->model);
+               outstr+= strlen(mdefs->model);
+               if (sfx) *outstr++= sfx;
+           }
+           else if ((*var=='v') && mdefs->variant[ndx] && *mdefs->variant[ndx]) {
+               if (pfx) *outstr++= pfx;
+               strcpy(outstr,mdefs->variant[ndx]);
+               outstr+= strlen(mdefs->variant[ndx]);
+               if (sfx) *outstr++= sfx;
+           }
+           if ((pfx=='(')&&(*str==')'))
+               str++;
+       }
+       else {
+           *outstr++= *str++;
+       }
+    }
+    *outstr++= '\0';
+    if (orig!=name)
+       _XkbFree(orig);
+    return name;
+}
+
+/***====================================================================***/
+
+Bool
+XkbRF_GetComponents(   XkbRF_RulesPtr          rules,
+                       XkbRF_VarDefsPtr        defs,
+                       XkbComponentNamesPtr    names)
+{
+    XkbRF_MultiDefsRec mdefs;
+
+    MakeMultiDefs(&mdefs, defs);
+
+    bzero((char *)names,sizeof(XkbComponentNamesRec));
+    XkbRF_ClearPartialMatches(rules);
+    XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Normal);
+    XkbRF_ApplyPartialMatches(rules, names);
+    XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Append);
+    XkbRF_ApplyPartialMatches(rules, names);
+    XkbRF_CheckApplyRules(rules, &mdefs, names, XkbRF_Option);
+    XkbRF_ApplyPartialMatches(rules, names);
+
+    if (names->keycodes)
+       names->keycodes= XkbRF_SubstituteVars(names->keycodes, &mdefs);
+    if (names->symbols)
+       names->symbols= XkbRF_SubstituteVars(names->symbols, &mdefs);
+    if (names->types)
+       names->types= XkbRF_SubstituteVars(names->types, &mdefs);
+    if (names->compat)
+       names->compat= XkbRF_SubstituteVars(names->compat, &mdefs);
+    if (names->geometry)
+       names->geometry= XkbRF_SubstituteVars(names->geometry, &mdefs);
+    if (names->keymap)
+       names->keymap= XkbRF_SubstituteVars(names->keymap, &mdefs);
+
+    FreeMultiDefs(&mdefs);
+    return (names->keycodes && names->symbols && names->types &&
+               names->compat && names->geometry ) || names->keymap;
+}
+
+XkbRF_RulePtr
+XkbRF_AddRule(XkbRF_RulesPtr   rules)
+{
+    if (rules->sz_rules<1) {
+       rules->sz_rules= 16;
+       rules->num_rules= 0;
+       rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec);
+    }
+    else if (rules->num_rules>=rules->sz_rules) {
+       rules->sz_rules*= 2;
+       rules->rules= _XkbTypedRealloc(rules->rules,rules->sz_rules,
+                                                       XkbRF_RuleRec);
+    }
+    if (!rules->rules) {
+       rules->sz_rules= rules->num_rules= 0;
+#ifdef DEBUG
+       fprintf(stderr,"Allocation failure in XkbRF_AddRule\n");
+#endif
+       return NULL;
+    }
+    bzero((char *)&rules->rules[rules->num_rules],sizeof(XkbRF_RuleRec));
+    return &rules->rules[rules->num_rules++];
+}
+
+XkbRF_GroupPtr
+XkbRF_AddGroup(XkbRF_RulesPtr  rules)
+{
+    if (rules->sz_groups<1) {
+       rules->sz_groups= 16;
+       rules->num_groups= 0;
+       rules->groups= _XkbTypedCalloc(rules->sz_groups,XkbRF_GroupRec);
+    }
+    else if (rules->num_groups >= rules->sz_groups) {
+       rules->sz_groups *= 2;
+       rules->groups= _XkbTypedRealloc(rules->groups,rules->sz_groups,
+                                                       XkbRF_GroupRec);
+    }
+    if (!rules->groups) {
+       rules->sz_groups= rules->num_groups= 0;
+       return NULL;
+    }
+
+    bzero((char *)&rules->groups[rules->num_groups],sizeof(XkbRF_GroupRec));
+    return &rules->groups[rules->num_groups++];
+}
+
+Bool
+XkbRF_LoadRules(FILE *file, XkbRF_RulesPtr rules)
+{
+InputLine      line;
+RemapSpec      remap;
+XkbRF_RuleRec  trule,*rule;
+XkbRF_GroupRec  tgroup,*group;
+
+    if (!(rules && file))
+       return False;
+    bzero((char *)&remap,sizeof(RemapSpec));
+    bzero((char *)&tgroup,sizeof(XkbRF_GroupRec));
+    InitInputLine(&line);
+    while (GetInputLine(file,&line,True)) {
+       if (CheckLine(&line,&remap,&trule,&tgroup)) {
+            if (tgroup.number) {
+               if ((group= XkbRF_AddGroup(rules))!=NULL) {
+                   *group= tgroup;
+                   bzero((char *)&tgroup,sizeof(XkbRF_GroupRec));
+               }
+           } else {
+               if ((rule= XkbRF_AddRule(rules))!=NULL) {
+                   *rule= trule;
+                   bzero((char *)&trule,sizeof(XkbRF_RuleRec));
+               }
+           }
+       }
+       line.num_line= 0;
+    }
+    FreeInputLine(&line);
+    return True;
+}
+
+Bool
+XkbRF_LoadRulesByName(char *base,char *locale,XkbRF_RulesPtr rules)
+{
+FILE *         file;
+char           buf[PATH_MAX];
+Bool           ok;
+
+    if ((!base)||(!rules))
+       return False;
+    if (locale) {
+       if (strlen(base)+strlen(locale)+2 > PATH_MAX)
+           return False;
+       sprintf(buf,"%s-%s", base, locale);
+    }
+    else {
+       if (strlen(base)+1 > PATH_MAX)
+           return False;
+       strcpy(buf,base);
+    }
+
+    file= fopen(buf, "r");
+    if ((!file)&&(locale)) { /* fallback if locale was specified */
+       strcpy(buf,base);
+       file= fopen(buf, "r");
+    }
+    if (!file)
+       return False;
+    ok= XkbRF_LoadRules(file,rules);
+    fclose(file);
+    return ok;
+}
+
+/***====================================================================***/
+
+#define HEAD_NONE      0
+#define HEAD_MODEL     1
+#define HEAD_LAYOUT    2
+#define HEAD_VARIANT   3
+#define HEAD_OPTION    4
+#define        HEAD_EXTRA      5
+
+XkbRF_VarDescPtr
+XkbRF_AddVarDesc(XkbRF_DescribeVarsPtr vars)
+{
+    if (vars->sz_desc<1) {
+       vars->sz_desc= 16;
+       vars->num_desc= 0;
+       vars->desc= _XkbTypedCalloc(vars->sz_desc,XkbRF_VarDescRec);
+    }
+    else if (vars->num_desc>=vars->sz_desc) {
+       vars->sz_desc*= 2;
+       vars->desc= _XkbTypedRealloc(vars->desc,vars->sz_desc,XkbRF_VarDescRec);
+    }
+    if (!vars->desc) {
+       vars->sz_desc= vars->num_desc= 0;
+       PR_DEBUG("Allocation failure in XkbRF_AddVarDesc\n");
+       return NULL;
+    }
+    vars->desc[vars->num_desc].name= NULL;
+    vars->desc[vars->num_desc].desc= NULL;
+    return &vars->desc[vars->num_desc++];
+}
+
+XkbRF_VarDescPtr
+XkbRF_AddVarDescCopy(XkbRF_DescribeVarsPtr vars,XkbRF_VarDescPtr from)
+{
+XkbRF_VarDescPtr       nd;
+
+    if ((nd=XkbRF_AddVarDesc(vars))!=NULL) {
+       nd->name= _XkbDupString(from->name);
+       nd->desc= _XkbDupString(from->desc);
+    }
+    return nd;
+}
+
+XkbRF_DescribeVarsPtr
+XkbRF_AddVarToDescribe(XkbRF_RulesPtr rules,char *name)
+{
+    if (rules->sz_extra<1) {
+       rules->num_extra= 0;
+       rules->sz_extra= 1;
+       rules->extra_names= _XkbTypedCalloc(rules->sz_extra,char *);
+       rules->extra= _XkbTypedCalloc(rules->sz_extra, XkbRF_DescribeVarsRec);
+    }
+    else if (rules->num_extra>=rules->sz_extra) {
+       rules->sz_extra*= 2;
+       rules->extra_names= _XkbTypedRealloc(rules->extra_names,rules->sz_extra,
+                                                               char *);
+       rules->extra=_XkbTypedRealloc(rules->extra, rules->sz_extra,
+                                                       XkbRF_DescribeVarsRec);
+    }
+    if ((!rules->extra_names)||(!rules->extra)) {
+       PR_DEBUG("allocation error in extra parts\n");
+       rules->sz_extra= rules->num_extra= 0;
+       rules->extra_names= NULL;
+       rules->extra= NULL;
+       return NULL;
+    }
+    rules->extra_names[rules->num_extra]= _XkbDupString(name);
+    bzero(&rules->extra[rules->num_extra],sizeof(XkbRF_DescribeVarsRec));
+    return &rules->extra[rules->num_extra++];
+}
+
+Bool
+XkbRF_LoadDescriptions(FILE *file,XkbRF_RulesPtr rules)
+{
+InputLine              line;
+XkbRF_VarDescRec       tmp;
+char                   *tok;
+int                    len,headingtype,extra_ndx = 0;
+
+    bzero((char *)&tmp, sizeof(XkbRF_VarDescRec));
+    headingtype = HEAD_NONE;
+    InitInputLine(&line);
+    for ( ; GetInputLine(file,&line,False); line.num_line= 0) {
+       if (line.line[0]=='!') {
+           tok = strtok(&(line.line[1]), " \t");
+           if (strcmp(tok,"model") == 0)
+               headingtype = HEAD_MODEL;
+           else if (_XkbStrCaseCmp(tok,"layout") == 0)
+               headingtype = HEAD_LAYOUT;
+           else if (_XkbStrCaseCmp(tok,"variant") == 0)
+               headingtype = HEAD_VARIANT;
+           else if (_XkbStrCaseCmp(tok,"option") == 0)
+               headingtype = HEAD_OPTION;
+           else {
+               int i;
+               headingtype = HEAD_EXTRA;
+               extra_ndx= -1;
+               for (i=0;(i<rules->num_extra)&&(extra_ndx<0);i++) {
+                   if (_XkbStrCaseCmp(tok,rules->extra_names[i]))
+                       extra_ndx= i;
+               }
+               if (extra_ndx<0) {
+                   XkbRF_DescribeVarsPtr       var;
+                   PR_DEBUG1("Extra heading \"%s\" encountered\n",tok);
+                   var= XkbRF_AddVarToDescribe(rules,tok);
+                   if (var)
+                        extra_ndx= var-rules->extra;
+                   else headingtype= HEAD_NONE;
+               }
+           }
+           continue;
+       }
+
+       if (headingtype == HEAD_NONE) {
+           PR_DEBUG("Must have a heading before first line of data\n");
+           PR_DEBUG("Illegal line of data ignored\n");
+           continue;
+       }
+
+       len = strlen(line.line);
+       if ((tmp.name= strtok(line.line, " \t")) == NULL) {
+           PR_DEBUG("Huh? No token on line\n");
+           PR_DEBUG("Illegal line of data ignored\n");
+           continue;
+       }
+       if (strlen(tmp.name) == len) {
+           PR_DEBUG("No description found\n");
+           PR_DEBUG("Illegal line of data ignored\n");
+           continue;
+       }
+
+       tok = line.line + strlen(tmp.name) + 1;
+       while ((*tok!='\n')&&isspace(*tok))
+               tok++;
+       if (*tok == '\0') {
+           PR_DEBUG("No description found\n");
+           PR_DEBUG("Illegal line of data ignored\n");
+           continue;
+       }
+       tmp.desc= tok;
+       switch (headingtype) {
+           case HEAD_MODEL:
+               XkbRF_AddVarDescCopy(&rules->models,&tmp);
+               break;
+           case HEAD_LAYOUT:
+               XkbRF_AddVarDescCopy(&rules->layouts,&tmp);
+               break;
+           case HEAD_VARIANT:
+               XkbRF_AddVarDescCopy(&rules->variants,&tmp);
+               break;
+           case HEAD_OPTION:
+               XkbRF_AddVarDescCopy(&rules->options,&tmp);
+               break;
+           case HEAD_EXTRA:
+               XkbRF_AddVarDescCopy(&rules->extra[extra_ndx],&tmp);
+               break;
+       }
+    }
+    FreeInputLine(&line);
+    if ((rules->models.num_desc==0) && (rules->layouts.num_desc==0) &&
+       (rules->variants.num_desc==0) && (rules->options.num_desc==0) &&
+       (rules->num_extra==0)) {
+       return False;
+    }
+    return True;
+}
+
+Bool
+XkbRF_LoadDescriptionsByName(char *base,char *locale,XkbRF_RulesPtr rules)
+{
+FILE *         file;
+char           buf[PATH_MAX];
+Bool           ok;
+
+    if ((!base)||(!rules))
+       return False;
+    if (locale) {
+       if (strlen(base)+strlen(locale)+6 > PATH_MAX)
+           return False;
+       sprintf(buf,"%s-%s.lst", base, locale);
+    }
+    else {
+       if (strlen(base)+5 > PATH_MAX)
+           return False;
+       sprintf(buf,"%s.lst", base);
+    }
+
+    file= fopen(buf, "r");
+    if ((!file)&&(locale)) { /* fallback if locale was specified */
+       sprintf(buf,"%s.lst", base);
+
+       file= fopen(buf, "r");
+    }
+    if (!file)
+       return False;
+    ok= XkbRF_LoadDescriptions(file,rules);
+    fclose(file);
+    return ok;
+}
+
+/***====================================================================***/
+
+XkbRF_RulesPtr
+XkbRF_Load(char *base,char *locale,Bool wantDesc,Bool wantRules)
+{
+XkbRF_RulesPtr rules;
+
+    if ((!base)||((!wantDesc)&&(!wantRules)))
+       return NULL;
+    if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL)
+       return NULL;
+    if (wantDesc&&(!XkbRF_LoadDescriptionsByName(base,locale,rules))) {
+       XkbRF_Free(rules,True);
+       return NULL;
+    }
+    if (wantRules&&(!XkbRF_LoadRulesByName(base,locale,rules))) {
+       XkbRF_Free(rules,True);
+       return NULL;
+    }
+    return rules;
+}
+
+XkbRF_RulesPtr
+XkbRF_Create(int szRules,int szExtra)
+{
+XkbRF_RulesPtr rules;
+
+    if ((rules=_XkbTypedCalloc(1,XkbRF_RulesRec))==NULL)
+       return NULL;
+    if (szRules>0) {
+       rules->sz_rules= szRules;
+       rules->rules= _XkbTypedCalloc(rules->sz_rules,XkbRF_RuleRec);
+       if (!rules->rules) {
+           _XkbFree(rules);
+           return NULL;
+       }
+    }
+    if (szExtra>0) {
+       rules->sz_extra= szExtra;
+       rules->extra= _XkbTypedCalloc(rules->sz_extra,XkbRF_DescribeVarsRec);
+       if (!rules->extra) {
+           if (rules->rules)
+               _XkbFree(rules->rules);
+           _XkbFree(rules);
+           return NULL;
+       }
+    }
+    return rules;
+}
+
+/***====================================================================***/
+
+static void
+XkbRF_ClearVarDescriptions(XkbRF_DescribeVarsPtr var)
+{
+register int i;
+
+    for (i=0;i<var->num_desc;i++) {
+       if (var->desc[i].name)
+           _XkbFree(var->desc[i].name);
+       if (var->desc[i].desc)
+           _XkbFree(var->desc[i].desc);
+       var->desc[i].name= var->desc[i].desc= NULL;
+    }
+    if (var->desc)
+       _XkbFree(var->desc);
+    var->desc= NULL;
+    return;
+}
+
+void
+XkbRF_Free(XkbRF_RulesPtr rules,Bool freeRules)
+{
+int            i;
+XkbRF_RulePtr  rule;
+XkbRF_GroupPtr group;
+
+    if (!rules)
+       return;
+    XkbRF_ClearVarDescriptions(&rules->models);
+    XkbRF_ClearVarDescriptions(&rules->layouts);
+    XkbRF_ClearVarDescriptions(&rules->variants);
+    XkbRF_ClearVarDescriptions(&rules->options);
+    if (rules->extra) {
+       for (i = 0; i < rules->num_extra; i++) {
+           XkbRF_ClearVarDescriptions(&rules->extra[i]);
+       }
+       _XkbFree(rules->extra);
+       rules->num_extra= rules->sz_extra= 0;
+       rules->extra= NULL;
+    }
+    if (rules->rules) {
+       for (i=0,rule=rules->rules;i<rules->num_rules;i++,rule++) {
+           if (rule->model)    _XkbFree(rule->model);
+           if (rule->layout)   _XkbFree(rule->layout);
+           if (rule->variant)  _XkbFree(rule->variant);
+           if (rule->option)   _XkbFree(rule->option);
+           if (rule->keycodes) _XkbFree(rule->keycodes);
+           if (rule->symbols)  _XkbFree(rule->symbols);
+           if (rule->types)    _XkbFree(rule->types);
+           if (rule->compat)   _XkbFree(rule->compat);
+           if (rule->geometry) _XkbFree(rule->geometry);
+           if (rule->keymap)   _XkbFree(rule->keymap);
+           bzero((char *)rule,sizeof(XkbRF_RuleRec));
+       }
+       _XkbFree(rules->rules);
+       rules->num_rules= rules->sz_rules= 0;
+       rules->rules= NULL;
+    }
+
+    if (rules->groups) {
+       for (i=0, group=rules->groups;i<rules->num_groups;i++,group++) {
+           if (group->name)    _XkbFree(group->name);
+           if (group->words)   _XkbFree(group->words);
+       }
+       _XkbFree(rules->groups);
+       rules->num_groups= 0;
+       rules->groups= NULL;
+    }
+    if (freeRules)
+       _XkbFree(rules);
+    return;
+}
+
+#ifndef XKB_IN_SERVER
+
+Bool
+XkbRF_GetNamesProp(Display *dpy,char **rf_rtrn,XkbRF_VarDefsPtr vd_rtrn)
+{
+Atom           rules_atom,actual_type;
+int            fmt;
+unsigned long  nitems,bytes_after;
+unsigned char   *data;
+char            *out, *end;
+Status         rtrn;
+
+    rules_atom= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,True);
+    if (rules_atom==None)      /* property cannot exist */
+       return False;
+    rtrn= XGetWindowProperty(dpy,DefaultRootWindow(dpy),rules_atom,
+                                0L,_XKB_RF_NAMES_PROP_MAXLEN,False,
+                                XA_STRING,&actual_type,
+                                &fmt,&nitems,&bytes_after,
+                                (unsigned char **)&data);
+    if (rtrn!=Success)
+       return False;
+    if (rf_rtrn)
+       *rf_rtrn= NULL;
+    (void)bzero((char *)vd_rtrn,sizeof(XkbRF_VarDefsRec));
+    if ((bytes_after>0)||(actual_type!=XA_STRING)||(fmt!=8)) {
+       if (data) XFree(data);
+       return (fmt==0?True:False);
+    }
+
+    out=(char*)data;
+    end=out+nitems;
+    if (out && (*out) && rf_rtrn)
+        *rf_rtrn= _XkbDupString(out);
+    out+=strlen(out)+1;
+
+    if (out<end) {
+       if (*out)
+           vd_rtrn->model= _XkbDupString(out);
+       out+=strlen(out)+1;
+    }
+
+    if (out<end) {
+       if (*out)
+           vd_rtrn->layout= _XkbDupString(out);
+       out+=strlen(out)+1;
+    }
+
+    if (out<end) {
+       if (*out)
+           vd_rtrn->variant= _XkbDupString(out);
+       out+=strlen(out)+1;
+    }
+
+    if (out<end) {
+       if (*out)
+           vd_rtrn->options= _XkbDupString(out);
+       out+=strlen(out)+1;
+    }
+
+    XFree(data);
+    return True;
+}
+
+Bool
+XkbRF_SetNamesProp(Display *dpy,char *rules_file,XkbRF_VarDefsPtr var_defs)
+{
+int    len,out;
+Atom   name;
+char * pval;
+
+    len= (rules_file?strlen(rules_file):0);
+    len+= (var_defs->model?strlen(var_defs->model):0);
+    len+= (var_defs->layout?strlen(var_defs->layout):0);
+    len+= (var_defs->variant?strlen(var_defs->variant):0);
+    len+= (var_defs->options?strlen(var_defs->options):0);
+    if (len<1)
+        return True;
+
+    len+= 5; /* trailing NULs */
+
+    name= XInternAtom(dpy,_XKB_RF_NAMES_PROP_ATOM,False);
+    if (name==None)  { /* should never happen */
+       _XkbLibError(_XkbErrXReqFailure,"XkbRF_SetNamesProp",X_InternAtom);
+        return False;
+    }
+    pval= (char *)_XkbAlloc(len);
+    if (!pval) {
+       _XkbLibError(_XkbErrBadAlloc,"XkbRF_SetNamesProp",len);
+        return False;
+    }
+    out= 0;
+    if (rules_file) {
+        strcpy(&pval[out],rules_file);
+        out+= strlen(rules_file);
+    }
+    pval[out++]= '\0';
+    if (var_defs->model) {
+        strcpy(&pval[out],var_defs->model);
+        out+= strlen(var_defs->model);
+    }
+    pval[out++]= '\0';
+    if (var_defs->layout) {
+        strcpy(&pval[out],var_defs->layout);
+        out+= strlen(var_defs->layout);
+    }
+    pval[out++]= '\0';
+    if (var_defs->variant) {
+        strcpy(&pval[out],var_defs->variant);
+        out+= strlen(var_defs->variant);
+    }
+    pval[out++]= '\0';
+    if (var_defs->options) {
+        strcpy(&pval[out],var_defs->options);
+        out+= strlen(var_defs->options);
+    }
+    pval[out++]= '\0';
+    if (out!=len) {
+       _XkbLibError(_XkbErrBadLength,"XkbRF_SetNamesProp",out);
+       _XkbFree(pval);
+       return False;
+    }
+
+    XChangeProperty(dpy,DefaultRootWindow(dpy),name,XA_STRING,8,PropModeReplace,
+                                                (unsigned char *)pval,len);
+    _XkbFree(pval);
+    return True;
+}
+
+#endif
diff --git a/src/srvmisc.c b/src/srvmisc.c
new file mode 100644 (file)
index 0000000..478d373
--- /dev/null
@@ -0,0 +1,214 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+Bool
+XkbWriteToServer(XkbFileInfo *result)
+{
+XkbDescPtr             xkb;
+Display *              dpy;
+
+    if ((result==NULL)||(result->xkb==NULL)||(result->xkb->dpy==NULL))
+       return False;
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if (!XkbSetMap(dpy,XkbAllMapComponentsMask,xkb))
+       return False;
+    if (!XkbSetIndicatorMap(dpy,~0,xkb))
+       return False;
+#ifdef NOTYET
+    if (!XkbSetControls(dpy,XkbAllControlsMask,xkb))
+       return False;
+#endif
+    if (!XkbSetCompatMap(dpy,XkbAllCompatMask,xkb,True))
+       return False;
+    if (!XkbSetNames(dpy,XkbAllNamesMask,0,xkb->map->num_types,xkb))
+       return False;
+    if (xkb->geom) {
+       if (XkbSetGeometry(dpy,xkb->device_spec,xkb->geom)!=Success)
+           return False;
+    }
+    return True;
+#ifdef NOTYET
+    switch (result->type) {
+       case XkmSemanticsFile:
+           func= WriteCHdrSemantics;
+           break;
+       case XkmLayoutFile:
+           func= WriteCHdrLayout;
+           break;
+       case XkmKeymapFile:
+           func= WriteCHdrKeymap;
+           break;
+       default:
+          _XkbLibError(_XkbErrIllegalContents,"XkbWriteToServer",result->type);
+          break;
+    }
+    return ok;
+#endif
+}
+
+unsigned
+XkbReadFromServer(Display *dpy,unsigned need,unsigned want,XkbFileInfo *result)
+{
+unsigned which= need|want;
+unsigned tmp = 0;
+
+    if ((result==NULL)||(dpy==NULL))
+       return which;
+
+    if (which&XkmSymbolsMask)          tmp= XkbAllMapComponentsMask;
+    else if (which&XkmTypesMask)       tmp= XkbKeyTypesMask;
+    if (result->xkb==NULL) {
+       result->xkb= XkbGetMap(dpy,tmp,XkbUseCoreKbd);
+       if (!result->xkb)
+            return which;
+       else which&= ~(XkmSymbolsMask|XkmTypesMask|XkmVirtualModsMask);
+    }
+    else if ((tmp)&&(XkbGetUpdatedMap(dpy,tmp,result->xkb)==Success))
+       which&= ~(XkmSymbolsMask|XkmTypesMask|XkmVirtualModsMask);
+
+    if (which&XkmIndicatorsMask) {
+       if (XkbGetIndicatorMap(dpy,XkbAllIndicatorsMask,result->xkb)==Success)
+           which&= ~XkmIndicatorsMask;
+    }
+
+    if (which&XkmCompatMapMask) {
+       if (XkbGetCompatMap(dpy,XkbAllCompatMask,result->xkb)==Success)
+           which&= ~XkmCompatMapMask;
+    }
+    if (which&XkmGeometryMask) {
+       if (XkbGetGeometry(dpy,result->xkb)==Success)
+           which&= ~XkmGeometryMask;
+    }
+    XkbGetNames(dpy,XkbAllNamesMask,result->xkb);
+    return which;
+}
+
+Status
+XkbChangeKbdDisplay(Display *newDpy,XkbFileInfo *result)
+{
+register int   i;
+XkbDescPtr     xkb;
+Display *      oldDpy;
+Atom *         atm;
+
+    if ((result->xkb==NULL)||(result->xkb->dpy==newDpy))
+       return Success;
+    xkb= result->xkb;
+    oldDpy= xkb->dpy;
+    if (xkb->names) {
+       XkbNamesPtr     names= xkb->names;
+       names->keycodes= XkbChangeAtomDisplay(oldDpy,newDpy,names->keycodes);
+       names->geometry= XkbChangeAtomDisplay(oldDpy,newDpy,names->geometry);
+       names->symbols= XkbChangeAtomDisplay(oldDpy,newDpy,names->symbols);
+       names->types= XkbChangeAtomDisplay(oldDpy,newDpy,names->types);
+       names->compat= XkbChangeAtomDisplay(oldDpy,newDpy,names->compat);
+       names->phys_symbols= XkbChangeAtomDisplay(oldDpy,newDpy,
+                                                        names->phys_symbols);
+       for (i=0,atm=names->vmods;i<XkbNumVirtualMods;i++,atm++) {
+           *atm= XkbChangeAtomDisplay(oldDpy,newDpy,*atm);
+       }
+       for (i=0,atm=names->indicators;i<XkbNumIndicators;i++,atm++) {
+           *atm= XkbChangeAtomDisplay(oldDpy,newDpy,*atm);
+       }
+       for (i=0,atm=names->groups;i<XkbNumKbdGroups;i++,atm++) {
+           *atm= XkbChangeAtomDisplay(oldDpy,newDpy,*atm);
+       }
+       for (i=0,atm=names->radio_groups;i<names->num_rg;i++,atm++) {
+           *atm= XkbChangeAtomDisplay(oldDpy,newDpy,*atm);
+       }
+    }
+    if (xkb->map) {
+       register int    t;
+       XkbKeyTypePtr   type;
+       for (t=0,type=xkb->map->types;t<xkb->map->num_types;t++,type++) {
+           type->name= XkbChangeAtomDisplay(oldDpy,newDpy,type->name);
+           if (type->level_names!=NULL) {
+               for (i=0,atm=type->level_names;i<type->num_levels;i++,atm++) {
+                   *atm= XkbChangeAtomDisplay(oldDpy,newDpy,*atm);
+               }
+           }
+       }
+    }
+    if (xkb->geom) {
+       XkbGeometryPtr  geom= xkb->geom;
+       geom->name= XkbChangeAtomDisplay(oldDpy,newDpy,geom->name);
+       if (geom->shapes) {
+           register int s;
+           XkbShapePtr shape;
+           for (s=0,shape=geom->shapes;s<geom->num_shapes;s++,shape++) {
+               shape->name= XkbChangeAtomDisplay(oldDpy,newDpy,shape->name);
+           }
+       }
+       if (geom->sections) {
+           register int s;
+           XkbSectionPtr       section;
+           for (s=0,section=geom->sections;s<geom->num_sections;s++,section++){
+               section->name=XkbChangeAtomDisplay(oldDpy,newDpy,section->name);
+               if (section->doodads) {
+                   register int d;
+                   XkbDoodadPtr doodad;
+                   for (d=0,doodad=section->doodads;d<section->num_doodads;
+                                                               d++,doodad++) {
+                       doodad->any.name= XkbChangeAtomDisplay(oldDpy,newDpy,
+                                                        doodad->any.name);
+                   }
+               }
+               if (section->overlays) {
+                   register int o;
+                   register XkbOverlayPtr ol;
+                   for (o=0,ol=section->overlays;o<section->num_overlays;
+                                                               o++,ol++) {
+                       ol->name= XkbChangeAtomDisplay(oldDpy,newDpy,ol->name);
+                   }
+               }
+           }
+       }
+       if (geom->doodads) {
+           register int d;
+           XkbDoodadPtr doodad;
+           for (d=0,doodad=geom->doodads;d<geom->num_doodads;d++,doodad++) {
+               doodad->any.name= XkbChangeAtomDisplay(oldDpy,newDpy,
+                                                        doodad->any.name);
+           }
+       }
+    }
+    xkb->dpy= newDpy;
+    return Success;
+}
diff --git a/src/xkbatom.c b/src/xkbatom.c
new file mode 100644 (file)
index 0000000..b60e90e
--- /dev/null
@@ -0,0 +1,243 @@
+/***********************************************************
+
+Copyright 1987, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/************************************************************
+ Copyright 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+/***====================================================================***/
+
+#define InitialTableSize 100
+
+typedef struct _Node {
+    struct _Node   *left,   *right;
+    Atom a;
+    unsigned int fingerPrint;
+    char   *string;
+} NodeRec, *NodePtr;
+
+#define BAD_RESOURCE 0xe0000000
+
+static Atom lastAtom = None;
+static NodePtr atomRoot = (NodePtr)NULL;
+static unsigned long tableLength;
+static NodePtr *nodeTable;
+
+static Atom
+_XkbMakeAtom(char *string,unsigned len,Bool makeit)
+{
+    register    NodePtr * np;
+    unsigned i;
+    int     comp;
+    register unsigned int   fp = 0;
+
+    np = &atomRoot;
+    for (i = 0; i < (len+1)/2; i++)
+    {
+       fp = fp * 27 + string[i];
+       fp = fp * 27 + string[len - 1 - i];
+    }
+    while (*np != (NodePtr) NULL)
+    {
+       if (fp < (*np)->fingerPrint)
+           np = &((*np)->left);
+       else if (fp > (*np)->fingerPrint)
+           np = &((*np)->right);
+       else
+       {                              /* now start testing the strings */
+           comp = strncmp(string, (*np)->string, (int)len);
+           if ((comp < 0) || ((comp == 0) && (len < strlen((*np)->string))))
+               np = &((*np)->left);
+           else if (comp > 0)
+               np = &((*np)->right);
+           else
+               return(*np)->a;
+           }
+    }
+    if (makeit)
+    {
+       register NodePtr nd;
+
+       nd = (NodePtr) _XkbAlloc(sizeof(NodeRec));
+       if (!nd)
+           return BAD_RESOURCE;
+       nd->string = (char *) _XkbAlloc(len + 1);
+       if (!nd->string) {
+           _XkbFree(nd);
+           return BAD_RESOURCE;
+       }
+       strncpy(nd->string, string, (int)len);
+       nd->string[len] = 0;
+       if ((lastAtom + 1) >= tableLength) {
+           NodePtr *table;
+
+           table = (NodePtr *) _XkbRealloc(nodeTable,
+                                        tableLength * (2 * sizeof(NodePtr)));
+           if (!table) {
+               if (nd->string != string)
+                   _XkbFree(nd->string);
+               _XkbFree(nd);
+               return BAD_RESOURCE;
+           }
+           tableLength <<= 1;
+           nodeTable = table;
+       }
+       *np = nd;
+       nd->left = nd->right = (NodePtr) NULL;
+       nd->fingerPrint = fp;
+       nd->a = (++lastAtom);
+       *(nodeTable+lastAtom) = nd;
+       return nd->a;
+    }
+    else
+       return None;
+}
+
+static char *
+_XkbNameForAtom(Atom atom)
+{
+    NodePtr node;
+    if (atom > lastAtom) return NULL;
+    if ((node = nodeTable[atom]) == (NodePtr)NULL) return NULL;
+    return strdup(node->string);
+}
+
+static void
+_XkbInitAtoms(void)
+{
+    tableLength = InitialTableSize;
+    nodeTable = (NodePtr *)_XkbAlloc(InitialTableSize*sizeof(NodePtr));
+    nodeTable[None] = (NodePtr)NULL;
+}
+
+/***====================================================================***/
+
+char *
+XkbAtomGetString(Display *dpy,Atom atm)
+{
+    if (atm==None)
+       return NULL;
+    if (dpy==NULL)
+       return _XkbNameForAtom(atm);
+    return XGetAtomName(dpy,atm);
+}
+
+/***====================================================================***/
+
+Atom
+XkbInternAtom(Display *dpy,char *name,Bool onlyIfExists)
+{
+    if (name==NULL)
+       return None;
+    if (dpy==NULL) {
+       return _XkbMakeAtom(name, strlen(name), (!onlyIfExists));
+    }
+    return XInternAtom(dpy,name,onlyIfExists);
+}
+
+/***====================================================================***/
+
+Atom
+XkbChangeAtomDisplay(Display *oldDpy,Display *newDpy,Atom atm)
+{
+char *tmp;
+
+    if (atm!=None) {
+       tmp= XkbAtomGetString(oldDpy,atm);
+       if (tmp!=NULL)
+           return XkbInternAtom(newDpy,tmp,False);
+    }
+    return None;
+}
+
+/***====================================================================***/
+
+void
+XkbInitAtoms(Display *dpy)
+{
+static int been_here= 0;
+    if ((dpy==NULL)&&(!been_here)) {
+       _XkbInitAtoms();
+       been_here= 1;
+    }
+    return;
+}
diff --git a/src/xkbbells.c b/src/xkbbells.c
new file mode 100644 (file)
index 0000000..10b2725
--- /dev/null
@@ -0,0 +1,102 @@
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include "XKBbells.h"
+
+static const char *_xkbStdBellNames[XkbBI_NumBells] = {
+       "Info",
+       "Warning",
+       "MinorError",
+       "MajorError",
+       "BadValue",
+       "InvalidLocation",
+       "Question",
+       "Start",
+       "End",
+       "Success",
+       "Failure",
+       "Wait",
+       "Proceed",
+       "Ignore",
+       "Iconify",
+       "Deconify",
+       "Open",
+       "Close",
+       "TerminalBell",
+       "MarginBell",
+       "CursorStuck",
+       "NewMail",
+       "LaunchApp",
+       "AppDeath",
+       "ImAlive",
+       "ClockChimeHour",
+       "ClockChimeHalf",
+       "ClockChimeQuarter",
+       "RepeatingLastBell",
+       "ComposeFail",
+       "AX_FeatureOn",
+       "AX_FeatureOff",
+       "AX_FeatureChange",
+       "AX_IndicatorOn",
+       "AX_IndicatorOff",
+       "AX_IndicatorChange",
+       "AX_SlowKeysWarning",
+       "AX_SlowKeyPress",
+       "AX_SlowKeyAccept",
+       "AX_SlowKeyReject",
+       "AX_SlowKeyRelease",
+       "AX_BounceKeyReject",
+       "AX_StickyLatch",
+       "AX_StickyLock",
+       "AX_StickyUnlock"
+};
+
+static Atom _xkbStdBellAtoms[XkbBI_NumBells];
+
+Bool
+XkbStdBell(Display *dpy,Window win,int percent,int bellDef)
+{
+    if ((bellDef<0)||(bellDef>=XkbBI_NumBells))
+       bellDef= XkbBI_Info;
+    if (_xkbStdBellAtoms[bellDef]==None)
+       _xkbStdBellAtoms[bellDef]= XInternAtom(dpy,_xkbStdBellNames[bellDef],0);
+    return XkbBell(dpy,win,percent,_xkbStdBellAtoms[bellDef]);
+}
+
+Bool
+XkbStdBellEvent(Display *dpy,Window win,int percent,int bellDef)
+{
+    if ((bellDef<0)||(bellDef>=XkbBI_NumBells))
+       bellDef= XkbBI_Info;
+    if (_xkbStdBellAtoms[bellDef]==None)
+       _xkbStdBellAtoms[bellDef]= XInternAtom(dpy,_xkbStdBellNames[bellDef],0);
+    return XkbBellEvent(dpy,win,percent,_xkbStdBellAtoms[bellDef]);
+}
diff --git a/src/xkbconfig.c b/src/xkbconfig.c
new file mode 100644 (file)
index 0000000..b60017f
--- /dev/null
@@ -0,0 +1,1352 @@
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xfuncs.h>
+
+#include <X11/Xfuncs.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
+#include "XKBfileInt.h"
+
+#else
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#define        XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+#endif
+
+#include <X11/extensions/XKBconfig.h>
+
+/***====================================================================***/
+
+#define        XKBCF_MAX_STR_LEN       100
+static char _XkbCF_rtrn[XKBCF_MAX_STR_LEN+1];
+
+static int
+ScanIdent(FILE *file,int ch,XkbCFScanResultPtr val_rtrn)
+{
+register int   i;
+char *         str;
+
+    val_rtrn->str= str= _XkbCF_rtrn;
+    for (i=0;(isalpha(ch)||isdigit(ch)||(ch=='_'));ch=getc(file)) {
+       if (i<XKBCF_MAX_STR_LEN)
+           str[i++]= ch;
+    }
+    if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
+       ungetc(ch,file);
+    str[i]= '\0';
+    return XkbCF_Ident;
+}
+
+static int
+ScanString(FILE *file,int quote,XkbCFScanResultPtr val_rtrn)
+{
+int    ch,nInBuf;
+
+    nInBuf = 0;
+    while ( ((ch=getc(file))!=EOF) && (ch!='\n') && (ch!=quote) ) {
+       if ( ch == '\\' ) {
+           if ((ch = getc(file))!=EOF) {
+               if ( ch=='n' )          ch = '\n';
+               else if ( ch == 't' )   ch = '\t';
+               else if ( ch == 'v' )   ch = '\v';
+               else if ( ch == 'b' )   ch = '\b';
+               else if ( ch == 'r' )   ch = '\r';
+               else if ( ch == 'f' )   ch = '\f';
+               else if ( ch == 'e' )   ch = '\033';
+               else if ( ch == '0' ) {
+                   int tmp,stop;
+                   ch = stop = 0;
+                   if (((tmp=getc(file))!=EOF) && (isdigit(tmp)) &&
+                                               (tmp!='8') && (tmp!='9')) {
+                       ch= (ch*8)+(tmp-'0');
+                   }
+                   else {
+                       stop= 1;
+                       ungetc(tmp,file);
+                   }
+                   if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) &&
+                                               (tmp!='8') && (tmp!='9')) {
+                       ch= (ch*8)+(tmp-'0');
+                   }
+                   else {
+                       stop= 1;
+                       ungetc(tmp,file);
+                   }
+                   if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) &&
+                                               (tmp!='8') && (tmp!='9')) {
+                       ch= (ch*8)+(tmp-'0');
+                   }
+                   else {
+                       stop= 1;
+                       ungetc(tmp,file);
+                   }
+               }
+           }
+           else return XkbCF_EOF;
+       }
+
+       if ( nInBuf < XKBCF_MAX_STR_LEN-1 )
+           _XkbCF_rtrn[nInBuf++] = ch;
+    }
+    if ( ch == quote ) {
+       _XkbCF_rtrn[nInBuf++] = '\0';
+       val_rtrn->str= _XkbCF_rtrn;
+       return XkbCF_String;
+    }
+    return XkbCF_UnterminatedString;
+}
+
+static int
+ScanInteger(FILE *file,int ch,XkbCFScanResultPtr val_rtrn)
+{
+int    i;
+
+    if (isdigit(ch))
+       ungetc(ch,file);
+    if (fscanf(file,"%i",&i)==1) {
+       val_rtrn->ival= i;
+       return XkbCF_Integer;
+    }
+    return XkbCF_Unknown;
+}
+
+int
+XkbCFScan(FILE *file,XkbCFScanResultPtr val_rtrn,XkbConfigRtrnPtr rtrn)
+{
+int    ch;
+
+    do {
+       ch= getc(file);
+    } while ((ch=='\t')||(ch==' '));
+    if (isalpha(ch))
+        return ScanIdent(file,ch,val_rtrn);
+    else if (isdigit(ch))
+        return ScanInteger(file,ch,val_rtrn);
+    else if (ch=='"')
+        return ScanString(file,ch,val_rtrn);
+    else if (ch=='\n') {
+       rtrn->line++;
+       return XkbCF_EOL;
+    }
+    else if (ch==';')
+       return XkbCF_Semi;
+    else if (ch=='=')
+       return XkbCF_Equals;
+    else if (ch=='+') {
+       ch= getc(file);
+       if (ch=='=')
+           return XkbCF_PlusEquals;
+       if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
+           ungetc(ch,file);
+       return XkbCF_Plus;
+    }
+    else if (ch=='-') {
+       ch= getc(file);
+       if (ch=='=')
+           return XkbCF_MinusEquals;
+       if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t'))
+           ungetc(ch,file);
+       return XkbCF_Minus;
+    }
+    else if (ch==EOF)
+       return XkbCF_EOF;
+    else if ((ch=='#')||((ch=='/')&&(getc(file)=='/'))) {
+       while ((ch!='\n')&&(ch!=EOF))
+           ch= getc(file);
+       rtrn->line++;
+       return XkbCF_EOL;
+    }
+    return XkbCF_Unknown;
+}
+
+/***====================================================================***/
+
+#define        _XkbCF_Illegal                  0
+#define        _XkbCF_Keymap                   1
+#define        _XkbCF_Keycodes                 2
+#define        _XkbCF_Geometry                 3
+#define        _XkbCF_PhysSymbols              4
+#define _XkbCF_Symbols                 5
+#define        _XkbCF_Types                    6
+#define        _XkbCF_CompatMap                7
+
+#define        _XkbCF_RulesFile                8
+#define        _XkbCF_Model                    9
+#define        _XkbCF_Layout                   10
+#define        _XkbCF_Variant                  11
+#define        _XkbCF_Options                  12
+
+#define        _XkbCF_InitialMods              13
+#define        _XkbCF_InitialCtrls             14
+
+#define        _XkbCF_ClickVolume              15
+#define        _XkbCF_BellVolume               16
+#define        _XkbCF_BellPitch                17
+#define        _XkbCF_BellDuration             18
+#define        _XkbCF_RepeatDelay              19
+#define        _XkbCF_RepeatInterval           20
+#define        _XkbCF_SlowKeysDelay            21
+#define        _XkbCF_DebounceDelay            22
+#define        _XkbCF_MouseKeysDelay           23
+#define        _XkbCF_MouseKeysInterval        24
+#define        _XkbCF_MouseKeysTimeToMax       25
+#define        _XkbCF_MouseKeysMaxSpeed        26
+#define        _XkbCF_MouseKeysCurve           27
+#define        _XkbCF_AccessXTimeout           28
+#define        _XkbCF_AccessXTimeoutCtrlsOn    29
+#define        _XkbCF_AccessXTimeoutCtrlsOff   30
+#define        _XkbCF_AccessXTimeoutOptsOn     31
+#define        _XkbCF_AccessXTimeoutOptsOff    32
+
+#define        _XkbCF_IgnoreLockMods           33
+#define        _XkbCF_IgnoreGroupLock          34
+#define        _XkbCF_InternalMods             35
+
+#define        _XkbCF_GroupsWrap               36
+#define        _XkbCF_InitialFeedback          37
+
+static Bool
+AddCtrlByName(XkbConfigRtrnPtr rtrn,char *name,unsigned long *ctrls_rtrn)
+{
+    if ((_XkbStrCaseCmp(name,"repeat")==0)||
+       (_XkbStrCaseCmp(name,"repeatkeys")==0))
+       *ctrls_rtrn= XkbRepeatKeysMask;
+    else if (_XkbStrCaseCmp(name,"slowkeys")==0)
+       *ctrls_rtrn= XkbSlowKeysMask;
+    else if (_XkbStrCaseCmp(name,"bouncekeys")==0)
+       *ctrls_rtrn= XkbBounceKeysMask;
+    else if (_XkbStrCaseCmp(name,"stickykeys")==0)
+       *ctrls_rtrn= XkbStickyKeysMask;
+    else if (_XkbStrCaseCmp(name,"mousekeys")==0)
+       *ctrls_rtrn= XkbMouseKeysMask;
+    else if (_XkbStrCaseCmp(name,"mousekeysaccel")==0)
+       *ctrls_rtrn= XkbMouseKeysAccelMask;
+    else if (_XkbStrCaseCmp(name,"accessxkeys")==0)
+       *ctrls_rtrn= XkbAccessXKeysMask;
+    else if (_XkbStrCaseCmp(name,"accessxtimeout")==0)
+       *ctrls_rtrn= XkbAccessXTimeoutMask;
+    else if (_XkbStrCaseCmp(name,"accessxfeedback")==0)
+       *ctrls_rtrn= XkbAccessXFeedbackMask;
+    else if (_XkbStrCaseCmp(name,"audiblebell")==0)
+       *ctrls_rtrn= XkbAudibleBellMask;
+    else if (_XkbStrCaseCmp(name,"overlay1")==0)
+       *ctrls_rtrn= XkbOverlay1Mask;
+    else if (_XkbStrCaseCmp(name,"overlay2")==0)
+       *ctrls_rtrn= XkbOverlay2Mask;
+    else if (_XkbStrCaseCmp(name,"ignoregrouplock")==0)
+       *ctrls_rtrn= XkbIgnoreGroupLockMask;
+    else {
+       rtrn->error= XkbCF_ExpectedControl;
+       return False;
+    }
+    return True;
+}
+
+static Bool
+AddAXTimeoutOptByName( XkbConfigRtrnPtr        rtrn,
+                       char *                  name,
+                       unsigned short *        opts_rtrn)
+{
+    if (_XkbStrCaseCmp(name,"slowkeyspress")==0)
+       *opts_rtrn= XkbAX_SKPressFBMask;
+    else if (_XkbStrCaseCmp(name,"slowkeysaccept")==0)
+       *opts_rtrn= XkbAX_SKAcceptFBMask;
+    else if (_XkbStrCaseCmp(name,"feature")==0)
+       *opts_rtrn= XkbAX_FeatureFBMask;
+    else if (_XkbStrCaseCmp(name,"slowwarn")==0)
+       *opts_rtrn= XkbAX_SlowWarnFBMask;
+    else if (_XkbStrCaseCmp(name,"indicator")==0)
+       *opts_rtrn= XkbAX_IndicatorFBMask;
+    else if (_XkbStrCaseCmp(name,"stickykeys")==0)
+       *opts_rtrn= XkbAX_StickyKeysFBMask;
+    else if (_XkbStrCaseCmp(name,"twokeys")==0)
+       *opts_rtrn= XkbAX_TwoKeysMask;
+    else if (_XkbStrCaseCmp(name,"latchtolock")==0)
+       *opts_rtrn= XkbAX_LatchToLockMask;
+    else if (_XkbStrCaseCmp(name,"slowkeysrelease")==0)
+       *opts_rtrn= XkbAX_SKReleaseFBMask;
+    else if (_XkbStrCaseCmp(name,"slowkeysreject")==0)
+       *opts_rtrn= XkbAX_SKRejectFBMask;
+    else if (_XkbStrCaseCmp(name,"bouncekeysreject")==0)
+       *opts_rtrn= XkbAX_BKRejectFBMask;
+    else if (_XkbStrCaseCmp(name,"dumbbell")==0)
+       *opts_rtrn= XkbAX_DumbBellFBMask;
+    else {
+       rtrn->error= XkbCF_ExpectedControl;
+       return False;
+    }
+    return True;
+}
+
+XkbConfigUnboundModPtr
+XkbCFAddModByName(     XkbConfigRtrnPtr        rtrn,
+                       int                     what,
+                       char *                  name,
+                       Bool                    merge,
+                       XkbConfigUnboundModPtr  last)
+{
+    if (rtrn->num_unbound_mods>=rtrn->sz_unbound_mods) {
+       rtrn->sz_unbound_mods+= 5;
+       rtrn->unbound_mods= _XkbTypedRealloc(rtrn->unbound_mods,
+                                                 rtrn->sz_unbound_mods,
+                                                 XkbConfigUnboundModRec);
+       if (rtrn->unbound_mods==NULL) {
+           rtrn->error= XkbCF_BadAlloc;
+           return NULL;
+       }
+    }
+    if (last==NULL) {
+       last= &rtrn->unbound_mods[rtrn->num_unbound_mods++];
+       last->what= what;
+       last->mods= 0;
+       last->vmods= 0;
+       last->merge= merge;
+       last->name= NULL;
+    }
+    if (_XkbStrCaseCmp(name,"shift")==0)
+       last->mods|= ShiftMask;
+    else if (_XkbStrCaseCmp(name,"lock")==0)
+       last->mods|= LockMask;
+    else if ((_XkbStrCaseCmp(name,"control")==0)||
+               (_XkbStrCaseCmp(name,"ctrl")==0))
+       last->mods|= ControlMask;
+    else if (_XkbStrCaseCmp(name,"mod1")==0)
+       last->mods|= Mod1Mask;
+    else if (_XkbStrCaseCmp(name,"mod2")==0)
+       last->mods|= Mod2Mask;
+    else if (_XkbStrCaseCmp(name,"mod3")==0)
+       last->mods|= Mod3Mask;
+    else if (_XkbStrCaseCmp(name,"mod4")==0)
+       last->mods|= Mod4Mask;
+    else if (_XkbStrCaseCmp(name,"mod5")==0)
+       last->mods|= Mod5Mask;
+    else {
+       if (last->name!=NULL) {
+           last= &rtrn->unbound_mods[rtrn->num_unbound_mods++];
+           last->what= what;
+           last->mods= 0;
+           last->vmods= 0;
+           last->merge= merge;
+           last->name= NULL;
+       }
+       last->name= _XkbDupString(name);
+    }
+    return last;
+}
+
+int
+XkbCFBindMods(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
+{
+register int           n,v;
+Atom                   name;
+XkbConfigUnboundModPtr mod;
+int                    missing;
+
+    if (rtrn->num_unbound_mods<1)
+       return 0;
+    if ((xkb==NULL) || (xkb->names==NULL))
+       return -1;
+
+    missing= 0;
+    for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) {
+       if (mod->name!=NULL) {
+           name= XkbInternAtom(xkb->dpy,mod->name,True);
+           if (name==None)
+               continue;
+           for (v=0;v<XkbNumVirtualMods;v++) {
+               if (xkb->names->vmods[v]==name) {
+                   mod->vmods= (1<<v);
+                   _XkbFree(mod->name);
+                   mod->name= NULL;
+                   break;
+               }
+           }
+           if (mod->name!=NULL)
+               missing++;
+       }
+    }
+    return missing;
+}
+
+Bool
+XkbCFApplyMods(XkbConfigRtrnPtr rtrn,int what,XkbConfigModInfoPtr info)
+{
+register int           n;
+XkbConfigUnboundModPtr mod;
+
+    if (rtrn->num_unbound_mods<1)
+       return True;
+
+    for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) {
+       if (mod->what!=what)
+           continue;
+       if (mod->merge==XkbCF_MergeRemove) {
+           info->mods_clear|= mod->mods;
+           info->vmods_clear|= mod->vmods;
+       }
+       else {
+           if (mod->merge==XkbCF_MergeSet)
+               info->replace= True;
+           info->mods|= mod->mods;
+           info->vmods|= mod->vmods;
+       }
+       if (mod->name==NULL) {
+           mod->what= _XkbCF_Illegal;
+       }
+       else {
+           mod->mods= 0;
+           mod->vmods= 0;
+       }
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+DefaultParser( FILE *                  file,
+               XkbConfigFieldsPtr      fields,
+               XkbConfigFieldPtr       field,
+               XkbDescPtr              xkb,
+               XkbConfigRtrnPtr        rtrn)
+{
+int                    tok;
+XkbCFScanResultRec     val;
+char **                        str;
+int                    merge;
+unsigned long *                ctrls, ctrls_mask;
+unsigned short *       opts, opts_mask;
+int *                  pival, sign;
+int                    onoff;
+XkbConfigUnboundModPtr last;
+unsigned               what;
+
+    tok= XkbCFScan(file,&val,rtrn);
+    str= NULL;
+    onoff= 0;
+    pival= NULL;
+    switch (field->field_id) {
+       case _XkbCF_RulesFile:  if (!str)       str= &rtrn->rules_file;
+       case _XkbCF_Model:      if (!str)       str= &rtrn->model;
+       case _XkbCF_Layout:     if (!str)       str= &rtrn->layout;
+       case _XkbCF_Variant:    if (!str)       str= &rtrn->variant;
+       case _XkbCF_Options:    if (!str)       str= &rtrn->options;
+       case _XkbCF_Keymap:     if (!str)       str= &rtrn->keymap;
+       case _XkbCF_Keycodes:   if (!str)       str= &rtrn->keycodes;
+       case _XkbCF_Geometry:   if (!str)       str= &rtrn->geometry;
+       case _XkbCF_PhysSymbols:if (!str)       str= &rtrn->phys_symbols;
+       case _XkbCF_Symbols:    if (!str)       str= &rtrn->symbols;
+       case _XkbCF_Types:      if (!str)       str= &rtrn->types;
+       case _XkbCF_CompatMap:  if (!str)       str= &rtrn->compat;
+           if (tok!=XkbCF_Equals) {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok!=XkbCF_String)&&(tok!=XkbCF_Ident)) {
+               rtrn->error= XkbCF_ExpectedString;
+               return False;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedEOS;
+               return False;
+           }
+           if (*str!=NULL)
+               _XkbFree(*str);
+           *str= _XkbDupString(val.str);
+           break;
+       case _XkbCF_InitialMods:
+       case _XkbCF_IgnoreLockMods:
+       case _XkbCF_InternalMods:
+           what= XkbCF_InitialMods;
+           if (field->field_id==_XkbCF_InitialMods)
+               rtrn->defined|= (what=XkbCF_InitialMods);
+           else if (field->field_id==_XkbCF_InternalMods)
+               rtrn->defined|= (what=XkbCF_InternalMods);
+           else if (field->field_id==_XkbCF_IgnoreLockMods)
+               rtrn->defined|= (what=XkbCF_IgnoreLockMods);
+           if (tok==XkbCF_Equals)              merge= XkbCF_MergeSet;
+           else if (tok==XkbCF_MinusEquals)    merge= XkbCF_MergeRemove;
+           else if (tok==XkbCF_PlusEquals)     merge= XkbCF_MergeAdd;
+           else {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedModifier;
+               return False;
+           }
+           last= NULL;
+           while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
+                   rtrn->error= XkbCF_ExpectedModifier;
+                   return False;
+               }
+               last=XkbCFAddModByName(rtrn,what,val.str,merge,last);
+               if (last==NULL)
+                   return False;
+               if (merge==XkbCF_MergeSet)
+                   merge= XkbCF_MergeAdd;
+               tok= XkbCFScan(file,&val,rtrn);
+               if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
+                   if (tok!=XkbCF_Plus) {
+                       rtrn->error= XkbCF_ExpectedOperator;
+                       return False;
+                   }
+                   tok= XkbCFScan(file,&val,rtrn);
+               }
+           }
+           break;
+       case _XkbCF_InitialCtrls:
+           rtrn->defined|= XkbCF_InitialCtrls;
+           ctrls= NULL;
+           if (tok==XkbCF_PlusEquals)
+               ctrls= &rtrn->initial_ctrls;
+           else if (tok==XkbCF_MinusEquals)
+               ctrls= &rtrn->initial_ctrls_clear;
+           else if (tok==XkbCF_Equals) {
+               ctrls= &rtrn->initial_ctrls;
+               rtrn->replace_initial_ctrls= True;
+               *ctrls= 0;
+           }
+           else {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedControl;
+               return False;
+           }
+           while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
+                   rtrn->error= XkbCF_ExpectedControl;
+                   return False;
+               }
+               if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) {
+                   return False;
+               }
+               *ctrls |= ctrls_mask;
+               tok= XkbCFScan(file,&val,rtrn);
+               if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
+                   if (tok!=XkbCF_Plus) {
+                       rtrn->error= XkbCF_ExpectedOperator;
+                       return False;
+                   }
+                   tok= XkbCFScan(file,&val,rtrn);
+               }
+           }
+           break;
+       case _XkbCF_AccessXTimeoutCtrlsOn:
+       case _XkbCF_AccessXTimeoutCtrlsOff:
+           opts= NULL;
+           if (tok==XkbCF_MinusEquals) {
+               ctrls= &rtrn->axt_ctrls_ignore;
+               opts= &rtrn->axt_opts_ignore;
+           }
+           else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) {
+               if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) {
+                   ctrls= &rtrn->axt_ctrls_off;
+                   opts= &rtrn->axt_opts_off;
+                   if (tok==XkbCF_Equals)
+                       rtrn->replace_axt_ctrls_off= True;
+               }
+               else {
+                   ctrls= &rtrn->axt_ctrls_on;
+                   opts= &rtrn->axt_opts_on;
+                   if (tok==XkbCF_Equals)
+                       rtrn->replace_axt_ctrls_on= True;
+               }
+               *ctrls= 0;
+           }
+           else {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedControl;
+               return False;
+           }
+           while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
+                   rtrn->error= XkbCF_ExpectedControl;
+                   return False;
+               }
+               if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) {
+                   if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask))
+                       return False;
+                   *opts |= opts_mask;
+                   if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) {
+                       rtrn->defined|= XkbCF_AccessXTimeoutOptsOff;
+                       if (rtrn->replace_axt_ctrls_off)
+                           rtrn->replace_axt_opts_off= True;
+                   }
+                   else {
+                       rtrn->defined|= XkbCF_AccessXTimeoutOptsOn;
+                       if (rtrn->replace_axt_ctrls_on)
+                           rtrn->replace_axt_opts_on= True;
+                   }
+               }
+               else
+                   *ctrls |= ctrls_mask;
+               tok= XkbCFScan(file,&val,rtrn);
+               if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
+                   if (tok!=XkbCF_Plus) {
+                       rtrn->error= XkbCF_ExpectedOperator;
+                       return False;
+                   }
+                   tok= XkbCFScan(file,&val,rtrn);
+               }
+           }
+           break;
+       case _XkbCF_InitialFeedback:
+           rtrn->defined|= XkbCF_InitialOpts;
+           opts= NULL;
+           if (tok==XkbCF_PlusEquals)
+               opts= &rtrn->initial_opts;
+           else if (tok==XkbCF_MinusEquals)
+               opts= &rtrn->initial_opts_clear;
+           else if (tok==XkbCF_Equals) {
+               opts= &rtrn->initial_opts;
+               rtrn->replace_initial_opts= True;
+               *opts= 0;
+           }
+           else {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedAXOption;
+               return False;
+           }
+           while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
+                   rtrn->error= XkbCF_ExpectedAXOption;
+                   return False;
+               }
+               if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask)) {
+                   return False;
+               }
+               *opts |= opts_mask;
+               tok= XkbCFScan(file,&val,rtrn);
+               if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
+                   if (tok!=XkbCF_Plus) {
+                       rtrn->error= XkbCF_ExpectedOperator;
+                       return False;
+                   }
+                   tok= XkbCFScan(file,&val,rtrn);
+               }
+           }
+           break;
+       case _XkbCF_AccessXTimeoutOptsOff:
+       case _XkbCF_AccessXTimeoutOptsOn:
+           opts= NULL;
+           if (tok==XkbCF_MinusEquals)
+               opts= &rtrn->axt_opts_ignore;
+           else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) {
+               if (field->field_id==_XkbCF_AccessXTimeoutOptsOff) {
+                   opts= &rtrn->axt_opts_off;
+                   if (tok==XkbCF_Equals)
+                       rtrn->replace_axt_opts_off= True;
+               }
+               else {
+                   opts= &rtrn->axt_opts_on;
+                   if (tok==XkbCF_Equals)
+                       rtrn->replace_axt_opts_on= True;
+               }
+               *opts = 0;
+           }
+           else {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedControl;
+               return False;
+           }
+           while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) {
+                   rtrn->error= XkbCF_ExpectedControl;
+                   return False;
+               }
+               if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask))
+                   return False;
+               *opts |= opts_mask;
+
+               tok= XkbCFScan(file,&val,rtrn);
+               if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) {
+                   if (tok!=XkbCF_Plus) {
+                       rtrn->error= XkbCF_ExpectedOperator;
+                       return False;
+                   }
+                   tok= XkbCFScan(file,&val,rtrn);
+               }
+           }
+           break;
+       case _XkbCF_ClickVolume:
+           if (!pival) {
+               pival= &rtrn->click_volume;
+               onoff= 100;
+           }
+       case _XkbCF_BellVolume:
+           if (!pival) {
+               pival= &rtrn->bell_volume;
+               onoff= 100;
+           }
+       case _XkbCF_BellPitch:
+           if (!pival)
+               pival= &rtrn->bell_pitch;
+       case _XkbCF_BellDuration:
+           if (!pival)
+               pival= &rtrn->bell_duration;
+       case _XkbCF_RepeatDelay:
+           if (!pival)
+               pival= &rtrn->repeat_delay;
+       case _XkbCF_RepeatInterval:
+           if (!pival)
+               pival= &rtrn->repeat_interval;
+       case _XkbCF_SlowKeysDelay:
+           if (!pival)
+               pival= &rtrn->slow_keys_delay;
+       case _XkbCF_DebounceDelay:
+           if (!pival)
+               pival= &rtrn->debounce_delay;
+       case _XkbCF_MouseKeysDelay:
+           if (!pival)
+               pival= &rtrn->mk_delay;
+       case _XkbCF_MouseKeysInterval:
+           if (!pival)
+               pival= &rtrn->mk_interval;
+       case _XkbCF_MouseKeysTimeToMax:
+           if (!pival)
+               pival= &rtrn->mk_time_to_max;
+       case _XkbCF_MouseKeysMaxSpeed:
+           if (!pival)
+               pival= &rtrn->mk_max_speed;
+       case _XkbCF_MouseKeysCurve:
+           if (!pival)
+               pival= &rtrn->mk_curve;
+       case _XkbCF_AccessXTimeout:
+           if (!pival)
+               pival= &rtrn->ax_timeout;
+           if (tok!=XkbCF_Equals) {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if (tok == XkbCF_Minus && field->field_id == _XkbCF_MouseKeysCurve) {
+               /* This can be a negative value */
+               tok = XkbCFScan(file,&val,rtrn);
+               sign = -1;
+           }
+           else
+               sign = 1;
+           if (tok!=XkbCF_Integer) {
+               Bool ok= False;
+               if ((onoff)&&(tok==XkbCF_Ident)&&(val.str!=NULL)) {
+                   if (_XkbStrCaseCmp(val.str,"on")) {
+                       val.ival= onoff;
+                       ok= True;
+                   }
+                   else if (_XkbStrCaseCmp(val.str,"off")) {
+                       val.ival= 0;
+                       ok= True;
+                   }
+               }
+               if (!ok) {
+                   rtrn->error= XkbCF_ExpectedInteger;
+                   goto BAILOUT;
+               }
+           }
+           *pival= val.ival * sign;
+           if (field->field_id == _XkbCF_AccessXTimeout)
+               rtrn->defined|=XkbCF_AccessXTimeout;
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedEOS;
+               return False;
+           }
+           break;
+       case _XkbCF_GroupsWrap:
+           if (tok!=XkbCF_Equals) {
+               rtrn->error= XkbCF_MissingEquals;
+               goto BAILOUT;
+           }
+           tok= XkbCFScan(file,&val,rtrn);
+           if (tok==XkbCF_Ident) {
+               if (_XkbStrCaseCmp(val.str,"wrap")==0) {
+                   rtrn->groups_wrap= XkbSetGroupInfo(0,XkbWrapIntoRange,0);
+               }
+               else if (_XkbStrCaseCmp(val.str,"clamp")==0) {
+                   rtrn->groups_wrap= XkbSetGroupInfo(0,XkbClampIntoRange,0);
+               }
+               else {
+                   rtrn->error= XkbCF_ExpectedOORGroupBehavior;
+                   return False;
+               }
+           }
+           else if ((tok==XkbCF_Integer)&&(XkbIsLegalGroup(val.ival-1))) {
+               rtrn->groups_wrap= XkbSetGroupInfo(0,XkbRedirectIntoRange,
+                                                               val.ival-1);
+           }
+           else {
+               rtrn->error= XkbCF_ExpectedOORGroupBehavior;
+               return False;
+           }
+           rtrn->defined|= XkbCF_GroupsWrap;
+           tok= XkbCFScan(file,&val,rtrn);
+           if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) {
+               rtrn->error= XkbCF_ExpectedEOS;
+               return False;
+           }
+           break;
+       default:
+           rtrn->error= XkbCF_ExpectedInteger;
+           goto BAILOUT;
+
+    }
+    return True;
+BAILOUT:
+    return False;
+}
+
+static Bool
+DefaultCleanUp(XkbConfigRtrnPtr rtrn)
+{
+    if (rtrn->keymap)  _XkbFree(rtrn->keymap);
+    if (rtrn->keycodes)        _XkbFree(rtrn->keycodes);
+    if (rtrn->geometry)        _XkbFree(rtrn->geometry);
+    if (rtrn->phys_symbols)    _XkbFree(rtrn->phys_symbols);
+    if (rtrn->symbols) _XkbFree(rtrn->symbols);
+    if (rtrn->types)   _XkbFree(rtrn->types);
+    if (rtrn->compat)  _XkbFree(rtrn->compat);
+    rtrn->keycodes= rtrn->geometry= NULL;
+    rtrn->symbols= rtrn->phys_symbols= NULL;
+    rtrn->types= rtrn->compat= NULL;
+    if ((rtrn->unbound_mods!=NULL)&&(rtrn->num_unbound_mods>0)) {
+       register int i;
+       for (i=0;i<rtrn->num_unbound_mods;i++) {
+           if (rtrn->unbound_mods[i].name!=NULL) {
+               _XkbFree(rtrn->unbound_mods[i].name);
+               rtrn->unbound_mods[i].name= NULL;
+           }
+       }
+       _XkbFree(rtrn->unbound_mods);
+       rtrn->sz_unbound_mods= 0;
+       rtrn->num_unbound_mods= 0;
+       rtrn->unbound_mods= NULL;
+    }
+    return True;
+}
+
+static Bool
+DefaultApplyNames(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
+{
+char *str;
+
+    if (XkbAllocNames(xkb,XkbComponentNamesMask,0,0)!=Success)
+       return False;
+    if ((str=rtrn->keycodes)!=NULL) {
+       xkb->names->keycodes= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->keycodes= NULL;
+    }
+    if ((str=rtrn->geometry)!=NULL) {
+       xkb->names->geometry= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->geometry= NULL;
+    }
+    if ((str=rtrn->symbols)!=NULL) {
+       xkb->names->symbols= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->symbols= NULL;
+    }
+    if ((str=rtrn->phys_symbols)!=NULL) {
+       xkb->names->phys_symbols= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->phys_symbols= NULL;
+    }
+    if ((str=rtrn->types)!=NULL) {
+       xkb->names->types= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->types= NULL;
+    }
+    if ((str=rtrn->compat)!=NULL) {
+       xkb->names->compat= XkbInternAtom(xkb->dpy,str,False);
+       _XkbFree(str);
+       rtrn->compat= NULL;
+    }
+    return True;
+}
+
+static Bool
+DefaultApplyControls(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb)
+{
+unsigned       on,off;
+XkbControlsPtr ctrls;
+unsigned int   mask;
+
+    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
+       return False;
+    ctrls= xkb->ctrls;
+    if (rtrn->replace_initial_ctrls)
+        ctrls->enabled_ctrls=  rtrn->initial_ctrls;
+    else ctrls->enabled_ctrls|= rtrn->initial_ctrls;
+    ctrls->enabled_ctrls&= ~rtrn->initial_ctrls_clear;
+    if (rtrn->internal_mods.replace) {
+       ctrls->internal.real_mods= rtrn->internal_mods.mods;
+       ctrls->internal.vmods= rtrn->internal_mods.vmods;
+    }
+    else {
+       ctrls->internal.real_mods&= ~rtrn->internal_mods.mods_clear;
+       ctrls->internal.vmods&= ~rtrn->internal_mods.vmods_clear;
+       ctrls->internal.real_mods|= rtrn->internal_mods.mods;
+       ctrls->internal.vmods|= rtrn->internal_mods.vmods;
+    }
+    mask= 0;
+    (void)XkbVirtualModsToReal(xkb,ctrls->internal.vmods,&mask);
+    ctrls->internal.mask= (ctrls->internal.real_mods|mask);
+
+    if (rtrn->ignore_lock_mods.replace) {
+       ctrls->ignore_lock.real_mods= rtrn->ignore_lock_mods.mods;
+       ctrls->ignore_lock.vmods= rtrn->ignore_lock_mods.vmods;
+    }
+    else {
+       ctrls->ignore_lock.real_mods&= ~rtrn->ignore_lock_mods.mods_clear;
+       ctrls->ignore_lock.vmods&= ~rtrn->ignore_lock_mods.vmods_clear;
+       ctrls->ignore_lock.real_mods|= rtrn->ignore_lock_mods.mods;
+       ctrls->ignore_lock.vmods|= rtrn->ignore_lock_mods.vmods;
+    }
+    mask= 0;
+    (void)XkbVirtualModsToReal(xkb,ctrls->ignore_lock.vmods,&mask);
+    ctrls->ignore_lock.mask= (ctrls->ignore_lock.real_mods|mask);
+
+    if (rtrn->repeat_delay>0)
+       ctrls->repeat_delay= rtrn->repeat_delay;
+    if (rtrn->repeat_interval>0)
+       ctrls->repeat_interval= rtrn->repeat_interval;
+    if (rtrn->slow_keys_delay>0)
+       ctrls->slow_keys_delay= rtrn->slow_keys_delay;
+    if (rtrn->debounce_delay>0)
+       ctrls->debounce_delay= rtrn->debounce_delay;
+    if (rtrn->mk_delay>0)
+       ctrls->mk_delay= rtrn->mk_delay;
+    if (rtrn->mk_interval>0)
+       ctrls->mk_interval= rtrn->mk_interval;
+    if (rtrn->mk_time_to_max>0)
+       ctrls->mk_time_to_max= rtrn->mk_time_to_max;
+    if (rtrn->mk_max_speed>0)
+       ctrls->mk_max_speed= rtrn->mk_max_speed;
+    if (rtrn->mk_curve>0)
+       ctrls->mk_curve= rtrn->mk_curve;
+    if (rtrn->defined&XkbCF_AccessXTimeout && rtrn->ax_timeout > 0)
+       ctrls->ax_timeout= rtrn->ax_timeout;
+
+    /* any value set to both off and on is reset to ignore */
+    if ((off=(rtrn->axt_ctrls_on&rtrn->axt_ctrls_off))!=0)
+       rtrn->axt_ctrls_ignore|= off;
+
+    /* ignore takes priority over on and off */
+    rtrn->axt_ctrls_on&= ~rtrn->axt_ctrls_ignore;
+    rtrn->axt_ctrls_off&= ~rtrn->axt_ctrls_ignore;
+
+    if (!rtrn->replace_axt_ctrls_off) {
+        off= (ctrls->axt_ctrls_mask&(~ctrls->axt_ctrls_values));
+        off&= ~rtrn->axt_ctrls_on;
+        off|= rtrn->axt_ctrls_off;
+    }
+    else off= rtrn->axt_ctrls_off;
+    if (!rtrn->replace_axt_ctrls_on) {
+        on= (ctrls->axt_ctrls_mask&ctrls->axt_ctrls_values);
+        on&= ~rtrn->axt_ctrls_off;
+        on|= rtrn->axt_ctrls_on;
+    }
+    else on= rtrn->axt_ctrls_on;
+    ctrls->axt_ctrls_mask= (on|off)&~rtrn->axt_ctrls_ignore;
+    ctrls->axt_ctrls_values= on&~rtrn->axt_ctrls_ignore;
+
+    /* any value set to both off and on is reset to ignore */
+    if ((off=(rtrn->axt_opts_on&rtrn->axt_opts_off))!=0)
+       rtrn->axt_opts_ignore|= off;
+
+    /* ignore takes priority over on and off */
+    rtrn->axt_opts_on&= ~rtrn->axt_opts_ignore;
+    rtrn->axt_opts_off&= ~rtrn->axt_opts_ignore;
+
+    if (rtrn->replace_axt_opts_off) {
+        off= (ctrls->axt_opts_mask&(~ctrls->axt_opts_values));
+        off&= ~rtrn->axt_opts_on;
+        off|= rtrn->axt_opts_off;
+    }
+    else off= rtrn->axt_opts_off;
+    if (!rtrn->replace_axt_opts_on) {
+        on= (ctrls->axt_opts_mask&ctrls->axt_opts_values);
+        on&= ~rtrn->axt_opts_off;
+        on|= rtrn->axt_opts_on;
+    }
+    else on= rtrn->axt_opts_on;
+    ctrls->axt_opts_mask= (unsigned short)((on|off)&~rtrn->axt_ctrls_ignore);
+    ctrls->axt_opts_values= (unsigned short)(on&~rtrn->axt_ctrls_ignore);
+
+    if (rtrn->defined&XkbCF_GroupsWrap) {
+       int n;
+       n= XkbNumGroups(ctrls->groups_wrap);
+       rtrn->groups_wrap= XkbSetNumGroups(rtrn->groups_wrap,n);
+       ctrls->groups_wrap= rtrn->groups_wrap;
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+DefaultFinish( XkbConfigFieldsPtr      fields,
+               XkbDescPtr              xkb,
+               XkbConfigRtrnPtr        rtrn,
+               int                     what)
+{
+    if ((what==XkbCF_Destroy)||(what==XkbCF_CleanUp))
+       return DefaultCleanUp(rtrn);
+    if (what==XkbCF_Check) {
+       if ((rtrn->symbols==NULL)&&(rtrn->phys_symbols!=NULL))
+           rtrn->symbols= _XkbDupString(rtrn->phys_symbols);
+    }
+    if ((what==XkbCF_Apply)||(what==XkbCF_Check)) {
+       if (xkb && xkb->names && (rtrn->num_unbound_mods>0))
+           XkbCFBindMods(rtrn,xkb);
+       XkbCFApplyMods(rtrn,XkbCF_InitialMods,&rtrn->initial_mods);
+       XkbCFApplyMods(rtrn,XkbCF_InternalMods,&rtrn->internal_mods);
+       XkbCFApplyMods(rtrn,XkbCF_IgnoreLockMods,&rtrn->ignore_lock_mods);
+    }
+    if (what==XkbCF_Apply) {
+       if (xkb!=NULL) {
+           DefaultApplyNames(rtrn,xkb);
+           DefaultApplyControls(rtrn,xkb);
+           XkbCFBindMods(rtrn,xkb);
+       }
+    }
+    return True;
+}
+
+static XkbConfigFieldRec _XkbCFDfltFields[] = {
+       { "rules",      _XkbCF_RulesFile },
+       { "model",      _XkbCF_Model },
+       { "layout",     _XkbCF_Layout },
+       { "variant",    _XkbCF_Variant },
+       { "options",    _XkbCF_Options },
+       { "keymap",     _XkbCF_Keymap },
+       { "keycodes",   _XkbCF_Keycodes },
+       { "geometry",   _XkbCF_Geometry },
+       { "realsymbols",_XkbCF_PhysSymbols },
+       { "actualsymbols",_XkbCF_PhysSymbols },
+       { "symbols",    _XkbCF_Symbols },
+       { "symbolstouse",_XkbCF_Symbols },
+       { "types",      _XkbCF_Types },
+       { "compat",     _XkbCF_CompatMap },
+       { "modifiers",  _XkbCF_InitialMods },
+       { "controls",   _XkbCF_InitialCtrls },
+       { "click",      _XkbCF_ClickVolume },
+       { "clickvolume",_XkbCF_ClickVolume },
+       { "bell",       _XkbCF_BellVolume },
+       { "bellvolume", _XkbCF_BellVolume },
+       { "bellpitch",  _XkbCF_BellPitch },
+       { "bellduration",_XkbCF_BellDuration },
+       { "repeatdelay",_XkbCF_RepeatDelay },
+       { "repeatinterval",_XkbCF_RepeatInterval },
+       { "slowkeysdelay",_XkbCF_SlowKeysDelay  },
+       { "debouncedelay",_XkbCF_DebounceDelay },
+       { "mousekeysdelay",_XkbCF_MouseKeysDelay },
+       { "mousekeysinterval",_XkbCF_MouseKeysInterval },
+       { "mousekeystimetomax",_XkbCF_MouseKeysTimeToMax },
+       { "mousekeysmaxspeed",_XkbCF_MouseKeysMaxSpeed },
+       { "mousekeyscurve",_XkbCF_MouseKeysCurve },
+       { "accessxtimeout",_XkbCF_AccessXTimeout },
+       { "axtimeout",_XkbCF_AccessXTimeout },
+       { "accessxtimeoutctrlson",_XkbCF_AccessXTimeoutCtrlsOn },
+       { "axtctrlson", _XkbCF_AccessXTimeoutCtrlsOn },
+       { "accessxtimeoutctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff },
+       { "axtctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff },
+       { "accessxtimeoutfeedbackon", _XkbCF_AccessXTimeoutOptsOn },
+       { "axtfeedbackon", _XkbCF_AccessXTimeoutOptsOn },
+       { "accessxtimeoutfeedbackoff", _XkbCF_AccessXTimeoutOptsOff },
+       { "axtfeedbackoff", _XkbCF_AccessXTimeoutOptsOff },
+       { "ignorelockmods",_XkbCF_IgnoreLockMods },
+       { "ignorelockmodifiers",_XkbCF_IgnoreLockMods },
+       { "ignoregrouplock",_XkbCF_IgnoreGroupLock },
+       { "internalmods",_XkbCF_InternalMods },
+       { "internalmodifiers",_XkbCF_InternalMods },
+       { "outofrangegroups",_XkbCF_GroupsWrap },
+       { "groups", _XkbCF_GroupsWrap },
+       { "feedback", _XkbCF_InitialFeedback },
+};
+#define        _XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec))
+
+static XkbConfigFieldsRec _XkbCFDflts = {
+       0,                      /* cfg_id */
+       _XkbCFNumDfltFields,    /* num_fields */
+       _XkbCFDfltFields,       /* fields */
+       DefaultParser,  /* parser */
+       DefaultFinish,  /* finish */
+       NULL,                   /* priv */
+       NULL                    /* next */
+};
+
+XkbConfigFieldsPtr     XkbCFDflts= &_XkbCFDflts;
+
+/***====================================================================***/
+
+XkbConfigFieldsPtr
+XkbCFDup(XkbConfigFieldsPtr fields)
+{
+XkbConfigFieldsPtr     pNew;
+
+    pNew= _XkbTypedAlloc(XkbConfigFieldsRec);
+    if (pNew!=NULL) {
+       memcpy(pNew,fields,sizeof(XkbConfigFieldsRec));
+       if ((pNew->fields!=NULL)&&(pNew->num_fields>0)) {
+           pNew->fields= _XkbTypedCalloc(pNew->num_fields,XkbConfigFieldRec);
+           if (pNew->fields) {
+               memcpy(fields->fields,pNew->fields,
+                               (pNew->num_fields*sizeof(XkbConfigFieldRec)));
+           }
+           else {
+               _XkbFree(pNew);
+               return NULL;
+           }
+       }
+       else {
+           pNew->num_fields= 0;
+           pNew->fields= NULL;
+       }
+       pNew->next= NULL;
+    }
+    return pNew;
+}
+
+XkbConfigFieldsPtr
+XkbCFFree(XkbConfigFieldsPtr fields,Bool all)
+{
+XkbConfigFieldsPtr     next;
+
+    next= NULL;
+    while (fields!=NULL) {
+       next= fields->next;
+       if (fields!=XkbCFDflts) {
+           if (fields->fields) {
+               _XkbFree(fields->fields);
+               fields->fields= NULL;
+               fields->num_fields= 0;
+           }
+           _XkbFree(fields);
+       }
+       fields= (all?next:NULL);
+    }
+    return next;
+}
+
+Bool
+XkbCFApplyRtrnValues(  XkbConfigRtrnPtr        rtrn,
+                       XkbConfigFieldsPtr      fields,
+                       XkbDescPtr              xkb)
+{
+Bool                   ok;
+
+    if ((fields==NULL)||(rtrn==NULL)||(xkb==NULL))
+       return False;
+    for (ok=True;fields!=NULL;fields=fields->next) {
+       if (fields->finish!=NULL)
+           ok= (*fields->finish)(fields,xkb,rtrn,XkbCF_Apply)&&ok;
+    }
+    return ok;
+}
+
+XkbConfigRtrnPrivPtr
+XkbCFAddPrivate(       XkbConfigRtrnPtr        rtrn,
+                       XkbConfigFieldsPtr      fields,
+                       XPointer                ptr)
+{
+XkbConfigRtrnPrivPtr   priv;
+
+    if ((rtrn==NULL)||(fields==NULL))
+       return NULL;
+    priv= _XkbTypedAlloc(XkbConfigRtrnPrivRec);
+    if (priv!=NULL) {
+       priv->cfg_id=   fields->cfg_id;
+       priv->priv=     ptr;
+       priv->next=     rtrn->priv;
+       rtrn->priv=     priv;
+    }
+    return priv;
+}
+
+void
+XkbCFFreeRtrn( XkbConfigRtrnPtr        rtrn,
+               XkbConfigFieldsPtr      fields,
+               XkbDescPtr              xkb)
+{
+XkbConfigRtrnPrivPtr   tmp,next;
+
+    if ((fields==NULL)||(rtrn==NULL))
+       return;
+    while (fields!=NULL) {
+       if (fields->finish!=NULL)
+           (*fields->finish)(fields,xkb,rtrn,XkbCF_Destroy);
+       fields= fields->next;
+    }
+    for (tmp=rtrn->priv;tmp!=NULL;tmp=next) {
+       next= tmp->next;
+       bzero((char *)tmp,sizeof(XkbConfigRtrnPrivRec));
+       _XkbFree(tmp);
+    }
+    bzero((char *)rtrn,sizeof(XkbConfigRtrnRec));
+    return;
+}
+
+Bool
+XkbCFParse(    FILE *                  file,
+               XkbConfigFieldsPtr      fields,
+               XkbDescPtr              xkb,
+               XkbConfigRtrnPtr        rtrn)
+{
+int                    tok;
+XkbCFScanResultRec     val;
+XkbConfigFieldsPtr     tmp;
+
+    if ((file==NULL)||(fields==NULL)||(rtrn==NULL))
+       return False;
+    for (tok=0,tmp=fields;tmp!=NULL;tmp=tmp->next,tok++) {
+       fields->cfg_id= tok;
+    }
+    bzero((char *)rtrn,sizeof(XkbConfigRtrnRec));
+    rtrn->line= 1;
+    rtrn->click_volume= -1;
+    rtrn->bell_volume= -1;
+    while ((tok=XkbCFScan(file,&val,rtrn))!=XkbCF_EOF) {
+       if (tok==XkbCF_Ident) {
+           Bool                done;
+           for (tmp=fields,done=False;(tmp!=NULL)&&(!done);tmp=tmp->next) {
+               register int            i;
+               XkbConfigFieldPtr       f;
+
+               for (i=0,f=tmp->fields;(i<tmp->num_fields)&&(!done);i++,f++) {
+                   if (_XkbStrCaseCmp(val.str,f->field)!=0)
+                       continue;
+                   if ((*tmp->parser)(file,tmp,f,xkb,rtrn))
+                        done= True;
+                   else goto BAILOUT;
+               }
+           }
+       }
+       else if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)) {
+           rtrn->error= XkbCF_MissingIdent;
+           goto BAILOUT;
+       }
+    }
+    for (tmp=fields;tmp!=NULL;tmp=tmp->next) {
+       if ((tmp->finish)&&(!(*tmp->finish)(tmp,xkb,rtrn,XkbCF_Check)))
+           goto BAILOUT;
+    }
+    return True;
+BAILOUT:
+    for (tmp=fields;tmp!=NULL;tmp=tmp->next) {
+       if (tmp->finish)
+           (*tmp->finish)(tmp,xkb,rtrn,XkbCF_CleanUp);
+    }
+    return False;
+}
+
+/*ARGSUSED*/
+void
+XkbCFReportError(FILE *file,char *name,int error,int line)
+{
+const char *msg;
+
+    switch(error) {
+       case XkbCF_BadAlloc:
+           msg= "allocation failed\n"; break;
+       case XkbCF_UnterminatedString:
+           msg= "unterminated string on line %d"; break;
+       case XkbCF_MissingIdent:
+           msg= "expected identifier on line %d"; break;
+       case XkbCF_MissingEquals:
+           msg= "expected '=' on line %d"; break;
+       case XkbCF_ExpectedEOS:
+           msg= "expected ';' or newline on line %d"; break;
+       case XkbCF_ExpectedBoolean:
+           msg= "expected a boolean value on line %d"; break;
+       case XkbCF_ExpectedInteger:
+           msg= "expected a numeric value on line %d"; break;
+       case XkbCF_ExpectedString:
+           msg= "expected a string on line %d"; break;
+       case XkbCF_ExpectedModifier:
+           msg= "expected a modifier name on line %d"; break;
+       case XkbCF_ExpectedControl:
+           msg= "expected a control name on line %d"; break;
+       case XkbCF_ExpectedAXOption:
+           msg= "expected an AccessX option on line %d"; break;
+       case XkbCF_ExpectedOperator:
+           msg= "expected '+' or '-' on line %d"; break;
+       case XkbCF_ExpectedOORGroupBehavior:
+           msg= "expected wrap, clamp or group number on line %d"; break;
+       default:
+           msg= "unknown error on line %d"; break;
+    }
+#ifndef XKB_IN_SERVER
+    fprintf(file,msg,line);
+    if (name)  fprintf(file," of %s\n",name);
+    else       fprintf(file,"\n");
+#else
+    ErrorF(msg,line);
+    if (name)  ErrorF(" of %s\n",name);
+    else       ErrorF("\n");
+#endif
+    return;
+}
diff --git a/src/xkbdraw.c b/src/xkbdraw.c
new file mode 100644 (file)
index 0000000..179dc74
--- /dev/null
@@ -0,0 +1,133 @@
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+static void
+_XkbAddDrawable(XkbDrawablePtr *pfirst,XkbDrawablePtr *plast,XkbDrawablePtr tmp)
+{
+XkbDrawablePtr old;
+
+    if (*pfirst==NULL) {
+       *pfirst= *plast= tmp;
+    }
+    else if (tmp->priority>=(*plast)->priority) {
+       (*plast)->next= tmp;
+       *plast= tmp;
+    }
+    else if (tmp->priority<(*pfirst)->priority) {
+       tmp->next= (*pfirst);
+       (*pfirst)= tmp;
+    }
+    else {
+       old= *pfirst;
+       while ((old->next)&&(old->next->priority<=tmp->priority)) {
+           old= old->next;
+       }
+       tmp->next= old->next;
+       old->next= tmp;
+    }
+    return;
+}
+
+XkbDrawablePtr
+XkbGetOrderedDrawables(XkbGeometryPtr geom,XkbSectionPtr section)
+{
+XkbDrawablePtr first,last,tmp;
+int            i;
+
+    first= last= NULL;
+    if (geom!=NULL) {
+       XkbSectionPtr   section;
+       XkbDoodadPtr    doodad;
+       for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
+           tmp= _XkbTypedCalloc(1,XkbDrawableRec);
+           if (!tmp) {
+               XkbFreeOrderedDrawables(first);
+               return NULL;
+           }
+           tmp->type= XkbDW_Section;
+           tmp->priority= section->priority;
+           tmp->u.section= section;
+           tmp->next= NULL;
+           _XkbAddDrawable(&first,&last,tmp);
+       }
+       for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
+           tmp= _XkbTypedCalloc(1,XkbDrawableRec);
+           if (!tmp) {
+               XkbFreeOrderedDrawables(first);
+               return NULL;
+           }
+           tmp->type= XkbDW_Doodad;
+           tmp->priority= doodad->any.priority;
+           tmp->u.doodad= doodad;
+           tmp->next= NULL;
+           _XkbAddDrawable(&first,&last,tmp);
+       }
+    }
+    if (section!=NULL) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=section->doodads;i<section->num_doodads;i++,doodad++) {
+           tmp= _XkbTypedCalloc(1,XkbDrawableRec);
+           if (!tmp) {
+               XkbFreeOrderedDrawables(first);
+               return NULL;
+           }
+           tmp->type= XkbDW_Doodad;
+           tmp->priority= doodad->any.priority;
+           tmp->u.doodad= doodad;
+           tmp->next= NULL;
+           _XkbAddDrawable(&first,&last,tmp);
+       }
+    }
+    return first;
+}
+
+void
+XkbFreeOrderedDrawables(XkbDrawablePtr draw)
+{
+XkbDrawablePtr tmp;
+
+   for (;draw!=NULL;draw=tmp) {
+       tmp= draw->next;
+       _XkbFree(draw);
+   }
+   return;
+}
diff --git a/src/xkberrs.c b/src/xkberrs.c
new file mode 100644 (file)
index 0000000..f28f02b
--- /dev/null
@@ -0,0 +1,77 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBfile.h>
+
+const char *   _XkbErrMessages[] = {
+       "success",                              /* _XkbSuccess               */
+       "key names not defined",                /* _XkbErrMissingNames       */
+       "key types not defined",                /* _XkbErrMissingTypes       */
+       "required key types not present",       /* _XkbErrMissingReqTypes    */
+       "symbols not defined",                  /* _XkbErrMissingSymbols     */
+       "virtual modifier bindings not defined",/* _XkbErrMissingVMods       */
+       "indicators not defined",               /* _XkbErrMissingIndicators  */
+       "compatibility map not defined",        /* _XkbErrMissingCompatMap   */
+       "symbol interpretations not defined",   /* _XkbErrMissingSymInterps  */
+       "geometry not defined",                 /* _XkbErrMissingGeometry    */
+       "illegal doodad type",                  /* _XkbErrIllegalDoodad      */
+       "illegal TOC type",                     /* _XkbErrIllegalTOCType     */
+       "illegal contents",                     /* _XkbErrIllegalContents    */
+       "empty file",                           /* _XkbErrEmptyFile          */
+       "file not found",                       /* _XkbErrFileNotFound       */
+       "cannot open",                          /* _XkbErrFileCannotOpen     */
+       "bad value",                            /* _XkbErrBadValue           */
+       "bad match",                            /* _XkbErrBadMatch           */
+       "illegal name for type",                /* _XkbErrBadTypeName        */
+       "illegal width for type",               /* _XkbErrBadTypeWidth       */
+       "bad file type",                        /* _XkbErrBadFileType        */
+       "bad file version",                     /* _XkbErrBadFileVersion     */
+       "error in Xkm file",                    /* _XkbErrBadFileFormat      */
+       "allocation failed",                    /* _XkbErrBadAlloc           */
+       "bad length",                           /* _XkbErrBadLength          */
+       "X request failed",                     /* _XkbErrXReqFailure        */
+       "not implemented"                       /* _XkbErrBadImplementation  */
+};
+
+unsigned       _XkbErrCode;
+const char *   _XkbErrLocation= NULL;
+unsigned       _XkbErrData;
+
diff --git a/src/xkbmisc.c b/src/xkbmisc.c
new file mode 100644 (file)
index 0000000..e0b9bd6
--- /dev/null
@@ -0,0 +1,674 @@
+/************************************************************
+ Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+#else
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS 1
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBgeom.h>
+#include "xkb.h"
+
+#endif
+
+unsigned
+_XkbKSCheckCase(KeySym ks)
+{
+unsigned       set,rtrn;
+
+    set= (ks & (~0xff)) >> 8;
+    rtrn= 0;
+    switch (set) {
+       case 0:         /* latin 1 */
+           if (((ks>=XK_A)&&(ks<=XK_Z))||
+               ((ks>=XK_Agrave)&&(ks<=XK_THORN)&&(ks!=XK_multiply))) {
+               rtrn|= _XkbKSUpper;
+           }
+           if (((ks>=XK_a)&&(ks<=XK_z))||
+               ((ks>=XK_agrave)&&(ks<=XK_ydiaeresis))) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+       case 1:         /* latin 2 */
+           if (((ks>=XK_Aogonek)&&(ks<=XK_Zabovedot)&&(ks!=XK_breve))||
+               ((ks>=XK_Racute)&&(ks<=XK_Tcedilla))) {
+               rtrn|= _XkbKSUpper;
+           }
+           if (((ks>=XK_aogonek)&&(ks<=XK_zabovedot)&&(ks!=XK_caron))||
+               ((ks>=XK_racute)&&(ks<=XK_tcedilla))) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+       case 2:         /* latin 3 */
+           if (((ks>=XK_Hstroke)&&(ks<=XK_Jcircumflex))||
+               ((ks>=XK_Cabovedot)&&(ks<=XK_Scircumflex))) {
+               rtrn|= _XkbKSUpper;
+           }
+           if (((ks>=XK_hstroke)&&(ks<=XK_jcircumflex))||
+               ((ks>=XK_cabovedot)&&(ks<=XK_scircumflex))) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+       case 3:         /* latin 4 */
+           if (((ks>=XK_Rcedilla)&&(ks<=XK_Tslash))||
+               (ks==XK_ENG)||
+               ((ks>=XK_Amacron)&&(ks<=XK_Umacron))) {
+               rtrn|= _XkbKSUpper;
+           }
+           if (((ks>=XK_rcedilla)&&(ks<=XK_tslash))||
+               (ks==XK_eng)||
+               ((ks>=XK_amacron)&&(ks<=XK_umacron))) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+       case 18:                /* latin 8 */
+           if ((ks==XK_Babovedot)||
+                ((ks>=XK_Dabovedot)&&(ks<=XK_Wacute))||
+               ((ks>=XK_Ygrave)&&(ks<=XK_Fabovedot))||
+               (ks==XK_Mabovedot)||
+               (ks==XK_Pabovedot)||
+               (ks==XK_Sabovedot)||
+               (ks==XK_Wdiaeresis)||
+               ((ks>=XK_Wcircumflex)&&(ks<=XK_Ycircumflex))) {
+               rtrn|= _XkbKSUpper;
+           }
+           if ((ks==XK_babovedot)||
+               (ks==XK_dabovedot)||
+               (ks==XK_fabovedot)||
+               (ks==XK_mabovedot)||
+                ((ks>=XK_wgrave)&&(ks<=XK_wacute))||
+               (ks==XK_ygrave)||
+               ((ks>=XK_wdiaeresis)&&(ks<=XK_ycircumflex))) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+       case 19:                /* latin 9 */
+           if ((ks==XK_OE)||(ks==XK_Ydiaeresis)) {
+               rtrn|= _XkbKSUpper;
+           }
+           if (ks==XK_oe) {
+               rtrn|= _XkbKSLower;
+           }
+           break;
+    }
+    return rtrn;
+}
+
+/***===================================================================***/
+
+Bool
+XkbLookupGroupAndLevel(        XkbDescPtr      xkb,
+                       int             key,
+                       int *           mods_inout,
+                       int *           grp_inout,
+                       int *           lvl_rtrn)
+{
+int            nG,eG;
+
+    if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout))
+       return False;
+
+    nG= XkbKeyNumGroups(xkb,key);
+    eG= *grp_inout;
+
+    if ( nG==0 ) {
+       *grp_inout= 0;
+       if (lvl_rtrn!=NULL)
+           *lvl_rtrn= 0;
+       return False;
+    }
+    else if ( nG==1 ) {
+       eG= 0;
+    }
+    else if ( eG>=nG ) {
+       unsigned gI= XkbKeyGroupInfo(xkb,key);
+       switch (XkbOutOfRangeGroupAction(gI)) {
+           default:
+               eG %= nG;
+               break;
+           case XkbClampIntoRange:
+               eG = nG-1;
+               break;
+           case XkbRedirectIntoRange:
+               eG = XkbOutOfRangeGroupNumber(gI);
+               if (eG>=nG)
+                   eG= 0;
+               break;
+       }
+    }
+    *grp_inout= eG;
+    if (mods_inout!=NULL) {
+       XkbKeyTypePtr   type;
+       int             preserve;
+
+       type = XkbKeyKeyType(xkb,key,eG);
+       if (lvl_rtrn!=NULL)
+           *lvl_rtrn= 0;
+       preserve= 0;
+       if (type->map) { /* find the shift level */
+           register int i;
+           register XkbKTMapEntryPtr entry;
+           for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
+               if ((entry->active)&&
+                       (((*mods_inout)&type->mods.mask)==entry->mods.mask)){
+                   if (lvl_rtrn!=NULL)
+                       *lvl_rtrn= entry->level;
+                   if (type->preserve)
+                       preserve= type->preserve[i].mask;
+                   break;
+               }
+           }
+       }
+       (*mods_inout)&= ~(type->mods.mask&(~preserve));
+    }
+    return True;
+}
+
+/***===================================================================***/
+
+static Bool
+XkbWriteSectionFromName(FILE *file, const char *sectionName, const char *name)
+{
+    fprintf(file,"    xkb_%-20s { include \"%s\" };\n",sectionName,name);
+    return True;
+}
+
+#define        NEED_DESC(n) ((!n)||((n)[0]=='+')||((n)[0]=='|')||(strchr((n),'%')))
+#define        COMPLETE(n)  ((n)&&(!NEED_DESC(n)))
+
+/* ARGSUSED */
+static void
+_AddIncl(      FILE *          file,
+               XkbFileInfo *   result,
+               Bool            topLevel,
+               Bool            showImplicit,
+               int             index,
+               void *          priv)
+{
+    if ((priv)&&(strcmp((char *)priv,"%")!=0))
+       fprintf(file,"    include \"%s\"\n",(char *)priv);
+    return;
+}
+
+Bool
+XkbWriteXKBKeymapForNames(     FILE *                  file,
+                               XkbComponentNamesPtr    names,
+                               Display *               dpy,
+                               XkbDescPtr              xkb,
+                               unsigned                want,
+                               unsigned                need)
+{
+char *         name,*tmp;
+unsigned       complete;
+XkbNamesPtr    old_names;
+int            multi_section;
+unsigned       wantNames,wantConfig,wantDflts;
+XkbFileInfo    finfo;
+
+    bzero(&finfo,sizeof(XkbFileInfo));
+
+    complete= 0;
+    if ((name=names->keymap)==NULL)    name= "default";
+    if (COMPLETE(names->keycodes))     complete|= XkmKeyNamesMask;
+    if (COMPLETE(names->types))                complete|= XkmTypesMask;
+    if (COMPLETE(names->compat))       complete|= XkmCompatMapMask;
+    if (COMPLETE(names->symbols))      complete|= XkmSymbolsMask;
+    if (COMPLETE(names->geometry))     complete|= XkmGeometryMask;
+    want|= (complete|need);
+    if (want&XkmSymbolsMask)
+       want|= XkmKeyNamesMask|XkmTypesMask;
+
+    if (want==0)
+       return False;
+
+    if (xkb!=NULL) {
+        old_names= xkb->names;
+        finfo.type= 0;
+        finfo.defined= 0;
+        finfo.xkb= xkb;
+        if (!XkbDetermineFileType(&finfo,XkbXKBFile,NULL))
+           return False;
+    }
+    else old_names= NULL;
+
+    wantConfig= want&(~complete);
+    if (xkb!=NULL) {
+       if (wantConfig&XkmTypesMask) {
+           if ((!xkb->map) || (xkb->map->num_types<XkbNumRequiredTypes))
+               wantConfig&= ~XkmTypesMask;
+       }
+       if (wantConfig&XkmCompatMapMask) {
+           if ((!xkb->compat) || (xkb->compat->num_si<1))
+               wantConfig&= ~XkmCompatMapMask;
+       }
+       if (wantConfig&XkmSymbolsMask) {
+           if ((!xkb->map) || (!xkb->map->key_sym_map))
+               wantConfig&= ~XkmSymbolsMask;
+       }
+       if (wantConfig&XkmIndicatorsMask) {
+           if (!xkb->indicators)
+               wantConfig&= ~XkmIndicatorsMask;
+       }
+       if (wantConfig&XkmKeyNamesMask) {
+           if ((!xkb->names)||(!xkb->names->keys))
+               wantConfig&= ~XkmKeyNamesMask;
+       }
+       if ((wantConfig&XkmGeometryMask)&&(!xkb->geom))
+           wantConfig&= ~XkmGeometryMask;
+    }
+    else {
+       wantConfig= 0;
+    }
+    complete|= wantConfig;
+
+    wantDflts= 0;
+    wantNames= want&(~complete);
+    if ((xkb!=NULL) && (old_names!=NULL)) {
+       if (wantNames&XkmTypesMask) {
+           if (old_names->types!=None) {
+               tmp= XkbAtomGetString(dpy,old_names->types);
+               names->types= tmp;
+           }
+           else {
+               wantDflts|= XkmTypesMask;
+           }
+           complete|= XkmTypesMask;
+       }
+       if (wantNames&XkmCompatMapMask) {
+           if (old_names->compat!=None) {
+               tmp= XkbAtomGetString(dpy,old_names->compat);
+               names->compat= tmp;
+           }
+           else wantDflts|= XkmCompatMapMask;
+           complete|= XkmCompatMapMask;
+       }
+       if (wantNames&XkmSymbolsMask) {
+           if (old_names->symbols==None)
+               return False;
+           tmp= XkbAtomGetString(dpy,old_names->symbols);
+           names->symbols= tmp;
+           complete|= XkmSymbolsMask;
+       }
+       if (wantNames&XkmKeyNamesMask) {
+          if (old_names->keycodes!=None) {
+               tmp= XkbAtomGetString(dpy,old_names->keycodes);
+               names->keycodes= tmp;
+           }
+           else wantDflts|= XkmKeyNamesMask;
+           complete|= XkmKeyNamesMask;
+       }
+       if (wantNames&XkmGeometryMask) {
+           if (old_names->geometry==None)
+               return False;
+           tmp= XkbAtomGetString(dpy,old_names->geometry);
+           names->geometry= tmp;
+           complete|= XkmGeometryMask;
+           wantNames&= ~XkmGeometryMask;
+       }
+    }
+    if (complete&XkmCompatMapMask)
+       complete|= XkmIndicatorsMask|XkmVirtualModsMask;
+    else if (complete&(XkmSymbolsMask|XkmTypesMask))
+       complete|= XkmVirtualModsMask;
+    if (need & (~complete))
+       return False;
+    if ((complete&XkmSymbolsMask)&&((XkmKeyNamesMask|XkmTypesMask)&(~complete)))
+       return False;
+
+    multi_section= 1;
+    if (((complete&XkmKeymapRequired)==XkmKeymapRequired)&&
+       ((complete&(~XkmKeymapLegal))==0)) {
+       fprintf(file,"xkb_keymap \"%s\" {\n",name);
+    }
+    else if (((complete&XkmSemanticsRequired)==XkmSemanticsRequired)&&
+       ((complete&(~XkmSemanticsLegal))==0)) {
+       fprintf(file,"xkb_semantics \"%s\" {\n",name);
+    }
+    else if (((complete&XkmLayoutRequired)==XkmLayoutRequired)&&
+       ((complete&(~XkmLayoutLegal))==0)) {
+       fprintf(file,"xkb_layout \"%s\" {\n",name);
+    }
+    else if (XkmSingleSection(complete&(~XkmVirtualModsMask))) {
+       multi_section= 0;
+    }
+    else {
+       return False;
+    }
+
+    wantNames= complete&(~(wantConfig|wantDflts));
+    name= names->keycodes;
+    if (wantConfig&XkmKeyNamesMask)
+       XkbWriteXKBKeycodes(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmKeyNamesMask)
+       fprintf(stderr,"Default symbols not implemented yet!\n");
+    else if (wantNames&XkmKeyNamesMask)
+       XkbWriteSectionFromName(file,"keycodes",name);
+
+    name= names->types;
+    if (wantConfig&XkmTypesMask)
+       XkbWriteXKBKeyTypes(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmTypesMask)
+       fprintf(stderr,"Default types not implemented yet!\n");
+    else if (wantNames&XkmTypesMask)
+       XkbWriteSectionFromName(file,"types",name);
+
+    name= names->compat;
+    if (wantConfig&XkmCompatMapMask)
+       XkbWriteXKBCompatMap(file,&finfo,False,False,_AddIncl,name);
+    else if (wantDflts&XkmCompatMapMask)
+       fprintf(stderr,"Default interps not implemented yet!\n");
+    else if (wantNames&XkmCompatMapMask)
+       XkbWriteSectionFromName(file,"compatibility",name);
+
+    name= names->symbols;
+    if (wantConfig&XkmSymbolsMask)
+       XkbWriteXKBSymbols(file,&finfo,False,False,_AddIncl,name);
+    else if (wantNames&XkmSymbolsMask)
+       XkbWriteSectionFromName(file,"symbols",name);
+
+    name= names->geometry;
+    if (wantConfig&XkmGeometryMask)
+       XkbWriteXKBGeometry(file,&finfo,False,False,_AddIncl,name);
+    else if (wantNames&XkmGeometryMask)
+       XkbWriteSectionFromName(file,"geometry",name);
+
+    if (multi_section)
+       fprintf(file,"};\n");
+    return True;
+}
+
+/***====================================================================***/
+
+/*ARGSUSED*/
+Status
+XkbMergeFile(XkbDescPtr xkb,XkbFileInfo finfo)
+{
+    return BadImplementation;
+}
+
+/***====================================================================***/
+
+int
+XkbFindKeycodeByName(XkbDescPtr xkb,char *name,Bool use_aliases)
+{
+register int   i;
+
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys))
+       return 0;
+    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+       if (strncmp(xkb->names->keys[i].name,name,XkbKeyNameLength)==0)
+           return i;
+    }
+    if (!use_aliases)
+       return 0;
+    if (xkb->geom && xkb->geom->key_aliases) {
+       XkbKeyAliasPtr  a;
+       a= xkb->geom->key_aliases;
+       for (i=0;i<xkb->geom->num_key_aliases;i++,a++) {
+           if (strncmp(name,a->alias,XkbKeyNameLength)==0)
+               return XkbFindKeycodeByName(xkb,a->real,False);
+       }
+    }
+    if (xkb->names && xkb->names->key_aliases) {
+       XkbKeyAliasPtr  a;
+       a= xkb->names->key_aliases;
+       for (i=0;i<xkb->names->num_key_aliases;i++,a++) {
+           if (strncmp(name,a->alias,XkbKeyNameLength)==0)
+               return XkbFindKeycodeByName(xkb,a->real,False);
+       }
+    }
+    return 0;
+}
+
+
+unsigned
+XkbConvertGetByNameComponents(Bool toXkm,unsigned orig)
+{
+unsigned       rtrn;
+
+    rtrn= 0;
+    if (toXkm) {
+       if (orig&XkbGBN_TypesMask)              rtrn|= XkmTypesMask;
+       if (orig&XkbGBN_CompatMapMask)          rtrn|= XkmCompatMapMask;
+       if (orig&XkbGBN_SymbolsMask)            rtrn|= XkmSymbolsMask;
+       if (orig&XkbGBN_IndicatorMapMask)       rtrn|= XkmIndicatorsMask;
+       if (orig&XkbGBN_KeyNamesMask)           rtrn|= XkmKeyNamesMask;
+       if (orig&XkbGBN_GeometryMask)           rtrn|= XkmGeometryMask;
+    }
+    else {
+       if (orig&XkmTypesMask)                  rtrn|= XkbGBN_TypesMask;
+       if (orig&XkmCompatMapMask)              rtrn|= XkbGBN_CompatMapMask;
+       if (orig&XkmSymbolsMask)                rtrn|= XkbGBN_SymbolsMask;
+       if (orig&XkmIndicatorsMask)             rtrn|= XkbGBN_IndicatorMapMask;
+       if (orig&XkmKeyNamesMask)               rtrn|= XkbGBN_KeyNamesMask;
+       if (orig&XkmGeometryMask)               rtrn|= XkbGBN_GeometryMask;
+       if (orig!=0)                            rtrn|= XkbGBN_OtherNamesMask;
+    }
+    return rtrn;
+}
+
+unsigned
+XkbConvertXkbComponents(Bool toXkm,unsigned orig)
+{
+unsigned       rtrn;
+
+    rtrn= 0;
+    if (toXkm) {
+       if (orig&XkbClientMapMask)      rtrn|= XkmTypesMask|XkmSymbolsMask;
+       if (orig&XkbServerMapMask)      rtrn|= XkmTypesMask|XkmSymbolsMask;
+       if (orig&XkbCompatMapMask)      rtrn|= XkmCompatMapMask;
+       if (orig&XkbIndicatorMapMask)   rtrn|= XkmIndicatorsMask;
+       if (orig&XkbNamesMask)          rtrn|= XkmKeyNamesMask;
+       if (orig&XkbGeometryMask)       rtrn|= XkmGeometryMask;
+    }
+    else {
+       if (orig!=0)                    rtrn|= XkbNamesMask;
+       if (orig&XkmTypesMask)          rtrn|= XkbClientMapMask;
+       if (orig&XkmCompatMapMask)
+               rtrn|= XkbCompatMapMask|XkbIndicatorMapMask;
+       if (orig&XkmSymbolsMask)        rtrn|=XkbClientMapMask|XkbServerMapMask;
+       if (orig&XkmIndicatorsMask)     rtrn|= XkbIndicatorMapMask;
+       if (orig&XkmKeyNamesMask)
+               rtrn|= XkbNamesMask|XkbIndicatorMapMask;
+       if (orig&XkmGeometryMask)       rtrn|= XkbGeometryMask;
+    }
+    return rtrn;
+}
+
+Bool
+XkbDetermineFileType(XkbFileInfoPtr finfo,int format,int *opts_missing)
+{
+unsigned       present;
+XkbDescPtr     xkb;
+
+    if ((!finfo)||(!finfo->xkb))
+       return False;
+    if (opts_missing)
+       *opts_missing= 0;
+    xkb= finfo->xkb;
+    present= 0;
+    if ((xkb->names)&&(xkb->names->keys))      present|= XkmKeyNamesMask;
+    if ((xkb->map)&&(xkb->map->types))         present|= XkmTypesMask;
+    if (xkb->compat)                           present|= XkmCompatMapMask;
+    if ((xkb->map)&&(xkb->map->num_syms>1))    present|= XkmSymbolsMask;
+    if (xkb->indicators)                       present|= XkmIndicatorsMask;
+    if (xkb->geom)                             present|= XkmGeometryMask;
+    if (!present)
+       return False;
+    else switch (present) {
+       case XkmKeyNamesMask:
+           finfo->type=        XkmKeyNamesIndex;
+           finfo->defined=     present;
+           return True;
+       case XkmTypesMask:
+           finfo->type=        XkmTypesIndex;
+           finfo->defined=     present;
+           return True;
+       case XkmCompatMapMask:
+           finfo->type=        XkmCompatMapIndex;
+           finfo->defined=     present;
+           return True;
+       case XkmSymbolsMask:
+           if (format!=XkbXKMFile) {
+               finfo->type=    XkmSymbolsIndex;
+               finfo->defined= present;
+               return True;
+           }
+           break;
+       case XkmGeometryMask:
+           finfo->type=        XkmGeometryIndex;
+           finfo->defined=     present;
+           return True;
+    }
+    if ((present&(~XkmSemanticsLegal))==0) {
+       if ((XkmSemanticsRequired&present)==XkmSemanticsRequired) {
+           if (opts_missing)
+               *opts_missing= XkmSemanticsOptional&(~present);
+           finfo->type=        XkmSemanticsFile;
+           finfo->defined=     present;
+           return True;
+       }
+    }
+    else if ((present&(~XkmLayoutLegal))==0) {
+       if ((XkmLayoutRequired&present)==XkmLayoutRequired) {
+           if (opts_missing)
+               *opts_missing= XkmLayoutOptional&(~present);
+           finfo->type=        XkmLayoutFile;
+           finfo->defined=     present;
+           return True;
+       }
+    }
+    else if ((present&(~XkmKeymapLegal))==0) {
+       if ((XkmKeymapRequired&present)==XkmKeymapRequired) {
+           if (opts_missing)
+               *opts_missing= XkmKeymapOptional&(~present);
+           finfo->type=        XkmKeymapFile;
+           finfo->defined=     present;
+           return True;
+       }
+    }
+    return False;
+}
+
+/* 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');
+}
+
+#ifdef NEED_STRCASECMP
+_X_HIDDEN int
+_XkbStrCaseCmp(char *str1,char *str2)
+{
+    const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2;
+
+    while (tolower(*us1) == tolower(*us2)) {
+        if (*us1++ == '\0')
+            return (0);
+        us2++;
+    }
+
+    return (tolower(*us1) - tolower(*us2));
+}
+#endif
diff --git a/src/xkbout.c b/src/xkbout.c
new file mode 100644 (file)
index 0000000..91cd1ba
--- /dev/null
@@ -0,0 +1,1069 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xfuncs.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+#else
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS 1
+#include <X11/extensions/XKBsrv.h>
+
+#include <X11/extensions/XKBgeom.h>
+#include <X11/extensions/XKBfile.h>
+
+#endif
+
+#define        VMOD_HIDE_VALUE 0
+#define        VMOD_SHOW_VALUE 1
+#define        VMOD_COMMENT_VALUE 2
+
+static Bool
+WriteXKBVModDecl(FILE *file,Display *dpy,XkbDescPtr xkb,int showValue)
+{
+register int   i,nMods;
+Atom *         vmodNames;
+
+    if (xkb==NULL)
+       return False;
+    if (xkb->names!=NULL)
+        vmodNames= xkb->names->vmods;
+    else vmodNames= NULL;
+
+    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(dpy,vmodNames[i],XkbXKBFile));
+           if ((showValue!=VMOD_HIDE_VALUE)&&
+               (xkb->server)&&(xkb->server->vmods[i]!=XkbNoModifierMask)) {
+               if (showValue==VMOD_COMMENT_VALUE) {
+                   fprintf(file,"/* = %s */",
+                       XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
+               }
+               else  {
+                   fprintf(file,"= %s",
+                       XkbModMaskText(xkb->server->vmods[i],XkbXKBFile));
+               }
+           }
+           nMods++;
+       }
+    }
+    if (nMods>0)
+       fprintf(file,";\n\n");
+    return True;
+}
+
+/***====================================================================***/
+
+static Bool
+WriteXKBAction(FILE *file,XkbFileInfo *result,XkbAnyAction *action)
+{
+XkbDescPtr     xkb;
+Display *      dpy;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    fprintf(file,"%s",XkbActionText(dpy,xkb,(XkbAction *)action,XkbXKBFile));
+    return True;
+}
+
+/***====================================================================***/
+
+Bool
+XkbWriteXKBKeycodes(   FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Atom                   kcName;
+register unsigned      i;
+XkbDescPtr             xkb;
+Display *              dpy;
+const char *           alternate;
+
+    xkb= result->xkb;
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
+       _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBKeycodes",0);
+       return False;
+    }
+    dpy= xkb->dpy;
+    kcName= xkb->names->keycodes;
+    if (kcName!=None)
+        fprintf(file,"xkb_keycodes \"%s\" {\n",
+                                       XkbAtomText(dpy,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);
+    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,
+                       XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile),
+                       i);
+       }
+    }
+    if (xkb->indicators!=NULL) {
+       for (i=0;i<XkbNumIndicators;i++) {
+           const char *type;
+           if (xkb->indicators->phys_indicators&(1<<i))
+                       type= "    ";
+           else        type= "    virtual ";
+           if (xkb->names->indicators[i]!=None) {
+               fprintf(file,"%sindicator %d = \"%s\";\n",type,i+1,
+                       XkbAtomText(dpy,xkb->names->indicators[i],XkbXKBFile));
+           }
+       }
+    }
+    if (xkb->names->key_aliases!=NULL) {
+       XkbKeyAliasPtr  pAl;
+       pAl= xkb->names->key_aliases;
+       for (i=0;i<xkb->names->num_key_aliases;i++,pAl++) {
+           fprintf(file,"    alias %6s = %6s;\n",
+                       XkbKeyNameText(pAl->alias,XkbXKBFile),
+                       XkbKeyNameText(pAl->real,XkbXKBFile));
+       }
+    }
+    if (addOn)
+       (*addOn)(file,result,topLevel,showImplicit,XkmKeyNamesIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBKeyTypes(   FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Display *              dpy;
+register unsigned      i,n;
+XkbKeyTypePtr          type;
+XkbKTMapEntryPtr       entry;
+XkbDescPtr             xkb;
+
+    xkb= result->xkb;
+    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
+       _XkbLibError(_XkbErrMissingTypes,"XkbWriteXKBKeyTypes",0);
+       return False;
+    }
+    dpy= xkb->dpy;
+    if (xkb->map->num_types<XkbNumRequiredTypes) {
+       _XkbLibError(_XkbErrMissingReqTypes,"XkbWriteXKBKeyTypes",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",
+                       XkbAtomText(dpy,xkb->names->types,XkbXKBFile));
+    WriteXKBVModDecl(file,dpy,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",
+               XkbAtomText(dpy,type->name,XkbXKBFile));
+       fprintf(file,"        modifiers= %s;\n",
+              XkbVModMaskText(dpy,xkb,type->mods.real_mods,type->mods.vmods,
+                                                               XkbXKBFile));
+       entry= type->map;
+       for (n=0;n<type->map_count;n++,entry++) {
+           char *str;
+           str=XkbVModMaskText(dpy,xkb,entry->mods.real_mods,entry->mods.vmods,
+                                                               XkbXKBFile);
+           fprintf(file,"        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(dpy,xkb,
+                                       type->preserve[n].real_mods,
+                                       type->preserve[n].vmods,
+                                       XkbXKBFile));
+           }
+       }
+       if (type->level_names!=NULL) {
+           Atom *name= type->level_names;
+           for (n=0;n<type->num_levels;n++,name++) {
+               if ((*name)==None)
+                   continue;
+               fprintf(file,"        level_name[Level%d]= \"%s\";\n",n+1,
+                                       XkbAtomText(dpy,*name,XkbXKBFile));
+           }
+       }
+       fprintf(file,"    };\n");
+    }
+    if (addOn)
+       (*addOn)(file,result,topLevel,showImplicit,XkmTypesIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteXKBIndicatorMap(  FILE *                  file,
+                       XkbFileInfo *           result,
+                       Atom                    name,
+                       XkbIndicatorMapPtr      led,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+XkbDescPtr     xkb;
+char *tmp;
+
+    xkb= result->xkb;
+    tmp = XkbAtomGetString(xkb->dpy, name);
+    fprintf(file,"    indicator \"%s\" {\n",tmp);
+    _XkbFree(tmp);
+    if (led->flags&XkbIM_NoExplicit)
+       fprintf(file,"        !allowExplicit;\n");
+    if (led->flags&XkbIM_LEDDrivesKB)
+       fprintf(file,"        indicatorDrivesKeyboard;\n");
+    if (led->which_groups!=0) {
+       if (led->which_groups!=XkbIM_UseEffective) {
+           fprintf(file,"        whichGroupState= %s;\n",
+                       XkbIMWhichStateMaskText(led->which_groups,XkbXKBFile));
+       }
+       fprintf(file,"        groups= 0x%02x;\n",led->groups);
+    }
+    if (led->which_mods!=0) {
+       if (led->which_mods!=XkbIM_UseEffective) {
+           fprintf(file,"        whichModState= %s;\n",
+                       XkbIMWhichStateMaskText(led->which_mods,XkbXKBFile));
+       }
+       fprintf(file,"        modifiers= %s;\n",
+                       XkbVModMaskText(xkb->dpy,xkb,
+                                       led->mods.real_mods,led->mods.vmods,
+                                       XkbXKBFile));
+    }
+    if (led->ctrls!=0) {
+       fprintf(file,"        controls= %s;\n",
+                       XkbControlsMaskText(led->ctrls,XkbXKBFile));
+    }
+    if (addOn)
+       (*addOn)(file,result,False,True,XkmIndicatorsIndex,priv);
+    fprintf(file,"    };\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBCompatMap(  FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Display *              dpy;
+register unsigned      i;
+XkbSymInterpretPtr     interp;
+XkbDescPtr             xkb;
+
+    xkb= result->xkb;
+    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
+       _XkbLibError(_XkbErrMissingCompatMap,"XkbWriteXKBCompatMap",0);
+       return False;
+    }
+    dpy= xkb->dpy;
+    if ((xkb->names==NULL)||(xkb->names->compat==None))
+        fprintf(file,"xkb_compatibility {\n\n");
+    else fprintf(file,"xkb_compatibility \"%s\" {\n\n",
+                       XkbAtomText(dpy,xkb->names->compat,XkbXKBFile));
+    WriteXKBVModDecl(file,dpy,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");
+    interp= xkb->compat->sym_interpret;
+    for (i=0;i<xkb->compat->num_si;i++,interp++) {
+       fprintf(file,"    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",
+               XkbVModIndexText(dpy,xkb,interp->virtual_mod,XkbXKBFile));
+       }
+       if (interp->match&XkbSI_LevelOneOnly)
+           fprintf(file,"        useModMapMods=level1;\n");
+       if (interp->flags&XkbSI_LockingKey)
+           fprintf(file,"        locking= True;\n");
+       if (interp->flags&XkbSI_AutoRepeat)
+           fprintf(file,"        repeat= True;\n");
+       fprintf(file,"        action= ");
+       WriteXKBAction(file,result,&interp->act);
+       fprintf(file,";\n");
+       fprintf(file,"    };\n");
+    }
+    for (i=0;i<XkbNumKbdGroups;i++) {
+       XkbModsPtr      gc;
+
+       gc= &xkb->compat->groups[i];
+       if ((gc->real_mods==0)&&(gc->vmods==0))
+           continue;
+       fprintf(file,"    group %d = %s;\n",i+1,XkbVModMaskText(xkb->dpy,xkb,
+                                                       gc->real_mods,gc->vmods,
+                                                       XkbXKBFile));
+    }
+    if (xkb->indicators) {
+       for (i=0;i<XkbNumIndicators;i++) {
+           XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+           if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
+               (map->which_mods!=0)||
+               (map->mods.real_mods!=0)||(map->mods.vmods!=0)||
+               (map->ctrls!=0)) {
+               WriteXKBIndicatorMap(file,result,xkb->names->indicators[i],map,
+                                                               addOn,priv);
+           }
+       }
+    }
+    if (addOn)
+       (*addOn)(file,result,topLevel,showImplicit,XkmCompatMapIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+Bool
+XkbWriteXKBSymbols(    FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Display *              dpy;
+register unsigned      i,tmp;
+XkbDescPtr             xkb;
+XkbClientMapPtr                map;
+XkbServerMapPtr                srv;
+Bool                   showActions;
+
+    xkb= result->xkb;
+
+    if ((!xkb)||(!xkb->map)||(!xkb->map->syms)||(!xkb->map->key_sym_map)) {
+       _XkbLibError(_XkbErrMissingSymbols,"XkbWriteXKBSymbols",0);
+       return False;
+    }
+    if ((!xkb->names)||(!xkb->names->keys)) {
+       _XkbLibError(_XkbErrMissingNames,"XkbWriteXKBSymbols",0);
+       return False;
+    }
+
+    map= xkb->map;
+    srv= xkb->server;
+    dpy= xkb->dpy;
+
+    if ((xkb->names==NULL)||(xkb->names->symbols==None))
+        fprintf(file,"xkb_symbols {\n\n");
+    else fprintf(file,"xkb_symbols \"%s\" {\n\n",
+                       XkbAtomText(dpy,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,
+                       XkbAtomText(dpy,xkb->names->groups[i],XkbXKBFile));
+           tmp++;
+       }
+    }
+    if (tmp>0)
+       fprintf(file,"\n");
+    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+       Bool    simple;
+       if ((int)XkbKeyNumSyms(xkb,i)<1)
+           continue;
+       if (XkbFindKeycodeByName(xkb,xkb->names->keys[i].name,True)!=i)
+           continue;
+       simple= True;
+       fprintf(file,"    key %6s {",
+                       XkbKeyNameText(xkb->names->keys[i].name,XkbXKBFile));
+       if (srv->explicit) {
+           if (((srv->explicit[i]&XkbExplicitKeyTypesMask)!=0)||
+                                                       (showImplicit)) {
+               int     typeNdx,g;
+               Bool    multi;
+               const char *    comment="  ";
+
+               if ((srv->explicit[i]&XkbExplicitKeyTypesMask)==0)
+                   comment= "//";
+               multi= False;
+               typeNdx= XkbKeyKeyTypeIndex(xkb,i,0);
+               for (g=1;(g<XkbKeyNumGroups(xkb,i))&&(!multi);g++) {
+                   if (XkbKeyKeyTypeIndex(xkb,i,g)!=typeNdx)
+                       multi= True;
+               }
+               if (multi) {
+                   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\",",
+                               comment,g+1,
+                               XkbAtomText(dpy,map->types[typeNdx].name,
+                               XkbXKBFile));
+                       }
+                       else if (showImplicit) {
+                           fprintf(file,"\n//      type[group%d]= \"%s\",",g+1,
+                               XkbAtomText(dpy,map->types[typeNdx].name,
+                               XkbXKBFile));
+                       }
+                   }
+               }
+               else {
+                   fprintf(file,"\n%s      type= \"%s\",",comment,
+                               XkbAtomText(dpy,map->types[typeNdx].name,
+                               XkbXKBFile));
+               }
+               simple= False;
+           }
+           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,");
+               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,",
+                               XkbVModMaskText(dpy,xkb,0,
+                                               xkb->server->vmodmap[i],
+                                               XkbXKBFile));
+               }
+               else if (showImplicit) {
+                   fprintf(file,"\n//      virtualMods= %s,",
+                               XkbVModMaskText(dpy,xkb,0,
+                                               xkb->server->vmodmap[i],
+                                               XkbXKBFile));
+               }
+           }
+       }
+       switch (XkbOutOfRangeGroupAction(XkbKeyGroupInfo(xkb,i))) {
+           case XkbClampIntoRange:
+               fprintf(file,"\n        groupsClamp,");
+               break;
+           case XkbRedirectIntoRange:
+               fprintf(file,"\n        groupsRedirect= Group%d,",
+                       XkbOutOfRangeGroupNumber(XkbKeyGroupInfo(xkb,i))+1);
+               break;
+       }
+       if (srv->behaviors!=NULL) {
+           unsigned type;
+           type= srv->behaviors[i].type&XkbKB_OpMask;
+
+           if (type!=XkbKB_Default) {
+               simple= False;
+               fprintf(file,"\n        %s,",
+                       XkbBehaviorText(xkb,&srv->behaviors[i],XkbXKBFile));
+           }
+       }
+       if ((srv->explicit==NULL) || showImplicit ||
+           ((srv->explicit[i]&XkbExplicitInterpretMask)!=0))
+            showActions= XkbKeyHasActions(xkb,i);
+       else showActions= False;
+
+       if (((unsigned)XkbKeyNumGroups(xkb,i)>1)||showActions)
+           simple= False;
+       if (simple) {
+           KeySym *syms;
+           unsigned s;
+
+           syms= XkbKeySymsPtr(xkb,i);
+           fprintf(file,"         [ ");
+           for (s=0;s<XkbKeyGroupWidth(xkb,i,XkbGroup1Index);s++) {
+               if (s!=0)
+                   fprintf(file,", ");
+               fprintf(file,"%15s",XkbKeysymText(*syms++,XkbXKBFile));
+           }
+           fprintf(file," ] };\n");
+       }
+       else {
+           unsigned g,s;
+           KeySym *syms;
+           XkbAction *acts;
+           syms= XkbKeySymsPtr(xkb,i);
+           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);
+               for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
+                   if (s!=0)
+                       fprintf(file,", ");
+                   fprintf(file,"%15s",XkbKeysymText(syms[s],XkbXKBFile));
+               }
+               fprintf(file," ]");
+               syms+= XkbKeyGroupsWidth(xkb,i);
+               if (showActions) {
+                   fprintf(file,",\n        actions[Group%d]= [ ",g+1);
+                   for (s=0;s<XkbKeyGroupWidth(xkb,i,g);s++) {
+                       if (s!=0)
+                           fprintf(file,", ");
+                       WriteXKBAction(file,result,(XkbAnyAction *)&acts[s]);
+                   }
+                   fprintf(file," ]");
+                   acts+= XkbKeyGroupsWidth(xkb,i);
+               }
+           }
+           fprintf(file,"\n    };\n");
+       }
+    }
+    if (map && map->modmap) {
+       for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+           if (map->modmap[i]!=0) {
+               register int n,bit;
+               for (bit=1,n=0;n<XkbNumModifiers;n++,bit<<=1) {
+                   if (map->modmap[i]&bit) {
+                       char buf[5];
+                       memcpy(buf,xkb->names->keys[i].name,4);
+                       buf[4]= '\0';
+                       fprintf(file,"    modifier_map %s { <%s> };\n",
+                                       XkbModIndexText(n,XkbXKBFile),buf);
+                   }
+               }
+           }
+       }
+    }
+    if (addOn)
+       (*addOn)(file,result,topLevel,showImplicit,XkmSymbolsIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+static Bool
+WriteXKBOutline(       FILE *          file,
+                       XkbShapePtr     shape,
+                       XkbOutlinePtr   outline,
+                       int             lastRadius,
+                       int             first,
+                       int             indent)
+{
+register int   i;
+XkbPointPtr    pt;
+char *         iStr;
+
+    fprintf(file,"%s",iStr= XkbIndentText(first));
+    if (first!=indent)
+       iStr= XkbIndentText(indent);
+    if (outline->corner_radius!=lastRadius) {
+       fprintf(file,"corner= %s,",
+                       XkbGeomFPText(outline->corner_radius,XkbMessage));
+       if (shape!=NULL) {
+           fprintf(file,"\n%s",iStr);
+       }
+    }
+    if (shape) {
+       if (outline==shape->approx)
+           fprintf(file,"approx= ");
+       else if (outline==shape->primary)
+           fprintf(file,"primary= ");
+    }
+    fprintf(file,"{");
+    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),
+                                 XkbGeomFPText(pt->y,XkbXKBFile));
+    }
+    fprintf(file," }");
+    return True;
+}
+
+static Bool
+WriteXKBDoodad(        FILE *          file,
+               Display *       dpy,
+               unsigned        indent,
+               XkbGeometryPtr  geom,
+               XkbDoodadPtr    doodad)
+{
+register char *        i_str;
+XkbShapePtr    shape;
+XkbColorPtr    color;
+
+    i_str= XkbIndentText(indent);
+    fprintf(file,"%s%s \"%s\" {\n",i_str,
+                               XkbDoodadTypeText(doodad->any.type,XkbMessage),
+                               XkbAtomText(dpy,doodad->any.name,XkbMessage));
+    fprintf(file,"%s    top=      %s;\n",i_str,
+                                XkbGeomFPText(doodad->any.top,XkbXKBFile));
+    fprintf(file,"%s    left=     %s;\n",i_str,
+                               XkbGeomFPText(doodad->any.left,XkbXKBFile));
+    fprintf(file,"%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,
+                            XkbGeomFPText(doodad->shape.angle,XkbXKBFile));
+           }
+           if (doodad->shape.color_ndx!=0) {
+               fprintf(file,"%s    color= \"%s\";\n",i_str,
+                            XkbShapeDoodadColor(geom,&doodad->shape)->spec);
+           }
+           shape= XkbShapeDoodadShape(geom,&doodad->shape);
+           fprintf(file,"%s    shape= \"%s\";\n",i_str,
+                           XkbAtomText(dpy,shape->name,XkbXKBFile));
+           break;
+       case XkbTextDoodad:
+           if (doodad->text.angle!=0) {
+               fprintf(file,"%s    angle=  %s;\n",i_str,
+                            XkbGeomFPText(doodad->text.angle,XkbXKBFile));
+           }
+           if (doodad->text.width!=0) {
+               fprintf(file,"%s    width=  %s;\n",i_str,
+                            XkbGeomFPText(doodad->text.width,XkbXKBFile));
+
+           }
+           if (doodad->text.height!=0) {
+               fprintf(file,"%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,
+                            XkbStringText(color->spec,XkbXKBFile));
+           }
+           fprintf(file,"%s    XFont= \"%s\";\n",i_str,
+                            XkbStringText(doodad->text.font,XkbXKBFile));
+           fprintf(file,"%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,
+                           XkbStringText(color->spec,XkbXKBFile));
+           color= XkbIndicatorDoodadOffColor(geom,&doodad->indicator);
+           fprintf(file,"%s    offColor= \"%s\";\n",i_str,
+                           XkbStringText(color->spec,XkbXKBFile));
+           fprintf(file,"%s    shape= \"%s\";\n",i_str,
+                            XkbAtomText(dpy,shape->name,XkbXKBFile));
+           break;
+       case XkbLogoDoodad:
+           fprintf(file,"%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,
+                            XkbGeomFPText(doodad->logo.angle,XkbXKBFile));
+           }
+           if (doodad->shape.color_ndx!=0) {
+               fprintf(file,"%s    color= \"%s\";\n",i_str,
+                            XkbLogoDoodadColor(geom,&doodad->logo)->spec);
+           }
+           shape= XkbLogoDoodadShape(geom,&doodad->logo);
+           fprintf(file,"%s    shape= \"%s\";\n",i_str,
+                           XkbAtomText(dpy,shape->name,XkbXKBFile));
+           break;
+    }
+    fprintf(file,"%s};\n",i_str);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+WriteXKBOverlay(       FILE *          file,
+                       Display *       dpy,
+                       unsigned        indent,
+                       XkbGeometryPtr  geom,
+                       XkbOverlayPtr   ol)
+{
+register char *                i_str;
+int                    r,k,nOut;
+XkbOverlayRowPtr       row;
+XkbOverlayKeyPtr       key;
+
+    i_str= XkbIndentText(indent);
+    if (ol->name!=None) {
+        fprintf(file,"%soverlay \"%s\" {\n",i_str,
+                                       XkbAtomText(dpy,ol->name,XkbMessage));
+    }
+    else fprintf(file,"%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);
+           else if ((nOut%4)==0)
+                fprintf(file,",\n%s    %6s=%6s",i_str,under,over);
+           else fprintf(file,", %6s=%6s",under,over);
+           nOut++;
+       }
+    }
+    fprintf(file,"\n%s};\n",i_str);
+    return True;
+}
+
+static Bool
+WriteXKBSection(       FILE *          file,
+                       Display *       dpy,
+                       XkbSectionPtr   s,
+                       XkbGeometryPtr  geom)
+{
+register int   i;
+XkbRowPtr      row;
+int            dfltKeyColor = 0;
+
+    fprintf(file,"    section \"%s\" {\n",
+                               XkbAtomText(dpy,s->name,XkbXKBFile));
+    if (s->rows&&(s->rows->num_keys>0)) {
+       dfltKeyColor= s->rows->keys[0].color_ndx;
+       fprintf(file,"        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",
+                                       XkbGeomFPText(s->height,XkbXKBFile));
+    if (s->angle!=0) {
+       fprintf(file,"        angle=  %s;\n",
+                                       XkbGeomFPText(s->angle,XkbXKBFile));
+    }
+    for (i=0,row=s->rows;row&&i<s->num_rows;i++,row++) {
+       fprintf(file,"        row {\n");
+       fprintf(file,"            top=  %s;\n",
+                                       XkbGeomFPText(row->top,XkbXKBFile));
+       fprintf(file,"            left= %s;\n",
+                                       XkbGeomFPText(row->left,XkbXKBFile));
+       if (row->vertical)
+           fprintf(file,"            vertical;\n");
+       if (row->num_keys>0) {
+           register int        k;
+           register XkbKeyPtr  key;
+           int                 forceNL=0;
+           int                 nThisLine= 0;
+           fprintf(file,"            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,"                ");
+                    nThisLine= 0;
+               }
+               else if (((nThisLine%2)==1)||(forceNL)) {
+                    fprintf(file,",\n                ");
+                    forceNL= nThisLine= 0;
+               }
+               else {
+                    fprintf(file,", ");
+                    nThisLine++;
+               }
+               shape= XkbKeyShape(geom,key);
+               fprintf(file,"{ %6s, \"%s\", %3s",
+                     XkbKeyNameText(key->name.name,XkbXKBFile),
+                     XkbAtomText(dpy,shape->name,XkbXKBFile),
+                     XkbGeomFPText(key->gap,XkbXKBFile));
+               if (key->color_ndx!=dfltKeyColor) {
+                   fprintf(file,", color=\"%s\"",XkbKeyColor(geom,key)->spec);
+                   forceNL= 1;
+               }
+               fprintf(file," }");
+           }
+           fprintf(file,"\n            };\n");
+       }
+       fprintf(file,"        };\n");
+    }
+    if (s->doodads!=NULL) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=s->doodads;i<s->num_doodads;i++,doodad++) {
+           WriteXKBDoodad(file,dpy,8,geom,doodad);
+       }
+    }
+    if (s->overlays!=NULL) {
+       XkbOverlayPtr   ol;
+       for (i=0,ol=s->overlays;i<s->num_overlays;i++,ol++) {
+           WriteXKBOverlay(file,dpy,8,geom,ol);
+       }
+    }
+    fprintf(file,"    }; // End of \"%s\" section\n\n",
+                               XkbAtomText(dpy,s->name,XkbXKBFile));
+    return True;
+}
+
+Bool
+XkbWriteXKBGeometry(   FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Display *              dpy;
+register unsigned      i,n;
+XkbDescPtr             xkb;
+XkbGeometryPtr         geom;
+
+    xkb= result->xkb;
+    if ((!xkb)||(!xkb->geom)) {
+       _XkbLibError(_XkbErrMissingGeometry,"XkbWriteXKBGeometry",0);
+       return False;
+    }
+    dpy= xkb->dpy;
+    geom= xkb->geom;
+    if (geom->name==None)
+        fprintf(file,"xkb_geometry {\n\n");
+    else fprintf(file,"xkb_geometry \"%s\" {\n\n",
+                               XkbAtomText(dpy,geom->name,XkbXKBFile));
+    fprintf(file,"    width=       %s;\n",
+                               XkbGeomFPText(geom->width_mm,XkbXKBFile));
+    fprintf(file,"    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",
+                               XkbKeyNameText(pAl->alias,XkbXKBFile),
+                               XkbKeyNameText(pAl->real,XkbXKBFile));
+       }
+       fprintf(file,"\n");
+    }
+
+    if (geom->base_color!=NULL)
+       fprintf(file,"    baseColor=   \"%s\";\n",
+                       XkbStringText(geom->base_color->spec,XkbXKBFile));
+    if (geom->label_color!=NULL)
+       fprintf(file,"    labelColor=  \"%s\";\n",
+                       XkbStringText(geom->label_color->spec,XkbXKBFile));
+    if (geom->label_font!=NULL)
+       fprintf(file,"    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,
+                               XkbStringText(color->spec,XkbXKBFile));
+       }
+       fprintf(file,"\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,
+                               XkbStringText(prop->value,XkbXKBFile));
+       }
+       fprintf(file,"\n");
+    }
+    if (geom->num_shapes>0) {
+       XkbShapePtr     shape;
+       XkbOutlinePtr   outline;
+       int             lastR;
+       for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
+           lastR=0;
+           fprintf(file,"    shape \"%s\" {",
+                                  XkbAtomText(dpy,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);
+                   lastR= outline->corner_radius;
+               }
+               fprintf(file,"\n    };\n");
+           }
+           else {
+               WriteXKBOutline(file,NULL,outline,lastR,1,8);
+               fprintf(file," };\n");
+           }
+       }
+    }
+    if (geom->num_sections>0) {
+       XkbSectionPtr   section;
+       for (section=geom->sections,i=0;i<geom->num_sections;i++,section++){
+           WriteXKBSection(file,dpy,section,geom);
+       }
+    }
+    if (geom->num_doodads>0) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
+           WriteXKBDoodad(file,dpy,4,geom,doodad);
+       }
+    }
+    if (addOn)
+       (*addOn)(file,result,topLevel,showImplicit,XkmGeometryIndex,priv);
+    fprintf(file,"};\n\n");
+    return True;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBSemantics(  FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Bool           ok;
+
+    fprintf(file,"xkb_semantics {\n");
+    ok= XkbWriteXKBKeyTypes(file,result,False,False,addOn,priv);
+    ok= ok&&XkbWriteXKBCompatMap(file,result,False,False,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBLayout(     FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Bool           ok;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    fprintf(file,"xkb_layout {\n");
+    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
+    if (xkb->geom)
+       ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+/*ARGSUSED*/
+Bool
+XkbWriteXKBKeymap(     FILE *                  file,
+                       XkbFileInfo *           result,
+                       Bool                    topLevel,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Bool           ok;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    fprintf(file,"xkb_keymap {\n");
+    ok= XkbWriteXKBKeycodes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBKeyTypes(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBCompatMap(file,result,False,showImplicit,addOn,priv);
+    ok= ok&&XkbWriteXKBSymbols(file,result,False,showImplicit,addOn,priv);
+    if (xkb->geom)
+       ok= ok&&XkbWriteXKBGeometry(file,result,False,showImplicit,addOn,priv);
+    fprintf(file,"};\n");
+    return ok;
+}
+
+Bool
+XkbWriteXKBFile(       FILE *                  out,
+                       XkbFileInfo *           result,
+                       Bool                    showImplicit,
+                       XkbFileAddOnFunc        addOn,
+                       void *                  priv)
+{
+Bool                   ok = False;
+Bool                   (*func)(
+    FILE *             /* file */,
+    XkbFileInfo *      /* result */,
+    Bool               /* topLevel */,
+    Bool               /* showImplicit */,
+    XkbFileAddOnFunc   /* addOn */,
+    void *             /* priv */
+) = NULL;
+
+    switch (result->type) {
+       case XkmSemanticsFile:
+           func= XkbWriteXKBSemantics;
+           break;
+       case XkmLayoutFile:
+           func= XkbWriteXKBLayout;
+           break;
+       case XkmKeymapFile:
+           func= XkbWriteXKBKeymap;
+           break;
+       case XkmTypesIndex:
+           func= XkbWriteXKBKeyTypes;
+           break;
+       case XkmCompatMapIndex:
+           func= XkbWriteXKBCompatMap;
+           break;
+       case XkmSymbolsIndex:
+           func= XkbWriteXKBSymbols;
+           break;
+       case XkmKeyNamesIndex:
+           func= XkbWriteXKBKeycodes;
+           break;
+       case XkmGeometryFile:
+       case XkmGeometryIndex:
+           func= XkbWriteXKBGeometry;
+           break;
+       case XkmVirtualModsIndex:
+       case XkmIndicatorsIndex:
+           _XkbLibError(_XkbErrBadImplementation,
+                       XkbConfigText(result->type,XkbMessage),0);
+           return False;
+    }
+    if (out==NULL) {
+       _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXkbFile",0);
+       ok= False;
+    }
+    else if (func) {
+       ok= (*func)(out,result,True,showImplicit,addOn,priv);
+    }
+    return ok;
+}
diff --git a/src/xkbtext.c b/src/xkbtext.c
new file mode 100644 (file)
index 0000000..3a82b17
--- /dev/null
@@ -0,0 +1,1441 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <X11/Xos.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+#else
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "dix.h"
+#include <X11/extensions/XKBstr.h>
+#define XKBSRV_NEED_FILE_FUNCS 1
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBgeom.h>
+
+#endif
+
+/***====================================================================***/
+
+#define        BUFFER_SIZE     512
+
+static char textBuffer[BUFFER_SIZE];
+static int  tbNext= 0;
+
+static char *
+tbGetBuffer(unsigned size)
+{
+char *rtrn;
+
+    if (size>=BUFFER_SIZE)
+       return NULL;
+    if ((BUFFER_SIZE-tbNext)<=size)
+       tbNext= 0;
+    rtrn= &textBuffer[tbNext];
+    tbNext+= size;
+    return rtrn;
+}
+
+/***====================================================================***/
+
+char *
+XkbAtomText(Display *dpy,Atom atm,unsigned format)
+{
+char   *rtrn,*tmp;
+
+    tmp= XkbAtomGetString(dpy,atm);
+    if (tmp!=NULL) {
+       int     len;
+       len= strlen(tmp)+1;
+       if (len>BUFFER_SIZE)
+           len= BUFFER_SIZE-2;
+       rtrn= tbGetBuffer(len);
+       strncpy(rtrn,tmp,len);
+       rtrn[len]= '\0';
+        _XkbFree(tmp);
+    }
+    else {
+       rtrn= tbGetBuffer(1);
+       rtrn[0]= '\0';
+    }
+    if (format==XkbCFile) {
+       for (tmp=rtrn;*tmp!='\0';tmp++) {
+           if ((tmp==rtrn)&&(!isalpha(*tmp)))
+               *tmp= '_';
+           else if (!isalnum(*tmp))
+               *tmp= '_';
+       }
+    }
+    return XkbStringText(rtrn,format);
+}
+
+/***====================================================================***/
+
+char *
+XkbVModIndexText(Display *dpy,XkbDescPtr xkb,unsigned ndx,unsigned format)
+{
+register int len;
+register Atom *vmodNames;
+char *rtrn,*tmp;
+
+    if (xkb && xkb->names)
+        vmodNames= xkb->names->vmods;
+    else vmodNames= NULL;
+
+    tmp= NULL;
+    if (ndx>=XkbNumVirtualMods)
+        tmp= strdup("illegal");
+    else if (vmodNames&&(vmodNames[ndx]!=None))
+        tmp= XkbAtomGetString(dpy,vmodNames[ndx]);
+    if (tmp==NULL) {
+        tmp= (char *)_XkbAlloc(20 * sizeof(char));
+       snprintf(tmp,20,"%d",ndx);
+    }
+
+    len= strlen(tmp)+1;
+    if (format==XkbCFile)
+       len+= 4;
+    if (len>=BUFFER_SIZE)
+       len= BUFFER_SIZE-1;
+    rtrn= tbGetBuffer(len);
+    if (format==XkbCFile) {
+         snprintf(rtrn, len, "vmod_%s", tmp);
+    }
+    else strncpy(rtrn,tmp,len);
+    _XkbFree(tmp);
+    return rtrn;
+}
+
+char *
+XkbVModMaskText(       Display *       dpy,
+                       XkbDescPtr      xkb,
+                       unsigned        modMask,
+                       unsigned        mask,
+                       unsigned        format)
+{
+register int i,bit;
+int     len;
+char *mm,*rtrn;
+char *str,buf[BUFFER_SIZE];
+
+    if ((modMask==0)&&(mask==0)) {
+       rtrn= tbGetBuffer(5);
+       if (format==XkbCFile)
+            sprintf(rtrn,"0");
+       else sprintf(rtrn,"none");
+       return rtrn;
+    }
+    if (modMask!=0)
+        mm= XkbModMaskText(modMask,format);
+    else mm= NULL;
+
+    str= buf;
+    buf[0]= '\0';
+    if (mask) {
+       char *tmp;
+       for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+           if (mask&bit) {
+               tmp= XkbVModIndexText(dpy,xkb,i,format);
+               len= strlen(tmp)+1+(str==buf?0:1);
+               if (format==XkbCFile)
+                   len+= 4;
+               if ((str-(buf+len))<=BUFFER_SIZE) {
+                   if (str!=buf) {
+                       if (format==XkbCFile)   *str++= '|';
+                       else                    *str++= '+';
+                       len--;
+                   }
+               }
+               if (format==XkbCFile)
+                    sprintf(str,"%sMask",tmp);
+               else strcpy(str,tmp);
+               str= &str[len-1];
+           }
+       }
+       str= buf;
+    }
+    else str= NULL;
+    if (mm)
+       len= strlen(mm);
+    else       len= 0;
+    if (str)
+       len+= strlen(str)+(mm==NULL?0:1);
+    if (len>=BUFFER_SIZE)
+       len= BUFFER_SIZE-1;
+    rtrn= tbGetBuffer(len+1);
+    rtrn[0]= '\0';
+
+    if (mm!=NULL) {
+       i= strlen(mm);
+       if (i>len)
+           i= len;
+       strcpy(rtrn,mm);
+    }
+    else {
+       i=0;
+    }
+    if (str!=NULL) {
+       if (mm!=NULL) {
+           if (format==XkbCFile)       strcat(rtrn,"|");
+           else                        strcat(rtrn,"+");
+       }
+       strncat(rtrn,str,len-i);
+    }
+    rtrn[len]= '\0';
+    return rtrn;
+}
+
+static const char *modNames[XkbNumModifiers] = {
+    "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5"
+};
+
+char *
+XkbModIndexText(unsigned ndx,unsigned format)
+{
+char * rtrn;
+char   buf[100];
+
+    if (format==XkbCFile) {
+       if (ndx<XkbNumModifiers)
+            sprintf(buf,"%sMapIndex",modNames[ndx]);
+       else if (ndx==XkbNoModifier)
+            sprintf(buf,"XkbNoModifier");
+       else sprintf(buf,"0x%02x",ndx);
+    }
+    else {
+       if (ndx<XkbNumModifiers)
+            strcpy(buf,modNames[ndx]);
+       else if (ndx==XkbNoModifier)
+            strcpy(buf,"none");
+       else sprintf(buf,"ILLEGAL_%02x",ndx);
+    }
+    rtrn= tbGetBuffer(strlen(buf)+1);
+    strcpy(rtrn,buf);
+    return rtrn;
+}
+
+char *
+XkbModMaskText(unsigned mask,unsigned format)
+{
+register int i,bit;
+char buf[64],*rtrn;
+
+    if ((mask&0xff)==0xff) {
+       if (format==XkbCFile)           strcpy(buf,"0xff");
+       else                            strcpy(buf,"all");
+    }
+    else if ((mask&0xff)==0) {
+       if (format==XkbCFile)           strcpy(buf,"0");
+       else                            strcpy(buf,"none");
+    }
+    else {
+       char *str= buf;
+       buf[0]= '\0';
+       for (i=0,bit=1;i<XkbNumModifiers;i++,bit<<=1) {
+           if (mask&bit) {
+               if (str!=buf) {
+                   if (format==XkbCFile)       *str++= '|';
+                   else                        *str++= '+';
+               }
+               strcpy(str,modNames[i]);
+               str= &str[strlen(str)];
+               if (format==XkbCFile) {
+                   strcpy(str,"Mask");
+                   str+= 4;
+               }
+           }
+       }
+    }
+    rtrn= tbGetBuffer(strlen(buf)+1);
+    strcpy(rtrn,buf);
+    return rtrn;
+}
+
+/***====================================================================***/
+
+/*ARGSUSED*/
+char *
+XkbConfigText(unsigned config,unsigned format)
+{
+static char *buf;
+
+    buf= tbGetBuffer(32);
+    switch (config) {
+       case XkmSemanticsFile:
+           strcpy(buf,"Semantics");
+           break;
+       case XkmLayoutFile:
+           strcpy(buf,"Layout");
+           break;
+       case XkmKeymapFile:
+           strcpy(buf,"Keymap");
+           break;
+       case XkmGeometryFile:
+       case XkmGeometryIndex:
+           strcpy(buf,"Geometry");
+           break;
+       case XkmTypesIndex:
+           strcpy(buf,"Types");
+           break;
+       case XkmCompatMapIndex:
+           strcpy(buf,"CompatMap");
+           break;
+       case XkmSymbolsIndex:
+           strcpy(buf,"Symbols");
+           break;
+       case XkmIndicatorsIndex:
+           strcpy(buf,"Indicators");
+           break;
+       case XkmKeyNamesIndex:
+           strcpy(buf,"KeyNames");
+           break;
+       case XkmVirtualModsIndex:
+           strcpy(buf,"VirtualMods");
+           break;
+       default:
+           sprintf(buf,"unknown(%d)",config);
+           break;
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbKeysymText(KeySym sym,unsigned format)
+{
+static char buf[32],*rtrn;
+
+#ifndef XKB_IN_SERVER
+    if (sym==NoSymbol)
+       strcpy(rtrn=buf,"NoSymbol");
+    else if ((rtrn=XKeysymToString(sym))==NULL)
+       sprintf(rtrn=buf, "0x%lx", (long)sym);
+    else if (format==XkbCFile) {
+       sprintf(buf,"XK_%s",rtrn);
+       rtrn= buf;
+    }
+    return rtrn;
+#else /* def XKB_IN_SERVER */
+    if (sym==NoSymbol)
+        strcpy(rtrn=buf,"NoSymbol");
+    else sprintf(rtrn=buf, "0x%lx", (long)sym);
+    return rtrn;
+#endif /* XKB_IN_SERVER */
+}
+
+char *
+XkbKeyNameText(char *name,unsigned format)
+{
+char *buf;
+
+    if (format==XkbCFile) {
+       buf= tbGetBuffer(5);
+       memcpy(buf,name,4);
+       buf[4]= '\0';
+    }
+    else {
+       int len;
+       buf= tbGetBuffer(7);
+       buf[0]= '<';
+       memcpy(&buf[1],name,4);
+       buf[5]= '\0';
+       len= strlen(buf);
+       buf[len++]= '>';
+       buf[len]= '\0';
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+static char *siMatchText[5] = {
+       "NoneOf", "AnyOfOrNone", "AnyOf", "AllOf", "Exactly"
+};
+
+char *
+XkbSIMatchText(unsigned type,unsigned format)
+{
+static char buf[40];
+char *rtrn;
+
+    switch (type&XkbSI_OpMask) {
+       case XkbSI_NoneOf:      rtrn= siMatchText[0]; break;
+       case XkbSI_AnyOfOrNone: rtrn= siMatchText[1]; break;
+       case XkbSI_AnyOf:       rtrn= siMatchText[2]; break;
+       case XkbSI_AllOf:       rtrn= siMatchText[3]; break;
+       case XkbSI_Exactly:     rtrn= siMatchText[4]; break;
+       default:                sprintf(buf,"0x%x",type&XkbSI_OpMask);
+                               return buf;
+    }
+    if (format==XkbCFile) {
+       if (type&XkbSI_LevelOneOnly)
+            sprintf(buf,"XkbSI_LevelOneOnly|XkbSI_%s",rtrn);
+       else sprintf(buf,"XkbSI_%s",rtrn);
+       rtrn= buf;
+    }
+    return rtrn;
+}
+
+/***====================================================================***/
+
+static const char *imWhichNames[]= {
+       "base",
+       "latched",
+       "locked",
+       "effective",
+       "compat"
+};
+
+char *
+XkbIMWhichStateMaskText(unsigned use_which,unsigned format)
+{
+int            len;
+unsigned       i,bit,tmp;
+char *         buf;
+
+    if (use_which==0) {
+       buf= tbGetBuffer(2);
+       strcpy(buf,"0");
+       return buf;
+    }
+    tmp= use_which&XkbIM_UseAnyMods;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+       if (tmp&bit) {
+           tmp&= ~bit;
+           len+= strlen(imWhichNames[i])+1;
+           if (format==XkbCFile)
+               len+= 9;
+       }
+    }
+    buf= tbGetBuffer(len+1);
+    tmp= use_which&XkbIM_UseAnyMods;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+       if (tmp&bit) {
+           tmp&= ~bit;
+           if (format==XkbCFile) {
+               if (len!=0)
+                   buf[len++]= '|';
+               sprintf(&buf[len],"XkbIM_Use%s",imWhichNames[i]);
+               buf[len+9]= toupper(buf[len+9]);
+           }
+           else {
+               if (len!=0)
+                   buf[len++]= '+';
+               sprintf(&buf[len],"%s",imWhichNames[i]);
+           }
+           len+= strlen(&buf[len]);
+       }
+    }
+    return buf;
+}
+
+char *
+XkbAccessXDetailText(unsigned state,unsigned format)
+{
+char *buf;
+const char *prefix;
+
+    buf= tbGetBuffer(32);
+    if (format==XkbMessage)    prefix= "";
+    else                       prefix= "XkbAXN_";
+    switch (state){
+       case XkbAXN_SKPress:    sprintf(buf,"%sSKPress",prefix); break;
+       case XkbAXN_SKAccept:   sprintf(buf,"%sSKAccept",prefix); break;
+       case XkbAXN_SKRelease:  sprintf(buf,"%sSKRelease",prefix); break;
+       case XkbAXN_SKReject:   sprintf(buf,"%sSKReject",prefix); break;
+       case XkbAXN_BKAccept:   sprintf(buf,"%sBKAccept",prefix); break;
+       case XkbAXN_BKReject:   sprintf(buf,"%sBKReject",prefix); break;
+       case XkbAXN_AXKWarning: sprintf(buf,"%sAXKWarning",prefix); break;
+       default:                sprintf(buf,"ILLEGAL"); break;
+    }
+    return buf;
+}
+
+static const char *nknNames[] = {
+       "keycodes", "geometry", "deviceID"
+};
+#define        NUM_NKN (sizeof(nknNames)/sizeof(char *))
+
+char *
+XkbNKNDetailMaskText(unsigned detail,unsigned format)
+{
+char *buf;
+const char *prefix,*suffix;
+register int           i;
+register unsigned      bit;
+int                    len,plen,slen;
+
+
+    if ((detail&XkbAllNewKeyboardEventsMask)==0) {
+       const char *tmp = "";
+       if (format==XkbCFile)                   tmp= "0";
+       else if (format==XkbMessage)            tmp= "none";
+       buf=  tbGetBuffer(strlen(tmp)+1);
+       strcpy(buf,tmp);
+       return buf;
+    }
+    else if ((detail&XkbAllNewKeyboardEventsMask)==XkbAllNewKeyboardEventsMask){
+       const char *    tmp;
+       if (format==XkbCFile)           tmp= "XkbAllNewKeyboardEventsMask";
+       else                            tmp= "all";
+       buf=  tbGetBuffer(strlen(tmp)+1);
+       strcpy(buf,tmp);
+       return buf;
+    }
+    if (format==XkbMessage) {
+       prefix= "";
+       suffix= "";
+       slen= plen= 0;
+    }
+    else {
+       prefix= "XkbNKN_";
+       plen= 7;
+       if (format==XkbCFile)
+            suffix= "Mask";
+       else suffix= "";
+       slen= strlen(suffix);
+    }
+    for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) {
+       if (detail&bit) {
+           if (len!=0) len+= 1;        /* room for '+' or '|' */
+           len+= plen+slen+strlen(nknNames[i]);
+       }
+    }
+    buf= tbGetBuffer(len+1);
+    buf[0]= '\0';
+    for (len=0,i=0,bit=1;i<NUM_NKN;i++,bit<<=1) {
+       if (detail&bit) {
+           if (len!=0) {
+               if (format==XkbCFile)   buf[len++]= '|';
+               else                    buf[len++]= '+';
+           }
+           if (plen) {
+               strcpy(&buf[len],prefix);
+               len+= plen;
+           }
+           strcpy(&buf[len],nknNames[i]);
+           len+= strlen(nknNames[i]);
+           if (slen) {
+               strcpy(&buf[len],suffix);
+               len+= slen;
+           }
+       }
+    }
+    buf[len++]= '\0';
+    return buf;
+}
+
+static const char *ctrlNames[] = {
+       "repeatKeys",
+       "slowKeys",
+       "bounceKeys",
+       "stickyKeys",
+       "mouseKeys",
+       "mouseKeysAccel",
+       "accessXKeys",
+       "accessXTimeout",
+       "accessXFeedback",
+       "audibleBell",
+       "overlay1",
+       "overlay2",
+       "ignoreGroupLock"
+};
+
+char *
+XkbControlsMaskText(unsigned ctrls,unsigned format)
+{
+int            len;
+unsigned       i,bit,tmp;
+char *         buf;
+
+    if (ctrls==0) {
+       buf= tbGetBuffer(5);
+       if (format==XkbCFile)
+            strcpy(buf,"0");
+       else strcpy(buf,"none");
+       return buf;
+    }
+    tmp= ctrls&XkbAllBooleanCtrlsMask;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+       if (tmp&bit) {
+           tmp&= ~bit;
+           len+= strlen(ctrlNames[i])+1;
+           if (format==XkbCFile)
+               len+= 7;
+       }
+    }
+    buf= tbGetBuffer(len+1);
+    tmp= ctrls&XkbAllBooleanCtrlsMask;
+    for (len=i=0,bit=1;tmp!=0;i++,bit<<=1) {
+       if (tmp&bit) {
+           tmp&= ~bit;
+           if (format==XkbCFile) {
+               if (len!=0)
+                   buf[len++]= '|';
+               sprintf(&buf[len],"Xkb%sMask",ctrlNames[i]);
+               buf[len+3]= toupper(buf[len+3]);
+           }
+           else {
+               if (len!=0)
+                   buf[len++]= '+';
+               sprintf(&buf[len],"%s",ctrlNames[i]);
+           }
+           len+= strlen(&buf[len]);
+       }
+    }
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbStringText(char *str,unsigned format)
+{
+char * buf;
+register char *in,*out;
+int    len;
+Bool   ok;
+
+    if (str==NULL) {
+       buf= tbGetBuffer(2);
+       buf[0]='\0';
+       return buf;
+    }
+    else if (format==XkbXKMFile)
+       return str;
+    for (ok= True,len=0,in=str;*in!='\0';in++,len++) {
+       if (!isprint(*in)) {
+           ok= False;
+           switch (*in) {
+               case '\n': case '\t': case '\v':
+               case '\b': case '\r': case '\f':
+                   len++;
+                   break;
+               default:
+                   len+= 4;
+                   break;
+           }
+       }
+    }
+    if (ok)
+       return str;
+    buf= tbGetBuffer(len+1);
+    for (in=str,out=buf;*in!='\0';in++) {
+       if (isprint(*in))
+           *out++= *in;
+       else {
+           *out++= '\\';
+           if (*in=='\n')      *out++= 'n';
+           else if (*in=='\t') *out++= 't';
+           else if (*in=='\v') *out++= 'v';
+           else if (*in=='\b') *out++= 'b';
+           else if (*in=='\r') *out++= 'r';
+           else if (*in=='\f') *out++= 'f';
+           else if ((*in=='\033')&&(format==XkbXKMFile)) {
+               *out++= 'e';
+           }
+           else {
+               *out++= '0';
+               sprintf(out,"%o",*in);
+               while (*out!='\0')
+                   out++;
+           }
+       }
+    }
+    *out++= '\0';
+    return buf;
+}
+
+/***====================================================================***/
+
+char *
+XkbGeomFPText(int val,unsigned format)
+{
+int    whole,frac;
+char * buf;
+
+    buf= tbGetBuffer(12);
+    if (format==XkbCFile) {
+       sprintf(buf,"%d",val);
+    }
+    else {
+       whole= val/XkbGeomPtsPerMM;
+       frac= val%XkbGeomPtsPerMM;
+       if (frac!=0)
+            sprintf(buf,"%d.%d",whole,frac);
+       else sprintf(buf,"%d",whole);
+    }
+    return buf;
+}
+
+char *
+XkbDoodadTypeText(unsigned type,unsigned format)
+{
+char * buf;
+    if (format==XkbCFile) {
+       buf= tbGetBuffer(24);
+       if (type==XkbOutlineDoodad)        strcpy(buf,"XkbOutlineDoodad");
+       else if (type==XkbSolidDoodad)     strcpy(buf,"XkbSolidDoodad");
+       else if (type==XkbTextDoodad)      strcpy(buf,"XkbTextDoodad");
+       else if (type==XkbIndicatorDoodad) strcpy(buf,"XkbIndicatorDoodad");
+       else if (type==XkbLogoDoodad)      strcpy(buf,"XkbLogoDoodad");
+       else                               sprintf(buf,"UnknownDoodad%d",type);
+    }
+    else {
+       buf= tbGetBuffer(12);
+       if (type==XkbOutlineDoodad)        strcpy(buf,"outline");
+       else if (type==XkbSolidDoodad)     strcpy(buf,"solid");
+       else if (type==XkbTextDoodad)      strcpy(buf,"text");
+       else if (type==XkbIndicatorDoodad) strcpy(buf,"indicator");
+       else if (type==XkbLogoDoodad)      strcpy(buf,"logo");
+       else                               sprintf(buf,"unknown%d",type);
+    }
+    return buf;
+}
+
+static char *actionTypeNames[XkbSA_NumActions]= {
+    "NoAction",
+    "SetMods",      "LatchMods",    "LockMods",
+    "SetGroup",     "LatchGroup",   "LockGroup",
+    "MovePtr",
+    "PtrBtn",       "LockPtrBtn",
+    "SetPtrDflt",
+    "ISOLock",
+    "Terminate",    "SwitchScreen",
+    "SetControls",  "LockControls",
+    "ActionMessage",
+    "RedirectKey",
+    "DeviceBtn",    "LockDeviceBtn"
+};
+
+char *
+XkbActionTypeText(unsigned type,unsigned format)
+{
+static char buf[32];
+char *rtrn;
+
+    if (type<=XkbSA_LastAction) {
+       rtrn= actionTypeNames[type];
+       if (format==XkbCFile) {
+           sprintf(buf,"XkbSA_%s",rtrn);
+           return buf;
+       }
+       return rtrn;
+    }
+    sprintf(buf,"Private");
+    return buf;
+}
+
+/***====================================================================***/
+
+static int
+TryCopyStr(char *to,const char *from,int *pLeft)
+{
+register int len;
+    if (*pLeft>0) {
+       len= strlen(from);
+       if (len<((*pLeft)-3)) {
+           strcat(to,from);
+           *pLeft-= len;
+           return True;
+       }
+    }
+    *pLeft= -1;
+    return False;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyNoActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int*sz)
+{
+    return True;
+}
+
+static Bool
+CopyModActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int* sz)
+{
+XkbModAction * act;
+unsigned       tmp;
+
+    act= &action->mods;
+    tmp= XkbModActionVMods(act);
+    TryCopyStr(buf,"modifiers=",sz);
+    if (act->flags&XkbSA_UseModMapMods)
+         TryCopyStr(buf,"modMapMods",sz);
+    else if (act->real_mods || tmp) {
+        TryCopyStr(buf,
+                    XkbVModMaskText(dpy,xkb,act->real_mods,tmp,XkbXKBFile),
+                    sz);
+    }
+    else TryCopyStr(buf,"none",sz);
+    if (act->type==XkbSA_LockMods)
+       return True;
+    if (act->flags&XkbSA_ClearLocks)
+       TryCopyStr(buf,",clearLocks",sz);
+    if (act->flags&XkbSA_LatchToLock)
+       TryCopyStr(buf,",latchToLock",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyGroupActionArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbGroupAction *       act;
+char                   tbuf[32];
+
+    act= &action->group;
+    TryCopyStr(buf,"group=",sz);
+    if (act->flags&XkbSA_GroupAbsolute)
+        sprintf(tbuf,"%d",XkbSAGroup(act)+1);
+    else if (XkbSAGroup(act)<0)
+        sprintf(tbuf,"%d",XkbSAGroup(act));
+    else sprintf(tbuf,"+%d",XkbSAGroup(act));
+    TryCopyStr(buf,tbuf,sz);
+    if (act->type==XkbSA_LockGroup)
+       return True;
+    if (act->flags&XkbSA_ClearLocks)
+       TryCopyStr(buf,",clearLocks",sz);
+    if (act->flags&XkbSA_LatchToLock)
+       TryCopyStr(buf,",latchToLock",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyMovePtrArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbPtrAction * act;
+int            x,y;
+char           tbuf[32];
+
+    act= &action->ptr;
+    x= XkbPtrActionX(act);
+    y= XkbPtrActionY(act);
+    if ((act->flags&XkbSA_MoveAbsoluteX)||(x<0))
+        sprintf(tbuf,"x=%d",x);
+    else sprintf(tbuf,"x=+%d",x);
+    TryCopyStr(buf,tbuf,sz);
+
+    if ((act->flags&XkbSA_MoveAbsoluteY)||(y<0))
+        sprintf(tbuf,",y=%d",y);
+    else sprintf(tbuf,",y=+%d",y);
+    TryCopyStr(buf,tbuf,sz);
+    if (act->flags&XkbSA_NoAcceleration)
+       TryCopyStr(buf,",!accel",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyPtrBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbPtrBtnAction *      act;
+char                   tbuf[32];
+
+    act= &action->btn;
+    TryCopyStr(buf,"button=",sz);
+    if ((act->button>0)&&(act->button<6)) {
+        sprintf(tbuf,"%d",act->button);
+        TryCopyStr(buf,tbuf,sz);
+    }
+    else TryCopyStr(buf,"default",sz);
+    if (act->count>0) {
+       sprintf(tbuf,",count=%d",act->count);
+       TryCopyStr(buf,tbuf,sz);
+    }
+    if (action->type==XkbSA_LockPtrBtn) {
+       switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
+           case XkbSA_LockNoLock:
+               sprintf(tbuf,",affect=unlock"); break;
+           case XkbSA_LockNoUnlock:
+               sprintf(tbuf,",affect=lock"); break;
+           case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
+               sprintf(tbuf,",affect=neither"); break;
+           default:
+               sprintf(tbuf,",affect=both"); break;
+       }
+       TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySetPtrDfltArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbPtrDfltAction *     act;
+char                   tbuf[32];
+
+    act= &action->dflt;
+    if (act->affect==XkbSA_AffectDfltBtn) {
+       TryCopyStr(buf,"affect=button,button=",sz);
+       if ((act->flags&XkbSA_DfltBtnAbsolute)||(XkbSAPtrDfltValue(act)<0))
+            sprintf(tbuf,"%d",XkbSAPtrDfltValue(act));
+       else sprintf(tbuf,"+%d",XkbSAPtrDfltValue(act));
+       TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+static Bool
+CopyISOLockArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbISOAction * act;
+char           tbuf[64];
+
+    act= &action->iso;
+    if (act->flags&XkbSA_ISODfltIsGroup) {
+       TryCopyStr(tbuf,"group=",sz);
+       if (act->flags&XkbSA_GroupAbsolute)
+            sprintf(tbuf,"%d",XkbSAGroup(act)+1);
+       else if (XkbSAGroup(act)<0)
+            sprintf(tbuf,"%d",XkbSAGroup(act));
+       else sprintf(tbuf,"+%d",XkbSAGroup(act));
+       TryCopyStr(buf,tbuf,sz);
+    }
+    else {
+       unsigned tmp;
+       tmp= XkbModActionVMods(act);
+       TryCopyStr(buf,"modifiers=",sz);
+       if (act->flags&XkbSA_UseModMapMods)
+            TryCopyStr(buf,"modMapMods",sz);
+       else if (act->real_mods || tmp) {
+           if (act->real_mods) {
+               TryCopyStr(buf,XkbModMaskText(act->real_mods,XkbXKBFile),sz);
+               if (tmp)
+                   TryCopyStr(buf,"+",sz);
+           }
+           if (tmp)
+               TryCopyStr(buf,XkbVModMaskText(dpy,xkb,0,tmp,XkbXKBFile),sz);
+       }
+       else TryCopyStr(buf,"none",sz);
+    }
+    TryCopyStr(buf,",affect=",sz);
+    if ((act->affect&XkbSA_ISOAffectMask)==0)
+       TryCopyStr(buf,"all",sz);
+    else {
+       int nOut= 0;
+       if ((act->affect&XkbSA_ISONoAffectMods)==0) {
+           TryCopyStr(buf,"mods",sz);
+           nOut++;
+       }
+       if ((act->affect&XkbSA_ISONoAffectGroup)==0) {
+           sprintf(tbuf,"%sgroups",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if ((act->affect&XkbSA_ISONoAffectPtr)==0) {
+           sprintf(tbuf,"%spointer",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if ((act->affect&XkbSA_ISONoAffectCtrls)==0) {
+           sprintf(tbuf,"%scontrols",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySwitchScreenArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbSwitchScreenAction *        act;
+char                   tbuf[32];
+
+    act= &action->screen;
+    if ((act->flags&XkbSA_SwitchAbsolute)||(XkbSAScreen(act)<0))
+        sprintf(tbuf,"screen=%d",XkbSAScreen(act));
+    else sprintf(tbuf,"screen=+%d",XkbSAScreen(act));
+    TryCopyStr(buf,tbuf,sz);
+    if (act->flags&XkbSA_SwitchApplication)
+        TryCopyStr(buf,",!same",sz);
+    else TryCopyStr(buf,",same",sz);
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopySetLockControlsArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,
+                                                       char *buf,int *sz)
+{
+XkbCtrlsAction *       act;
+unsigned               tmp;
+char                   tbuf[32];
+
+    act= &action->ctrls;
+    tmp= XkbActionCtrls(act);
+    TryCopyStr(buf,"controls=",sz);
+    if (tmp==0)
+       TryCopyStr(buf,"none",sz);
+    else if ((tmp&XkbAllBooleanCtrlsMask)==XkbAllBooleanCtrlsMask)
+       TryCopyStr(buf,"all",sz);
+    else {
+       int nOut= 0;
+       if (tmp&XkbRepeatKeysMask) {
+           sprintf(tbuf,"%sRepeatKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbSlowKeysMask) {
+           sprintf(tbuf,"%sSlowKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbBounceKeysMask) {
+           sprintf(tbuf,"%sBounceKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbStickyKeysMask) {
+           sprintf(tbuf,"%sStickyKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbMouseKeysMask) {
+           sprintf(tbuf,"%sMouseKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbMouseKeysAccelMask) {
+           sprintf(tbuf,"%sMouseKeysAccel",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbAccessXKeysMask) {
+           sprintf(tbuf,"%sAccessXKeys",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbAccessXTimeoutMask) {
+           sprintf(tbuf,"%sAccessXTimeout",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbAccessXFeedbackMask) {
+           sprintf(tbuf,"%sAccessXFeedback",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbAudibleBellMask) {
+           sprintf(tbuf,"%sAudibleBell",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbOverlay1Mask) {
+           sprintf(tbuf,"%sOverlay1",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbOverlay2Mask) {
+           sprintf(tbuf,"%sOverlay2",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+       if (tmp&XkbIgnoreGroupLockMask) {
+           sprintf(tbuf,"%sIgnoreGroupLock",(nOut>0?"+":""));
+           TryCopyStr(buf,tbuf,sz);
+           nOut++;
+       }
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyActionMessageArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbMessageAction *     act;
+unsigned               all;
+char                   tbuf[32];
+
+    act= &action->msg;
+    all= XkbSA_MessageOnPress|XkbSA_MessageOnRelease;
+    TryCopyStr(buf,"report=",sz);
+    if ((act->flags&all)==0)
+       TryCopyStr(buf,"none",sz);
+    else if ((act->flags&all)==all)
+       TryCopyStr(buf,"all",sz);
+    else if (act->flags&XkbSA_MessageOnPress)
+        TryCopyStr(buf,"KeyPress",sz);
+    else TryCopyStr(buf,"KeyRelease",sz);
+    sprintf(tbuf,",data[0]=0x%02x",act->message[0]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[1]=0x%02x",act->message[1]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[2]=0x%02x",act->message[2]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[3]=0x%02x",act->message[3]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[4]=0x%02x",act->message[4]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[5]=0x%02x",act->message[5]); TryCopyStr(buf,tbuf,sz);
+    return True;
+}
+
+static Bool
+CopyRedirectKeyArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbRedirectKeyAction * act;
+char                   tbuf[32],*tmp;
+unsigned               kc;
+unsigned               vmods,vmods_mask;
+
+    act= &action->redirect;
+    kc= act->new_key;
+    vmods= XkbSARedirectVMods(act);
+    vmods_mask= XkbSARedirectVModsMask(act);
+    if (xkb && xkb->names && xkb->names->keys && (kc<=xkb->max_key_code) &&
+                               (xkb->names->keys[kc].name[0]!='\0')) {
+       char *kn;
+       kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
+       sprintf(tbuf,"key=%s",kn);
+    }
+    else sprintf(tbuf,"key=%d",kc);
+    TryCopyStr(buf,tbuf,sz);
+    if ((act->mods_mask==0)&&(vmods_mask==0))
+       return True;
+    if ((act->mods_mask==XkbAllModifiersMask)&&
+       (vmods_mask==XkbAllVirtualModsMask)) {
+       tmp= XkbVModMaskText(dpy,xkb,act->mods,vmods,XkbXKBFile);
+       TryCopyStr(buf,",mods=",sz);
+       TryCopyStr(buf,tmp,sz);
+    }
+    else {
+       if ((act->mods_mask&act->mods)||(vmods_mask&vmods)) {
+           tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&act->mods,
+                                        vmods_mask&vmods,XkbXKBFile);
+           TryCopyStr(buf,",mods= ",sz);
+           TryCopyStr(buf,tmp,sz);
+       }
+       if ((act->mods_mask&(~act->mods))||(vmods_mask&(~vmods))) {
+           tmp= XkbVModMaskText(dpy,xkb,act->mods_mask&(~act->mods),
+                                        vmods_mask&(~vmods),XkbXKBFile);
+           TryCopyStr(buf,",clearMods= ",sz);
+           TryCopyStr(buf,tmp,sz);
+       }
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyDeviceBtnArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,
+                                                               int *sz)
+{
+XkbDeviceBtnAction *   act;
+char                   tbuf[32];
+
+    act= &action->devbtn;
+    sprintf(tbuf,"device= %d",act->device); TryCopyStr(buf,tbuf,sz);
+    TryCopyStr(buf,",button=",sz);
+    sprintf(tbuf,"%d",act->button);
+    TryCopyStr(buf,tbuf,sz);
+    if (act->count>0) {
+       sprintf(tbuf,",count=%d",act->count);
+       TryCopyStr(buf,tbuf,sz);
+    }
+    if (action->type==XkbSA_LockDeviceBtn) {
+       switch (act->flags&(XkbSA_LockNoUnlock|XkbSA_LockNoLock)) {
+           case XkbSA_LockNoLock:
+               sprintf(tbuf,",affect=unlock"); break;
+           case XkbSA_LockNoUnlock:
+               sprintf(tbuf,",affect=lock"); break;
+           case XkbSA_LockNoUnlock|XkbSA_LockNoLock:
+               sprintf(tbuf,",affect=neither"); break;
+           default:
+               sprintf(tbuf,",affect=both"); break;
+       }
+       TryCopyStr(buf,tbuf,sz);
+    }
+    return True;
+}
+
+/*ARGSUSED*/
+static Bool
+CopyOtherArgs(Display *dpy,XkbDescPtr xkb,XkbAction *action,char *buf,int *sz)
+{
+XkbAnyAction * act;
+char           tbuf[32];
+
+    act= &action->any;
+    sprintf(tbuf,"type=0x%02x",act->type); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[0]=0x%02x",act->data[0]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[1]=0x%02x",act->data[1]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[2]=0x%02x",act->data[2]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[3]=0x%02x",act->data[3]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[4]=0x%02x",act->data[4]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[5]=0x%02x",act->data[5]); TryCopyStr(buf,tbuf,sz);
+    sprintf(tbuf,",data[6]=0x%02x",act->data[6]); TryCopyStr(buf,tbuf,sz);
+    return True;
+}
+
+typedef        Bool    (*actionCopy)(
+       Display *       /* dpy */,
+       XkbDescPtr      /* xkb */,
+       XkbAction *     /* action */,
+       char *          /* buf */,
+       int*            /* sz */
+);
+static actionCopy      copyActionArgs[XkbSA_NumActions] = {
+       CopyNoActionArgs                /* NoAction     */,
+       CopyModActionArgs               /* SetMods      */,
+       CopyModActionArgs               /* LatchMods    */,
+       CopyModActionArgs               /* LockMods     */,
+       CopyGroupActionArgs             /* SetGroup     */,
+       CopyGroupActionArgs             /* LatchGroup   */,
+       CopyGroupActionArgs             /* LockGroup    */,
+       CopyMovePtrArgs                 /* MovePtr      */,
+       CopyPtrBtnArgs                  /* PtrBtn       */,
+       CopyPtrBtnArgs                  /* LockPtrBtn   */,
+       CopySetPtrDfltArgs              /* SetPtrDflt   */,
+       CopyISOLockArgs                 /* ISOLock      */,
+       CopyNoActionArgs                /* Terminate    */,
+       CopySwitchScreenArgs            /* SwitchScreen */,
+       CopySetLockControlsArgs         /* SetControls  */,
+       CopySetLockControlsArgs         /* LockControls */,
+       CopyActionMessageArgs           /* ActionMessage*/,
+       CopyRedirectKeyArgs             /* RedirectKey  */,
+       CopyDeviceBtnArgs               /* DeviceBtn    */,
+       CopyDeviceBtnArgs               /* LockDeviceBtn*/
+};
+
+#define        ACTION_SZ       256
+
+char *
+XkbActionText(Display *dpy,XkbDescPtr xkb,XkbAction *action,unsigned format)
+{
+char   buf[ACTION_SZ],*tmp;
+int    sz;
+
+    if (format==XkbCFile) {
+       sprintf(buf,
+           "{ %20s, { 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x } }",
+           XkbActionTypeText(action->type,XkbCFile),
+           action->any.data[0],action->any.data[1],action->any.data[2],
+           action->any.data[3],action->any.data[4],action->any.data[5],
+           action->any.data[6]);
+    }
+    else {
+       sprintf(buf,"%s(",XkbActionTypeText(action->type,XkbXKBFile));
+       sz= ACTION_SZ-strlen(buf)+2; /* room for close paren and NULL */
+       if (action->type<(unsigned)XkbSA_NumActions)
+            (*copyActionArgs[action->type])(dpy,xkb,action,buf,&sz);
+       else CopyOtherArgs(dpy,xkb,action,buf,&sz);
+       TryCopyStr(buf,")",&sz);
+    }
+    tmp= tbGetBuffer(strlen(buf)+1);
+    if (tmp!=NULL)
+       strcpy(tmp,buf);
+    return tmp;
+}
+
+char *
+XkbBehaviorText(XkbDescPtr xkb,XkbBehavior *behavior,unsigned format)
+{
+char   buf[256],*tmp;
+
+    if (format==XkbCFile) {
+       if (behavior->type==XkbKB_Default)
+            sprintf(buf,"{   0,    0 }");
+       else sprintf(buf,"{ %3d, 0x%02x }",behavior->type,behavior->data);
+    }
+    else {
+       unsigned        type,permanent;
+       type= behavior->type&XkbKB_OpMask;
+       permanent=((behavior->type&XkbKB_Permanent)!=0);
+
+       if (type==XkbKB_Lock) {
+           sprintf(buf,"lock= %s",(permanent?"Permanent":"True"));
+       }
+       else if (type==XkbKB_RadioGroup) {
+           int         g;
+           char        *tmp;
+           g= ((behavior->data)&(~XkbKB_RGAllowNone))+1;
+           if (XkbKB_RGAllowNone&behavior->data) {
+               sprintf(buf,"allowNone,");
+               tmp= &buf[strlen(buf)];
+           }
+           else tmp= buf;
+           if (permanent)
+                sprintf(tmp,"permanentRadioGroup= %d",g);
+           else sprintf(tmp,"radioGroup= %d",g);
+       }
+       else if ((type==XkbKB_Overlay1)||(type==XkbKB_Overlay2)) {
+           int ndx,kc;
+           char *kn;
+
+           ndx= ((type==XkbKB_Overlay1)?1:2);
+           kc= behavior->data;
+           if ((xkb)&&(xkb->names)&&(xkb->names->keys))
+               kn= XkbKeyNameText(xkb->names->keys[kc].name,XkbXKBFile);
+           else {
+               static char tbuf[8];
+               sprintf(tbuf,"%d",kc);
+               kn= tbuf;
+           }
+           if (permanent)
+                sprintf(buf,"permanentOverlay%d= %s",ndx,kn);
+           else sprintf(buf,"overlay%d= %s",ndx,kn);
+       }
+    }
+    tmp= tbGetBuffer(strlen(buf)+1);
+    if (tmp!=NULL)
+       strcpy(tmp,buf);
+    return tmp;
+}
+
+/***====================================================================***/
+
+char *
+XkbIndentText(unsigned size)
+{
+static char buf[32];
+register int i;
+
+    if (size>31)
+       size= 31;
+
+    for (i=0;i<size;i++) {
+       buf[i]= ' ';
+    }
+    buf[size]= '\0';
+    return buf;
+}
+
+#ifndef XKB_IN_SERVER
+
+/***====================================================================***/
+
+#define        PIXEL_MAX       65535
+
+Bool
+XkbLookupCanonicalRGBColor(char *def,XColor *color)
+{
+int     tmp;
+
+    if (_XkbStrCaseEqual(def,"black")) {
+       color->red= color->green= color->blue= 0;
+       return True;
+    }
+    else if (_XkbStrCaseEqual(def,"white")) {
+       color->red= color->green= color->blue= PIXEL_MAX;
+       return True;
+    }
+    else if ((sscanf(def,"grey%d",&tmp)==1)||
+        (sscanf(def,"gray%d",&tmp)==1)||
+        (sscanf(def,"Grey%d",&tmp)==1)||
+        (sscanf(def,"Gray%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->red= color->green= color->blue= tmp;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"red")*100))||
+             (sscanf(def,"red%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->red= tmp;
+           color->green= color->blue= 0;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"green")*100))||
+             (sscanf(def,"green%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->green= tmp;
+           color->red= color->blue= 0;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"blue")*100))||
+             (sscanf(def,"blue%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->blue= tmp;
+           color->red= color->green= 0;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"magenta")*100))||
+             (sscanf(def,"magenta%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->green= 0;
+           color->red= color->blue= tmp;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"cyan")*100))||
+             (sscanf(def,"cyan%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->red= 0;
+           color->green= color->blue= tmp;
+           return True;
+       }
+    }
+    else if ((tmp=(_XkbStrCaseEqual(def,"yellow")*100))||
+             (sscanf(def,"yellow%d",&tmp)==1)) {
+       if ((tmp>0)&&(tmp<=100)) {
+           tmp= (PIXEL_MAX*tmp)/100;
+           color->blue= 0;
+           color->red= color->green= tmp;
+           return True;
+       }
+    }
+    return False;
+}
+
+#endif
diff --git a/src/xkmout.c b/src/xkmout.c
new file mode 100644 (file)
index 0000000..1e43157
--- /dev/null
@@ -0,0 +1,1387 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBgeom.h>
+
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+typedef struct _XkmInfo {
+     unsigned short    bound_vmods;
+     unsigned short    named_vmods;
+     unsigned char     num_bound;
+     unsigned char     group_compat;
+     unsigned short    num_group_compat;
+     unsigned short    num_leds;
+     int               total_vmodmaps;
+} XkmInfo;
+
+/***====================================================================***/
+
+#define        xkmPutCARD8(f,v)        (putc(v,f),1)
+
+static int
+xkmPutCARD16(FILE *file,unsigned val)
+{
+CARD16 tmp= val;
+
+    fwrite(&tmp,2,1,file);
+    return 2;
+}
+
+static int
+xkmPutCARD32(FILE *file,unsigned long val)
+{
+CARD32 tmp= val;
+
+    fwrite(&tmp,4,1,file);
+    return 4;
+}
+
+static int
+xkmPutPadding(FILE *file,unsigned pad)
+{
+int    i;
+    for (i=0;i<pad;i++) {
+       putc('\0',file);
+    }
+    return pad;
+}
+
+static int
+xkmPutCountedBytes(FILE *file,char *ptr,unsigned count)
+{
+register int nOut;
+register unsigned pad;
+
+    if (count==0)
+       return xkmPutCARD32(file,(unsigned long)0);
+
+    xkmPutCARD16(file,count);
+    nOut= fwrite(ptr,1,count,file);
+    if (nOut<0)
+       return 2;
+    nOut= count+2;
+    pad= XkbPaddedSize(nOut)-nOut;
+    if (pad)
+       xkmPutPadding(file,pad);
+    return nOut+pad;
+}
+
+static unsigned
+xkmSizeCountedString(char *str)
+{
+    if (str==NULL)
+       return 4;
+    return XkbPaddedSize(strlen(str)+2);
+}
+
+static int
+xkmPutCountedString(FILE *file,char *str)
+{
+    if (str==NULL)
+        return xkmPutCARD32(file,(unsigned long)0);
+    return xkmPutCountedBytes(file,str,strlen(str));
+}
+
+#define        xkmSizeCountedAtomString(d,a)   \
+       xkmSizeCountedString(XkbAtomGetString((d),(a)))
+
+#define        xkmPutCountedAtomString(d,f,a)  \
+       xkmPutCountedString((f),XkbAtomGetString((d),(a)))
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMVirtualMods(    XkbFileInfo *           result,
+                       XkmInfo *               info,
+                       xkmSectionInfo *        toc,
+                       int *                   offset_inout)
+{
+Display *      dpy;
+XkbDescPtr     xkb;
+unsigned       nBound,bound;
+unsigned       nNamed,named,szNames;
+register unsigned      i,bit;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->names)||(!xkb->server)) {
+       _XkbLibError(_XkbErrMissingVMods,"SizeXKMVirtualMods",0);
+       return 0;
+    }
+    bound=named=0;
+    for (i=nBound=nNamed=szNames=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+       if (xkb->server->vmods[i]!=XkbNoModifierMask) {
+           bound|= bit;
+           nBound++;
+       }
+       if (xkb->names->vmods[i]!=None) {
+           named|= bit;
+           szNames+= xkmSizeCountedAtomString(dpy,xkb->names->vmods[i]);
+           nNamed++;
+       }
+    }
+    info->num_bound= nBound;
+    info->bound_vmods= bound;
+    info->named_vmods= named;
+    if ((nBound==0)&&(nNamed==0))
+       return 0;
+    toc->type=                 XkmVirtualModsIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 4+XkbPaddedSize(nBound)+szNames+SIZEOF(xkmSectionInfo);
+    toc->offset=       *offset_inout;
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMVirtualMods(FILE *file,XkbFileInfo *result,XkmInfo *info)
+{
+register unsigned int i,bit;
+XkbDescPtr     xkb;
+Display *      dpy;
+unsigned       size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    size+= xkmPutCARD16(file,info->bound_vmods);
+    size+= xkmPutCARD16(file,info->named_vmods);
+    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+       if (info->bound_vmods&bit)
+           size+= xkmPutCARD8(file,xkb->server->vmods[i]);
+    }
+    if ((i= XkbPaddedSize(info->num_bound)-info->num_bound)>0)
+       size+= xkmPutPadding(file,i);
+    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+       if (info->named_vmods&bit) {
+           register char *name;
+           name= XkbAtomGetString(dpy,xkb->names->vmods[i]);
+           size+= xkmPutCountedString(file,name);
+       }
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMKeycodes(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
+{
+XkbDescPtr     xkb;
+Atom           kcName;
+int            size=0;
+Display *      dpy;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->names)||(!xkb->names->keys)) {
+       _XkbLibError(_XkbErrMissingNames,"SizeXKMKeycodes",0);
+       return 0;
+    }
+    kcName= xkb->names->keycodes;
+    size+= 4;  /* min and max keycode */
+    size+= xkmSizeCountedAtomString(dpy,kcName);
+    size+= XkbNumKeys(xkb)*sizeof(XkbKeyNameRec);
+    if (xkb->names->num_key_aliases>0) {
+       if (xkb->names->key_aliases!=NULL)
+            size+= xkb->names->num_key_aliases*sizeof(XkbKeyAliasRec);
+       else xkb->names->num_key_aliases= 0;
+    }
+    toc->type=                 XkmKeyNamesIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMKeycodes(FILE *file,XkbFileInfo *result)
+{
+XkbDescPtr     xkb;
+Atom           kcName;
+char           *start;
+Display *      dpy;
+unsigned       tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    kcName= xkb->names->keycodes;
+    start= xkb->names->keys[xkb->min_key_code].name;
+
+    size+= xkmPutCountedString(file,XkbAtomGetString(dpy,kcName));
+    size+= xkmPutCARD8(file,xkb->min_key_code);
+    size+= xkmPutCARD8(file,xkb->max_key_code);
+    size+= xkmPutCARD8(file,xkb->names->num_key_aliases);
+    size+= xkmPutPadding(file,1);
+    tmp= fwrite(start,sizeof(XkbKeyNameRec),XkbNumKeys(xkb),file);
+    size+= tmp*sizeof(XkbKeyNameRec);
+    if (xkb->names->num_key_aliases>0) {
+       tmp= fwrite((char *)xkb->names->key_aliases,
+                       sizeof(XkbKeyAliasRec),xkb->names->num_key_aliases,
+                       file);
+       size+= tmp*sizeof(XkbKeyAliasRec);
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMKeyTypes(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
+{
+register unsigned      i,n,size;
+XkbKeyTypePtr          type;
+XkbDescPtr             xkb;
+Display *              dpy;
+char *                 name;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->map)||(!xkb->map->types)) {
+       _XkbLibError(_XkbErrMissingTypes,"SizeXKBKeyTypes",0);
+       return 0;
+    }
+    if (xkb->map->num_types<XkbNumRequiredTypes) {
+       _XkbLibError(_XkbErrMissingReqTypes,"SizeXKBKeyTypes",0);
+       return 0;
+    }
+    if (xkb->names)    name= XkbAtomGetString(dpy,xkb->names->types);
+    else               name= NULL;
+    size= xkmSizeCountedString(name);
+    size+= 4;  /* room for # of key types + padding */
+    for (i=0,type=xkb->map->types;i<xkb->map->num_types;i++,type++) {
+       size+= SIZEOF(xkmKeyTypeDesc);
+       size+= SIZEOF(xkmKTMapEntryDesc)*type->map_count;
+       size+= xkmSizeCountedAtomString(dpy,type->name);
+       if (type->preserve)
+           size+= SIZEOF(xkmModsDesc)*type->map_count;
+       if (type->level_names) {
+           Atom *names;
+           names= type->level_names;
+           for (n=0;n<(unsigned)type->num_levels;n++) {
+               size+= xkmSizeCountedAtomString(dpy,names[n]);
+           }
+       }
+    }
+    toc->type=                 XkmTypesIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMKeyTypes(FILE *file,XkbFileInfo *result)
+{
+register unsigned      i,n;
+XkbDescPtr             xkb;
+XkbKeyTypePtr          type;
+xkmKeyTypeDesc         wire;
+XkbKTMapEntryPtr       entry;
+xkmKTMapEntryDesc      wire_entry;
+Atom *                 names;
+Display *              dpy;
+unsigned               tmp,size= 0;
+char *                 name;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if (xkb->names)    name= XkbAtomGetString(dpy,xkb->names->types);
+    else               name= NULL;
+    size+= xkmPutCountedString(file,name);
+    size+= xkmPutCARD16(file,xkb->map->num_types);
+    size+= xkmPutPadding(file,2);
+    type= xkb->map->types;
+    for (i=0;i<xkb->map->num_types;i++,type++) {
+       wire.realMods= type->mods.real_mods;
+       wire.virtualMods= type->mods.vmods;
+       wire.numLevels= type->num_levels;
+       wire.nMapEntries= type->map_count;
+       wire.preserve= (type->preserve!=NULL);
+       if (type->level_names!=NULL)
+            wire.nLevelNames= type->num_levels;
+       else wire.nLevelNames= 0;
+       tmp= fwrite(&wire,SIZEOF(xkmKeyTypeDesc),1,file);
+       size+= tmp*SIZEOF(xkmKeyTypeDesc);
+       for (n=0,entry= type->map;n<type->map_count;n++,entry++) {
+           wire_entry.level= entry->level;
+           wire_entry.realMods= entry->mods.real_mods;
+           wire_entry.virtualMods= entry->mods.vmods;
+           tmp= fwrite(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file);
+           size+= tmp*SIZEOF(xkmKTMapEntryDesc);
+       }
+       size+= xkmPutCountedString(file,XkbAtomGetString(dpy,type->name));
+       if (type->preserve) {
+           xkmModsDesc p_entry;
+           XkbModsPtr  pre;
+           for (n=0,pre=type->preserve;n<type->map_count;n++,pre++) {
+               p_entry.realMods= pre->real_mods;
+               p_entry.virtualMods= pre->vmods;
+               tmp= fwrite(&p_entry,SIZEOF(xkmModsDesc),1,file);
+               size+= tmp*SIZEOF(xkmModsDesc);
+           }
+       }
+       if (type->level_names!=NULL) {
+           names= type->level_names;
+           for (n=0;n<wire.nLevelNames;n++) {
+               size+= xkmPutCountedString(file,XkbAtomGetString(dpy,names[n]));
+           }
+       }
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMCompatMap(      XkbFileInfo *           result,
+                       XkmInfo *               info,
+                       xkmSectionInfo *        toc,
+                       int *                   offset_inout)
+{
+XkbDescPtr     xkb;
+char *         name;
+int            size;
+register int   i;
+unsigned       groups,nGroups;
+Display *      dpy;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->compat)||(!xkb->compat->sym_interpret)) {
+       _XkbLibError(_XkbErrMissingCompatMap,"SizeXKMCompatMap",0);
+       return 0;
+    }
+    if (xkb->names)    name= XkbAtomGetString(dpy,xkb->names->compat);
+    else               name= NULL;
+
+    for (i=groups=nGroups=0;i<XkbNumKbdGroups;i++) {
+       if ((xkb->compat->groups[i].real_mods!=0)||
+                       (xkb->compat->groups[i].vmods!=0)) {
+           groups|= (1<<i);
+           nGroups++;
+       }
+    }
+    info->group_compat= groups;
+    info->num_group_compat= nGroups;
+    size= 4; /* room for num_si and group_compat mask */
+    size+= xkmSizeCountedString(name);
+    size+= (SIZEOF(xkmSymInterpretDesc)*xkb->compat->num_si);
+    size+= (SIZEOF(xkmModsDesc)*nGroups);
+    toc->type=                 XkmCompatMapIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMCompatMap(FILE *file,XkbFileInfo *result,XkmInfo *info)
+{
+register unsigned      i;
+char *                 name;
+XkbDescPtr             xkb;
+XkbSymInterpretPtr     interp;
+xkmSymInterpretDesc    wire;
+Display *              dpy;
+unsigned               tmp,size=0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if (xkb->names)    name= XkbAtomGetString(dpy,xkb->names->compat);
+    else               name= NULL;
+    size+= xkmPutCountedString(file,name);
+    size+= xkmPutCARD16(file,xkb->compat->num_si);
+    size+= xkmPutCARD8(file,info->group_compat);
+    size+= xkmPutPadding(file,1);
+    interp= xkb->compat->sym_interpret;
+    for (i=0;i<xkb->compat->num_si;i++,interp++) {
+       wire.sym= interp->sym;
+       wire.mods= interp->mods;
+       wire.match= interp->match;
+       wire.virtualMod= interp->virtual_mod;
+       wire.flags= interp->flags;
+       wire.actionType= interp->act.type;
+       wire.actionData[0]= interp->act.data[0];
+       wire.actionData[1]= interp->act.data[1];
+       wire.actionData[2]= interp->act.data[2];
+       wire.actionData[3]= interp->act.data[3];
+       wire.actionData[4]= interp->act.data[4];
+       wire.actionData[5]= interp->act.data[5];
+       wire.actionData[6]= interp->act.data[6];
+       tmp= fwrite(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
+       size+= tmp*SIZEOF(xkmSymInterpretDesc);
+    }
+    if (info->group_compat) {
+       register unsigned       bit;
+       xkmModsDesc             modsWire;
+       for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
+           if (info->group_compat&bit) {
+               modsWire.realMods= xkb->compat->groups[i].real_mods;
+               modsWire.virtualMods= xkb->compat->groups[i].vmods;
+               fwrite(&modsWire,SIZEOF(xkmModsDesc),1,file);
+               size+= SIZEOF(xkmModsDesc);
+           }
+       }
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMSymbols(        XkbFileInfo *           result,
+               XkmInfo *               info,
+               xkmSectionInfo *        toc,
+               int *                   offset_inout)
+{
+Display *      dpy;
+XkbDescPtr     xkb;
+unsigned       size;
+register int   i,nSyms;
+char *         name;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->map)||((!xkb->map->syms))) {
+       _XkbLibError(_XkbErrMissingSymbols,"SizeXKMSymbols",0);
+       return 0;
+    }
+    if (xkb->names && (xkb->names->symbols!=None))
+        name= XkbAtomGetString(dpy,xkb->names->symbols);
+    else name= NULL;
+    size= xkmSizeCountedString(name);
+    size+= 4;  /* min and max keycode, group names mask */
+    for (i=0;i<XkbNumKbdGroups;i++) {
+       if (xkb->names->groups[i]!=None)
+           size+= xkmSizeCountedAtomString(dpy,xkb->names->groups[i]);
+    }
+    info->total_vmodmaps= 0;
+    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++) {
+       nSyms= XkbKeyNumSyms(xkb,i);
+       size+= SIZEOF(xkmKeySymMapDesc)+(nSyms*4);
+       if (xkb->server) {
+           if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
+               register int g;
+               for (g=XkbKeyNumGroups(xkb,i)-1;g>=0;g--) {
+                   if (xkb->server->explicit[i]&(1<<g)) {
+                       XkbKeyTypePtr   type;
+                       char *          name;
+                       type= XkbKeyKeyType(xkb,i,g);
+                       name= XkbAtomGetString(dpy,type->name);
+                       if (name!=NULL)
+                           size+= xkmSizeCountedString(name);
+                   }
+               }
+           }
+           if (XkbKeyHasActions(xkb,i))
+               size+= nSyms*SIZEOF(xkmActionDesc);
+           if (xkb->server->behaviors[i].type!=XkbKB_Default)
+               size+= SIZEOF(xkmBehaviorDesc);
+           if (xkb->server->vmodmap && (xkb->server->vmodmap[i]!=0))
+               info->total_vmodmaps++;
+       }
+    }
+    size+= info->total_vmodmaps*SIZEOF(xkmVModMapDesc);
+    toc->type=                 XkmSymbolsIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMSymbols(FILE *file,XkbFileInfo *result,XkmInfo *info)
+{
+Display *              dpy;
+XkbDescPtr             xkb;
+register int           i,n;
+xkmKeySymMapDesc       wireMap;
+char *                 name;
+unsigned               tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if (xkb->names && (xkb->names->symbols!=None))
+        name= XkbAtomGetString(dpy,xkb->names->symbols);
+    else name= NULL;
+    size+= xkmPutCountedString(file,name);
+    for (tmp=i=0;i<XkbNumKbdGroups;i++) {
+       if (xkb->names->groups[i]!=None)
+           tmp|= (1<<i);
+    }
+    size+= xkmPutCARD8(file,xkb->min_key_code);
+    size+= xkmPutCARD8(file,xkb->max_key_code);
+    size+= xkmPutCARD8(file,tmp);
+    size+= xkmPutCARD8(file,info->total_vmodmaps);
+    for (i=0,n=1;i<XkbNumKbdGroups;i++,n<<=1) {
+       if ((tmp&n)==0)
+           continue;
+       size+= xkmPutCountedAtomString(dpy,file,xkb->names->groups[i]);
+    }
+    for (i=xkb->min_key_code;i<=(int)xkb->max_key_code;i++)  {
+       char *typeName[XkbNumKbdGroups];
+       wireMap.width= XkbKeyGroupsWidth(xkb,i);
+       wireMap.num_groups= XkbKeyGroupInfo(xkb,i);
+       if (xkb->map && xkb->map->modmap)
+            wireMap.modifier_map= xkb->map->modmap[i];
+       else wireMap.modifier_map= 0;
+       wireMap.flags= 0;
+       bzero((char *)typeName,XkbNumKbdGroups*sizeof(char *));
+       if (xkb->server) {
+           if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
+               register int g;
+               for (g=0;g<XkbKeyNumGroups(xkb,i);g++) {
+                   if (xkb->server->explicit[i]&(1<<g)) {
+                       XkbKeyTypePtr   type;
+                       type= XkbKeyKeyType(xkb,i,g);
+                       typeName[g]= XkbAtomGetString(dpy,type->name);
+                       if (typeName[g]!=NULL)
+                           wireMap.flags|= (1<<g);
+                   }
+               }
+           }
+           if (XkbKeyHasActions(xkb,i))
+               wireMap.flags|= XkmKeyHasActions;
+           if (xkb->server->behaviors[i].type!=XkbKB_Default)
+               wireMap.flags|= XkmKeyHasBehavior;
+           if ((xkb->server->explicit[i]&XkbExplicitAutoRepeatMask)&&
+               (xkb->ctrls!=NULL)) {
+               if (xkb->ctrls->per_key_repeat[(i/8)]&(1<<(i%8)))
+                    wireMap.flags|= XkmRepeatingKey;
+               else wireMap.flags|= XkmNonRepeatingKey;
+           }
+       }
+       tmp= fwrite(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file);
+       size+= tmp*SIZEOF(xkmKeySymMapDesc);
+       if (xkb->server->explicit[i]&XkbExplicitKeyTypesMask) {
+           register int g;
+           for (g=0;g<XkbNumKbdGroups;g++) {
+               if (typeName[g]!=NULL)
+                   size+= xkmPutCountedString(file,typeName[g]);
+           }
+       }
+       if (XkbNumGroups(wireMap.num_groups)>0) {
+           KeySym      *sym;
+           sym= XkbKeySymsPtr(xkb,i);
+           for (n=XkbKeyNumSyms(xkb,i);n>0;n--,sym++) {
+               size+= xkmPutCARD32(file,(CARD32)*sym);
+           }
+           if (wireMap.flags&XkmKeyHasActions) {
+               XkbAction *     act;
+               act= XkbKeyActionsPtr(xkb,i);
+               for (n=XkbKeyNumActions(xkb,i);n>0;n--,act++) {
+                   tmp= fwrite(act,SIZEOF(xkmActionDesc),1,file);
+                   size+= tmp*SIZEOF(xkmActionDesc);
+               }
+           }
+       }
+       if (wireMap.flags&XkmKeyHasBehavior) {
+           xkmBehaviorDesc     b;
+           b.type= xkb->server->behaviors[i].type;
+           b.data= xkb->server->behaviors[i].data;
+           tmp= fwrite(&b,SIZEOF(xkmBehaviorDesc),1,file);
+           size+= tmp*SIZEOF(xkmBehaviorDesc);
+       }
+    }
+    if (info->total_vmodmaps>0) {
+       xkmVModMapDesc  v;
+       for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+           if (xkb->server->vmodmap[i]!=0) {
+               v.key= i;
+               v.vmods= xkb->server->vmodmap[i];
+               tmp= fwrite(&v,SIZEOF(xkmVModMapDesc),1,file);
+               size+= tmp*SIZEOF(xkmVModMapDesc);
+           }
+       }
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMIndicators(XkbFileInfo *result,XkmInfo *info,xkmSectionInfo *toc,
+                                                       int *offset_inout)
+{
+Display *              dpy;
+XkbDescPtr             xkb;
+unsigned               size;
+register unsigned      i,nLEDs;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((xkb==NULL)||(xkb->indicators==NULL)) {
+/*     _XkbLibError(_XkbErrMissingIndicators,"SizeXKMIndicators",0);*/
+       return 0;
+    }
+    nLEDs=0;
+    size= 8;   /* number of indicator maps/physical indicators */
+    if (xkb->indicators!=NULL) {
+       for (i=0;i<XkbNumIndicators;i++) {
+           XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+           if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
+               (map->which_mods!=0)||
+               (map->mods.real_mods!=0)||(map->mods.vmods!=0)||
+               (map->ctrls!=0) ||
+               (xkb->names && (xkb->names->indicators[i]!=None))) {
+               char *name;
+               if (xkb->names && xkb->names->indicators[i]!=None) {
+                    name= XkbAtomGetString(dpy,xkb->names->indicators[i]);
+               }
+               else name= NULL;
+               size+= xkmSizeCountedString(name);
+               size+= SIZEOF(xkmIndicatorMapDesc);
+               nLEDs++;
+           }
+       }
+    }
+    info->num_leds= nLEDs;
+    toc->type=                 XkmIndicatorsIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMIndicators(FILE *file,XkbFileInfo *result,XkmInfo *info)
+{
+Display *              dpy;
+XkbDescPtr             xkb;
+register unsigned      i;
+xkmIndicatorMapDesc    wire;
+unsigned               tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    size+= xkmPutCARD8(file,info->num_leds);
+    size+= xkmPutPadding(file,3);
+    size+= xkmPutCARD32(file,xkb->indicators->phys_indicators);
+    if (xkb->indicators!=NULL) {
+       for (i=0;i<XkbNumIndicators;i++) {
+           XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
+           if ((map->flags!=0)||(map->which_groups!=0)||(map->groups!=0)||
+               (map->which_mods!=0)||
+               (map->mods.real_mods!=0)||(map->mods.vmods!=0)||
+               (map->ctrls!=0) ||
+               (xkb->names && (xkb->names->indicators[i]!=None))) {
+               char *name;
+               if (xkb->names && xkb->names->indicators[i]!=None) {
+                    name= XkbAtomGetString(dpy,xkb->names->indicators[i]);
+               }
+               else name= NULL;
+               size+= xkmPutCountedString(file,name);
+               wire.indicator= i+1;
+               wire.flags= map->flags;
+               wire.which_mods= map->which_mods;
+               wire.real_mods= map->mods.real_mods;
+               wire.vmods= map->mods.vmods;
+               wire.which_groups= map->which_groups;
+               wire.groups= map->groups;
+               wire.ctrls= map->ctrls;
+               tmp= fwrite(&wire,SIZEOF(xkmIndicatorMapDesc),1,file);
+               size+= tmp*SIZEOF(xkmIndicatorMapDesc);
+           }
+       }
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+static unsigned
+SizeXKMGeomDoodad(XkbFileInfo *result,XkbDoodadPtr doodad)
+{
+unsigned       size;
+
+    size= SIZEOF(xkmAnyDoodadDesc);
+    size+= xkmSizeCountedAtomString(result->xkb->dpy,doodad->any.name);
+    if (doodad->any.type==XkbTextDoodad) {
+       size+= xkmSizeCountedString(doodad->text.text);
+       size+= xkmSizeCountedString(doodad->text.font);
+    }
+    else if (doodad->any.type==XkbLogoDoodad) {
+       size+= xkmSizeCountedString(doodad->logo.logo_name);
+    }
+    return size;
+}
+
+static unsigned
+SizeXKMGeomSection(XkbFileInfo *result,XkbSectionPtr section)
+{
+register int i;
+unsigned size;
+
+    size= SIZEOF(xkmSectionDesc);
+    size+= xkmSizeCountedAtomString(result->xkb->dpy,section->name);
+    if (section->rows) {
+       XkbRowPtr       row;
+       for (row=section->rows,i=0;i<section->num_rows;i++,row++) {
+           size+= SIZEOF(xkmRowDesc);
+           size+= row->num_keys*SIZEOF(xkmKeyDesc);
+       }
+    }
+    if (section->doodads) {
+       XkbDoodadPtr    doodad;
+       for (doodad=section->doodads,i=0;i<section->num_doodads;i++,doodad++) {
+           size+= SizeXKMGeomDoodad(result,doodad);
+       }
+    }
+    if (section->overlays) {
+       XkbOverlayPtr   ol;
+       for (ol=section->overlays,i=0;i<section->num_overlays;i++,ol++) {
+           register int r;
+           XkbOverlayRowPtr    row;
+           size+= xkmSizeCountedAtomString(result->xkb->dpy,ol->name);
+           size+= SIZEOF(xkmOverlayDesc);
+           for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
+               size+= SIZEOF(xkmOverlayRowDesc);
+               size+= row->num_keys*SIZEOF(xkmOverlayKeyDesc);
+           }
+       }
+    }
+    return size;
+}
+
+static unsigned
+SizeXKMGeometry(XkbFileInfo *result,xkmSectionInfo *toc,int *offset_inout)
+{
+register int   i;
+Display *      dpy;
+XkbDescPtr     xkb;
+XkbGeometryPtr geom;
+unsigned       size;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->geom))
+       return 0;
+    geom= xkb->geom;
+    size= xkmSizeCountedAtomString(dpy,geom->name);
+    size+= SIZEOF(xkmGeometryDesc);
+    size+= xkmSizeCountedString(geom->label_font);
+    if (geom->properties) {
+       XkbPropertyPtr  prop;
+       for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
+           size+= xkmSizeCountedString(prop->name);
+           size+= xkmSizeCountedString(prop->value);
+       }
+    }
+    if (geom->colors) {
+       XkbColorPtr     color;
+       for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
+           size+= xkmSizeCountedString(color->spec);
+       }
+    }
+    if (geom->shapes) {
+       XkbShapePtr     shape;
+       for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
+           register int n;
+           register XkbOutlinePtr      ol;
+           size+= xkmSizeCountedAtomString(dpy,shape->name);
+           size+= SIZEOF(xkmShapeDesc);
+           for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
+               size+= SIZEOF(xkmOutlineDesc);
+               size+= ol->num_points*SIZEOF(xkmPointDesc);
+           }
+       }
+    }
+    if (geom->sections) {
+       XkbSectionPtr   section;
+       for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
+           size+= SizeXKMGeomSection(result,section);
+       }
+    }
+    if  (geom->doodads) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
+           size+= SizeXKMGeomDoodad(result,doodad);
+       }
+    }
+    if (geom->key_aliases) {
+       size+= geom->num_key_aliases*(XkbKeyNameLength*2);
+    }
+    toc->type=                 XkmGeometryIndex;
+    toc->format=       MSBFirst;
+    toc->size=                 size+SIZEOF(xkmSectionInfo);
+    toc->offset=       (*offset_inout);
+    (*offset_inout)+=  toc->size;
+    return 1;
+}
+
+static unsigned
+WriteXKMGeomDoodad(FILE *file,XkbFileInfo *result,XkbDoodadPtr doodad)
+{
+Display *      dpy;
+XkbDescPtr     xkb;
+xkmDoodadDesc  doodadWire;
+unsigned       tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    bzero((char *)&doodadWire,sizeof(doodadWire));
+    doodadWire.any.type= doodad->any.type;
+    doodadWire.any.priority= doodad->any.priority;
+    doodadWire.any.top= doodad->any.top;
+    doodadWire.any.left= doodad->any.left;
+    switch (doodad->any.type) {
+       case XkbOutlineDoodad:
+       case XkbSolidDoodad:
+           doodadWire.shape.angle= doodad->shape.angle;
+           doodadWire.shape.color_ndx= doodad->shape.color_ndx;
+           doodadWire.shape.shape_ndx= doodad->shape.shape_ndx;
+           break;
+       case XkbTextDoodad:
+           doodadWire.text.angle= doodad->text.angle;
+           doodadWire.text.width= doodad->text.width;
+           doodadWire.text.height= doodad->text.height;
+           doodadWire.text.color_ndx= doodad->text.color_ndx;
+           break;
+       case XkbIndicatorDoodad:
+           doodadWire.indicator.shape_ndx= doodad->indicator.shape_ndx;
+           doodadWire.indicator.on_color_ndx= doodad->indicator.on_color_ndx;
+           doodadWire.indicator.off_color_ndx= doodad->indicator.off_color_ndx;
+           break;
+       case XkbLogoDoodad:
+           doodadWire.logo.angle= doodad->logo.angle;
+           doodadWire.logo.color_ndx= doodad->logo.color_ndx;
+           doodadWire.logo.shape_ndx= doodad->logo.shape_ndx;
+           break;
+       default:
+           _XkbLibError(_XkbErrIllegalDoodad,"WriteXKMGeomDoodad",
+                                                       doodad->any.type);
+           return 0;
+    }
+    size+= xkmPutCountedAtomString(dpy,file,doodad->any.name);
+    tmp= fwrite(&doodadWire,SIZEOF(xkmDoodadDesc),1,file);
+    size+= tmp*SIZEOF(xkmDoodadDesc);
+    if (doodad->any.type==XkbTextDoodad) {
+       size+= xkmPutCountedString(file,doodad->text.text);
+       size+= xkmPutCountedString(file,doodad->text.font);
+    }
+    else if (doodad->any.type==XkbLogoDoodad) {
+       size+= xkmPutCountedString(file,doodad->logo.logo_name);
+    }
+    return size;
+}
+
+static unsigned
+WriteXKMGeomOverlay(FILE *file,XkbFileInfo *result,XkbOverlayPtr ol)
+{
+register int           r,k;
+Display *              dpy;
+XkbDescPtr             xkb;
+XkbOverlayRowPtr       row;
+xkmOverlayDesc         olWire;
+xkmOverlayRowDesc      rowWire;
+xkmOverlayKeyDesc      keyWire;
+unsigned               tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    bzero((char *)&olWire,sizeof(olWire));
+    bzero((char *)&rowWire,sizeof(rowWire));
+    bzero((char *)&keyWire,sizeof(keyWire));
+    size+= xkmPutCountedAtomString(dpy,file,ol->name);
+    olWire.num_rows= ol->num_rows;
+    tmp= fwrite(&olWire,SIZEOF(xkmOverlayDesc),1,file);
+    size+= tmp*SIZEOF(xkmOverlayDesc);
+    for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
+       XkbOverlayKeyPtr        key;
+       rowWire.row_under= row->row_under;
+       rowWire.num_keys= row->num_keys;
+       tmp= fwrite(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file);
+       size+= tmp*SIZEOF(xkmOverlayRowDesc);
+       for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+           memcpy(keyWire.over,key->over.name,XkbKeyNameLength);
+           memcpy(keyWire.under,key->under.name,XkbKeyNameLength);
+           tmp= fwrite(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file);
+           size+= tmp*SIZEOF(xkmOverlayKeyDesc);
+       }
+    }
+    return size;
+}
+
+static unsigned
+WriteXKMGeomSection(FILE *file,XkbFileInfo *result,XkbSectionPtr section)
+{
+register int   i;
+Display *      dpy;
+XkbDescPtr     xkb;
+xkmSectionDesc sectionWire;
+unsigned       tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    size+= xkmPutCountedAtomString(dpy,file,section->name);
+    sectionWire.top= section->top;
+    sectionWire.left= section->left;
+    sectionWire.width= section->width;
+    sectionWire.height= section->height;
+    sectionWire.angle= section->angle;
+    sectionWire.priority= section->priority;
+    sectionWire.num_rows= section->num_rows;
+    sectionWire.num_doodads= section->num_doodads;
+    sectionWire.num_overlays= section->num_overlays;
+    tmp= fwrite(&sectionWire,SIZEOF(xkmSectionDesc),1,file);
+    size+= tmp*SIZEOF(xkmSectionDesc);
+    if (section->rows) {
+       register unsigned k;
+       XkbRowPtr       row;
+       xkmRowDesc      rowWire;
+       XkbKeyPtr       key;
+       xkmKeyDesc      keyWire;
+       for (i=0,row=section->rows;i<section->num_rows;i++,row++) {
+           rowWire.top= row->top;
+           rowWire.left= row->left;
+           rowWire.num_keys= row->num_keys;
+           rowWire.vertical= row->vertical;
+           tmp= fwrite(&rowWire,SIZEOF(xkmRowDesc),1,file);
+           size+= tmp*SIZEOF(xkmRowDesc);
+           for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
+               memcpy(keyWire.name,key->name.name,XkbKeyNameLength);
+               keyWire.gap= key->gap;
+               keyWire.shape_ndx= key->shape_ndx;
+               keyWire.color_ndx= key->color_ndx;
+               tmp= fwrite(&keyWire,SIZEOF(xkmKeyDesc),1,file);
+               size+= tmp*SIZEOF(xkmKeyDesc);
+           }
+       }
+    }
+    if (section->doodads) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=section->doodads;i<section->num_doodads;i++,doodad++) {
+           size+= WriteXKMGeomDoodad(file,result,doodad);
+       }
+    }
+    if (section->overlays) {
+       XkbOverlayPtr   ol;
+       for (i=0,ol=section->overlays;i<section->num_overlays;i++,ol++) {
+           size+= WriteXKMGeomOverlay(file,result,ol);
+       }
+    }
+    return size;
+}
+
+static unsigned
+WriteXKMGeometry(FILE *file,XkbFileInfo *result)
+{
+register int   i;
+Display *      dpy;
+XkbDescPtr     xkb;
+XkbGeometryPtr geom;
+xkmGeometryDesc        wire;
+unsigned       tmp,size= 0;
+
+    xkb= result->xkb;
+    dpy= xkb->dpy;
+    if ((!xkb)||(!xkb->geom))
+       return 0;
+    geom= xkb->geom;
+    wire.width_mm= geom->width_mm;
+    wire.height_mm= geom->height_mm;
+    wire.base_color_ndx= XkbGeomColorIndex(geom,geom->base_color);
+    wire.label_color_ndx= XkbGeomColorIndex(geom,geom->label_color);
+    wire.num_properties= geom->num_properties;
+    wire.num_colors= geom->num_colors;
+    wire.num_shapes= geom->num_shapes;
+    wire.num_sections= geom->num_sections;
+    wire.num_doodads= geom->num_doodads;
+    wire.num_key_aliases= geom->num_key_aliases;
+    size+= xkmPutCountedAtomString(dpy,file,geom->name);
+    tmp= fwrite(&wire,SIZEOF(xkmGeometryDesc),1,file);
+    size+= tmp*SIZEOF(xkmGeometryDesc);
+    size+= xkmPutCountedString(file,geom->label_font);
+    if (geom->properties) {
+       XkbPropertyPtr  prop;
+       for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
+           size+= xkmPutCountedString(file,prop->name);
+           size+= xkmPutCountedString(file,prop->value);
+       }
+    }
+    if (geom->colors) {
+       XkbColorPtr     color;
+       for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
+           size+= xkmPutCountedString(file,color->spec);
+       }
+    }
+    if (geom->shapes) {
+       XkbShapePtr     shape;
+       xkmShapeDesc    shapeWire;
+
+       for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
+           register int        n;
+           XkbOutlinePtr       ol;
+           xkmOutlineDesc      olWire;
+           bzero((char *)&shapeWire,sizeof(xkmShapeDesc));
+           size+= xkmPutCountedAtomString(dpy,file,shape->name);
+           shapeWire.num_outlines= shape->num_outlines;
+           if (shape->primary!=NULL)
+                shapeWire.primary_ndx= XkbOutlineIndex(shape,shape->primary);
+           else shapeWire.primary_ndx= XkbNoShape;
+           if (shape->approx!=NULL)
+                shapeWire.approx_ndx= XkbOutlineIndex(shape,shape->approx);
+           else shapeWire.approx_ndx= XkbNoShape;
+           tmp= fwrite(&shapeWire,SIZEOF(xkmShapeDesc),1,file);
+           size+= tmp*SIZEOF(xkmShapeDesc);
+           for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
+               register int    p;
+               XkbPointPtr     pt;
+               xkmPointDesc    ptWire;
+               olWire.num_points= ol->num_points;
+               olWire.corner_radius= ol->corner_radius;
+               tmp= fwrite(&olWire,SIZEOF(xkmOutlineDesc),1,file);
+               size+= tmp*SIZEOF(xkmOutlineDesc);
+               for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
+                   ptWire.x= pt->x;
+                   ptWire.y= pt->y;
+                   tmp= fwrite(&ptWire,SIZEOF(xkmPointDesc),1,file);
+                   size+= tmp*SIZEOF(xkmPointDesc);
+               }
+           }
+       }
+    }
+    if (geom->sections) {
+       XkbSectionPtr   section;
+       for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
+           size+= WriteXKMGeomSection(file,result,section);
+       }
+    }
+    if (geom->doodads) {
+       XkbDoodadPtr    doodad;
+       for (i=0,doodad=geom->doodads;i<geom->num_doodads;i++,doodad++) {
+           size+= WriteXKMGeomDoodad(file,result,doodad);
+       }
+    }
+    if (geom->key_aliases) {
+       tmp= fwrite(geom->key_aliases,2*XkbKeyNameLength,geom->num_key_aliases,
+                                                                       file);
+       size+= tmp*(2*XkbKeyNameLength);
+    }
+    return size;
+}
+
+/***====================================================================***/
+
+/*ARGSUSED*/
+static int
+GetXKMKeyNamesTOC(     XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMTypesTOC(        XkbFileInfo *   result,
+               XkmInfo *       info,
+               int             max_toc,
+               xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMCompatMapTOC(    XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMSemanticsTOC(    XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMLayoutTOC(       XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMSymbols(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMKeymapTOC(       XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMVirtualMods(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeycodes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMKeyTypes(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMCompatMap(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMSymbols(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMIndicators(result,info,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+/*ARGSUSED*/
+static int
+GetXKMGeometryTOC(     XkbFileInfo *   result,
+                       XkmInfo *       info,
+                       int             max_toc,
+                       xkmSectionInfo *toc_rtrn)
+{
+int    num_toc;
+int    total_size;
+
+    total_size= num_toc=0;
+    if (SizeXKMGeometry(result,&toc_rtrn[num_toc],&total_size))
+       num_toc++;
+    return num_toc;
+}
+
+static Bool
+WriteXKMFile(  FILE *          file,
+               XkbFileInfo *   result,
+               int             num_toc,
+               xkmSectionInfo *toc,
+               XkmInfo *       info)
+{
+register int   i;
+unsigned       tmp,size,total= 0;
+
+    for (i=0;i<num_toc;i++) {
+       tmp= fwrite(&toc[i],SIZEOF(xkmSectionInfo),1,file);
+       total+= tmp*SIZEOF(xkmSectionInfo);
+       switch (toc[i].type) {
+           case XkmTypesIndex:
+               size= WriteXKMKeyTypes(file,result);
+               break;
+           case XkmCompatMapIndex:
+               size= WriteXKMCompatMap(file,result,info);
+               break;
+           case XkmSymbolsIndex:
+               size= WriteXKMSymbols(file,result,info);
+               break;
+           case XkmIndicatorsIndex:
+               size= WriteXKMIndicators(file,result,info);
+               break;
+           case XkmKeyNamesIndex:
+               size= WriteXKMKeycodes(file,result);
+               break;
+           case XkmGeometryIndex:
+               size= WriteXKMGeometry(file,result);
+               break;
+           case XkmVirtualModsIndex:
+               size= WriteXKMVirtualMods(file,result,info);
+               break;
+           default:
+               _XkbLibError(_XkbErrIllegalTOCType,"WriteXKMFile",toc[i].type);
+               return False;
+       }
+       size+= SIZEOF(xkmSectionInfo);
+       if (size!=toc[i].size) {
+           _XkbLibError(_XkbErrBadLength,XkbConfigText(toc[i].type,XkbMessage),
+                                                       size-toc[i].size);
+           return False;
+       }
+    }
+    return True;
+}
+
+
+#define        MAX_TOC 16
+
+Bool
+XkbWriteXKMFile(FILE *out,XkbFileInfo *result)
+{
+Bool                   ok;
+XkbDescPtr             xkb;
+XkmInfo                        info;
+int                    size_toc,i;
+unsigned               hdr,present;
+xkmFileInfo            fileInfo;
+xkmSectionInfo         toc[MAX_TOC];
+int                    (*getTOC)(
+       XkbFileInfo *   /* result */,
+       XkmInfo *       /* info */,
+       int             /* max_to */,
+       xkmSectionInfo */* toc_rtrn */
+);
+
+    switch (result->type) {
+       case XkmKeyNamesIndex:
+           getTOC= GetXKMKeyNamesTOC;
+           break;
+       case XkmTypesIndex:
+           getTOC= GetXKMTypesTOC;
+           break;
+       case XkmCompatMapIndex:
+           getTOC= GetXKMCompatMapTOC;
+           break;
+       case XkmSemanticsFile:
+           getTOC= GetXKMSemanticsTOC;
+           break;
+       case XkmLayoutFile:
+           getTOC= GetXKMLayoutTOC;
+           break;
+       case XkmKeymapFile:
+           getTOC= GetXKMKeymapTOC;
+           break;
+       case XkmGeometryFile:
+       case XkmGeometryIndex:
+           getTOC= GetXKMGeometryTOC;
+           break;
+       default:
+           _XkbLibError(_XkbErrIllegalContents,
+                               XkbConfigText(result->type,XkbMessage),0);
+           return False;
+    }
+    xkb= result->xkb;
+
+    bzero((char *)&info,sizeof(XkmInfo));
+    size_toc= (*getTOC)(result,&info,MAX_TOC,toc);
+    if (size_toc<1) {
+       _XkbLibError(_XkbErrEmptyFile,"XkbWriteXKMFile",0);
+       return False;
+    }
+    if (out==NULL) {
+       _XkbLibError(_XkbErrFileCannotOpen,"XkbWriteXKMFile",0);
+       return False;
+    }
+    for (i=present=0;i<size_toc;i++) {
+       toc[i].offset+= 4+SIZEOF(xkmFileInfo);
+       toc[i].offset+= (size_toc*SIZEOF(xkmSectionInfo));
+       if (toc[i].type<=XkmLastIndex) {
+           present|= (1<<toc[i].type);
+       }
+#ifdef DEBUG
+       else {
+           fprintf(stderr,"Illegal section type %d\n",toc[i].type);
+           fprintf(stderr,"Ignored\n");
+       }
+#endif
+    }
+    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
+    xkmPutCARD32(out,(unsigned long)hdr);
+    fileInfo.type= result->type;
+    fileInfo.min_kc= xkb->min_key_code;
+    fileInfo.max_kc= xkb->max_key_code;
+    fileInfo.num_toc= size_toc;
+    fileInfo.present= present;
+    fileInfo.pad= 0;
+    fwrite(&fileInfo,SIZEOF(xkmFileInfo),1,out);
+    fwrite(toc,SIZEOF(xkmSectionInfo),size_toc,out);
+    ok= WriteXKMFile(out,result,size_toc,toc,&info);
+    return ok;
+}
diff --git a/src/xkmread.c b/src/xkmread.c
new file mode 100644 (file)
index 0000000..5df95aa
--- /dev/null
@@ -0,0 +1,1299 @@
+/************************************************************
+ Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
+
+ Permission to use, copy, modify, and distribute this
+ software and its documentation for any purpose and without
+ fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting
+ documentation, and that the name of Silicon Graphics not be
+ used in advertising or publicity pertaining to distribution
+ of the software without specific prior written permission.
+ Silicon Graphics makes no representation about the suitability
+ of this software for any purpose. It is provided "as is"
+ without any express or implied warranty.
+
+ SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+
+#ifndef XKB_IN_SERVER
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include <X11/XKBlib.h>
+
+#include <X11/extensions/XKBgeom.h>
+#include "XKMformat.h"
+#include "XKBfileInt.h"
+
+#else
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/keysym.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <X11/extensions/XKBstr.h>
+#define         XKBSRV_NEED_FILE_FUNCS
+#include <X11/extensions/XKBsrv.h>
+#include <X11/extensions/XKBgeom.h>
+
+Atom
+XkbInternAtom(Display *dpy,char *str,Bool only_if_exists)
+{
+    if (str==NULL)
+       return None;
+    return MakeAtom(str,strlen(str),!only_if_exists);
+}
+
+#endif
+
+#ifndef SEEK_SET
+#define        SEEK_SET 0
+#endif
+
+/***====================================================================***/
+
+static XPointer
+XkmInsureSize(XPointer oldPtr,int oldCount,int *newCountRtrn,int elemSize)
+{
+int    newCount= *newCountRtrn;
+
+    if (oldPtr==NULL) {
+       if (newCount==0)
+           return NULL;
+       oldPtr= (XPointer)_XkbCalloc(newCount,elemSize);
+    }
+    else if (oldCount<newCount) {
+       oldPtr= (XPointer)_XkbRealloc(oldPtr,newCount*elemSize);
+       if (oldPtr!=NULL) {
+           char *tmp= (char *)oldPtr;
+           bzero(&tmp[oldCount*elemSize],(newCount-oldCount)*elemSize);
+       }
+    }
+    else if (newCount<oldCount) {
+       *newCountRtrn= oldCount;
+    }
+    return oldPtr;
+}
+
+#define        XkmInsureTypedSize(p,o,n,t) ((p)=((t *)XkmInsureSize((char *)(p),(o),(n),sizeof(t))))
+
+static CARD8
+XkmGetCARD8(FILE *file,int *pNRead)
+{
+int    tmp;
+    tmp= getc(file);
+    if (pNRead&&(tmp!=EOF))
+       (*pNRead)+= 1;
+    return tmp;
+}
+
+static CARD16
+XkmGetCARD16(FILE *file,int *pNRead)
+{
+CARD16         val;
+
+    if ((fread(&val,2,1,file)==1)&&(pNRead))
+       (*pNRead)+= 2;
+    return val;
+}
+
+static CARD32
+XkmGetCARD32(FILE *file,int *pNRead)
+{
+CARD32 val;
+
+    if ((fread(&val,4,1,file)==1)&&(pNRead))
+       (*pNRead)+= 4;
+    return val;
+}
+
+static int
+XkmSkipPadding(FILE *file,unsigned pad)
+{
+register int   i,nRead=0;
+
+    for (i=0;i<pad;i++) {
+       if (getc(file)!=EOF)
+           nRead++;
+    }
+    return nRead;
+}
+
+static int
+XkmGetCountedString(FILE *file,char *str,int max_len)
+{
+int    count,nRead=0;
+
+    count= XkmGetCARD16(file,&nRead);
+    if (count>0) {
+       int tmp;
+       if (count>max_len) {
+           tmp= fread(str,1,max_len,file);
+           while (tmp<count) {
+               if ((getc(file))!=EOF)
+                    tmp++;
+               else break;
+           }
+       }
+       else {
+           tmp= fread(str,1,count,file);
+       }
+       nRead+= tmp;
+    }
+    if (count>=max_len)        str[max_len-1]= '\0';
+    else               str[count]= '\0';
+    count= XkbPaddedSize(nRead)-nRead;
+    if (count>0)
+       nRead+= XkmSkipPadding(file,count);
+    return nRead;
+}
+
+/***====================================================================***/
+
+static int
+ReadXkmVirtualMods(FILE *file,XkbFileInfo *result,XkbChangesPtr changes)
+{
+register unsigned int i,bit;
+unsigned int   bound,named,tmp;
+int            nRead=0;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    if (XkbAllocServerMap(xkb,XkbVirtualModsMask,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
+       return -1;
+    }
+    bound= XkmGetCARD16(file,&nRead);
+    named= XkmGetCARD16(file,&nRead);
+    for (i=tmp=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+       if (bound&bit) {
+           xkb->server->vmods[i]= XkmGetCARD8(file,&nRead);
+           if (changes)
+               changes->map.vmods|= bit;
+           tmp++;
+       }
+    }
+    if ((i= XkbPaddedSize(tmp)-tmp)>0)
+       nRead+= XkmSkipPadding(file,i);
+    if (XkbAllocNames(xkb,XkbVirtualModNamesMask,0,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmVirtualMods",0);
+       return -1;
+    }
+    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+       char name[100];
+       if (named&bit) {
+           if (nRead+=XkmGetCountedString(file,name,100)) {
+               xkb->names->vmods[i]= XkbInternAtom(xkb->dpy,name,False);
+               if (changes)
+                   changes->names.changed_vmods|= bit;
+           }
+       }
+    }
+    return nRead;
+}
+
+/***====================================================================***/
+
+static int
+ReadXkmKeycodes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes)
+{
+register int   i;
+unsigned       minKC,maxKC,nAl;
+int            nRead=0;
+char           name[100];
+XkbKeyNamePtr  pN;
+XkbDescPtr     xkb;
+
+    xkb= result->xkb;
+    name[0]= '\0';
+    nRead+= XkmGetCountedString(file,name,100);
+    minKC= XkmGetCARD8(file,&nRead);
+    maxKC= XkmGetCARD8(file,&nRead);
+    if (xkb->min_key_code==0) {
+       xkb->min_key_code= minKC;
+       xkb->max_key_code= maxKC;
+    }
+    else {
+       if (minKC<xkb->min_key_code)
+           xkb->min_key_code= minKC;
+       if (maxKC>xkb->max_key_code) {
+           _XkbLibError(_XkbErrBadValue,"ReadXkmKeycodes",maxKC);
+           return -1;
+       }
+    }
+    nAl= XkmGetCARD8(file,&nRead);
+    nRead+= XkmSkipPadding(file,1);
+
+#define WANTED (XkbKeycodesNameMask|XkbKeyNamesMask|XkbKeyAliasesMask)
+    if (XkbAllocNames(xkb,WANTED,0,nAl)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
+       return -1;
+    }
+    if (name[0]!='\0') {
+       xkb->names->keycodes= XkbInternAtom(xkb->dpy,name,False);
+    }
+
+    for (pN=&xkb->names->keys[minKC],i=minKC;i<=(int)maxKC;i++,pN++) {
+       if (fread(pN,1,XkbKeyNameLength,file)!=XkbKeyNameLength) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
+           return -1;
+       }
+       nRead+= XkbKeyNameLength;
+    }
+    if (nAl>0) {
+       XkbKeyAliasPtr  pAl;
+       for (pAl= xkb->names->key_aliases,i=0;i<nAl;i++,pAl++) {
+           int tmp;
+           tmp= fread(pAl,1,2*XkbKeyNameLength,file);
+           if (tmp!=2*XkbKeyNameLength) {
+               _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
+               return -1;
+           }
+           nRead+= 2*XkbKeyNameLength;
+       }
+       if (changes)
+           changes->names.changed|= XkbKeyAliasesMask;
+    }
+    if (changes)
+       changes->names.changed|= XkbKeyNamesMask;
+    return nRead;
+}
+
+/***====================================================================***/
+
+static int
+ReadXkmKeyTypes(FILE *file,XkbFileInfo *result,XkbChangesPtr changes)
+{
+register unsigned      i,n;
+unsigned               num_types;
+int                    nRead=0;
+int                    tmp;
+XkbKeyTypePtr          type;
+xkmKeyTypeDesc         wire;
+XkbKTMapEntryPtr       entry;
+xkmKTMapEntryDesc      wire_entry;
+char                   buf[100];
+XkbDescPtr             xkb;
+
+    xkb= result->xkb;
+    if ((tmp= XkmGetCountedString(file,buf,100))<1) {
+       _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
+       return -1;
+    }
+    nRead+= tmp;
+    if (buf[0]!='\0') {
+       if (XkbAllocNames(xkb,XkbTypesNameMask,0,0)!=Success) {
+           _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
+           return -1;
+        }
+       xkb->names->types= XkbInternAtom(xkb->dpy,buf,False);
+    }
+    num_types= XkmGetCARD16(file,&nRead);
+    nRead+= XkmSkipPadding(file,2);
+    if (num_types<1)
+       return nRead;
+    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_types)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeyTypes",0);
+       return nRead;
+    }
+    xkb->map->num_types= num_types;
+    if (num_types<XkbNumRequiredTypes) {
+       _XkbLibError(_XkbErrMissingReqTypes,"ReadXkmKeyTypes",0);
+       return -1;
+    }
+    type= xkb->map->types;
+    for (i=0;i<num_types;i++,type++) {
+       if ((int)fread(&wire,SIZEOF(xkmKeyTypeDesc),1,file)<1) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
+           return -1;
+       }
+       nRead+= SIZEOF(xkmKeyTypeDesc);
+       if (((i==XkbOneLevelIndex)&&(wire.numLevels!=1))||
+           (((i==XkbTwoLevelIndex)||(i==XkbAlphabeticIndex)||
+            ((i)==XkbKeypadIndex))&&(wire.numLevels!=2))) {
+           _XkbLibError(_XkbErrBadTypeWidth,"ReadXkmKeyTypes",i);
+           return -1;
+       }
+       tmp= wire.nMapEntries;
+       XkmInsureTypedSize(type->map,type->map_count,&tmp,XkbKTMapEntryRec);
+       if ((wire.nMapEntries>0)&&(type->map==NULL)) {
+           _XkbLibError(_XkbErrBadValue,"ReadXkmKeyTypes",wire.nMapEntries);
+           return -1;
+       }
+       for (n=0,entry= type->map;n<wire.nMapEntries;n++,entry++) {
+           if (fread(&wire_entry,SIZEOF(xkmKTMapEntryDesc),1,file)<(int)1) {
+               _XkbLibError(_XkbErrBadLength,"ReadXkmKeyTypes",0);
+               return -1;
+           }
+           nRead+= SIZEOF(xkmKTMapEntryDesc);
+           entry->active= (wire_entry.virtualMods==0);
+           entry->level= wire_entry.level;
+           entry->mods.mask= wire_entry.realMods;
+           entry->mods.real_mods= wire_entry.realMods;
+           entry->mods.vmods= wire_entry.virtualMods;
+       }
+       nRead+= XkmGetCountedString(file,buf,100);
+       if (((i==XkbOneLevelIndex)&&(strcmp(buf,"ONE_LEVEL")!=0))||
+           ((i==XkbTwoLevelIndex)&&(strcmp(buf,"TWO_LEVEL")!=0))||
+           ((i==XkbAlphabeticIndex)&&(strcmp(buf,"ALPHABETIC")!=0))||
+           ((i==XkbKeypadIndex)&&(strcmp(buf,"KEYPAD")!=0))) {
+          _XkbLibError(_XkbErrBadTypeName,"ReadXkmKeyTypes",0);
+          return -1;
+       }
+       if (buf[0]!='\0') {
+            type->name= XkbInternAtom(xkb->dpy,buf,False);
+       }
+       else type->name= None;
+
+       if (wire.preserve) {
+           xkmModsDesc p_entry;
+           XkbModsPtr  pre;
+           XkmInsureTypedSize(type->preserve,type->map_count,&tmp,
+                                               XkbModsRec);
+           if (type->preserve==NULL) {
+               _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
+               return -1;
+           }
+           for (n=0,pre=type->preserve;n<wire.nMapEntries;n++,pre++) {
+               if (fread(&p_entry,SIZEOF(xkmModsDesc),1,file)<1) {
+                   _XkbLibError(_XkbErrBadLength,"ReadXkmKeycodes",0);
+                   return -1;
+               }
+               nRead+= SIZEOF(xkmModsDesc);
+               pre->mask= p_entry.realMods;
+               pre->real_mods= p_entry.realMods;
+               pre->vmods= p_entry.virtualMods;
+           }
+       }
+       if (wire.nLevelNames>0) {
+           int width= wire.numLevels;
+           if (wire.nLevelNames>(unsigned)width) {
+               _XkbLibError(_XkbErrBadMatch,"ReadXkmKeycodes",0);
+               return -1;
+           }
+           XkmInsureTypedSize(type->level_names,type->num_levels,&width,Atom);
+           if (type->level_names!=NULL) {
+               for (n=0;n<wire.nLevelNames;n++) {
+                   if ((tmp=XkmGetCountedString(file,buf,100))<1)
+                       return -1;
+                   nRead+= tmp;
+                   if (strlen(buf)==0)
+                        type->level_names[n]= None;
+                   else type->level_names[n]= XkbInternAtom(xkb->dpy,buf,0);
+               }
+           }
+       }
+       type->mods.mask= wire.realMods;
+       type->mods.real_mods= wire.realMods;
+       type->mods.vmods= wire.virtualMods;
+       type->num_levels= wire.numLevels;
+       type->map_count= wire.nMapEntries;
+    }
+    if (changes) {
+       changes->map.changed|= XkbKeyTypesMask;
+       changes->map.first_type= 0;
+       changes->map.num_types= xkb->map->num_types;
+    }
+    return nRead;
+}
+
+/***====================================================================***/
+
+static int
+ReadXkmCompatMap(FILE *file,XkbFileInfo *result,XkbChangesPtr changes)
+{
+register int           i;
+unsigned               num_si,groups;
+char                   name[100];
+XkbSymInterpretPtr     interp;
+xkmSymInterpretDesc    wire;
+unsigned               tmp;
+int                    nRead=0;
+XkbDescPtr             xkb;
+XkbCompatMapPtr                compat;
+
+    xkb= result->xkb;
+    if ((tmp= XkmGetCountedString(file,name,100))<1) {
+       _XkbLibError(_XkbErrBadLength,"ReadXkmCompatMap",0);
+       return -1;
+    }
+    nRead+= tmp;
+    if (name[0]!='\0') {
+       if (XkbAllocNames(xkb,XkbCompatNameMask,0,0)!=Success) {
+           _XkbLibError(_XkbErrBadAlloc,"ReadXkmCompatMap",0);
+           return -1;
+       }
+       xkb->names->compat= XkbInternAtom(xkb->dpy,name,False);
+    }
+    num_si= XkmGetCARD16(file,&nRead);
+    groups= XkmGetCARD8(file,&nRead);
+    nRead+= XkmSkipPadding(file,1);
+    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_si)!=Success)
+       return -1;
+    compat= xkb->compat;
+    compat->num_si= num_si;
+    interp= compat->sym_interpret;
+    for (i=0;i<num_si;i++,interp++) {
+       tmp= fread(&wire,SIZEOF(xkmSymInterpretDesc),1,file);
+       nRead+= tmp*SIZEOF(xkmSymInterpretDesc);
+       interp->sym= wire.sym;
+       interp->mods= wire.mods;
+       interp->match= wire.match;
+       interp->virtual_mod= wire.virtualMod;
+       interp->flags= wire.flags;
+       interp->act.type= wire.actionType;
+       interp->act.data[0]= wire.actionData[0];
+       interp->act.data[1]= wire.actionData[1];
+       interp->act.data[2]= wire.actionData[2];
+       interp->act.data[3]= wire.actionData[3];
+       interp->act.data[4]= wire.actionData[4];
+       interp->act.data[5]= wire.actionData[5];
+       interp->act.data[6]= wire.actionData[6];
+    }
+    if ((num_si>0)&&(changes)) {
+       changes->compat.first_si= 0;
+       changes->compat.num_si= num_si;
+    }
+    if (groups) {
+       register unsigned bit;
+       for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
+           xkmModsDesc md;
+           if (groups&bit) {
+               tmp= fread(&md,SIZEOF(xkmModsDesc),1,file);
+               nRead+= tmp*SIZEOF(xkmModsDesc);
+               xkb->compat->groups[i].real_mods= md.realMods;
+               xkb->compat->groups[i].vmods= md.virtualMods;
+               if (md.virtualMods != 0) {
+                   unsigned mask;
+                   if (XkbVirtualModsToReal(xkb,md.virtualMods,&mask))
+                       xkb->compat->groups[i].mask= md.realMods|mask;
+               }
+               else xkb->compat->groups[i].mask= md.realMods;
+           }
+       }
+       if (changes)
+           changes->compat.changed_groups|= groups;
+    }
+    return nRead;
+}
+
+static int
+ReadXkmIndicators(FILE *file,XkbFileInfo *result,XkbChangesPtr changes)
+{
+register unsigned      nLEDs;
+xkmIndicatorMapDesc    wire;
+char                   buf[100];
+unsigned               tmp;
+int                    nRead=0;
+XkbDescPtr             xkb;
+
+    xkb= result->xkb;
+    if ((xkb->indicators==NULL)&&(XkbAllocIndicatorMaps(xkb)!=Success)) {
+       _XkbLibError(_XkbErrBadAlloc,"indicator rec",0);
+       return -1;
+    }
+    if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"indicator names",0);
+       return -1;
+    }
+    nLEDs= XkmGetCARD8(file,&nRead);
+    nRead+= XkmSkipPadding(file,3);
+    xkb->indicators->phys_indicators= XkmGetCARD32(file,&nRead);
+    while (nLEDs-->0) {
+       Atom                    name;
+       XkbIndicatorMapPtr      map;
+
+       if ((tmp=XkmGetCountedString(file,buf,100))<1) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
+           return -1;
+       }
+       nRead+= tmp;
+       if (buf[0]!='\0')
+            name= XkbInternAtom(xkb->dpy,buf,False);
+       else name= None;
+       if ((tmp=fread(&wire,SIZEOF(xkmIndicatorMapDesc),1,file))<1) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmIndicators",0);
+           return -1;
+       }
+       nRead+= tmp*SIZEOF(xkmIndicatorMapDesc);
+       if (xkb->names) {
+           xkb->names->indicators[wire.indicator-1]= name;
+           if (changes)
+               changes->names.changed_indicators|= (1<<(wire.indicator-1));
+       }
+       map= &xkb->indicators->maps[wire.indicator-1];
+       map->flags= wire.flags;
+       map->which_groups= wire.which_groups;
+       map->groups= wire.groups;
+       map->which_mods= wire.which_mods;
+       map->mods.mask= wire.real_mods;
+       map->mods.real_mods= wire.real_mods;
+       map->mods.vmods= wire.vmods;
+       map->ctrls= wire.ctrls;
+    }
+    return nRead;
+}
+
+static XkbKeyTypePtr
+FindTypeForKey(XkbDescPtr xkb,Atom name,unsigned width,KeySym *syms)
+{
+    if ((!xkb)||(!xkb->map))
+       return NULL;
+    if (name!=None) {
+       register unsigned i;
+       for (i=0;i<xkb->map->num_types;i++) {
+           if (xkb->map->types[i].name==name) {
+#ifdef DEBUG
+               if (xkb->map->types[i].num_levels!=width)
+                   fprintf(stderr,"Group width mismatch between key and type\n");
+#endif
+               return &xkb->map->types[i];
+           }
+       }
+    }
+    if ((width<2)||((syms!=NULL)&&(syms[1]==NoSymbol)))
+       return &xkb->map->types[XkbOneLevelIndex];
+    if (syms!=NULL) {
+       if (XkbKSIsLower(syms[0])&&XkbKSIsUpper(syms[1]))
+           return &xkb->map->types[XkbAlphabeticIndex];
+       else if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1]))
+           return &xkb->map->types[XkbKeypadIndex];
+    }
+    return &xkb->map->types[XkbTwoLevelIndex];
+}
+
+static int
+ReadXkmSymbols(FILE *file,XkbFileInfo *result)
+{
+register int           i,g,s,totalVModMaps;
+xkmKeySymMapDesc       wireMap;
+char                   buf[100];
+unsigned               minKC,maxKC,groupNames,tmp;
+int                    nRead=0;
+XkbDescPtr             xkb;
+
+    xkb= result->xkb;
+    if ((tmp=XkmGetCountedString(file,buf,100))<1)
+       return -1;
+    nRead+= tmp;
+    minKC= XkmGetCARD8(file,&nRead);
+    maxKC= XkmGetCARD8(file,&nRead);
+    groupNames= XkmGetCARD8(file,&nRead);
+    totalVModMaps= XkmGetCARD8(file,&nRead);
+    if (XkbAllocNames(xkb,
+             XkbSymbolsNameMask|XkbPhysSymbolsNameMask|XkbGroupNamesMask,
+             0,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"physical names",0);
+       return -1;
+    }
+    if ((buf[0]!='\0')&&(xkb->names)) {
+       Atom name;
+       name= XkbInternAtom(xkb->dpy,buf,0);
+       xkb->names->symbols= name;
+       xkb->names->phys_symbols= name;
+    }
+    for (i=0,g=1;i<XkbNumKbdGroups;i++,g<<=1) {
+       if (groupNames&g) {
+           if ((tmp=XkmGetCountedString(file,buf,100))<1)
+               return -1;
+           nRead+= tmp;
+           if ((buf[0]!='\0')&&(xkb->names)) {
+               Atom name;
+               name= XkbInternAtom(xkb->dpy,buf,0);
+               xkb->names->groups[i]= name;
+           }
+           else xkb->names->groups[i]= None;
+       }
+    }
+    if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"server map",0);
+       return -1;
+    }
+    if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"client map",0);
+       return -1;
+    }
+    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"controls",0);
+       return -1;
+    }
+    if ((xkb->map==NULL)||(xkb->server==NULL))
+       return -1;
+    if (xkb->min_key_code<8)   xkb->min_key_code= minKC;
+    if (xkb->max_key_code<8)   xkb->max_key_code= maxKC;
+    if ((minKC>=8)&&(minKC<xkb->min_key_code))
+       xkb->min_key_code= minKC;
+    if ((maxKC>=8)&&(maxKC>xkb->max_key_code)) {
+       _XkbLibError(_XkbErrBadValue,"keys in symbol map",maxKC);
+       return -1;
+    }
+    for (i=minKC;i<=(int)maxKC;i++)  {
+       Atom            typeName[XkbNumKbdGroups];
+       XkbKeyTypePtr   type[XkbNumKbdGroups];
+       if ((tmp=fread(&wireMap,SIZEOF(xkmKeySymMapDesc),1,file))<1) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmSymbols",0);
+           return -1;
+       }
+       nRead+= tmp*SIZEOF(xkmKeySymMapDesc);
+       bzero((char *)typeName,XkbNumKbdGroups*sizeof(Atom));
+       bzero((char *)type,XkbNumKbdGroups*sizeof(XkbKeyTypePtr));
+       if (wireMap.flags&XkmKeyHasTypes) {
+           register int g;
+           for (g=0;g<XkbNumKbdGroups;g++) {
+               if ((wireMap.flags&(1<<g))&&
+                       ((tmp=XkmGetCountedString(file,buf,100))>0)) {
+                   typeName[g]= XkbInternAtom(xkb->dpy,buf,1);
+                   nRead+= tmp;
+               }
+               type[g]=FindTypeForKey(xkb,typeName[g],wireMap.width,NULL);
+               if (type[g]==NULL) {
+                   _XkbLibError(_XkbErrMissingTypes,"ReadXkmSymbols",0);
+                   return -1;
+               }
+               if (typeName[g]==type[g]->name)
+                   xkb->server->explicit[i]|= (1<<g);
+           }
+       }
+       if (wireMap.flags&XkmRepeatingKey) {
+           xkb->ctrls->per_key_repeat[i/8]|= (1<<(i%8));
+           xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
+       }
+       else if (wireMap.flags&XkmNonRepeatingKey) {
+           xkb->ctrls->per_key_repeat[i/8]&= ~(1<<(i%8));
+           xkb->server->explicit[i]|= XkbExplicitAutoRepeatMask;
+       }
+       xkb->map->modmap[i]= wireMap.modifier_map;
+       if (XkbNumGroups(wireMap.num_groups)>0) {
+           KeySym      *sym;
+           int          nSyms;
+
+           if (XkbNumGroups(wireMap.num_groups)>xkb->ctrls->num_groups)
+               xkb->ctrls->num_groups= wireMap.num_groups;
+           nSyms= XkbNumGroups(wireMap.num_groups)*wireMap.width;
+           sym= XkbResizeKeySyms(xkb,i,nSyms);
+           if (!sym)
+               return -1;
+           for (s=0;s<nSyms;s++) {
+               *sym++= XkmGetCARD32(file,&nRead);
+           }
+           if (wireMap.flags&XkmKeyHasActions) {
+               XkbAction *     act;
+               act= XkbResizeKeyActions(xkb,i,nSyms);
+               for (s=0;s<nSyms;s++,act++) {
+                   tmp=fread(act,SIZEOF(xkmActionDesc),1,file);
+                   nRead+= tmp*SIZEOF(xkmActionDesc);
+               }
+               xkb->server->explicit[i]|= XkbExplicitInterpretMask;
+           }
+       }
+       for (g=0;g<XkbNumGroups(wireMap.num_groups);g++) {
+           if (((xkb->server->explicit[i]&(1<<g))==0)||(type[g]==NULL)) {
+               KeySym *tmpSyms;
+               tmpSyms= XkbKeySymsPtr(xkb,i)+(wireMap.width*g);
+               type[g]= FindTypeForKey(xkb,None,wireMap.width,tmpSyms);
+           }
+           xkb->map->key_sym_map[i].kt_index[g]= type[g]-(&xkb->map->types[0]);
+       }
+       xkb->map->key_sym_map[i].group_info= wireMap.num_groups;
+       xkb->map->key_sym_map[i].width= wireMap.width;
+       if (wireMap.flags&XkmKeyHasBehavior) {
+           xkmBehaviorDesc     b;
+           tmp= fread(&b,SIZEOF(xkmBehaviorDesc),1,file);
+           nRead+= tmp*SIZEOF(xkmBehaviorDesc);
+           xkb->server->behaviors[i].type= b.type;
+           xkb->server->behaviors[i].data= b.data;
+           xkb->server->explicit[i]|= XkbExplicitBehaviorMask;
+       }
+    }
+    if (totalVModMaps>0) {
+       xkmVModMapDesc  v;
+       for (i=0;i<totalVModMaps;i++) {
+           tmp= fread(&v,SIZEOF(xkmVModMapDesc),1,file);
+           nRead+= tmp*SIZEOF(xkmVModMapDesc);
+           if (tmp>0)
+               xkb->server->vmodmap[v.key]= v.vmods;
+       }
+    }
+    return nRead;
+}
+
+static int
+ReadXkmGeomDoodad(
+    FILE *             file,
+    Display *          dpy,
+    XkbGeometryPtr     geom,
+    XkbSectionPtr      section)
+{
+XkbDoodadPtr   doodad;
+xkmDoodadDesc  doodadWire;
+char           buf[100];
+unsigned       tmp;
+int            nRead=0;
+
+    nRead+= XkmGetCountedString(file,buf,100);
+    tmp= fread(&doodadWire,SIZEOF(xkmDoodadDesc),1,file);
+    nRead+= SIZEOF(xkmDoodadDesc)*tmp;
+    doodad= XkbAddGeomDoodad(geom,section,XkbInternAtom(dpy,buf,False));
+    if (!doodad)
+       return nRead;
+    doodad->any.type= doodadWire.any.type;
+    doodad->any.priority= doodadWire.any.priority;
+    doodad->any.top= doodadWire.any.top;
+    doodad->any.left= doodadWire.any.left;
+    switch (doodadWire.any.type) {
+       case XkbOutlineDoodad:
+       case XkbSolidDoodad:
+           doodad->shape.angle= doodadWire.shape.angle;
+           doodad->shape.color_ndx= doodadWire.shape.color_ndx;
+           doodad->shape.shape_ndx= doodadWire.shape.shape_ndx;
+           break;
+       case XkbTextDoodad:
+           doodad->text.angle= doodadWire.text.angle;
+           doodad->text.width= doodadWire.text.width;
+           doodad->text.height= doodadWire.text.height;
+           doodad->text.color_ndx= doodadWire.text.color_ndx;
+           nRead+= XkmGetCountedString(file,buf,100);
+           doodad->text.text= _XkbDupString(buf);
+           nRead+= XkmGetCountedString(file,buf,100);
+           doodad->text.font= _XkbDupString(buf);
+           break;
+       case XkbIndicatorDoodad:
+           doodad->indicator.shape_ndx= doodadWire.indicator.shape_ndx;
+           doodad->indicator.on_color_ndx= doodadWire.indicator.on_color_ndx;
+           doodad->indicator.off_color_ndx= doodadWire.indicator.off_color_ndx;
+           break;
+       case XkbLogoDoodad:
+           doodad->logo.angle= doodadWire.logo.angle;
+           doodad->logo.color_ndx= doodadWire.logo.color_ndx;
+           doodad->logo.shape_ndx= doodadWire.logo.shape_ndx;
+           nRead+= XkmGetCountedString(file,buf,100);
+           doodad->logo.logo_name= _XkbDupString(buf);
+           break;
+       default:
+           /* report error? */
+           return nRead;
+    }
+    return nRead;
+}
+
+static int
+ReadXkmGeomOverlay(    FILE *          file,
+                       Display *       dpy,
+                       XkbGeometryPtr  geom,
+                       XkbSectionPtr   section)
+{
+char                   buf[100];
+unsigned               tmp;
+int                    nRead=0;
+XkbOverlayPtr          ol;
+XkbOverlayRowPtr       row;
+xkmOverlayDesc                 olWire;
+xkmOverlayRowDesc      rowWire;
+register int           r;
+
+    nRead+= XkmGetCountedString(file,buf,100);
+    tmp= fread(&olWire,SIZEOF(xkmOverlayDesc),1,file);
+    nRead+= tmp*SIZEOF(xkmOverlayDesc);
+    ol= XkbAddGeomOverlay(section,XkbInternAtom(dpy,buf,False),
+                                                       olWire.num_rows);
+    if (!ol)
+       return nRead;
+    for (r=0;r<olWire.num_rows;r++)  {
+       int                     k;
+       xkmOverlayKeyDesc       keyWire;
+       tmp= fread(&rowWire,SIZEOF(xkmOverlayRowDesc),1,file);
+       nRead+= tmp*SIZEOF(xkmOverlayRowDesc);
+       row= XkbAddGeomOverlayRow(ol,rowWire.row_under,rowWire.num_keys);
+       if (!row) {
+           _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomOverlay",0);
+          return nRead;
+       }
+       for (k=0;k<rowWire.num_keys;k++) {
+           tmp= fread(&keyWire,SIZEOF(xkmOverlayKeyDesc),1,file);
+           nRead+= tmp*SIZEOF(xkmOverlayKeyDesc);
+           memcpy(row->keys[k].over.name,keyWire.over,XkbKeyNameLength);
+           memcpy(row->keys[k].under.name,keyWire.under,XkbKeyNameLength);
+       }
+       row->num_keys= rowWire.num_keys;
+    }
+    return nRead;
+}
+
+static int
+ReadXkmGeomSection(    FILE *          file,
+                       Display *       dpy,
+                       XkbGeometryPtr  geom)
+{
+register int   i;
+XkbSectionPtr  section;
+xkmSectionDesc sectionWire;
+unsigned       tmp;
+int            nRead= 0;
+char           buf[100];
+Atom           nameAtom;
+
+    nRead+= XkmGetCountedString(file,buf,100);
+    nameAtom= XkbInternAtom(dpy,buf,False);
+    tmp= fread(&sectionWire,SIZEOF(xkmSectionDesc),1,file);
+    nRead+= SIZEOF(xkmSectionDesc)*tmp;
+    section= XkbAddGeomSection(geom,nameAtom,sectionWire.num_rows,
+                                               sectionWire.num_doodads,
+                                               sectionWire.num_overlays);
+    if (!section) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
+       return nRead;
+    }
+    section->top= sectionWire.top;
+    section->left= sectionWire.left;
+    section->width= sectionWire.width;
+    section->height= sectionWire.height;
+    section->angle= sectionWire.angle;
+    section->priority= sectionWire.priority;
+    if (sectionWire.num_rows>0) {
+       register int    k;
+       XkbRowPtr       row;
+       xkmRowDesc      rowWire;
+       XkbKeyPtr       key;
+       xkmKeyDesc      keyWire;
+
+       for (i=0;i<sectionWire.num_rows;i++) {
+           tmp= fread(&rowWire,SIZEOF(xkmRowDesc),1,file);
+           nRead+= SIZEOF(xkmRowDesc)*tmp;
+           row= XkbAddGeomRow(section,rowWire.num_keys);
+           if (!row) {
+               _XkbLibError(_XkbErrBadAlloc,"ReadXkmKeycodes",0);
+               return nRead;
+           }
+           row->top= rowWire.top;
+           row->left= rowWire.left;
+           row->vertical= rowWire.vertical;
+           for (k=0;k<rowWire.num_keys;k++) {
+               tmp= fread(&keyWire,SIZEOF(xkmKeyDesc),1,file);
+               nRead+= SIZEOF(xkmKeyDesc)*tmp;
+               key= XkbAddGeomKey(row);
+               if (!key) {
+                   _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeomSection",0);
+                   return nRead;
+               }
+               memcpy(key->name.name,keyWire.name,XkbKeyNameLength);
+               key->gap= keyWire.gap;
+               key->shape_ndx= keyWire.shape_ndx;
+               key->color_ndx= keyWire.color_ndx;
+           }
+       }
+    }
+    if (sectionWire.num_doodads>0) {
+       for (i=0;i<sectionWire.num_doodads;i++) {
+           tmp= ReadXkmGeomDoodad(file,dpy,geom,section);
+           nRead+= tmp;
+           if (tmp<1)
+               return nRead;
+       }
+    }
+    if (sectionWire.num_overlays>0) {
+       for (i=0;i<sectionWire.num_overlays;i++) {
+           tmp= ReadXkmGeomOverlay(file,dpy,geom,section);
+           nRead+= tmp;
+           if (tmp<1)
+               return nRead;
+       }
+    }
+    return nRead;
+}
+
+static int
+ReadXkmGeometry(FILE *file,XkbFileInfo *result)
+{
+register int           i;
+char                   buf[100];
+unsigned               tmp;
+int                    nRead= 0;
+xkmGeometryDesc                wireGeom;
+XkbGeometryPtr         geom;
+XkbGeometrySizesRec    sizes;
+
+    nRead+= XkmGetCountedString(file,buf,100);
+    tmp= fread(&wireGeom,SIZEOF(xkmGeometryDesc),1,file);
+    nRead+= tmp*SIZEOF(xkmGeometryDesc);
+    sizes.which= XkbGeomAllMask;
+    sizes.num_properties= wireGeom.num_properties;
+    sizes.num_colors= wireGeom.num_colors;
+    sizes.num_shapes= wireGeom.num_shapes;
+    sizes.num_sections= wireGeom.num_sections;
+    sizes.num_doodads= wireGeom.num_doodads;
+    sizes.num_key_aliases= wireGeom.num_key_aliases;
+    if (XkbAllocGeometry(result->xkb,&sizes)!=Success) {
+       _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
+       return nRead;
+    }
+    geom= result->xkb->geom;
+    geom->name= XkbInternAtom(result->xkb->dpy,buf,False);
+    geom->width_mm= wireGeom.width_mm;
+    geom->height_mm= wireGeom.height_mm;
+    nRead+= XkmGetCountedString(file,buf,100);
+    geom->label_font= _XkbDupString(buf);
+    if (wireGeom.num_properties>0) {
+       char val[1024];
+       for (i=0;i<wireGeom.num_properties;i++) {
+           nRead+= XkmGetCountedString(file,buf,100);
+           nRead+= XkmGetCountedString(file,val,1024);
+           if (XkbAddGeomProperty(geom,buf,val)==NULL) {
+               _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
+               return nRead;
+           }
+       }
+    }
+    if (wireGeom.num_colors>0) {
+       for (i=0;i<wireGeom.num_colors;i++) {
+           nRead+= XkmGetCountedString(file,buf,100);
+           if (XkbAddGeomColor(geom,buf,i)==NULL) {
+               _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
+               return nRead;
+           }
+       }
+    }
+    geom->base_color= &geom->colors[wireGeom.base_color_ndx];
+    geom->label_color= &geom->colors[wireGeom.label_color_ndx];
+    if (wireGeom.num_shapes>0) {
+       XkbShapePtr     shape;
+       xkmShapeDesc    shapeWire;
+       Atom            nameAtom;
+       for (i=0;i<wireGeom.num_shapes;i++) {
+           register int        n;
+           XkbOutlinePtr       ol;
+           xkmOutlineDesc      olWire;
+           nRead+= XkmGetCountedString(file,buf,100);
+           nameAtom= XkbInternAtom(result->xkb->dpy,buf,False);
+           tmp= fread(&shapeWire,SIZEOF(xkmShapeDesc),1,file);
+           nRead+= tmp*SIZEOF(xkmShapeDesc);
+           shape= XkbAddGeomShape(geom,nameAtom,shapeWire.num_outlines);
+           if (!shape) {
+               _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
+               return nRead;
+           }
+           for (n=0;n<shapeWire.num_outlines;n++) {
+               register int    p;
+               xkmPointDesc    ptWire;
+               tmp= fread(&olWire,SIZEOF(xkmOutlineDesc),1,file);
+               nRead+= tmp*SIZEOF(xkmOutlineDesc);
+               ol= XkbAddGeomOutline(shape,olWire.num_points);
+               if (!ol) {
+                   _XkbLibError(_XkbErrBadAlloc,"ReadXkmGeometry",0);
+                   return nRead;
+               }
+               ol->num_points= olWire.num_points;
+               ol->corner_radius= olWire.corner_radius;
+               for (p=0;p<olWire.num_points;p++) {
+                   tmp= fread(&ptWire,SIZEOF(xkmPointDesc),1,file);
+                   nRead+= tmp*SIZEOF(xkmPointDesc);
+                   ol->points[p].x= ptWire.x;
+                   ol->points[p].y= ptWire.y;
+                   if (ptWire.x<shape->bounds.x1) shape->bounds.x1= ptWire.x;
+                   if (ptWire.x>shape->bounds.x2) shape->bounds.x2= ptWire.x;
+                   if (ptWire.y<shape->bounds.y1) shape->bounds.y1= ptWire.y;
+                   if (ptWire.y>shape->bounds.y2) shape->bounds.y2= ptWire.y;
+               }
+           }
+           if (shapeWire.primary_ndx!=XkbNoShape)
+               shape->primary= &shape->outlines[shapeWire.primary_ndx];
+           if (shapeWire.approx_ndx!=XkbNoShape)
+               shape->approx= &shape->outlines[shapeWire.approx_ndx];
+       }
+    }
+    if (wireGeom.num_sections>0) {
+       for (i=0;i<wireGeom.num_sections;i++) {
+           tmp= ReadXkmGeomSection(file,result->xkb->dpy,geom);
+           nRead+= tmp;
+           if (tmp==0)
+               return nRead;
+       }
+    }
+    if (wireGeom.num_doodads>0) {
+       for (i=0;i<wireGeom.num_doodads;i++) {
+           tmp= ReadXkmGeomDoodad(file,result->xkb->dpy,geom,NULL);
+           nRead+= tmp;
+           if (tmp==0)
+               return nRead;
+       }
+    }
+    if ((wireGeom.num_key_aliases>0)&&(geom->key_aliases)) {
+       int sz= XkbKeyNameLength*2;
+       int num= wireGeom.num_key_aliases;
+       if (fread(geom->key_aliases,sz,num,file)!=num) {
+           _XkbLibError(_XkbErrBadLength,"ReadXkmGeometry",0);
+           return -1;
+       }
+       nRead+= (num*sz);
+       geom->num_key_aliases= num;
+    }
+    return nRead;
+}
+
+Bool
+XkmProbe(FILE *file)
+{
+unsigned hdr,tmp;
+int     nRead=0;
+
+    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
+    tmp= XkmGetCARD32(file,&nRead);
+    if (tmp!=hdr) {
+       if ((tmp&(~0xff))==(hdr&(~0xff))) {
+           _XkbLibError(_XkbErrBadFileVersion,"XkmProbe",tmp&0xff);
+       }
+       return 0;
+    }
+    return 1;
+}
+
+Bool
+XkmReadTOC(FILE *file,xkmFileInfo* file_info,int max_toc,xkmSectionInfo *toc)
+{
+unsigned hdr,tmp;
+int    nRead=0;
+unsigned i,size_toc;
+
+    hdr= (('x'<<24)|('k'<<16)|('m'<<8)|XkmFileVersion);
+    tmp= XkmGetCARD32(file,&nRead);
+    if (tmp!=hdr) {
+       if ((tmp&(~0xff))==(hdr&(~0xff))) {
+           _XkbLibError(_XkbErrBadFileVersion,"XkmReadTOC",tmp&0xff);
+       }
+       else {
+           _XkbLibError(_XkbErrBadFileType,"XkmReadTOC",tmp);
+       }
+       return 0;
+    }
+    fread(file_info,SIZEOF(xkmFileInfo),1,file);
+    size_toc= file_info->num_toc;
+    if (size_toc>max_toc) {
+#ifdef DEBUG
+       fprintf(stderr,"Warning! Too many TOC entries; last %d ignored\n",
+                                                       size_toc-max_toc);
+#endif
+       size_toc= max_toc;
+    }
+    for (i=0;i<size_toc;i++) {
+       fread(&toc[i],SIZEOF(xkmSectionInfo),1,file);
+    }
+    return 1;
+}
+
+xkmSectionInfo *
+XkmFindTOCEntry(xkmFileInfo *finfo,xkmSectionInfo *toc,unsigned type)
+{
+register int i;
+
+    for (i=0;i<finfo->num_toc;i++) {
+       if (toc[i].type==type)
+           return &toc[i];
+    }
+    return NULL;
+}
+
+Bool
+XkmReadFileSection(    FILE *                  file,
+                       xkmSectionInfo *        toc,
+                       XkbFileInfo *           result,
+                       unsigned *              loaded_rtrn)
+{
+xkmSectionInfo         tmpTOC;
+int                    nRead;
+
+    if ((!result)||(!result->xkb)) {
+       _XkbLibError(_XkbErrBadMatch,"XkmReadFileSection",0);
+       return 0;
+    }
+    fseek(file,toc->offset,SEEK_SET);
+    fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file);
+    nRead= SIZEOF(xkmSectionInfo);
+    if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)||
+       (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) {
+       _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSection",0);
+       return 0;
+    }
+    switch (tmpTOC.type) {
+       case XkmVirtualModsIndex:
+           nRead+= ReadXkmVirtualMods(file,result,NULL);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmVirtualModsMask;
+           break;
+       case XkmTypesIndex:
+           nRead+= ReadXkmKeyTypes(file,result,NULL);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmTypesMask;
+           break;
+       case XkmCompatMapIndex:
+           nRead+= ReadXkmCompatMap(file,result,NULL);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmCompatMapMask;
+           break;
+       case XkmKeyNamesIndex:
+           nRead+= ReadXkmKeycodes(file,result,NULL);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmKeyNamesMask;
+           break;
+       case XkmSymbolsIndex:
+           nRead+= ReadXkmSymbols(file,result);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmSymbolsMask;
+           break;
+       case XkmIndicatorsIndex:
+           nRead+= ReadXkmIndicators(file,result,NULL);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmIndicatorsMask;
+           break;
+       case XkmGeometryIndex:
+           nRead+= ReadXkmGeometry(file,result);
+           if ((loaded_rtrn)&&(nRead>=0))
+               *loaded_rtrn|= XkmGeometryMask;
+           break;
+       default:
+           _XkbLibError(_XkbErrBadImplementation,
+                               XkbConfigText(tmpTOC.type,XkbMessage),0);
+           nRead= 0;
+           break;
+    }
+    if (nRead!=tmpTOC.size) {
+       _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
+                                               nRead-tmpTOC.size);
+       return 0;
+    }
+    return (nRead>=0);
+}
+
+char *
+XkmReadFileSectionName(FILE *file,xkmSectionInfo *toc)
+{
+xkmSectionInfo tmpTOC;
+char           name[100];
+
+    if ((!file)||(!toc))
+       return NULL;
+    switch (toc->type) {
+       case XkmVirtualModsIndex:
+       case XkmIndicatorsIndex:
+           break;
+       case XkmTypesIndex:
+       case XkmCompatMapIndex:
+       case XkmKeyNamesIndex:
+       case XkmSymbolsIndex:
+       case XkmGeometryIndex:
+           fseek(file,toc->offset,SEEK_SET);
+           fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file);
+           if ((tmpTOC.type!=toc->type)||(tmpTOC.format!=toc->format)||
+               (tmpTOC.size!=toc->size)||(tmpTOC.offset!=toc->offset)) {
+               _XkbLibError(_XkbErrIllegalContents,"XkmReadFileSectionName",0);
+               return NULL;
+           }
+           if (XkmGetCountedString(file,name,100)>0)
+               return _XkbDupString(name);
+           break;
+       default:
+           _XkbLibError(_XkbErrBadImplementation,
+                               XkbConfigText(tmpTOC.type,XkbMessage),0);
+           break;
+    }
+    return NULL;
+}
+
+/***====================================================================***/
+
+#define        MAX_TOC 16
+unsigned
+XkmReadFile(FILE *file,unsigned need,unsigned want,XkbFileInfo *result)
+{
+register unsigned      i;
+xkmSectionInfo         toc[MAX_TOC],tmpTOC;
+xkmFileInfo            fileInfo;
+unsigned               tmp,nRead=0;
+unsigned               which= need|want;
+
+    if (!XkmReadTOC(file,&fileInfo,MAX_TOC,toc))
+       return which;
+    if ((fileInfo.present&need)!=need) {
+       _XkbLibError(_XkbErrIllegalContents,"XkmReadFile",
+                                                       need&(~fileInfo.present));
+       return which;
+    }
+    result->type= fileInfo.type;
+    if (result->xkb==NULL)
+       result->xkb= XkbAllocKeyboard();
+    for (i=0;i<fileInfo.num_toc;i++) {
+#ifdef SEEK_SET
+       fseek(file,toc[i].offset,SEEK_SET);
+#else
+       fseek(file,toc[i].offset,0);
+#endif
+       tmp= fread(&tmpTOC,SIZEOF(xkmSectionInfo),1,file);
+       nRead= tmp*SIZEOF(xkmSectionInfo);
+       if ((tmpTOC.type!=toc[i].type)||(tmpTOC.format!=toc[i].format)||
+           (tmpTOC.size!=toc[i].size)||(tmpTOC.offset!=toc[i].offset)) {
+           return which;
+       }
+       if ((which&(1<<tmpTOC.type))==0) {
+           continue;
+       }
+       switch (tmpTOC.type) {
+           case XkmVirtualModsIndex:
+               tmp= ReadXkmVirtualMods(file,result,NULL);
+               break;
+           case XkmTypesIndex:
+               tmp= ReadXkmKeyTypes(file,result,NULL);
+               break;
+           case XkmCompatMapIndex:
+               tmp= ReadXkmCompatMap(file,result,NULL);
+               break;
+           case XkmKeyNamesIndex:
+               tmp= ReadXkmKeycodes(file,result,NULL);
+               break;
+           case XkmIndicatorsIndex:
+               tmp= ReadXkmIndicators(file,result,NULL);
+               break;
+           case XkmSymbolsIndex:
+               tmp= ReadXkmSymbols(file,result);
+               break;
+           case XkmGeometryIndex:
+               tmp= ReadXkmGeometry(file,result);
+               break;
+           default:
+               _XkbLibError(_XkbErrBadImplementation,
+                               XkbConfigText(tmpTOC.type,XkbMessage),0);
+               tmp= 0;
+               break;
+       }
+       if (tmp>0) {
+           nRead+= tmp;
+           which&= ~(1<<toc[i].type);
+           result->defined|= (1<<toc[i].type);
+       }
+       if (nRead!=tmpTOC.size) {
+           _XkbLibError(_XkbErrBadLength,XkbConfigText(tmpTOC.type,XkbMessage),
+                                                       nRead-tmpTOC.size);
+       }
+    }
+    return which;
+}
diff --git a/xkbfile.pc.in b/xkbfile.pc.in
new file mode 100644 (file)
index 0000000..5079d5d
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: xkbfile
+Description: The xkbfile Library
+Version: @PACKAGE_VERSION@
+Requires: kbproto
+Requires.private: x11
+Cflags: -I${includedir}
+Libs: -L${libdir} -lxkbfile