Initial revision
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9cee037
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Keith Packard <keithp@keithp.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..6a4d888
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,22 @@
+$XFree86: $
+
+Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission.  Keith Packard makes no
+representations about the suitability of this software for any purpose.  It
+is provided "as is" without express or implied warranty.
+
+KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL KEITH PACKARD 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
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..6798b36
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,3 @@
+The configuration files (fonts.conf, fonts.dtd) go in a new directory
+/etc/fonts, the install step doesn't current create this directory or copy
+the config files.
diff --git a/Imakefile b/Imakefile
new file mode 100644
index 0000000..3c26d2d
--- /dev/null
+++ b/Imakefile
@@ -0,0 +1,25 @@
+#define IHaveSubdirs
+#define PassCDebugFlags
+
+LINTSUBDIRS=src fc-cache fc-list
+
+SUBDIRS=fontconfig $(LINTSUBDIRS)
+
+#ifndef FontconfigDir
+#define FontconfigDir /etc/fonts
+#endif
+
+FONTCONFIGDIR=FontconfigDir
+
+MakeSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+MakeLintLibSubdirs($(LINTSUBDIRS))
+MakeLintSubdirs($(LINTSUBDIRS),install.ln,install.ln)
+
+InstallNonExecFileNoClobber(fonts.conf,$(FONTCONFIGDIR))
+InstallNonExecFileNoClobber(fonts.dtd,$(FONTCONFIGDIR))
+
+all:: fonts.conf
+
+fonts.conf: fonts.conf.in
+	sh ./setfontdirs
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..98f0fca
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+			Fontconfig
+	Font configuration and customization library
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..8ed6317
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,2 @@
+#undef HAVE_FREETYPE 
+#undef FC_FALLBACK_FONTS
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..0cfcba0
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,202 @@
+AC_INIT(fontconfig/fontconfig.h)
+
+AC_PREREQ(2.13)
+
+FC_MAJOR=1
+FC_MINOR=0
+FC_SUB=1
+FC_PRE=
+FC_IFACE_AGE=0
+FC_BIN_AGE=0
+
+AC_SUBST(FC_MAJOR)
+AC_SUBST(FC_MINOR)
+AC_SUBST(FC_SUB)
+AC_SUBST(FC_IFACE_AGE)
+AC_SUBST(FC_BIN_AGE)
+
+LT_RELEASE=$FC_MAJOR.$FC_MINOR
+LT_CURRENT=`expr $FC_SUB - $FC_IFACE_AGE`
+LT_REVISION=$FC_IFACE_AGE
+LT_AGE=`expr $FC_BIN_AGE - $FC_IFACE_AGE`
+AC_SUBST(LT_RELEASE)
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
+AM_INIT_AUTOMAKE("fontconfig", $FC_MAJOR.$FC_MINOR.$FC_SUB$FC_PRE)
+
+AC_CANONICAL_HOST
+AM_CONFIG_HEADER(config.h)
+
+AC_ARG_WITH(freetype_includes, [  --with-freetype-includes=DIR  Use FreeType includes in DIR], freetype_includes=$withval, freetype_includes=yes)
+AC_ARG_WITH(freetype_lib,      [  --with-freetype-lib=DIR       Use FreeType library in DIR], freetype_lib=$withval, freetype_lib=yes)
+AC_ARG_WITH(freetype_config,   [  --with-freeetype-config=PROG  Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=yes)
+AC_ARG_WITH(xml2_includes,     [  --with-xml2-includes=DIR      Use xml2 includes in DIR], xml2_includes=$withval, xml2_includes=yes)
+AC_ARG_WITH(xml2_lib,          [  --with-xml2-lib=DIR           Use xml2 library in DIR], xml2_lib=$withval, xml2_lib=yes)
+AC_ARG_WITH(xml2_config,       [  --with-freeetype-config=PROG  Use FreeType configuration program PROG], xml2_config=$withval, xml2_config=yes)
+AC_ARG_WITH(fallback_fonts,    [  --with-fallback-fonts=DIR     Use fonts from DIR when config is busted], fallback_fonts="$withval", fallback_fonts=yes)
+AC_ISC_POSIX
+AC_PROG_CC
+AC_STDC_HEADERS
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+
+AC_PROG_LN_S
+
+dnl
+dnl Libtool
+dnl
+AM_DISABLE_STATIC
+AM_PROG_LIBTOOL
+AC_SUBST(LIBTOOL_DEPS)
+if libtool --features | grep "enable static" >/dev/null; then
+  STATIC="-static"
+else
+  STATIC=
+fi
+AC_SUBST(STATIC)
+
+AC_SUBST(DEBUG_CFLAGS)
+AC_SUBST(GLOBAL_CFLAGS)
+
+AC_CHECK_FUNCS(getopt_long getopt)
+
+case "$freetype_config" in
+no)
+	;;
+yes)
+	AC_CHECK_PROG(ft_config, freetype-config, freetype-config, no)
+	;;
+*)
+	ft_config="$freetype_config"
+	;;
+esac
+
+case "$freetype_includes" in
+no)
+	freetype_includes=""
+	;;
+yes)
+	case "$ft_config" in
+	no)
+		freetype_includes=""
+		;;
+	*)
+		freetype_includes="`$ft_config --cflags`"
+		;;
+	esac
+	;;
+*)
+	freetype_includes="-I$freetype_includes"
+	;;
+esac
+
+case "$freetype_lib" in
+no)
+	freetype_lib=""
+	;;
+yes)
+	case "$ft_config" in
+	no)
+		freetype_lib=""
+		;;
+	*)
+		freetype_lib="`$ft_config --libs`"
+		;;
+	esac
+	;;
+*)
+	freetype_lib="-L$freetype_lib -lfreetype"
+	;;
+esac
+
+case "$fallback_fonts" in
+yes)
+	AC_DEFINE_UNQUOTED(FC_FALLBACK_FONTS, "/usr/X11R6/lib/X11/fonts/Type1")
+	;;
+*)
+	AC_DEFINE_UNQUOTED(FC_FALLBACK_FONTS, "$fallback_fonts")
+	;;
+esac
+
+saved_LIBS="$LIBS"
+LIBS="$LIBS $freetype_lib"
+saved_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $freetype_includes"
+AC_CHECK_HEADERS(ft2build.h)
+
+case "$ac_cv_header_ft2build_h" in
+no)
+	CPPFLAGS="$saved_CPPFLAGS"
+	LIBS="$saved_LIBS"
+	;;
+yes)
+	AC_CHECK_FUNCS(FT_Init_FreeType)
+	case "$ac_cv_func_FT_Init_FreeType" in
+	no)
+		CPPFLAGS="$saved_CPPFLAGS"
+		LIBS="$saved_LIBS"
+		;;
+	yes)
+		AC_DEFINE(HAVE_FREETYPE)
+		;;
+	esac
+	;;
+esac
+
+case "$xml2_config" in
+no)
+	;;
+yes)
+	AC_CHECK_PROG(xml2_config_prog, xml2-config, xml2-config, no)
+	;;
+*)
+	;;
+esac
+
+case "$xml2_includes" in
+no)
+	xml2_includes=""
+	;;
+yes)
+	case "$xml2_config_prog" in
+	no)
+		xml2_includes=""
+		;;
+	*)
+		xml2_includes="`$xml2_config_prog --cflags`"
+		;;
+	esac
+	;;
+*)
+	xml2_includes="-I$xml2_includes"
+	;;
+esac
+
+case "$xml2_lib" in
+no)
+	xml2_lib=""
+	;;
+yes)
+	case "$xml2_config_prog" in
+	no)
+		xml2_lib=""
+		;;
+	*)
+		xml2_lib="`$xml2_config_prog --libs`"
+		;;
+	esac
+	;;
+*)
+	xml2_lib="-L$xml2_lib -lxml2"
+	;;
+esac
+
+saved_LIBS="$LIBS"
+LIBS="$LIBS $xml2_lib"
+saved_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $xml2_includes"
+AC_CHECK_HEADERS(xmlversion.h)
+
+AC_OUTPUT(Makefile src/Makefile fontconfig/Makefile fc-cache/Makefile fc-list/Makefile)
diff --git a/cvscompile.sh b/cvscompile.sh
new file mode 100644
index 0000000..371f458
--- /dev/null
+++ b/cvscompile.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+aclocal
+autoheader
+automake -a
+autoconf
+
diff --git a/doc/fontconfig.tex b/doc/fontconfig.tex
new file mode 100644
index 0000000..2e60a51
--- /dev/null
+++ b/doc/fontconfig.tex
@@ -0,0 +1,55 @@
+\documentclass[10pt]{article}
+\usepackage{latexsym}
+\usepackage{epsfig}
+\usepackage{times}
+
+\begin{document}
+\date{}
+\title{The Fontconfig Library:\\
+Architecture and Users Guide}
+\author{Keith Packard\\
+{\em XFree86 Core Team}\\
+keithp@keithp.com}
+\maketitle
+\thispagestyle{empty}
+
+\abstract
+
+The Fontconfig library provides for central administration and configuration
+of fonts in a POSIX system.  All font consumers can share a common database
+of fonts and use common matching rules for font names.  The set of available
+fonts can be configured for each user and a set of configurable matching
+rules allow for customizing the selection of fonts and configuring various
+parameters related to rasterizing of those fonts for display in a variety of
+media.  The Fontconfig library is designed to co-exist peacefully with
+existing font configuration and rasterization mechanisms; while it uses the
+FreeType library to discover characteristics of available fonts, there
+is no requirement to use FreeType for rasterization.
+
+\section				{Introduction}
+
+\section				{Configuration Files}
+
+\section				{Application Interface}
+
+\subsection				{Datatypes}
+
+\subsection				{Font Set Interface}
+
+\subsection				{Font Patterns}
+
+\subsection				{Listing Available Fonts}
+
+\subsection				{Using Font Names}
+
+\subsection				{Manipulating Matrices}
+
+\subsection				{UTF-8 Helper Functions}
+
+\section				{Font Sub-System Interface}
+
+\subsection				{Extending Font Names}
+
+\subsection				{Executing Configuration Rules}
+
+\end{document}
diff --git a/fc-cache/Imakefile b/fc-cache/Imakefile
new file mode 100644
index 0000000..12216e7
--- /dev/null
+++ b/fc-cache/Imakefile
@@ -0,0 +1,19 @@
+#include "../../libxml2/config.h"
+#if HAVE_ZLIB_H
+ZLIB=-lz
+#endif
+
+INCLUDES=-I../../freetype2 -I/usr/include/libxml2 -I..
+FREETYPE2REQLIB = ../../freetype2/libfreetype.a
+XML2REQLIB=../../libxml2/.libs/libxml2.a $(ZLIB) -lm
+
+LOCAL_LIBRARIES=-L../src -lfontconfig $(FREETYPE2REQLIB) $(XML2REQLIB)
+
+SRCS=fc-cache.c
+OBJS=fc-cache.o
+
+ComplexProgramTarget(fc-cache)
+LinkBuildBinary(ProgramTargetName(fc-cache))
+
+install::
+	FC_DEBUG=128 FONTCONFIG_PATH=.. ./fc-cache -v
diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
new file mode 100644
index 0000000..6e84ccd
--- /dev/null
+++ b/fc-cache/fc-cache.c
@@ -0,0 +1,145 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <fontconfig/fontconfig.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#else
+#define HAVE_GETOPT 1
+#endif
+
+#if HAVE_GETOPT_LONG
+#define _GNU_SOURCE
+#include <getopt.h>
+const struct option longopts[] = {
+    {"version", 0, 0, 'V'},
+    {"verbose", 0, 0, 'v'},
+    {"help", 0, 0, '?'},
+    {NULL,0,0,0},
+};
+#else
+#if HAVE_GETOPT
+extern char *optarg;
+extern int optind, opterr, optopt;
+#endif
+#endif
+
+void usage (char *program)
+{
+    fprintf (stderr, "usage: %s [-vV?] [--verbose] [--version] [--help] [dirs]\n",
+	     program);
+    fprintf (stderr, "Build font information caches in [dirs]\n"
+	     "(all directories in font configuration by default).\n");
+    fprintf (stderr, "\n");
+    fprintf (stderr, "  -v, --verbose        display status information while busy\n");
+    fprintf (stderr, "  -V, --version        display font config version and exit\n");
+    fprintf (stderr, "  -?, --help           display this help and exit\n");
+    exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+    int		ret = 0;
+    FcFontSet	*set;
+    char	**dirs;
+    int		verbose = 0;
+    int		i;
+#if HAVE_GETOPT_LONG || HAVE_GETOPT
+    int		c;
+
+#if HAVE_GETOPT_LONG
+    while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1)
+#else
+    while ((c = getopt (argc, argv, "Vv?")) != -1)
+#endif
+    {
+	switch (c) {
+	case 'V':
+	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
+		     FC_MAJOR, FC_MINOR, FC_REVISION);
+	    exit (0);
+	case 'v':
+	    verbose = 1;
+	    break;
+	default:
+	    usage (argv[0]);
+	}
+    }
+    i = optind;
+#else
+    i = 1;
+#endif
+
+    if (!FcInitConfig ())
+    {
+	fprintf (stderr, "Can't init font config library\n");
+	return 1;
+    }
+    if (argv[i])
+	dirs = argv+i;
+    else
+	dirs = FcConfigGetDirs (0);
+    /*
+     * Now scan all of the directories into separate databases
+     * and write out the results
+     */
+    while (dirs && *dirs)
+    {
+	if (verbose)
+	    printf ("%s: Scanning directory \"%s\"\n", argv[0], *dirs);
+	set = FcFontSetCreate ();
+	if (!set)
+	{
+	    fprintf (stderr, "Out of memory in \"%s\"\n", *dirs);
+	    ret++;
+	}
+	else
+	{
+	    if (!FcDirScan (set, 0, FcConfigGetBlanks (0), *dirs, FcTrue))
+	    {
+		fprintf (stderr, "Can't scan directory \"%s\"\n", *dirs);
+		ret++;
+	    }
+	    else
+	    {
+		if (verbose)
+		    printf ("%s: Saving %d font names for \"%s\"\n", 
+			    argv[0], set->nfont, *dirs);
+		if (!FcDirSave (set, *dirs))
+		{
+		    fprintf (stderr, "Can't save cache in \"%s\"\n", *dirs);
+		    ret++;
+		}
+	    }
+	    FcFontSetDestroy (set);
+	}
+	++dirs;
+    }
+    if (verbose)
+	printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded");
+    return ret;
+}
diff --git a/fc-cache/fc-cache.man b/fc-cache/fc-cache.man
new file mode 100644
index 0000000..6fc4ed9
--- /dev/null
+++ b/fc-cache/fc-cache.man
@@ -0,0 +1,45 @@
+.\"
+.\" Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+.\" advertising or publicity pertaining to distribution of the software without
+.\" specific, written prior permission.  Keith Packard makes no
+.\" representations about the suitability of this software for any purpose.  It
+.\" is provided "as is" without express or implied warranty.
+.\"
+.\" KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+.\" EVENT SHALL KEITH PACKARD 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.
+.\"
+.\"
+.\" $XFree86: xc/programs/fc-cache/fc-cache.man,v 1.3 2001/02/09 03:47:56 tsi Exp $
+.\"
+.TH FC-CACHE 1 __vendorversion__
+.SH NAME
+fc-cache, fonts.cache \- create an index of FreeType font files in a directory
+.SH SYNOPSIS
+.B "fc-cache"
+.RI [ directory-name
+\|.\|.\|. ]
+.SH DESCRIPTION
+If directory arguments are not given,
+.I fc-cache
+uses each directory in the current font configuration.  Each directory is
+scanned for font files readable by FreeType.  A cache is created which
+contains properties of each font and the associated filename.  This cache is
+used to speed application startup when using the fontconfig library.
+.SH FILES
+.TP 15
+.B fonts.cache
+Maps file names to font properties.  Read by the fontconfig library at
+application startup to locate appropriate fonts.
+.SH "SEE ALSO"
+fontconfig(3)
diff --git a/fc-list/Imakefile b/fc-list/Imakefile
new file mode 100644
index 0000000..a773b45
--- /dev/null
+++ b/fc-list/Imakefile
@@ -0,0 +1,17 @@
+#include "../../libxml2/config.h"
+#if HAVE_ZLIB_H
+ZLIB=-lz
+#endif
+
+INCLUDES=-I../../freetype2 -I/usr/include/libxml2 -I..
+FREETYPE2REQLIB = ../../freetype2/libfreetype.a
+XML2REQLIB=../../libxml2/.libs/libxml2.a $(ZLIB) -lm
+
+LOCAL_LIBRARIES=-L../src -lfontconfig $(FREETYPE2REQLIB) $(XML2REQLIB)
+DEPLIBS=../src/libfontconfig.a
+
+SRCS=fc-list.c
+OBJS=fc-list.o
+
+ComplexProgramTarget(fc-list)
+LinkBuildBinary(ProgramTargetName(fc-list))
diff --git a/fc-list/fc-list.c b/fc-list/fc-list.c
new file mode 100644
index 0000000..67d7120
--- /dev/null
+++ b/fc-list/fc-list.c
@@ -0,0 +1,128 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <fontconfig/fontconfig.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#else
+#define HAVE_GETOPT 1
+#endif
+
+#if HAVE_GETOPT_LONG
+#define _GNU_SOURCE
+#include <getopt.h>
+const struct option longopts[] = {
+    {"version", 0, 0, 'V'},
+    {"verbose", 0, 0, 'v'},
+    {"help", 0, 0, '?'},
+    {NULL,0,0,0},
+};
+#else
+#if HAVE_GETOPT
+extern char *optarg;
+extern int optind, opterr, optopt;
+#endif
+#endif
+
+void usage (char *program)
+{
+    fprintf (stderr, "usage: %s [-vV?] [--verbose] [--version] [--help] [dirs]\n",
+	     program);
+    fprintf (stderr, "Build font information caches in [dirs]\n"
+	     "(all directories in font configuration by default).\n");
+    fprintf (stderr, "\n");
+    fprintf (stderr, "  -v, --verbose        display status information while busy\n");
+    fprintf (stderr, "  -V, --version        display font config version and exit\n");
+    fprintf (stderr, "  -?, --help           display this help and exit\n");
+    exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+    int		ret = 0;
+    FcFontSet	*set;
+    int		verbose = 0;
+    int		i;
+    FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_LANG, 0);
+    FcFontSet	*fs;
+    FcPattern   *pat;
+#if HAVE_GETOPT_LONG || HAVE_GETOPT
+    int		c;
+
+#if HAVE_GETOPT_LONG
+    while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1)
+#else
+    while ((c = getopt (argc, argv, "Vv?")) != -1)
+#endif
+    {
+	switch (c) {
+	case 'V':
+	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
+		     FC_MAJOR, FC_MINOR, FC_REVISION);
+	    exit (0);
+	case 'v':
+	    verbose = 1;
+	    break;
+	default:
+	    usage (argv[0]);
+	}
+    }
+    i = optind;
+#else
+    i = 1;
+#endif
+
+    if (!FcInit ())
+    {
+	fprintf (stderr, "Can't init font config library\n");
+	return 1;
+    }
+    if (argv[i])
+	pat = FcNameParse (argv[i]);
+    else
+	pat = FcPatternCreate ();
+    
+    fs = FcFontList (0, pat, os);
+    if (pat)
+	FcPatternDestroy (pat);
+
+    if (fs)
+    {
+	int	j;
+
+	for (j = 0; j < fs->nfont; j++)
+	{
+	    FcChar8 *font;
+
+	    font = FcNameUnparse (fs->fonts[j]);
+	    printf ("%s\n", font);
+	    free (font);
+	}
+	FcFontSetDestroy (fs);
+    }
+    return 0;
+}
diff --git a/fc-list/fc-list.man b/fc-list/fc-list.man
new file mode 100644
index 0000000..87eb792
--- /dev/null
+++ b/fc-list/fc-list.man
@@ -0,0 +1,36 @@
+.\"
+.\" Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+.\" advertising or publicity pertaining to distribution of the software without
+.\" specific, written prior permission.  Keith Packard makes no
+.\" representations about the suitability of this software for any purpose.  It
+.\" is provided "as is" without express or implied warranty.
+.\"
+.\" KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+.\" EVENT SHALL KEITH PACKARD 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.
+.\"
+.\"
+.\" $XFree86: xc/programs/fc-list/fc-list.man,v 1.3 2001/02/09 03:47:56 tsi Exp $
+.\"
+.TH FC-LIST 1 __vendorversion__
+.SH NAME
+fc-list \- list available fonts
+.SH SYNOPSIS
+.B "fc-list"
+.RI [ font-pattern ]
+.SH DESCRIPTION
+If font pattern is not given,
+.I fc-list
+lists all available faces and styles in the current font configuration.
+.SH "SEE ALSO"
+fontconfig(3)
diff --git a/findfonts b/findfonts
new file mode 100755
index 0000000..2666f8d
--- /dev/null
+++ b/findfonts
@@ -0,0 +1,8 @@
+#!/bin/sh
+dirs="/usr/share/fonts /usr/X11R6/lib/X11/fonts"
+for d in $dirs; do
+    find $d \( -name '*.[Tt][Tt][Ff]' -o -name '*.[Pp][Ff][BbAa]' \) -print
+done | while read f; do
+	dir=`dirname $f`
+	echo $dir
+done | sort -u | sed 's/^/	<dir>/' | sed 's;$;</dir>;'
diff --git a/fontconfig/Imakefile b/fontconfig/Imakefile
new file mode 100644
index 0000000..be1f65c
--- /dev/null
+++ b/fontconfig/Imakefile
@@ -0,0 +1,8 @@
+#define IncSubdir fontconfig
+
+HEADERS=fcfreetype.h fcprivate.h fcxml.h fontconfig.h
+
+BuildIncludes($(HEADERS),IncSubdir,..)
+#if BuildLibraries
+InstallMultipleFlags($(HEADERS),$(INCDIR)/IncSubdir,$(INSTINCFLAGS))
+#endif
diff --git a/fontconfig/fcfreetype.h b/fontconfig/fcfreetype.h
new file mode 100644
index 0000000..14f342b
--- /dev/null
+++ b/fontconfig/fcfreetype.h
@@ -0,0 +1,34 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _FCFREETYPE_H_
+#define _FCFREETYPE_H_
+
+FT_UInt
+FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4);
+
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks);
+
+#endif
diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h
new file mode 100644
index 0000000..490ca33
--- /dev/null
+++ b/fontconfig/fcprivate.h
@@ -0,0 +1,117 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _FCPRIVATE_H_
+#define _FCPRIVATE_H_
+
+/*
+ * I tried this with functions that took va_list* arguments
+ * but portability concerns made me change these functions
+ * into macros (sigh).
+ */
+
+#define FcPatternVapBuild(result, orig, va)			    \
+{								    \
+    FcPattern	*__p__ = (orig);				    \
+    const char	*__o__;						    \
+    FcValue	__v__;						    \
+								    \
+    if (!__p__)							    \
+    {								    \
+	__p__ = FcPatternCreate ();				    \
+	if (!__p__)		    				    \
+	    goto _FcPatternVapBuild_bail0;			    \
+    }				    				    \
+    for (;;)			    				    \
+    {				    				    \
+	__o__ = va_arg (va, const char *);			    \
+	if (!__o__)		    				    \
+	    break;		    				    \
+	__v__.type = va_arg (va, FcType);			    \
+	switch (__v__.type) {	    				    \
+	case FcTypeVoid:					    \
+	    goto _FcPatternVapBuild_bail1;       		    \
+	case FcTypeInteger:	    				    \
+	    __v__.u.i = va_arg (va, int);			    \
+	    break;						    \
+	case FcTypeDouble:					    \
+	    __v__.u.d = va_arg (va, double);			    \
+	    break;						    \
+	case FcTypeString:					    \
+	    __v__.u.s = va_arg (va, char *);			    \
+	    break;						    \
+	case FcTypeBool:					    \
+	    __v__.u.b = va_arg (va, FcBool);			    \
+	    break;						    \
+	case FcTypeMatrix:					    \
+	    __v__.u.m = va_arg (va, FcMatrix *);		    \
+	    break;						    \
+	case FcTypeCharSet:					    \
+	    __v__.u.c = va_arg (va, FcCharSet *);		    \
+	    break;						    \
+	}							    \
+	if (!FcPatternAdd (__p__, __o__, __v__, FcTrue))	    \
+	    goto _FcPatternVapBuild_bail1;			    \
+    }								    \
+    result = __p__;						    \
+    goto _FcPatternVapBuild_return;				    \
+								    \
+_FcPatternVapBuild_bail1:					    \
+    if (!orig)							    \
+	FcPatternDestroy (__p__);				    \
+_FcPatternVapBuild_bail0:					    \
+    result = 0;							    \
+								    \
+_FcPatternVapBuild_return:					    \
+    ;								    \
+}
+
+
+#define FcObjectSetVapBuild(__ret__, __first__, __va__) 		\
+{									\
+    FcObjectSet    *__os__;						\
+    const char	    *__ob__;						\
+									\
+    __ret__ = 0;						    	\
+    __os__ = FcObjectSetCreate ();					\
+    if (!__os__)							\
+	goto _FcObjectSetVapBuild_bail0;				\
+    __ob__ = __first__;							\
+    while (__ob__)							\
+    {									\
+	if (!FcObjectSetAdd (__os__, __ob__))				\
+	    goto _FcObjectSetVapBuild_bail1;				\
+	__ob__ = va_arg (__va__, const char *);				\
+    }									\
+    __ret__ = __os__;							\
+									\
+_FcObjectSetVapBuild_bail1:						\
+    if (!__ret__ && __os__)					    	\
+	FcObjectSetDestroy (__os__);					\
+_FcObjectSetVapBuild_bail0:						\
+    ;									\
+}
+
+#endif /* _FCPRIVATE_H_ */
+
diff --git a/fontconfig/fcxml.h b/fontconfig/fcxml.h
new file mode 100644
index 0000000..b5d1b7d
--- /dev/null
+++ b/fontconfig/fcxml.h
@@ -0,0 +1,37 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _FCXML_H_
+#define _FCXML_H_
+
+#include <libxml/parser.h>
+
+xmlDocPtr
+FcConfigLoad (const char *file);
+
+FcBool
+FcConfigParse (FcConfig	    *config,
+	       xmlDocPtr    doc);
+
+#endif /* _FCXML_H_ */
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
new file mode 100644
index 0000000..c7105e0
--- /dev/null
+++ b/fontconfig/fontconfig.h
@@ -0,0 +1,551 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _FONTCONFIG_H_
+#define _FONTCONFIG_H_
+
+#include <stdarg.h>
+
+typedef unsigned char	FcChar8;
+typedef unsigned short	FcChar16;
+typedef unsigned int	FcChar32;
+typedef int		FcBool;
+
+/*
+ * Current Fontconfig version number
+ */
+#define FC_MAJOR	1
+#define FC_MINOR	0
+#define FC_REVISION	0
+
+#define FC_VERSION	((FC_MAJOR * 10000) + (FC_MINOR * 100) + (FC_REVISION))
+
+#define FcTrue		1
+#define FcFalse		0
+
+#define FC_FAMILY	    "family"		/* String */
+#define FC_STYLE	    "style"		/* String */
+#define FC_SLANT	    "slant"		/* Int */
+#define FC_WEIGHT	    "weight"		/* Int */
+#define FC_SIZE		    "size"		/* Double */
+#define FC_PIXEL_SIZE	    "pixelsize"		/* Double */
+#define FC_SPACING	    "spacing"		/* Int */
+#define FC_FOUNDRY	    "foundry"		/* String */
+#define FC_ANTIALIAS	    "antialias"		/* Bool (depends) */
+#define FC_HINTING	    "hinting"		/* Bool (true) */
+#define FC_VERTICAL_LAYOUT  "verticallayout"	/* Bool (false) */
+#define FC_AUTOHINT	    "autohint"		/* Bool (false) */
+#define FC_GLOBAL_ADVANCE   "globaladvance"	/* Bool (true) */
+#define FC_FILE		    "file"		/* String */
+#define FC_INDEX	    "index"		/* Int */
+#define FC_RASTERIZER	    "rasterizer"	/* String */
+#define FC_OUTLINE	    "outline"		/* Bool */
+#define FC_SCALABLE	    "scalable"		/* Bool */
+#define FC_SCALE	    "scale"		/* double */
+#define FC_DPI		    "dpi"		/* double */
+#define FC_RGBA		    "rgba"		/* Int */
+#define FC_MINSPACE	    "minspace"		/* Bool use minimum line spacing */
+#define FC_SOURCE	    "source"		/* String (X11, freetype) */
+#define FC_CHARSET	    "charset"		/* CharSet */
+#define FC_LANG		    "lang"		/* String OS/2 CodePageRange */
+
+#define FC_DIR_CACHE_FILE	    "fonts.cache"
+#define FC_USER_CACHE_FILE	    ".fonts.cache"
+
+/* Adjust outline rasterizer */
+#define FC_CHAR_WIDTH	    "charwidth"	/* Int */
+#define FC_CHAR_HEIGHT	    "charheight"/* Int */
+#define FC_MATRIX	    "matrix"    /* FcMatrix */
+
+#define FC_WEIGHT_LIGHT	    0
+#define FC_WEIGHT_MEDIUM    100
+#define FC_WEIGHT_DEMIBOLD  180
+#define FC_WEIGHT_BOLD	    200
+#define FC_WEIGHT_BLACK	    210
+
+#define FC_SLANT_ROMAN	    0
+#define FC_SLANT_ITALIC	    100
+#define FC_SLANT_OBLIQUE    110
+
+#define FC_PROPORTIONAL	    0
+#define FC_MONO		    100
+#define FC_CHARCELL	    110
+
+/* sub-pixel order */
+#define FC_RGBA_NONE	    0
+#define FC_RGBA_RGB	    1
+#define FC_RGBA_BGR	    2
+#define FC_RGBA_VRGB	    3
+#define FC_RGBA_VBGR	    4
+
+/* language groups from the OS/2 CodePageRange bits */
+#define FC_LANG_LATIN_1			"latin1"		/* 0 */
+#define FC_LANG_LATIN_2_EASTERN_EUROPE	"latin2easterneurope"	/* 1 */
+#define FC_LANG_CYRILLIC		"cyrillic"		/* 2 */
+#define FC_LANG_GREEK			"greek"			/* 3 */
+#define FC_LANG_TURKISH			"turkish"		/* 4 */
+#define FC_LANG_HEBREW			"hebrew"		/* 5 */
+#define FC_LANG_ARABIC			"arabic"		/* 6 */
+#define FC_LANG_WINDOWS_BALTIC		"windowsbaltic"		/* 7 */
+#define FC_LANG_VIETNAMESE		"vietnamese"		/* 8 */
+/* 9-15 reserved for Alternate ANSI */
+#define FC_LANG_THAI			"thai"			/* 16 */
+#define FC_LANG_JAPANESE		"japanese"		/* 17 */
+#define FC_LANG_SIMPLIFIED_CHINESE	"simplifiedchinese"	/* 18 */
+#define FC_LANG_KOREAN_WANSUNG		"koreanwansung"		/* 19 */
+#define FC_LANG_TRADITIONAL_CHINESE	"traditionalchinese"	/* 20 */
+#define FC_LANG_KOREAN_JOHAB		"koreanjohab"		/* 21 */
+/* 22-28 reserved for Alternate ANSI & OEM */
+#define FC_LANG_MACINTOSH		"macintosh"		/* 29 */
+#define FC_LANG_OEM			"oem"			/* 30 */
+#define FC_LANG_SYMBOL			"symbol"		/* 31 */
+/* 32-47 reserved for OEM */
+#define FC_LANG_IBM_GREEK		"ibmgreek"		/* 48 */
+#define FC_LANG_MSDOS_RUSSIAN		"msdosrussian"		/* 49 */
+#define FC_LANG_MSDOS_NORDIC		"msdosnordic"		/* 50 */
+#define FC_LANG_ARABIC_864    		"arabic864"		/* 51 */
+#define FC_LANG_MSDOS_CANADIAN_FRENCH	"msdoscanadianfrench"	/* 52 */
+#define FC_LANG_HEBREW_862		"hebrew862"		/* 53 */
+#define FC_LANG_MSDOS_ICELANDIC		"msdosicelandic"	/* 54 */
+#define FC_LANG_MSDOS_PORTUGUESE	"msdosportuguese"	/* 55 */
+#define FC_LANG_IBM_TURKISH		"ibmturkish"		/* 56 */
+#define FC_LANG_IBM_CYRILLIC		"ibmcyrillic"		/* 57 */
+#define FC_LANG_LATIN_2			"latin2"		/* 58 */
+#define FC_LANG_MSDOS_BALTIC		"msdosbaltic"		/* 59 */
+#define FC_LANG_GREEK_437_G		"greek437g"		/* 60 */
+#define FC_LANG_ARABIC_ASMO_708		"arabicasmo708"		/* 61 */
+#define FC_LANG_WE_LATIN_1		"welatin1"		/* 62 */
+#define FC_LANG_US			"us"			/* 63 */
+
+typedef enum _FcType {
+    FcTypeVoid, 
+    FcTypeInteger, 
+    FcTypeDouble, 
+    FcTypeString, 
+    FcTypeBool,
+    FcTypeMatrix,
+    FcTypeCharSet
+} FcType;
+
+typedef struct _FcMatrix {
+    double xx, xy, yx, yy;
+} FcMatrix;
+
+#define FcMatrixInit(m)	((m)->xx = (m)->yy = 1, \
+			 (m)->xy = (m)->yx = 0)
+
+/*
+ * A data structure to represent the available glyphs in a font.
+ * This is represented as a sparse boolean btree.
+ */
+
+typedef struct _FcCharSet FcCharSet;
+
+typedef struct _FcObjectType {
+    const char	*object;
+    FcType	type;
+} FcObjectType;
+
+typedef struct _FcConstant {
+    const char  *name;
+    const char	*object;
+    int		value;
+} FcConstant;
+
+typedef enum _FcResult {
+    FcResultMatch, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId
+} FcResult;
+
+typedef struct _FcValue {
+    FcType	type;
+    union {
+	const FcChar8	*s;
+	int		i;
+	FcBool		b;
+	double		d;
+	const FcMatrix	*m;
+	const FcCharSet	*c;
+    } u;
+} FcValue;
+
+typedef struct _FcPattern   FcPattern;
+
+typedef struct _FcFontSet {
+    int		nfont;
+    int		sfont;
+    FcPattern	**fonts;
+} FcFontSet;
+
+typedef struct _FcObjectSet {
+    int		nobject;
+    int		sobject;
+    const char	**objects;
+} FcObjectSet;
+    
+typedef enum _FcMatchKind {
+    FcMatchPattern, FcMatchFont 
+} FcMatchKind;
+
+typedef enum _FcSetName {
+    FcSetSystem = 0,
+    FcSetApplication = 1
+} FcSetName;
+
+#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */
+#define _FCFUNCPROTOBEGIN extern "C" {	/* do not leave open across includes */
+#define _FCFUNCPROTOEND }
+#else
+#define _FCFUNCPROTOBEGIN
+#define _FCFUNCPROTOEND
+#endif
+
+typedef struct _FcConfig    FcConfig;
+
+typedef struct _FcFileCache FcFileCache;
+
+typedef struct _FcBlanks    FcBlanks;
+
+_FCFUNCPROTOBEGIN
+
+/* fcblanks.c */
+FcBlanks *
+FcBlanksCreate (void);
+
+void
+FcBlanksDestroy (FcBlanks *b);
+
+FcBool
+FcBlanksAdd (FcBlanks *b, FcChar32 ucs4);
+
+FcBool
+FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4);
+
+/* fccfg.c */
+char *
+FcConfigFilename (const char *url);
+    
+FcConfig *
+FcConfigCreate (void);
+
+void
+FcConfigDestroy (FcConfig *config);
+
+FcBool
+FcConfigSetCurrent (FcConfig *config);
+
+FcConfig *
+FcConfigGetCurrent (void);
+
+FcBool
+FcConfigBuildFonts (FcConfig *config);
+
+char **
+FcConfigGetDirs (FcConfig   *config);
+
+char **
+FcConfigGetConfigFiles (FcConfig    *config);
+
+char *
+FcConfigGetCache (FcConfig  *config);
+
+FcBlanks *
+FcConfigGetBlanks (FcConfig *config);
+
+FcFontSet *
+FcConfigGetFonts (FcConfig	*config,
+		  FcSetName	set);
+
+FcBool
+FcConfigAppFontAddFile (FcConfig    *config,
+			const char  *file);
+
+FcBool
+FcConfigAppFontAddDir (FcConfig	    *config,
+		       const char   *dir);
+
+void
+FcConfigAppFontClear (FcConfig	    *config);
+
+FcBool
+FcConfigSubstitute (FcConfig	*config,
+		    FcPattern	*p,
+		    FcMatchKind	kind);
+
+/* fccharset.c */
+FcCharSet *
+FcCharSetCreate (void);
+
+void
+FcCharSetDestroy (FcCharSet *fcs);
+
+FcBool
+FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4);
+
+FcCharSet *
+FcCharSetCopy (FcCharSet *src);
+
+FcBool
+FcCharSetEqual (const FcCharSet *a, const FcCharSet *b);
+
+FcCharSet *
+FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b);
+
+FcCharSet *
+FcCharSetUnion (const FcCharSet *a, const FcCharSet *b);
+
+FcCharSet *
+FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b);
+
+FcBool
+FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4);
+
+FcChar32
+FcCharSetCount (const FcCharSet *a);
+
+FcChar32
+FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b);
+
+FcChar32
+FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b);
+
+#ifndef FONTCONFIG_NO_FREETYPE
+#include <freetype/freetype.h>
+FT_UInt
+FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4);
+#endif
+
+/* fcdbg.c */
+void
+FcPatternPrint (FcPattern *p);
+
+/* fcdefault.c */
+void
+FcDefaultSubstitute (FcPattern *pattern);
+
+/* fcdir.c */
+FcBool
+FcDirScan (FcFontSet	*set,
+	   FcFileCache	*cache,
+	   FcBlanks	*blanks,
+	   const char	*dir,
+	   FcBool	force);
+
+FcBool
+FcDirSave (FcFontSet *set, const char *dir);
+
+/* fcfreetype.c */
+FcPattern *
+FcFreeTypeQuery (const char *file, int id, FcBlanks *blanks, int *count);
+
+/* fcfs.c */
+
+FcFontSet *
+FcFontSetCreate (void);
+
+void
+FcFontSetDestroy (FcFontSet *s);
+
+FcBool
+FcFontSetAdd (FcFontSet *s, FcPattern *font);
+
+/* fcinit.c */
+FcBool
+FcInitFonts (void);
+
+FcBool
+FcInitConfig (void);
+
+FcBool
+FcInit (void);
+
+/* fclist.c */
+FcObjectSet *
+FcObjectSetCreate (void);
+
+FcBool
+FcObjectSetAdd (FcObjectSet *os, const char *object);
+
+void
+FcObjectSetDestroy (FcObjectSet *os);
+
+FcObjectSet *
+FcObjectSetVaBuild (const char *first, va_list va);
+
+FcObjectSet *
+FcObjectSetBuild (const char *first, ...);
+
+FcFontSet *
+FcFontList (FcConfig	*config,
+	    FcPattern	*p,
+	    FcObjectSet *os);
+
+/* fcmatch.c */
+FcPattern *
+FcFontMatch (FcConfig	*config,
+	     FcPattern	*p, 
+	     FcResult	*result);
+
+/* fcmatrix.c */
+FcMatrix *
+FcMatrixCopy (const FcMatrix *mat);
+
+FcBool
+FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2);
+
+void
+FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b);
+
+void
+FcMatrixRotate (FcMatrix *m, double c, double s);
+
+void
+FcMatrixScale (FcMatrix *m, double sx, double sy);
+
+void
+FcMatrixShear (FcMatrix *m, double sh, double sv);
+
+/* fcname.c */
+
+FcBool
+FcNameRegisterObjectTypes (const FcObjectType *types, int ntype);
+
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntype);
+    
+const FcObjectType *
+FcNameGetObjectType (const char *object);
+
+FcBool
+FcNameRegisterConstants (const FcConstant *consts, int nconsts);
+
+FcBool
+FcNameUnregisterConstants (const FcConstant *consts, int nconsts);
+    
+const FcConstant *
+FcNameGetConstant (char *string);
+
+FcBool
+FcNameConstant (char *string, int *result);
+
+FcPattern *
+FcNameParse (const char *name);
+
+FcChar8 *
+FcNameUnparse (FcPattern *pat);
+
+/* fcpat.c */
+FcPattern *
+FcPatternCreate (void);
+
+FcPattern *
+FcPatternDuplicate (FcPattern *p);
+
+void
+FcValueDestroy (FcValue v);
+
+FcValue
+FcValueSave (FcValue v);
+
+void
+FcPatternDestroy (FcPattern *p);
+
+FcBool
+FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append);
+    
+FcResult
+FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v);
+    
+FcBool
+FcPatternDel (FcPattern *p, const char *object);
+
+FcBool
+FcPatternAddInteger (FcPattern *p, const char *object, int i);
+
+FcBool
+FcPatternAddDouble (FcPattern *p, const char *object, double d);
+
+FcBool
+FcPatternAddString (FcPattern *p, const char *object, const char *s);
+
+FcBool
+FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s);
+
+FcBool
+FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c);
+
+FcBool
+FcPatternAddBool (FcPattern *p, const char *object, FcBool b);
+
+FcResult
+FcPatternGetInteger (FcPattern *p, const char *object, int n, int *i);
+
+FcResult
+FcPatternGetDouble (FcPattern *p, const char *object, int n, double *d);
+
+FcResult
+FcPatternGetString (FcPattern *p, const char *object, int n, char **const s);
+
+FcResult
+FcPatternGetMatrix (FcPattern *p, const char *object, int n, FcMatrix **s);
+
+FcResult
+FcPatternGetCharSet (FcPattern *p, const char *object, int n, FcCharSet **c);
+
+FcResult
+FcPatternGetBool (FcPattern *p, const char *object, int n, FcBool *b);
+
+FcPattern *
+FcPatternVaBuild (FcPattern *orig, va_list va);
+    
+FcPattern *
+FcPatternBuild (FcPattern *orig, ...);
+
+/* fcstr.c */
+
+char *
+FcStrCopy (const char *s);
+
+#define FcToLower(c)	(('A' <= (c) && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+int
+FcStrCmpIgnoreCase (const char *s1, const char *s2);
+
+int
+FcUtf8ToUcs4 (FcChar8   *src_orig,
+	      FcChar32  *dst,
+	      int	len);
+
+FcBool
+FcUtf8Len (FcChar8	*string,
+	   int		len,
+	   int		*nchar,
+	   int		*wchar);
+
+/* fcxml.c */
+FcBool
+FcConfigParseAndLoad (FcConfig *config, const char *file, FcBool complain);
+
+_FCFUNCPROTOEND
+
+#endif /* _FONTCONFIG_H_ */
diff --git a/fonts.conf.in b/fonts.conf.in
new file mode 100644
index 0000000..e85c0c4
--- /dev/null
+++ b/fonts.conf.in
@@ -0,0 +1,191 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<!-- /etc/fonts.conf file to configure system font access -->
+<fontconfig>
+
+<!-- FONTPATH_START -->
+
+<!-- 
+  Common X11R6 font directories
+-->
+
+	<dir>/usr/X11R6/lib/X11/fonts/truetype</dir>
+ 	<dir>/usr/X11R6/lib/X11/fonts/Type1</dir>
+  	<dir>/usr/X11R6/lib/X11/fonts/TrueType</dir>
+
+<!-- FONTPATH_END -->
+
+<!--
+  Accept deprecated 'mono' alias, replacing it with 'monospace'
+-->
+	<match target="pattern">
+		<test qual="any" name="family">
+			<string>mono</string>
+		</test>
+		<edit name="family" mode="assign">
+			<string>monospace</string>
+		</edit>
+	</match>
+
+<!--
+  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
+-->
+	<match target="pattern">
+		<test qual="any" name="family">
+			<string>sans</string>
+		</test>
+		<edit name="family" mode="assign">
+			<string>sans-serif</string>
+		</edit>
+	</match>
+
+<!--
+  Mark common families with their generics so we'll get
+  something reasonable
+-->
+
+<!--
+  Serif faces
+ -->
+	<alias>
+		<family>Times</family>
+		<default><family>serif</family></default>
+	</alias>
+	<alias>
+		<family>Times New Roman</family>
+		<default><family>serif</family></default>
+	</alias>
+<!--
+  Sans-serif faces
+ -->
+	<alias>
+		<family>Helvetica</family>
+		<default><family>sans-serif</family></default>
+	</alias>
+	<alias>
+		<family>Arial</family>
+		<default><family>sans-serif</family></default>
+	</alias>
+	<alias>
+		<family>Verdana</family>
+		<default><family>sans-serif</family></default>
+	</alias>
+<!--
+  Monospace faces
+ -->
+ 	<alias>
+		<family>Courier</family>
+		<default><family>monospace</family></default>
+	</alias>
+	<alias>
+		<family>Courier New</family>
+		<default><family>monospace</family></default>
+	</alias>
+	<alias>
+		<family>Andale Mono</family>
+		<default><family>monospace</family></default>
+	</alias>
+<!--
+  If the font still has no generic name, add sans-serif
+ -->
+	<match target="pattern">
+		<test qual="all" name="family" compare="not_eq">
+			<string>sans-serif</string>
+		</test>
+		<test qual="all" name="family" compare="not_eq">
+			<string>serif</string>
+		</test>
+		<test qual="all" name="family" compare="not_eq">
+			<string>monospace</string>
+		</test>
+		<edit name="family" mode="append_last">
+			<string>sans-serif</string>
+		</edit>
+	</match>
+	
+<!--
+  Load per-user customization file
+-->
+	<include ignore_missing="yes">~/.fonts.conf</include>
+
+<!--
+  Alias well known font names to available TrueType fonts
+-->
+	<alias>
+		<family>Times</family>
+		<prefer><family>Times New Roman</family></prefer>
+		<default><family>serif</family></default>
+	</alias>
+	<alias>
+		<family>Helvetica</family>
+		<prefer><family>Verdana</family></prefer>
+		<default><family>sans-serif</family></default>
+	</alias>
+	<alias>
+		<family>Arial</family>
+		<prefer><family>Verdana</family></prefer>
+		<default><family>sans-serif</family></default>
+	</alias>
+	<alias>
+		<family>Courier</family>
+		<prefer><family>Courier New</family></prefer>
+		<default><family>monospace</family></default>
+	</alias>
+
+<!--
+  Provide required aliases for standard names
+-->
+	<alias>
+		<family>serif</family>
+		<prefer>
+			<family>Times New Roman</family>
+			<family>Nimbus Roman No9 L</family>
+			<family>Luxi Serif</family>
+			<family>Times</family>
+		</prefer>
+	</alias>
+	<alias>
+		<family>sans-serif</family>
+		<prefer>
+			<family>Verdana</family>
+			<family>Nimbus Sans L</family>
+			<family>Luxi Sans</family>
+			<family>Arial</family>
+			<family>Helvetica</family>
+		</prefer>
+	</alias>
+	<alias>
+		<family>monospace</family>
+		<prefer>
+			<family>Andale Mono</family>
+			<family>Courier New</family>
+			<family>Nimbus Mono L</family>
+			<family>Luxi Mono</family>
+		</prefer>
+	</alias>
+
+<!--
+  These are the default Unicode chars that are expected to be blank
+  in fonts.  All other blank chars are assumed to be broken and
+  won't appear in the resulting charsets
+ -->
+	<config><blank>
+		<int>0x20</int>		<!-- space -->
+		<int>0xa0</int>		<!-- nsbp  -->
+		<int>0x2000</int>	<!-- general punctuation spaces -->
+		<int>0x2001</int>
+		<int>0x2002</int>
+		<int>0x2003</int>
+		<int>0x2004</int>
+		<int>0x2005</int>
+		<int>0x2005</int>
+		<int>0x2006</int>
+		<int>0x2007</int>
+		<int>0x2008</int>
+		<int>0x2009</int>
+		<int>0x200a</int>
+		<int>0x200b</int>
+		<int>0x3000</int>	<!-- CJK space -->
+	</blank></config>
+
+</fontconfig>
diff --git a/fonts.dtd b/fonts.dtd
new file mode 100644
index 0000000..a3c987b
--- /dev/null
+++ b/fonts.dtd
@@ -0,0 +1,165 @@
+<!-- This is the Document Type Definition for font configuration files -->
+<!ELEMENT fontconfig (dir | 
+		      cache | 
+		      include | 
+		      config |
+		      match | 
+		      alias)* >
+
+<!-- 
+    Add a directory that provides fonts
+-->
+<!ELEMENT dir (#PCDATA)>
+<!ATTLIST dir xml:space (default|preserve) 'preserve'>
+
+<!--
+    Define the per-user file that holds cache font information.
+
+    If the filename begins with '~', it is replaced with the users
+    home directory path.
+-->
+<!ELEMENT cache (#PCDATA)>
+<!ATTLIST cache xml:space (default|preserve) 'preserve'>
+
+<!--
+    Reference another configuration file; note that this
+    is another complete font configuration file and not
+    just a file included by the XML parser.
+
+    Set 'ignore_missing' to 'yes' if errors are to be ignored.
+
+    If the filename begins with '~', it is replaced with the users
+    home directory path.
+-->
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+	  ignore_missing    (no|yes)		"no"
+	  xml:space	    (default|preserve)	"preserve">
+
+<!--
+    Global library configuration data
+ -->
+<!ELEMENT config (blanks)*>
+
+<!--
+    Specify the set of Unicode encoding values which
+    represent glyphs that are allowed to contain no
+    data.  With this list, fontconfig can examine
+    fonts for broken glyphs and eliminate them from
+    the set of valid Unicode chars.  This idea
+    was borrowed from Mozilla
+ -->
+<!ELEMENT blanks (int)*>
+
+<!--
+    Aliases are just a special case for multiple match elements
+
+    They are syntactically equivalent to:
+
+    <match>
+	<test name="family">
+	    <string value=[family]/>
+	</test>
+	<edit name="family" mode="prepend">
+	    <string value=[prefer]/>
+	    ...
+	</edit>
+	<edit name="family" mode="append">
+	    <string value=[accept]/>
+	    ...
+	</edit>
+	<edit name="family" mode="append_last">
+	    <string value=[default]/>
+	    ...
+	</edit>
+    </match>
+-->
+<!ELEMENT alias (family, prefer?, accept?, default?)>
+<!ELEMENT prefer (family)*>
+<!ELEMENT accept (family)*>
+<!ELEMENT default (family)*>
+<!ELEMENT family (#PCDATA)>
+<!ATTLIST family xml:space (default|preserve) 'preserve'>
+
+<!ENTITY % expr 'int|double|string|matrix|bool|charset
+		|name|const
+		|or|and|eq|not_eq|less|less_eq|more|more_eq
+		|plus|minus|times|divide|not|if'>
+
+<!--
+    Match and edit patterns.
+
+    If 'target' is 'pattern', execute the match before selecting a font.
+    if 'target' is 'font', execute the match on the result of a font
+    selection.
+-->
+<!ELEMENT match (test*, edit*)>
+<!ATTLIST match
+	  target (pattern|font)	"pattern">
+
+<!--
+    Match a field in a pattern
+
+    if 'qual' is 'any', then the match succeeds if any value in the field matches.
+    if 'qual' is 'all', then the match succeeds only if all values match.
+-->
+<!ELEMENT test (%expr;)>
+<!ATTLIST test 
+	  qual (any|all)    "any"
+	  name CDATA	    #REQUIRED
+	  compare (eq|not_eq|less|less_eq|more|more_eq)	"eq">
+
+<!--
+    Edit a field in a pattern
+
+    The enclosed values are used together to edit the list of values
+    associated with 'name'.
+
+    If 'name' matches one of those used in a test element for this match element:
+	if 'mode' is 'assign', replace the matched value.
+	if 'mode' is 'assign_replace', replace all of the values
+	if 'mode' is 'prepend', insert before the matched value
+	if 'mode' is 'append', insert after the matched value
+	if 'mode' is 'prepend_first', insert before all of the values
+	if 'mode' is 'append_last', insert after all of the values
+    If 'name' doesn't match any of those used in a test element:
+	if 'mode' is 'assign' or 'assign_replace, replace all of the values
+	if 'mode' is 'prepend' or 'prepend_first', insert before all of the values
+	if 'mode' is 'append' or 'append_last', insert after all of the values
+-->
+<!ELEMENT edit (%expr;)*>
+<!ATTLIST edit
+	  name CDATA	    #REQUIRED
+	  mode (assign|assign_replace|prepend|append|prepend_first|append_last) "assign">
+
+<!--
+    Elements of expressions follow
+-->
+<!ELEMENT int (#PCDATA)>
+<!ATTLIST int xml:space (default|preserve) 'preserve'>
+<!ELEMENT double (#PCDATA)>
+<!ATTLIST double xml:space (default|preserve) 'preserve'>
+<!ELEMENT string (#PCDATA)>
+<!ATTLIST string xml:space (default|preserve) 'preserve'>
+<!ELEMENT matrix (double,double,double,double)>
+<!ELEMENT bool (true|false)>
+<!ELEMENT charset (#PCDATA)>
+<!ATTLIST charset xml:space (default|preserve) 'preserve'>
+<!ELEMENT name (#PCDATA)>
+<!ATTLIST name xml:space (default|preserve) 'preserve'>
+<!ELEMENT const (#PCDATA)>
+<!ATTLIST const xml:space (default|preserve) 'preserve'>
+<!ELEMENT or (%expr;)*>
+<!ELEMENT and (%expr;)*>
+<!ELEMENT eq ((%expr;), (%expr;))>
+<!ELEMENT not_eq ((%expr;), (%expr;))>
+<!ELEMENT less ((%expr;), (%expr;))>
+<!ELEMENT less_eq ((%expr;), (%expr;))>
+<!ELEMENT more ((%expr;), (%expr;))>
+<!ELEMENT more_eq ((%expr;), (%expr;))>
+<!ELEMENT plus (%expr;)*>
+<!ELEMENT minus (%expr;)*>
+<!ELEMENT times (%expr;)*>
+<!ELEMENT divide (%expr;)*>
+<!ELEMENT not (%expr;)>
+<!ELEMENT if ((%expr;), (%expr;), (%expr;))>
diff --git a/setfontdirs b/setfontdirs
new file mode 100755
index 0000000..7bed787
--- /dev/null
+++ b/setfontdirs
@@ -0,0 +1,19 @@
+#!/bin/sh
+FONTDIRS=fontdirs$$
+trap "rm $FONTDIRS" 0
+sh ./findfonts > $FONTDIRS
+cp fonts.conf.in fonts.conf
+chmod +w fonts.conf
+ed fonts.conf << EOF
+/FONTPATH_END/a
+<!-- Font directories found on `date` -->
+.
++r $FONTDIRS
+a
+
+.
+/FONTPATH_START/,/FONTPATH_END/d
+w
+q
+EOF
+
diff --git a/src/Imakefile b/src/Imakefile
new file mode 100644
index 0000000..1ba4cb5
--- /dev/null
+++ b/src/Imakefile
@@ -0,0 +1,90 @@
+#include "../../libxml2/config.h"
+#if HAVE_ZLIB_H
+ZLIB=-lz
+#endif
+
+#if 0
+#define SharedLibFontconfig YES
+#endif
+
+#ifndef SharedLibFontconfig
+#define SharedLibFontconfig NO
+#endif
+
+#ifndef NormalLibFontconfig
+#define NormalLibFontconfig (!SharedLibFontConfig | ForceNormalLib)
+#endif
+
+#ifndef DebugLibFontconfig
+#define DebugLibFontconfig		NO
+#endif
+
+#ifndef ProfileLibFontconfig
+#define ProfileLibFontconfig		NO
+#endif
+
+#define LibHeaders NO
+
+FONTCONFIGSRC=.
+
+FALLBACK_FONTS=$(FONTDIR)/Type1
+
+#if SharedLibFontconfig
+#ifndef SharedFontconfigRev
+#define SharedFontconfigRev 1.0
+#endif
+SharedLibReferences(FONTCONFIG,Fontconfig,$(FONTCONFIGSRC),SOXLIBREV,SharedFontconfigRev)
+#else
+ProjectUnsharedLibReferences(FONTCONFIG,Fontconfig,$(FONTCONFIGSRC),BuildLibDir)
+#endif
+
+#define DoNormalLib NormalLibFontconfig
+#define DoSharedLib SharedLibFontconfig
+#define DoExtraLib SharedLibFontconfig
+#define DoDebugLib DebugLibFontconfig
+#define DoProfileLib ProfileLibFontconfig
+#define HasSharedData YES
+#define LibName fontconfig
+SOFONTCONFIGREV=1.0
+#define SoRev SOFONTCONFIGREV
+
+#include <Threads.tmpl>
+
+#if SharedLibFontconfig
+INCLUDES=-I/usr/local/include/freetype2 -I/usr/include/libxml2 -I..
+FREETYPE2REQLIB = -L/usr/local/lib -lfreetype
+XML2REQLIB=-lxml2
+#else
+INCLUDES=-I../../freetype2 -I../../libxml2/include -I..
+FREETYPE2REQLIB = ../../freetype2/libfreetype.a
+XML2REQLIB=../../libxml2/.libs/libxml2.a $(ZLIB) -lm
+#endif
+DEFINES=-DFC_FALLBACK_FONTS='"$(FALLBACK_FONTS)"'
+
+REQUIREDLIBS=$(LDPRELIBS) $(FREETYPE2REQLIB) $(XML2REQLIB)
+
+SRCS=fcblanks.c fccache.c fccfg.c fccharset.c fcdbg.c fcdefault.c fcdir.c \
+     fcfreetype.c fcfs.c fcinit.c fclist.c fcmatch.c fcmatrix.c fcname.c \
+     fcpat.c fcstr.c fcxml.c
+
+OBJS=fcblanks.o fccache.o fccfg.o fccharset.o fcdbg.o fcdefault.o fcdir.o \
+     fcfreetype.o fcfs.o fcinit.o fclist.o fcmatch.o fcmatrix.o fcname.o \
+     fcpat.o fcstr.o fcxml.o
+
+#define LibInstallBuild YES
+#undef LinkBuildLibrary
+#define LinkBuildLibrary(lib) MakeDir($(BUILDLIBDIR))			@@\
+	RemoveFile($(BUILDLIBDIR)/lib)					@@\
+	cd $(BUILDLIBDIR) && $(LN) $(BUILDLIBTOP)/$(CURRENT_DIR)/lib .
+
+
+#include <Library.tmpl>
+
+#if DoSharedLib && SharedDataSeparation
+SpecialCObjectRule(sharedlib,NullParameter,$(SHLIBDEF))
+#endif
+
+MANSUFFIX = $(LIBMANSUFFIX)
+InstallManPage(fontconfig,$(LIBMANDIR))
+DependTarget()
+
diff --git a/src/fcblanks.c b/src/fcblanks.c
new file mode 100644
index 0000000..8b3a9a9
--- /dev/null
+++ b/src/fcblanks.c
@@ -0,0 +1,84 @@
+/*
+ * $XFree86$
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 "fcint.h"
+
+FcBlanks *
+FcBlanksCreate (void)
+{
+    FcBlanks	*b;
+
+    b = malloc (sizeof (FcBlanks));
+    if (!b)
+	return 0;
+    b->nblank = 0;
+    b->sblank = 0;
+    b->blanks = 0;
+    return b;
+}
+
+void
+FcBlanksDestroy (FcBlanks *b)
+{
+    if (b->blanks)
+	free (b->blanks);
+    free (b);
+}
+
+FcBool
+FcBlanksAdd (FcBlanks *b, FcChar32 ucs4)
+{
+    FcChar32	*c;
+    int		sblank;
+
+    for (sblank = 0; sblank < b->nblank; sblank++)
+	if (b->blanks[sblank] == ucs4)
+	    return FcTrue;
+
+    if (b->nblank == b->sblank)
+    {
+	sblank = b->sblank + 32;
+	if (b->blanks)
+	    c = (FcChar32 *) realloc (b->blanks, sblank * sizeof (FcChar32));
+	else
+	    c = (FcChar32 *) malloc (sblank * sizeof (FcChar32));
+	if (!c)
+	    return FcFalse;
+	b->sblank = sblank;
+	b->blanks = c;
+    }
+    b->blanks[b->nblank++] = ucs4;
+    return FcTrue;
+}
+
+FcBool
+FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4)
+{
+    int	i;
+
+    for (i = 0; i < b->nblank; i++)
+	if (b->blanks[i] == ucs4)
+	    return FcTrue;
+    return FcFalse;
+}
diff --git a/src/fccache.c b/src/fccache.c
new file mode 100644
index 0000000..2251286
--- /dev/null
+++ b/src/fccache.c
@@ -0,0 +1,592 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 "fcint.h"
+
+static unsigned int
+FcFileCacheHash (const char *string)
+{
+    unsigned int    h = 0;
+    char	    c;
+
+    while ((c = *string++))
+	h = (h << 1) ^ c;
+    return h;
+}
+
+char *
+FcFileCacheFind (FcFileCache	*cache,
+		 const char	*file,
+		 int		id,
+		 int		*count)
+{
+    unsigned int    hash;
+    const char	    *match;
+    FcFileCacheEnt *c, *name;
+    int		    maxid;
+    struct stat	    statb;
+    
+    match = file;
+    
+    hash = FcFileCacheHash (match);
+    name = 0;
+    maxid = -1;
+    for (c = cache->ents[hash % FC_FILE_CACHE_HASH_SIZE]; c; c = c->next)
+    {
+	if (c->hash == hash && !strcmp (match, c->file))
+	{
+	    if (c->id > maxid)
+		maxid = c->id;
+	    if (c->id == id)
+	    {
+		if (stat (file, &statb) < 0)
+		{
+		    if (FcDebug () & FC_DBG_CACHE)
+			printf (" file missing\n");
+		    return 0;
+		}
+		if (statb.st_mtime != c->time)
+		{
+		    if (FcDebug () & FC_DBG_CACHE)
+			printf (" timestamp mismatch (was %d is %d)\n",
+				(int) c->time, (int) statb.st_mtime);
+		    return 0;
+		}
+		if (!c->referenced)
+		{
+		    cache->referenced++;
+		    c->referenced = FcTrue;
+		}
+		name = c;
+	    }
+	}
+    }
+    if (!name)
+	return 0;
+    *count = maxid + 1;
+    return name->name;
+}
+
+/*
+ * Cache file syntax is quite simple:
+ *
+ * "file_name" id time "font_name" \n
+ */
+ 
+static FcBool
+FcFileCacheReadString (FILE *f, char *dest, int len)
+{
+    int	    c;
+    FcBool    escape;
+
+    while ((c = getc (f)) != EOF)
+	if (c == '"')
+	    break;
+    if (c == EOF)
+	return FcFalse;
+    if (len == 0)
+	return FcFalse;
+    
+    escape = FcFalse;
+    while ((c = getc (f)) != EOF)
+    {
+	if (!escape)
+	{
+	    switch (c) {
+	    case '"':
+		*dest++ = '\0';
+		return FcTrue;
+	    case '\\':
+		escape = FcTrue;
+		continue;
+	    }
+	}
+        if (--len <= 1)
+	    return FcFalse;
+	*dest++ = c;
+	escape = FcFalse;
+    }
+    return FcFalse;
+}
+
+static FcBool
+FcFileCacheReadUlong (FILE *f, unsigned long *dest)
+{
+    unsigned long   t;
+    int		    c;
+
+    while ((c = getc (f)) != EOF)
+    {
+	if (!isspace (c))
+	    break;
+    }
+    if (c == EOF)
+	return FcFalse;
+    t = 0;
+    for (;;)
+    {
+	if (c == EOF || isspace (c))
+	    break;
+	if (!isdigit (c))
+	    return FcFalse;
+	t = t * 10 + (c - '0');
+	c = getc (f);
+    }
+    *dest = t;
+    return FcTrue;
+}
+
+static FcBool
+FcFileCacheReadInt (FILE *f, int *dest)
+{
+    unsigned long   t;
+    FcBool	    ret;
+
+    ret = FcFileCacheReadUlong (f, &t);
+    if (ret)
+	*dest = (int) t;
+    return ret;
+}
+
+static FcBool
+FcFileCacheReadTime (FILE *f, time_t *dest)
+{
+    unsigned long   t;
+    FcBool	    ret;
+
+    ret = FcFileCacheReadUlong (f, &t);
+    if (ret)
+	*dest = (time_t) t;
+    return ret;
+}
+
+static FcBool
+FcFileCacheAdd (FcFileCache	*cache,
+		 const char	*file,
+		 int		id,
+		 time_t		time,
+		 const char	*name,
+		 FcBool		replace)
+{
+    FcFileCacheEnt    *c;
+    FcFileCacheEnt    **prev, *old;
+    unsigned int    hash;
+
+    if (FcDebug () & FC_DBG_CACHE)
+    {
+	printf ("%s face %s/%d as %s\n", replace ? "Replace" : "Add",
+		file, id, name);
+    }
+    hash = FcFileCacheHash (file);
+    for (prev = &cache->ents[hash % FC_FILE_CACHE_HASH_SIZE]; 
+	 (old = *prev);
+	 prev = &(*prev)->next)
+    {
+	if (old->hash == hash && old->id == id && !strcmp (old->file, file))
+	    break;
+    }
+    if (*prev)
+    {
+	if (!replace)
+	    return FcFalse;
+
+	old = *prev;
+	if (old->referenced)
+	    cache->referenced--;
+	*prev = old->next;
+	free (old);
+	cache->entries--;
+    }
+	
+    c = malloc (sizeof (FcFileCacheEnt) +
+		strlen (file) + 1 +
+		strlen (name) + 1);
+    if (!c)
+	return FcFalse;
+    c->next = *prev;
+    *prev = c;
+    c->hash = hash;
+    c->file = (char *) (c + 1);
+    c->id = id;
+    c->name = c->file + strlen (file) + 1;
+    strcpy (c->file, file);
+    c->time = time;
+    c->referenced = replace;
+    strcpy (c->name, name);
+    cache->entries++;
+    return FcTrue;
+}
+
+FcFileCache *
+FcFileCacheCreate (void)
+{
+    FcFileCache	*cache;
+    int		h;
+
+    cache = malloc (sizeof (FcFileCache));
+    if (!cache)
+	return 0;
+    for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
+	cache->ents[h] = 0;
+    cache->entries = 0;
+    cache->referenced = 0;
+    cache->updated = FcFalse;
+    return cache;
+}
+
+void
+FcFileCacheDestroy (FcFileCache *cache)
+{
+    FcFileCacheEnt *c, *next;
+    int		    h;
+
+    for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
+    {
+	for (c = cache->ents[h]; c; c = next)
+	{
+	    next = c->next;
+	    free (c);
+	}
+    }
+    free (cache);
+}
+
+void
+FcFileCacheLoad (FcFileCache	*cache,
+		 const char	*cache_file)
+{
+    FILE	    *f;
+    char	    file[8192];
+    int		    id;
+    time_t	    time;
+    char	    name[8192];
+
+    f = fopen (cache_file, "r");
+    if (!f)
+	return;
+
+    cache->updated = FcFalse;
+    while (FcFileCacheReadString (f, file, sizeof (file)) &&
+	   FcFileCacheReadInt (f, &id) &&
+	   FcFileCacheReadTime (f, &time) &&
+	   FcFileCacheReadString (f, name, sizeof (name)))
+    {
+	(void) FcFileCacheAdd (cache, file, id, time, name, FcFalse);
+    }
+    fclose (f);
+}
+
+FcBool
+FcFileCacheUpdate (FcFileCache	*cache,
+		   const char	*file,
+		   int		id,
+		   const char	*name)
+{
+    const char	    *match;
+    struct stat	    statb;
+    FcBool	    ret;
+
+    match = file;
+
+    if (stat (file, &statb) < 0)
+	return FcFalse;
+    ret = FcFileCacheAdd (cache, match, id, 
+			    statb.st_mtime, name, FcTrue);
+    if (ret)
+	cache->updated = FcTrue;
+    return ret;
+}
+
+static FcBool
+FcFileCacheWriteString (FILE *f, char *string)
+{
+    char    c;
+
+    if (putc ('"', f) == EOF)
+	return FcFalse;
+    while ((c = *string++))
+    {
+	switch (c) {
+	case '"':
+	case '\\':
+	    if (putc ('\\', f) == EOF)
+		return FcFalse;
+	    /* fall through */
+	default:
+	    if (putc (c, f) == EOF)
+		return FcFalse;
+	}
+    }
+    if (putc ('"', f) == EOF)
+	return FcFalse;
+    return FcTrue;
+}
+
+static FcBool
+FcFileCacheWriteUlong (FILE *f, unsigned long t)
+{
+    int	    pow;
+    unsigned long   temp, digit;
+
+    temp = t;
+    pow = 1;
+    while (temp >= 10)
+    {
+	temp /= 10;
+	pow *= 10;
+    }
+    temp = t;
+    while (pow)
+    {
+	digit = temp / pow;
+	if (putc ((char) digit + '0', f) == EOF)
+	    return FcFalse;
+	temp = temp - pow * digit;
+	pow = pow / 10;
+    }
+    return FcTrue;
+}
+
+static FcBool
+FcFileCacheWriteInt (FILE *f, int i)
+{
+    return FcFileCacheWriteUlong (f, (unsigned long) i);
+}
+
+static FcBool
+FcFileCacheWriteTime (FILE *f, time_t t)
+{
+    return FcFileCacheWriteUlong (f, (unsigned long) t);
+}
+
+FcBool
+FcFileCacheSave (FcFileCache	*cache,
+		 const char	*cache_file)
+{
+    char	    *lck;
+    char	    *tmp;
+    FILE	    *f;
+    int		    h;
+    FcFileCacheEnt *c;
+
+    if (!cache->updated && cache->referenced == cache->entries)
+	return FcTrue;
+    
+    lck = malloc (strlen (cache_file)*2 + 4);
+    if (!lck)
+	goto bail0;
+    tmp = lck + strlen (cache_file) + 2;
+    strcpy (lck, cache_file);
+    strcat (lck, "L");
+    strcpy (tmp, cache_file);
+    strcat (tmp, "T");
+    if (link (lck, cache_file) < 0 && errno != ENOENT)
+	goto bail1;
+    if (access (tmp, F_OK) == 0)
+	goto bail2;
+    f = fopen (tmp, "w");
+    if (!f)
+	goto bail2;
+
+    for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
+    {
+	for (c = cache->ents[h]; c; c = c->next)
+	{
+	    if (!c->referenced)
+		continue;
+	    if (!FcFileCacheWriteString (f, c->file))
+		goto bail4;
+	    if (putc (' ', f) == EOF)
+		goto bail4;
+	    if (!FcFileCacheWriteInt (f, c->id))
+		goto bail4;
+	    if (putc (' ', f) == EOF)
+		goto bail4;
+	    if (!FcFileCacheWriteTime (f, c->time))
+		goto bail4;
+	    if (putc (' ', f) == EOF)
+		goto bail4;
+	    if (!FcFileCacheWriteString (f, c->name))
+		goto bail4;
+	    if (putc ('\n', f) == EOF)
+		goto bail4;
+	}
+    }
+
+    if (fclose (f) == EOF)
+	goto bail3;
+    
+    if (rename (tmp, cache_file) < 0)
+	goto bail3;
+    
+    unlink (lck);
+    cache->updated = FcFalse;
+    return FcTrue;
+
+bail4:
+    fclose (f);
+bail3:
+    unlink (tmp);
+bail2:
+    unlink (lck);
+bail1:
+    free (lck);
+bail0:
+    return FcFalse;
+}
+
+FcBool
+FcFileCacheReadDir (FcFontSet *set, const char *cache_file)
+{
+    FcPattern	    *font;
+    FILE	    *f;
+    char	    *path;
+    char	    *base;
+    char	    file[8192];
+    int		    id;
+    char	    name[8192];
+    FcBool	    ret = FcFalse;
+
+    if (FcDebug () & FC_DBG_CACHE)
+    {
+	printf ("FcFileCacheReadDir cache_file \"%s\"\n", cache_file);
+    }
+    
+    f = fopen (cache_file, "r");
+    if (!f)
+    {
+	if (FcDebug () & FC_DBG_CACHE)
+	{
+	    printf (" no cache file\n");
+	}
+	goto bail0;
+    }
+
+    base = strrchr (cache_file, '/');
+    if (!base)
+	goto bail1;
+    base++;
+    path = malloc (base - cache_file + 8192 + 1);
+    if (!path)
+	goto bail1;
+    memcpy (path, cache_file, base - cache_file);
+    base = path + (base - cache_file);
+    
+    while (FcFileCacheReadString (f, file, sizeof (file)) &&
+	   FcFileCacheReadInt (f, &id) &&
+	   FcFileCacheReadString (f, name, sizeof (name)))
+    {
+	font = FcNameParse (name);
+	if (font)
+	{
+	    strcpy (base, file);
+	    if (FcDebug () & FC_DBG_CACHEV)
+	    {
+		printf (" dir cache file \"%s\"\n", file);
+	    }
+	    FcPatternAddString (font, FC_FILE, path);
+	    if (!FcFontSetAdd (set, font))
+		goto bail2;
+	}
+    }
+    if (FcDebug () & FC_DBG_CACHE)
+    {
+	printf (" cache loaded\n");
+    }
+    
+    ret = FcTrue;
+bail2:
+    free (path);
+bail1:
+    fclose (f);
+bail0:
+    return ret;
+}
+
+FcBool
+FcFileCacheWriteDir (FcFontSet *set, const char *cache_file)
+{
+    FcPattern	    *font;
+    FILE	    *f;
+    char	    *name;
+    char	    *file, *base;
+    int		    n;
+    int		    id;
+    FcBool	    ret;
+
+    if (FcDebug () & FC_DBG_CACHE)
+	printf ("FcFileCacheWriteDir cache_file \"%s\"\n", cache_file);
+    
+    f = fopen (cache_file, "w");
+    if (!f)
+    {
+	if (FcDebug () & FC_DBG_CACHE)
+	    printf (" can't create \"%s\"\n", cache_file);
+	goto bail0;
+    }
+    for (n = 0; n < set->nfont; n++)
+    {
+	font = set->fonts[n];
+	if (FcPatternGetString (font, FC_FILE, 0, &file) != FcResultMatch)
+	    goto bail1;
+	base = strrchr (file, '/');
+	if (base)
+	    base = base + 1;
+	else
+	    base = file;
+	if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
+	    goto bail1;
+	if (FcDebug () & FC_DBG_CACHEV)
+	    printf (" write file \"%s\"\n", base);
+	if (!FcFileCacheWriteString (f, base))
+	    goto bail1;
+	if (putc (' ', f) == EOF)
+	    goto bail1;
+	if (!FcFileCacheWriteInt (f, id))
+	    goto bail1;
+        if (putc (' ', f) == EOF)
+	    goto bail1;
+	name = FcNameUnparse (font);
+	if (!name)
+	    goto bail1;
+	ret = FcFileCacheWriteString (f, name);
+	free (name);
+	if (!ret)
+	    goto bail1;
+	if (putc ('\n', f) == EOF)
+	    goto bail1;
+    }
+    if (fclose (f) == EOF)
+	goto bail0;
+    
+    if (FcDebug () & FC_DBG_CACHE)
+	printf (" cache written\n");
+    return FcTrue;
+    
+bail1:
+    fclose (f);
+bail0:
+    unlink (cache_file);
+    return FcFalse;
+}
diff --git a/src/fccfg.c b/src/fccfg.c
new file mode 100644
index 0000000..0280ee1
--- /dev/null
+++ b/src/fccfg.c
@@ -0,0 +1,1369 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "fcint.h"
+
+static FcConfig    *fcConfig;
+
+FcConfig *
+FcConfigCreate (void)
+{
+    FcSetName	set;
+    FcConfig	*config;
+
+    config = malloc (sizeof (FcConfig));
+    if (!config)
+	goto bail0;
+    
+    config->dirs = malloc (sizeof (char *));
+    if (!config->dirs)
+	goto bail1;
+    config->dirs[0] = 0;
+    
+    config->configFiles = malloc (sizeof (char *));
+    if (!config->configFiles)
+	goto bail2;
+    config->configFiles[0] = 0;
+    
+    config->cache = 0;
+    if (!FcConfigSetCache (config, "~/" FC_USER_CACHE_FILE))
+	goto bail3;
+
+    config->blanks = 0;
+
+    config->substPattern = 0;
+    config->substFont = 0;
+    config->maxObjects = 0;
+    for (set = FcSetSystem; set <= FcSetApplication; set++)
+	config->fonts[set] = 0;
+    
+    return config;
+
+bail3:
+    free (config->configFiles);
+bail2:
+    free (config->dirs);
+bail1:
+    free (config);
+bail0:
+    return 0;
+}
+
+static void
+FcSubstDestroy (FcSubst *s)
+{
+    FcSubst *n;
+    
+    while (s)
+    {
+	n = s->next;
+	FcTestDestroy (s->test);
+	FcEditDestroy (s->edit);
+	s = n;
+    }
+}
+
+static void
+FcConfigDestroyStrings (char **strings)
+{
+    char    **s;
+
+    for (s = strings; s && *s; s++)
+	free (*s);
+    if (strings)
+	free (strings);
+}
+    
+static FcBool
+FcConfigAddString (char ***strings, char *string)
+{
+    int	    n;
+    char    **s;
+    
+    n = 0;
+    for (s = *strings; s && *s; s++)
+	n++;
+    s = malloc ((n + 2) * sizeof (char *));
+    if (!s)
+	return FcFalse;
+    s[n] = string;
+    s[n+1] = 0;
+    memcpy (s, *strings, n * sizeof (char *));
+    free (*strings);
+    *strings = s;
+    return FcTrue;
+}
+
+void
+FcConfigDestroy (FcConfig *config)
+{
+    FcSetName	set;
+    FcConfigDestroyStrings (config->dirs);
+    FcConfigDestroyStrings (config->configFiles);
+
+    free (config->cache);
+
+    FcSubstDestroy (config->substPattern);
+    FcSubstDestroy (config->substFont);
+    for (set = FcSetSystem; set <= FcSetApplication; set++)
+	if (config->fonts[set])
+	    FcFontSetDestroy (config->fonts[set]);
+}
+
+/*
+ * Scan the current list of directories in the configuration
+ * and build the set of available fonts. Update the
+ * per-user cache file to reflect the new configuration
+ */
+
+FcBool
+FcConfigBuildFonts (FcConfig *config)
+{
+    FcFontSet   *fonts;
+    FcFileCache *cache;
+    char	**d;
+
+    fonts = FcFontSetCreate ();
+    if (!fonts)
+	goto bail0;
+    
+    cache = FcFileCacheCreate ();
+    if (!cache)
+	goto bail1;
+
+    FcFileCacheLoad (cache, config->cache);
+
+    for (d = config->dirs; d && *d; d++)
+    {
+	if (FcDebug () & FC_DBG_FONTSET)
+	    printf ("scan dir %s\n", *d);
+	FcDirScan (fonts, cache, config->blanks, *d, FcFalse);
+    }
+    
+    if (FcDebug () & FC_DBG_FONTSET)
+	FcFontSetPrint (fonts);
+
+    FcFileCacheSave (cache, config->cache);
+    FcFileCacheDestroy (cache);
+
+    FcConfigSetFonts (config, fonts, FcSetSystem);
+    
+    return FcTrue;
+bail1:
+    FcFontSetDestroy (fonts);
+bail0:
+    return FcFalse;
+}
+
+FcBool
+FcConfigSetCurrent (FcConfig *config)
+{
+    if (!config->fonts)
+	if (!FcConfigBuildFonts (config))
+	    return FcFalse;
+
+    if (fcConfig)
+	FcConfigDestroy (fcConfig);
+    fcConfig = config;
+    return FcTrue;
+}
+
+FcConfig *
+FcConfigGetCurrent (void)
+{
+    return fcConfig;
+}
+
+FcBool
+FcConfigAddDir (FcConfig    *config,
+		const char  *d)
+{
+    char    *dir;
+    char    *h;
+
+    if (*d == '~')
+    {
+	h = getenv ("HOME");
+	if (!h)
+	    return FcFalse;
+	dir = (char *) malloc (strlen (h) + strlen (d));
+	if (!dir)
+	    return FcFalse;
+	strcpy (dir, h);
+	strcat (dir, d+1);
+    }
+    else
+    {
+	dir = (char *) malloc (strlen (d) + 1);
+	if (!dir)
+	    return FcFalse;
+	strcpy (dir, d);
+    }
+    if (!FcConfigAddString (&config->dirs, dir))
+    {
+	free (dir);
+	return FcFalse;
+    }
+    return FcTrue;
+}
+
+char **
+FcConfigGetDirs (FcConfig   *config)
+{
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    return config->dirs;
+}
+
+FcBool
+FcConfigAddConfigFile (FcConfig	    *config,
+		       const char   *f)
+{
+    char    *file;
+    file = FcConfigFilename (f);
+    if (!file)
+	return FcFalse;
+    if (!FcConfigAddString (&config->configFiles, file))
+    {
+	free (file);
+	return FcFalse;
+    }
+    return FcTrue;
+}
+
+char **
+FcConfigGetConfigFiles (FcConfig    *config)
+{
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    return config->configFiles;
+}
+
+FcBool
+FcConfigSetCache (FcConfig	*config,
+		  const char	*c)
+{
+    char    *new;
+    char    *h;
+
+    if (*c == '~')
+    {
+	h = getenv ("HOME");
+	if (!h)
+	    return FcFalse;
+	new = (char *) malloc (strlen (h) + strlen (c));
+	if (!new)
+	    return FcFalse;
+	strcpy (new, h);
+	strcat (new, c+1);
+    }
+    else
+    {
+	new = FcStrCopy (c);
+    }
+    if (config->cache)
+	free (config->cache);
+    config->cache = new;
+    return FcTrue;
+}
+
+char *
+FcConfigGetCache (FcConfig  *config)
+{
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    return config->cache;
+}
+
+FcFontSet *
+FcConfigGetFonts (FcConfig	*config,
+		  FcSetName	set)
+{
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    return config->fonts[set];
+}
+
+void
+FcConfigSetFonts (FcConfig	*config,
+		  FcFontSet	*fonts,
+		  FcSetName	set)
+{
+    if (config->fonts[set])
+	FcFontSetDestroy (config->fonts[set]);
+    config->fonts[set] = fonts;
+}
+
+FcBlanks *
+FcConfigGetBlanks (FcConfig	*config)
+{
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    return config->blanks;
+}
+
+FcBool
+FcConfigAddBlank (FcConfig	*config,
+		  FcChar32    	blank)
+{
+    FcBlanks	*b;
+    
+    b = config->blanks;
+    if (!b)
+    {
+	b = FcBlanksCreate ();
+	if (!b)
+	    return FcFalse;
+    }
+    if (!FcBlanksAdd (b, blank))
+	return FcFalse;
+    config->blanks = b;
+    return FcTrue;
+}
+
+FcBool
+FcConfigAddEdit (FcConfig	*config,
+		 FcTest		*test,
+		 FcEdit		*edit,
+		 FcMatchKind	kind)
+{
+    FcSubst	*subst, **prev;
+    FcTest	*t;
+    int		num;
+
+    subst = (FcSubst *) malloc (sizeof (FcSubst));
+    if (!subst)
+	return FcFalse;
+    if (kind == FcMatchPattern)
+	prev = &config->substPattern;
+    else
+	prev = &config->substFont;
+    for (; *prev; prev = &(*prev)->next);
+    *prev = subst;
+    subst->next = 0;
+    subst->test = test;
+    subst->edit = edit;
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("Add Subst ");
+	FcSubstPrint (subst);
+    }
+    num = 0;
+    for (t = test; t; t = t->next)
+	num++;
+    if (config->maxObjects < num)
+	config->maxObjects = num;
+    return FcTrue;
+}
+
+typedef struct _FcSubState {
+    FcPatternElt   *elt;
+    FcValueList    *value;
+} FcSubState;
+
+static const FcMatrix    FcIdentityMatrix = { 1, 0, 0, 1 };
+
+static FcValue
+FcConfigPromote (FcValue v, FcValue u)
+{
+    if (v.type == FcTypeInteger)
+    {
+	v.type = FcTypeDouble;
+	v.u.d = (double) v.u.i;
+    }
+    else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
+    {
+	v.u.m = (FcMatrix *) &FcIdentityMatrix;
+	v.type = FcTypeMatrix;
+    }
+    return v;
+}
+
+FcBool
+FcConfigCompareValue (FcValue	m,
+		      FcOp	op,
+		      FcValue	v)
+{
+    FcBool    ret = FcFalse;
+    
+    m = FcConfigPromote (m, v);
+    v = FcConfigPromote (v, m);
+    if (m.type == v.type) 
+    {
+	ret = FcFalse;
+	switch (m.type) {
+	case FcTypeInteger:
+	    break;	/* FcConfigPromote prevents this from happening */
+	case FcTypeDouble:
+	    switch (op) {
+	    case FcOpEqual:
+	    case FcOpContains:
+		ret = m.u.d == v.u.d;
+		break;
+	    case FcOpNotEqual:    
+		ret = m.u.d != v.u.d;
+		break;
+	    case FcOpLess:    
+		ret = m.u.d < v.u.d;
+		break;
+	    case FcOpLessEqual:    
+		ret = m.u.d <= v.u.d;
+		break;
+	    case FcOpMore:    
+		ret = m.u.d > v.u.d;
+		break;
+	    case FcOpMoreEqual:    
+		ret = m.u.d >= v.u.d;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	case FcTypeBool:
+	    switch (op) {
+	    case FcOpEqual:    
+	    case FcOpContains:
+		ret = m.u.b == v.u.b;
+		break;
+	    case FcOpNotEqual:    
+		ret = m.u.b != v.u.b;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	case FcTypeString:
+	    switch (op) {
+	    case FcOpEqual:    
+	    case FcOpContains:
+		ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0;
+		break;
+	    case FcOpNotEqual:    
+		ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	case FcTypeMatrix:
+	    switch (op) {
+	    case FcOpEqual:
+	    case FcOpContains:
+		ret = FcMatrixEqual (m.u.m, v.u.m);
+		break;
+	    case FcOpNotEqual:
+		ret = !FcMatrixEqual (m.u.m, v.u.m);
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	case FcTypeCharSet:
+	    switch (op) {
+	    case FcOpContains:
+		/* m contains v if v - m is empty */
+		ret = FcCharSetSubtractCount (v.u.c, m.u.c) == 0;
+		break;
+	    case FcOpEqual:
+		ret = FcCharSetEqual (m.u.c, v.u.c);
+		break;
+	    case FcOpNotEqual:
+		ret = !FcCharSetEqual (m.u.c, v.u.c);
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	case FcTypeVoid:
+	    switch (op) {
+	    case FcOpEqual:
+	    case FcOpContains:
+		ret = FcTrue;
+		break;
+	    default:
+		break;
+	    }
+	    break;
+	}
+    }
+    else
+    {
+	if (op == FcOpNotEqual)
+	    ret = FcTrue;
+    }
+    return ret;
+}
+
+
+static FcValue
+FcConfigEvaluate (FcPattern *p, FcExpr *e)
+{
+    FcValue	v, vl, vr;
+    FcResult	r;
+    FcMatrix	*m;
+    FcChar8	*s;
+    
+    switch (e->op) {
+    case FcOpInteger:
+	v.type = FcTypeInteger;
+	v.u.i = e->u.ival;
+	break;
+    case FcOpDouble:
+	v.type = FcTypeDouble;
+	v.u.d = e->u.dval;
+	break;
+    case FcOpString:
+	v.type = FcTypeString;
+	v.u.s = e->u.sval;
+	v = FcValueSave (v);
+	break;
+    case FcOpMatrix:
+	v.type = FcTypeMatrix;
+	v.u.m = e->u.mval;
+	v = FcValueSave (v);
+	break;
+    case FcOpCharSet:
+	v.type = FcTypeCharSet;
+	v.u.c = e->u.cval;
+	v = FcValueSave (v);
+	break;
+    case FcOpBool:
+	v.type = FcTypeBool;
+	v.u.b = e->u.bval;
+	break;
+    case FcOpField:
+	r = FcPatternGet (p, e->u.field, 0, &v);
+	if (r != FcResultMatch)
+	    v.type = FcTypeVoid;
+	break;
+    case FcOpConst:
+	if (FcNameConstant (e->u.constant, &v.u.i))
+	    v.type = FcTypeInteger;
+	else
+	    v.type = FcTypeVoid;
+	break;
+    case FcOpQuest:
+	vl = FcConfigEvaluate (p, e->u.tree.left);
+	if (vl.type == FcTypeBool)
+	{
+	    if (vl.u.b)
+		v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left);
+	    else
+		v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right);
+	}
+	else
+	    v.type = FcTypeVoid;
+	FcValueDestroy (vl);
+	break;
+    case FcOpOr:
+    case FcOpAnd:
+    case FcOpEqual:
+    case FcOpContains:
+    case FcOpNotEqual:
+    case FcOpLess:
+    case FcOpLessEqual:
+    case FcOpMore:
+    case FcOpMoreEqual:
+    case FcOpPlus:
+    case FcOpMinus:
+    case FcOpTimes:
+    case FcOpDivide:
+	vl = FcConfigEvaluate (p, e->u.tree.left);
+	vr = FcConfigEvaluate (p, e->u.tree.right);
+	vl = FcConfigPromote (vl, vr);
+	vr = FcConfigPromote (vr, vl);
+	if (vl.type == vr.type)
+	{
+	    switch (vl.type) {
+	    case FcTypeDouble:
+		switch (e->op) {
+		case FcOpPlus:	   
+		    v.type = FcTypeDouble;
+		    v.u.d = vl.u.d + vr.u.d; 
+		    break;
+		case FcOpMinus:
+		    v.type = FcTypeDouble;
+		    v.u.d = vl.u.d - vr.u.d; 
+		    break;
+		case FcOpTimes:
+		    v.type = FcTypeDouble;
+		    v.u.d = vl.u.d * vr.u.d; 
+		    break;
+		case FcOpDivide:
+		    v.type = FcTypeDouble;
+		    v.u.d = vl.u.d / vr.u.d; 
+		    break;
+		case FcOpEqual:
+		case FcOpContains:
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d == vr.u.d;
+		    break;
+		case FcOpNotEqual:    
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d != vr.u.d;
+		    break;
+		case FcOpLess:    
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d < vr.u.d;
+		    break;
+		case FcOpLessEqual:    
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d <= vr.u.d;
+		    break;
+		case FcOpMore:    
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d > vr.u.d;
+		    break;
+		case FcOpMoreEqual:    
+		    v.type = FcTypeBool; 
+		    v.u.b = vl.u.d >= vr.u.d;
+		    break;
+		default:
+		    v.type = FcTypeVoid; 
+		    break;
+		}
+		if (v.type == FcTypeDouble &&
+		    v.u.d == (double) (int) v.u.d)
+		{
+		    v.type = FcTypeInteger;
+		    v.u.i = (int) v.u.d;
+		}
+		break;
+	    case FcTypeBool:
+		switch (e->op) {
+		case FcOpOr:
+		    v.type = FcTypeBool;
+		    v.u.b = vl.u.b || vr.u.b;
+		    break;
+		case FcOpAnd:
+		    v.type = FcTypeBool;
+		    v.u.b = vl.u.b && vr.u.b;
+		    break;
+		case FcOpEqual:
+		case FcOpContains:
+		    v.type = FcTypeBool;
+		    v.u.b = vl.u.b == vr.u.b;
+		    break;
+		case FcOpNotEqual:
+		    v.type = FcTypeBool;
+		    v.u.b = vl.u.b != vr.u.b;
+		    break;
+		default:
+		    v.type = FcTypeVoid; 
+		    break;
+		}
+		break;
+	    case FcTypeString:
+		switch (e->op) {
+		case FcOpEqual:
+		case FcOpContains:
+		    v.type = FcTypeBool;
+		    v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) == 0;
+		    break;
+		case FcOpNotEqual:
+		    v.type = FcTypeBool;
+		    v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) != 0;
+		    break;
+		case FcOpPlus:
+		    v.type = FcTypeString;
+		    v.u.s = FcStrPlus (vl.u.s, vr.u.s);
+		    if (!v.u.s)
+			v.type = FcTypeVoid;
+		    break;
+		default:
+		    v.type = FcTypeVoid;
+		    break;
+		}
+	    case FcTypeMatrix:
+		switch (e->op) {
+		case FcOpEqual:
+		case FcOpContains:
+		    v.type = FcTypeBool;
+		    v.u.b = FcMatrixEqual (vl.u.m, vr.u.m);
+		    break;
+		case FcOpNotEqual:
+		    v.type = FcTypeBool;
+		    v.u.b = FcMatrixEqual (vl.u.m, vr.u.m);
+		    break;
+		case FcOpTimes:
+		    v.type = FcTypeMatrix;
+		    m = malloc (sizeof (FcMatrix));
+		    if (m)
+		    {
+			FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
+			FcMatrixMultiply (m, vl.u.m, vr.u.m);
+			v.u.m = m;
+		    }
+		    else
+		    {
+			v.type = FcTypeVoid;
+		    }
+		    break;
+		default:
+		    v.type = FcTypeVoid;
+		    break;
+		}
+		break;
+	    case FcTypeCharSet:
+		switch (e->op) {
+		case FcOpContains:
+		    /* vl contains vr if vr - vl is empty */
+		    v.type = FcTypeBool;
+		    v.u.b = FcCharSetSubtractCount (vr.u.c, vl.u.c) == 0;
+		    break;
+		case FcOpEqual:
+		    v.type = FcTypeBool;
+		    v.u.b = FcCharSetEqual (vl.u.c, vr.u.c);
+		    break;
+		case FcOpNotEqual:
+		    v.type = FcTypeBool;
+		    v.u.b = !FcCharSetEqual (vl.u.c, vr.u.c);
+		    break;
+		default:
+		    v.type = FcTypeVoid;
+		    break;
+		}
+		break;
+	    default:
+		v.type = FcTypeVoid;
+		break;
+	    }
+	}
+	else
+	    v.type = FcTypeVoid;
+	FcValueDestroy (vl);
+	FcValueDestroy (vr);
+	break;
+    case FcOpNot:
+	vl = FcConfigEvaluate (p, e->u.tree.left);
+	switch (vl.type) {
+	case FcTypeBool:
+	    v.type = FcTypeBool;
+	    v.u.b = !vl.u.b;
+	    break;
+	default:
+	    v.type = FcTypeVoid;
+	    break;
+	}
+	FcValueDestroy (vl);
+	break;
+    default:
+	v.type = FcTypeVoid;
+	break;
+    }
+    return v;
+}
+
+static FcValueList *
+FcConfigMatchValueList (FcPattern	*p,
+			FcTest		*t,
+			FcValueList	*v)
+{
+    FcValueList    *ret = 0;
+    FcValue	    value = FcConfigEvaluate (p, t->expr);
+    
+    for (; v; v = v->next)
+    {
+	if (FcConfigCompareValue (v->value, t->op, value))
+	{
+	    if (!ret)
+		ret = v;
+	}
+	else
+	{
+	    if (t->qual == FcQualAll)
+	    {
+		ret = 0;
+		break;
+	    }
+	}
+    }
+    FcValueDestroy (value);
+    return ret;
+}
+
+static FcValueList *
+FcConfigValues (FcPattern *p, FcExpr *e)
+{
+    FcValueList	*l;
+    
+    if (!e)
+	return 0;
+    l = (FcValueList *) malloc (sizeof (FcValueList));
+    if (!l)
+	return 0;
+    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
+    if (e->op == FcOpComma)
+    {
+	l->value = FcConfigEvaluate (p, e->u.tree.left);
+	l->next  = FcConfigValues (p, e->u.tree.right);
+    }
+    else
+    {
+	l->value = FcConfigEvaluate (p, e);
+	l->next  = 0;
+    }
+    while (l->value.type == FcTypeVoid)
+    {
+	FcValueList	*next = l->next;
+	
+	FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+	free (l);
+	l = next;
+    }
+    return l;
+}
+
+static FcBool
+FcConfigAdd (FcValueList    **head,
+	     FcValueList    *position,
+	     FcBool	    append,
+	     FcValueList    *new)
+{
+    FcValueList    **prev, *last;
+    
+    if (append)
+    {
+	if (position)
+	    prev = &position->next;
+	else
+	    for (prev = head; *prev; prev = &(*prev)->next)
+		;
+    }
+    else
+    {
+	if (position)
+	{
+	    for (prev = head; *prev; prev = &(*prev)->next)
+	    {
+		if (*prev == position)
+		    break;
+	    }
+	}
+	else
+	    prev = head;
+
+	if (FcDebug () & FC_DBG_EDIT)
+	{
+	    if (!*prev)
+		printf ("position not on list\n");
+	}
+    }
+
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("%s list before ", append ? "Append" : "Prepend");
+	FcValueListPrint (*head);
+	printf ("\n");
+    }
+    
+    if (new)
+    {
+	last = new;
+	while (last->next)
+	    last = last->next;
+    
+	last->next = *prev;
+	*prev = new;
+    }
+    
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("%s list after ", append ? "Append" : "Prepend");
+	FcValueListPrint (*head);
+	printf ("\n");
+    }
+    
+    return FcTrue;
+}
+
+static void
+FcConfigDel (FcValueList    **head,
+	     FcValueList    *position)
+{
+    FcValueList    **prev;
+
+    for (prev = head; *prev; prev = &(*prev)->next)
+    {
+	if (*prev == position)
+	{
+	    *prev = position->next;
+	    position->next = 0;
+	    FcValueListDestroy (position);
+	    break;
+	}
+    }
+}
+
+static void
+FcConfigPatternAdd (FcPattern	*p,
+		    const char	*object,
+		    FcValueList	*list,
+		    FcBool	append)
+{
+    if (list)
+    {
+	FcPatternElt    *e = FcPatternFind (p, object, FcTrue);
+    
+	if (!e)
+	    return;
+	FcConfigAdd (&e->values, 0, append, list);
+    }
+}
+
+/*
+ * Delete all values associated with a field
+ */
+static void
+FcConfigPatternDel (FcPattern	*p,
+		    const char	*object)
+{
+    FcPatternElt    *e = FcPatternFind (p, object, FcFalse);
+    if (!e)
+	return;
+    while (e->values)
+	FcConfigDel (&e->values, e->values);
+}
+
+static void
+FcConfigPatternCanon (FcPattern	    *p,
+		      const char    *object)
+{
+    FcPatternElt    *e = FcPatternFind (p, object, FcFalse);
+    if (!e)
+	return;
+    if (!e->values)
+	FcPatternDel (p, object);
+}
+
+FcBool
+FcConfigSubstitute (FcConfig	*config,
+		    FcPattern	*p,
+		    FcMatchKind	kind)
+{
+    FcSubst	    *s;
+    FcSubState	    *st;
+    int		    i;
+    FcTest	    *t;
+    FcEdit	    *e;
+    FcValueList	    *l;
+
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return FcFalse;
+    }
+
+    st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
+    if (!st && config->maxObjects)
+	return FcFalse;
+    FcMemAlloc (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
+
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("FcConfigSubstitute ");
+	FcPatternPrint (p);
+    }
+    if (kind == FcMatchPattern)
+	s = config->substPattern;
+    else
+	s = config->substFont;
+    for (; s; s = s->next)
+    {
+	/*
+	 * Check the tests to see if
+	 * they all match the pattern
+	 */
+	for (t = s->test, i = 0; t; t = t->next, i++)
+	{
+	    if (FcDebug () & FC_DBG_EDIT)
+	    {
+		printf ("FcConfigSubstitute test ");
+		FcTestPrint (t);
+	    }
+	    st[i].elt = FcPatternFind (p, t->field, FcFalse);
+	    /*
+	     * If there's no such field in the font,
+	     * then FcQualAll matches while FcQualAny does not
+	     */
+	    if (!st[i].elt)
+	    {
+		if (t->qual == FcQualAll)
+		{
+		    st[i].value = 0;
+		    continue;
+		}
+		else
+		    break;
+	    }
+	    /*
+	     * Check to see if there is a match, mark the location
+	     * to apply match-relative edits
+	     */
+	    st[i].value = FcConfigMatchValueList (p, t, st[i].elt->values);
+	    if (!st[i].value)
+		break;
+	}
+	if (t)
+	{
+	    if (FcDebug () & FC_DBG_EDIT)
+		printf ("No match\n");
+	    continue;
+	}
+	if (FcDebug () & FC_DBG_EDIT)
+	{
+	    printf ("Substitute ");
+	    FcSubstPrint (s);
+	}
+	for (e = s->edit; e; e = e->next)
+	{
+	    /*
+	     * Evaluate the list of expressions
+	     */
+	    l = FcConfigValues (p, e->expr);
+	    /*
+	     * Locate any test associated with this field
+	     */
+	    for (t = s->test, i = 0; t; t = t->next, i++)
+		if (!FcStrCmpIgnoreCase (t->field, e->field))
+		    break;
+	    switch (e->op) {
+	    case FcOpAssign:
+		/*
+		 * If there was a test, then replace the matched
+		 * value with the new list of values
+		 */
+		if (t)
+		{
+		    FcValueList	*thisValue = st[i].value;
+		    FcValueList	*nextValue = thisValue ? thisValue->next : 0;
+		    
+		    /*
+		     * Append the new list of values after the current value
+		     */
+		    FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l);
+		    /*
+		     * Adjust any pointers into the value list to ensure
+		     * future edits occur at the same place
+		     */
+		    for (t = s->test, i = 0; t; t = t->next, i++)
+		    {
+			if (st[i].value == thisValue)
+			    st[i].value = nextValue;
+		    }
+		    /*
+		     * Delete the marked value
+		     */
+		    FcConfigDel (&st[i].elt->values, thisValue);
+		    break;
+		}
+		/* fall through ... */
+	    case FcOpAssignReplace:
+		/*
+		 * Delete all of the values and insert
+		 * the new set
+		 */
+		FcConfigPatternDel (p, e->field);
+		FcConfigPatternAdd (p, e->field, l, FcTrue);
+		/*
+		 * Adjust any pointers into the value list as they no
+		 * longer point to anything valid
+		 */
+		if (t)
+		{
+		    FcPatternElt    *thisElt = st[i].elt;
+		    for (t = s->test, i = 0; t; t = t->next, i++)
+		    {
+			if (st[i].elt == thisElt)
+			    st[i].value = 0;
+		    }
+		}
+		break;
+	    case FcOpPrepend:
+		if (t)
+		{
+		    FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l);
+		    break;
+		}
+		/* fall through ... */
+	    case FcOpPrependFirst:
+		FcConfigPatternAdd (p, e->field, l, FcFalse);
+		break;
+	    case FcOpAppend:
+		if (t)
+		{
+		    FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l);
+		    break;
+		}
+		/* fall through ... */
+	    case FcOpAppendLast:
+		FcConfigPatternAdd (p, e->field, l, FcTrue);
+		break;
+	    default:
+		break;
+	    }
+	}
+	/*
+	 * Now go through the pattern and eliminate
+	 * any properties without data
+	 */
+	for (e = s->edit; e; e = e->next)
+	    FcConfigPatternCanon (p, e->field);
+
+	if (FcDebug () & FC_DBG_EDIT)
+	{
+	    printf ("FcConfigSubstitute edit");
+	    FcPatternPrint (p);
+	}
+    }
+    FcMemFree (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
+    free (st);
+    if (FcDebug () & FC_DBG_EDIT)
+    {
+	printf ("FcConfigSubstitute done");
+	FcPatternPrint (p);
+    }
+    return FcTrue;
+}
+
+#ifndef FONTCONFIG_PATH
+#define FONTCONFIG_PATH	"/etc/fonts"
+#endif
+
+#ifndef FONTCONFIG_FILE
+#define FONTCONFIG_FILE	"fonts.conf"
+#endif
+
+static char *
+FcConfigFileExists (const char *dir, const char *file)
+{
+    char    *path;
+
+    if (!dir)
+	dir = "";
+    path = malloc (strlen (dir) + 1 + strlen (file) + 1);
+    if (!path)
+	return 0;
+
+    strcpy (path, dir);
+    /* make sure there's a single separating / */
+    if ((!path[0] || path[strlen(path)-1] != '/') && file[0] != '/')
+	strcat (path, "/");
+    strcat (path, file);
+
+    if (access (path, R_OK) == 0)
+	return path;
+    
+    free (path);
+    return 0;
+}
+
+static char **
+FcConfigGetPath (void)
+{
+    char    **path;
+    char    *env, *e, *colon;
+    char    *dir;
+    int	    npath;
+    int	    i;
+
+    npath = 2;	/* default dir + null */
+    env = getenv ("FONTCONFIG_PATH");
+    if (env)
+    {
+	e = env;
+	npath++;
+	while (*e)
+	    if (*e++ == ':')
+		npath++;
+    }
+    path = calloc (npath, sizeof (char *));
+    if (!path)
+	goto bail0;
+    i = 0;
+
+    if (env)
+    {
+	e = env;
+	while (*e) 
+	{
+	    colon = strchr (e, ':');
+	    if (!colon)
+		colon = e + strlen (e);
+	    path[i] = malloc (colon - e + 1);
+	    if (!path[i])
+		goto bail1;
+	    strncpy (path[i], e, colon - e);
+	    path[i][colon - e] = '\0';
+	    if (*colon)
+		e = colon + 1;
+	    else
+		e = colon;
+	    i++;
+	}
+    }
+    
+    dir = FONTCONFIG_PATH;
+    path[i] = malloc (strlen (dir) + 1);
+    if (!path[i])
+	goto bail1;
+    strcpy (path[i], dir);
+    return path;
+
+bail1:
+    for (i = 0; path[i]; i++)
+	free (path[i]);
+    free (path);
+bail0:
+    return 0;
+}
+
+static void
+FcConfigFreePath (char **path)
+{
+    char    **p;
+
+    for (p = path; *p; p++)
+	free (*p);
+    free (path);
+}
+
+char *
+FcConfigFilename (const char *url)
+{
+    char    *file, *dir, **path, **p;
+    
+    if (!url || !*url)
+    {
+	url = getenv ("FONTCONFIG_FILE");
+	if (!url)
+	    url = FONTCONFIG_FILE;
+    }
+    switch (*url) {
+    case '~':
+	dir = getenv ("HOME");
+	if (dir)
+	    file = FcConfigFileExists (dir, url + 1);
+	else
+	    file = 0;
+	break;
+    case '/':
+	file = FcConfigFileExists (0, url);
+	break;
+    default:
+	path = FcConfigGetPath ();
+	if (!path)
+	    return 0;
+	for (p = path; *p; p++)
+	{
+	    file = FcConfigFileExists (*p, url);
+	    if (file)
+		break;
+	}
+	FcConfigFreePath (path);
+	break;
+    }
+    return file;
+}
+
+/*
+ * Manage the application-specific fonts
+ */
+
+FcBool
+FcConfigAppFontAddFile (FcConfig    *config,
+			const char  *file)
+{
+    FcFontSet	*set;
+
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return FcFalse;
+    }
+
+    set = FcConfigGetFonts (config, FcSetApplication);
+    if (!set)
+    {
+	set = FcFontSetCreate ();
+	if (!set)
+	    return FcFalse;
+	FcConfigSetFonts (config, set, FcSetApplication);
+    }
+    return FcFileScan (set, 0, config->blanks, file, FcFalse);
+}
+
+FcBool
+FcConfigAppFontAddDir (FcConfig	    *config,
+		       const char   *dir)
+{
+    FcFontSet	*set;
+    
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return FcFalse;
+    }
+    set = FcConfigGetFonts (config, FcSetApplication);
+    if (!set)
+    {
+	set = FcFontSetCreate ();
+	if (!set)
+	    return FcFalse;
+	FcConfigSetFonts (config, set, FcSetApplication);
+    }
+    return FcDirScan (set, 0, config->blanks, dir, FcFalse);
+}
+
+void
+FcConfigAppFontClear (FcConfig	    *config)
+{
+    FcConfigSetFonts (config, 0, FcSetApplication);
+}
diff --git a/src/fccharset.c b/src/fccharset.c
new file mode 100644
index 0000000..b29a48a
--- /dev/null
+++ b/src/fccharset.c
@@ -0,0 +1,1521 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+/* #define CHECK */
+
+static int
+FcCharSetLevels (FcChar32 ucs4)
+{
+    if (ucs4 <= 0xff)
+	return 1;
+    if (ucs4 <= 0xffff)
+	return 2;
+    if (ucs4 <= 0xffffff)
+	return 3;
+    return 4;
+}
+
+static FcBool
+FcCharSetCheckLevel (FcCharSet *fcs, FcChar32 ucs4)
+{
+    int	level = FcCharSetLevels (ucs4);
+    
+    if (level <= fcs->levels)
+	return FcTrue;
+    while (fcs->levels < level)
+    {
+	if (fcs->levels == 0)
+	{
+	    FcCharLeaf	    *leaf;
+
+	    leaf = (FcCharLeaf *) calloc (1, sizeof (FcCharLeaf));
+	    if (!leaf)
+		return FcFalse;
+	    FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
+	    fcs->node.leaf = leaf;
+	}
+	else
+	{
+	    FcCharBranch    *branch;
+    
+	    branch = (FcCharBranch *) calloc (1, sizeof (FcCharBranch));
+	    if (!branch)
+		return FcFalse;
+	    FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharBranch));
+	    branch->nodes[0] = fcs->node;
+	    fcs->node.branch = branch;
+	}
+	++fcs->levels;
+    }
+    return FcTrue;
+}
+
+FcCharSet *
+FcCharSetCreate (void)
+{
+    FcCharSet	*fcs;
+
+    fcs = (FcCharSet *) malloc (sizeof (FcCharSet));
+    if (!fcs)
+	return 0;
+    FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
+    fcs->ref = 1;
+    fcs->levels = 0;
+    fcs->node.leaf = 0;
+    fcs->constant = FcFalse;
+    return fcs;
+}
+
+FcCharSet *
+FcCharSetNew (void);
+    
+FcCharSet *
+FcCharSetNew (void)
+{
+    return FcCharSetCreate ();
+}
+
+static void
+FcCharNodeDestroy (FcCharNode node, int level)
+{
+    int	i;
+
+    switch (level) {
+    case 0:
+	break;
+    case 1:
+	FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
+	free (node.leaf);
+	break;
+    default:
+	for (i = 0; i < 256; i++)
+	    if (node.branch->nodes[i].branch)
+		FcCharNodeDestroy (node.branch->nodes[i], level - 1);
+        FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharBranch));
+	free (node.branch);
+    }
+}
+
+void
+FcCharSetDestroy (FcCharSet *fcs)
+{
+    if (fcs->constant)
+	return;
+    if (--fcs->ref <= 0)
+    {
+	FcCharNodeDestroy (fcs->node, fcs->levels);
+	FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+	free (fcs);
+    }
+}
+
+/*
+ * Locate the leaf containing the specified char, returning
+ * null if it doesn't exist
+ */
+
+static FcCharLeaf *
+FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
+{
+    int			l;
+    const FcCharNode	*prev;
+    FcCharNode		node;
+    FcChar8		i;
+
+    prev = &fcs->node;
+    l = fcs->levels;
+    while (--l > 0)
+    {
+	node = *prev;
+	if (!node.branch)
+	    return 0;
+	i = (ucs4 >> (l << 3)) & 0xff;
+	prev = &node.branch->nodes[i];
+    }
+    return prev->leaf;
+}
+
+/*
+ * Locate the leaf containing the specified char, creating it
+ * if desired
+ */
+
+static FcCharLeaf *
+FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
+{
+    int		l;
+    FcCharNode  *prev, node;
+    FcChar8	i;
+
+    if (!FcCharSetCheckLevel (fcs, ucs4))
+	return FcFalse;
+    prev = &fcs->node;
+    l = fcs->levels;
+    while (--l > 0)
+    {
+	node = *prev;
+	if (!node.branch)
+	{
+	    node.branch = calloc (1, sizeof (FcCharBranch));
+	    if (!node.branch)
+		return 0;
+	    FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharBranch));
+	    *prev = node;
+	}
+	i = (ucs4 >> (l << 3)) & 0xff;
+	prev = &node.branch->nodes[i];
+    }
+    node = *prev;
+    if (!node.leaf)
+    {
+	node.leaf = calloc (1, sizeof (FcCharLeaf));
+	if (!node.leaf)
+	    return 0;
+	FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
+	*prev = node;
+    }
+    return node.leaf;
+}
+
+FcBool
+FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
+{
+    FcCharLeaf	*leaf;
+    FcChar32	*b;
+    
+    if (fcs->constant)
+	return FcFalse;
+    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+    if (!leaf)
+	return FcFalse;
+    b = &leaf->map[(ucs4 & 0xff) >> 5];
+    *b |= (1 << (ucs4 & 0x1f));
+    return FcTrue;
+}
+
+/*
+ * An iterator for the leaves of a charset
+ */
+
+typedef struct _fcCharSetIter {
+    FcCharLeaf	    *leaf;
+    FcChar32	    ucs4;
+} FcCharSetIter;
+
+/*
+ * Find the nearest leaf at or beyond *ucs4, return 0 if no leaf
+ * exists
+ */
+static FcCharLeaf *
+FcCharSetIterLeaf (FcCharNode node, int level, FcChar32 *ucs4)
+{
+    if (level <= 1)
+        return node.leaf;
+    else if (!node.branch)
+	return 0;
+    else
+    {
+	int	    shift = ((level - 1) << 3);
+	FcChar32    inc = 1 << shift;
+	FcChar32    mask = ~(inc - 1);
+	FcChar8	    byte = (*ucs4 >> shift) & 0xff;
+	FcCharLeaf  *leaf;
+
+	for (;;)
+	{
+	    leaf = FcCharSetIterLeaf (node.branch->nodes[byte], 
+				      level - 1, 
+				      ucs4);
+	    if (leaf)
+		break;
+	    /* step to next branch, resetting lower indices */
+	    *ucs4 = (*ucs4 & mask) + inc;
+	    byte++;
+	    if (byte == 0)
+		break;
+	}
+	return leaf;
+    }
+}
+
+static void
+FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+    if (FcCharSetLevels (iter->ucs4) > fcs->levels)
+	iter->leaf = 0;
+    else
+	iter->leaf = FcCharSetIterLeaf (fcs->node, fcs->levels,
+					&iter->ucs4);
+    if (!iter->leaf)
+	iter->ucs4 = ~0;
+}
+
+static void
+FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+    iter->ucs4 += 0x100;
+    FcCharSetIterSet (fcs, iter);
+}
+
+static void
+FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+    iter->ucs4 = 0;
+    FcCharSetIterSet (fcs, iter);
+}
+
+FcCharSet *
+FcCharSetCopy (FcCharSet *src)
+{
+    src->ref++;
+    return src;
+}
+
+FcBool
+FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
+{
+    FcCharSetIter   ai, bi;
+    int		    i;
+    
+    if (a == b)
+	return FcTrue;
+    for (FcCharSetIterStart (a, &ai), FcCharSetIterStart (b, &bi);
+	 ai.leaf && bi.leaf;
+	 FcCharSetIterNext (a, &ai), FcCharSetIterNext (b, &bi))
+    {
+	if (ai.ucs4 != bi.ucs4)
+	    return FcFalse;
+	for (i = 0; i < 256/32; i++)
+	    if (ai.leaf->map[i] != bi.leaf->map[i])
+		return FcFalse;
+    }
+    return ai.leaf == bi.leaf;
+}
+
+static FcBool
+FcCharSetAddLeaf (FcCharSet	*fcs,
+		  FcChar32	ucs4,
+		  FcCharLeaf	*leaf)
+{
+    FcCharLeaf   *new = FcCharSetFindLeafCreate (fcs, ucs4);
+    if (!new)
+	return FcFalse;
+    *new = *leaf;
+    return FcTrue;
+}
+
+static FcCharSet *
+FcCharSetOperate (const FcCharSet   *a,
+		  const FcCharSet   *b,
+		  FcBool	    (*overlap) (FcCharLeaf	    *result,
+						const FcCharLeaf    *al,
+						const FcCharLeaf    *bl),
+		  FcBool	aonly,
+		  FcBool	bonly)
+{
+    FcCharSet	    *fcs;
+    FcCharSetIter   ai, bi;
+
+    fcs = FcCharSetCreate ();
+    if (!fcs)
+	goto bail0;
+    FcCharSetIterStart (a, &ai);
+    FcCharSetIterStart (b, &bi);
+    while ((ai.leaf || bonly) && (bi.leaf || aonly))
+    {
+	if (ai.ucs4 < bi.ucs4)
+	{
+	    if (aonly)
+	    {
+		if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf))
+		    goto bail1;
+		FcCharSetIterNext (a, &ai);
+	    }
+	    else
+	    {
+		ai.ucs4 = bi.ucs4;
+		FcCharSetIterSet (a, &ai);
+	    }
+	}
+	else if (bi.ucs4 < ai.ucs4 )
+	{
+	    if (bonly)
+	    {
+		if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf))
+		    goto bail1;
+		FcCharSetIterNext (b, &bi);
+	    }
+	    else
+	    {
+		bi.ucs4 = ai.ucs4;
+		FcCharSetIterSet (b, &bi);
+	    }
+	}
+	else
+	{
+	    FcCharLeaf  leaf;
+
+	    if ((*overlap) (&leaf, ai.leaf, bi.leaf))
+	    {
+		if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf))
+		    goto bail1;
+	    }
+	    FcCharSetIterNext (a, &ai);
+	    FcCharSetIterNext (b, &bi);
+	}
+    }
+    return fcs;
+bail1:
+    FcCharSetDestroy (fcs);
+bail0:
+    return 0;
+}
+
+static FcBool
+FcCharSetIntersectLeaf (FcCharLeaf *result,
+			const FcCharLeaf *al,
+			const FcCharLeaf *bl)
+{
+    int	    i;
+    FcBool  nonempty = FcFalse;
+
+    for (i = 0; i < 256/32; i++)
+	if ((result->map[i] = al->map[i] & bl->map[i]))
+	    nonempty = FcTrue;
+    return nonempty;
+}
+
+FcCharSet *
+FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b)
+{
+    return FcCharSetOperate (a, b, FcCharSetIntersectLeaf, FcFalse, FcFalse);
+}
+
+static FcBool
+FcCharSetUnionLeaf (FcCharLeaf *result,
+		    const FcCharLeaf *al,
+		    const FcCharLeaf *bl)
+{
+    int	i;
+
+    for (i = 0; i < 256/32; i++)
+	result->map[i] = al->map[i] | bl->map[i];
+    return FcTrue;
+}
+
+FcCharSet *
+FcCharSetUnion (const FcCharSet *a, const FcCharSet *b)
+{
+    return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue, FcTrue);
+}
+
+static FcBool
+FcCharSetSubtractLeaf (FcCharLeaf *result,
+		       const FcCharLeaf *al,
+		       const FcCharLeaf *bl)
+{
+    int	    i;
+    FcBool  nonempty = FcFalse;
+
+    for (i = 0; i < 256/32; i++)
+	if ((result->map[i] = al->map[i] & ~bl->map[i]))
+	    nonempty = FcTrue;
+    return nonempty;
+}
+
+FcCharSet *
+FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b)
+{
+    return FcCharSetOperate (a, b, FcCharSetSubtractLeaf, FcTrue, FcFalse);
+}
+
+FcBool
+FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4)
+{
+    FcCharLeaf	*leaf = FcCharSetFindLeaf (fcs, ucs4);
+    if (!leaf)
+	return FcFalse;
+    return (leaf->map[(ucs4 & 0xff) >> 5] & (1 << (ucs4 & 0x1f))) != 0;
+}
+
+static FcChar32
+FcCharSetPopCount (FcChar32 c1)
+{
+    /* hackmem 169 */
+    FcChar32	c2 = (c1 >> 1) & 033333333333;
+    c2 = c1 - c2 - ((c2 >> 1) & 033333333333);
+    return (((c2 + (c2 >> 3)) & 030707070707) % 077);
+}
+
+FcChar32
+FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b)
+{
+    FcCharSetIter   ai, bi;
+    FcChar32	    count = 0;
+    
+    FcCharSetIterStart (a, &ai);
+    FcCharSetIterStart (b, &bi);
+    while (ai.leaf && bi.leaf)
+    {
+	if (ai.ucs4 == bi.ucs4)
+	{
+	    FcChar32	*am = ai.leaf->map;
+	    FcChar32	*bm = bi.leaf->map;
+	    int		i = 256/32;
+	    while (i--)
+		count += FcCharSetPopCount (*am++ & *bm++);
+	    FcCharSetIterNext (a, &ai);
+	} 
+	else if (ai.ucs4 < bi.ucs4)
+	{
+	    ai.ucs4 = bi.ucs4;
+	    FcCharSetIterSet (a, &ai);
+	}
+	if (bi.ucs4 < ai.ucs4)
+	{
+	    bi.ucs4 = ai.ucs4;
+	    FcCharSetIterSet (b, &bi);
+	}
+    }
+    return count;
+}
+
+FcChar32
+FcCharSetCount (const FcCharSet *a)
+{
+    FcCharSetIter   ai;
+    FcChar32	    count = 0;
+    
+    for (FcCharSetIterStart (a, &ai); ai.leaf; FcCharSetIterNext (a, &ai))
+    {
+	int		    i = 256/32;
+	FcChar32	    *am = ai.leaf->map;
+
+	while (i--)
+	    count += FcCharSetPopCount (*am++);
+    }
+    return count;
+}
+
+FcChar32
+FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
+{
+    FcCharSetIter   ai, bi;
+    FcChar32	    count = 0;
+    
+    FcCharSetIterStart (a, &ai);
+    FcCharSetIterStart (b, &bi);
+    while (ai.leaf)
+    {
+	if (ai.ucs4 <= bi.ucs4)
+	{
+	    FcChar32	*am = ai.leaf->map;
+	    int		i = 256/32;
+	    if (ai.ucs4 == bi.ucs4)
+	    {
+		FcChar32	*bm = bi.leaf->map;;
+		while (i--)
+		    count += FcCharSetPopCount (*am++ & ~*bm++);
+	    }
+	    else
+	    {
+		while (i--)
+		    count += FcCharSetPopCount (*am++);
+	    }
+	    FcCharSetIterNext (a, &ai);
+	}
+	else if (bi.leaf)
+	{
+	    bi.ucs4 = ai.ucs4;
+	    FcCharSetIterSet (b, &bi);
+	}
+    }
+    return count;
+}
+
+/*
+ * ASCII representation of charsets.
+ * 
+ * Each leaf is represented as 9 32-bit values, the code of the first character followed
+ * by 8 32 bit values for the leaf itself.  Each value is encoded as 5 ASCII characters,
+ * only 85 different values are used to avoid control characters as well as the other
+ * characters used to encode font names.  85**5 > 2^32 so things work out, but
+ * it's not exactly human readable output.  As a special case, 0 is encoded as a space
+ */
+
+static FcChar8	charToValue[256] = {
+    /*     "" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /*   "\b" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\020" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\030" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /*    " " */ 0xff,  0x00,  0xff,  0x01,  0x02,  0x03,  0x04,  0xff, 
+    /*    "(" */ 0x05,  0x06,  0x07,  0x08,  0xff,  0xff,  0x09,  0x0a, 
+    /*    "0" */ 0x0b,  0x0c,  0x0d,  0x0e,  0x0f,  0x10,  0x11,  0x12, 
+    /*    "8" */ 0x13,  0x14,  0xff,  0x15,  0x16,  0xff,  0x17,  0x18, 
+    /*    "@" */ 0x19,  0x1a,  0x1b,  0x1c,  0x1d,  0x1e,  0x1f,  0x20, 
+    /*    "H" */ 0x21,  0x22,  0x23,  0x24,  0x25,  0x26,  0x27,  0x28, 
+    /*    "P" */ 0x29,  0x2a,  0x2b,  0x2c,  0x2d,  0x2e,  0x2f,  0x30, 
+    /*    "X" */ 0x31,  0x32,  0x33,  0x34,  0xff,  0x35,  0x36,  0xff, 
+    /*    "`" */ 0xff,  0x37,  0x38,  0x39,  0x3a,  0x3b,  0x3c,  0x3d, 
+    /*    "h" */ 0x3e,  0x3f,  0x40,  0x41,  0x42,  0x43,  0x44,  0x45, 
+    /*    "p" */ 0x46,  0x47,  0x48,  0x49,  0x4a,  0x4b,  0x4c,  0x4d, 
+    /*    "x" */ 0x4e,  0x4f,  0x50,  0x51,  0x52,  0x53,  0x54,  0xff, 
+    /* "\200" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\210" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\220" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\230" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\240" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\250" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\260" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\270" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\300" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\310" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\320" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\330" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\340" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\350" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\360" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+    /* "\370" */ 0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff,  0xff, 
+};
+
+static FcChar8 valueToChar[0x55] = {
+    /* 0x00 */ '!', '#', '$', '%', '&', '(', ')', '*',
+    /* 0x08 */ '+', '.', '/', '0', '1', '2', '3', '4',
+    /* 0x10 */ '5', '6', '7', '8', '9', ';', '<', '>',
+    /* 0x18 */ '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
+    /* 0x20 */ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+    /* 0x28 */ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+    /* 0x30 */ 'W', 'X', 'Y', 'Z', '[', ']', '^', 'a',
+    /* 0x38 */ 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+    /* 0x40 */ 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
+    /* 0x48 */ 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+    /* 0x50 */ 'z', '{', '|', '}', '~',
+};
+
+static FcChar8 *
+FcCharSetParseValue (FcChar8 *string, FcChar32 *value)
+{
+    int		i;
+    FcChar32	v;
+    FcChar8	c;
+    
+    if (*string == ' ')
+    {
+	v = 0;
+	string++;
+    }
+    else
+    {
+	v = 0;
+	for (i = 0; i < 5; i++)
+	{
+	    if (!(c = *string++))
+		return 0;
+	    c = charToValue[c];
+	    if (c == 0xff)
+		return 0;
+	    v = v * 85 + c;
+	}
+    }
+    *value = v;
+    return string;
+}
+
+static FcBool
+FcCharSetUnparseValue (FcNameBuf *buf, FcChar32 value)
+{
+    int	    i;
+    if (value == 0)
+    {
+	return FcNameBufChar (buf, ' ');
+    }
+    else
+    {
+	FcChar8	string[6];
+	FcChar8	*s = string + 5;
+	string[5] = '\0';
+	for (i = 0; i < 5; i++)
+	{
+	    *--s = valueToChar[value % 85];
+	    value /= 85;
+	}
+	for (i = 0; i < 5; i++)
+	    if (!FcNameBufChar (buf, *s++))
+		return FcFalse;
+    }
+    return FcTrue;
+}
+
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string)
+{
+    FcCharSet	*c;
+    FcChar32	ucs4;
+    FcCharLeaf	*leaf;
+    int		i;
+
+    c = FcCharSetCreate ();
+    if (!c)
+	goto bail0;
+    while (*string)
+    {
+	string = FcCharSetParseValue (string, &ucs4);
+	if (!string)
+	    goto bail1;
+	leaf = FcCharSetFindLeafCreate (c, ucs4);
+	if (!leaf)
+	    goto bail1;
+	for (i = 0; i < 256/32; i++)
+	{
+	    string = FcCharSetParseValue (string, &leaf->map[i]);
+	    if (!string)
+		goto bail1;
+	}
+    }
+    return c;
+bail1:
+    FcCharSetDestroy (c);
+bail0:
+    return 0;
+}
+
+FcBool
+FcNameUnparseCharSet (FcNameBuf *buf, const FcCharSet *c)
+{
+    FcCharSetIter   ci;
+    int		    i;
+#ifdef CHECK
+    int		    len = buf->len;
+#endif
+
+    for (FcCharSetIterStart (c, &ci);
+	 ci.leaf;
+	 FcCharSetIterNext (c, &ci))
+    {
+	if (!FcCharSetUnparseValue (buf, ci.ucs4))
+	    return FcFalse;
+	for (i = 0; i < 256/32; i++)
+	    if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
+		return FcFalse;
+    }
+#ifdef CHECK
+    {
+	FcCharSet	*check;
+	FcChar32	missing;
+	FcCharSetIter	ci, checki;
+	
+	/* null terminate for parser */
+	FcNameBufChar (buf, '\0');
+	/* step back over null for life after test */
+	buf->len--;
+	check = FcNameParseCharSet (buf->buf + len);
+	FcCharSetIterStart (c, &ci);
+	FcCharSetIterStart (check, &checki);
+	while (ci.leaf || checki.leaf)
+	{
+	    if (ci.ucs4 < checki.ucs4)
+	    {
+		printf ("Missing leaf node at 0x%x\n", ci.ucs4);
+		FcCharSetIterNext (c, &ci);
+	    }
+	    else if (checki.ucs4 < ci.ucs4)
+	    {
+		printf ("Extra leaf node at 0x%x\n", checki.ucs4);
+		FcCharSetIterNext (check, &checki);
+	    }
+	    else
+	    {
+		int	    i = 256/32;
+		FcChar32    *cm = ci.leaf->map;
+		FcChar32    *checkm = checki.leaf->map;
+
+		for (i = 0; i < 256; i += 32)
+		{
+		    if (*cm != *checkm)
+			printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
+				ci.ucs4 + i, *cm, *checkm);
+		    cm++;
+		    checkm++;
+		}
+		FcCharSetIterNext (c, &ci);
+		FcCharSetIterNext (check, &checki);
+	    }
+	}
+	if ((missing = FcCharSetSubtractCount (c, check)))
+	    printf ("%d missing in reparsed result\n", missing);
+	if ((missing = FcCharSetSubtractCount (check, c)))
+	    printf ("%d extra in reparsed result\n", missing);
+	FcCharSetDestroy (check);
+    }
+#endif
+    
+    return FcTrue;
+}
+
+#include <freetype/freetype.h>
+#include <fontconfig/fcfreetype.h>
+
+/*
+ * Figure out whether the available freetype has FT_Get_Next_Char
+ */
+
+#if FREETYPE_MAJOR > 2
+# define HAS_NEXT_CHAR
+#else
+# if FREETYPE_MAJOR == 2
+#  if FREETYPE_MINOR > 0
+#   define HAS_NEXT_CHAR
+#  else
+#   if FREETYPE_MINOR == 0
+#    if FREETYPE_PATCH >= 8
+#     define HAS_NEXT_CHAR
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+/*
+ * For our purposes, this approximation is sufficient
+ */
+#ifndef HAS_NEXT_CHAR
+#define FT_Get_Next_Char(face, ucs4) ((ucs4) >= 0xffffff ? 0 : (ucs4) + 1)
+#warning "No FT_Get_Next_Char"
+#endif
+
+typedef struct _FcCharEnt {
+    FcChar16	bmp;
+    FcChar8	encode;
+} FcCharEnt;
+
+typedef struct _FcCharMap {
+    const FcCharEnt *ent;
+    int		    nent;
+} FcCharMap;
+
+typedef struct _FcFontDecode {
+    FT_Encoding	    encoding;
+    const FcCharMap *map;
+    FcChar32	    max;
+} FcFontDecode;
+
+static const FcCharMap AppleRoman;
+static const FcCharMap AdobeSymbol;
+    
+static const FcFontDecode fcFontDecoders[] = {
+    { ft_encoding_unicode,	0,		(1 << 21) - 1 },
+    { ft_encoding_symbol,	&AdobeSymbol,	(1 << 16) - 1 },
+    { ft_encoding_apple_roman,	&AppleRoman,	(1 << 16) - 1 },
+};
+
+#define NUM_DECODE  (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
+
+static FT_ULong
+FcFreeTypeMapChar (FcChar32 ucs4, const FcCharMap *map)
+{
+    int		low, high, mid;
+    FcChar16	bmp;
+
+    low = 0;
+    high = map->nent - 1;
+    if (ucs4 < map->ent[low].bmp || map->ent[high].bmp < ucs4)
+	return ~0;
+    while (high - low > 1)
+    {
+	mid = (high + low) >> 1;
+	bmp = map->ent[mid].bmp;
+	if (ucs4 == bmp)
+	    return (FT_ULong) map->ent[mid].encode;
+	if (ucs4 < bmp)
+	    high = mid;
+	else
+	    low = mid;
+    }
+    for (mid = low; mid <= high; mid++)
+    {
+	if (ucs4 == map->ent[mid].bmp)
+	    return (FT_ULong) map->ent[mid].encode;
+    }
+    return ~0;
+}
+
+/*
+ * Map a UCS4 glyph to a glyph index.  Use all available encoding
+ * tables to try and find one that works.  This information is expected
+ * to be cached by higher levels, so performance isn't critical
+ */
+
+FT_UInt
+FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
+{
+    int		    initial, offset, decode;
+    FT_UInt	    glyphindex;
+    FT_ULong	    charcode;
+
+    initial = 0;
+    /*
+     * Find the current encoding
+     */
+    if (face->charmap)
+    {
+	for (; initial < NUM_DECODE; initial++)
+	    if (fcFontDecoders[initial].encoding == face->charmap->encoding)
+		break;
+	if (initial == NUM_DECODE)
+	    initial = 0;
+    }
+    /*
+     * Check each encoding for the glyph, starting with the current one
+     */
+    for (offset = 0; offset < NUM_DECODE; offset++)
+    {
+	decode = (initial + offset) % NUM_DECODE;
+	if (!face->charmap || face->charmap->encoding != fcFontDecoders[decode].encoding)
+	    if (FT_Select_Charmap (face, fcFontDecoders[decode].encoding) != 0)
+		continue;
+	if (fcFontDecoders[decode].map)
+	{
+	    charcode = FcFreeTypeMapChar (ucs4, fcFontDecoders[decode].map);
+	    if (charcode == ~0)
+		continue;
+	}
+	else
+	    charcode = (FT_ULong) ucs4;
+	glyphindex = FT_Get_Char_Index (face, charcode);
+	if (glyphindex)
+	    return glyphindex;
+    }
+    return 0;
+}
+
+static FcBool
+FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, 
+		      FT_UInt glyph, FcBlanks *blanks)
+{
+    FT_Int	    load_flags = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+    FT_GlyphSlot    slot;
+    
+    /*
+     * When using scalable fonts, only report those glyphs
+     * which can be scaled; otherwise those fonts will
+     * only be available at some sizes, and never when
+     * transformed.  Avoid this by simply reporting bitmap-only
+     * glyphs as missing
+     */
+    if (face->face_flags & FT_FACE_FLAG_SCALABLE)
+	load_flags |= FT_LOAD_NO_BITMAP;
+    
+    if (FT_Load_Glyph (face, glyph, load_flags))
+	return FcFalse;
+    
+    slot = face->glyph;
+    if (!glyph)
+	return FcFalse;
+    
+    switch (slot->format) {
+    case ft_glyph_format_bitmap:
+	/*
+	 * Bitmaps are assumed to be reasonable; if
+	 * this proves to be a rash assumption, this
+	 * code can be easily modified
+	 */
+	return FcTrue;
+    case ft_glyph_format_outline:
+	/*
+	 * Glyphs with contours are always OK
+	 */
+	if (slot->outline.n_contours != 0)
+	    return FcTrue;
+	/*
+	 * Glyphs with no contours are only OK if
+	 * they're members of the Blanks set specified
+	 * in the configuration.  If blanks isn't set,
+	 * then allow any glyph to be blank
+	 */
+	if (!blanks || FcBlanksIsMember (blanks, ucs4))
+	    return FcTrue;
+	/* fall through ... */
+    default:
+    }
+    return FcFalse;
+}
+
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
+{
+    FcChar32	    page, off, max, ucs4;
+#ifdef CHECK
+    FcChar32	    font_max = 0;
+#endif
+    FcCharSet	    *fcs;
+    FcCharLeaf	    *leaf;
+    const FcCharMap *map;
+    int		    o;
+    int		    i;
+    FT_UInt	    glyph;
+
+    fcs = FcCharSetCreate ();
+    if (!fcs)
+	goto bail0;
+    
+    for (o = 0; o < NUM_DECODE; o++)
+    {
+	if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0)
+	    continue;
+	map = fcFontDecoders[o].map;
+	if (map)
+	{
+	    /*
+	     * Non-Unicode tables are easy; there's a list of all possible
+	     * characters
+	     */
+	    for (i = 0; i < map->nent; i++)
+	    {
+		ucs4 = map->ent[i].bmp;
+		glyph = FT_Get_Char_Index (face, map->ent[i].encode);
+		if (glyph && FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks))
+		{
+		    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+		    if (!leaf)
+			goto bail1;
+		    leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
+#ifdef CHECK
+		    if (ucs4 > font_max)
+			font_max = ucs4;
+#endif
+		}
+	    }
+	}
+	else
+	{
+	    max = fcFontDecoders[o].max;
+	  
+	    /*
+	     * Find the first encoded character in the font
+	     */
+	    ucs4 = 0;
+	    if (FT_Get_Char_Index (face, 0))
+		ucs4 = 0;
+	    else
+		ucs4 = FT_Get_Next_Char (face, 0);
+
+	    for (;;)
+	    {
+		page = ucs4 >> 8;
+		leaf = 0;
+		while ((ucs4 >> 8) == page)
+		{
+		    glyph = FT_Get_Char_Index (face, ucs4);
+		    if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
+						       glyph, blanks))
+		    {
+			if (!leaf)
+			{
+			    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+			    if (!leaf)
+				goto bail1;
+			}
+			off = ucs4 & 0xff;
+			leaf->map[off >> 5] |= (1 << (off & 0x1f));
+#ifdef CHECK
+			if (ucs4 > font_max)
+			    font_max = ucs4;
+#endif
+		    }
+		    ucs4++;
+		}
+		ucs4 = FT_Get_Next_Char (face, ucs4 - 1);
+		if (!ucs4)
+		    break;
+	    }
+#ifdef CHECK
+	    for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
+	    {
+		FcBool	    FT_Has, FC_Has;
+
+		FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
+		FC_Has = FcCharSetHasChar (fcs, ucs4);
+		if (FT_Has != FC_Has)
+		{
+		    printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
+		}
+	    }
+#endif
+	}
+    }
+#ifdef CHECK
+    printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
+    for (ucs4 = 0; ucs4 <= font_max; ucs4++)
+    {
+	FcBool	has_char = FcFreeTypeCharIndex (face, ucs4) != 0;
+	FcBool	has_bit = FcCharSetHasChar (fcs, ucs4);
+
+	if (has_char && !has_bit)
+	    printf ("Bitmap missing char 0x%x\n", ucs4);
+	else if (!has_char && has_bit)
+	    printf ("Bitmap extra char 0x%x\n", ucs4);
+    }
+#endif
+    return fcs;
+bail1:
+    FcCharSetDestroy (fcs);
+bail0:
+    return 0;
+}
+
+static const FcCharEnt AppleRomanEnt[] = {
+    { 0x0020, 0x20 }, /* SPACE */
+    { 0x0021, 0x21 }, /* EXCLAMATION MARK */
+    { 0x0022, 0x22 }, /* QUOTATION MARK */
+    { 0x0023, 0x23 }, /* NUMBER SIGN */
+    { 0x0024, 0x24 }, /* DOLLAR SIGN */
+    { 0x0025, 0x25 }, /* PERCENT SIGN */
+    { 0x0026, 0x26 }, /* AMPERSAND */
+    { 0x0027, 0x27 }, /* APOSTROPHE */
+    { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
+    { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
+    { 0x002A, 0x2A }, /* ASTERISK */
+    { 0x002B, 0x2B }, /* PLUS SIGN */
+    { 0x002C, 0x2C }, /* COMMA */
+    { 0x002D, 0x2D }, /* HYPHEN-MINUS */
+    { 0x002E, 0x2E }, /* FULL STOP */
+    { 0x002F, 0x2F }, /* SOLIDUS */
+    { 0x0030, 0x30 }, /* DIGIT ZERO */
+    { 0x0031, 0x31 }, /* DIGIT ONE */
+    { 0x0032, 0x32 }, /* DIGIT TWO */
+    { 0x0033, 0x33 }, /* DIGIT THREE */
+    { 0x0034, 0x34 }, /* DIGIT FOUR */
+    { 0x0035, 0x35 }, /* DIGIT FIVE */
+    { 0x0036, 0x36 }, /* DIGIT SIX */
+    { 0x0037, 0x37 }, /* DIGIT SEVEN */
+    { 0x0038, 0x38 }, /* DIGIT EIGHT */
+    { 0x0039, 0x39 }, /* DIGIT NINE */
+    { 0x003A, 0x3A }, /* COLON */
+    { 0x003B, 0x3B }, /* SEMICOLON */
+    { 0x003C, 0x3C }, /* LESS-THAN SIGN */
+    { 0x003D, 0x3D }, /* EQUALS SIGN */
+    { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
+    { 0x003F, 0x3F }, /* QUESTION MARK */
+    { 0x0040, 0x40 }, /* COMMERCIAL AT */
+    { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
+    { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
+    { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
+    { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
+    { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
+    { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
+    { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
+    { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
+    { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
+    { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
+    { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
+    { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
+    { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
+    { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
+    { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
+    { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
+    { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
+    { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
+    { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
+    { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
+    { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
+    { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
+    { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
+    { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
+    { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
+    { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
+    { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
+    { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
+    { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
+    { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
+    { 0x005F, 0x5F }, /* LOW LINE */
+    { 0x0060, 0x60 }, /* GRAVE ACCENT */
+    { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
+    { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
+    { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
+    { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
+    { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
+    { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
+    { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
+    { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
+    { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
+    { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
+    { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
+    { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
+    { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
+    { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
+    { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
+    { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
+    { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
+    { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
+    { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
+    { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
+    { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
+    { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
+    { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
+    { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
+    { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
+    { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
+    { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
+    { 0x007C, 0x7C }, /* VERTICAL LINE */
+    { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
+    { 0x007E, 0x7E }, /* TILDE */
+    { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
+    { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
+    { 0x00A2, 0xA2 }, /* CENT SIGN */
+    { 0x00A3, 0xA3 }, /* POUND SIGN */
+    { 0x00A5, 0xB4 }, /* YEN SIGN */
+    { 0x00A7, 0xA4 }, /* SECTION SIGN */
+    { 0x00A8, 0xAC }, /* DIAERESIS */
+    { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
+    { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
+    { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+    { 0x00AC, 0xC2 }, /* NOT SIGN */
+    { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
+    { 0x00AF, 0xF8 }, /* MACRON */
+    { 0x00B0, 0xA1 }, /* DEGREE SIGN */
+    { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
+    { 0x00B4, 0xAB }, /* ACUTE ACCENT */
+    { 0x00B5, 0xB5 }, /* MICRO SIGN */
+    { 0x00B6, 0xA6 }, /* PILCROW SIGN */
+    { 0x00B7, 0xE1 }, /* MIDDLE DOT */
+    { 0x00B8, 0xFC }, /* CEDILLA */
+    { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
+    { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+    { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
+    { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
+    { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
+    { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+    { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
+    { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
+    { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
+    { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
+    { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
+    { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
+    { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
+    { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+    { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
+    { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
+    { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
+    { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+    { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
+    { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
+    { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
+    { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
+    { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+    { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
+    { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
+    { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
+    { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
+    { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
+    { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+    { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
+    { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
+    { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
+    { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
+    { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+    { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
+    { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
+    { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
+    { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
+    { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
+    { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
+    { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
+    { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+    { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
+    { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
+    { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
+    { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+    { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
+    { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
+    { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
+    { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
+    { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+    { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
+    { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
+    { 0x00F7, 0xD6 }, /* DIVISION SIGN */
+    { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
+    { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
+    { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
+    { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+    { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
+    { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
+    { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
+    { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
+    { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
+    { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+    { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
+    { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+    { 0x02C7, 0xFF }, /* CARON */
+    { 0x02D8, 0xF9 }, /* BREVE */
+    { 0x02D9, 0xFA }, /* DOT ABOVE */
+    { 0x02DA, 0xFB }, /* RING ABOVE */
+    { 0x02DB, 0xFE }, /* OGONEK */
+    { 0x02DC, 0xF7 }, /* SMALL TILDE */
+    { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
+    { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
+    { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
+    { 0x2013, 0xD0 }, /* EN DASH */
+    { 0x2014, 0xD1 }, /* EM DASH */
+    { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
+    { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
+    { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
+    { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
+    { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
+    { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
+    { 0x2020, 0xA0 }, /* DAGGER */
+    { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
+    { 0x2022, 0xA5 }, /* BULLET */
+    { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
+    { 0x2030, 0xE4 }, /* PER MILLE SIGN */
+    { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+    { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+    { 0x2044, 0xDA }, /* FRACTION SLASH */
+    { 0x20AC, 0xDB }, /* EURO SIGN */
+    { 0x2122, 0xAA }, /* TRADE MARK SIGN */
+    { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
+    { 0x2206, 0xC6 }, /* INCREMENT */
+    { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
+    { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
+    { 0x221A, 0xC3 }, /* SQUARE ROOT */
+    { 0x221E, 0xB0 }, /* INFINITY */
+    { 0x222B, 0xBA }, /* INTEGRAL */
+    { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
+    { 0x2260, 0xAD }, /* NOT EQUAL TO */
+    { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
+    { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
+    { 0x25CA, 0xD7 }, /* LOZENGE */
+    { 0xF8FF, 0xF0 }, /* Apple logo */
+    { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
+    { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
+};
+
+static const FcCharMap AppleRoman = {
+    AppleRomanEnt,
+    sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
+};
+
+static const FcCharEnt AdobeSymbolEnt[] = {
+    { 0x0020, 0x20 }, /* SPACE	# space */
+    { 0x0021, 0x21 }, /* EXCLAMATION MARK	# exclam */
+    { 0x0023, 0x23 }, /* NUMBER SIGN	# numbersign */
+    { 0x0025, 0x25 }, /* PERCENT SIGN	# percent */
+    { 0x0026, 0x26 }, /* AMPERSAND	# ampersand */
+    { 0x0028, 0x28 }, /* LEFT PARENTHESIS	# parenleft */
+    { 0x0029, 0x29 }, /* RIGHT PARENTHESIS	# parenright */
+    { 0x002B, 0x2B }, /* PLUS SIGN	# plus */
+    { 0x002C, 0x2C }, /* COMMA	# comma */
+    { 0x002E, 0x2E }, /* FULL STOP	# period */
+    { 0x002F, 0x2F }, /* SOLIDUS	# slash */
+    { 0x0030, 0x30 }, /* DIGIT ZERO	# zero */
+    { 0x0031, 0x31 }, /* DIGIT ONE	# one */
+    { 0x0032, 0x32 }, /* DIGIT TWO	# two */
+    { 0x0033, 0x33 }, /* DIGIT THREE	# three */
+    { 0x0034, 0x34 }, /* DIGIT FOUR	# four */
+    { 0x0035, 0x35 }, /* DIGIT FIVE	# five */
+    { 0x0036, 0x36 }, /* DIGIT SIX	# six */
+    { 0x0037, 0x37 }, /* DIGIT SEVEN	# seven */
+    { 0x0038, 0x38 }, /* DIGIT EIGHT	# eight */
+    { 0x0039, 0x39 }, /* DIGIT NINE	# nine */
+    { 0x003A, 0x3A }, /* COLON	# colon */
+    { 0x003B, 0x3B }, /* SEMICOLON	# semicolon */
+    { 0x003C, 0x3C }, /* LESS-THAN SIGN	# less */
+    { 0x003D, 0x3D }, /* EQUALS SIGN	# equal */
+    { 0x003E, 0x3E }, /* GREATER-THAN SIGN	# greater */
+    { 0x003F, 0x3F }, /* QUESTION MARK	# question */
+    { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET	# bracketleft */
+    { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET	# bracketright */
+    { 0x005F, 0x5F }, /* LOW LINE	# underscore */
+    { 0x007B, 0x7B }, /* LEFT CURLY BRACKET	# braceleft */
+    { 0x007C, 0x7C }, /* VERTICAL LINE	# bar */
+    { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET	# braceright */
+    { 0x00A0, 0x20 }, /* NO-BREAK SPACE	# space */
+    { 0x00AC, 0xD8 }, /* NOT SIGN	# logicalnot */
+    { 0x00B0, 0xB0 }, /* DEGREE SIGN	# degree */
+    { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN	# plusminus */
+    { 0x00B5, 0x6D }, /* MICRO SIGN	# mu */
+    { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN	# multiply */
+    { 0x00F7, 0xB8 }, /* DIVISION SIGN	# divide */
+    { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK	# florin */
+    { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA	# Alpha */
+    { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA	# Beta */
+    { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA	# Gamma */
+    { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA	# Delta */
+    { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON	# Epsilon */
+    { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA	# Zeta */
+    { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA	# Eta */
+    { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA	# Theta */
+    { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA	# Iota */
+    { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA	# Kappa */
+    { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA	# Lambda */
+    { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU	# Mu */
+    { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU	# Nu */
+    { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI	# Xi */
+    { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON	# Omicron */
+    { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI	# Pi */
+    { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO	# Rho */
+    { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA	# Sigma */
+    { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU	# Tau */
+    { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON	# Upsilon */
+    { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI	# Phi */
+    { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI	# Chi */
+    { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI	# Psi */
+    { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA	# Omega */
+    { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA	# alpha */
+    { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA	# beta */
+    { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA	# gamma */
+    { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA	# delta */
+    { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON	# epsilon */
+    { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA	# zeta */
+    { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA	# eta */
+    { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA	# theta */
+    { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA	# iota */
+    { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA	# kappa */
+    { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA	# lambda */
+    { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU	# mu */
+    { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU	# nu */
+    { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI	# xi */
+    { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON	# omicron */
+    { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI	# pi */
+    { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO	# rho */
+    { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA	# sigma1 */
+    { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA	# sigma */
+    { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU	# tau */
+    { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON	# upsilon */
+    { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI	# phi */
+    { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI	# chi */
+    { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI	# psi */
+    { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA	# omega */
+    { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL	# theta1 */
+    { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL	# Upsilon1 */
+    { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL	# phi1 */
+    { 0x03D6, 0x76 }, /* GREEK PI SYMBOL	# omega1 */
+    { 0x2022, 0xB7 }, /* BULLET	# bullet */
+    { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS	# ellipsis */
+    { 0x2032, 0xA2 }, /* PRIME	# minute */
+    { 0x2033, 0xB2 }, /* DOUBLE PRIME	# second */
+    { 0x2044, 0xA4 }, /* FRACTION SLASH	# fraction */
+    { 0x20AC, 0xA0 }, /* EURO SIGN	# Euro */
+    { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I	# Ifraktur */
+    { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P	# weierstrass */
+    { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R	# Rfraktur */
+    { 0x2126, 0x57 }, /* OHM SIGN	# Omega */
+    { 0x2135, 0xC0 }, /* ALEF SYMBOL	# aleph */
+    { 0x2190, 0xAC }, /* LEFTWARDS ARROW	# arrowleft */
+    { 0x2191, 0xAD }, /* UPWARDS ARROW	# arrowup */
+    { 0x2192, 0xAE }, /* RIGHTWARDS ARROW	# arrowright */
+    { 0x2193, 0xAF }, /* DOWNWARDS ARROW	# arrowdown */
+    { 0x2194, 0xAB }, /* LEFT RIGHT ARROW	# arrowboth */
+    { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS	# carriagereturn */
+    { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW	# arrowdblleft */
+    { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW	# arrowdblup */
+    { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW	# arrowdblright */
+    { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW	# arrowdbldown */
+    { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW	# arrowdblboth */
+    { 0x2200, 0x22 }, /* FOR ALL	# universal */
+    { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL	# partialdiff */
+    { 0x2203, 0x24 }, /* THERE EXISTS	# existential */
+    { 0x2205, 0xC6 }, /* EMPTY SET	# emptyset */
+    { 0x2206, 0x44 }, /* INCREMENT	# Delta */
+    { 0x2207, 0xD1 }, /* NABLA	# gradient */
+    { 0x2208, 0xCE }, /* ELEMENT OF	# element */
+    { 0x2209, 0xCF }, /* NOT AN ELEMENT OF	# notelement */
+    { 0x220B, 0x27 }, /* CONTAINS AS MEMBER	# suchthat */
+    { 0x220F, 0xD5 }, /* N-ARY PRODUCT	# product */
+    { 0x2211, 0xE5 }, /* N-ARY SUMMATION	# summation */
+    { 0x2212, 0x2D }, /* MINUS SIGN	# minus */
+    { 0x2215, 0xA4 }, /* DIVISION SLASH	# fraction */
+    { 0x2217, 0x2A }, /* ASTERISK OPERATOR	# asteriskmath */
+    { 0x221A, 0xD6 }, /* SQUARE ROOT	# radical */
+    { 0x221D, 0xB5 }, /* PROPORTIONAL TO	# proportional */
+    { 0x221E, 0xA5 }, /* INFINITY	# infinity */
+    { 0x2220, 0xD0 }, /* ANGLE	# angle */
+    { 0x2227, 0xD9 }, /* LOGICAL AND	# logicaland */
+    { 0x2228, 0xDA }, /* LOGICAL OR	# logicalor */
+    { 0x2229, 0xC7 }, /* INTERSECTION	# intersection */
+    { 0x222A, 0xC8 }, /* UNION	# union */
+    { 0x222B, 0xF2 }, /* INTEGRAL	# integral */
+    { 0x2234, 0x5C }, /* THEREFORE	# therefore */
+    { 0x223C, 0x7E }, /* TILDE OPERATOR	# similar */
+    { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO	# congruent */
+    { 0x2248, 0xBB }, /* ALMOST EQUAL TO	# approxequal */
+    { 0x2260, 0xB9 }, /* NOT EQUAL TO	# notequal */
+    { 0x2261, 0xBA }, /* IDENTICAL TO	# equivalence */
+    { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO	# lessequal */
+    { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO	# greaterequal */
+    { 0x2282, 0xCC }, /* SUBSET OF	# propersubset */
+    { 0x2283, 0xC9 }, /* SUPERSET OF	# propersuperset */
+    { 0x2284, 0xCB }, /* NOT A SUBSET OF	# notsubset */
+    { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO	# reflexsubset */
+    { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO	# reflexsuperset */
+    { 0x2295, 0xC5 }, /* CIRCLED PLUS	# circleplus */
+    { 0x2297, 0xC4 }, /* CIRCLED TIMES	# circlemultiply */
+    { 0x22A5, 0x5E }, /* UP TACK	# perpendicular */
+    { 0x22C5, 0xD7 }, /* DOT OPERATOR	# dotmath */
+    { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL	# integraltp */
+    { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL	# integralbt */
+    { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET	# angleleft */
+    { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET	# angleright */
+    { 0x25CA, 0xE0 }, /* LOZENGE	# lozenge */
+    { 0x2660, 0xAA }, /* BLACK SPADE SUIT	# spade */
+    { 0x2663, 0xA7 }, /* BLACK CLUB SUIT	# club */
+    { 0x2665, 0xA9 }, /* BLACK HEART SUIT	# heart */
+    { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT	# diamond */
+    { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF	# copyrightserif (CUS) */
+    { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF	# registerserif (CUS) */
+    { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF	# trademarkserif (CUS) */
+    { 0xF8E5, 0x60 }, /* RADICAL EXTENDER	# radicalex (CUS) */
+    { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER	# arrowvertex (CUS) */
+    { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER	# arrowhorizex (CUS) */
+    { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF	# registersans (CUS) */
+    { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF	# copyrightsans (CUS) */
+    { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF	# trademarksans (CUS) */
+    { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP	# parenlefttp (CUS) */
+    { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER	# parenleftex (CUS) */
+    { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM	# parenleftbt (CUS) */
+    { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP	# bracketlefttp (CUS) */
+    { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER	# bracketleftex (CUS) */
+    { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM	# bracketleftbt (CUS) */
+    { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP	# bracelefttp (CUS) */
+    { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID	# braceleftmid (CUS) */
+    { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM	# braceleftbt (CUS) */
+    { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER	# braceex (CUS) */
+    { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER	# integralex (CUS) */
+    { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP	# parenrighttp (CUS) */
+    { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER	# parenrightex (CUS) */
+    { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM	# parenrightbt (CUS) */
+    { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP	# bracketrighttp (CUS) */
+    { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER	# bracketrightex (CUS) */
+    { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM	# bracketrightbt (CUS) */
+    { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP	# bracerighttp (CUS) */
+    { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID	# bracerightmid (CUS) */
+    { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM	# bracerightbt (CUS) */
+};
+
+static const FcCharMap AdobeSymbol = {
+    AdobeSymbolEnt,
+    sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
+};
diff --git a/src/fcdbg.c b/src/fcdbg.c
new file mode 100644
index 0000000..78af630
--- /dev/null
+++ b/src/fcdbg.c
@@ -0,0 +1,272 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdio.h>
+#include <stdlib.h>
+#include "fcint.h"
+
+void
+FcValuePrint (FcValue v)
+{
+    switch (v.type) {
+    case FcTypeVoid:
+	printf (" <void>");
+	break;
+    case FcTypeInteger:
+	printf (" %d", v.u.i);
+	break;
+    case FcTypeDouble:
+	printf (" %g", v.u.d);
+	break;
+    case FcTypeString:
+	printf (" \"%s\"", v.u.s);
+	break;
+    case FcTypeBool:
+	printf (" %s", v.u.b ? "FcTrue" : "FcFalse");
+	break;
+    case FcTypeMatrix:
+	printf (" (%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
+	break;
+    case FcTypeCharSet:	/* XXX */
+	printf (" set");
+	break;
+    }
+}
+
+void
+FcValueListPrint (FcValueList *l)
+{
+    for (; l; l = l->next)
+	FcValuePrint (l->value);
+}
+
+void
+FcPatternPrint (FcPattern *p)
+{
+    int		    i;
+    FcPatternElt   *e;
+    
+    if (!p)
+    {
+	printf ("Null pattern\n");
+	return;
+    }
+    printf ("Pattern %d of %d\n", p->num, p->size);
+    for (i = 0; i < p->num; i++)
+    {
+	e = &p->elts[i];
+	printf ("\t%s:", e->object);
+	FcValueListPrint (e->values);
+	printf ("\n");
+    }
+    printf ("\n");
+}
+
+void
+FcOpPrint (FcOp op)
+{
+    switch (op) {
+    case FcOpInteger: printf ("Integer"); break;
+    case FcOpDouble: printf ("Double"); break;
+    case FcOpString: printf ("String"); break;
+    case FcOpMatrix: printf ("Matrix"); break;
+    case FcOpBool: printf ("Bool"); break;
+    case FcOpCharSet: printf ("CharSet"); break;
+    case FcOpField: printf ("Field"); break;
+    case FcOpConst: printf ("Const"); break;
+    case FcOpAssign: printf ("Assign"); break;
+    case FcOpAssignReplace: printf ("AssignReplace"); break;
+    case FcOpPrepend: printf ("Prepend"); break;
+    case FcOpPrependFirst: printf ("PrependFirst"); break;
+    case FcOpAppend: printf ("Append"); break;
+    case FcOpAppendLast: printf ("AppendLast"); break;
+    case FcOpQuest: printf ("Quest"); break;
+    case FcOpOr: printf ("Or"); break;
+    case FcOpAnd: printf ("And"); break;
+    case FcOpEqual: printf ("Equal"); break;
+    case FcOpContains: printf ("Contains"); break;
+    case FcOpNotEqual: printf ("NotEqual"); break;
+    case FcOpLess: printf ("Less"); break;
+    case FcOpLessEqual: printf ("LessEqual"); break;
+    case FcOpMore: printf ("More"); break;
+    case FcOpMoreEqual: printf ("MoreEqual"); break;
+    case FcOpPlus: printf ("Plus"); break;
+    case FcOpMinus: printf ("Minus"); break;
+    case FcOpTimes: printf ("Times"); break;
+    case FcOpDivide: printf ("Divide"); break;
+    case FcOpNot: printf ("Not"); break;
+    case FcOpNil: printf ("Nil"); break;
+    case FcOpComma: printf ("Comma"); break;
+    case FcOpInvalid: printf ("Invalid"); break;
+    }
+}
+
+void
+FcExprPrint (FcExpr *expr)
+{
+    switch (expr->op) {
+    case FcOpInteger: printf ("%d", expr->u.ival); break;
+    case FcOpDouble: printf ("%g", expr->u.dval); break;
+    case FcOpString: printf ("\"%s\"", expr->u.sval); break;
+    case FcOpMatrix: printf ("[%g %g %g %g]",
+			      expr->u.mval->xx,
+			      expr->u.mval->xy,
+			      expr->u.mval->yx,
+			      expr->u.mval->yy);
+    case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break;
+    case FcOpField: printf ("%s", expr->u.field); break;
+    case FcOpQuest:
+	FcExprPrint (expr->u.tree.left);
+	printf (" quest ");
+	FcExprPrint (expr->u.tree.right->u.tree.left);
+	printf (" colon ");
+	FcExprPrint (expr->u.tree.right->u.tree.right);
+	break;
+    case FcOpOr:
+    case FcOpAnd:
+    case FcOpEqual:
+    case FcOpContains:
+    case FcOpNotEqual:
+    case FcOpLess:
+    case FcOpLessEqual:
+    case FcOpMore:
+    case FcOpMoreEqual:
+    case FcOpPlus:
+    case FcOpMinus:
+    case FcOpTimes:
+    case FcOpDivide:
+	FcExprPrint (expr->u.tree.left);
+	printf (" ");
+	switch (expr->op) {
+	case FcOpOr: printf ("Or"); break;
+	case FcOpAnd: printf ("And"); break;
+	case FcOpEqual: printf ("Equal"); break;
+	case FcOpContains: printf ("Contains"); break;
+	case FcOpNotEqual: printf ("NotEqual"); break;
+	case FcOpLess: printf ("Less"); break;
+	case FcOpLessEqual: printf ("LessEqual"); break;
+	case FcOpMore: printf ("More"); break;
+	case FcOpMoreEqual: printf ("MoreEqual"); break;
+	case FcOpPlus: printf ("Plus"); break;
+	case FcOpMinus: printf ("Minus"); break;
+	case FcOpTimes: printf ("Times"); break;
+	case FcOpDivide: printf ("Divide"); break;
+	default: break;
+	}
+	printf (" ");
+	FcExprPrint (expr->u.tree.right);
+	break;
+    case FcOpNot:
+	printf ("Not ");
+	FcExprPrint (expr->u.tree.left);
+	break;
+    default:
+	break;
+    }
+}
+
+void
+FcTestPrint (FcTest *test)
+{
+    switch (test->qual) {
+    case FcQualAny:
+	printf ("any ");
+	break;
+    case FcQualAll:
+	printf ("all ");
+	break;
+    }
+    printf ("%s ", test->field);
+    FcOpPrint (test->op);
+    printf (" ");
+    FcExprPrint (test->expr);
+    printf ("\n");
+}
+
+void
+FcEditPrint (FcEdit *edit)
+{
+    printf ("Edit %s ", edit->field);
+    FcOpPrint (edit->op);
+    printf (" ");
+    FcExprPrint (edit->expr);
+}
+
+void
+FcSubstPrint (FcSubst *subst)
+{
+    FcEdit	*e;
+    FcTest	*t;
+    
+    printf ("match\n");
+    for (t = subst->test; t; t = t->next)
+    {
+	printf ("\t");
+	FcTestPrint (t);
+    }
+    printf ("edit\n");
+    for (e = subst->edit; e; e = e->next)
+    {
+	printf ("\t");
+	FcEditPrint (e);
+	printf (";\n");
+    }
+    printf ("\n");
+}
+
+void
+FcFontSetPrint (FcFontSet *s)
+{
+    int	    i;
+
+    printf ("FontSet %d of %d\n", s->nfont, s->sfont);
+    for (i = 0; i < s->nfont; i++)
+    {
+	printf ("Font %d ", i);
+	FcPatternPrint (s->fonts[i]);
+    }
+}
+
+int
+FcDebug (void)
+{
+    static int  initialized;
+    static int  debug;
+
+    if (!initialized)
+    {
+	char    *e;
+
+	initialized = 1;
+	e = getenv ("FC_DEBUG");
+	if (e)
+	{
+	    printf ("FC_DEBUG=%s\n", e);
+	    debug = atoi (e);
+	    if (debug < 0)
+		debug = 0;
+	}
+    }
+    return debug;
+}
diff --git a/src/fcdefault.c b/src/fcdefault.c
new file mode 100644
index 0000000..365595d
--- /dev/null
+++ b/src/fcdefault.c
@@ -0,0 +1,87 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 "fcint.h"
+
+static struct {
+    char	*field;
+    FcBool	value;
+} FcBoolDefaults[] = {
+    { FC_HINTING,	    FcTrue	},  /* !FT_LOAD_NO_HINTING */
+    { FC_VERTICAL_LAYOUT,   FcFalse	},  /* FC_LOAD_VERTICAL_LAYOUT */
+    { FC_AUTOHINT,	    FcFalse	},  /* FC_LOAD_FORCE_AUTOHINT */
+    { FC_GLOBAL_ADVANCE,    FcTrue	},  /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
+};
+
+#define NUM_FC_BOOL_DEFAULTS	(sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
+
+void
+FcDefaultSubstitute (FcPattern *pattern)
+{
+    FcValue v;
+    int	    i;
+
+    if (FcPatternGet (pattern, FC_STYLE, 0, &v) == FcResultNoMatch)
+    {
+	if (FcPatternGet (pattern, FC_WEIGHT, 0, &v) == FcResultNoMatch )
+	{
+	    FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_MEDIUM);
+	}
+	if (FcPatternGet (pattern, FC_SLANT, 0, &v) == FcResultNoMatch)
+	{
+	    FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
+	}
+    }
+
+    for (i = 0; i < NUM_FC_BOOL_DEFAULTS; i++)
+	if (FcPatternGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch)
+	    FcPatternAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value);
+    
+    if (FcPatternGet (pattern, FC_PIXEL_SIZE, 0, &v) == FcResultNoMatch)
+    {
+	double	dpi, size, scale;
+
+	if (FcPatternGetDouble (pattern, FC_SIZE, 0, &size) != FcResultMatch)
+	{
+	    size = 12.0;
+	    (void) FcPatternDel (pattern, FC_SIZE);
+	    FcPatternAddDouble (pattern, FC_SIZE, size);
+	}
+	if (FcPatternGetDouble (pattern, FC_SCALE, 0, &scale) != FcResultMatch)
+	{
+	    scale = 1.0;
+	    (void) FcPatternDel (pattern, FC_SCALE);
+	    FcPatternAddDouble (pattern, FC_SCALE, scale);
+	}
+	size *= scale;
+	if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) != FcResultMatch)
+	{
+	    dpi = 75.0;
+	    (void) FcPatternDel (pattern, FC_DPI);
+	    FcPatternAddDouble (pattern, FC_DPI, dpi);
+	}
+	size *= dpi / 72.0;
+	FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
+    }
+}
diff --git a/src/fcdir.c b/src/fcdir.c
new file mode 100644
index 0000000..a49cb54
--- /dev/null
+++ b/src/fcdir.c
@@ -0,0 +1,178 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include "fcint.h"
+
+#define FC_INVALID_FONT_FILE "."
+
+FcBool
+FcFileScan (FcFontSet	*set,
+	    FcFileCache	*cache,
+	    FcBlanks	*blanks,
+	    const char	*file,
+	    FcBool	force)
+{
+    int		    id;
+    char	    *name;
+    FcPattern	    *font;
+    FcBool	    ret = FcTrue;
+    int		    count;
+    
+    id = 0;
+    do
+    {
+	if (!force && cache)
+	    name = FcFileCacheFind (cache, file, id, &count);
+	else
+	    name = 0;
+	if (name)
+	{
+	    /* "." means the file doesn't contain a font */
+	    if (strcmp (name, FC_INVALID_FONT_FILE) != 0)
+	    {
+		font = FcNameParse (name);
+		if (font)
+		    FcPatternAddString (font, FC_FILE, file);
+	    }
+	    else
+		font = 0;
+	}
+	else
+	{
+	    if (FcDebug () & FC_DBG_SCAN)
+	    {
+		printf ("\tScanning file %s...", file);
+		fflush (stdout);
+	    }
+	    font = FcFreeTypeQuery (file, id, blanks, &count);
+	    if (FcDebug () & FC_DBG_SCAN)
+		printf ("done\n");
+	    if (!force && cache)
+	    {
+		if (font)
+		{
+		    FcChar8	*unparse;
+
+		    unparse = FcNameUnparse (font);
+		    if (unparse)
+		    {
+			(void) FcFileCacheUpdate (cache, file, id, unparse);
+			free (unparse);
+		    }
+		}
+		else
+		{
+		    /* negative cache files not containing fonts */
+		    FcFileCacheUpdate (cache, file, id, FC_INVALID_FONT_FILE);
+		}
+	    }
+	}
+	if (font)
+	{
+	    if (!FcFontSetAdd (set, font))
+	    {
+		FcPatternDestroy (font);
+		font = 0;
+		ret = FcFalse;
+	    }
+	}
+	id++;
+    } while (font && ret && id < count);
+    return ret;
+}
+
+FcBool
+FcDirScan (FcFontSet	*set,
+	   FcFileCache	*cache,
+	   FcBlanks	*blanks,
+	   const char	*dir,
+	   FcBool	force)
+{
+    DIR		    *d;
+    struct dirent   *e;
+    char	    *file;
+    char	    *base;
+    FcBool	    ret = FcTrue;
+
+    file = (char *) malloc (strlen (dir) + 1 + 256 + 1);
+    if (!file)
+	return FcFalse;
+
+    strcpy (file, dir);
+    strcat (file, "/");
+    base = file + strlen (file);
+    if (!force)
+    {
+	strcpy (base, FC_DIR_CACHE_FILE);
+	
+	if (FcFileCacheReadDir (set, file))
+	{
+	    free (file);
+	    return FcTrue;
+	}
+    }
+    
+    d = opendir (dir);
+    if (!d)
+    {
+	free (file);
+	return FcFalse;
+    }
+    while (ret && (e = readdir (d)))
+    {
+	if (e->d_name[0] != '.')
+	{
+	    strcpy (base, e->d_name);
+	    FcFileScan (set, cache, blanks, file, force);
+	}
+    }
+    free (file);
+    closedir (d);
+    return ret;
+}
+
+FcBool
+FcDirSave (FcFontSet *set, const char *dir)
+{
+    char	    *file;
+    char	    *base;
+    FcBool	    ret;
+    
+    file = (char *) malloc (strlen (dir) + 1 + 256 + 1);
+    if (!file)
+	return FcFalse;
+
+    strcpy (file, dir);
+    strcat (file, "/");
+    base = file + strlen (file);
+    strcpy (base, FC_DIR_CACHE_FILE);
+    ret = FcFileCacheWriteDir (set, file);
+    free (file);
+    return ret;
+}
+
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
new file mode 100644
index 0000000..788b85a
--- /dev/null
+++ b/src/fcfreetype.c
@@ -0,0 +1,236 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "fcint.h"
+#include <freetype/freetype.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/tttables.h>
+#include <fontconfig/fcfreetype.h>
+
+static const struct {
+    int	    bit;
+    char    *name;
+} FcCodePageRange[] = {
+    { 0,	FC_LANG_LATIN_1 },
+    { 1,	FC_LANG_LATIN_2_EASTERN_EUROPE },
+    { 2,	FC_LANG_CYRILLIC },
+    { 3,	FC_LANG_GREEK },
+    { 4,	FC_LANG_TURKISH },
+    { 5,	FC_LANG_HEBREW },
+    { 6,	FC_LANG_ARABIC },
+    { 7,	FC_LANG_WINDOWS_BALTIC },
+    { 8,	FC_LANG_VIETNAMESE },
+/* 9-15 reserved for Alternate ANSI */
+    { 16,	FC_LANG_THAI },
+    { 17,	FC_LANG_JAPANESE },
+    { 18,	FC_LANG_SIMPLIFIED_CHINESE },
+    { 19,	FC_LANG_KOREAN_WANSUNG },
+    { 20,	FC_LANG_TRADITIONAL_CHINESE },
+    { 21,	FC_LANG_KOREAN_JOHAB },
+/* 22-28 reserved for Alternate ANSI & OEM */
+    { 29,	FC_LANG_MACINTOSH },
+    { 30,	FC_LANG_OEM },
+    { 31,	FC_LANG_SYMBOL },
+/* 32-47 reserved for OEM */
+    { 48,	FC_LANG_IBM_GREEK },
+    { 49,	FC_LANG_MSDOS_RUSSIAN },
+    { 50,	FC_LANG_MSDOS_NORDIC },
+    { 51,	FC_LANG_ARABIC_864 },
+    { 52,	FC_LANG_MSDOS_CANADIAN_FRENCH },
+    { 53,	FC_LANG_HEBREW_862 },
+    { 54,	FC_LANG_MSDOS_ICELANDIC },
+    { 55,	FC_LANG_MSDOS_PORTUGUESE },
+    { 56,	FC_LANG_IBM_TURKISH },
+    { 57,	FC_LANG_IBM_CYRILLIC },
+    { 58,	FC_LANG_LATIN_2 },
+    { 59,	FC_LANG_MSDOS_BALTIC },
+    { 60,	FC_LANG_GREEK_437_G },
+    { 61,	FC_LANG_ARABIC_ASMO_708 },
+    { 62,	FC_LANG_WE_LATIN_1 },
+    { 63,	FC_LANG_US },
+};
+
+#define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
+
+FcPattern *
+FcFreeTypeQuery (const char *file,
+		 int	    id,
+		 FcBlanks   *blanks,
+		 int	    *count)
+{
+    FT_Face	face;
+    FcPattern	*pat;
+    int		slant;
+    int		weight;
+    int		i;
+    FcCharSet	*cs;
+    FT_Library	ftLibrary;
+    const char	*family;
+    TT_OS2	*os2;
+
+    if (FT_Init_FreeType (&ftLibrary))
+	return 0;
+    
+    if (FT_New_Face (ftLibrary, file, id, &face))
+	goto bail;
+
+    *count = face->num_faces;
+
+    pat = FcPatternCreate ();
+    if (!pat)
+	goto bail0;
+
+    if (!FcPatternAddBool (pat, FC_OUTLINE,
+			   (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+	goto bail1;
+
+    if (!FcPatternAddBool (pat, FC_SCALABLE,
+			   (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+	goto bail1;
+
+
+    slant = FC_SLANT_ROMAN;
+    if (face->style_flags & FT_STYLE_FLAG_ITALIC)
+	slant = FC_SLANT_ITALIC;
+
+    if (!FcPatternAddInteger (pat, FC_SLANT, slant))
+	goto bail1;
+
+    weight = FC_WEIGHT_MEDIUM;
+    if (face->style_flags & FT_STYLE_FLAG_BOLD)
+	weight = FC_WEIGHT_BOLD;
+
+    if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
+	goto bail1;
+
+    family = face->family_name;
+    if (!family)
+    {
+	family = strrchr (file, '/');
+	if (family)
+	    family++;
+	else
+	    family = file;
+    }
+    if (!FcPatternAddString (pat, FC_FAMILY, family))
+	goto bail1;
+
+    if (face->style_name)
+    {
+	if (!FcPatternAddString (pat, FC_STYLE, face->style_name))
+	    goto bail1;
+    }
+
+    if (!FcPatternAddString (pat, FC_FILE, file))
+	goto bail1;
+
+    if (!FcPatternAddInteger (pat, FC_INDEX, id))
+	goto bail1;
+
+    if (!FcPatternAddString (pat, FC_SOURCE, "FreeType"))
+	goto bail1;
+
+#if 0
+    if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
+	if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
+	    goto bail1;
+#endif
+
+    cs = FcFreeTypeCharSet (face, blanks);
+    if (!cs)
+	goto bail1;
+
+    /*
+     * Skip over PCF fonts that have no encoded characters; they're
+     * usually just Unicode fonts transcoded to some legacy encoding
+     */
+    if (FcCharSetCount (cs) == 0)
+    {
+	if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
+	    goto bail2;
+    }
+
+    if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
+	goto bail2;
+    /*
+     * Drop our reference to the charset
+     */
+    FcCharSetDestroy (cs);
+    
+    if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
+    {
+	for (i = 0; i < face->num_fixed_sizes; i++)
+	    if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
+				     (double) face->available_sizes[i].height))
+		goto bail1;
+	if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
+	    goto bail1;
+    }
+
+    /*
+     * Get the OS/2 table and poke about
+     */
+    os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
+    if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
+    {
+	for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
+	{
+	    FT_ULong	bits;
+	    int		bit;
+	    if (FcCodePageRange[i].bit < 32)
+	    {
+		bits = os2->ulCodePageRange1;
+		bit = FcCodePageRange[i].bit;
+	    }
+	    else
+	    {
+		bits = os2->ulCodePageRange2;
+		bit = FcCodePageRange[i].bit - 32;
+	    }
+	    if (bits & (1 << bit))
+	    {
+		if (!FcPatternAddString (pat, FC_LANG,
+					 FcCodePageRange[i].name))
+		    goto bail1;
+	    }
+	}
+    }
+
+    FT_Done_Face (face);
+    FT_Done_FreeType (ftLibrary);
+    return pat;
+
+bail2:
+    FcCharSetDestroy (cs);
+bail1:
+    FcPatternDestroy (pat);
+bail0:
+    FT_Done_Face (face);
+bail:
+    FT_Done_FreeType (ftLibrary);
+    return 0;
+}
diff --git a/src/fcfs.c b/src/fcfs.c
new file mode 100644
index 0000000..afc071f
--- /dev/null
+++ b/src/fcfs.c
@@ -0,0 +1,82 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+FcFontSet *
+FcFontSetCreate (void)
+{
+    FcFontSet	*s;
+
+    s = (FcFontSet *) malloc (sizeof (FcFontSet));
+    if (!s)
+	return 0;
+    FcMemAlloc (FC_MEM_FONTSET, sizeof (FcFontSet));
+    s->nfont = 0;
+    s->sfont = 0;
+    s->fonts = 0;
+    return s;
+}
+
+void
+FcFontSetDestroy (FcFontSet *s)
+{
+    int	    i;
+
+    for (i = 0; i < s->nfont; i++)
+	FcPatternDestroy (s->fonts[i]);
+    if (s->fonts)
+    {
+	FcMemFree (FC_MEM_FONTPTR, s->sfont * sizeof (FcPattern *));
+	free (s->fonts);
+    }
+    FcMemFree (FC_MEM_FONTSET, sizeof (FcFontSet));
+    free (s);
+}
+
+FcBool
+FcFontSetAdd (FcFontSet *s, FcPattern *font)
+{
+    FcPattern	**f;
+    int		sfont;
+    
+    if (s->nfont == s->sfont)
+    {
+	sfont = s->sfont + 32;
+	if (s->fonts)
+	    f = (FcPattern **) realloc (s->fonts, sfont * sizeof (FcPattern *));
+	else
+	    f = (FcPattern **) malloc (sfont * sizeof (FcPattern *));
+	if (!f)
+	    return FcFalse;
+	if (s->sfont)
+	    FcMemFree (FC_MEM_FONTPTR, s->sfont * sizeof (FcPattern *));
+	FcMemAlloc (FC_MEM_FONTPTR, sfont * sizeof (FcPattern *));
+	s->sfont = sfont;
+	s->fonts = f;
+    }
+    s->fonts[s->nfont++] = font;
+    return FcTrue;
+}
diff --git a/src/fcinit.c b/src/fcinit.c
new file mode 100644
index 0000000..f82e018
--- /dev/null
+++ b/src/fcinit.c
@@ -0,0 +1,174 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+FcBool
+FcInitFonts (void)
+{
+    FcConfig	*config;
+
+    config = FcConfigGetCurrent ();
+    if (!config)
+	return FcFalse;
+
+    if (FcConfigGetFonts (config, FcSetSystem))
+	return FcTrue;
+
+    return FcConfigBuildFonts (config);
+}
+
+static FcBool
+FcInitFallbackConfig (void)
+{
+    FcConfig	*config;
+
+    config = FcConfigCreate ();
+    if (!config)
+	goto bail0;
+    if (!FcConfigAddDir (config, FC_FALLBACK_FONTS))
+	goto bail1;
+    FcConfigSetCurrent (config);
+    return FcTrue;
+
+bail1:
+    FcConfigDestroy (config);
+bail0:
+    return FcFalse;
+}
+
+/*
+ * Locate and parse the configuration file
+ */
+FcBool
+FcInitConfig (void)
+{
+    FcConfig    *config;
+    
+    if (FcConfigGetCurrent ())
+	return FcTrue;
+    
+    config = FcConfigCreate ();
+    if (!config)
+	return FcFalse;
+    
+    if (!FcConfigParseAndLoad (config, 0, FcTrue))
+    {
+	FcConfigDestroy (config);
+	return FcInitFallbackConfig ();
+    }
+    
+    FcConfigSetCurrent (config);
+    return FcTrue;
+}
+
+FcBool
+FcInit (void)
+{
+    return FcInitConfig () && FcInitFonts ();
+}
+
+static struct {
+    char    *name;
+    int	    alloc_count;
+    int	    alloc_mem;
+    int	    free_count;
+    int	    free_mem;
+} FcInUse[FC_MEM_NUM] = {
+    { "charset", 0, 0 },
+    { "charnode", 0 ,0 },
+    { "fontset", 0, 0 },
+    { "fontptr", 0, 0 },
+    { "objectset", 0, 0 },
+    { "objectptr", 0, 0 },
+    { "matrix", 0, 0 },
+    { "pattern", 0, 0 },
+    { "patelt", 0, 0 },
+    { "vallist", 0, 0 },
+    { "substate", 0, 0 },
+    { "string", 0, 0 },
+    { "listbuck", 0, 0 },
+};
+
+static int  FcAllocCount, FcAllocMem;
+static int  FcFreeCount, FcFreeMem;
+
+static int  FcMemNotice = 1*1024*1024;
+
+static int  FcAllocNotify, FcFreeNotify;
+
+void
+FcMemReport (void)
+{
+    int	i;
+    printf ("Fc Memory Usage:\n");
+    printf ("\t   Which       Alloc           Free           Active\n");
+    printf ("\t           count   bytes   count   bytes   count   bytes\n");
+    for (i = 0; i < FC_MEM_NUM; i++)
+	printf ("\t%8.8s%8d%8d%8d%8d%8d%8d\n",
+		FcInUse[i].name,
+		FcInUse[i].alloc_count, FcInUse[i].alloc_mem,
+		FcInUse[i].free_count, FcInUse[i].free_mem,
+		FcInUse[i].alloc_count - FcInUse[i].free_count,
+		FcInUse[i].alloc_mem - FcInUse[i].free_mem);
+    printf ("\t%8.8s%8d%8d%8d%8d%8d%8d\n",
+	    "Total",
+	    FcAllocCount, FcAllocMem,
+	    FcFreeCount, FcFreeMem,
+	    FcAllocCount - FcFreeCount,
+	    FcAllocMem - FcFreeMem);
+    FcAllocNotify = 0;
+    FcFreeNotify = 0;
+}
+
+void
+FcMemAlloc (int kind, int size)
+{
+    if (FcDebug() & FC_DBG_MEMORY)
+    {
+	FcInUse[kind].alloc_count++;
+	FcInUse[kind].alloc_mem += size;
+	FcAllocCount++;
+	FcAllocMem += size;
+	FcAllocNotify += size;
+	if (FcAllocNotify > FcMemNotice)
+	    FcMemReport ();
+    }
+}
+
+void
+FcMemFree (int kind, int size)
+{
+    if (FcDebug() & FC_DBG_MEMORY)
+    {
+	FcInUse[kind].free_count++;
+	FcInUse[kind].free_mem += size;
+	FcFreeCount++;
+	FcFreeMem += size;
+	FcFreeNotify += size;
+	if (FcFreeNotify > FcMemNotice)
+	    FcMemReport ();
+    }
+}
diff --git a/src/fcint.h b/src/fcint.h
new file mode 100644
index 0000000..139df3b
--- /dev/null
+++ b/src/fcint.h
@@ -0,0 +1,480 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _FCINT_H_
+#define _FCINT_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <libxml/parserInternals.h>
+#include <fontconfig/fontconfig.h>
+#include <fontconfig/fcprivate.h>
+#include <fontconfig/fcxml.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+typedef struct _FcMatcher {
+    char    *object;
+    double  (*compare) (char *object, FcValue value1, FcValue value2);
+} FcMatcher;
+
+typedef struct _FcSymbolic {
+    const char	*name;
+    int		value;
+} FcSymbolic;
+
+#ifndef FC_CONFIG_PATH
+#define FC_CONFIG_PATH "fonts.conf"
+#endif
+
+#define FC_DBG_MATCH	1
+#define FC_DBG_MATCHV	2
+#define FC_DBG_EDIT	4
+#define FC_DBG_FONTSET	8
+#define FC_DBG_CACHE	16
+#define FC_DBG_CACHEV	32
+#define FC_DBG_PARSE	64
+#define FC_DBG_SCAN	128
+#define FC_DBG_MEMORY	512
+
+#define FC_MEM_CHARSET	    0
+#define FC_MEM_CHARNODE	    1
+#define FC_MEM_FONTSET	    2
+#define FC_MEM_FONTPTR	    3
+#define FC_MEM_OBJECTSET    4
+#define FC_MEM_OBJECTPTR    5
+#define FC_MEM_MATRIX	    6
+#define FC_MEM_PATTERN	    7
+#define FC_MEM_PATELT	    8
+#define FC_MEM_VALLIST	    9
+#define FC_MEM_SUBSTATE	    10
+#define FC_MEM_STRING	    11
+#define FC_MEM_LISTBUCK	    12
+#define FC_MEM_NUM	    13
+
+typedef struct _FcValueList {
+    struct _FcValueList    *next;
+    FcValue		    value;
+} FcValueList;
+
+typedef struct _FcPatternElt {
+    const char	    *object;
+    FcValueList    *values;
+} FcPatternElt;
+
+struct _FcPattern {
+    int		    num;
+    int		    size;
+    FcPatternElt   *elts;
+};
+
+typedef enum _FcOp {
+    FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpBool, FcOpCharSet, 
+    FcOpNil,
+    FcOpField, FcOpConst,
+    FcOpAssign, FcOpAssignReplace, 
+    FcOpPrependFirst, FcOpPrepend, FcOpAppend, FcOpAppendLast,
+    FcOpQuest,
+    FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual, FcOpContains,
+    FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual,
+    FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide,
+    FcOpNot, FcOpComma, FcOpInvalid
+} FcOp;
+
+typedef struct _FcExpr {
+    FcOp   op;
+    union {
+	int	    ival;
+	double	    dval;
+	char	    *sval;
+	FcMatrix    *mval;
+	FcBool	    bval;
+	FcCharSet   *cval;
+	char	    *field;
+	char	    *constant;
+	struct {
+	    struct _FcExpr *left, *right;
+	} tree;
+    } u;
+} FcExpr;
+
+typedef enum _FcQual {
+    FcQualAny, FcQualAll
+} FcQual;
+
+typedef struct _FcTest {
+    struct _FcTest	*next;
+    FcQual		qual;
+    const char		*field;
+    FcOp		op;
+    FcExpr		*expr;
+} FcTest;
+
+typedef struct _FcEdit {
+    struct _FcEdit *next;
+    const char	    *field;
+    FcOp	    op;
+    FcExpr	    *expr;
+} FcEdit;
+
+typedef struct _FcSubst {
+    struct _FcSubst	*next;
+    FcTest		*test;
+    FcEdit		*edit;
+} FcSubst;
+
+typedef struct _FcCharLeaf FcCharLeaf;
+typedef struct _FcCharBranch FcCharBranch;
+typedef union  _FcCharNode FcCharNode;
+
+struct _FcCharLeaf {
+    FcChar32	map[256/32];
+};
+
+union _FcCharNode {
+    FcCharBranch    *branch;
+    FcCharLeaf	    *leaf;
+};
+
+struct _FcCharBranch {
+    FcCharNode	    nodes[256];
+};
+
+struct _FcCharSet {
+    int		    levels;
+    int		    ref;	/* reference count */
+    FcBool	    constant;	/* shared constant */
+    FcCharNode	    node;
+};
+
+typedef struct _FcNameBuf {
+    FcChar8 *buf;
+    FcBool  allocated;
+    FcBool  failed;
+    int	    len;
+    int	    size;
+} FcNameBuf;
+
+typedef struct _FcFileCacheEnt {
+    struct _FcFileCacheEnt *next;
+    unsigned int	    hash;
+    char		    *file;
+    int			    id;
+    time_t		    time;
+    char		    *name;
+    FcBool		    referenced;
+} FcFileCacheEnt;
+
+#define FC_FILE_CACHE_HASH_SIZE   509
+
+struct _FcFileCache {
+    FcFileCacheEnt	*ents[FC_FILE_CACHE_HASH_SIZE];
+    FcBool		updated;
+    int			entries;
+    int			referenced;
+};
+
+struct _FcBlanks {
+    int		nblank;
+    int		sblank;
+    FcChar32	*blanks;
+};
+
+struct _FcConfig {
+    /*
+     * File names loaded from the configuration -- saved here as the
+     * cache file must be consulted before the directories are scanned,
+     * and those directives may occur in any order
+     */
+    char	**dirs;		    /* directories containing fonts */
+    char	*cache;		    /* name of per-user cache file */
+    /*
+     * Set of allowed blank chars -- used to
+     * trim fonts of bogus glyphs
+     */
+    FcBlanks	*blanks;
+    /*
+     * Names of all of the configuration files used
+     * to create this configuration
+     */
+    char	**configFiles;	    /* config files loaded */
+    /*
+     * Substitution instructions for patterns and fonts;
+     * maxObjects is used to allocate appropriate intermediate storage
+     * while performing a whole set of substitutions
+     */
+    FcSubst	*substPattern;	    /* substitutions for patterns */
+    FcSubst	*substFont;	    /* substitutions for fonts */
+    int		maxObjects;	    /* maximum number of tests in all substs */
+    /*
+     * The set of fonts loaded from the listed directories; the
+     * order within the set does not determine the font selection,
+     * except in the case of identical matches in which case earlier fonts
+     * match preferrentially
+     */
+    FcFontSet	*fonts[FcSetApplication + 1];
+};
+ 
+/* fcblanks.c */
+
+/* fccache.c */
+
+FcFileCache *
+FcFileCacheCreate (void);
+
+char *
+FcFileCacheFind (FcFileCache	*cache,
+		 const char	*file,
+		 int		id,
+		 int		*count);
+
+void
+FcFileCacheDestroy (FcFileCache	*cache);
+
+void
+FcFileCacheLoad (FcFileCache	*cache,
+		 const char	*cache_file);
+
+FcBool
+FcFileCacheUpdate (FcFileCache	*cache,
+		   const char	*file,
+		   int		id,
+		   const char	*name);
+
+FcBool
+FcFileCacheSave (FcFileCache	*cache,
+		 const char	*cache_file);
+
+FcBool
+FcFileCacheReadDir (FcFontSet *set, const char *cache_file);
+
+FcBool
+FcFileCacheWriteDir (FcFontSet *set, const char *cache_file);
+    
+/* fccfg.c */
+
+FcBool
+FcConfigAddDir (FcConfig    *config,
+		const char  *d);
+
+FcBool
+FcConfigAddConfigFile (FcConfig	    *config,
+		       const char   *f);
+
+FcBool
+FcConfigSetCache (FcConfig	*config,
+		  const char	*c);
+
+FcBool
+FcConfigAddBlank (FcConfig	*config,
+		  FcChar32    	blank);
+
+FcBool
+FcConfigAddEdit (FcConfig	*config,
+		 FcTest		*test,
+		 FcEdit		*edit,
+		 FcMatchKind	kind);
+
+void
+FcConfigSetFonts (FcConfig	*config,
+		  FcFontSet	*fonts,
+		  FcSetName	set);
+
+FcBool
+FcConfigCompareValue (const FcValue m,
+		      FcOp	    op,
+		      const FcValue v);
+
+/* fccharset.c */
+FcBool
+FcNameUnparseCharSet (FcNameBuf *buf, const FcCharSet *c);
+
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string);
+
+/* fcdbg.c */
+void
+FcValuePrint (FcValue v);
+
+void
+FcValueListPrint (FcValueList *l);
+
+void
+FcPatternPrint (FcPattern *p);
+
+void
+FcOpPrint (FcOp op);
+
+void
+FcTestPrint (FcTest *test);
+
+void
+FcExprPrint (FcExpr *expr);
+
+void
+FcEditPrint (FcEdit *edit);
+
+void
+FcSubstPrint (FcSubst *subst);
+
+void
+FcFontSetPrint (FcFontSet *s);
+
+int
+FcDebug (void);
+
+/* fcdir.c */
+FcBool
+FcFileScan (FcFontSet	*set,
+	    FcFileCache	*cache,
+	    FcBlanks	*blanks,
+	    const char	*file,
+	    FcBool	force);
+
+FcBool
+FcDirScan (FcFontSet	*set,
+	   FcFileCache	*cache,
+	   FcBlanks	*blanks,
+	   const char	*dir,
+	   FcBool	force);
+
+FcBool
+FcDirSave (FcFontSet *set, const char *dir);
+
+/* fcfont.c */
+int
+FcFontDebug (void);
+    
+/* fcfs.c */
+/* fcgram.y */
+int
+FcConfigparse (void);
+
+int
+FcConfigwrap (void);
+    
+void
+FcConfigerror (char *fmt, ...);
+    
+char *
+FcConfigSaveField (const char *field);
+
+FcTest *
+FcTestCreate (FcQual qual, const char *field, FcOp compare, FcExpr *expr);
+
+void
+FcTestDestroy (FcTest *test);
+
+FcExpr *
+FcExprCreateInteger (int i);
+
+FcExpr *
+FcExprCreateDouble (double d);
+
+FcExpr *
+FcExprCreateString (const char *s);
+
+FcExpr *
+FcExprCreateMatrix (const FcMatrix *m);
+
+FcExpr *
+FcExprCreateBool (FcBool b);
+
+FcExpr *
+FcExprCreateNil (void);
+
+FcExpr *
+FcExprCreateField (const char *field);
+
+FcExpr *
+FcExprCreateConst (const char *constant);
+
+FcExpr *
+FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right);
+
+void
+FcExprDestroy (FcExpr *e);
+
+FcEdit *
+FcEditCreate (const char *field, FcOp op, FcExpr *expr);
+
+void
+FcEditDestroy (FcEdit *e);
+
+/* fcinit.c */
+
+void
+FcMemReport (void);
+
+void
+FcMemAlloc (int kind, int size);
+
+void
+FcMemFree (int kind, int size);
+
+/* fclist.c */
+
+/* fcmatch.c */
+
+/* fcname.c */
+FcBool
+FcNameConstant (char *string, int *result);
+
+FcBool
+FcNameBool (char *v, FcBool *result);
+
+FcBool
+FcNameBufChar (FcNameBuf *buf, FcChar8 c);
+
+FcBool
+FcNameBufString (FcNameBuf *buf, const FcChar8 *s);
+
+/* fcpat.c */
+void
+FcValueListDestroy (FcValueList *l);
+    
+FcPatternElt *
+FcPatternFind (FcPattern *p, const char *object, FcBool insert);
+
+/* fcrender.c */
+
+/* fcmatrix.c */
+void
+FcMatrixFree (FcMatrix *mat);
+
+/* fcstr.c */
+char *
+FcStrPlus (const char *s1, const char *s2);
+    
+void
+FcStrFree (char *s);
+
+#endif /* _FC_INT_H_ */
diff --git a/src/fclist.c b/src/fclist.c
new file mode 100644
index 0000000..4cbfed2
--- /dev/null
+++ b/src/fclist.c
@@ -0,0 +1,442 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+FcObjectSet *
+FcObjectSetCreate (void)
+{
+    FcObjectSet    *os;
+
+    os = (FcObjectSet *) malloc (sizeof (FcObjectSet));
+    if (!os)
+	return 0;
+    FcMemAlloc (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
+    os->nobject = 0;
+    os->sobject = 0;
+    os->objects = 0;
+    return os;
+}
+
+FcBool
+FcObjectSetAdd (FcObjectSet *os, const char *object)
+{
+    int		s;
+    const char	**objects;
+    
+    if (os->nobject == os->sobject)
+    {
+	s = os->sobject + 4;
+	if (os->objects)
+	    objects = (const char **) realloc ((void *) os->objects,
+					       s * sizeof (const char *));
+	else
+	    objects = (const char **) malloc (s * sizeof (const char *));
+	if (!objects)
+	    return FcFalse;
+	if (os->sobject)
+	    FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
+	FcMemAlloc (FC_MEM_OBJECTPTR, s * sizeof (const char *));
+	os->objects = objects;
+	os->sobject = s;
+    }
+    os->objects[os->nobject++] = object;
+    return FcTrue;
+}
+
+void
+FcObjectSetDestroy (FcObjectSet *os)
+{
+    if (os->objects)
+    {
+	FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
+	free ((void *) os->objects);
+    }
+    FcMemFree (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
+    free (os);
+}
+
+FcObjectSet *
+FcObjectSetVaBuild (const char *first, va_list va)
+{
+    FcObjectSet    *ret;
+
+    FcObjectSetVapBuild (ret, first, va);
+    return ret;
+}
+
+FcObjectSet *
+FcObjectSetBuild (const char *first, ...)
+{
+    va_list	    va;
+    FcObjectSet    *os;
+
+    va_start (va, first);
+    FcObjectSetVapBuild (os, first, va);
+    va_end (va);
+    return os;
+}
+
+static FcBool
+FcListValueListMatchAny (FcValueList *v1orig,
+			 FcValueList *v2orig)
+{
+    FcValueList	    *v1, *v2;
+
+    for (v1 = v1orig; v1; v1 = v1->next)
+	for (v2 = v2orig; v2; v2 = v2->next)
+	    if (FcConfigCompareValue (v2->value, FcOpContains, v1->value))
+		return FcTrue;
+    return FcFalse;
+}
+
+static FcBool
+FcListValueListEqual (FcValueList   *v1orig,
+		      FcValueList   *v2orig)
+{
+    FcValueList	    *v1, *v2;
+
+    for (v1 = v1orig; v1; v1 = v1->next)
+    {
+	for (v2 = v2orig; v2; v2 = v2->next)
+	    if (FcConfigCompareValue (v1->value, FcOpEqual, v2->value))
+		break;
+	if (!v2)
+	    return FcFalse;
+    }
+    for (v2 = v2orig; v2; v2 = v2->next)
+    {
+	for (v1 = v1orig; v1; v1 = v1->next)
+	    if (FcConfigCompareValue (v1->value, FcOpEqual, v2->value))
+		break;
+	if (!v1)
+	    return FcFalse;
+    }
+    return FcTrue;
+}
+
+/*
+ * FcTrue iff all objects in "p" match "font"
+ */
+
+static FcBool
+FcListPatternMatchAny (FcPattern *p,
+		       FcPattern *font)
+{
+    int		    i;
+    FcPatternElt   *e;
+
+    for (i = 0; i < p->num; i++)
+    {
+	e = FcPatternFind (font, p->elts[i].object, FcFalse);
+	if (!e)
+	    return FcFalse;
+	if (!FcListValueListMatchAny (p->elts[i].values, e->values))
+	    return FcFalse;
+    }
+    return FcTrue;
+}
+
+static FcBool
+FcListPatternEqual (FcPattern	*p1,
+		    FcPattern	*p2,
+		    FcObjectSet	*os)
+{
+    int		    i;
+    FcPatternElt    *e1, *e2;
+
+    for (i = 0; i < os->nobject; i++)
+    {
+	e1 = FcPatternFind (p1, os->objects[i], FcFalse);
+	e2 = FcPatternFind (p2, os->objects[i], FcFalse);
+	if (!e1 && !e2)
+	    return FcTrue;
+	if (!e1 || !e2)
+	    return FcFalse;
+	if (!FcListValueListEqual (e1->values, e2->values))
+	    return FcFalse;
+    }
+    return FcTrue;
+}
+
+static FcChar32
+FcListStringHash (const FcChar8	*s)
+{
+    FcChar32	h = 0;
+    FcChar8	c;
+
+    while ((c = *s++))
+    {
+	c = FcToLower (c);
+	h = ((h << 3) ^ (h >> 3)) ^ c;
+    }
+    return h;
+}
+
+static FcChar32
+FcListMatrixHash (const FcMatrix *m)
+{
+    int	    xx = (int) (m->xx * 100), 
+	    xy = (int) (m->xy * 100), 
+	    yx = (int) (m->yx * 100),
+	    yy = (int) (m->yy * 100);
+
+    return ((FcChar32) xx) ^ ((FcChar32) xy) ^ ((FcChar32) yx) ^ ((FcChar32) yy);
+}
+
+static FcChar32
+FcListValueHash (FcValue    v)
+{
+    switch (v.type) {
+    case FcTypeVoid:
+	return 0;
+    case FcTypeInteger:
+	return (FcChar32) v.u.i;
+    case FcTypeDouble:
+	return (FcChar32) (int) v.u.d;
+    case FcTypeString:
+	return FcListStringHash (v.u.s);
+    case FcTypeBool:
+	return (FcChar32) v.u.b;
+    case FcTypeMatrix:
+	return FcListMatrixHash (v.u.m);
+    case FcTypeCharSet:
+	return FcCharSetCount (v.u.c);
+    }
+    return 0;
+}
+
+static FcChar32
+FcListValueListHash (FcValueList    *list)
+{
+    FcChar32	h = 0;
+    
+    while (list)
+    {
+	h = h ^ FcListValueHash (list->value);
+	list = list->next;
+    }
+    return h;
+}
+
+static FcChar32
+FcListPatternHash (FcPattern	*font,
+		   FcObjectSet	*os)
+{
+    int		    n;
+    FcPatternElt    *e;
+    FcChar32	    h = 0;
+
+    for (n = 0; n < os->nobject; n++)
+    {
+	e = FcPatternFind (font, os->objects[n], FcFalse);
+	if (e)
+	    h = h ^ FcListValueListHash (e->values);
+    }
+    return h;
+}
+
+typedef struct _FcListBucket {
+    struct _FcListBucket    *next;
+    FcChar32		    hash;
+    FcPattern		    *pattern;
+} FcListBucket;
+
+#define FC_LIST_HASH_SIZE   4099
+
+typedef struct _FcListHashTable {
+    int		    entries;
+    FcListBucket    *buckets[FC_LIST_HASH_SIZE];
+} FcListHashTable;
+    
+static void
+FcListHashTableInit (FcListHashTable *table)
+{
+    table->entries = 0;
+    memset (table->buckets, '\0', sizeof (table->buckets));
+}
+
+static void
+FcListHashTableCleanup (FcListHashTable *table)
+{
+    int	i;
+    FcListBucket    *bucket, *next;
+
+    for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+    {
+	for (bucket = table->buckets[i]; bucket; bucket = next)
+	{
+	    next = bucket->next;
+	    FcPatternDestroy (bucket->pattern);
+	    FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+	    free (bucket);
+	}
+	table->buckets[i] = 0;
+    }
+    table->entries = 0;
+}
+
+static FcBool
+FcListAppend (FcListHashTable	*table,
+	      FcPattern		*font,
+	      FcObjectSet	*os)
+{
+    int		    o;
+    FcPatternElt    *e;
+    FcValueList	    *v;
+    FcChar32	    hash;
+    FcListBucket    **prev, *bucket;
+
+    hash = FcListPatternHash (font, os);
+    for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
+	 (bucket = *prev); prev = &(bucket->next))
+    {
+	if (bucket->hash == hash && 
+	    FcListPatternEqual (bucket->pattern, font, os))
+	    return FcTrue;
+    }
+    bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
+    if (!bucket)
+	goto bail0;
+    FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+    bucket->next = 0;
+    bucket->hash = hash;
+    bucket->pattern = FcPatternCreate ();
+    if (!bucket->pattern)
+	goto bail1;
+    
+    for (o = 0; o < os->nobject; o++)
+    {
+	e = FcPatternFind (font, os->objects[o], FcFalse);
+	if (e)
+	{
+	    for (v = e->values; v; v = v->next)
+	    {
+		if (!FcPatternAdd (bucket->pattern, 
+				   os->objects[o], 
+				   v->value, FcTrue))
+		    goto bail2;
+	    }
+	}
+    }
+    *prev = bucket;
+    ++table->entries;
+
+    return FcTrue;
+    
+bail2:
+    FcPatternDestroy (bucket->pattern);
+bail1:
+    FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+    free (bucket);
+bail0:
+    return FcFalse;
+}
+
+FcFontSet *
+FcFontList (FcConfig	*config,
+	    FcPattern	*p,
+	    FcObjectSet *os)
+{
+    FcFontSet	    *ret;
+    FcFontSet	    *s;
+    int		    f;
+    FcSetName	    set;
+    FcListHashTable table;
+    int		    i;
+    FcListBucket    *bucket;
+
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    goto bail0;
+    }
+    FcListHashTableInit (&table);
+    /*
+     * Walk all available fonts adding those that
+     * match to the hash table
+     */
+    for (set = FcSetSystem; set <= FcSetApplication; set++)
+    {
+	s = config->fonts[set];
+	if (!s)
+	    continue;
+	for (f = 0; f < s->nfont; f++)
+	    if (FcListPatternMatchAny (p, s->fonts[f]))
+		if (!FcListAppend (&table, s->fonts[f], os))
+		    goto bail1;
+    }
+#if 0
+    {
+	int	max = 0;
+	int	full = 0;
+	int	ents = 0;
+	int	len;
+	for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+	{
+	    if ((bucket = table.buckets[i]))
+	    {
+		len = 0;
+		for (; bucket; bucket = bucket->next)
+		{
+		    ents++;
+		    len++;
+		}
+		if (len > max)
+		    max = len;
+		full++;
+	    }
+	}
+	printf ("used: %d max: %d avg: %g\n", full, max, 
+		(double) ents / FC_LIST_HASH_SIZE);
+    }
+#endif
+    /*
+     * Walk the hash table and build
+     * a font set
+     */
+    ret = FcFontSetCreate ();
+    if (!ret)
+	goto bail0;
+    for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+	while ((bucket = table.buckets[i]))
+	{
+	    if (!FcFontSetAdd (ret, bucket->pattern))
+		goto bail2;
+	    table.buckets[i] = bucket->next;
+	    FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+	    free (bucket);
+	}
+    
+    return ret;
+
+bail2:
+    FcFontSetDestroy (ret);
+bail1:
+    FcListHashTableCleanup (&table);
+bail0:
+    return 0;
+}
diff --git a/src/fcmatch.c b/src/fcmatch.c
new file mode 100644
index 0000000..069f69f
--- /dev/null
+++ b/src/fcmatch.c
@@ -0,0 +1,347 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <string.h>
+#include <ctype.h>
+#include "fcint.h"
+#include <stdio.h>
+
+static double
+FcCompareInteger (char *object, FcValue value1, FcValue value2)
+{
+    int	v;
+    
+    if (value2.type != FcTypeInteger || value1.type != FcTypeInteger)
+	return -1.0;
+    v = value2.u.i - value1.u.i;
+    if (v < 0)
+	v = -v;
+    return (double) v;
+}
+
+static double
+FcCompareString (char *object, FcValue value1, FcValue value2)
+{
+    if (value2.type != FcTypeString || value1.type != FcTypeString)
+	return -1.0;
+    return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
+}
+
+static double
+FcCompareBool (char *object, FcValue value1, FcValue value2)
+{
+    if (value2.type != FcTypeBool || value1.type != FcTypeBool)
+	return -1.0;
+    return (double) value2.u.b != value1.u.b;
+}
+
+static double
+FcCompareCharSet (char *object, FcValue value1, FcValue value2)
+{
+    if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
+	return -1.0;
+    return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c);
+}
+
+static double
+FcCompareSize (char *object, FcValue value1, FcValue value2)
+{
+    double  v1, v2, v;
+
+    switch (value1.type) {
+    case FcTypeInteger:
+	v1 = value1.u.i;
+	break;
+    case FcTypeDouble:
+	v1 = value1.u.d;
+	break;
+    default:
+	return -1;
+    }
+    switch (value2.type) {
+    case FcTypeInteger:
+	v2 = value2.u.i;
+	break;
+    case FcTypeDouble:
+	v2 = value2.u.d;
+	break;
+    default:
+	return -1;
+    }
+    if (v2 == 0)
+	return 0;
+    v = v2 - v1;
+    if (v < 0)
+	v = -v;
+    return v;
+}
+
+/*
+ * Order is significant, it defines the precedence of
+ * each value, earlier values are more significant than
+ * later values
+ */
+static FcMatcher _FcMatchers [] = {
+    { FC_FOUNDRY,	FcCompareString, },
+    { FC_CHARSET,	FcCompareCharSet },
+    { FC_ANTIALIAS,	FcCompareBool, },
+    { FC_LANG,		FcCompareString },
+    { FC_FAMILY,	FcCompareString, },
+    { FC_SPACING,	FcCompareInteger, },
+    { FC_PIXEL_SIZE,	FcCompareSize, },
+    { FC_STYLE,		FcCompareString, },
+    { FC_SLANT,		FcCompareInteger, },
+    { FC_WEIGHT,	FcCompareInteger, },
+    { FC_RASTERIZER,	FcCompareString, },
+    { FC_OUTLINE,	FcCompareBool, },
+};
+
+#define NUM_MATCHER (sizeof _FcMatchers / sizeof _FcMatchers[0])
+
+static FcBool
+FcCompareValueList (const char  *object,
+		    FcValueList	*v1orig,	/* pattern */
+		    FcValueList *v2orig,	/* target */
+		    FcValue	*bestValue,
+		    double	*value,
+		    FcResult	*result)
+{
+    FcValueList    *v1, *v2;
+    double    	    v, best;
+    int		    j;
+    int		    i;
+    
+    for (i = 0; i < NUM_MATCHER; i++)
+    {
+	if (!FcStrCmpIgnoreCase (_FcMatchers[i].object, object))
+	    break;
+    }
+    if (i == NUM_MATCHER)
+    {
+	if (bestValue)
+	    *bestValue = v2orig->value;
+	return FcTrue;
+    }
+    
+    best = 1e99;
+    j = 0;
+    for (v1 = v1orig; v1; v1 = v1->next)
+    {
+	for (v2 = v2orig; v2; v2 = v2->next)
+	{
+	    v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
+					    v1->value,
+					    v2->value);
+	    if (v < 0)
+	    {
+		*result = FcResultTypeMismatch;
+		return FcFalse;
+	    }
+	    if (FcDebug () & FC_DBG_MATCHV)
+		printf (" v %g j %d ", v, j);
+	    v = v * 100 + j;
+	    if (v < best)
+	    {
+		if (bestValue)
+		    *bestValue = v2->value;
+		best = v;
+	    }
+	}
+	j++;
+    }
+    if (FcDebug () & FC_DBG_MATCHV)
+    {
+	printf (" %s: %g ", object, best);
+	FcValueListPrint (v1orig);
+	printf (", ");
+	FcValueListPrint (v2orig);
+	printf ("\n");
+    }
+    value[i] += best;
+    return FcTrue;
+}
+
+/*
+ * Return a value indicating the distance between the two lists of
+ * values
+ */
+
+static FcBool
+FcCompare (FcPattern	*pat,
+	   FcPattern	*fnt,
+	   double	*value,
+	   FcResult	*result)
+{
+    int		    i, i1, i2;
+    
+    for (i = 0; i < NUM_MATCHER; i++)
+	value[i] = 0.0;
+    
+    for (i1 = 0; i1 < pat->num; i1++)
+    {
+	for (i2 = 0; i2 < fnt->num; i2++)
+	{
+	    if (!FcStrCmpIgnoreCase (pat->elts[i1].object,
+				     fnt->elts[i2].object))
+	    {
+		if (!FcCompareValueList (pat->elts[i1].object,
+					 pat->elts[i1].values,
+					 fnt->elts[i2].values,
+					 0,
+					 value,
+					 result))
+		    return FcFalse;
+		break;
+	    }
+	}
+#if 0
+	/*
+	 * Overspecified patterns are slightly penalized in
+	 * case some other font includes the requested field
+	 */
+	if (i2 == fnt->num)
+	{
+	    for (i2 = 0; i2 < NUM_MATCHER; i2++)
+	    {
+		if (!FcStrCmpIgnoreCase (_FcMatchers[i2].object,
+					 pat->elts[i1].object))
+		{
+		    value[i2] = 1.0;
+		    break;
+		}
+	    }
+	}
+#endif
+    }
+    return FcTrue;
+}
+
+FcPattern *
+FcFontMatch (FcConfig	*config,
+	     FcPattern	*p, 
+	     FcResult	*result)
+{
+    double    	    score[NUM_MATCHER], bestscore[NUM_MATCHER];
+    int		    f;
+    FcFontSet	    *s;
+    FcPattern	    *best;
+    FcPattern	    *new;
+    FcPatternElt   *fe, *pe;
+    FcValue	    v;
+    int		    i;
+    FcSetName	    set;
+
+    for (i = 0; i < NUM_MATCHER; i++)
+	bestscore[i] = 0;
+    best = 0;
+    if (FcDebug () & FC_DBG_MATCH)
+    {
+	printf ("Match ");
+	FcPatternPrint (p);
+    }
+    if (!config)
+    {
+	config = FcConfigGetCurrent ();
+	if (!config)
+	    return 0;
+    }
+    for (set = FcSetSystem; set <= FcSetApplication; set++)
+    {
+	s = config->fonts[set];
+	if (!s)
+	    continue;
+	for (f = 0; f < s->nfont; f++)
+	{
+	    if (FcDebug () & FC_DBG_MATCHV)
+	    {
+		printf ("Font %d ", f);
+		FcPatternPrint (s->fonts[f]);
+	    }
+	    if (!FcCompare (p, s->fonts[f], score, result))
+		return 0;
+	    if (FcDebug () & FC_DBG_MATCHV)
+	    {
+		printf ("Score");
+		for (i = 0; i < NUM_MATCHER; i++)
+		{
+		    printf (" %g", score[i]);
+		}
+		printf ("\n");
+	    }
+	    for (i = 0; i < NUM_MATCHER; i++)
+	    {
+		if (best && bestscore[i] < score[i])
+		    break;
+		if (!best || score[i] < bestscore[i])
+		{
+		    for (i = 0; i < NUM_MATCHER; i++)
+			bestscore[i] = score[i];
+		    best = s->fonts[f];
+		    break;
+		}
+	    }
+	}
+    }
+    if (FcDebug () & FC_DBG_MATCH)
+    {
+	printf ("Best score");
+	for (i = 0; i < NUM_MATCHER; i++)
+	    printf (" %g", bestscore[i]);
+	FcPatternPrint (best);
+    }
+    if (!best)
+    {
+	*result = FcResultNoMatch;
+	return 0;
+    }
+    new = FcPatternCreate ();
+    if (!new)
+	return 0;
+    for (i = 0; i < best->num; i++)
+    {
+	fe = &best->elts[i];
+	pe = FcPatternFind (p, fe->object, FcFalse);
+	if (pe)
+	{
+	    if (!FcCompareValueList (pe->object, pe->values, 
+				     fe->values, &v, score, result))
+	    {
+		FcPatternDestroy (new);
+		return 0;
+	    }
+	}
+	else
+	    v = fe->values->value;
+	FcPatternAdd (new, fe->object, v, FcTrue);
+    }
+    for (i = 0; i < p->num; i++)
+    {
+	pe = &p->elts[i];
+	fe = FcPatternFind (best, pe->object, FcFalse);
+	if (!fe)
+	    FcPatternAdd (new, pe->object, pe->values->value, FcTrue);
+    }
+    FcConfigSubstitute (config, new, FcMatchFont);
+    return new;
+}
diff --git a/src/fcmatrix.c b/src/fcmatrix.c
new file mode 100644
index 0000000..d2a9f1e
--- /dev/null
+++ b/src/fcmatrix.c
@@ -0,0 +1,112 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Tuomas J. Lukka
+ *
+ * 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 Tuomas Lukka not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Tuomas Lukka makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * TUOMAS LUKKA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL TUOMAS LUKKA 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 <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "fcint.h"
+
+FcMatrix *
+FcMatrixCopy (const FcMatrix *mat) 
+{
+    FcMatrix *r;
+    if(!mat) 
+	return 0;
+    r = (FcMatrix *) malloc (sizeof (*r) );
+    if (!r)
+	return 0;
+    FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
+    *r = *mat;
+    return r;
+}
+
+void
+FcMatrixFree (FcMatrix *mat)
+{
+    FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
+    free (mat);
+}
+
+FcBool
+FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2)
+{
+    if(mat1 == mat2) return FcTrue;
+    if(mat1 == 0 || mat2 == 0) return FcFalse;
+    return mat1->xx == mat2->xx && 
+	   mat1->xy == mat2->xy &&
+	   mat1->yx == mat2->yx &&
+	   mat1->yy == mat2->yy;
+}
+
+void
+FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b)
+{
+    FcMatrix	r;
+
+    r.xx = a->xx * b->xx + a->xy * b->yx;
+    r.xy = a->xx * b->xy + a->xy * b->yy;
+    r.yx = a->yx * b->xx + a->yy * b->yx;
+    r.yy = a->yx * b->xy + a->yy * b->yy;
+    *result = r;
+}
+
+void
+FcMatrixRotate (FcMatrix *m, double c, double s)
+{
+    FcMatrix	r;
+
+    /*
+     * X Coordinate system is upside down, swap to make
+     * rotations counterclockwise
+     */
+    r.xx = c;
+    r.xy = -s;
+    r.yx = s;
+    r.yy = c;
+    FcMatrixMultiply (m, &r, m);
+}
+
+void
+FcMatrixScale (FcMatrix *m, double sx, double sy)
+{
+    FcMatrix	r;
+
+    r.xx = sx;
+    r.xy = 0;
+    r.yx = 0;
+    r.yy = sy;
+    FcMatrixMultiply (m, &r, m);
+}
+
+void
+FcMatrixShear (FcMatrix *m, double sh, double sv)
+{
+    FcMatrix	r;
+
+    r.xx = 1;
+    r.xy = sh;
+    r.yx = sv;
+    r.yy = 1;
+    FcMatrixMultiply (m, &r, m);
+}
diff --git a/src/fcname.c b/src/fcname.c
new file mode 100644
index 0000000..ed7c6c5
--- /dev/null
+++ b/src/fcname.c
@@ -0,0 +1,621 @@
+/*
+ * $XFree86: xc/lib/Fc/xftname.c,v 1.10 2001/03/30 18:50:18 keithp Exp $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "fcint.h"
+
+static const FcObjectType _FcBaseObjectTypes[] = {
+    { FC_FAMILY,	FcTypeString, },
+    { FC_STYLE,		FcTypeString, },
+    { FC_SLANT,		FcTypeInteger, },
+    { FC_WEIGHT,	FcTypeInteger, },
+    { FC_SIZE,		FcTypeDouble, },
+    { FC_PIXEL_SIZE,	FcTypeDouble, },
+    { FC_SPACING,	FcTypeInteger, },
+    { FC_FOUNDRY,	FcTypeString, },
+/*    { FC_CORE,		FcTypeBool, }, */
+    { FC_ANTIALIAS,	FcTypeBool, },
+/*    { FC_XLFD,		FcTypeString, }, */
+    { FC_FILE,		FcTypeString, },
+    { FC_INDEX,		FcTypeInteger, },
+    { FC_RASTERIZER,	FcTypeString, },
+    { FC_OUTLINE,	FcTypeBool, },
+    { FC_SCALABLE,	FcTypeBool, },
+    { FC_RGBA,		FcTypeInteger, },
+    { FC_SCALE,		FcTypeDouble, },
+/*    { FC_RENDER,	FcTypeBool, },*/
+    { FC_MINSPACE,	FcTypeBool, },
+    { FC_CHAR_WIDTH,	FcTypeInteger },
+    { FC_CHAR_HEIGHT,	FcTypeInteger },
+    { FC_MATRIX,	FcTypeMatrix },
+    { FC_CHARSET,	FcTypeCharSet },
+    { FC_LANG,		FcTypeString },
+};
+
+#define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
+
+typedef struct _FcObjectTypeList    FcObjectTypeList;
+
+struct _FcObjectTypeList {
+    const FcObjectTypeList  *next;
+    const FcObjectType	    *types;
+    int			    ntypes;
+};
+
+static const FcObjectTypeList _FcBaseObjectTypesList = {
+    0,
+    _FcBaseObjectTypes,
+    NUM_OBJECT_TYPES
+};
+
+static const FcObjectTypeList	*_FcObjectTypes = &_FcBaseObjectTypesList;
+
+FcBool
+FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    FcObjectTypeList	*l;
+
+    l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
+    if (!l)
+	return FcFalse;
+    l->types = types;
+    l->ntypes = ntypes;
+    l->next = _FcObjectTypes;
+    _FcObjectTypes = l;
+    return FcTrue;
+}
+
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+    const FcObjectTypeList	*l, **prev;
+
+    for (prev = &_FcObjectTypes; 
+	 (l = *prev); 
+	 prev = (const FcObjectTypeList **) &(l->next))
+    {
+	if (l->types == types && l->ntypes == ntypes)
+	{
+	    *prev = l->next;
+	    free ((void *) l);
+	    return FcTrue;
+	}
+    }
+    return FcFalse;
+}
+
+const FcObjectType *
+FcNameGetObjectType (const char *object)
+{
+    int			    i;
+    const FcObjectTypeList  *l;
+    const FcObjectType	    *t;
+    
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+	for (i = 0; i < l->ntypes; i++)
+	{
+	    t = &l->types[i];
+	    if (!FcStrCmpIgnoreCase (object, t->object))
+		return t;
+	}
+    }
+    return 0;
+}
+
+static const FcConstant _FcBaseConstants[] = {
+    { "light",		"weight",   FC_WEIGHT_LIGHT, },
+    { "medium",		"weight",   FC_WEIGHT_MEDIUM, },
+    { "demibold",	"weight",   FC_WEIGHT_DEMIBOLD, },
+    { "bold",		"weight",   FC_WEIGHT_BOLD, },
+    { "black",		"weight",   FC_WEIGHT_BLACK, },
+
+    { "roman",		"slant",    FC_SLANT_ROMAN, },
+    { "italic",		"slant",    FC_SLANT_ITALIC, },
+    { "oblique",	"slant",    FC_SLANT_OBLIQUE, },
+
+    { "proportional",	"spacing",  FC_PROPORTIONAL, },
+    { "mono",		"spacing",  FC_MONO, },
+    { "charcell",	"spacing",  FC_CHARCELL, },
+
+    { "rgb",		"rgba",	    FC_RGBA_RGB, },
+    { "bgr",		"rgba",	    FC_RGBA_BGR, },
+    { "vrgb",		"rgba",	    FC_RGBA_VRGB },
+    { "vbgr",		"rgba",	    FC_RGBA_VBGR },
+};
+
+#define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
+
+typedef struct _FcConstantList FcConstantList;
+
+struct _FcConstantList {
+    const FcConstantList    *next;
+    const FcConstant	    *consts;
+    int			    nconsts;
+};
+
+static const FcConstantList _FcBaseConstantList = {
+    0,
+    _FcBaseConstants,
+    NUM_FC_CONSTANTS
+};
+
+static const FcConstantList	*_FcConstants = &_FcBaseConstantList;
+
+FcBool
+FcNameRegisterConstants (const FcConstant *consts, int nconsts)
+{
+    FcConstantList	*l;
+
+    l = (FcConstantList *) malloc (sizeof (FcConstantList));
+    if (!l)
+	return FcFalse;
+    l->consts = consts;
+    l->nconsts = nconsts;
+    l->next = _FcConstants;
+    _FcConstants = l;
+    return FcTrue;
+}
+
+FcBool
+FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
+{
+    const FcConstantList	*l, **prev;
+
+    for (prev = &_FcConstants; 
+	 (l = *prev); 
+	 prev = (const FcConstantList **) &(l->next))
+    {
+	if (l->consts == consts && l->nconsts == nconsts)
+	{
+	    *prev = l->next;
+	    free ((void *) l);
+	    return FcTrue;
+	}
+    }
+    return FcFalse;
+}
+
+const FcConstant *
+FcNameGetConstant (char *string)
+{
+    const FcConstantList    *l;
+    int			    i;
+    
+    for (l = _FcConstants; l; l = l->next)
+    {
+	for (i = 0; i < l->nconsts; i++)
+	    if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
+		return &l->consts[i];
+    }
+    return 0;
+}
+
+FcBool
+FcNameConstant (char *string, int *result)
+{
+    const FcConstant	*c;
+
+    if ((c = FcNameGetConstant(string)))
+    {
+	*result = c->value;
+	return FcTrue;
+    }
+    return FcFalse;
+}
+
+FcBool
+FcNameBool (char *v, FcBool *result)
+{
+    char    c0, c1;
+
+    c0 = *v;
+    if (isupper (c0))
+	c0 = tolower (c0);
+    if (c0 == 't' || c0 == 'y' || c0 == '1')
+    {
+	*result = FcTrue;
+	return FcTrue;
+    }
+    if (c0 == 'f' || c0 == 'n' || c0 == '0')
+    {
+	*result = FcFalse;
+	return FcTrue;
+    }
+    if (c0 == 'o')
+    {
+	c1 = v[1];
+	if (isupper (c1))
+	    c1 = tolower (c1);
+	if (c1 == 'n')
+	{
+	    *result = FcTrue;
+	    return FcTrue;
+	}
+	if (c1 == 'f')
+	{
+	    *result = FcFalse;
+	    return FcTrue;
+	}
+    }
+    return FcFalse;
+}
+
+static FcValue
+FcNameConvert (FcType type, char *string, FcMatrix *m)
+{
+    FcValue	v;
+
+    v.type = type;
+    switch (v.type) {
+    case FcTypeInteger:
+	if (!FcNameConstant (string, &v.u.i))
+	    v.u.i = atoi (string);
+	break;
+    case FcTypeString:
+	v.u.s = string;
+	break;
+    case FcTypeBool:
+	if (!FcNameBool (string, &v.u.b))
+	    v.u.b = FcFalse;
+	break;
+    case FcTypeDouble:
+	v.u.d = strtod (string, 0);
+	break;
+    case FcTypeMatrix:
+	v.u.m = m;
+	sscanf (string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
+	break;
+    case FcTypeCharSet:
+	v.u.c = FcNameParseCharSet (string);
+	break;
+    default:
+	break;
+    }
+    return v;
+}
+
+static const char *
+FcNameFindNext (const char *cur, const char *delim, char *save, char *last)
+{
+    char    c;
+    
+    while ((c = *cur))
+    {
+	if (c == '\\')
+	{
+	    ++cur;
+	    if (!(c = *cur))
+		break;
+	}
+	else if (strchr (delim, c))
+	    break;
+	++cur;
+	*save++ = c;
+    }
+    *save = 0;
+    *last = *cur;
+    if (*cur)
+	cur++;
+    return cur;
+}
+
+FcPattern *
+FcNameParse (const char *name)
+{
+    char		*save;
+    FcPattern		*pat;
+    double		d;
+    char		*e;
+    char		delim;
+    FcValue		v;
+    FcMatrix		m;
+    const FcObjectType	*t;
+    const FcConstant	*c;
+
+    save = malloc (strlen (name) + 1);
+    if (!save)
+	goto bail0;
+    pat = FcPatternCreate ();
+    if (!pat)
+	goto bail1;
+
+    for (;;)
+    {
+	name = FcNameFindNext (name, "-,:", save, &delim);
+	if (save[0])
+	{
+	    if (!FcPatternAddString (pat, FC_FAMILY, save))
+		goto bail2;
+	}
+	if (delim != ',')
+	    break;
+    }
+    if (delim == '-')
+    {
+	for (;;)
+	{
+	    name = FcNameFindNext (name, "-,:", save, &delim);
+	    d = strtod (save, &e);
+	    if (e != save)
+	    {
+		if (!FcPatternAddDouble (pat, FC_SIZE, d))
+		    goto bail2;
+	    }
+	    if (delim != ',')
+		break;
+	}
+    }
+    while (delim == ':')
+    {
+	name = FcNameFindNext (name, "=_:", save, &delim);
+	if (save[0])
+	{
+	    if (delim == '=' || delim == '_')
+	    {
+		t = FcNameGetObjectType (save);
+		for (;;)
+		{
+		    name = FcNameFindNext (name, ":,", save, &delim);
+		    if (save[0] && t)
+		    {
+			v = FcNameConvert (t->type, save, &m);
+			if (!FcPatternAdd (pat, t->object, v, FcTrue))
+			{
+			    if (v.type == FcTypeCharSet)
+				FcCharSetDestroy ((FcCharSet *) v.u.c);
+			    goto bail2;
+			}
+			if (v.type == FcTypeCharSet)
+			    FcCharSetDestroy ((FcCharSet *) v.u.c);
+		    }
+		    if (delim != ',')
+			break;
+		}
+	    }
+	    else
+	    {
+		if ((c = FcNameGetConstant (save)))
+		{
+		    if (!FcPatternAddInteger (pat, c->object, c->value))
+			goto bail2;
+		}
+	    }
+	}
+    }
+
+    free (save);
+    return pat;
+
+bail2:
+    FcPatternDestroy (pat);
+bail1:
+    free (save);
+bail0:
+    return 0;
+}
+
+static void
+FcNameBufInit (FcNameBuf *buf, FcChar8 *init, int size)
+{
+    buf->buf = init;
+    buf->allocated = FcFalse;
+    buf->failed = FcFalse;
+    buf->len = 0;
+    buf->size = size;
+}
+
+static void
+FcNameBufDestroy (FcNameBuf *buf)
+{
+    if (buf->allocated)
+	free (buf->buf);
+}
+
+static FcChar8 *
+FcNameBufDone (FcNameBuf *buf)
+{
+    FcChar8 *ret;
+
+    ret = malloc (buf->len + 1);
+    if (ret)
+    {
+	memcpy (ret, buf->buf, buf->len);
+	ret[buf->len] = '\0';
+    }
+    FcNameBufDestroy (buf);
+    return ret;
+}
+
+FcBool
+FcNameBufChar (FcNameBuf *buf, FcChar8 c)
+{
+    if (buf->len == buf->size)
+    {
+	FcChar8	    *new;
+	int	    size;
+
+	if (buf->allocated)
+	{
+	    size = buf->size * 2;
+	    new = realloc (buf->buf, size);
+	}
+	else
+	{
+	    size = buf->size + 1024;
+	    new = malloc (size);
+	    if (new)
+	    {
+		buf->allocated = FcTrue;
+		memcpy (new, buf->buf, buf->len);
+	    }
+	}
+	if (!new)
+	{
+	    buf->failed = FcTrue;
+	    return FcFalse;
+	}
+	buf->size = size;
+	buf->buf = new;
+    }
+    buf->buf[buf->len++] = c;
+    return FcTrue;
+}
+
+FcBool
+FcNameBufString (FcNameBuf *buf, const FcChar8 *s)
+{
+    FcChar8 c;
+    while ((c = *s++))
+	if (!FcNameBufChar (buf, c))
+	    return FcFalse;
+    return FcTrue;
+}
+
+static FcBool
+FcNameUnparseString (FcNameBuf	    *buf, 
+		     const FcChar8  *string,
+		     const FcChar8  *escape)
+{
+    FcChar8 c;
+    while ((c = *string++))
+    {
+	if (escape && strchr ((char *) escape, (char) c))
+	{
+	    if (!FcNameBufChar (buf, escape[0]))
+		return FcFalse;
+	}
+	if (!FcNameBufChar (buf, c))
+	    return FcFalse;
+    }
+    return FcTrue;
+}
+
+static FcBool
+FcNameUnparseValue (FcNameBuf	*buf,
+		    FcValue	v,
+		    FcChar8	*escape)
+{
+    FcChar8	temp[1024];
+    
+    switch (v.type) {
+    case FcTypeVoid:
+	return FcTrue;
+    case FcTypeInteger:
+	sprintf ((char *) temp, "%d", v.u.i);
+	return FcNameUnparseString (buf, temp, 0);
+    case FcTypeDouble:
+	sprintf ((char *) temp, "%g", v.u.d);
+	return FcNameUnparseString (buf, temp, 0);
+    case FcTypeString:
+	return FcNameUnparseString (buf, v.u.s, escape);
+    case FcTypeBool:
+	return FcNameUnparseString (buf, v.u.b ? "True" : "False", 0);
+    case FcTypeMatrix:
+	sprintf ((char *) temp, "%g %g %g %g", 
+		 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
+	return FcNameUnparseString (buf, temp, 0);
+    case FcTypeCharSet:
+	return FcNameUnparseCharSet (buf, v.u.c);
+    }
+    return FcFalse;
+}
+
+static FcBool
+FcNameUnparseValueList (FcNameBuf	*buf,
+			FcValueList	*v,
+			char		*escape)
+{
+    while (v)
+    {
+	if (!FcNameUnparseValue (buf, v->value, escape))
+	    return FcFalse;
+	if ((v = v->next))
+	    if (!FcNameUnparseString (buf, ",", 0))
+		return FcFalse;
+    }
+    return FcTrue;
+}
+
+#define FC_ESCAPE_FIXED    "\\-:,"
+#define FC_ESCAPE_VARIABLE "\\=_:,"
+
+FcChar8 *
+FcNameUnparse (FcPattern *pat)
+{
+    FcNameBuf		    buf;
+    FcChar8		    buf_static[8192];
+    int			    i;
+    FcPatternElt	    *e;
+    const FcObjectTypeList  *l;
+    const FcObjectType	    *o;
+
+    FcNameBufInit (&buf, buf_static, sizeof (buf_static));
+    e = FcPatternFind (pat, FC_FAMILY, FcFalse);
+    if (e)
+    {
+	if (!FcNameUnparseValueList (&buf, e->values, FC_ESCAPE_FIXED))
+	    goto bail0;
+    }
+    e = FcPatternFind (pat, FC_SIZE, FcFalse);
+    if (e)
+    {
+	if (!FcNameUnparseString (&buf, "-", 0))
+	    goto bail0;
+	if (!FcNameUnparseValueList (&buf, e->values, FC_ESCAPE_FIXED))
+	    goto bail0;
+    }
+    for (l = _FcObjectTypes; l; l = l->next)
+    {
+	for (i = 0; i < l->ntypes; i++)
+	{
+	    o = &l->types[i];
+	    if (!strcmp (o->object, FC_FAMILY) || 
+		!strcmp (o->object, FC_SIZE) ||
+		!strcmp (o->object, FC_FILE))
+		continue;
+	    
+	    e = FcPatternFind (pat, o->object, FcFalse);
+	    if (e)
+	    {
+		if (!FcNameUnparseString (&buf, ":", 0))
+		    goto bail0;
+		if (!FcNameUnparseString (&buf, o->object, FC_ESCAPE_VARIABLE))
+		    goto bail0;
+		if (!FcNameUnparseString (&buf, "=", 0))
+		    goto bail0;
+		if (!FcNameUnparseValueList (&buf, e->values, 
+					     FC_ESCAPE_VARIABLE))
+		    goto bail0;
+	    }
+	}
+    }
+    return FcNameBufDone (&buf);
+bail0:
+    FcNameBufDestroy (&buf);
+    return 0;
+}
diff --git a/src/fcpat.c b/src/fcpat.c
new file mode 100644
index 0000000..a1fd774
--- /dev/null
+++ b/src/fcpat.c
@@ -0,0 +1,491 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <string.h>
+#include "fcint.h"
+
+FcPattern *
+FcPatternCreate (void)
+{
+    FcPattern	*p;
+
+    p = (FcPattern *) malloc (sizeof (FcPattern));
+    if (!p)
+	return 0;
+    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
+    p->num = 0;
+    p->size = 0;
+    p->elts = 0;
+    return p;
+}
+
+void
+FcValueDestroy (FcValue v)
+{
+    switch (v.type) {
+    case FcTypeString:
+	FcStrFree ((FcChar8 *) v.u.s);
+	break;
+    case FcTypeMatrix:
+	FcMatrixFree ((FcMatrix *) v.u.m);
+	break;
+    case FcTypeCharSet:
+	FcCharSetDestroy ((FcCharSet *) v.u.c);
+	break;
+    default:
+	break;
+    }
+}
+
+FcValue
+FcValueSave (FcValue v)
+{
+    switch (v.type) {
+    case FcTypeString:
+	v.u.s = FcStrCopy (v.u.s);
+	if (!v.u.s)
+	    v.type = FcTypeVoid;
+	break;
+    case FcTypeMatrix:
+	v.u.m = FcMatrixCopy (v.u.m);
+	if (!v.u.m)
+	    v.type = FcTypeVoid;
+	break;
+    case FcTypeCharSet:
+	v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
+	if (!v.u.c)
+	    v.type = FcTypeVoid;
+	break;
+    default:
+	break;
+    }
+    return v;
+}
+
+void
+FcValueListDestroy (FcValueList *l)
+{
+    FcValueList    *next;
+    for (; l; l = next)
+    {
+	switch (l->value.type) {
+	case FcTypeString:
+	    FcStrFree ((FcChar8 *) l->value.u.s);
+	    break;
+	case FcTypeMatrix:
+	    FcMatrixFree ((FcMatrix *) l->value.u.m);
+	    break;
+	case FcTypeCharSet:
+	    FcCharSetDestroy ((FcCharSet *) l->value.u.c);
+	    break;
+	default:
+	    break;
+	}
+	next = l->next;
+	FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+	free (l);
+    }
+}
+
+void
+FcPatternDestroy (FcPattern *p)
+{
+    int		    i;
+    
+    for (i = 0; i < p->num; i++)
+	FcValueListDestroy (p->elts[i].values);
+
+    p->num = 0;
+    if (p->elts)
+    {
+	FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+	free (p->elts);
+	p->elts = 0;
+    }
+    p->size = 0;
+    FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
+    free (p);
+}
+
+FcPatternElt *
+FcPatternFind (FcPattern *p, const char *object, FcBool insert)
+{
+    int		    i;
+    int		    s;
+    FcPatternElt   *e;
+    
+    /* match existing */
+    for (i = 0; i < p->num; i++)
+    {
+	if (!FcStrCmpIgnoreCase (object, p->elts[i].object))
+	    return &p->elts[i];
+    }
+
+    if (!insert)
+	return FcFalse;
+
+    /* grow array */
+    if (i == p->size)
+    {
+	s = p->size + 16;
+	if (p->elts)
+	    e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+	else
+	    e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
+	if (!e)
+	    return FcFalse;
+	p->elts = e;
+	if (p->size)
+	    FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+	FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
+	while (p->size < s)
+	{
+	    p->elts[p->size].object = 0;
+	    p->elts[p->size].values = 0;
+	    p->size++;
+	}
+    }
+    
+    /* bump count */
+    p->num++;
+    
+    p->elts[i].object = object;
+    
+    return &p->elts[i];
+}
+
+FcBool
+FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
+{
+    FcPatternElt   *e;
+    FcValueList    *new, **prev;
+
+    new = (FcValueList *) malloc (sizeof (FcValueList));
+    if (!new)
+	goto bail0;
+
+    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
+    /* dup string */
+    value = FcValueSave (value);
+    if (value.type == FcTypeVoid)
+	goto bail1;
+
+    new->value = value;
+    new->next = 0;
+    
+    e = FcPatternFind (p, object, FcTrue);
+    if (!e)
+	goto bail2;
+    
+    if (append)
+    {
+	for (prev = &e->values; *prev; prev = &(*prev)->next);
+	*prev = new;
+    }
+    else
+    {
+	new->next = e->values;
+	e->values = new;
+    }
+    
+    return FcTrue;
+
+bail2:    
+    switch (value.type) {
+    case FcTypeString:
+	FcStrFree ((FcChar8 *) value.u.s);
+	break;
+    case FcTypeMatrix:
+	FcMatrixFree ((FcMatrix *) value.u.m);
+	break;
+    case FcTypeCharSet:
+	FcCharSetDestroy ((FcCharSet *) value.u.c);
+	break;
+    default:
+	break;
+    }
+bail1:
+    FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+    free (new);
+bail0:
+    return FcFalse;
+}
+
+FcBool
+FcPatternDel (FcPattern *p, const char *object)
+{
+    FcPatternElt   *e;
+    int		    i;
+
+    e = FcPatternFind (p, object, FcFalse);
+    if (!e)
+	return FcFalse;
+
+    i = e - p->elts;
+    
+    /* destroy value */
+    FcValueListDestroy (e->values);
+    
+    /* shuffle existing ones down */
+    memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
+    p->num--;
+    p->elts[p->num].object = 0;
+    p->elts[p->num].values = 0;
+    return FcTrue;
+}
+
+FcBool
+FcPatternAddInteger (FcPattern *p, const char *object, int i)
+{
+    FcValue	v;
+
+    v.type = FcTypeInteger;
+    v.u.i = i;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddDouble (FcPattern *p, const char *object, double d)
+{
+    FcValue	v;
+
+    v.type = FcTypeDouble;
+    v.u.d = d;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+
+FcBool
+FcPatternAddString (FcPattern *p, const char *object, const char *s)
+{
+    FcValue	v;
+
+    v.type = FcTypeString;
+    v.u.s = (char *) s;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
+{
+    FcValue	v;
+
+    v.type = FcTypeMatrix;
+    v.u.m = (FcMatrix *) s;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+
+FcBool
+FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
+{
+    FcValue	v;
+
+    v.type = FcTypeBool;
+    v.u.b = b;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
+{
+    FcValue	v;
+
+    v.type = FcTypeCharSet;
+    v.u.c = (FcCharSet *) c;
+    return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcResult
+FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
+{
+    FcPatternElt   *e;
+    FcValueList    *l;
+
+    e = FcPatternFind (p, object, FcFalse);
+    if (!e)
+	return FcResultNoMatch;
+    for (l = e->values; l; l = l->next)
+    {
+	if (!id)
+	{
+	    *v = l->value;
+	    return FcResultMatch;
+	}
+	id--;
+    }
+    return FcResultNoId;
+}
+
+FcResult
+FcPatternGetInteger (FcPattern *p, const char *object, int id, int *i)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    switch (v.type) {
+    case FcTypeDouble:
+	*i = (int) v.u.d;
+	break;
+    case FcTypeInteger:
+	*i = v.u.i;
+	break;
+    default:
+        return FcResultTypeMismatch;
+    }
+    return FcResultMatch;
+}
+
+FcResult
+FcPatternGetDouble (FcPattern *p, const char *object, int id, double *d)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    switch (v.type) {
+    case FcTypeDouble:
+	*d = v.u.d;
+	break;
+    case FcTypeInteger:
+	*d = (double) v.u.i;
+	break;
+    default:
+        return FcResultTypeMismatch;
+    }
+    return FcResultMatch;
+}
+
+FcResult
+FcPatternGetString (FcPattern *p, const char *object, int id, char ** s)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    if (v.type != FcTypeString)
+        return FcResultTypeMismatch;
+    *s = (char *) v.u.s;
+    return FcResultMatch;
+}
+
+FcResult
+FcPatternGetMatrix (FcPattern *p, const char *object, int id, FcMatrix **m)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    if (v.type != FcTypeMatrix)
+        return FcResultTypeMismatch;
+    *m = (FcMatrix *) v.u.m;
+    return FcResultMatch;
+}
+
+
+FcResult
+FcPatternGetBool (FcPattern *p, const char *object, int id, FcBool *b)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    if (v.type != FcTypeBool)
+        return FcResultTypeMismatch;
+    *b = v.u.b;
+    return FcResultMatch;
+}
+
+FcResult
+FcPatternGetCharSet (FcPattern *p, const char *object, int id, FcCharSet **c)
+{
+    FcValue	v;
+    FcResult	r;
+
+    r = FcPatternGet (p, object, id, &v);
+    if (r != FcResultMatch)
+	return r;
+    if (v.type != FcTypeCharSet)
+        return FcResultTypeMismatch;
+    *c = (FcCharSet *) v.u.c;
+    return FcResultMatch;
+}
+
+FcPattern *
+FcPatternDuplicate (FcPattern *orig)
+{
+    FcPattern	    *new;
+    int		    i;
+    FcValueList    *l;
+
+    new = FcPatternCreate ();
+    if (!new)
+	goto bail0;
+
+    for (i = 0; i < orig->num; i++)
+    {
+	for (l = orig->elts[i].values; l; l = l->next)
+	    if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
+		goto bail1;
+    }
+
+    return new;
+
+bail1:
+    FcPatternDestroy (new);
+bail0:
+    return 0;
+}
+
+FcPattern *
+FcPatternVaBuild (FcPattern *orig, va_list va)
+{
+    FcPattern	*ret;
+    
+    FcPatternVapBuild (ret, orig, va);
+    return ret;
+}
+
+FcPattern *
+FcPatternBuild (FcPattern *orig, ...)
+{
+    va_list	va;
+    
+    va_start (va, orig);
+    FcPatternVapBuild (orig, orig, va);
+    va_end (va);
+    return orig;
+}
diff --git a/src/fcstr.c b/src/fcstr.c
new file mode 100644
index 0000000..658890e
--- /dev/null
+++ b/src/fcstr.c
@@ -0,0 +1,188 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "fcint.h"
+
+char *
+FcStrCopy (const char *s)
+{
+    char	*r;
+
+    if (!s)
+	return 0;
+    r = (char *) malloc (strlen (s) + 1);
+    if (!r)
+	return 0;
+    FcMemAlloc (FC_MEM_STRING, strlen (s) + 1);
+    strcpy (r, s);
+    return r;
+}
+
+char *
+FcStrPlus (const char *s1, const char *s2)
+{
+    int	    l = strlen (s1) + strlen (s2) + 1;
+    char    *s = malloc (l);
+
+    if (!s)
+	return 0;
+    FcMemAlloc (FC_MEM_STRING, l);
+    strcpy (s, s1);
+    strcat (s, s2);
+    return s;
+}
+
+void
+FcStrFree (char *s)
+{
+    FcMemFree (FC_MEM_STRING, strlen (s) + 1);
+    free (s);
+}
+
+int
+FcStrCmpIgnoreCase (const char *s1, const char *s2)
+{
+    char    c1, c2;
+    
+    for (;;) 
+    {
+	c1 = *s1++;
+	c2 = *s2++;
+	if (!c1 || !c2)
+	    break;
+	c1 = FcToLower (c1);
+	c2 = FcToLower (c2);
+	if (c1 != c2)
+	    break;
+    }
+    return (int) c2 - (int) c1;
+}
+
+int
+FcUtf8ToUcs4 (FcChar8   *src_orig,
+	      FcChar32  *dst,
+	      int	len)
+{
+    FcChar8	*src = src_orig;
+    FcChar8	s;
+    int		extra;
+    FcChar32	result;
+
+    if (len == 0)
+	return 0;
+    
+    s = *src++;
+    len--;
+    
+    if (!(s & 0x80))
+    {
+	result = s;
+	extra = 0;
+    } 
+    else if (!(s & 0x40))
+    {
+	return -1;
+    }
+    else if (!(s & 0x20))
+    {
+	result = s & 0x1f;
+	extra = 1;
+    }
+    else if (!(s & 0x10))
+    {
+	result = s & 0xf;
+	extra = 2;
+    }
+    else if (!(s & 0x08))
+    {
+	result = s & 0x07;
+	extra = 3;
+    }
+    else if (!(s & 0x04))
+    {
+	result = s & 0x03;
+	extra = 4;
+    }
+    else if ( ! (s & 0x02))
+    {
+	result = s & 0x01;
+	extra = 5;
+    }
+    else
+    {
+	return -1;
+    }
+    if (extra > len)
+	return -1;
+    
+    while (extra--)
+    {
+	result <<= 6;
+	s = *src++;
+	
+	if ((s & 0xc0) != 0x80)
+	    return -1;
+	
+	result |= s & 0x3f;
+    }
+    *dst = result;
+    return src - src_orig;
+}
+
+FcBool
+FcUtf8Len (FcChar8	*string,
+	    int		len,
+	    int		*nchar,
+	    int		*wchar)
+{
+    int		n;
+    int		clen;
+    FcChar32	c;
+    FcChar32	max;
+    
+    n = 0;
+    max = 0;
+    while (len)
+    {
+	clen = FcUtf8ToUcs4 (string, &c, len);
+	if (clen <= 0)	/* malformed UTF8 string */
+	    return FcFalse;
+	if (c > max)
+	    max = c;
+	string += clen;
+	len -= clen;
+	n++;
+    }
+    *nchar = n;
+    if (max >= 0x10000)
+	*wchar = 4;
+    else if (max > 0x100)
+	*wchar = 2;
+    else
+	*wchar = 1;
+    return FcTrue;
+}
diff --git a/src/fcxml.c b/src/fcxml.c
new file mode 100644
index 0000000..07e24df
--- /dev/null
+++ b/src/fcxml.c
@@ -0,0 +1,1032 @@
+/*
+ * $XFree86: $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdarg.h>
+#include "fcint.h"
+
+static xmlParserInputPtr
+FcEntityLoader (const char *url, const char *id, xmlParserCtxtPtr ctxt)
+{
+    xmlParserInputPtr	ret;
+    char		*file;
+
+    file = FcConfigFilename (url);
+    if (!file)
+	return 0;
+    ret = xmlNewInputFromFile (ctxt, file);
+    free (file);
+    return ret;
+}
+
+xmlDocPtr
+FcConfigLoad (const char *file)
+{
+    xmlDocPtr		    doc;
+    xmlExternalEntityLoader previous;
+
+    previous = xmlGetExternalEntityLoader ();
+    xmlSetExternalEntityLoader (FcEntityLoader);
+    doc = xmlParseFile (file);
+    xmlSetExternalEntityLoader (previous);
+    return doc;
+}
+
+#if 0
+int
+FcConfigSave (char *file, xmlDocPtr doc)
+{
+}
+#endif
+
+FcTest *
+FcTestCreate (FcQual qual, const char *field, FcOp compare, FcExpr *expr)
+{
+    FcTest	*test = (FcTest *) malloc (sizeof (FcTest));;
+
+    if (test)
+    {
+	test->next = 0;
+	test->qual = qual;
+	test->field = FcStrCopy (field);
+	test->op = compare;
+	test->expr = expr;
+    }
+    return test;
+}
+
+void
+FcTestDestroy (FcTest *test)
+{
+    if (test->next)
+	FcTestDestroy (test->next);
+    FcExprDestroy (test->expr);
+    FcStrFree ((FcChar8 *) test->field);
+    free (test);
+}
+
+FcExpr *
+FcExprCreateInteger (int i)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpInteger;
+	e->u.ival = i;
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateDouble (double d)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpDouble;
+	e->u.dval = d;
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateString (const char *s)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpString;
+	e->u.sval = FcStrCopy (s);
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateMatrix (const FcMatrix *m)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpMatrix;
+	e->u.mval = FcMatrixCopy (m);
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateBool (FcBool b)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpBool;
+	e->u.bval = b;
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateNil (void)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpNil;
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateField (const char *field)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpField;
+	e->u.field = FcStrCopy (field);
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateConst (const char *constant)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = FcOpConst;
+	e->u.constant = FcStrCopy (constant);
+    }
+    return e;
+}
+
+FcExpr *
+FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
+{
+    FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+    if (e)
+    {
+	e->op = op;
+	e->u.tree.left = left;
+	e->u.tree.right = right;
+    }
+    return e;
+}
+
+void
+FcExprDestroy (FcExpr *e)
+{
+    switch (e->op) {
+    case FcOpInteger:
+	break;
+    case FcOpDouble:
+	break;
+    case FcOpString:
+	FcStrFree (e->u.sval);
+	break;
+    case FcOpMatrix:
+	FcMatrixFree (e->u.mval);
+	break;
+    case FcOpCharSet:
+	FcCharSetDestroy (e->u.cval);
+	break;
+    case FcOpBool:
+	break;
+    case FcOpField:
+	FcStrFree (e->u.field);
+	break;
+    case FcOpConst:
+	FcStrFree (e->u.constant);
+	break;
+    case FcOpAssign:
+    case FcOpAssignReplace:
+    case FcOpPrepend:
+    case FcOpPrependFirst:
+    case FcOpAppend:
+    case FcOpAppendLast:
+	break;
+    case FcOpOr:
+    case FcOpAnd:
+    case FcOpEqual:
+    case FcOpContains:
+    case FcOpNotEqual:
+    case FcOpLess:
+    case FcOpLessEqual:
+    case FcOpMore:
+    case FcOpMoreEqual:
+    case FcOpPlus:
+    case FcOpMinus:
+    case FcOpTimes:
+    case FcOpDivide:
+    case FcOpQuest:
+    case FcOpComma:
+	FcExprDestroy (e->u.tree.right);
+	/* fall through */
+    case FcOpNot:
+	FcExprDestroy (e->u.tree.left);
+	break;
+    case FcOpNil:
+    case FcOpInvalid:
+	break;
+    }
+    free (e);
+}
+
+FcEdit *
+FcEditCreate (const char *field, FcOp op, FcExpr *expr)
+{
+    FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
+
+    if (e)
+    {
+	e->next = 0;
+	e->field = field;   /* already saved in grammar */
+	e->op = op;
+	e->expr = expr;
+    }
+    return e;
+}
+
+void
+FcEditDestroy (FcEdit *e)
+{
+    if (e->next)
+	FcEditDestroy (e->next);
+    FcStrFree ((FcChar8 *) e->field);
+    if (e->expr)
+	FcExprDestroy (e->expr);
+}
+
+char *
+FcConfigSaveField (const char *field)
+{
+    return FcStrCopy (field);
+}
+
+static void
+FcConfigParseError (char *fmt, ...)
+{
+    va_list	args;
+
+    va_start (args, fmt);
+    fprintf (stderr, "font configuration error: ");
+    vfprintf (stderr, fmt, args);
+    fprintf (stderr, "\n");
+    va_end (args);
+}
+
+static char *
+FcConfigContent (xmlDocPtr    doc,
+		 xmlNodePtr   node)
+{
+    char	    *content;
+    
+    content = xmlNodeListGetString (doc, node->children, 1);
+    if (!content)
+    {
+	FcConfigParseError ("<%s> must have content",
+			    node->name);
+	return FcFalse;
+    }
+    return content;
+}
+
+static char *
+FcConfigAttr (xmlDocPtr	    doc,
+	      xmlAttrPtr    attr)
+{
+    char	    *content;
+    
+    content = xmlNodeListGetString (doc, attr->children, 1);
+    if (!content)
+    {
+	FcConfigParseError ("attribute %s must have a value",
+			    attr->name);
+	return FcFalse;
+    }
+    return content;
+}
+
+static struct {
+    char    *name;
+    FcOp    op;
+} fcOps[] = {
+    { "int",		FcOpInteger	    },
+    { "double",		FcOpDouble	    },
+    { "string",		FcOpString	    },
+    { "matrix",		FcOpMatrix	    },
+    { "bool",		FcOpBool	    },
+    { "charset",	FcOpCharSet	    },
+    { "name",		FcOpField	    },
+    { "const",		FcOpConst	    },
+    { "field",		FcOpField	    },
+    { "if",		FcOpQuest	    },
+    { "or",		FcOpOr		    },
+    { "and",		FcOpAnd		    },
+    { "eq",		FcOpEqual	    },
+    { "not_eq",		FcOpNotEqual	    },
+    { "less",		FcOpLess	    },
+    { "less_eq",	FcOpLessEqual	    },
+    { "more",		FcOpMore	    },
+    { "more_eq",	FcOpMoreEqual	    },
+    { "plus",		FcOpPlus	    },
+    { "minus",		FcOpMinus	    },
+    { "times",		FcOpTimes	    },
+    { "divide",		FcOpDivide	    },
+    { "not",		FcOpNot		    },
+    { "assign",		FcOpAssign	    },
+    { "assign_replace",	FcOpAssignReplace   },
+    { "prepend",	FcOpPrepend	    },
+    { "prepend_first",	FcOpPrependFirst    },
+    { "append",		FcOpAppend	    },
+    { "append_last",	FcOpAppendLast	    },
+};
+
+#define NUM_OPS (sizeof fcOps / sizeof fcOps[0])
+
+static FcOp
+FcConfigLexOp (const char *op)
+{
+    int	i;
+
+    for (i = 0; i < NUM_OPS; i++)
+	if (!strcmp (op, fcOps[i].name)) return fcOps[i].op;
+    return FcOpInvalid;
+}
+
+static FcBool
+FcConfigLexBool (const char *bool)
+{
+    if (*bool == 't' || *bool == 'T')
+	return FcTrue;
+    if (*bool == 'y' || *bool == 'Y')
+	return FcTrue;
+    if (*bool == '1')
+	return FcTrue;
+    return FcFalse;
+}
+
+static FcBool
+FcConfigParseDir (FcConfig	*config,
+		  xmlDocPtr	doc,
+		  xmlNodePtr	dir)
+{
+    char    *content = FcConfigContent (doc, dir);
+
+    if (!content)
+	return FcFalse;
+    return FcConfigAddDir (config, content);
+}
+
+static FcBool
+FcConfigParseCache (FcConfig	*config,
+		    xmlDocPtr	doc,
+		    xmlNodePtr	dir)
+{
+    char    *content = FcConfigContent (doc, dir);
+
+    if (!content)
+	return FcFalse;
+    return FcConfigSetCache (config, content);
+}
+
+static FcBool
+FcConfigParseInclude (FcConfig	    *config,
+		      xmlDocPtr	    doc,
+		      xmlNodePtr    inc)
+{
+    char	*content = FcConfigContent (doc, inc);
+    xmlAttr	*attr;
+    FcBool	complain = FcTrue;
+
+    if (!content)
+	return FcFalse;
+    
+    for (attr = inc->properties; attr; attr = attr->next)
+    {
+	if (attr->type != XML_ATTRIBUTE_NODE)
+	    continue;
+	if (!strcmp (attr->name, "ignore_missing"))
+	    complain = !FcConfigLexBool (FcConfigAttr (doc, attr));
+    }
+    return FcConfigParseAndLoad (config, content, complain);
+}
+
+static FcBool
+FcConfigParseBlank (FcConfig	    *config,
+		    xmlDocPtr	    doc,
+		    xmlNodePtr	    blank)
+{
+    xmlNode	*node;
+    FcChar32	ucs4;
+
+    for (node = blank->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (!strcmp (node->name, "int"))
+	{
+	    ucs4 = (FcChar32) strtol (FcConfigContent (doc, node), 0, 0);
+	    if (!config->blanks)
+	    {
+		config->blanks = FcBlanksCreate ();
+		if (!config->blanks)
+		    break;
+	    }
+	    if (!FcBlanksAdd (config->blanks, ucs4))
+		break;
+	}
+    }
+    if (node)
+	return FcFalse;
+    return FcTrue;
+}
+
+static FcBool
+FcConfigParseConfig (FcConfig	    *config,
+		     xmlDocPtr	    doc,
+		     xmlNodePtr	    cfg)
+{
+    xmlNode	*node;
+
+    for (node = cfg->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (!strcmp (node->name, "blank"))
+	{
+	    if (!FcConfigParseBlank (config, doc, node))
+		break;
+	}
+    }
+    if (node)
+	return FcFalse;
+    return FcTrue;
+}
+
+static FcMatrix *
+FcConfigParseMatrix (xmlDocPtr	doc,
+		     xmlNodePtr	node)
+{
+    static FcMatrix m;
+    enum { m_xx, m_xy, m_yx, m_yy, m_done } matrix_state = m_xx;
+    double  v;
+    char    *text;
+    
+    FcMatrixInit (&m);
+
+    for (; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (strcmp (node->name, "double"))
+	    continue;
+	text = FcConfigContent (doc, node);
+	if (!text)
+	    continue;
+	v = strtod (text, 0);
+	switch (matrix_state) {
+	case m_xx: m.xx = v; break;
+	case m_xy: m.xy = v; break;
+	case m_yx: m.yx = v; break;
+	case m_yy: m.yy = v; break;
+	default: break;
+	}
+	matrix_state++;
+    }
+	 
+    return &m;
+}
+
+static FcExpr *
+FcConfigParseExpr (xmlDocPtr	doc,
+		   xmlNodePtr	expr)
+{
+    FcOp	op = FcConfigLexOp (expr->name);
+    xmlNodePtr	node;
+    FcExpr	*l = 0, *e = 0, *r = 0, *c = 0;
+
+    switch (op) {
+    case FcOpInteger:
+	l = FcExprCreateInteger (strtol (FcConfigContent (doc, expr), 0, 0));
+	break;
+    case FcOpDouble:
+	l = FcExprCreateDouble (strtod (FcConfigContent (doc, expr), 0));
+	break;
+    case FcOpString:
+	l = FcExprCreateString (FcConfigContent (doc, expr));
+	break;
+    case FcOpMatrix:
+	l = FcExprCreateMatrix (FcConfigParseMatrix (doc, expr));
+	break;
+    case FcOpBool:
+	l = FcExprCreateBool (FcConfigLexBool(FcConfigContent (doc, expr)));
+	break;
+    case FcOpCharSet:
+	/* not sure what to do here yet */
+	break;
+    case FcOpField:
+	l = FcExprCreateField (FcConfigContent (doc, expr));
+	break;
+    case FcOpConst:
+	l = FcExprCreateConst (FcConfigContent (doc, expr));
+	break;
+    case FcOpQuest:
+	for (node = expr->children; node; node = node->next)
+	{
+	    if (node->type != XML_ELEMENT_NODE)
+		continue;
+	    e = FcConfigParseExpr (doc, node);
+	    if (!e)
+		break;
+	    if (!l)
+		l = e;
+	    else if (!c)
+		c = e;
+	    else if (!r)
+		r = e;
+	    else
+		FcExprDestroy (e);
+	}
+	e = 0;
+	if (!node && l && c && r)
+	{
+	    e = FcExprCreateOp (c, FcOpQuest, r);
+	    if (e)
+	    {
+		r = e;
+		c = 0;
+		e = FcExprCreateOp (l, FcOpQuest, r);
+	    }
+	    if (!e)
+		node = expr->children;
+	}
+	if (node || !l || !c || !r || !e)
+	{
+	    if (l)
+		FcExprDestroy (l);
+	    if (c)
+		FcExprDestroy (c);
+	    if (r)
+		FcExprDestroy (r);
+	    return 0;
+	}
+	break;
+    default:
+	for (node = expr->children; node; node = node->next)
+	{
+	    if (node->type != XML_ELEMENT_NODE)
+		continue;
+	    e = FcConfigParseExpr (doc, node);
+	    if (!e)
+		break;
+	    if (!l)
+		l = e;
+	    else
+	    {
+		r = e;
+		e = FcExprCreateOp (l, op, r);
+		if (!e)
+		{
+		    FcExprDestroy (r);
+		    break;
+		}
+		l = e;
+	    }
+	}
+	if (node || !l)
+	{
+	    if (l)
+		FcExprDestroy (l);
+	    return 0;
+	}
+	/*
+	 * Special case for unary ops 
+	 */
+	if (!r)
+	{
+	    e = FcExprCreateOp (l, op, 0);
+	    if (!e)
+	    {
+		FcExprDestroy (l);
+		return 0;
+	    }
+	}
+	break;
+    
+    case FcOpInvalid:
+	return 0;
+    }
+    return l;
+}
+
+static FcTest *
+FcConfigParseTest (xmlDocPtr	doc,
+		   xmlNodePtr	test)
+{
+    xmlNodePtr	node;
+    xmlAttrPtr	attr;
+    FcQual	qual = FcQualAny;
+    FcOp	op = FcOpEqual;
+    char	*field = 0;
+    FcExpr	*expr = 0;
+
+    for (attr = test->properties; attr; attr = attr->next)
+    {
+	if (attr->type != XML_ATTRIBUTE_NODE)
+	    continue;
+	if (!strcmp (attr->name, "qual"))
+	{
+	    char    *qual_name = FcConfigAttr (doc, attr);
+	    if (!qual_name)
+		;
+	    else if (!strcmp (qual_name, "any"))
+		qual = FcQualAny;
+	    else if (!strcmp (qual_name, "all"))
+		qual = FcQualAll;
+	}
+	else if (!strcmp (attr->name, "name"))
+	{
+	    field = FcConfigAttr (doc, attr);
+	}
+	else if (!strcmp (attr->name, "compare"))
+	{
+	    char    *compare = FcConfigAttr (doc, attr);
+	    
+	    if (!compare || (op = FcConfigLexOp (compare)) == FcOpInvalid)
+	    {
+		FcConfigParseError ("Invalid comparison %s", 
+				    compare ? compare : "<missing>");
+		return 0;
+	    }
+	}
+    }
+    if (attr)
+	return 0;
+
+    for (node = test->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	expr = FcConfigParseExpr (doc, node);
+	if (!expr)
+	    return 0;
+	break;
+    }
+
+    if (!expr)
+    {
+	FcConfigParseError ("Missing test expression");
+	return 0;
+    }
+    
+    return FcTestCreate (qual, field, op, expr);
+}
+
+static FcExpr *
+FcConfigParseExprList (xmlDocPtr    doc,
+		       xmlNodePtr   expr)
+{
+    FcExpr  *l, *e, *r;
+    
+    if (!expr)
+	return 0;
+    
+    e = FcConfigParseExprList (doc, expr->next);
+
+    if (expr->type == XML_ELEMENT_NODE)
+    {
+	r = e;
+	l = FcConfigParseExpr (doc, expr);
+	if (!l)
+	    goto bail;
+	if (r)
+	{
+	    e = FcExprCreateOp (l, FcOpComma, r);
+	    if (!e)
+		goto bail;
+	}
+	else
+	    e = l;
+    }
+    
+    return e;
+bail:
+    if (l)
+	FcExprDestroy (l);
+    if (r)
+	FcExprDestroy (r);
+    return 0;
+}
+
+static FcEdit *
+FcConfigParseEdit (xmlDocPtr	doc,
+		   xmlNodePtr	edit)
+{
+    xmlAttrPtr	attr;
+    char	*name = 0;
+    FcOp	mode = FcOpAssign;
+    FcExpr	*e;
+    FcEdit	*ed;
+
+    for (attr = edit->properties; attr; attr = attr->next)
+    {
+	if (attr->type != XML_ATTRIBUTE_NODE)
+	    continue;
+	if (!strcmp (attr->name, "name"))
+	    name = FcConfigAttr (doc, attr);
+	else if (!strcmp (attr->name, "mode"))
+	    mode = FcConfigLexOp (FcConfigAttr (doc, attr));
+    }
+
+    e = FcConfigParseExprList (doc, edit->children);
+
+    ed = FcEditCreate (name, mode, e);
+    if (!ed)
+	FcExprDestroy (e);
+    return ed;
+}
+
+static FcBool
+FcConfigParseMatch (FcConfig	*config,
+		    xmlDocPtr	doc,
+		    xmlNodePtr	match)
+{
+    xmlNodePtr	node;
+    xmlAttrPtr	attr;
+    FcTest	*tests = 0, **prevTest = &tests, *test;
+    FcEdit	*edits = 0, **prevEdit = &edits, *edit;
+    FcMatchKind	kind;
+    FcBool	found_kind = FcFalse;
+
+    for (node = match->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (!strcmp (node->name, "test"))
+	{
+	    test = FcConfigParseTest (doc, node);
+	    if (!test)
+		break;
+	    *prevTest = test;
+	    prevTest = &test->next;
+	}
+	else if (!strcmp (node->name, "edit"))
+	{
+	    edit = FcConfigParseEdit (doc, node);
+	    if (!edit)
+		break;
+	    *prevEdit = edit;
+	    prevEdit = &edit->next;
+	}
+    }
+
+    for (attr = match->properties; attr; attr = attr->next)
+    {
+	if (attr->type != XML_ATTRIBUTE_NODE)
+	    continue;
+	if (!strcmp (attr->name, "target"))
+	{
+	    char    *target = FcConfigAttr (doc, attr);
+	    if (!target)
+	    {
+		FcConfigParseError ("Missing match target");
+		break;
+	    }
+	    else if (!strcmp (target, "pattern"))
+	    {
+		kind = FcMatchPattern;
+		found_kind = FcTrue;
+	    }
+	    else if (!strcmp (target, "font"))
+	    {
+		kind = FcMatchFont;
+		found_kind = FcTrue;
+	    }
+	}
+    }
+
+    if (node || attr || !found_kind || 
+	!FcConfigAddEdit (config, tests, edits, kind))
+    {
+	if (tests)
+	    FcTestDestroy (tests);
+	if (edits)
+	    FcEditDestroy (edits);
+	return FcFalse;
+    }
+
+    return FcTrue;
+}
+
+static FcExpr *
+FcConfigParseFamilies (xmlDocPtr    doc,
+		       xmlNodePtr   family)
+{
+    FcExpr  *next = 0, *this = 0, *expr = 0;
+    
+    if (!family)
+	return 0;
+    next = FcConfigParseFamilies (doc, family->next);
+    
+    if (family->type == XML_ELEMENT_NODE && !strcmp (family->name, "family"))
+    {
+	this = FcExprCreateString (FcConfigContent (doc, family));
+	if (!this)
+	    goto bail;
+	if (next)
+	{
+	    expr = FcExprCreateOp (this, FcOpComma, next);
+	    if (!expr)
+		goto bail;
+	}
+	else
+	    expr = this;
+    }
+    else
+	expr = next;
+    return expr;
+
+bail:
+    if (expr)
+	FcExprDestroy (expr);
+    if (this)
+	FcExprDestroy (this);
+    if (next)
+	FcExprDestroy (next);
+    return 0;
+}
+
+static FcBool
+FcConfigParseAlias (FcConfig	*config,
+		    xmlDocPtr	doc,
+		    xmlNodePtr	alias)
+{
+    xmlNodePtr	node;
+    FcExpr	*prefer = 0, *accept = 0, *def = 0;
+    FcExpr	*family;
+    FcEdit	*edit = 0, *next;
+    FcTest	*test;
+
+    for (node = alias->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (!strcmp (node->name, "family"))
+	    family = FcExprCreateString (FcConfigContent (doc, node));
+	else if (!strcmp (node->name, "prefer"))
+	    prefer = FcConfigParseFamilies (doc, node->children);
+	else if (!strcmp (node->name, "accept"))
+	    accept = FcConfigParseFamilies (doc, node->children);
+	else if (!strcmp (node->name, "default"))
+	    def = FcConfigParseFamilies (doc, node->children);
+    }
+    
+    if (prefer)
+    {
+	edit = FcEditCreate (FcConfigSaveField ("family"),
+			     FcOpPrepend,
+			     prefer);
+	if (edit)
+	    edit->next = 0;
+    }
+    if (accept)
+    {
+	next = edit;
+	edit = FcEditCreate (FcConfigSaveField ("family"),
+			     FcOpAppend,
+			     accept);
+	if (edit)
+	    edit->next = next;
+    }
+    if (def)
+    {
+	next = edit;
+	edit = FcEditCreate (FcConfigSaveField ("family"),
+			      FcOpAppendLast,
+			      def);
+	if (edit)
+	    edit->next = next;
+    }
+    if (edit)
+    {
+	test = FcTestCreate (FcQualAny,
+			     FcConfigSaveField ("family"),
+			     FcOpEqual,
+			     family);
+	if (test)
+	    FcConfigAddEdit (config, test, edit, FcMatchPattern);
+    }
+    return FcTrue;
+}
+
+FcBool
+FcConfigParse (FcConfig	    *config,
+	       xmlDocPtr    doc)
+{
+    xmlNodePtr	cur;
+    xmlNodePtr	node;
+    
+    cur = xmlDocGetRootElement (doc);
+
+    for (node = cur->children; node; node = node->next)
+    {
+	if (node->type != XML_ELEMENT_NODE)
+	    continue;
+	if (!strcmp (node->name, "dir"))
+	{
+	    if (!FcConfigParseDir (config, doc, node))
+		break;
+	}
+	else if (!strcmp (node->name, "cache"))
+	{
+	    if (!FcConfigParseCache (config, doc, node))
+		break;
+	}
+	else if (!strcmp (node->name, "include"))
+	{
+	    if (!FcConfigParseInclude (config, doc, node))
+		break;
+	}
+	else if (!strcmp (node->name, "config"))
+	{
+	    if (!FcConfigParseConfig (config, doc, node))
+		break;
+	}
+	else if (!strcmp (node->name, "match"))
+	{
+	    if (!FcConfigParseMatch (config, doc, node))
+		break;
+	}
+	else if (!strcmp (node->name, "alias"))
+	{
+	    if (!FcConfigParseAlias (config, doc, node))
+		break;
+	}
+	else
+	{
+	    FcConfigParseError ("invalid element %s", node->name);
+	    break;
+	}   
+    }
+    if (node)
+	return FcFalse;
+    return FcTrue;
+}
+
+FcBool
+FcConfigParseAndLoad (FcConfig	    *config,
+		      const char    *file,
+		      FcBool	    complain)
+{
+    xmlDocPtr	doc;
+    FcBool	ret;
+
+    doc = FcConfigLoad (file);
+    if (doc)
+    {
+	ret = FcConfigAddConfigFile (config, file);
+	if (ret)
+	    ret = FcConfigParse (config, doc);
+	xmlFreeDoc (doc);
+	return ret;
+    }
+    if (complain)
+    {
+	if (file)
+	    FcConfigParseError ("Cannot load config file \"%s\"", file);
+	else
+	    FcConfigParseError ("Cannot load default config file");
+	return FcFalse;
+    }
+    return FcTrue;
+}
diff --git a/src/fontconfig.man b/src/fontconfig.man
new file mode 100644
index 0000000..eb9915f
--- /dev/null
+++ b/src/fontconfig.man
@@ -0,0 +1,1113 @@
+.\"
+.\" $XFree86: fontconfig.man,v 1.2 2000/11/30 06:59:45 keithp Exp $
+.\"
+.\" Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 Keith Packard not be used in
+.\" advertising or publicity pertaining to distribution of the software without
+.\" specific, written prior permission.  Keith Packard makes no
+.\" representations about the suitability of this software for any purpose.  It
+.\" is provided "as is" without express or implied warranty.
+.\"
+.\" KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+.\" EVENT SHALL KEITH PACKARD 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.
+.\"
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.TH FONTCONFIG 3 "Version 1.0" "XFree86"
+
+.SH NAME
+fontconfig \- Font configuration and customization library
+
+.SH SYNOPSIS
+.nf
+.B #include <fontconfig/fontconfig.h>
+.B #include <fontconfig/fcfreetype.h>
+.B #include <fontconfig/fcxml.h>
+.fi
+.SH DESCRIPTION
+.B Fontconfig
+is a library designed to provide system-wide font configuration,
+customization and application access.
+
+.SH FUNCTIONAL OVERVIEW
+Fontconfig contains two essential modules, the configuration module which
+builds an internal configuration from XML files and the matching module
+which accepts font patterns and returns the nearest matching font.
+
+.SS FONT CONFIGURATION
+The configuration module consists of the FcConfig datatype, libxml2 and
+FcConfigParse which walks over an XML tree and ammends a configuration with
+data found within.  From an external perspective, configuration of the
+library consists of generating a valid XML tree and feeding that to
+FcConfigParse.  The only other mechanism provided to applications for
+changing the running configuration is to add fonts and directories to the
+list of application-provided font files.  
+.P
+The intent is to make font configurations relatively static, and shared by
+as many applications as possible.  It is hoped that this will lead to more
+stable font selection when passing names from one application to another.
+XML was chosen as a configuration file format because it provides a format
+which is easy for external agents to edit while retaining the correct
+structure and syntax.
+.P
+Font configuration is separate from font matching; applications needing to
+do their own matching can access the available fonts from the library and
+perform private matching.  The intent is to permit applications to pick and
+choose appropriate functionality from the library instead of forcing them to
+choose between this library and a private configuration mechanism.  The hope
+is that this will ensure that configuration of fonts for all applications
+can be centralized in one place.  Centralizing font configuration will make
+simplify and regularize font installation and customization.
+
+.SS FONT PROPERTIES
+While font patterns may contain essentially any properties, there are some
+well known properties with associated types.  Fontconfig uses some of these
+properties for font matching and font completion.  Others are provided as a
+convenience for the applications rendering mechanism.
+.sp
+.nf
+.ta 1i 2.75i 3.5i 5.5i
+.lc \(em
+Property	CPP symbol	Type	Description
+
+family	FC_FAMILY	String	Font family name
+style	FC_STYLE	String	Font style. Overrides weight and slant
+slant	FC_SLANT	Int	Italic, oblique or roman
+weight	FC_WEIGHT	Int	Light, medium, demibold, bold or black
+size	FC_SIZE	Double	Point size
+pixelsize	FC_PIXEL_SIZE	Double	Pixel size
+spacing	FC_SPACING	Int	Proportional, monospace or charcell
+foundry	FC_FOUNDRY	String	Font foundry name
+antialias	FC_ANTIALIAS	Bool	Whether glyphs can be antialiased
+hinting	FC_HINTING	Bool	Whether the rasterizer should use hinting
+verticallayout	FC_VERTICAL_LAYOUT	Bool	Use vertical layout
+globaladvance	FC_GLOBAL_ADVANCE	Bool	Use font global advance data
+file	FC_FILE	String	The filename holding the font
+index	FC_INDEX	Int	The index of the font within the file
+rasterizer	FC_RASTERIZER	String	Which rasterizer is in use
+outline	FC_OUTLINE	Bool	Whether the glyphs are outlines
+scalable	FC_SCALABLE	Bool	Whether glyphs can be scaled
+scale	FC_SCALE	Double	Scale factor for point->pixel conversions
+dpi	FC_DPI	Double	Target dots per inch
+rgba	FC_RGBA	Int	rgb, bgr, vrgb, vbgr - subpixel geometry
+minspace	FC_MINSPACE	Bool	Eliminate leading from line spacing
+charset	FC_CHARSET	CharSet	Unicode chars encoded by the font
+lang	FC_LANG	String	List of language groups this font is designed for
+.DT
+.fi
+
+.SS FONT MATCHING
+Fontconfig performs matching by measuring the distance from a provided
+pattern to all of the available fonts in the system.  The closest matching
+font is selected.  This ensures that a font will always be returned, but
+doesn't ensure that it is anything like the requested pattern.
+.P
+Font matching starts with an application constructed pattern.  The desired
+attributes of the resulting font are collected together in an FcPattern
+object.  Each property of the pattern can contain one or more values; these
+are listed in priority order; matches earlier in the list are considered
+"closer" than matches later in the list.
+.P
+The initial pattern is modified by applying the list of editing instructions
+specific to patterns found in the configuration; each consists of a match
+predicate and a set of editing operations.  They are executed in the order
+they appeared in the configuration.  Each match causes the associated
+sequence of editing operations to be applied.
+.P
+After the pattern has been edited, a sequence of default substitutions are
+performed to canonicalize the set of available properties; this avoids the
+need for the lower layers to constantly provide default values for various
+font properties during rendering.
+.P
+The canonical font pattern is finally matched against all available fonts.
+The distance from the pattern to the font is measured for each of several
+properties: foundry, charset, antialias, family, spacing, pixelsize, style,
+slant, weight, rasterizer and outline.  This list is in priority order --
+results of comparing earlier elements of this list weigh more heavily than
+later elements.
+.P
+The pattern representing that font is augmented to include any properties
+found in the pattern but not found in the font itself; this permits the
+application to pass rendering instructions or any other data through the
+matching system.  Finally, the list of editing instructions specific to
+fonts found in the configuration are applied to the pattern.  This modified
+pattern is returned to the application.
+.P
+The return value contains sufficient information to locate and rasterize the
+font, including the file name, pixel size and other rendering data.  As
+none of the information involved pertains to the FreeType library,
+applications are free to use any rasterization engine or even to take
+the identified font file and access it directly.
+.P
+The match/edit sequences in the configuration are performed in two passes
+because there are essentially two different operations necessary -- the
+first is to modify how fonts are selected; aliasing families and adding
+suitable defaults.  The second is to modify how the selected fonts are
+rasterized.  Those must apply to the selected font, not the original pattern
+as false matches will often occur.
+.SS FONT NAMES
+Fontconfig provides a textual representation for patterns that the library
+can both accept and generate.  The representation is in three parts, first a
+list of family names, second a list of point sizes and finally a list of
+additional properties:
+.nf
+	<families>-<point sizes>:<name1>=<values1>:<name2>=<values2>...
+.fi
+Values in a list are separated with commas.  The name needn't include either
+families or point sizes; they can be elided.  In addition, there are
+symbolic constants that simultaneously indicate both a name and a value.
+Here are some examples:
+.sp
+.nf
+.ta 1i 3i
+	Times-12	12 point Times Roman
+	Times-12:bold	12 point Times Bold
+	Courier:italic	Courier Italic in the default size
+	Monospace:matrix=1 .1 0 1	The users preferred monospace font
+		with artificial obliquing
+.fi
+.DT
+
+.SH DATATYPES
+
+.TP
+.B FcChar8
+.TQ
+.B FcChar16
+.TQ
+.B FcChar32
+.TQ
+.B FcBool
+These are primitive datatypes; the FcChar* types hold precisely the number
+of bits stated (if supported by the C implementation).  FcBool holds
+one of two CPP symbols: FcFalse or FcTrue.
+
+.TP
+.B FcMatrix
+An FcMatrix holds an affine transformation, usually used to reshape glyphs.
+A small set of matrix operations are provided to manipulate these.
+.sp
+.nf
+	typedef struct _FcMatrix {
+		double xx, xy, yx, yy;
+	} FcMatrix;
+.fi
+
+.TP
+.B FcCharSet
+An FcCharSet is an abstract type that holds the set of encoded unicode chars
+in a font.  Operations to build and compare these sets are provided.
+
+.TP
+.B FcType
+Tags the kind of data stored in an FcValue.
+
+.TP
+.B FcValue
+An FcValue object holds a single value with one of a number of different
+types.  The 'type' tag indicates which member is valid.
+.sp
+.nf
+	typedef struct _FcValue {
+		FcType type;
+		union {
+			const FcChar8 *s;
+			int i;
+			FcBool b;
+			double d;
+			const FcMatrix *m;
+			const FcCharSet *c;
+		} u;
+	} FcValue;
+.fi
+.P
+.ta 1i 2i 3i 4i
+.nf
+.lc \(em
+	type	Union member	Datatype
+	
+	FcTypeVoid	(none)	(none)
+	FcTypeInteger	i	int
+	FcTypeDouble	d	double
+	FcTypeString	s	char *
+	FcTypeBool	b	b
+	FcTypeMatrix	m	FcMatrix *
+	FcTypeCharSet	c	FcCharSet *
+.fi
+.DT
+.TP
+.B FcPattern
+holds a set of names with associated value lists; each name refers to a
+property of a font.  FcPatterns are used as inputs to the matching code as
+well as holding information about specific fonts.  Each property can hold
+one or more values; conventionally all of the same type, although the
+interface doesn't demand that.
+
+.TP
+.B FcFontSet
+.sp
+.nf
+	typedef struct _FcFontSet {
+		int nfont;
+		int sfont;
+		FcPattern **fonts;
+	} FcFontSet;
+.fi	
+An FcFontSet contains a list of FcPatterns.  Internally fontconfig uses this
+data structure to hold sets of fonts.  Externally, fontconfig returns the
+results of listing fonts in this format.  'nfont' holds the number of
+patterns in the 'fonts' array; 'sfont' is used to indicate the size of that
+array.
+
+.TP
+.B FcObjectSet
+.sp
+.nf
+	typedef struct _FcObjectSet {
+		int nobject;
+		int sobject;
+		const char **objects;
+	} FcObjectSet;
+.fi
+holds a set of names and is used to specify which fields from fonts are
+placed in the the list of returned patterns when listing fonts.
+
+.TP
+.B FcBlanks
+holds a list of Unicode chars which are expected to be blank; unexpectedly
+blank chars are assumed to be invalid and are elided from the charset
+associated with the font.
+
+.TP
+.B FcFileCache
+holds the per-user cache information for use while loading the font
+database. This is built automatically for the current configuration when
+that is loaded.  Applications must always pass '0' when one is requested.
+
+.TP
+.B FcConfig
+holds a complete configuration of the library; there is one default
+configuration, other can be constructed from XML data structures.  All
+public entry points that need global data can take an optional FcConfig*
+argument; passing 0 uses the default configuration.  FcConfig objects hold two
+sets of fonts, the first contains those specified by the configuration, the
+second set holds those added by the application at run-time.  Interfaces
+that need to reference a particulat set use one of the FcSetName enumerated
+values.
+
+.TP
+.B FcSetName
+Specifies one of the two sets of fonts available in a configuration;
+FcSetSystem for those fonts specified in the configuration and
+FcSetApplication which holds fonts provided by the application.
+
+.TP
+.B FcResult
+Used as a return type for functions manipulating FcPattern objects.
+.P
+.ta 1i 3i 4i
+.lc \(em
+	Result code	Meaning
+.br
+	
+.br
+	FcResultMatch	Object exists with the specified ID
+.br
+	FcResultNoMatch	Object doesn't exist at all
+.br
+	FcResultTypeMismatch	Object exists, but the type doesn't match
+.br
+	FcResultNoId	Object exists, but has fewer values than specified
+.br
+.DT
+
+.SH FUNCTIONS
+
+.SS FcMatrix
+FcMatrix structures hold an affine transformation in matrix form.
+.TP
+#define FcMatrixInit(m)	((m)->xx = (m)->yy = 1, (m)->xy = (m)->yx = 0)
+Initializes a matrix to the identify transformation.
+
+.TP
+FcMatrix *FcMatrixCopy (const FcMatrix *mat)
+Allocates a new FcMatrix and copies 'mat' into it.
+
+.TP
+FcBool FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2)
+Returns FcTrue if 'mat1' and 'mat2' are equal, else FcFalse.
+
+.TP
+void FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b)
+Multiplies 'a' and 'b' together, placing the result in
+'result'.  'result' may refer to the sam matrix as either 'a' or 'b'.
+
+.TP
+void FcMatrixRotate (FcMatrix *m, double c, double s)
+If 'c' is cos(angle) and 's' is sin(angle), FcMatrixRotate rotates the
+matrix by 'angle'.
+
+.TP
+void FcMatrixScale (FcMatrix *m, double sx, double sy)
+Scales 'm' by 'sx' in the horizontal dimension and 'sy' in the
+vertical dimension.
+
+.TP
+void FcMatrixShear (FcMatrix *m, double sh, double sv)
+Shears 'm' by 'sh' in the horizontal direction and 'sv' in the
+vertical direction.
+
+.SS FcCharSet
+An FcCharSet is a boolean array indicating a set of unicode chars.  Those
+associated with a font are marked constant and cannot be edited.
+FcCharSets may be reference counted internally to reduce memory consumption;
+this may be visible to applications as the result of FcCharSetCopy may
+return it's argument, and that CharSet may remain unmodifiable.
+
+.TP
+FcCharSet *FcCharSetCreate (void)
+Creates an empty FcCharSet object.
+
+.TP
+void FcCharSetDestroy (FcCharSet *fcs)
+Frees an FcCharSet object.
+
+.TP
+FcBool FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
+Adds a single unicode char to the set, returning FcFalse on
+failure, either as a result of a constant set or from running out of memory.
+
+.TP
+FcCharSet *FcCharSetCopy (FcCharSet *src)
+Makes a copy of 'src'; note that this may not actually do anything more than
+increment the reference count on 'src'.
+
+.TP
+FcBool FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
+Returns whether 'a' and 'b' contain the same set of unicode chars.
+
+.TP
+FcCharSet *FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b)
+Returns a set including only those chars found in both 'a' and 'b'.
+
+.TP
+FcCharSet *FcCharSetUnion (const FcCharSet *a, const FcCharSet *b);
+Returns a set including only those chars found in either 'a' or 'b'.
+
+.TP 
+FcCharSet *FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b)
+Returns a set including only those chars found in 'a' but not 'b'.
+
+.TP
+FcBool FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4)
+Returns whether 'fcs' contains the char 'ucs4'.
+
+.TP
+FcChar32 FcCharSetCount (const FcCharSet *a)
+Returns the total number of unicode chars in 'a'.
+
+.TP
+FcChar32 FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b)
+Returns the number of chars that are in both 'a' and 'b'.
+
+.TP
+FcChar32 FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
+Returns the number of chars that are in 'a' but not in 'b'.
+
+.SS FcValue
+FcValue is a structure containing a type tag and a union of all possible
+datatypes.  The tag is an enum of type 
+.B FcType
+and is intended to provide a measure of run-time
+typechecking, although that depends on careful programming.
+
+.TP
+void FcValueDestroy (FcValue v)
+Frees any memory referenced by `v'.  Values of type FcTypeString,
+FcTypeMatrix and FcTypeCharSet reference memory, the other types do not.
+
+.TP
+FcValue FcValueSave (FcValue v)
+Returns a copy of `v' duplicating any object referenced by it so that `v'
+may be safely destroyed without harming the new value.
+
+.SS FcPattern
+An FcPattern is an opaque type that holds both patterns to match against the
+available fonts, as well as the information about each font.
+
+.TP
+FcPattern *FcPatternCreate (void)
+Creates a pattern with no properties; used to build patterns from scratch.
+
+.TP
+void FcPatternDestroy (FcPattern *p)
+Destroys a pattern, in the process destroying all related values.
+
+.TP
+FcBool FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
+Adds a single value to the list of values associated with the property named
+`object'.  If `append' is FcTrue, the value is added at the end of any
+existing list, otherwise it is inserted at the begining.  `value' is saved
+(with FcValueSave) when inserted into the pattern so that the library
+retains no reference to any application-supplied data structure.
+
+.TP
+FcBool FcPatternAddInteger (FcPattern *p, const char *object, int i)
+.TQ
+FcBool FcPatternAddDouble (FcPattern *p, const char *object, double d)
+.TQ
+FcBool FcPatternAddString (FcPattern *p, const char *object, const char *s)
+.TQ
+FcBool FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
+.TQ
+FcBool FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
+.TQ
+FcBool FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
+These are all convenience functions that insert objects of the specified
+type into the pattern.  Use these in preference to FcPatternAdd as they
+will provide compile-time typechecking.  These all append values to
+any existing list of values.
+
+.TP
+FcResult FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
+Returns in `v' the `id'th value associated with the property `object'.
+The value returned is not a copy, but rather refers to the data stored
+within the pattern directly.  Applications must not free this value.
+
+.TP
+FcResult FcPatternGetInteger (FcPattern *p, const char *object, int n, int *i);
+.TQ
+FcResult FcPatternGetDouble (FcPattern *p, const char *object, int n, double *d);
+.TQ
+FcResult FcPatternGetString (FcPattern *p, const char *object, int n, char **const s);
+.TQ
+FcResult FcPatternGetMatrix (FcPattern *p, const char *object, int n, FcMatrix **s);
+.TQ
+FcResult FcPatternGetCharSet (FcPattern *p, const char *object, int n, FcCharSet **c);
+.TQ
+FcResult FcPatternGetBool (FcPattern *p, const char *object, int n, FcBool *b);
+These are convenience functions that call FcPatternGet and verify that the
+returned data is of the expected type. They return FcResultTypeMismatch if
+this is not the case.  Note that these (like FcPatternGet) do not make a
+copy of any data structure referenced by the return value.  Use these
+in preference to FcPatternGet to provide compile-time typechecking.
+
+.TP
+FcPattern *FcPatternBuild (FcPattern *orig, ...);
+.TQ
+FcPattern *FcPatternVaBuild (FcPattern *orig, va_list va)
+Builds a pattern using a list of objects, types and values.  Each
+value to be entered in the pattern is specified with three arguments:
+.IP
+1. Object name, a string describing the property to be added.
+.IP
+2. Object type, one of the FcType enumerated values
+.IP
+3. Value, not an FcValue, but the raw type as passed to any of the
+FcPatternAdd<type> functions.  Must match the type of the second argument.
+.IP
+The argument list is terminated by a null object name, no object type nor
+value need be passed for this.  The values are added to `pattern', if
+`pattern' is null, a new pattern is created.  In either case, the pattern is
+returned. Example:
+.RS
+.IP
+pattern = FcPatternBuild (0, FC_FAMILY, FtTypeString, "Times", (char *) 0);
+.RE
+.IP
+FcPatternVaBuild is used when the arguments are already in the form of a
+varargs value.
+
+.TP
+FcBool FcPatternDel (FcPattern *p, const char *object)
+Deletes all values associated with the property `object', returning 
+whether the property existed or not.
+
+.TP
+void FcPatternPrint (FcPattern *p)
+Prints an easily readable version of the pattern to stdout.  There is
+no provision for reparsing data in this format, it's just for diagnostics
+and debugging.
+
+.TP
+void FcDefaultSubstitute (FcPattern *pattern)
+Supplies default values for underspecified font patterns:
+.RS
+.IP \(bu 
+Patterns without a specified style or weight are set to Medium
+.IP \(bu
+Patterns without a specified style or slant are set to Roman
+.IP \(bu
+Patterns without a specified pixel size are given one computed from
+any specified point size (default 12), dpi (default 75) and scale (default
+1).
+.RE
+
+.TP
+FcPattern *FcNameParse (const char *name)
+Converts 'name' from the standard text format described above into a pattern.
+
+.TP
+FcChar8 *FcNameUnparse (FcPattern *pat)
+Converts the given pattern into the standard text format described above.
+The return value is not static, but instead refers to newly allocated memory
+which should be freed by the caller.
+
+.SS FcFontSet
+An FcFontSet simply holds a list of patterns; these are used to return the
+results of listing available fonts.
+.TP
+FcFontSet *FcFontSetCreate (void)
+Creates an empty font set.
+
+.TP
+void FcFontSetDestroy (FcFontSet *s);
+Destroys a font set.  Note that this destroys any referenced patterns as
+well.
+
+.TP 
+FcBool FcFontSetAdd (FcFontSet *s, FcPattern *font)
+Adds a pattern to a font set.  Note that the pattern is not copied before
+being inserted into the set.
+
+.SS FcObjectSet
+An FcObjectSet holds a list of pattern property names; it is used to
+indiciate which properties are to be returned in the patterns from
+FcFontList.
+
+.TP
+FcObjectSet *FcObjectSetCreate (void)
+Creates an empty set.
+
+.TP
+FcBool FcObjectSetAdd (FcObjectSet *os, const char *object)
+Adds a proprety name to the set.
+
+.TP
+void FcObjectSetDestroy (FcObjectSet *os)
+Destroys an object set.
+
+
+.TP
+FcObjectSet *FcObjectSetBuild (const char *first, ...)
+.TQ
+FcObjectSet *FcObjectSetVaBuild (const char *first, va_list va)
+These build an object set from a null-terminated list of property names.
+
+.SS FcBlanks
+An FcBlanks object holds a list of Unicode chars which are expected to
+be blank when drawn.  When scanning new fonts, any glyphs which are
+empty and not in this list will be assumed to be broken and not placed in
+the FcCharSet associated with the font.  This provides a significantly more
+accurate CharSet for applications.
+
+.TP
+FcBlanks *FcBlanksCreate (void)
+Creates an empty FcBlanks object.
+
+.TP
+void FcBlanksDestroy (FcBlanks *b)
+Destroys an FcBlanks object, freeing any associated memory.
+
+.TP
+FcBool FcBlanksAdd (FcBlanks *b, FcChar32 ucs4)
+Adds a single character to an FcBlanks object, returning FcFalse
+if this process ran out of memory.
+
+.TP
+FcBool FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4)
+Returns whether the specified FcBlanks object contains the indicated Unicode
+value.
+
+.SS FcConfig
+An FcConfig object holds the internal representation of a configuration.
+There is a default configuration which applications may use by passing 0 to
+any function using the data within an FcConfig.
+
+.TP
+FcConfig *FcConfigCreate (void)
+Creates an empty configuration.
+
+.TP 
+void FcConfigDestroy (FcConfig *config)
+Destroys a configuration and any data associated with it.  Note that calling
+this function with the return from FcConfigGetCurrent will place the library
+in an indeterminate state.
+
+.TP
+FcBool FcConfigSetCurrent (FcConfig *config)
+Sets the current default configuration to 'config'.  Implicitly calls
+FcConfigBuildFonts if necessary, returning FcFalse if that call fails.
+
+.TP
+FcConfig *FcConfigGetCurrent (void)
+Returns the current default configuration.
+
+.TP
+FcBool FcConfigBuildFonts (FcConfig *config)
+Builds the set of available fonts for the given configuration.  Note that
+any changes to the configuration after this call have indeterminate effects.
+Returns FcFalse if this operation runs out of memory.
+
+.TP
+char **FcConfigGetDirs (FcConfig *config)
+Returns the list of font directories specified in 'config'.
+
+.TP 
+char **FcConfigGetConfigFiles (FcConfig *config)
+Returns the list of known configuration files used to generate 'config'.
+Note that this will not include any configuration done with FcConfigParse.
+
+.TP
+char *FcConfigGetCache (FcConfig *config)
+Returns the name of the file used to store per-user font information.
+
+.TP
+FcFontSet *FcConfigGetFonts (FcConfig *config, FcSetName set)
+Returns one of the two sets of fonts from the configuration as specified 
+by 'set'.
+
+.TP
+FcBlanks *FcConfigGetBlanks (FcConfig *config)
+Returns the FcBlanks object associated with the given configuration, if no
+blanks were present in the configuration, this function will return 0.
+
+.TP
+FcBool FcConfigAppFontAddFile (FcConfig *config, const char *file)
+Adds an application-specific font to the configuration.
+
+.TP 
+FcBool FcConfigAppFontAddDir (FcConfig *config, const char *dir)
+Scans the specified directory for fonts, adding each one found to the
+application-specific set of fonts.
+
+.TP 
+void FcConfigAppFontClear (FcConfig *config)
+Clears the set of application-specific fonts.
+
+.TP
+FcBool FcConfigSubstitute (FcConfig *config, FcPattern *p, FcMatchKind kind)
+Performs the sequence of pattern modification operations, if 'kind' is
+FcMatchPattern, then those tagged as pattern operations are applied, else 
+if 'kind' is FcMatchFont, those tagged as font operations are applied.
+
+.TP
+FcPattern *FcFontMatch (FcConfig *config, FcPattern *p, FcResult *result)
+Returns the font in 'config' most close matching 'p'.  This function
+should be called only after FcConfigSubstitute and FcDefaultSubstitute have
+been called; otherwise the results will be less useful.
+
+.TP
+FcFontSet *FcFontList (FcConfig *config, FcPattern *p, FcObjectSet *os)
+Selects fonts matching 'p', creates patterns from those fonts containing
+only the objects in 'os' and returns the set of unique such patterns.
+
+.TP
+char *FcConfigFilename (const char *name)
+Given the specified external entity name, return the associated filename.
+This provides applications a way to convert various configuration file
+references into filename form. 
+.P
+A null or empty 'name' indicates that the default configuration file should
+be used; which file this references can be overridden with the
+FC_CONFIG_FILE environment variable.  Next, if the name starts with '~', it
+refers to a file in the current users home directory.  Otherwise if the name
+doesn't start with '/', it refers to a file in the default configuration
+directory; the built-in default directory can be overridden with the
+FC_CONFIG_DIR environment variable.
+
+.SS Initialization
+These functions provide some control over how the library is initialized.
+
+.TP
+FcBool FcInitConfig (void)
+Initializes the default configuration using the default configuration file
+
+.TP
+FcBool FcInitFonts (void)
+Initializes the set of fonts available in the default configuration
+
+.TP
+FcBool FcInit (void)
+Calls FcInitConfig and FcInitFonts to completely initialize the default
+configuration.
+
+.SS FreeType specific functions
+.nf
+.B #include <fontconfig/fcfreetype.h>
+.fi
+While the fontconfig library doesn't insist that FreeType be used as the
+rasterization mechanism for fonts, it does provide some convenience
+functions.
+
+.TP
+FT_UInt FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
+Maps a Unicode char to a glyph index.  This function uses information from
+several possible underlying encoding tables to work around broken fonts.
+As a result, this function isn't designed to be used in performance
+sensitive areas; results from this function are intended to be cached by
+higher level functions.
+
+.TP
+FcCharSet *FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks) Scans a
+FreeType face and returns the set of encoded Unicode chars.  This scans
+several encoding tables to build as complete a list as possible.  If
+'blanks' is not 0, the glyphs in the font are examined and any blank glyphs
+not in 'blanks' are not placed in the returned FcCharSet.
+
+.TP
+FcPattern *FcFreeTypeQuery (const char *file, int id, FcBlanks *blanks, int *count)
+Constructs a pattern representing the 'id'th font in 'file'.  The number
+of fonts in 'file' is returned in 'count'.
+
+.SS XML specific functions
+.nf
+.B #include <fontconfig/fcxml.h>
+.fi
+These functions expose the libxml2 datatypes used for font configuration.
+
+.TP
+xmlDocPtr FcConfigLoad (const char *file)
+Loads a configuration file mapping 'file' into a filename with
+FcConfigFilename.  This doesn't load a complete configuration as any
+include files referenced from 'file' will not be loaded.
+
+.TP
+FcBool FcConfigParse (FcConfig *config, xmlDocPtr doc)
+Walks the given configuration and constructs the internal representation in
+'config'.  Any include files referenced from within 'doc' will be loaded
+with FcConfigLoad and also parsed.
+
+.SS File and Directory routines
+
+.TP
+FcBool FcFileScan (FcFontSet *set, FcFileCache *cache, FcBlanks *blanks, const char *file, FcBool force)
+Scans a single file and adds all fonts found to 'set'.  If 'force' is FcTrue,
+then the file is scanned even if associated information is found in 'cache'.
+
+.TP
+FcBool FcDirScan (FcFontSet *set, FcFileCache *cache, FcBlanks *blanks, const char *dir, FcBool force)
+Scans an entire directory and adds all fonts found to 'set'.  If 'force' is
+FcTrue, then the directory and all files within it are scanned even if
+information is present in the per-directory cache file or 'cache'.
+
+.TP
+FcBool FcDirSave (FcFontSet *set, const char *dir)
+Creates the per-directory cache file for 'dir' and populates it with the
+fonts in 'set'.
+
+.SS String utilities
+
+.TP
+int FcUtf8ToUcs4 (FcChar8 *src, FcChar32 *dst, int len)
+Converts the next Unicode char from 'src' into 'dst' and returns the number
+of bytes containing the char.  'src' nust be at least 'len' bytes long.
+
+.TP
+FcBool FcUtf8Len (FcChar8 *string, int len, int *nchar, int *wchar)
+Counts the number of Unicode chars in 'len' bytes of 'string'.  Places that
+count in 'nchar'.  'wchar' contains 1, 2 or 4 depending on the number of
+bytes needed to hold the largest unicode char counted.  The return value
+indicates whether 'string' is a well-formed UTF8 string.
+
+.TP
+char *FcStrCopy (const char *s)
+Allocates memory, copies 's' and returns the resulting buffer.  Yes, this is
+'strdup', but that function isn't available on every platform.
+
+.TP
+int FcStrCmpIgnoreCase (const char *s1, const char *s2)
+Returns the usual <0, 0, >0 result of comparing 's1' and 's2'.  This test
+is case-insensitive in the ASCII range and will operate properly with UTF8
+encoded strings, although it does not check for well formed strings.
+
+.SH CONFIGURATION FILE FORMAT
+Configuration files for fontconfig are stored in XML format; this
+format makes external configuration tools easier to write and ensures that
+they will generate syntactically correct configuration files.  As XML
+files are plain text, they can also be manipulated by the expert user using
+a text editor.
+.P
+The fontconfig document type definition resides in the external entity
+"fonts.dtd"; this is normally stored in the default font configuration
+directory (/etc/fonts).  Each configuration file should contain the
+following structure:
+.sp
+.nf
+	<?xml version="1.0"?>
+	<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+	<fontconfig>
+	...
+	</fontconfig>
+.fi
+.P
+.SS <fontconfig>
+This is the top level element for a font configuration and can contain
+<dir>, <cache>, <include>, <match> and <alias> elements in any order.
+
+.SS <dir>
+This element contains a directory name which will be scanned for font files
+to include in the set of available fonts.
+
+.SS <cache>
+This element contains a file name for the per-user cache of font
+information.  If it starts with '~', it refers to a file in the users
+home directory.  This file is used to hold information about fonts that
+isn't present in the per-directory cache files.  It is automatically
+maintained by the fontconfig library.  The default for this file 
+is ``~/.fonts.cache''.
+
+.SS <include ignore_missing="no">
+This element contains the name of an additional configuration file.  When
+the XML datatype is traversed by FcConfigParse, the contents of the file
+will also be incorporated into the configuration by passing the filename to
+FcConfigLoadAndParse.  If 'ignore_missing' is set to "yes" instead of the
+default "no", a missing file will elicit no warning message from the library.
+
+.SS <match target="pattern">
+This element holds first a (possibly empty) list of tests and then a
+(possibly empty) list of edits.  Patterns which match all of the tests are
+subjected to all the edits.  If 'target' is set to "font" instead of the
+default "pattern", then this element applies to the font name resulting from
+a match rather than a font pattern to be matched.
+
+.SS <test qual="any" name="property" compare="eq">
+This element contains a single value which is compared with the pattern
+property "property" (substitute any of the property names seen above).
+'compare' can be one of "eq", "not_eq", "less", "less_eq", "more", or
+"more_eq".  'qual' may either be the default, "any", in which case the match
+succeeds if any value associated with the property matches the test value, or
+"all", in which case all of the values associated with the property must
+match the test value.
+
+.SS <edit name="property" mode="assign">
+This element contains a list of expression elements (any of the value or
+operator elements).  The expression elements are evaluated at run-time and
+modify the property "property".  The modification depends on whether
+"property" was matched by one of the associated <test> elements, if so, the
+modification may affect the first matched value.  'mode' is one of:
+.nf
+.RS
+.ta 1i 3i 5i
+Mode	Operation with match	Operation without match
+
+"assign"	Replace matching value	Replace all values
+"assign_replace"	Replace all values	Replace all values
+"prepend"	Insert before matching value	Insert at head of list
+"prepend_first"	Insert at head of list	Insert at head of list
+"append"	Append after matching value	Append at end of list
+"append_last"	Append at end of list	Append at end of list
+.RE
+.DT
+.fi
+.SS <int>
+.SS <double>
+.SS <string>
+.SS <bool>
+These elements hold a single value of the indicated type.  <bool> elements
+hold either true or false.
+.SS <matrix>
+This element holds the four <double> elements of an affine transformation.
+.SS <name>
+Holds a property name.  Evaluates to the first value from the property of
+the font, not the pattern.
+.SS <const>
+Holds the name of a constant; these are always integers and serve as
+symbolic names for common font values:
+.RS
+.sp
+.nf
+.ta 1i 2i 3i
+.lc \(em
+Constant	Property	CPP symbol
+
+light	weight	FC_WEIGHT_LIGHT
+medium	weight	FC_WEIGHT_MEDIUM
+demibold	weight	FC_WEIGHT_DEMIBOLD
+bold	weight	FC_WEIGHT_BOLD
+black	weight	FC_WEIGHT_BLACK
+roman	slant	FC_SLANT_ROMAN
+italic	slant	FC_SLANT_ITALIC
+oblique	slant	FC_SLANT_OBLIQUE
+proportional	spacing	FC_PROPORTIONAL
+mono	spacing	FC_MONO
+charcell	spacing	FC_CHARCELL
+rgb	rgba	FC_RGBA_RGB
+bgr	rgba	FC_RGBA_BGR
+vrgb	rgba	FC_RGBA_VRGB
+vbgr	rgba	FC_RGBA_VBGR
+.DT
+.fi
+.RE
+.SS <or>
+.SS <and>
+.SS <plus>
+.SS <minus>
+.SS <times>
+.SS <divide>
+These elements perform the specified operation on a list of expression
+elements.  <or> and <and> are boolean, not bitwise.
+.SS <eq>
+.SS <not_eq>
+.SS <less>
+.SS <less_eq>
+.SS <more>
+.SS <more_eq>
+These elements compare two values, producing a boolean result.
+.SS <not>
+Inverts the boolean sense of its one expression element
+.SS <if>
+This element takes three expression elements; if the value of the first is
+true, it produces the value of the second, otherwise it produces the value
+of the third.
+.SS <alias>
+Alias elements provide a shorthand notation for the set of common match
+operations needed to substitute one font family for another.  They contain a
+<family> element followed by optional <prefer>, <accept> and <default>
+elements.  Fonts matching the <family> element are edited to prepend the
+list of <prefer>ed families before the matching <family>, append the
+<accept>able familys after the matching <family> and append the <default>
+families to the end of the family list.
+.SS <family>
+Holds a single font family name
+.SS <prefer>
+.SS <accept>
+.SS <default>
+These hold a list of <family> elements to be used by the <alias> element.
+.SH EXAMPLE CONFIGURATION FILE
+.SS System configuration file
+This is an example of a system-wide configuration file
+.sp
+.nf
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<!-- /etc/fonts/fonts.conf file to configure system font access -->
+<fontconfig>
+<!-- 
+	Find fonts in these directories
+-->
+<dir>/usr/X11R6/lib/X11/fonts/truetype</dir>
+<dir>/usr/X11R6/lib/X11/fonts/Type1</dir>
+
+<!--
+	Accept deprecated 'mono' alias, replacing it with 'monospace'
+-->
+<match target="pattern">
+	<test qual="any" name="family"><string>mono</string></test>
+	<edit name="family" mode="assign"><string>monospace</string></edit>
+</match>
+
+<!--
+	Names not including any well known alias are given 'sans'
+-->
+<match target="pattern">
+	<test qual="all" name="family" mode="not_eq">sans</test>
+	<test qual="all" name="family" mode="not_eq">serif</test>
+	<test qual="all" name="family" mode="not_eq">monospace</test>
+	<edit name="family" mode="append_last"><string>sans</string></edit>
+</match>
+
+<!--
+	Load per-user customization file, but don't complain
+	if it doesn't exist
+-->
+<include ignore_missing="yes">~/.fonts.conf</include>
+
+<!--
+	Alias well known font names to available TrueType fonts.
+	These substitute TrueType faces for similar Type1
+	faces to improve screen appearance.
+-->
+<alias>
+	<family>Times</family>
+	<prefer><family>Times New Roman</family></prefer>
+	<default><family>serif</family></default>
+</alias>
+<alias>
+	<family>Helvetica</family>
+	<prefer><family>Verdana</family></prefer>
+	<default><family>sans</family></default>
+</alias>
+<alias>
+	<family>Courier</family>
+	<prefer><family>Courier New</family></prefer>
+	<default><family>monospace</family></default>
+</alias>
+
+<!--
+	Provide required aliases for standard names
+	Do these after the users configuration file so that
+	any aliases there are used preferentially
+-->
+<alias>
+	<family>serif</family>
+	<prefer><family>Times New Roman</family></prefer>
+</alias>
+<alias>
+	<family>sans</family>
+	<prefer><family>Verdana</family></prefer>
+</alias>
+<alias>
+	<family>monospace</family>
+	<prefer><family>Andale Mono</family></prefer>
+</alias>
+</fontconfig>
+.fi
+.SS User configuration file
+This is an example of a per-user configuration file that lives in
+~/.fonts.conf
+.sp
+.nf
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<!-- ~/.fonts.conf for per-user font configuration -->
+<fontconfig>
+
+<!--
+	Private font directory
+-->
+<dir>~/misc/fonts</dir>
+
+<!--
+	use rgb sub-pixel ordering to improve glyph appearance on
+	LCD screens.  Changes affecting rendering, but not matching
+	should always use target="font".
+-->
+<match target="font">
+	<edit name="rgba" mode="assign"><const>rgb</const></edit>
+</match>
+</fontconfig>
+.fi
+.SH FILES
+.B fonts.conf
+contains configuration information for the fontconfig library
+consisting of directories to look at for font information as well as
+instructions on editing program specified font patterns before attempting to
+match the available fonts.  It is in xml format.
+
+.B fonts.dtd 
+is a DTD that describes the format of the configuration files.
+
+.B ~/.fonts.conf
+is the conventional location for per-user font configuration, although the
+actual location is specified in the global fonts.conf file.
+
+.B ~/.fonts.cache
+is the conventional repository of font information that isn't found in the
+per-directory caches.  This file is automatically maintained by fontconfig.
+
+.SH AUTHOR
+Keith Packard, member of the XFree86 Project, Inc.