--- xorg-server-1.4.2.orig/debian/rules
+++ xorg-server-1.4.2/debian/rules
@@ -0,0 +1,216 @@
+#!/usr/bin/make -f
+# debian/rules for the Debian xorg-server package.
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>
+# Copyright © 2005 Daniel Stone <daniel@fooishbar.org>
+# Copyright © 2005 David Nusinow <dnusinow@debian.org>
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+include debian/xsfbs/xsfbs.mk
+
+CFLAGS = -Wall -g
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+	INSTALL_PROGRAM += -s
+endif
+CPPFLAGS += -DPRE_RELEASE=0
+
+DEB_HOST_ARCH      ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+DEB_HOST_ARCH_OS   ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+	confflags += --build=$(DEB_HOST_GNU_TYPE)
+else
+	confflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+endif
+
+#ifeq ($(DEB_HOST_ARCH_OS), linux)
+#	build_xfbdev = --enable-xfbdev
+#else
+	build_xfbdev = --disable-xfbdev
+#endif
+
+BUILD_XPRINT = true
+ifeq ($(BUILD_XPRINT), true)
+	confflags += --enable-xprint
+else
+	confflags += --disable-xprint
+endif
+
+INSTALL=/usr/bin/install
+
+VENDOR = $(shell lsb_release -i -s)
+
+# disable-static is so we don't get libfoo.a for modules.  now if only we could
+# kill the .las.
+confflags += --disable-static \
+	     --enable-xorg \
+	     --with-mesa-source=/usr/share/mesa-source \
+	     --with-default-font-path="/usr/share/fonts/X11/misc,/usr/share/fonts/X11/cyrillic,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType" \
+	     --with-serverconfig-path=/etc/X11/xserver \
+	     --with-rgb-path=/etc/X11/rgb \
+	     --enable-xtrap \
+	     --enable-dmx \
+	     --enable-vfb \
+	     --enable-kdrive \
+	     --enable-xephyr \
+	     --disable-xsdl \
+	     --disable-xfake \
+	     $(build_xfbdev) \
+	     --disable-kdrive-vesa \
+	     --disable-lbx \
+	     --enable-freetype \
+	     --disable-xorgconfig \
+	     --disable-xorgcfg \
+	     --with-xkb-path=/usr/share/X11/xkb \
+	     --with-xkb-output=/var/lib/xkb \
+	     --enable-xfree86-utils \
+	     --with-os-name="$(shell uname)" \
+	     --with-os-vendor="$(VENDOR) ($(SOURCE_NAME) $(SOURCE_VERSION))" \
+	     --with-int10=x86emu \
+	     --disable-type1
+
+build: patch build-stamp
+build-stamp: 
+	dh_testdir
+	
+	mkdir -p obj-$(DEB_BUILD_GNU_TYPE)/GL
+	cd obj-$(DEB_BUILD_GNU_TYPE) && \
+	../configure --prefix=/usr --mandir=\$${prefix}/share/man \
+	             --infodir=\$${prefix}/share/info --sysconfdir=/etc \
+	             --localstatedir=/var $(confflags) CFLAGS="$(CFLAGS)" \
+	             CPPFLAGS="$(CPPFLAGS)"
+	cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE)
+	
+	touch build-stamp
+
+clean: xsfclean
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp
+	
+	rm -f config.cache config.log config.status
+	rm -f */config.cache */config.log */config.status
+	rm -f conftest* */conftest*
+	rm -rf autom4te.cache */autom4te.cache
+	rm -rf obj-*
+	# generated file, left over in the upstream tarball
+	# see https://bugs.freedesktop.org/show_bug.cgi?id=9277
+	rm -f hw/xfree86/common/xf86Build.h
+	# more generated files
+	rm -f include/dix-config.h include/do-not-use-config.h \
+		include/xorg-config.h include/xorg-server.h
+	# needed for git snapshots
+	chmod +x configure
+	
+	dh_clean
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs
+	
+	cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+	
+	# oh, yuck.
+	find $(CURDIR)/debian/tmp/usr/lib/xorg -type f -name '*.la' | \
+	  xargs rm -f
+	
+	install -m 755 debian/local/xvfb-run debian/tmp/usr/bin
+	install debian/local/xvfb-run.1 debian/tmp/usr/share/man/man1
+	
+#	# something funny going on with Xprinters, will have to sort it out upstream
+#	mv debian/tmp/usr/lib/X11/xserver/C/print/Xprinters.ghostscript debian/tmp/usr/lib/X11/xserver/C/print/Xprinters
+
+
+# stub to start building deb files, used by binary-indep and binary-arch
+binary-initial:
+	dh_testdir
+	dh_testroot
+
+# stub to build deb files, used by binary-indep and binary-arch
+# (cf. /usr/share/debhelper/dh_make/debianm/rules)
+binary-deb:
+	dh_compress
+	dh_fixperms
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	$(MAKE) -f debian/rules DH_OPTIONS=-a binary-initial
+	
+	dh_installdocs -a
+	dh_installchangelogs -a ChangeLog
+	dh_install -a --sourcedir=debian/tmp --list-missing -Xusr/share/man/man1/Xprt -Xusr/lib/X11/xserver -Xetc/X11/Xsession.d/92xprint-xpserverlist
+	$(INSTALL) -d $(CURDIR)/debian/xserver-xorg-dev/usr/share/xserver-xorg
+	$(INSTALL) -m644 $(CURDIR)/debian/videoabiver \
+	           $(CURDIR)/debian/xserver-xorg-dev/usr/share/xserver-xorg/videoabiver
+	$(INSTALL) -m644 $(CURDIR)/debian/inputabiver \
+	           $(CURDIR)/debian/xserver-xorg-dev/usr/share/xserver-xorg/inputabiver
+	$(INSTALL) -m644 $(CURDIR)/debian/serverminver \
+	           $(CURDIR)/debian/xserver-xorg-dev/usr/share/xserver-xorg/serverminver
+	$(INSTALL) -m 755 -d debian/xserver-xorg-core/usr/share/bug/xserver-xorg-core
+	$(INSTALL) -m 755 debian/xserver-xorg-core.bug.script debian/xserver-xorg-core/usr/share/bug/xserver-xorg-core/script
+	dh_installdebconf -a
+	dh_installman -a
+ifeq ($(BUILD_XPRINT), true)
+	$(INSTALL) -m 644 $(CURDIR)/debian/xprint-overrides $(CURDIR)/debian/xprint/usr/share/lintian/overrides/xprint
+	# xprint docs are linked to xprint-common
+	rm -rf debian/xprint/usr/share/doc/xprint
+endif
+	
+	dh_link -a
+	dh_strip -a --exclude=usr/lib/xorg/modules \
+		--dbg-package=xserver-xorg-core
+	for i in $$(find debian/xserver-xorg-core/usr/lib/xorg/modules -name "lib*.so"); do \
+	  mkdir -p $$(dirname debian/xserver-xorg-core-dbg/usr/lib/debug/$${i#*debian/xserver-xorg-core/}) && \
+	  objcopy --only-keep-debug $$i debian/xserver-xorg-core-dbg/usr/lib/debug/$${i#*debian/xserver-xorg-core/} && \
+	  objcopy --add-gnu-debuglink=debian/xserver-xorg-core-dbg/usr/lib/debug/$${i#*debian/xserver-xorg-core/} $$i; \
+	done
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+	find debian/xserver-xorg-core/usr/lib/xorg/modules -name "lib*.so" | \
+	  xargs --no-run-if-empty \
+	  strip --strip-debug --remove-section=.note --remove-section=.comment
+endif
+	$(MAKE) -f debian/rules DH_OPTIONS=-a binary-deb
+
+
+# Build architecture-independent files here (xprint-common)
+binary-indep: build install
+	$(MAKE) -f debian/rules DH_OPTIONS=-i binary-initial
+	dh_install -i --sourcedir=debian/tmp --list-missing -Xusr/share/man -Xusr/include/xorg -Xusr/share/aclocal -Xusr/lib/xorg/modules -Xusr/lib/pkgconfig/xorg-server.pc -Xusr/bin -XSecurityPolicy -Xvar/lib/xkb -Xusr/lib/X11/Cards -Xusr/lib/X11/Options
+	
+ifeq ($(BUILD_XPRINT), true)
+	$(INSTALL) -m 644 $(CURDIR)/debian/xprint-common-overrides $(CURDIR)/debian/xprint-common/usr/share/lintian/overrides/xprint-common
+	# split Xprint config files so font files do not land in /etc
+	# (for xprint-common only)
+	mv debian/xprint-common/usr/share/Xprint/xserver/C/print/attributes debian/xprint-common/etc/Xprint/C/print/attributes
+	mv debian/xprint-common/usr/share/Xprint/xserver/C/print/Xprinters debian/xprint-common/etc/Xprint/C/print/Xprinters
+	mv debian/xprint-common/usr/share/Xprint/xserver/C/print/ddx-config debian/xprint-common/etc/Xprint/C/print/ddx-config
+	mv debian/xprint-common/usr/share/Xprint/xserver/en_US/print/attributes debian/xprint-common/etc/Xprint/en_US/print/attributes
+	# dh_install cannot rename files, sigh
+	$(INSTALL) -m 644 $(CURDIR)/debian/xprint-common.default $(CURDIR)/debian/xprint-common/etc/default/xprint
+	dh_installinit -p xprint-common --name=xprint
+endif
+	
+	dh_installdocs -i
+	dh_installchangelogs -i ChangeLog
+	dh_installdebconf -i
+	dh_link -i
+	
+	$(MAKE) -f debian/rules DH_OPTIONS=-i binary-deb
+
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
--- xorg-server-1.4.2.orig/debian/videoabiver
+++ xorg-server-1.4.2/debian/videoabiver
@@ -0,0 +1 @@
+2
--- xorg-server-1.4.2.orig/debian/xprint-common.install
+++ xorg-server-1.4.2/debian/xprint-common.install
@@ -0,0 +1,2 @@
+usr/lib/X11/xserver	usr/share/Xprint
+etc/X11/Xsession.d/92xprint-xpserverlist
--- xorg-server-1.4.2.orig/debian/xprint-common.xprint.init
+++ xorg-server-1.4.2/debian/xprint-common.xprint.init
@@ -0,0 +1,1246 @@
+#!/bin/bash
+#
+# Copyright 2002-2004 by Roland Mainz <roland.mainz@nrubsig.org>.
+#
+# This script manages the Xprint server side
+
+# Basic support for IRIX-style "chkconfig"
+# chkconfig: 2345 61 61
+# description: Startup/shutdown script for Xprint server(s)
+
+# Basic support for the Linux Standard Base Specification 1.0.0
+# (Note: The Should-Start/Stop lines are there so that this works in the
+# future, when the LSB adopts these. The X-UnitedLinux lines are there 
+# so that it works right now.)
+### BEGIN INIT INFO
+# Provides: xprint
+# Required-Start: $local_fs $remote_fs $syslog $network
+# Required-Stop: $local_fs $remote_fs $syslog
+# Should-Start: cups lpd xfs
+# Should-Stop:  cups lpd xfs
+# X-UnitedLinux-Should-Start: cups lpd xfs
+# X-UnitedLinux-Should-Stop:  cups lpd xfs
+# Default-Start: 3 5
+# Default-Stop: 0 1 2 6
+# Description: Startup/shutdown script for Xprint server(s)
+### END INIT INFO
+
+
+
+
+############################################################################
+#
+# This script has three main tasks:
+# 1. Start Xprint servers ("Xprt") at boot time.
+# 2. Shutdown Xprint servers when the machine is being shut down.
+# 3. Query the list of available printers.
+#
+# Additional tasks are:
+# 4. Restart ('restart') and conditional restart
+#    ('condrestart'/'try-restart'|'force-reload') for Linux support
+# 5. Wrapping of application call with setting XPSERVERLIST ('wrapper')
+#
+# Usage:
+# - Start Xprint server(s) manually:
+#   % /etc/init.d/xprint start
+#
+# - Stop Xprint server(s) manually:
+#   % /etc/init.d/xprint stop
+#
+# - Populate $XPSERVERLIST env var (for example as part of a global
+#   login script like /etc/profile or per-user login scripts like
+#   $HOME/.profile (sh/ksh/bash))
+#   % XPSERVERLIST="`/etc/init.d/xprint get_xpserverlist`"
+#   % export XPSERVERLIST
+#
+# Installation:
+#   Copy this script to /etc/init.d/xprint and make sure that it is
+#   executable. If your installation is LSB-compliant, then run
+#   % /usr/lib/lsb/install_initd /etc/init.d/xprint
+#   to start the service on startup. Otherwise, manually create links
+#   to the matching run levels.
+#   Examples:
+#     - Solaris 2.7/2.8/2.9:
+#       % cp xprint /etc/init.d/xprint
+#       % chmod a+rx /etc/init.d/xprint
+#       % ln /etc/init.d/xprint /etc/rc0.d/K38xprint
+#       % ln /etc/init.d/xprint /etc/rc1.d/K38xprint
+#       % ln /etc/init.d/xprint /etc/rc2.d/S81xprint
+#       % ln /etc/init.d/xprint /etc/rcS.d/K38xprint
+#
+#     - SuSE Linux 7.3
+#       % cp xprint /etc/init.d/xprint
+#       % chmod a+rx /etc/init.d/xprint
+#       % ln -s ../xprint /etc/init.d/rc3.d/K13xprint
+#       % ln -s ../xprint /etc/init.d/rc3.d/S12xprint
+#       % ln -s ../xprint /etc/init.d/rc5.d/K13xprint
+#       % ln -s ../xprint /etc/init.d/rc5.d/S12xprint
+#       % ln -s ../xprint /etc/init.d/rc2.d/K13xprint
+#       % ln -s ../xprint /etc/init.d/rc2.d/S12xprint
+#
+#     - SuSE Linux 6.4:
+#       % cp xprint /sbin/init.d/xprint
+#       % chmod a+rx /sbin/init.d/xprint
+#       % ln -s ../xprint /sbin/init.d/rc2.d/K20xprint
+#       % ln -s ../xprint /sbin/init.d/rc2.d/S20xprint
+#       % ln -s ../xprint /sbin/init.d/rc3.d/K20xprint
+#       % ln -s ../xprint /sbin/init.d/rc3.d/S20xprint
+#
+#   Notes: 
+#   - The Xprint servers must be started _after_ the print
+#     spooler or the server(s) may refuse to start
+#   - The script should be readable by all users to ensure that they
+#     can use the "get_xpserverlist"-option
+#
+# Custom configuration:
+#   - Edit the function setup_config() in this script to match your needs
+#
+# Known bugs/ToDo/Notes:
+#   - The shell script assumes that a Xserver can be reached via 
+#     "hostname:displaynum" where "hostname" is obtained from
+#     "/usr/bin/hostname". It may happen that a kernel firewall
+#     blocks an X connection on the same host (e.g. client && Xserver 
+#     are running on the same host).
+#     Suggested fix: Fix the firewall config.
+#     Suggested workaround: Edit this script and replace the use of 
+#     /usr/bin/hostname with "echo 'localhost'".
+#
+############################################################################
+#
+
+
+############################################################################
+
+fatal_error()
+{
+    echo "${0}: ## FATAL ERROR: ${1}" 1>&2
+    exit 1
+}
+
+error_echo()
+{
+    echo "${0}: ## ERROR: ${1}" 1>&2
+}
+
+warning_echo()
+{
+    echo "${0}: ## WARNING: ${1}" 1>&2
+}
+
+verbose_echo()
+{
+    echo "${0}: ${1}"
+}
+
+msg()
+{
+    echo "${1}"
+}
+
+############################################################################
+
+
+##debug
+# set -x
+
+# Change current dir to a location which is writeable by everyone
+cd /tmp
+
+# Clear some environment variables
+unset TEMP TMPDIR SCREENDIR
+
+# Set search path for commands
+export PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+
+
+
+## Try to figure-out where X11 was installed
+
+
+
+
+
+
+[ -d /usr/X11/bin ]     && XPROJECTROOT=/usr/X11
+[ -d /usr/X11R6/bin ]   && XPROJECTROOT=/usr/X11R6
+
+# X11R7 now follows FHS, doesn't use it's own separate directory
+XPROJECTROOT=/usr
+
+XPCUSTOMGLUE=DebianGlue # This is used for customizing this script
+export XPROJECTROOT XPCUSTOMGLUE
+
+if [ -z "${XPROJECTROOT}" ] ; then
+    fatal_error "Unknown XProjectRoot."
+fi
+
+# Set the location of the Xprt binary we want to use.
+XPRT_BIN="${XPROJECTROOT}/bin/Xprt"
+
+# Set the location of the global file where we store the locations 
+# of the system-wide servers
+if [ -d /var/run ] ; then
+    XP_GLOBAL_SERVERS=/var/run/Xprint_servers
+else
+    XP_GLOBAL_SERVERS=/tmp/.Xprint_servers
+fi
+
+# ${LOGNAME} will not work if user su'ed into another account
+export CURRLOGNAME="$(id -u -n)"
+
+# Set location where we want to store the list of Xprint servers managed
+# by this user
+# - If we start as "root" use the global file
+# - If we start as normal user use a per-user file
+
+if [ "${CURRLOGNAME}" != "root" -a "${CURRLOGNAME}" != "" ] ; then
+    XP_PER_USER_SERVERS="/tmp/.Xprint_servers_${CURRLOGNAME}"
+    XP_SERVERS="${XP_PER_USER_SERVERS}"
+else
+    XP_SERVERS="${XP_GLOBAL_SERVERS}"
+fi
+
+# Set umask that owner can r/w all files and everyone else can read them
+umask 022
+
+# Bump limit for per-process open files to ensure that Xprt can open many many fonts
+ulimit -n 1024
+
+############################################################################
+
+# Get list of fonts for a given display
+get_fontlist_from_display()
+{
+    ${XPROJECTROOT}/bin/xset -display "${1}" q | 
+      awk "/Font Path:/ { i=1 ; next } i==1 { print \$0 ; i=0 }" | 
+        fontpath2fontlist
+}
+
+# Get list from a fontserver config
+get_fontlist_from_xfs_config()
+{
+    if [ ! -r "${1}" ] ; then
+        return 0
+    fi
+      
+    (        
+      cat "${1}" |
+      while read -r i ; do
+          for val in $i; do
+              case $val in
+                \#*)  break ;;
+                ?*=*) key="${val%%=*}" ;;
+                =*)   key="${tok}" ;;
+                *)    [ "${key}" = "catalogue" -a "${tok}" != "" ] && echo "${tok}" ;;
+              esac
+              tok="${val#*=}"
+          done
+      done
+    ) | tr "," "\n" | fontpath2fontlist
+}
+
+get_fontlist_from_all_xfs_configs()
+{
+    get_fontlist_from_xfs_config "/etc/openwin/fs/fontserver.cfg"
+    get_fontlist_from_xfs_config "/usr/openwin/lib/X11/fontserver.cfg"
+    get_fontlist_from_xfs_config "/etc/X11/fs-xtt/config"
+    get_fontlist_from_xfs_config "/etc/X11/fs/config"
+    get_fontlist_from_xfs_config "/etc/X11/xfs/config"
+    get_fontlist_from_xfs_config "${XPROJECTROOT}/lib/X11/fs/config"
+}
+
+get_fontlist_from_xf86config()
+{
+    srcxconf=""
+
+    # see xorg.conf(5x) manual page for the list of locations used here    
+    [ "${srcxconf}" = "" -a -f "/etc/X11/xorg.conf"  ]                      && srcxconf="/etc/X11/xorg.conf"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/etc/X11/xorg.conf" ]             && srcxconf="/usr/X11R6/etc/X11/xorg.conf"
+    [ "${srcxconf}" = "" -a -f "/etc/X11/xorg.conf-4" ]                     && srcxconf="/etc/X11/xorg.conf-4"
+    [ "${srcxconf}" = "" -a -f "/etc/X11/xorg.conf" ]                       && srcxconf="/etc/X11/xorg.conf"
+    [ "${srcxconf}" = "" -a -f "/etc/xorg.conf" ]                           && srcxconf="/etc/xorg.conf"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/etc/X11/xorg.conf.${hostname}" ] && srcxconf="/usr/X11R6/etc/X11/xorg.conf.${hostname}"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/etc/X11/xorg.conf-4" ]           && srcxconf="/usr/X11R6/etc/X11/xorg.conf-4"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/etc/X11/xorg.conf" ]             && srcxconf="/usr/X11R6/etc/X11/xorg.conf"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/lib/X11/xorg.conf.${hostname}" ] && srcxconf="/usr/X11R6/lib/X11/xorg.conf.${hostname}"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/lib/X11/xorg.conf-4" ]           && srcxconf="/usr/X11R6/lib/X11/xorg.conf-4"
+    [ "${srcxconf}" = "" -a -f "/usr/X11R6/lib/X11/xorg.conf" ]             && srcxconf="/usr/X11R6/lib/X11/xorg.conf"
+
+    # Xfree86 locations
+    [ "${srcxconf}" = "" -a -f "/etc/X11/XF86Config-4" ] && srcxconf="/etc/X11/XF86Config-4"
+    [ "${srcxconf}" = "" -a -f "/etc/X11/XF86Config" ]   && srcxconf="/etc/X11/XF86Config"
+
+
+    if [ "${srcxconf}" = "" ] ; then
+        return 0
+    fi
+
+    currsection=""
+    cat "${srcxconf}" |
+    while read i1 i2 i3 i4 ; do
+        # Strip "\"" from I2
+        i2="${i2#\"}" ; i2="${i2%\"}"
+
+        case "${i1}" in
+            \#*)
+                continue
+                ;;
+            'Section')
+                currsection="${i2}"
+                ;;
+            'EndSection')
+                currsection=""
+                ;;
+            'FontPath')
+                [ "$currsection" = "Files" ] && echo "${i2%:unscaled}"
+                ;;
+        esac  
+    done | egrep -v -i "tcp/|tcp4/|tcp6/|unix/"
+    
+    return 0
+}
+
+get_fontlist_from_defoma()
+{
+    # Include Debian defoma font directory where relevant
+    if [ -d "/var/lib/defoma/x-ttcidfont-conf.d/dirs" ] ; then        
+        find "/var/lib/defoma/x-ttcidfont-conf.d/dirs" -name fonts.dir |
+          while read i ; do echo "${i%/fonts.dir}" ; done
+    fi
+}
+
+# Get list of system fonts
+get_system_fontlist()
+{
+          (
+            get_fontlist_from_defoma
+
+            get_fontlist_from_xf86config
+            
+            # Getting font paths from XFS is mainly required for compatibilty to RedHat
+            get_fontlist_from_all_xfs_configs
+                   
+            ## List all fonts in all locales installed on this machine
+            (
+              [ -d "/usr/share/fonts" ] && find /usr/share/fonts -name fonts.dir
+              [ -d "${XPROJECTROOT}/lib/X11/fonts" ] && find "${XPROJECTROOT}/lib/X11/fonts" -name fonts.dir 
+            ) | 
+              while read i ; do echo "${i%/fonts.dir}" ; done
+          ) | sort -u
+}
+
+# Filter fonts per given extended regular expressions
+# (and make sure we filter any model-config fonts - they are managed by Xprt internally)
+filter_fontlist()
+{
+    egrep -- "${1}" | fgrep -v "/models/" | egrep -v -- "${2}"
+}
+
+# Filter font paths with unsupported font types
+# (such as CID fonts)
+filter_unsupported_fonts()
+{
+    egrep -v -i "/cid(/$|$)|/csl(/$|$)"
+}
+
+# Validate fontpath
+# Only return valid font path entries (note that these entries may
+# include non-file stuff like font server references)
+validate_fontlist()
+{
+    while read i ; do       
+        case "${i}" in
+            # Check if font path entry is a font server...
+            tcp/''*|tcp4/''*|tcp6/''*|unix/''*)
+                echo "${i}"
+                ;;
+            # ... if not check if the path is accessible
+            # and has a valid "fonts.dir" index
+            *)
+                [ -f "${i}/fonts.dir" ] && echo "${i}"
+                ;;
+        esac
+    done
+}
+
+# Build a comma-seperated list of fonts (font path) from a list of fonts
+fontlist2fontpath()
+{
+    fp=""
+    read fp;
+    while read i ; do
+        fp="${fp},${i}"
+    done
+    
+    echo "$fp"
+}
+
+# Build a list (one item per line) of fonts from a font path
+fontpath2fontlist()
+{
+    while read i ; do
+        echo "${i}" | tr "," "\n"
+    done
+}
+
+# Sort scaleable fonts (PS Type1 and TrueType) first in a font list
+sort_scaleable_fonts_first()
+{
+    i="$(fontlist2fontpath)"
+    # First list PS Type1 fonts...
+    echo "${i}" | fontpath2fontlist | fgrep "/Type1"
+    # ... then TrueType fonts ...
+    echo "${i}" | fontpath2fontlist | egrep -i "/TrueType|/TT(/$|$)|/TTF(/$|$)"
+    # ... then all others
+    echo "${i}" | fontpath2fontlist | egrep -v -i "/Type1|/TrueType|/TT(/$|$)|/TTF(/$|$)"
+}
+
+# Check if a X display is used by a Xserver or not
+# Known bugs:
+# - there is no way in plain bourne shell or bash (see comment about ksh93
+#   below) to test if a Xserver sits only on a socket and not on a pipe
+# - some Xserver's don't cleanup their stuff in /tmp on exit which may end
+#   in the problem that we don't detect possible free display numbers
+#   (one problem is that only ksh93 can do stuff like 
+#   "cat </dev/tcp/0.0.0.0/6001")
+CheckIfDisplayIsInUse()
+{
+    id=$1
+    
+    [ -r "/tmp/.X${id}-lock"     ] && return 0;
+    [ -r "/tmp/.X11-unix/X${id}" ] && return 0;
+    [ -r "/tmp/.X11-pipe/X${id}" ] && return 0;
+    
+    return 1;
+}
+
+lastdisplaynumreturned_store=/tmp/.Xp_last_display_returned_by_findfreexdisplaynum_${RANDOM}_${RANDOM}
+
+# Try to find a free display number
+FindFreeXDisplayNum()
+{
+    if [ -r "${lastdisplaynumreturned_store}" ] ; then
+      i="$(cat "${lastdisplaynumreturned_store}")"
+    else
+      i=32 # start at display 32
+    fi
+    
+    while [ $i -lt 127 ] ; do
+        i=$(($i + 1))
+
+        if CheckIfDisplayIsInUse $i ; then
+            true
+        else
+            echo "$i"
+            echo "$i" >"${lastdisplaynumreturned_store}"
+            return 0
+        fi
+    done
+
+    # Using "magic" value of 189 here due lack of a better solution
+    echo "189"
+    echo "189" >"${lastdisplaynumreturned_store}"    
+    return 0
+}
+
+# Check if a process exists or not
+pexists()
+{
+    [ "$1" = "" ] && return 1;
+
+    # Use of /proc would be better but not all platforms (like AIX) have procfs
+    [ "$(ps -p $1 | fgrep $1)" != "" ] && return 0;
+    return 1
+}
+
+# Check if there is a spooler running...
+is_spooler_running()
+{
+    # This covers Linux lpd, CUPS, Solaris and AIX 4.x - but what about
+    # AIX 5.x, HP-UX and IRIX ?
+
+    [ "$(ps -A | egrep 'lpd|lpsched|cupsd|qdaemon' | fgrep -v 'grep')" != "" ] && return 0;
+    return 1
+}
+
+# Wait until the spooler system has been started (but not more than 30secs)
+wait_for_print_spooler()
+{
+    for i in 1 2 3 4 5 6 7 8 9 10 ; do
+        is_spooler_running && return 0;
+        sleep 3
+    done
+    
+    return 0
+}
+
+lock_server_registry()
+{
+    lock_counter=0 # counts in 1/100s
+    waiting_for_lock_msg_send="false"
+    while ! mkdir "${XP_SERVERS}.lock" 2>/dev/null ; do
+        # print notice after 2 seconds
+        if [ ${lock_counter} -gt 200 -a "${waiting_for_lock_msg_send}" != "true" ] ; then
+            echo "${0}: waiting for lock(=${XP_SERVERS}.lock)..."
+            waiting_for_lock_msg_send="true"
+        fi
+
+        # tread the lock as "broken" after 20 seconds
+        if [ ${lock_counter} -gt 2000 ] ; then
+            echo "${0}: WARNING: lock timeout for lock(=${XP_SERVERS}.lock)."
+            return 0
+        fi
+                
+        if [ -x /bin/usleep ] ; then
+            /bin/usleep 200000
+            lock_counter=$((${lock_counter} + 20)) # 20/100s
+        else
+            sleep 1
+            lock_counter=$((${lock_counter} + 100)) # 100/100s
+        fi
+    done
+}
+
+unlock_server_registry()
+{
+    rmdir "${XP_SERVERS}.lock"
+}
+
+# Kill dead registry locks (silently!)
+kill_dead_registry_locks()
+{
+    rm -Rf "${XP_SERVERS}.lock"
+}
+
+# Start Xprint servers
+start_servers()
+{
+    # Write registry "intro" ...
+    lock_server_registry
+    echo "# Xprint server list"                               >>"${XP_SERVERS}"
+    echo "# File is for private use for ${0}."                >>"${XP_SERVERS}"
+    echo "# Do not edit, rely on the content or file format." >>"${XP_SERVERS}"
+    unlock_server_registry
+
+    hostname="$(hostname)"
+
+    default_fontpath="$(get_system_fontlist | fontlist2fontpath)"
+    default_fontpath_acceptpattern=".*";
+    default_fontpath_rejectpattern="_No_Match_"; # Match nothing   
+    
+    curr=0
+    while [ $curr -lt $num_xpstart ] ; do
+        if [ "${xpstart_remote_server[$curr]}" != "" ] ; then
+            # Remote Xprt, just put the entry into the registry
+            lock_server_registry
+            echo "display=${xpstart_remote_server[$curr]}" >>"${XP_SERVERS}"
+            unlock_server_registry
+        else
+            # Run block in seperate process to avoid that changes to the
+            # xpstart_* variables affect the next cycle
+            (
+              # Use defaults if there are no special options
+              [ "${xpstart_fontpath[$curr]}"               = "" ] &&               xpstart_fontpath[$curr]="${default_fontpath}";
+              [ "${xpstart_fontpath_acceptpattern[$curr]}" = "" ] && xpstart_fontpath_acceptpattern[$curr]="$default_fontpath_acceptpattern";
+              [ "${xpstart_fontpath_rejectpattern[$curr]}" = "" ] && xpstart_fontpath_rejectpattern[$curr]="$default_fontpath_rejectpattern";
+              [ "${xpstart_displayid[$curr]}"              = "" ] &&              xpstart_displayid[$curr]="$(FindFreeXDisplayNum)"       
+              [ "${xpstart_logger[$curr]}"                 = "" ] &&                 xpstart_logger[$curr]="logger -p lpr.notice -t Xprt_${xpstart_displayid[$curr]}";
+              [ "${xpstart_logfile[$curr]}"                = "" ] &&                xpstart_logfile[$curr]="/dev/null";
+              [ "${xpstart_xprt_binary[$curr]}"            = "" ] &&            xpstart_xprt_binary[$curr]="${XPRT_BIN}";
+              if [ "${xpstart_xprt_binary[$curr]}" = "/usr/openwin/bin/Xprt" -o "$(uname -s)" = "SunOS" ] ; then
+                  # Solaris /usr/openwin/bin/Xprt does not support "-nolisten tcp"
+                  # yet nor is it possible to run a Xserver on a unix socket only
+                  # in Solaris since access to the unix domain sockets in
+                  # /tmp/.X11-pipe and /tmp/.X11-unix is restricted to applications
+                  # with group-id "root" (e.g. the Xprt server would need to be
+                  # setgid "root" that plain users can start it listening on a unix
+                  # socket only)
+                  [ "${xpstart_options[$curr]}" = "" ] && xpstart_options[$curr]="-ac -pn"
+              else
+                  [ "${xpstart_options[$curr]}" = "" ] && xpstart_options[$curr]="-ac -pn -nolisten tcp"
+              fi
+
+              # Check if the Xprt binary is available                                     
+              if [ ! -x "${xpstart_xprt_binary[$curr]}" ] ; then
+	    	  # Debian policy 9.3.2 says just stop quietly here
+		  exit 0
+		
+                  error_echo "Can't find \"${xpstart_xprt_binary[$curr]}\"."                                  
+                  exit 1 # exit block                                                               
+              fi                                                                          
+
+              # Verify and set location of font encodings directory file
+              if [ "${xpstart_font_encodings_dir[$curr]}" = "" ] ; then
+                  if [ -f "${XPROJECTROOT}/lib/X11/fonts/xf86encodings/encodings.dir" ] ; then
+                      xpstart_font_encodings_dir[$curr]="${XPROJECTROOT}/lib/X11/fonts/xf86encodings/encodings.dir"
+		  elif [ -f "${XPROJECTROOT}/lib/X11/fonts/encodings/encodings.dir" ]; then
+		      xpstart_font_encodings_dir[$curr]="${XPROJECTROOT}/lib/X11/fonts/encodings/encodings.dir"
+                  else
+                      xpstart_font_encodings_dir[$curr]="${XPROJECTROOT}/share/fonts/X11/encodings/encodings.dir";
+                  fi
+              fi
+
+              unset FONT_ENCODINGS_DIRECTORY
+              if [ ! -f "${xpstart_font_encodings_dir[$curr]}" ] ; then
+                  warning_echo "Can't find \"${xpstart_font_encodings_dir[$curr]}\", TrueType font support may not work."
+              fi
+
+              export FONT_ENCODINGS_DIRECTORY="${xpstart_font_encodings_dir[$curr]}"
+
+              # Generate font path (containing only valid font path elements)
+              # from input font path and filter expressions
+              curr_fp=$(echo "${xpstart_fontpath[$curr]}" | 
+                        fontpath2fontlist |
+                        filter_fontlist "${xpstart_fontpath_acceptpattern[$curr]}" "${xpstart_fontpath_rejectpattern[$curr]}" | 
+                        filter_unsupported_fonts |
+                        sort_scaleable_fonts_first | 
+                        validate_fontlist | 
+                        fontlist2fontpath)
+
+              # Set Xserver auditing level option
+              unset curr_audit
+              if [ "${xpstart_auditlevel[$curr]}" != "" ] ; then
+                  curr_audit="-audit ${xpstart_auditlevel[$curr]}"
+              fi
+
+              # Set Xprt -XpFile option
+              unset curr_xpfile
+              if [ "${xpstart_xpfile[$curr]}" != "" ] ; then
+                  curr_xpfile="-XpFile ${xpstart_xpfile[$curr]}"
+              fi
+
+              # Set custom XPCONFIGDIR (if there is one)
+              unset XPCONFIGDIR
+              if [ "${xpstart_xpconfigdir[$curr]}" != "" ] ; then
+                  export XPCONFIGDIR="${xpstart_xpconfigdir[$curr]}"
+              fi
+
+              # If someone uses "-nolisten tcp" make sure we do not add a hostname to force local transport
+              if [ "$(echo "${xpstart_options[$curr]}" | egrep "nolisten.*tcp")" != "" ] ; then
+                  xp_display=":${xpstart_displayid[$curr]}"
+              else
+                  xp_display="${hostname}:${xpstart_displayid[$curr]}"
+              fi
+              
+              (
+                (
+		  DAEMON_OPTS="${xpstart_options[$curr]}                       ${curr_xpfile} ${curr_audit}                       -fp ${curr_fp}                       :${xpstart_displayid[$curr]}"
+
+
+
+		  PIDFILE=/var/run/Xprt_${curr}.pid
+		  start-stop-daemon --start --background --oknodo --quiet 		      --pidfile ${PIDFILE} --make-pidfile 		      --exec ${xpstart_xprt_binary[$curr]} -- $DAEMON_OPTS
+
+
+		  server_pid="$(cat ${PIDFILE})"
+
+                  # Append the new server to the registry
+                  lock_server_registry
+                  echo "display=${xp_display} display_id=${xpstart_displayid[$curr]} pid=${server_pid}" >>"${XP_SERVERS}"
+                  unlock_server_registry
+                  
+                ) 2>&1 | while read i ; do echo "$i" | tee -a "${xpstart_logfile[$curr]}" | ${xpstart_logger[$curr]} ; done
+              ) <&- >&- 2>&- &
+            )
+        fi
+        
+        curr=$(($curr + 1))
+    done
+    
+    # Remove tmp. file created by |FindFreeXDisplayNum()|
+    rm -f "${lastdisplaynumreturned_store}"
+
+    # Done.
+    lock_server_registry
+    echo "# EOF." >>"${XP_SERVERS}"
+    unlock_server_registry
+    return 0
+}
+
+
+# Convenience function to check setup and start Xprt server(s)
+do_start()
+{
+    if [ -f "${XP_SERVERS}" ] ; then
+        numservers="$(do_get_xpserverlist | wc -l)"
+        if [ ${numservers} -gt 0 ] ; then
+            verbose_echo "Xprint servers are already running."
+            return 0
+        else
+            verbose_echo "Old server registry found, cleaning-up..."
+            do_stop
+        fi
+    fi
+    
+    # Check if we can write the registry file
+    touch "${XP_SERVERS}" 2>/dev/null
+    if [ ! -f "${XP_SERVERS}" ] ; then
+        error_echo "Cannot create \"${XP_SERVERS}\"."
+        # exit code 4 = user had insufficient privilege (LSB)
+        exit 4
+    fi
+
+    if ! setup_config ; then
+        error_echo "setup_config failed."
+        exit 1
+    fi
+
+    # Provide two paths here - one which simply starts the Xprt servers,
+    # assuming that there is a print spooler already running (or that 
+    # ${XPCONFIG}/C/print/Xprinters provides static print queue entries
+    # (like for the PSspooldir print model)) and a 2nd path which
+    # explicitly checks if the print queue daemons are running
+    if true ; then
+        msg "Starting Xprint servers: Xprt."
+        start_servers
+    else 
+        # Continue in the background if there is no spooler running yet (that
+        # we don't hold off the boot process nor run in a possible race-condition
+        # when /etc/init.d/lpd was not called yet but the runlevel script waits
+        # for us to finish first ...
+        if is_spooler_running ; then
+            msg "Starting Xprint servers: Xprt."
+            start_servers
+        else
+            msg "Starting Xprint servers (in the background): Xprt."
+            (wait_for_print_spooler ; start_servers) &
+            sleep 5
+        fi
+    fi
+    
+    if [ "${CURRLOGNAME}" = "root" -a -d /var/lock/subsys/ ] ; then
+        touch /var/lock/subsys/xprint
+    fi
+}
+
+# Convenience function to stop Xprt server(s)
+do_stop()
+{
+    msg "Stopping Xprint servers: Xprt."
+
+    # need to run setup_config to grab values of xpstart_xprt_binary, etc.
+    if ! setup_config ; then
+        error_echo "setup_config failed."
+        exit 1
+    fi
+
+    curr=0
+    while [ $curr -lt $num_xpstart ] ; do
+        [ "${xpstart_xprt_binary[$curr]}"            = "" ] &&            xpstart_xprt_binary[$curr]="${XPRT_BIN}";
+        PIDFILE=/var/run/Xprt_${curr}.pid
+        if [ -f ${PIDFILE} ] ; then
+          start-stop-daemon --stop --oknodo --quiet             --pidfile ${PIDFILE}             --exec ${xpstart_xprt_binary[$curr]}
+
+
+          rm -f ${PIDFILE}
+        fi
+        curr=$(($curr + 1))
+    done
+
+    lock_server_registry
+    if [ -f "${XP_SERVERS}" ] ; then       
+        reglist="$(cat "${XP_SERVERS}")"
+        rm -f "${XP_SERVERS}"
+    fi
+    unlock_server_registry
+    
+    if [ "${reglist}" != "" ] ; then
+        echo "${reglist}" |
+          grep "^display=.*:.* pid=[0-9]*$" |
+          while read i ; do
+              (
+                eval ${i}
+                if pexists ${pid} ; then 
+                    kill ${pid}
+                fi
+
+                # Remove the X sockets/pipes which are not in use anymore
+                # (It would be better if the Xservers would cleanup this
+                # automatically, but most Xservers do not do that... ;-(
+                # Note that this will not work on Solaris where applications
+                # must run with groupid="root" if they want to write into
+                # /tmp/.X11-unix/ and/or /tmp/.X11-pipe/)
+                if [ "${display_id}" != "" ] ; then
+                    rm -f "/tmp/.X${display_id}-lock"     2>/dev/null
+                    rm -f "/tmp/.X11-unix/X${display_id}" 2>/dev/null
+                    rm -f "/tmp/.X11-pipe/X${display_id}" 2>/dev/null
+                fi 
+              )
+          done
+    fi
+
+    if [ "${CURRLOGNAME}" = "root" -a -d /var/lock/subsys/ ] ; then
+        rm -f /var/lock/subsys/xprint
+    fi
+    
+    # Remove any outstanding (dead) locks and cleanup
+    rm -f "${XP_SERVERS}"
+    kill_dead_registry_locks
+}
+
+# Convenience function to obtain a list of available Xprint servers
+do_get_xpserverlist()
+{
+    if [ -f "${XP_PER_USER_SERVERS}" -o -f "${XP_GLOBAL_SERVERS}" ] ; then
+        xpserverlist=$(
+          # Enumerate both per-user and global servers (in that order)
+          (
+            [ -f "${XP_PER_USER_SERVERS}" ]  && cat "${XP_PER_USER_SERVERS}"
+            [ -f "${XP_GLOBAL_SERVERS}"   ]  && cat "${XP_GLOBAL_SERVERS}"
+          ) |
+            egrep "^display=.*:.* pid=[0-9]*$|^display=.*:[0-9]*$" |
+              while read i ; do
+                  (
+                    pid="none"
+                    eval ${i}
+                    # Check if the Xprt process exists (if possible)
+                    if [ "$pid" != "none" ] ; then
+                        if pexists ${pid} ; then
+                            echo ${display}
+                        fi
+                    else
+                        echo ${display}
+                    fi
+                  )
+              done | tr "[\n]" " "
+          )
+        # Only produce output if we have some entries...
+        [ "${xpserverlist}" != "" ] && echo "${xpserverlist}"
+    fi
+}
+
+do_restart()
+{
+    msg "Restarting Xprint server(s): Xprt."
+    do_stop
+    sleep 1
+    do_start
+}
+
+do_diag()
+{
+    echo "##### Diag start $(date)."
+    
+    # General info
+    echo "## General info start."
+    (
+      echo "PATH=\"${PATH}\""
+      echo "TZ=\"${TZ}\""
+      echo "LANG=\"${LANG}\""
+      echo "uname -a=\"$(uname -a)\""
+      echo "uname -s=\"$(uname -s)\""
+      echo "uname -p=\"$(uname -p)\""
+      echo "uname -i=\"$(uname -i)\""
+      echo "uname -m=\"$(uname -m)\""
+      echo "has /etc/SuSE-release ... $([ -f "/etc/SuSE-release" ] && echo "yes" || echo "no")"
+      echo "has /etc/redhat-release ... $([ -f "/etc/redhat-release" ] && echo "yes" || echo "no")"
+      echo "has /etc/debian_version ... $([ -f "/etc/debian_version" ] && echo "yes" || echo "no")"
+      echo "how many Xprt servers are running ...$(ps -ef | fgrep Xprt | fgrep -v "grep" | wc -l)"
+    ) 2>&1 | while read i ; do echo "  $i" ; done
+    echo "## General info end."
+    
+    # Testing font paths
+    echo "## Testing font paths start."
+    (
+      get_system_fontlist |
+          filter_unsupported_fonts |
+          sort_scaleable_fonts_first | 
+          validate_fontlist | while read d ; do
+          echo "#### Testing \"${d}\" ..."
+          if [ ! -d "$d" ] ; then
+              echo "# Error: $d does not exists."
+              continue
+          fi
+          if [ ! -r "$d" ] ; then
+              echo "# Error: $d not readable."
+              continue
+          fi
+          if [ ! -f "${d}/fonts.dir" ] ; then
+              echo "# Error: ${d}/fonts.dir not found."
+              continue
+          else
+              if [ ! -r "${d}/fonts.dir" ] ; then
+                  echo "# Error: ${d}/fonts.dir not readable."
+                  continue
+              fi
+          fi
+          if [ -f "${d}/fonts.alias" ] ; then
+              if [ ! -r "${d}/fonts.alias" ] ; then
+                  echo "# Error: ${d}/fonts.alias not readable."
+              fi
+          fi
+
+          if [ "$(cat "${d}/fonts.dir" | fgrep 'cursor')" != "" ] ; then
+              echo "${d}/fonts.dir has cursor font."
+          fi
+          if [ "$(cat "${d}/fonts.dir" | fgrep 'fixed')" != "" ] ; then
+              echo "${d}/fonts.dir has fixed font."
+          fi
+
+          if [ -r "${d}/fonts.alias" ] ; then 
+              if [ "$(cat "${d}/fonts.alias" | fgrep 'cursor')" != "" ] ; then
+                  echo "${d}/fonts.alias has cursor font."
+              fi
+              if [ "$(cat "${d}/fonts.alias" | fgrep 'fixed')" != "" ] ; then
+                  echo "${d}/fonts.alias has fixed font."
+              fi
+          fi
+
+          linenum=0
+          cat "${d}/fonts.dir" | while read i1 i2 i3 i4 ; do
+              linenum=$((${linenum} + 1))
+              [ ${linenum} -eq 1 ] && continue
+
+              if [ ! -f "${d}/${i1}" ] ; then
+                  echo "ERROR: ${d}/fonts.dir line ${linenum} has non-exististant font \"${i1}\" (=\"${i1} ${i2} ${i3} ${i4}\")"
+              fi
+          done
+      done
+    ) 2>&1 | while read i ; do echo "  $i" ; done
+    echo "## Testing font paths end."
+    
+    echo "##### Diag End $(date)."
+}
+
+# Set platform-defaults for setup_config()
+setup_config_defaults()
+{
+    curr_num_xpstart="${1}"
+    
+    #### Defaults for Linux/Solaris
+    # Start Xprt using builtin XPCONFIGDIR at a free display numer
+    # (Solaris(=SunOS5.x)'s /usr/openwin/bin/Xprt supports TrueType fonts,
+    # therefore we don't need to filter them)
+                      xpstart_fontpath[${curr_num_xpstart}]="";
+        xpstart_fontpath_acceptpattern[${curr_num_xpstart}]=".*";
+        xpstart_fontpath_rejectpattern[${curr_num_xpstart}]="/Speedo|/F3bitmaps|/F3";
+                     xpstart_displayid[${curr_num_xpstart}]="";
+                   xpstart_xpconfigdir[${curr_num_xpstart}]="";
+                        xpstart_xpfile[${curr_num_xpstart}]="";
+                    xpstart_auditlevel[${curr_num_xpstart}]="4";
+                       xpstart_options[${curr_num_xpstart}]="";
+                        xpstart_logger[${curr_num_xpstart}]="";
+    # Check whether we have /dev/stderr (needed for old AIX + old Debian)
+    if [ -w "/dev/stderr" ] ; then
+                       xpstart_logfile[${curr_num_xpstart}]="/dev/stderr";
+    else
+                       xpstart_logfile[${curr_num_xpstart}]="/dev/tty";
+    fi
+                   xpstart_xprt_binary[${curr_num_xpstart}]="";
+
+    # Custom rules for the GISWxprintglue package on Solaris
+    # (which uses Solaris's /usr/openwin/bin/Xprt but a custom config)
+    if [ "${XPCUSTOMGLUE}" = "GISWxprintglue" ] ; then
+        xpstart_xpconfigdir[${curr_num_xpstart}]="/opt/GISWxprintglue/server/etc/XpConfig"
+        xpstart_xprt_binary[${curr_num_xpstart}]="/usr/openwin/bin/Xprt"
+    fi
+    # Custom rules for the GISWxprint package on Solaris
+    # (which uses both it's own Xprt and a custom config)
+    if [ "${XPCUSTOMGLUE}" = "GISWxprint" ] ; then
+        xpstart_xpconfigdir[${curr_num_xpstart}]="/opt/GISWxprint/server/etc/XpConfig"
+        xpstart_xprt_binary[${curr_num_xpstart}]="/opt/GISWxprint/bin/Xprt"
+        xpstart_font_encodings_dir[${curr_num_xpstart}]="/opt/GISWxprint/lib/X11/fonts/encodings/encodings.dir"
+    fi
+    
+    #######################################################
+    ###
+    ### Debian Xprint package default configuration
+    ###
+    if [ "${XPCUSTOMGLUE}" = "DebianGlue" ] ; then
+        # Set XPCONFIGDIR=/usr/share/Xprint/xserver
+        xpstart_xpconfigdir[${curr_num_xpstart}]="/usr/share/Xprint/xserver";
+
+        # Use fixed display ID (":64"), or else all client programs will have to be
+        # restarted simply to update XPSERVERLIST to the latest ID when upgrading,
+        # which would be a nightmare.
+        xpstart_displayid[${curr_num_xpstart}]=64;
+
+        # Do not send any messages to console
+        xpstart_logfile[${curr_num_xpstart}]="/dev/null";
+
+        # By default use binary provided by Debian's "xprt-xprintorg" package
+        # (=/usr/bin/Xprt), otherwise leave blank (e.g. use script's default
+        # (=/usr/X11R6/bin/Xprt))
+        if [ -x "/usr/bin/Xprt" ] ; then
+            xpstart_xprt_binary[${curr_num_xpstart}]="/usr/bin/Xprt";
+        fi
+    fi
+    ###
+    ### End Debian default configuration
+    ###
+    #######################################################
+}
+
+fetch_etc_initd_xprint_envvars()
+{
+    curr_num_xpstart="${1}"
+
+    ## Process some $ETC_INITD_XPRINT_* vars after all which may be used by
+    # a user to override the hardcoded values here when starting Xprt per-user
+    # (a more flexible way is to provide an own setup config script in
+    # "~./Xprint_per_user_startup" - see above)
+    if [ "${ETC_INITD_XPRINT_XPRT_PATH}" != "" ] ; then
+        xpstart_xprt_binary[${curr_num_xpstart}]="${ETC_INITD_XPRINT_XPRT_PATH}"
+    fi
+    if [ "${ETC_INITD_XPRINT_XPCONFIGDIR}" != "" ] ; then
+        xpstart_xpconfigdir[${curr_num_xpstart}]="${ETC_INITD_XPRINT_XPCONFIGDIR}"
+    fi
+    if [ "${ETC_INITD_XPRINT_XPFILE}" != "" ] ; then
+        xpstart_xpfile[${curr_num_xpstart}]="${ETC_INITD_XPRINT_XPFILE}"
+    fi
+    if [ "${ETC_INITD_XPRINT_LOGFILE}" != "" ] ; then
+        xpstart_logfile[${curr_num_xpstart}]="${ETC_INITD_XPRINT_LOGFILE}"
+    fi
+    if [ "${ETC_INITD_XPRINT_DISPLAYID}" != "" ] ; then
+        xpstart_displayid[${curr_num_xpstart}]="${ETC_INITD_XPRINT_DISPLAYID}"
+    fi
+    if [ "${ETC_INITD_XPRINT_FONTPATH}" != "" ] ; then
+        xpstart_fontpath[${curr_num_xpstart}]="${ETC_INITD_XPRINT_FONTPATH}"
+    fi
+    if [ "${ETC_INITD_XPRINT_XPRT_OPTIONS}" != "" ] ; then
+        xpstart_options[${curr_num_xpstart}]="${ETC_INITD_XPRINT_XPRT_OPTIONS}"
+    fi
+    if [ "${ETC_INITD_XPRINT_AUDITLEVEL}" != "" ] ; then
+        xpstart_auditlevel[${curr_num_xpstart}]="${ETC_INITD_XPRINT_AUDITLEVEL}"
+    fi
+    if [ "${ETC_INITD_XPRINT_XF86ENCODINGSDIR}" != "" ] ; then
+        xpstart_font_encodings_dir[${curr_num_xpstart}]="${ETC_INITD_XPRINT_XF86ENCODINGSDIR}"
+    fi
+}
+
+############################################################################
+# setup_config() sets the configuration parameters used to start one
+# or more Xprint servers ("Xprt").
+# The following variables are used:
+# - "num_xpstart" - number of servers to start
+# - "xpstart_fontpath[index]" - custom font path. Leave blank if you want
+#   the platform-specific default
+# - "xpstart_fontpath_acceptpattern[index]" - extended regular expression
+#   (see egrep(1)) used to filter the font path - items only pass this
+#   filter if they match the pattern (leave blank if you want to filter
+#   nothing)
+# - "xpstart_fontpath_rejectpattern[index]" - extended regular expression
+#   (see egrep(1)) used to filter the font path - items only pass this
+#   filter if they do not match the pattern (leave blank if you want to
+#   filter nothing)
+# - "xpstart_font_encodings_dir[index]" - location of "encodings.dir".
+#   Leave blank to use the default.
+# - "xpstart_displayid[index]" - display id to use for the Xprint server
+#   (leave blank to choose the next available free display id)
+# - "xpstart_xpconfigdir[index]" - value for custom XPCONFIGDIR (leave blank
+#   if you don not want that that XPCONFIGDIR is set at Xprt startup)
+# - "xpstart_xpfile[index]" - value used for Xprt's "-XpFile" option (leave
+#   blank if you do not want to set this option)
+# - "xpstart_auditlevel[index]" - set Xserver auditing level (leave blank to
+#   use no auditing)
+# - "xpstart_options[index]" - set further Xprt options (leave blank to set
+#   no further options)
+# - "xpstart_logger[index]" - utility which gets stderr/stdout messages from
+#   Xprt and sends them to a logging daemon. Leave blank to use /usr/bin/logger
+#   to send such messages to the lpr.notice syslog)
+# - "xpstart_logfile[index]" - log file to append stderr/stdout messages from
+#   Xprt to. Leave blank to send messages to /dev/null
+# - "xpstart_xprt_binary[index]" - set custom Xprt binary (leave blank to use
+#   the platform-specifc default)
+setup_config()
+{
+    num_xpstart=0;
+    
+    if [ "${ETC_INITD_XPRINT_CUSTOM_SETUP_CONFIG}" != "" ] ; then
+        user_cfg="${ETC_INITD_XPRINT_CUSTOM_SETUP_CONFIG}"
+    else
+        user_cfg="${HOME}/.Xprint_per_user_startup"
+    fi
+    
+    # Source per-user ~/.Xprint_per_user_startup file if there is one
+    # (and do not use the script's defaults below)
+    if [ -r "${user_cfg}" ] ; then
+        # Define API version which should be checked by ${HOME}/.Xprint_per_user_startup
+        # ${HOME}/.Xprint_per_user_startup should bail-out if the version differ
+        etc_initd_xprint_api_version=2
+        
+        # Source per-user settings script
+        . "${user_cfg}"
+        
+        # done with setting the config for per-user Xprt instances
+        return 0;
+    else
+        # Use /etc/init.d/xprint's builtin config
+        # Each entry should start with |setup_config_defaults| to pull the
+        # platform defaults and finish with |num_xpstart=$(($num_xpstart + 1))|
+        # to end the entry
+        
+        # Set platform-defaults
+        setup_config_defaults "${num_xpstart}"
+
+        ## -- snip --
+
+        # Admins can put their stuff "in" here...
+
+        ## -- snip --
+
+        # Override script's builtin values with those a user may set via the
+        # $ETC_INIITD_XPRINT_* env vars
+        fetch_etc_initd_xprint_envvars "${num_xpstart}"
+
+        num_xpstart=$((${num_xpstart} + 1))
+
+        return 0;
+    fi
+
+    #### Sample 1:
+    # # Start Xprt on a free display ID with custom XPCONFIGDIR and without
+    # # Speedo and TrueType fonts
+    #    xpstart_fontpath_rejectpattern[$num_xpstart]="/Speedo|/TrueType|/TT(/$|$)|/TTF(/$|$)";
+    #               xpstart_xpconfigdir[$num_xpstart]="/home/gisburn/cwork/Xprint/Xprt_config/XpConfig";
+    #                xpstart_auditlevel[$num_xpstart]="4";
+    #                   xpstart_options[$num_xpstart]="-ac -pn";
+    #num_xpstart=$(($num_xpstart + 1))
+
+
+    #### Sample 2: 
+    # # Start Xprt without TrueType fonts on a display 55 with custom
+    # # XPCONFIGDIR
+    #    xpstart_fontpath_rejectpattern[$num_xpstart]="/TrueType|/TT(/$|$)|/TTF(/$|$)";
+    #                 xpstart_displayid[$num_xpstart]=55;
+    #               xpstart_xpconfigdir[$num_xpstart]="/home/gisburn/cwork/Xprint/Xprt_config/XpConfig";
+    #                xpstart_auditlevel[$num_xpstart]=4;
+    #                   xpstart_options[$num_xpstart]="-ac -pn";
+    #num_xpstart=$(($num_xpstart + 1))
+
+    #### Sample 3: 
+    # # Start Xprt without TrueType fonts on a display 56 with custom
+    # # XPCONFIGDIR and alternate "Xprinters" file
+    #    xpstart_fontpath_rejectpattern[$num_xpstart]="/TrueType|/TT(/$|$)|/TTF(/$|$)";
+    #                 xpstart_displayid[$num_xpstart]=56;
+    #               xpstart_xpconfigdir[$num_xpstart]="/etc/XpConfig/default";
+    #                    xpstart_xpfile[$num_xpstart]="/etc/XpConfig/default/Xprinters_test2"
+    #                xpstart_auditlevel[$num_xpstart]="4";
+    #                   xpstart_options[$num_xpstart]="-ac -pn";
+    #               xpstart_xprt_binary[$num_xpstart]="";
+    #num_xpstart=$(($num_xpstart + 1))
+
+    #### Sample 4:
+    # # Start Xprt with Solaris ISO-8859-7 (greek(="el") locale) fonts on
+    # # display 57
+    #                  xpstart_fontpath[$num_xpstart]="/usr/openwin/lib/locale/iso_8859_7/X11/fonts/75dpi,/usr/openwin/lib/locale/iso_8859_7/X11/fonts/Type1,/usr/openwin/lib/X11/fonts/misc/";
+    #    xpstart_fontpath_acceptpattern[$num_xpstart]="";
+    #    xpstart_fontpath_rejectpattern[$num_xpstart]="_No_Match_";
+    #                 xpstart_displayid[$num_xpstart]="57";
+    #                xpstart_auditlevel[$num_xpstart]="4";
+    #                   xpstart_options[$num_xpstart]="-ac -pn";
+    #num_xpstart=$(($num_xpstart + 1))
+
+    #### Sample 5:
+    # # Start Xprt with the font list of an existing Xserver (excluding Speedo fonts) on
+    # # display 58
+    # # Note that this only works within a X session. At system boot time
+    # # there will be no $DISPLAY to fetch the information from!!
+    #                  xpstart_fontpath[$num_xpstart]="$(get_fontlist_from_display ${DISPLAY} | fontlist2fontpath)";
+    #    xpstart_fontpath_acceptpattern[$num_xpstart]="";
+    #    xpstart_fontpath_rejectpattern[$num_xpstart]="";
+    #                 xpstart_displayid[$num_xpstart]="58";
+    #               xpstart_xpconfigdir[$num_xpstart]="";
+    #                xpstart_auditlevel[$num_xpstart]="4";
+    #                   xpstart_options[$num_xpstart]="-ac -pn";
+    #               xpstart_xprt_binary[$num_xpstart]="";
+    #num_xpstart=$(($num_xpstart + 1))
+
+    #### Sample 6:
+    # # List remote Xprt's here 
+    # # (note that there is no test to check whether these DISPLAYs are valid!)
+    #             xpstart_remote_server[$num_xpstart]="sera:12"    ; num_xpstart=$(($num_xpstart + 1))
+    #             xpstart_remote_server[$num_xpstart]="gandalf:19" ; num_xpstart=$(($num_xpstart + 1))   
+}
+
+############################################################################
+
+# Main
+case "$1" in
+    ## Start Xprint servers
+    'start')
+        do_start
+        ;;
+
+    ## Stop Xprint servers
+    # Note that this does _not_ kill Xprt instances started using this script 
+    # by non-root users
+    'stop')
+        do_stop
+        ;;
+
+    ## Restart Xprint servers
+    'restart')
+        do_restart
+        ;;
+
+    ## Reload configuration without stopping and restarting
+    'reload')
+        # not supported
+        msg "reload not supported, use 'restart' or 'force-reload'"
+        exit 3
+        ;;
+
+    ## Restart Xprint only if it is already running
+    'condrestart'|'try-restart'|'force-reload')
+        # only restart if it is already running
+        [ -f /var/lock/subsys/xprint ] && do_restart || :
+        ;;
+    
+    ## Get list of all Xprint servers for this user
+    # (incl. per-user and system-wide instances)    
+    'get_xpserverlist')
+        do_get_xpserverlist
+        ;;
+
+    ## Get status of Xprint servers, RedHat-style
+    'status')
+        x="$(do_get_xpserverlist)"
+        if [ "${x}" != "" ] ; then
+            msg "Xprint (${x}) is running..."
+            exit 0
+        else
+            msg "Xprint is stopped"
+            exit 3
+        fi 
+        ;;
+        
+    ## Wrapper
+    'wrapper')
+        cmd="${2}"
+        [ "${cmd}" = "" ] && fatal_error "No command given."
+        shift ; shift
+        export XPSERVERLIST="$(do_get_xpserverlist)"
+        [ "${XPSERVERLIST}" = "" ] && fatal_error "No Xprint servers found."
+        exec "${cmd}" "$@"
+        ;;
+
+    ## Wrapper for "xplsprinters"
+    'lsprinters')
+        [                  "${ETC_INITD_XPRINT_XPLSPRINTERS_PATH}" != "" ] && cmd="${ETC_INITD_XPRINT_XPLSPRINTERS_PATH}"
+        [ ! -x "${cmd}" -a "${XPCUSTOMGLUE}" = "GISWxprintglue"          ] && cmd="/opt/GISWxprintglue/bin/xplsprinters"
+        [ ! -x "${cmd}" -a "${XPCUSTOMGLUE}" = "GISWxprint"              ] && cmd="/opt/GISWxprint/bin/xplsprinters"
+        [ ! -x "${cmd}" -a "${XPROJECTROOT}" != ""                       ] && cmd="${XPROJECTROOT}/bin/xplsprinters"
+        [ ! -x "${cmd}"                                                  ] && cmd="/usr/bin/xplsprinters"
+        [ ! -x "${cmd}"                                                  ] && cmd="xplsprinters"
+
+        shift
+        export XPSERVERLIST="$(do_get_xpserverlist)"
+        [ "${XPSERVERLIST}" = "" ] && fatal_error "No Xprint servers found."
+        exec "${cmd}" "$@"
+        ;;
+
+    ## Diagnostics
+    'diag')
+        do_diag
+        ;;
+    
+    ## Print usage
+    *)
+        msg "Usage: $0 { start | stop | restart | force-reload | status | condrestart | try-restart | wrapper | lsprinters | get_xpserverlist | diag }"
+        exit 2
+esac
+exit 0
+
+# EOF.
--- xorg-server-1.4.2.orig/debian/control
+++ xorg-server-1.4.2/debian/control
@@ -0,0 +1,260 @@
+Source: xorg-server
+Section: x11
+Priority: optional
+Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
+Uploaders: David Nusinow <dnusinow@debian.org>, Steve Langasek <vorlon@debian.org>, Julien Cristau <jcristau@debian.org>, Drew Parsons <dparsons@debian.org>, Brice Goglin <bgoglin@debian.org>
+# all the Build-Depends up to x11proto-xf86-dri-dev are for the normal Xorg
+# server, and common dependencies for the DIX.
+# x11proto-xf86dri-dev and libdrm-dev are for DRI support for the Xorg server.
+# x11proto-print-dev and libfreetype6-dev are for Xprint
+# everything on is for the DMX and Xnest servers.
+Build-Depends: debhelper (>= 4.0.0), lsb-release, pkg-config, bison, flex,
+ x11proto-bigreqs-dev, x11proto-composite-dev (>= 1:0.4), x11proto-core-dev (>= 7.0.9),
+ x11proto-damage-dev (>= 1.1), x11proto-evie-dev, x11proto-fixes-dev (>= 4.0),
+ x11proto-kb-dev (>= 1.0.3), x11proto-xinerama-dev, x11proto-randr-dev (>= 1.2),
+ x11proto-record-dev, x11proto-render-dev (>= 2:0.9.3), x11proto-resource-dev,
+ x11proto-scrnsaver-dev, x11proto-trap-dev, x11proto-video-dev,
+ x11proto-xcmisc-dev, x11proto-xext-dev (>= 6.9.99.0),
+ x11proto-xf86bigfont-dev, x11proto-xf86dga-dev, x11proto-xf86misc-dev,
+ x11proto-xf86vidmode-dev, xtrans-dev, libxau-dev (>= 1:0.99.1),
+ x11proto-input-dev (>= 1.4.2),
+ libxdmcp-dev (>= 1:0.99.1), libxfont-dev, libfontenc-dev,
+ libxkbfile-dev (>= 1:0.99.1), libpixman-1-dev (>= 0.9.4-2),
+ x11proto-xf86dri-dev, libdrm-dev (>= 2.3.0) [!hurd-i386], 
+ x11proto-print-dev, libfreetype6-dev, xfonts-utils,
+ mesa-swx11-source (>> 7.0.1~rc2-1),
+ x11proto-gl-dev (>= 1.4.8), libgl1-mesa-dev (>= 6.5.1),
+ libxmuu-dev (>= 1:0.99.1), libxext-dev (>= 1:0.99.1),
+ libx11-dev (>= 1:0.99.2), libxrender-dev (>= 1:0.9.0),
+ libxi-dev (>= 1:0.99.1), x11proto-dmx-dev, quilt, libdmx-dev (>= 1:1.0.1),
+ libxpm-dev (>= 1:3.5.3), libxaw7-dev (>= 1:0.99.1),
+ libxt-dev (>= 1:0.99.1), libxmu-dev (>= 1:0.99.1),
+ libxtst-dev (>= 1:0.99.1), libxres-dev (>= 1:0.99.1),
+ libxfixes-dev (>= 1:3.0.0), libdbus-1-dev [!hurd-i386], libhal-dev [!hurd-i386]
+Build-Conflicts: xlibs-static-dev
+Standards-Version: 3.7.3
+Vcs-Git: git://git.debian.org/git/pkg-xorg/xserver/xorg-server
+Vcs-Browser: http://git.debian.org/?p=pkg-xorg/xserver/xorg-server.git
+
+Package: xserver-xorg-core
+Architecture: any
+Depends: x11-common (>= 1:7.0.0), ${shlibs:Depends}, ${misc:Depends}, xserver-xorg
+Recommends: xkb-data, xfonts-base
+Suggests: xfonts-100dpi | xfonts-75dpi, xfonts-scalable
+Conflicts: xserver-xorg (<< 6.8.2-38), xserver-xfree86 (<< 1:7.0.0),
+ xserver-xorg-video, xserver-common, xserver-xorg-video-1.0, xserver-xorg-input,
+ xserver-xorg-video-1.9, xserver-xorg-input-wacom (<< 0.7.8)
+Replaces: xserver-xorg (<< 6.8.2-38), xserver-xfree86 (<< 1:7.0.0),
+ xserver-common
+Provides: xserver
+Description: Xorg X server - core server
+ The Xorg X server is an X server for several architectures and operating
+ systems, which is derived from the XFree86 4.x series of X servers.
+ .
+ The Xorg server supports most modern graphics hardware from most vendors,
+ and supersedes all XFree86 X servers.
+ .
+ The Xorg server either needs fonts installed on the local host, or needs to
+ know of a remote hosts that provides font services (with xfs, for instance).
+ The former means that fonts packages are mandatory. The latter means that
+ font packages may be gratuitous. To err on the side of caution, install at
+ least the xfonts-base, xfonts-100dpi or xfonts-75dpi, and xfonts-scalable
+ packages.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xserver-xorg-dev
+Architecture: any
+Depends: ${misc:Depends}, libpixman-1-dev, x11proto-core-dev, x11proto-input-dev (>= 1.4), x11proto-xext-dev, x11proto-video-dev, x11proto-randr-dev (>= 1.2), x11proto-render-dev (>= 2:0.9.3), x11proto-fonts-dev
+Description: Xorg X server - development files
+ This package provides development files for the X.Org ('Xorg') X server.
+ This is not quite the same as the DDK (Driver Development Kit) from the
+ XFree86 4.x and X.Org 6.7, 6.8 and 6.9 series of servers; it provides
+ headers and a pkg-config file for drivers using autotools to build
+ against.
+ .
+ Unless you are developing or building a driver, you probably want
+ xserver-xorg and/or xserver-xorg-core instead.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xdmx
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: distributed multihead X server
+ Xdmx is a proxy X server that uses one or more other X servers as its
+ display device(s). It provides multi-head X functionality for displays that
+ might be located on different machines. Xdmx functions as a front-end X server
+ that acts as a proxy to a set of back-end X servers. All of the visible
+ rendering is passed to the back-end X servers. Clients connect to the Xdmx
+ front-end, and everything appears as it would in a regular multi-head
+ configuration. If Xinerama is enabled (e.g., with +xinerama on the command
+ line), the clients see a single large screen.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xdmx-tools
+Architecture: any
+Depends: xdmx, ${shlibs:Depends}, ${misc:Depends}
+Replaces: xdmx (<= 2:1.1.1-10)
+Description: Distributed Multihead X tools
+ This package provides a collection of tools used for administration of
+ the Xdmx server; see the xdmx package for more information.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xnest
+Architecture: any
+Depends: x11-common, ${shlibs:Depends}, ${misc:Depends}
+Description: Nested X server
+ Xnest is a nested X server that simply relays all its requests to another
+ X server, where it runs as a client.  This means that it appears as another
+ window in your current X session.  Xnest relies upon its parent X server
+ for font services.
+ .
+ Use of the Xephyr X server instead of Xnest is recommended.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xvfb
+Architecture: any
+Depends: x11-common, ${shlibs:Depends}, ${misc:Depends}
+Recommends: xbase-clients, xfonts-base
+Description: Virtual Framebuffer 'fake' X server
+ Xvfb provides an X server that can run on machines with no display hardware
+ and no physical input devices. It emulates a dumb framebuffer using virtual
+ memory. The primary use of this server was intended to be server testing,
+ but other novel uses for it have been found, including testing clients
+ against unusual depths and screen configurations, doing batch processing with
+ Xvfb as a background rendering engine, load testing, as an aid to porting the
+ X server to a new platform, and providing an unobtrusive way to run
+ applications that don't really need an X server but insist on having one
+ anyway.
+ .
+ This package also contains a convenience script called xvfb-run which
+ simplifies the automated execution of X clients in a virtual server
+ environment. This convenience script requires the use of the xauth
+ program.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xserver-xephyr
+Architecture: any
+Depends: x11-common, ${shlibs:Depends}, ${misc:Depends}
+Recommends: xbase-clients, xfonts-base
+Description: nested X server
+ Xephyr is an X server that can be run inside another X server,
+ much like Xnest. It is based on the kdrive X server, and as a
+ result it supports newer extensions than Xnest, including render and
+ composite.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+#Package: xserver-xfbdev
+#Architecture: alpha amd64 arm armeb armel hppa i386 ia64 lpia m32r m68k mips mipsel powerpc ppc64 sh3 sh3eb sh4 sh4eb sparc
+#Depends: ${shlibs:Depends}, ${misc:Depends}
+#Recommends: xbase-clients
+#Description: Linux framebuffer device tiny X server
+# xserver-xfbdev is a Linux framebuffer device tiny X server based on the
+# kdrive X server.
+# .
+# More information about X.Org can be found at:
+# <URL:http://www.X.org>
+# <URL:http://xorg.freedesktop.org>
+# <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+# .
+# This package is built from the X.org xserver module.
+
+Package: xprint
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, xprint-common, libxfont1 (>= 1:1.1)
+Recommends: xprint-utils
+Conflicts: xprt (<= 4.3.0.dfsg.1-10)
+Description: X11 print system (binary)
+ Xprint is an advanced printing system which enables X11 applications
+ to use devices like printers, fax or create documents in formats like
+ PostScript, PDF, PCL, etc.
+ .
+ This package provides Xprt, the Xprint server compiled from
+ xprint.mozdev.org, an X.org subproject. Xprint provides superior support
+ for printing from Mozilla, including non-Latin characters and MathML.
+ TrueType fonts are supported.
+ .
+ Xprint uses ttf2pt1 internally for some font support.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xprint-common
+Architecture: all
+Depends: xbase-clients, xfonts-encodings, x11-common (>= 1:7.0.12), ${shlibs:Depends}, ${misc:Depends}
+Recommends: xprint, xfonts-base
+Conflicts: xprt-common
+Replaces: xprt-common
+Description: Xprint - the X11 print system (configuration files)
+ Xprint is an advanced printing system which enables X11 applications
+ to use devices like printers, FAX or create documents in formats like
+ PostScript, PDF, PCL, etc.
+ .
+ This package provides the configuration and Postscript definition files
+ required to run Xprt, the Xprint server. Xprt is provided by xprint.
+ .
+ More information about X.Org can be found at:
+ <URL:http://www.X.org>
+ <URL:http://xorg.freedesktop.org>
+ <URL:http://lists.freedesktop.org/mailman/listinfo/xorg>
+ .
+ This package is built from the X.org xserver module.
+
+Package: xserver-xorg-core-dbg
+Architecture: any
+Depends: xserver-xorg-core (= ${binary:Version})
+Priority: extra
+Description: Xorg - the X.Org X server (debugging symbols)
+ The Xorg X server is an X server for several architectures and operating
+ systems, which is derived from the XFree86 4.x series of X servers.
+ .
+ The Xorg server supports most modern graphics hardware from most vendors,
+ and supersedes all XFree86 X servers.
+ .
+ This package provides debugging symbols for the Xorg X server and associated
+ modules.
--- xorg-server-1.4.2.orig/debian/README.printing-problems
+++ xorg-server-1.4.2/debian/README.printing-problems
@@ -0,0 +1,162 @@
+Printing Problems
+-----------------
+
+This file is a mini-FAQ for two printing problems:
+
+Q1) Spaces between words are lost (words run together)
+
+Q2) Image is too big (font size too large) 
+    OR 
+    Image is too small (only takes up 1/4 of the page)
+
+
+=======================================================================
+Q1) Spaces between words are lost (words run together)
+
+At the time of the release of sarge, there is an unresolved problem
+printing certain webpages from firefox using Xprint. The problem has been
+reproduced with mozilla-firefox (0.9.3-2) and xprint (0.1.0.alpha1), 
+although the situation seems to have improved with firefox 1.0.1.
+
+mozilla proper (mozilla-browser 2:1.7.2-2) does not exhibit the
+problem, it prints fine on the package maintainer's system, although 
+others have unfortunately reported seeing the problem there. 
+
+The symptom of the problem is that spaces between words are lost,
+words are printed strung all together. The font may be sans-serif,
+where serif font is displayed on screen.
+
+The problem appears to happen on pages where the font is not
+explicitly chosen in the HTML code. An example is Debian's home page,
+www.debian.org.  Other pages which specify the font to be used do not
+seem to be affected.
+
+There are three known workarounds for the problem.
+
+1) Only use the default fonts in mozilla/firefox.
+
+   The printing error will start happening if you change font settings 
+   using Edit->Preferences (in particular if you set the serif font). 
+   Changing the setting back again to the default value of "serif" will 
+   not fix the problem.
+   
+   This is because setting the font places a "font.name.serif.x-western" 
+   entry into ~/.mozilla/firefox/default.***/prefs.js.  Even if the value 
+   of the entry is "serif", it's mere presence will ruin printing.
+   
+   The workaround is to manually delete the "font.name.serif.x-western" 
+   entry from prefs.js.
+   
+   This seems to fix the problem with the Debian home page, but depending 
+   the page and language you want to print with you might find you will need
+   to delete other font.name entries as well.
+
+2) Remove Xprint's own font directory.
+
+   Xprint contains font information in the directory
+   /usr/share/Xprint/xserver/C/print/models/PSdefault/fonts
+   If this directory is removed, then firefox prints www.debian.org
+   with correct spacing between words.  The font used is sans-serif.
+   Xprint obtains information about fonts from other parts of the system.
+   
+   Since this workaround has not been fully tested and its consequences
+   are not fully understood (other locales and printer models in
+   Xprint link to this directory), the fonts directory will be left
+   intact for the official release of Xprint in Debian.
+   
+   A side-effect is that the date stamps for news entries on
+   www.debian.org are rendered using sans-serif font, where they
+   ought to be, I believe, rendered using a monospace font.
+   
+   
+3) Use default stylesheet settings for firefox.
+
+   User directories for firefox contain sample default style settings
+   in the chrome directory, at
+   ~/.firefox/default/<user-key>/chrome/userContent-example.css
+   This file, userContent-example.css, can be renamed to userContent.css,
+   and the following style added:
+
+@media print {
+	body {
+        	font-family: times, serif;
+	}
+	tt, pre {
+		font-family: courier, monospace;
+	}
+}
+
+   This will instruct firefox to use serif font for the main text of web
+   pages where the default font is not specified. The spacing between
+   words will be rendered correctly.
+   
+   System administrators wishing to provide this style snippet
+   automatically to all users will want to make the adjustments in
+   /usr/lib/mozilla-firefox/defaults/profile/chrome/
+   
+   Note, the same can be done for mozilla proper, if needed.
+
+
+The problem is being tracked on the Debian Bug Tracking System at bugs
+#235592 and #251067, and upstream at
+http://xprint.freedesktop.org/bugzilla/show_bug.cgi?id=1112
+
+
+========================================================================
+Q2) Image is too big (font size too large) 
+    OR 
+    Image is too small (only takes up 1/4 of the page)
+
+This question is a standard Xprint FAQ (Q70).
+
+The problem means your default printer resolution is set to the wrong 
+value.  The value is set in /etc/Xprint/C/print/attributes/document (or possibly
+en_US/print/... rather than C/print/..., depending on your locale):
+
+*default-printer-resolution: 600
+
+The standard default value is set to 600dpi.  If your printer can only handle 
+300dpi, then four pixels (2x2) will be used for every one in your image, making
+it print on paper larger than it ought to. The solution is to change the default
+resolution to 300.
+
+Likewise if the default value is set to 300, but your printer can only handle
+600dpi, then the pixels will only take up half the space on paper that they are
+supposed to, so the image will only occupy a quarter of the page (1/2 x 1/2).
+This problem was often reported under previous versions of Xprint, before the 
+default resolution was set to 600.  In the latest version we have made the 
+assumption that 300dpi printers are today relatively rare, and so have set the
+default value to 600. A side-effect is the first problem discussed in the 
+previous paragraph, for 300dpi-only printers.
+
+For your convenience, a debconf question has been provided enabling you to set
+the default resolution at installation time (or after running 
+"dpkg-reconfigure xprint-common").
+
+Note that these problems do not affect all printers. Some 600dpi printers will
+happily render 300dpi images, using a 2x2 block for each pixel in the image to
+give a normal physical image size on paper.
+
+Your printer's resolutions may possibly also need to be set consistently in the 
+underlying spooler. For instance CUPS settings can usually be accessed at 
+http://localhost:631/printers (use the "Configure Printer" link).
+
+If you have different printers which need to be run at different resolutions,
+you will need to manually set a value for default-printer-resolution for each printer
+separately (that is, for each one which differs from the default value). 
+See FAQ Q211. For instance, if the printer named "old_printer" needs to run at 
+300 dpi, while others work at 600dpi, then you need to use:
+*default-printer-resolution: 600
+old_printer.default-printer-resolution: 300
+
+We can't please everybody all the time!  Please set your default resolution
+according to your own needs.  We hope that in a future version, Xprint will be
+able to set these values dynamically from the underlying printing spooler 
+(CUPS, if not others).  Watch http://bugzilla.mozdev.org/show_bug.cgi?id=5517 
+for further developments.
+
+
+
+Good luck!
+
+Drew Parsons <dparsons@debian.org>, 15 Mar 2005.
--- xorg-server-1.4.2.orig/debian/xprint.install
+++ xorg-server-1.4.2/debian/xprint.install
@@ -0,0 +1 @@
+usr/bin/Xprt
--- xorg-server-1.4.2.orig/debian/xserver-xorg-core.install
+++ xorg-server-1.4.2/debian/xserver-xorg-core.install
@@ -0,0 +1,17 @@
+etc/X11/xserver/SecurityPolicy
+usr/lib/xorg/modules/*.so
+usr/lib/xorg/modules/extensions/*.so
+usr/lib/xorg/modules/fonts/*
+usr/lib/xorg/modules/linux/*.so
+usr/lib/xorg/modules/freebsd/*.so
+usr/lib/xorg/modules/multimedia/*.so
+usr/bin/Xorg
+usr/share/man/man1/Xserver.1
+usr/share/man/man1/Xorg.1
+usr/share/man/man4/exa.4
+usr/share/man/man4/fbdevhw.4
+usr/share/man/man5/xorg.conf.5
+usr/bin/cvt
+usr/bin/gtf
+usr/share/man/man1/cvt.1
+usr/share/man/man1/gtf.1
--- xorg-server-1.4.2.orig/debian/xserver-xephyr.install
+++ xorg-server-1.4.2/debian/xserver-xephyr.install
@@ -0,0 +1 @@
+usr/bin/Xephyr
--- xorg-server-1.4.2.orig/debian/xserver-xfbdev.install
+++ xorg-server-1.4.2/debian/xserver-xfbdev.install
@@ -0,0 +1 @@
+usr/bin/Xfbdev
--- xorg-server-1.4.2.orig/debian/watch
+++ xorg-server-1.4.2/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://xorg.freedesktop.org/releases/individual/xserver/ xorg-server-(.*)\.tar\.gz
--- xorg-server-1.4.2.orig/debian/xprint-common.README.Debian
+++ xorg-server-1.4.2/debian/xprint-common.README.Debian
@@ -0,0 +1,82 @@
+xprint for Debian
+===========================
+
+This package supplies Xprt, the Xprint server.  It is able to work with the
+mozilla printing system, allowing non-latin characters and MathML to be
+printed, among other improvements over the default mozilla printing driver. 
+
+
+Running the Xprint server
+-----------------------
+
+The Xprint server is started and stopped via /etc/init.d/xprint, 
+provided in package xprint-common.
+
+As of version 0.0.8, Xprint supports TrueType fonts.
+
+Xprint requires a print server such as lprng or CUPS to be installed.  It
+uses lpc or lpstat to identify available printers.
+
+The Xprint server is not registered in /etc/inetd.conf.  If you require the use
+of the Xprint server across a network, you will be responsible for
+this yourself (use update-inetd to register the server). Note that
+this question is not the same as using a networked printer via a local
+Xprint server.  The printers themselves are configured via /etc/cups/printers.conf,
+/etc/printcap or similar, independently of Xprint.
+
+
+-----------------------------
+Xprint server will not start:
+Error: could not open default font 'fixed'
+
+Some users have reported experiencing this problem, which prevents Xprt from 
+starting.  We have not yet been able to precisely pinpoint the cause of the
+problem. It appears to happen when some TrueType fonts are not correctly 
+installed.  It may be that Xprt finds the bad fonts and quits working through
+the font list, rather than simply ignoring the bad fonts as it ought to. Hence 
+Xprt does not manage to get to the font directory in the font list containing
+the fixed fonts.
+
+Some users have reported a workaround in /etc/init.d/xprint:
+In line 343, use
+    "sort -u -r"
+instead of
+    "sort -u"
+
+This has not been patched in to the package since it does not actually fix 
+the problem, it simply provides an alternative means of (hopefully) finding a
+fixed font, by reversing the order in which font directories are searched.
+
+
+
+Running Xprint clients
+----------------------
+
+Client programs such as mozilla will require the Xprint server to be 
+identified in variable XPSERVERLIST. This variable is automatically defined
+for all X sessions in /etc/X11/Xsession.d/92xprint-xpserverlist.sh. If
+required, the value for this variable can be obtained manually using
+/etc/init.d/xprint, via "/etc/init.d/xprint get_xpserverlist". 
+
+You may find it helpful to define your default printer, with, for example,
+	export LPDEST=lp
+Unfortunately, default printers set within CUPS are not currently
+recognised.
+
+You can test that Xprt is working by running xplsprinters. 
+xphelloworld prints a simple test page.  Both these test programs are provided 
+by xprint, along with a handful of others.
+
+
+Printing Problems
+-----------------
+
+If you experience the problem that words are run together on the
+printed page with no spaces between them, then please read
+README.printing-problems for further instructions.
+
+This file also describes how to change the printer resolution settings if your
+image on paper is printed too large or too small.
+
+
+ -- Drew Parsons <dparsons@debian.org>, 17 Feb 2005
--- xorg-server-1.4.2.orig/debian/copyright
+++ xorg-server-1.4.2/debian/copyright
@@ -0,0 +1,952 @@
+This package was downloaded from
+http://xorg.freedesktop.org/releases/individual/xserver/
+The upstream tarball has been modified to remove the files listed in
+debian/prune/non-free.
+
+                                  Licenses
+
+                            The X.Org Foundation
+
+                                 March 2004
+
+1.  Introduction
+
+The X.org Foundation X Window System distribution is a compilation of code
+and documentation from many sources.  This document is intended primarily as
+a guide to the licenses used in the distribution: you must check each file
+and/or package for precise redistribution terms. None-the-less, this summary
+may be useful to many users.  No software incorporating the XFree86 1.1
+license has been incorporated.
+
+This document is based on the compilation from XFree86.
+
+2.  XFree86 License
+
+XFree86 code without an explicit copyright is covered by the following copy-
+right/license:
+
+Copyright (C) 1994-2003 The XFree86 Project, Inc.  All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the XFree86 Project shall not
+be used in advertising or otherwise to promote the sale, use or other deal-
+ings in this Software without prior written authorization from the XFree86
+Project.
+
+3.  Other Licenses
+
+Portions of code are covered by the following licenses/copyrights.  See indi-
+vidual files for the copyright dates.
+
+3.1  X/MIT Copyrights
+
+3.1.1  X Consortium
+
+Copyright (C) <date> X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE X
+CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+X Window System is a trademark of X Consortium, Inc.
+
+3.1.2  The Open Group
+
+Copyright <date>  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+3.2  Berkeley-based copyrights:
+
+o
+
+3.2.1  General
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.  Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+  2.  Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  3.  The name of the author may not be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+3.2.2  UCB/LBL
+
+Copyright (c) 1993 The Regents of the University of California.  All rights
+reserved.
+
+This software was developed by the Computer Systems Engineering group at
+Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and contributed to
+Berkeley.
+
+All advertising materials mentioning features or use of this software must
+display the following acknowledgement: This product includes software devel-
+oped by the University of California, Lawrence Berkeley Laboratory.
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.  Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+  2.  Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  3.  All advertising materials mentioning features or use of this software
+      must display the following acknowledgement: This product includes soft-
+      ware developed by the University of California, Berkeley and its con-
+      tributors.
+
+  4.  Neither the name of the University nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
+CLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+3.2.3  The NetBSD Foundation, Inc.
+
+Copyright (c) 2003 The NetBSD Foundation, Inc.  All rights reserved.
+
+This code is derived from software contributed to The NetBSD Foundation by
+Ben Collver <collver1@attbi.com>
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.   Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+  2.   Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  3.   All advertising materials mentioning features or use of this software
+      must display the following acknowledgement: This product includes soft-
+      ware developed by the NetBSD Foundation, Inc. and its contributors.
+
+  4.   Neither the name of The NetBSD Foundation nor the names of its con-
+      tributors may be used to endorse or promote products derived from this
+      software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSE-
+QUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAM-
+AGE.
+
+3.2.4  Theodore Ts'o.
+
+Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.  All rights
+reserved.
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.  Redistributions of source code must retain the above copyright notice,
+      and the entire permission notice in its entirety, including the dis-
+      claimer of warranties.
+
+  2.  Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  3.  he name of the author may not be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE, ALL OF WHICH ARE HEREBY DISCLAIMED.  IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF NOT
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+3.2.5  Theo de Raadt and Damien Miller
+
+Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.  Copyright (c)
+2001-2002 Damien Miller.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.   Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+  2.   Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+3.2.6  Todd C. Miller
+
+Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+
+Permission to use, copy, modify, and distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright
+notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MER-
+CHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE FOR ANY
+SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CON-
+TRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+3.2.7  Thomas Winischhofer
+
+Copyright (C) 2001-2004 Thomas Winischhofer
+
+Redistribution and use in source and binary forms, with or without modifica-
+tion, are permitted provided that the following conditions are met:
+
+  1.   Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+  2.   Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  3.   The name of the author may not be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+3.3  NVIDIA Corp
+
+Copyright (c) 1996 NVIDIA, Corp.  All rights reserved.
+
+NOTICE TO USER: The source code is copyrighted under U.S. and international
+laws.  NVIDIA, Corp. of Sunnyvale, California owns the copyright and as
+design patents pending on the design and interface of the NV chips.  Users
+and possessors of this source code are hereby granted a nonexclusive, roy-
+alty-free copyright and design patent license to use this code in individual
+and commercial software.
+
+Any use of this source code must include, in the user documentation and
+internal comments to the code, notices to the end user as follows:
+
+Copyright (c) 1996 NVIDIA, Corp.  NVIDIA design patents pending in the U.S.
+and foreign countries.
+
+NVIDIA, CORP.  MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
+CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WAR-
+RANTY OF ANY KIND.  NVIDIA, CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA, CORP.  BE LIABLE
+FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAM-
+AGES 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 SOURCE CODE.
+
+3.4  GLX Public License
+
+GLX PUBLIC LICENSE (Version 1.0 (2/11/99)) ("License")
+
+Subject to any third party claims, Silicon Graphics, Inc. ("SGI") hereby
+grants permission to Recipient (defined below), under Recipient's copyrights
+in the Original Software (defined below), to use, copy, modify, merge, pub-
+lish, distribute, sublicense and/or sell copies of Subject Software (defined
+below), and to permit persons to whom the Subject Software is furnished in
+accordance with this License to do the same, subject to all of the following
+terms and conditions, which Recipient accepts by engaging in any such use,
+copying, modifying, merging, publishing, distributing, sublicensing or sell-
+ing:
+
+1. Definitions.
+
+     (a) "Original Software" means source code of computer software code
+     which is described in Exhibit A as Original Software.
+
+     (b) "Modifications" means any addition to or deletion from the sub-
+     stance or structure of either the Original Software or any previous
+     Modifications. When Subject Software is released as a series of
+     files, a Modification means (i) any addition to or deletion from
+     the contents of a file containing Original Software or previous
+     Modifications and (ii) any new file that contains any part of the
+     Original Code or previous Modifications.
+
+     (c) "Subject Software" means the Original Software or Modifications
+     or the combination of the Original Software and Modifications, or
+     portions of any of the foregoing.
+
+     (d) "Recipient" means an individual or a legal entity exercising
+     rights under, and complying with all of the terms of, this License.
+     For legal entities, "Recipient" includes any entity which controls,
+     is controlled by, or is under common control with Recipient. For
+     purposes of this definition, "control" of an entity means (a) the
+     power, direct or indirect, to direct or manage such entity, or (b)
+     ownership of fifty percent (50%) or more of the outstanding shares
+     or beneficial ownership of such entity.
+
+2. Redistribution of Source Code Subject to These Terms. Redistributions of
+Subject Software in source code form must retain the notice set forth in
+Exhibit A, below, in every file. A copy of this License must be included in
+any documentation for such Subject Software where the recipients' rights
+relating to Subject Software are described. Recipient may distribute the
+source code version of Subject Software under a license of Recipient's
+choice, which may contain terms different from this License, provided that
+(i) Recipient is in compliance with the terms of this License, and (ii) the
+license terms include this Section 2 and Sections 3, 4, 7, 8, 10, 12 and 13
+of this License, which terms may not be modified or superseded by any other
+terms of such license. If Recipient distributes the source code version under
+a different license Recipient must make it absolutely clear that any terms
+which differ from this License are offered by Recipient alone, not by SGI.
+Recipient hereby agrees to indemnify SGI for any liability incurred by SGI as
+a result of any such terms Recipient offers.
+
+3. Redistribution in Executable Form. The notice set forth in Exhibit A must
+be conspicuously included in any notice in an executable version of Subject
+Software, related documentation or collateral in which Recipient describes
+the user's rights relating to the Subject Software. Recipient may distribute
+the executable version of Subject Software under a license of Recipient's
+choice, which may contain terms different from this License, provided that
+(i) Recipient is in compliance with the terms of this License, and (ii) the
+license terms include this Section 3 and Sections 4, 7, 8, 10, 12 and 13 of
+this License, which terms may not be modified or superseded by any other
+terms of such license. If Recipient distributes the executable version under
+a different license Recipient must make it absolutely clear that any terms
+which differ from this License are offered by Recipient alone, not by SGI.
+Recipient hereby agrees to indemnify SGI for any liability incurred by SGI as
+a result of any such terms Recipient offers.
+
+4. Termination. This License and the rights granted hereunder will terminate
+automatically if Recipient fails to comply with terms herein and fails to
+cure such breach within 30 days of the breach. Any sublicense to the Subject
+Software which is properly granted shall survive any termination of this
+License absent termination by the terms of such sublicense. Provisions which,
+by their nature, must remain in effect beyond the termination of this License
+shall survive.
+
+5. No Trademark Rights. This License does not grant any rights to use any
+trade name, trademark or service mark whatsoever. No trade name, trademark or
+service mark of SGI may be used to endorse or promote products derived from
+the Subject Software without prior written permission of SGI.
+
+6. No Other Rights. This License does not grant any rights with respect to
+the OpenGL API or to any software or hardware implementation thereof or to
+any other software whatsoever, nor shall any other rights or licenses not
+expressly granted hereunder arise by implication, estoppel or otherwise with
+respect to the Subject Software. Title to and ownership of the Original Soft-
+ware at all times remains with SGI. All rights in the Original Software not
+expressly granted under this License are reserved.
+
+7. Compliance with Laws; Non-Infringement. Recipient shall comply with all
+applicable laws and regulations in connection with use and distribution of
+the Subject Software, including but not limited to, all export and import
+control laws and regulations of the U.S. government and other countries.
+Recipient may not distribute Subject Software that (i) in any way infringes
+(directly or contributorily) the rights (including patent, copyright, trade
+secret, trademark or other intellectual property rights of any kind) of any
+other person or entity or (ii) breaches any representation or warranty,
+express, implied or statutory, which under any applicable law it might be
+deemed to have been distributed.
+
+8. Claims of Infringement. If Recipient at any time has knowledge of any one
+or more third party claims that reproduction, modification, use, distribu-
+tion, import or sale of Subject Software (including particular functionality
+or code incorporated in Subject Software) infringes the third party's intel-
+lectual property rights, Recipient must place in a well-identified web page
+bearing the title "LEGAL" a description of each such claim and a description
+of the party making each such claim in sufficient detail that a user of the
+Subject Software will know whom to contact regarding the claim. Also, upon
+gaining such knowledge of any such claim, Recipient must conspicuously
+include the URL for such web page in the Exhibit A notice required under Sec-
+tions 2 and 3, above, and in the text of any related documentation, license
+agreement or collateral in which Recipient describes end user's rights relat-
+ing to the Subject Software. If Recipient obtains such knowledge after it
+makes Subject Software available to any other person or entity, Recipient
+shall take other steps (such as notifying appropriate mailing lists or news-
+groups) reasonably calculated to inform those who received the Subject Soft-
+ware that new knowledge has been obtained.
+
+9. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MER-
+CHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON- INFRINGING. SGI ASSUMES NO
+RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE
+PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY SER-
+VICING, REPAIR OR CORRECTION.  THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED
+HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THE-
+ORY, WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIA-
+BILITY), CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR
+ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF
+THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY
+TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SGI's NEGLIGENCE TO
+THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
+NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES,
+SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO RECIPIENT.
+
+11. Indemnity. Recipient shall be solely responsible for damages arising,
+directly or indirectly, out of its utilization of rights under this License.
+Recipient will defend, indemnify and hold harmless Silicon Graphics, Inc.
+from and against any loss, liability, damages, costs or expenses (including
+the payment of reasonable attorneys fees) arising out of Recipient's use,
+modification, reproduction and distribution of the Subject Software or out of
+any representation or warranty made by Recipient.
+
+12. U.S. Government End Users. The Subject Software is a "commercial item"
+consisting of "commercial computer software" as such terms are defined in
+title 48 of the Code of Federal Regulations and all U.S.  Government End
+Users acquire only the rights set forth in this License and are subject to
+the terms of this License.
+
+13. Miscellaneous. This License represents the complete agreement concerning
+subject matter hereof. If any provision of this License is held to be unen-
+forceable, such provision shall be reformed so as to achieve as nearly as
+possible the same economic effect as the original provision and the remainder
+of this License will remain in effect. This License shall be governed by and
+construed in accordance with the laws of the United States and the State of
+California as applied to agreements entered into and to be performed entirely
+within California between California residents. Any litigation relating to
+this License shall be subject to the exclusive jurisdiction of the Federal
+Courts of the Northern District of California (or, absent subject matter
+jurisdiction in such courts, the courts of the State of California), with
+venue lying exclusively in Santa Clara County, California, with the losing
+party responsible for costs, including without limitation, court costs and
+reasonable attorneys fees and expenses. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is expressly
+excluded. Any law or regulation which provides that the language of a con-
+tract shall be construed against the drafter shall not apply to this License.
+
+Exhibit A
+
+The contents of this file are subject to Sections 2, 3, 4, 7, 8, 10, 12 and
+13 of the GLX Public License Version 1.0 (the "License"). You may not use
+this file except in compliance with those sections of the License. You may
+obtain a copy of the License at Silicon Graphics, Inc., attn: Legal Services,
+2011 N. Shoreline Blvd., Mountain View, CA 94043 or at
+http://www.sgi.com/software/opensource/glx/license.html.
+
+Software distributed under the License is distributed on an "AS IS" basis.
+ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON-
+INFRINGEMENT. See the License for the specific language governing rights and
+limitations under the License.
+
+The Original Software is GLX version 1.2 source code, released February,
+1999. The developer of the Original Software is Silicon Graphics, Inc.  Those
+portions of the Subject Software created by Silicon Graphics, Inc.  are Copy-
+right (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
+
+3.5  CID Font Code Public License
+
+CID FONT CODE PUBLIC LICENSE (Version 1.0 (3/31/99))("License")
+
+Subject to any applicable third party claims, Silicon Graphics, Inc. ("SGI")
+hereby grants permission to Recipient (defined below), under SGI's copyrights
+in the Original Software (defined below), to use, copy, modify, merge, pub-
+lish, distribute, sublicense and/or sell copies of Subject Software (defined
+below) in both source code and executable form, and to permit persons to whom
+the Subject Software is furnished in accordance with this License to do the
+same, subject to all of the following terms and conditions, which Recipient
+accepts by engaging in any such use, copying, modifying, merging, publica-
+tion, distributing, sublicensing or selling:
+
+1. Definitions.
+
+     a. "Original Software" means source code of computer software code
+     that is described in Exhibit A as Original Software.
+
+     b. "Modifications" means any addition to or deletion from the sub-
+     stance or structure of either the Original Software or any previous
+     Modifications. When Subject Software is released as a series of
+     files, a Modification means (i) any addition to or deletion from
+     the contents of a file containing Original Software or previous
+     Modifications and (ii) any new file that contains any part of the
+     Original Code or previous Modifications.
+
+     c. "Subject Software" means the Original Software or Modifications
+     or the combination of the Original Software and Modifications, or
+     portions of any of the foregoing.
+
+     d. "Recipient" means an individual or a legal entity exercising
+     rights under the terms of this License. For legal entities, "Recip-
+     ient" includes any entity that controls, is controlled by, or is
+     under common control with Recipient. For purposes of this defini-
+     tion, "control" of an entity means (i) the power, direct or indi-
+     rect, to direct or manage such entity, or (ii) ownership of fifty
+     percent (50%) or more of the outstanding shares or beneficial own-
+     ership of such entity.
+
+     e. "Required Notice" means the notice set forth in Exhibit A to
+     this License.
+
+     f. "Accompanying Technology" means any software or other technology
+     that is not a Modification and that is distributed or made publicly
+     available by Recipient with the Subject Software.  Separate soft-
+     ware files that do not contain any Original Software or any previ-
+     ous Modification shall not be deemed a Modification, even if such
+     software files are aggregated as part of a product, or in any
+     medium of storage, with any file that does contain Original Soft-
+     ware or any previous Modification.
+
+2. License Terms. All distribution of the Subject Software must be made sub-
+ject to the terms of this License. A copy of this License and the Required
+Notice must be included in any documentation for Subject Software where
+Recipient's rights relating to Subject Software and/or any Accompanying Tech-
+nology are described. Distributions of Subject Software in source code form
+must also include the Required Notice in every file distributed. In addition,
+a ReadMe file entitled "Important Legal Notice" must be distributed with each
+distribution of one or more files that incorporate Subject Software. That
+file must be included with distributions made in both source code and exe-
+cutable form. A copy of the License and the Required Notice must be included
+in that file.  Recipient may distribute Accompanying Technology under a
+license of Recipient's choice, which may contain terms different from this
+License, provided that (i) Recipient is in compliance with the terms of this
+License, (ii) such other license terms do not modify or supersede the terms
+of this License as applicable to the Subject Software, (iii) Recipient hereby
+indemnifies SGI for any liability incurred by SGI as a result of the distri-
+bution of Accompanying Technology or the use of other license terms.
+
+3. Termination. This License and the rights granted hereunder will terminate
+automatically if Recipient fails to comply with terms herein and fails to
+cure such breach within 30 days of the breach. Any sublicense to the Subject
+Software that is properly granted shall survive any termination of this
+License absent termination by the terms of such sublicense. Provisions which,
+by their nature, must remain in effect beyond the termination of this License
+shall survive.
+
+4. Trademark Rights. This License does not grant any rights to use any trade
+name, trademark or service mark whatsoever. No trade name, trademark or ser-
+vice mark of SGI may be used to endorse or promote products derived from or
+incorporating any Subject Software without prior written permission of SGI.
+
+5. No Other Rights. No rights or licenses not expressly granted hereunder
+shall arise by implication, estoppel or otherwise. Title to and ownership of
+the Original Software at all times remains with SGI. All rights in the Origi-
+nal Software not expressly granted under this License are reserved.
+
+6. Compliance with Laws; Non-Infringement. Recipient shall comply with all
+applicable laws and regulations in connection with use and distribution of
+the Subject Software, including but not limited to, all export and import
+control laws and regulations of the U.S. government and other countries.
+Recipient may not distribute Subject Software that (i) in any way infringes
+(directly or contributorily) the rights (including patent, copyright, trade
+secret, trademark or other intellectual property rights of any kind) of any
+other person or entity, or (ii) breaches any representation or warranty,
+express, implied or statutory, which under any applicable law it might be
+deemed to have been distributed.
+
+7. Claims of Infringement. If Recipient at any time has knowledge of any one
+or more third party claims that reproduction, modification, use, distribu-
+tion, import or sale of Subject Software (including particular functionality
+or code incorporated in Subject Software) infringes the third party's intel-
+lectual property rights, Recipient must place in a well-identified web page
+bearing the title "LEGAL" a description of each such claim and a description
+of the party making each such claim in sufficient detail that a user of the
+Subject Software will know whom to contact regarding the claim. Also, upon
+gaining such knowledge of any such claim, Recipient must conspicuously
+include the URL for such web page in the Required Notice, and in the text of
+any related documentation, license agreement or collateral in which Recipient
+describes end user's rights relating to the Subject Software. If Recipient
+obtains such knowledge after it makes Subject Software available to any other
+person or entity, Recipient shall take other steps (such as notifying appro-
+priate mailing lists or newsgroups) reasonably calculated to provide such
+knowledge to those who received the Subject Software.
+
+8. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, MER-
+CHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO
+RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE
+PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY SER-
+VICING, REPAIR OR CORRECTION.  THIS DISCLAIMER OF WARRANTY CONSTITUTES AN
+ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED
+HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY,
+WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY),
+CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SUBJECT SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SUBJECT SOFTWARE. SOME JURISDICTIONS DO NOT
+ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO THIS EXCLUSION AND
+LIMITATION MAY NOT APPLY TO RECIPIENT TO THE EXTENT SO DISALLOWED.
+
+10. Indemnity. Recipient shall be solely responsible for damages arising,
+directly or indirectly, out of its utilization of rights under this License.
+Recipient will defend, indemnify and hold SGI and its successors and assigns
+harmless from and against any loss, liability, damages, costs or expenses
+(including the payment of reasonable attorneys fees) arising out of (Recipi-
+ent's use, modification, reproduction and distribution of the Subject Soft-
+ware or out of any representation or warranty made by Recipient.
+
+11. U.S. Government End Users. The Subject Software is a "commercial item"
+consisting of "commercial computer software" as such terms are defined in
+title 48 of the Code of Federal Regulations and all U.S. Government End Users
+acquire only the rights set forth in this License and are subject to the
+terms of this License.
+
+12. Miscellaneous. This License represents the complete agreement concerning
+subject matter hereof. If any provision of this License is held to be unen-
+forceable by any judicial or administrative authority having proper jurisdic-
+tion with respect thereto, such provision shall be reformed so as to achieve
+as nearly as possible the same economic effect as the original provision and
+the remainder of this License will remain in effect. This License shall be
+governed by and construed in accordance with the laws of the United States
+and the State of California as applied to agreements entered into and to be
+performed entirely within California between California residents. Any liti-
+gation relating to this License shall be subject to the exclusive jurisdic-
+tion of the Federal Courts of the Northern District of California (or, absent
+subject matter jurisdiction in such courts, the courts of the State of Cali-
+fornia), with venue lying exclusively in Santa Clara County, California, with
+the losing party responsible for costs, including without limitation, court
+costs and reasonable attorneys fees and expenses. The application of the
+United Nations Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any law or regulation that provides that the language of
+a contract shall be construed against the drafter shall not apply to this
+License.
+
+Exhibit A
+
+Copyright (c) 1994-1999 Silicon Graphics, Inc.
+
+The contents of this file are subject to the CID Font Code Public License
+Version 1.0 (the "License"). You may not use this file except in compliance
+with the License. You may obtain a copy of the License at Silicon Graphics,
+Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043
+or at http://www.sgi.com/software/opensource/cid/license.html
+
+Software distributed under the License is distributed on an "AS IS" basis.
+ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON-
+INFRINGEMENT. See the License for the specific language governing rights and
+limitations under the License.
+
+The Original Software (as defined in the License) is CID font code that was
+developed by Silicon Graphics, Inc. Those portions of the Subject Software
+(as defined in the License) that were created by Silicon Graphics, Inc. are
+Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved.
+
+[NOTE: When using this text in connection with Subject Software delivered
+solely in object code form, Recipient may replace the words "this file" with
+"this software" in both the first and second sentences.]
+
+3.6  Bitstream Vera Fonts Copyright
+
+The fonts have a generous copyright, allowing derivative works (as long as
+"Bitstream" or "Vera" are not in the names), and full redistribution (so long
+as they are not *sold* by themselves). They can be be bundled, redistributed
+and sold with any software.
+
+The fonts are distributed under the following copyright:
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated documentation
+files (the "Font Software"), to reproduce and distribute the Font Software,
+including without limitation the rights to use, copy, merge, publish, dis-
+tribute, and/or sell copies of the Font Software, and to permit persons to
+whom the Font Software is furnished to do so, subject to the following condi-
+tions:
+
+The above copyright and trademark notices and this permission notice shall be
+included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and addi-
+tional glyphs or characters may be added to the Fonts, only if the fonts are
+renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream Vera"
+names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDA-
+TION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GEN-
+ERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
+INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFT-
+WARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome Foundation,
+and Bitstream Inc., shall not be used in advertising or otherwise to promote
+the sale, use or other dealings in this Font Software without prior written
+authorization from the Gnome Foundation or Bitstream Inc., respectively. For
+further information, contact: fonts at gnome dot org.
+
+3.7  Bigelow & Holmes Inc and URW++ GmbH Luxi font license
+
+Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font instruction
+code copyright (c) 2001 by URW++ GmbH. All Rights Reserved. Luxi is a regis-
+tered trademark of Bigelow & Holmes Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of these Fonts and associated documentation files (the "Font Software"), to
+deal in the Font Software, including without limitation the rights to use,
+copy, merge, publish, distribute, sublicense, and/or sell copies of the Font
+Software, and to permit persons to whom the Font Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright and trademark notices and this permission notice shall be
+included in all copies of one or more of the Font Software.
+
+The Font Software may not be modified, altered, or added to, and in particu-
+lar the designs of glyphs or characters in the Fonts may not be modified nor
+may additional glyphs or characters be added to the Fonts. This License
+becomes null and void when the Fonts or Font Software have been modified.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT.  IN NO EVENT SHALL BIGELOW & HOLMES INC. OR URW++
+GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GEN-
+ERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
+INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFT-
+WARE.
+
+Except as contained in this notice, the names of Bigelow & Holmes Inc. and
+URW++ GmbH. shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Font Software without prior written
+authorization from Bigelow & Holmes Inc. and URW++ GmbH.
+
+For further information, contact:
+
+info@urwpp.de or design@bigelowandholmes.com
+
+     $Id: LICENSE,v 1.3 2004/09/03 23:41:21 kem Exp $
+
+
+========================================================================
+Certain files in this package (e.g. GL/glx/g_*) are covered by the SGI
+Free Software License B, Version 1.1, http://oss.sgi.com/projects/FreeB
+
+SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+
+Copyright (C) [dates of first publication] Silicon Graphics, Inc. All Rights
+Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice including the dates of first publication and either
+this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
+shall be included in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+Except as contained in this notice, the name of Silicon Graphics, Inc. shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Silicon
+Graphics, Inc.
+
+=============================================================================
+Xprint uses ttf2pt1 for Freetype support.
+
+     -- ttf2pt1 licence --
+
+The following copyright notice applies to all the files provided
+in this distribution unless explicitly noted otherwise
+(the most notable exception being t1asm.c).
+
+  Copyright (c) 1997-2002 by the AUTHORS:
+   Andrew Weeks <ccsaw@bath.ac.uk>
+   Frank M. Siegert <fms@this.net>
+   Mark Heath <mheath@netspace.net.au>
+   Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
+   Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
+   Turgut Uyar <uyar@cs.itu.edu.tr>
+   Rihardas Hepas <rch@WriteMe.Com>
+   Szalay Tamas <tomek@elender.hu>
+   Johan Vromans <jvromans@squirrel.nl>
+   Petr Titera <P.Titera@sh.cvut.cz>
+   Lei Wang <lwang@amath8.amt.ac.cn>
+   Chen Xiangyang <chenxy@sun.ihep.ac.cn>
+   Zvezdan Petkovic <z.petkovic@computer.org>
+   Rigel <rigel863@yahoo.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. All advertising materials mentioning features or use of this software
+     must display the following acknowledgement:
+       This product includes software developed by the TTF2PT1 Project
+       and its contributors.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.
+
+For the approximate list of the AUTHORS' responsibilities see the
+project history.
+
+Other contributions to the project are:
+
+Turgut Uyar <uyar@cs.itu.edu.tr>
+ The Unicode translation table for the Turkish language.
+
+Rihardas Hepas <rch@WriteMe.Com>
+ The Unicode translation table for the Baltic languages.
+
+Szalay Tamas <tomek@elender.hu>
+ The Unicode translation table for the Central European languages.
+
+Johan Vromans <jvromans@squirrel.nl>
+ The RPM file.
+
+Petr Titera <P.Titera@sh.cvut.cz>
+ The Unicode map format with names, the forced Unicode option.
+
+Frank M. Siegert <frank@this.net>
+ Port to Windows
+
+Lei Wang <lwang@amath8.amt.ac.cn>
+Chen Xiangyang <chenxy@sun.ihep.ac.cn>
+ Translation maps for Chinese fonts.
+
+Zvezdan Petkovic <z.petkovic@computer.org>
+ The Unicode translation tables for the Cyrillic alphabet.
+
+Rigel <rigel863@yahoo.com>
+ Generation of the dvips encoding files, modification to the Chinese maps.
+
+I. Lee Hetherington <ilh@lcs.mit.edu>
+ The Type1 assembler (from the package 't1utils'), its full copyright
+ notice:
+  Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
+  Permission is hereby granted to use, modify, and distribute this program
+  for any purpose provided this copyright notice and the one below remain
+  intact.
--- xorg-server-1.4.2.orig/debian/inputabiver
+++ xorg-server-1.4.2/debian/inputabiver
@@ -0,0 +1 @@
+2
--- xorg-server-1.4.2.orig/debian/xprint.changelog.Debian
+++ xorg-server-1.4.2/debian/xprint.changelog.Debian
@@ -0,0 +1,810 @@
+xprint (1:1.1.99.3+git20060910-9) unstable; urgency=low
+
+  * Galician debconf translation. Thanks Jacobo Tarrio. Closes: #408216.
+  * Patch 60_font_links makes symlinks to font files relative to local
+    directory, for easier management.  Also ensures
+    NewCenturySchlbk-BoldItalic.pmf is installed. Closes: #412990.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat,  3 Mar 2007 00:32:11 +1100
+
+xprint (1:1.1.99.3+git20060910-8) unstable; urgency=low
+
+  * Spanish debconf translation. Thanks Fernando Cereza. Closes: #402984.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue,  2 Jan 2007 22:29:25 +1100
+
+xprint (1:1.1.99.3+git20060910-7) unstable; urgency=low
+
+  * Patch 50_byteswap.patch enables Xprint with GLX support on Hurd
+    and GNU/FreeBSD. Closes: #400869.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri,  1 Dec 2006 14:21:16 +1100
+
+xprint (1:1.1.99.3+git20060910-6) unstable; urgency=low
+
+  * Xprint 1.1.99.3 actually Build-Depends: mesa (>= 6.5.1).
+    Closes: #395519.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 12 Nov 2006 14:53:25 +1100
+
+xprint (1:1.1.99.3+git20060910-5) unstable; urgency=low
+
+  * Even though --disable-record is used, record is still built. This
+    is probably a bug in upstream Makefile.am, or possibly recordproto
+    ought to be added to the REQUIRED_MODULES in configure.ac.
+    Workaround with Build-Depends: x11proto-record-dev.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  2 Oct 2006 14:14:17 +1000
+
+xprint (1:1.1.99.3+git20060910-4) unstable; urgency=low
+
+  * Connect tabbed blocks in debian/rules in order to properly disable
+    dri, Xorg, Xvfb and Xnest at configure step.
+  * Refine extension dependencies and disables in line with what
+    Xprint actually supports, as defined in mi/miinitext.c.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  2 Oct 2006 02:12:13 +1000
+
+xprint (1:1.1.99.3+git20060910-3) unstable; urgency=low
+
+  * Restore OpenGL support.  "Because I can".
+  * Incidentally, bugs fixed previously in experimental can be closed
+    by using -v with dpkg-buildpackage when next uploading to unstable.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun,  1 Oct 2006 21:03:11 +1000
+
+xprint (1:1.1.99.3+git20060910-2) unstable; urgency=low
+
+  * xfixes 4 is now in unstable, so bring the new xprint into unstable
+  * It really irritates me the way bugs fixed in experimental are not
+    fully closed when the upload to unstable is made.
+    Closes: #377659, #384775, #383166, #375125, #369834.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 20 Sep 2006 10:21:50 +1000
+
+xprint (1:1.1.99.3+git20060910-1) experimental; urgency=low
+
+  * Latest git.
+    Patches applied upstream:
+        80_no_composite
+      	91_Xprint_README
+  	91_enforce_bash
+      	91_install_config
+      	91_install_etc
+      	94_man_typoes
+  * Install manpages via * to avoid defining .1 or .1x. Closes: #383166.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 10 Sep 2006 19:21:27 +1000
+
+xprint (1:1.1.99.2+git20060627-0.4) experimental; urgency=low
+
+  * Swapped patch 80_check_windowpixmap for 80_no_composite. Composite has
+    no role in Xprint.
+  * LSB compliance: force-reload only operates conditionally when Xprt is
+    already running. Thanks Sven Mueller. Closes: #377659.
+  * Added Portuguese debconf translation, thanks Rui Branco. Closes: #384775.
+  * Adjust debian/xprint.manpages to allow for a shifting suffix. 
+    Closes: #383166.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 27 Aug 2006 13:51:57 +1000
+
+xprint (1:1.1.99.2+git20060627-0.3) experimental; urgency=low
+
+  * Why doesn't dpkg -l damn well report versions correctly?
+    Build-Depends: libxfont-dev (>=1:1.1) not (>=1.1).
+
+ -- Drew Parsons <dparsons@debian.org>  Tue, 27 Jun 2006 21:04:24 +1000
+
+xprint (1:1.1.99.2+git20060627-0.2) experimental; urgency=low
+
+  * Oops should add versioned build-depends on libxfont-dev too.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue, 27 Jun 2006 19:28:03 +1000
+
+xprint (1:1.1.99.2+git20060627-0.1) experimental; urgency=low
+
+  * Latest upstream git: Xprint subdirectory moved to hw.
+    Patches updated accordingly.
+  * Actually create the patch allowing build with new libxfont (freetype
+    2.2) and avoiding a segfault (patch 80_check_windowpixmap).
+  * Versioned dependencies on x11proto-fixes-dev, libxfont1. Closes: #375125.
+  * Standards version 3.7.2.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue, 27 Jun 2006 13:31:08 +1000
+
+xprint (1:1.1.99.2+git20060614-0.1) experimental; urgency=low
+
+  * New upstream version (including lastest git).
+  * Russian debconf translation. Спасибо Юрию Козлову. Closes: #369834.
+  * Upload to experimental while we wait for dependencies (libxfont 1.1,
+    libxfixes 4) to reach unstable.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu, 22 Jun 2006 16:04:40 +1000
+
+xprint (1:1.0.2-1) unstable; urgency=low
+
+  * New upstream version (hey! slashdot is good for something after all!
+    (http://linux.slashdot.org/article.pl?sid=06/05/02/2216235)
+  * Only include the required ft.h, ftfuncs.h files in ./extras.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu,  4 May 2006 17:46:57 +1000
+
+xprint (1:1.0.1-7) unstable; urgency=low
+
+  * Build-Depends: libgl1-mesa-dev|libgl-dev.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 22:58:28 +1000
+
+xprint (1:1.0.1-6) unstable; urgency=low
+
+  * I wonder if I should install pbuilder?
+  * Build-Depends: mesa-common-dev (only needed when compiling with
+    OpenGL support). Guess what, closes: #365386.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 22:22:40 +1000
+
+xprint (1:1.0.1-5) unstable; urgency=low
+
+  * Build-Depends: pkg-config *sigh*.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 17:55:46 +1000
+
+xprint (1:1.0.1-4) unstable; urgency=low
+
+  * Added Build-Depends: xutils-dev to get BUILD_LINUXDOC etc defined for
+    configure.ac.
+  * Looking more closely at "checking for XSERVERCFLAGS", need to add
+    Build-Depends: libxau-dev, libxdmcp-dev.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 17:32:46 +1000
+
+xprint (1:1.0.1-3) unstable; urgency=low
+
+  * Build-Depends: libtool. Closes: #365386 (again).
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 09:31:33 +1000
+
+xprint (1:1.0.1-2) unstable; urgency=low
+
+  * Dutch debconf translation. Thanks Kurt De Bree. Closes: #363035.
+  * Restore dh_installdebconf in debian/rules to get debconf back again.
+  * Added xprint-common Depends: xfonts-encodings, since /etc/init.d.xprint
+    expects to be able to find encodings.dir.
+  * Since /etc/init.d/xprint no longer knows about /usr/X11R6/bin, let
+    xprint-common Depends on x11-common (>=1:7.0.12) to ensure Xprt is in
+    /usr/bin (even if it comes from an old package, where it would be
+    forced to use the /usr/X11R6/bin symlink). Closes: #363245.
+  * Make /etc/init.d/xprint exit quietly if the Xprt binary can't be found.
+    Closes: #270054.
+  * Added Build-Depends: automake1.9. Closes: #365386.
+  * Standards version 3.7.0.
+  * Restore xprint-common debconf files lost in X11R7 transition (where did
+    they disappear to?)
+  * Added lintian override to xprint-common to not trigger 
+    "package-depends-on-an-x-font-package" on Depends: xfonts-encodings.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  1 May 2006 00:35:12 +1000
+
+xprint (1:1.0.1-1) unstable; urgency=low
+
+  * Xprint from X11R7! Closes: #360446, #356987, #362884.
+  * Xprt does not build in Xorg 7.0, hence need CVS (X11R7.1).  However CVS
+    needs xfixes 4 which will not be available in Debian until the XSF
+    prepares 7.1.  So backport patches (relating to build with FreeType
+    support).
+  * Please be advised that as a consequence of the above there will be a
+    degradation of output quality until Debian is able to upgrade to 7.1 
+    (due end of May).  Please hold back from filing bug reports about font
+    quality until that upgrade has occurred. My apologies for the
+    inconvenience.
+  * Build-depends updated to follow modular X11R7.
+  * Xprint utilities removed (transferred to xprint-utils).
+  * Set debhelper compatibility version to 5.
+  * Updated xprint init file to expect encodings.dir in
+    /usr/share/fonts/X11/encodings.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon, 17 Apr 2006 14:03:06 +1000
+
+xprint (1:0.1.0.alpha1-13) unstable; urgency=low
+
+  * Got to actually install the overrides file for it to take effect, dammit.
+  * Swedish debconf translation. Thanks, Daniel Nylander. Closes: #330651.
+  * Patch 91_xsession_ifexec: only define XPSERVERLIST in
+    /etc/X11/Xsession.d/92xprint-xpserverlist if /etc/init.d/xprint is
+    present and executable.  Some administrators may wish to disable xprint
+    by making the init script non-executable. Closes: #330812.
+  * Break a circular dependency by downgrading xprint-common's Depends: on
+    xprint to a Recommends:.  Closes: #339928.
+  * Added a paragraph to README.printing-problems indicating that CUPS
+    settings may also need to be adjusted if the printer resolution is
+    mismatched. Closes: #342714.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 11 Dec 2005 21:10:52 +1100
+
+xprint (1:0.1.0.alpha1-12) unstable; urgency=low
+
+  * Patch 93_init_startstopdaemon has the side effect that some log messages
+    (errors and warnings) from Xprt are lost, including attempted connections.
+    Let me know if you want all such messages back again.
+  * Ditch the xprt and xprt-xprintorg dummy packages. Closes: #322078, #303123.
+  * Time to start stripping binaries. Closes: #164952.
+  * Vietnamese debconf translation. Thanks Clytie Siddall. Closes: #324267.
+  * Added xprint-overrides to ignore pesky lintian warnings.
+  * Removed 93_check_default_start, since the facility to control rc scripts
+    is provided elsewhere (see command update-rc.d, or packages rcconf,
+    sysv-rc-conf or file-rc). This means /etc/default/Xprint is no longer
+    used. Use the facilities mentioned above if you want Xprint installed
+    but not to start up by default.
+    However, it is true that the manner in which Debian handles packages is
+    only partially implemented. Packages start their daemons using
+    invoke-rc.d, whose operations may be controlled by /usr/sbin/policy-rc.d
+    it exists. But it does not exist. Therefore upon upgrade (or
+    dpkg-reconfigure), the Xprt daemon will be started, even if you have
+    correctly set the rc symlinks. You will need to stop it by hand
+    "/etc/init.d/xprint stop" (this only applies to upgrades, your rc
+    configuration will be honoured at boot).  This is a general Debian
+    problem, for having daemons installed but not running. It is *not* an
+    Xprint problem.  Sorry.  See Bug#291766 for further discussion.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 10 Sep 2005 00:38:08 +1000
+
+xprint (1:0.1.0.alpha1-11) unstable; urgency=low
+
+  * Created patch 93_init_startstopdaemon to use start-stop-daemon to launch
+    and kill Xprt.  It handles backgrounding of the Xprt process, so we
+    don't get rogue /etc/init.d/xprint processes running alongside Xprt.
+    Note during stop, we retain kill ${pid} to facilitate compatibility when
+    upgrading (otherwise the new init script won't have a
+    /var/run/Xprt_0.pid file to kill when upgrading from the old version).
+    Closes: #229252, #255240, #313315.
+  * Patch 94_man_typoes fixes spelling errors. Thanks A. Costa.
+    Fixed in *.sgml docbook files, propagated to man and html using
+    docbookconv.sh (also altered to adapt to Debian's current XSLT
+    structure, accounting for the fact that docbook2man cannot read the sgml
+    file at the moment).  Note there are problems generating the derived doc
+    files using HasDocBookTools in config/cf/xprint_host.def, so html and
+    man are generated by hand and included in the patch.
+    Closes: #306701, #306702.
+  * New standards version: 3.6.2.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat,  2 Jul 2005 23:05:44 +1000
+
+xprint (1:0.1.0.alpha1-10) unstable; urgency=high
+
+  * Reduced the priority of the printer resolution debconf question to
+    "medium", since the default of 600 is fine for most printers today.
+    Closes: #298954.
+  * Reduced the amount of the text in the debconf question.
+    Closes: #298956, #298959.
+  * Added new binaries and man pages to xprint.install.
+  * New patch 92_lib_not_lib64_on_amd64ppc64: ppc64 and amb64 use
+    /usr/X11R6/lib not /usr/X11R6/lib64. Reported upstream, Xprint bug #2803.
+    Closes: #301028.
+  * New patch 91_no_ExecCommand: ExecCommand does not belong in
+    attributes.{c|h}, and gcc4 complains about it. See Debian bug #301028 and
+    upstream Xprint bug #2254.
+  * New patch 93_spooltodir_check_file_exists. Closes: #295139.
+  * 93_spooltodir_check_file_exists also checks size of file name is not too
+    long. Closes: #284620.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri, 25 Mar 2005 18:29:49 +1100
+
+xprint (1:0.1.0.alpha1-9) unstable; urgency=medium
+
+  * Taking over xprt, which has been expelled from XFree86.
+  * Take the opportunity the rationalise package naming:
+    - use "xprint" rather than "xprint-xprintorg". Since the Xprint
+      development version (known as xprint.xprintorg but hosted at
+      xprint.mozdev.org) has been accepted as the official X.org development
+      version, it is now unlikely that the separate domain xprint.org will be
+      registered.
+    - xprint contains Xprt and other architecture-dependent binaries
+    - xprint-common contains architecture-independent files (config files,
+      including /etc/init.d/xprint)
+    - xprt and xprt-xprintorg become dummy packages. Closes: #294324.
+  * Even without Super-Cow powers, this Xprint washes whiter than.
+    Closes: #275656.
+  * Add example of different resolutions for different printers to
+    README.printing-problems. Closes: #293539.
+  * In xprint-common.postinst, explicitly stop server before letting debhelper
+    (dh_installinit) start it. This avoids complaints in the situation where
+    Xprt was started by a simultaneous upgrade of the xprint package.
+    Closes: #292355.
+  * For simplicity of maintenance, removed debconf question about old
+    arrangement of config files. Since Xprint is not in woody, this will not
+    cause upgrade problems.
+  * Bump up the epoch to ensure a smooth upgrade of xprt (from
+    4.3.0.dfsg.1-10).
+
+ -- Drew Parsons <dparsons@debian.org>  Thu, 17 Feb 2005 21:02:18 +1100
+
+xprint-xprintorg (0.1.0.alpha1-8) unstable; urgency=low
+
+  * Updated debconf translations:
+    	    - Brazilian (thanks Andre Luis Lopes)
+	    - German (thanks Erik Schanze)
+	    - Czech (thanks Miroslav Kure)
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 30 Jan 2005 13:16:30 +1100
+
+xprint-xprintorg (0.1.0.alpha1-7) unstable; urgency=medium
+
+  * Updated debconf translations:
+    	    - Danish, (thanks Morten Bo Johansen)
+	    - Japanese (thanks Hideki Yamane)
+	    - French (thanks Christian Perrier)
+
+    Closes: #291425, #292363, #292459.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu, 27 Jan 2005 19:09:39 +1100
+
+xprint-xprintorg (0.1.0.alpha1-6) unstable; urgency=medium
+
+  * Added debconf question to set the default printer resolution.
+    Closes: #280159.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 19 Jan 2005 01:44:29 +1100
+
+xprint-xprintorg (0.1.0.alpha1-5) unstable; urgency=high
+
+  * Related to the dash problem again, just remove /bin/sh altogether from
+    92xprint-xpserverlist; this should be simpler than changing it to
+    /bin/bash. Will close #288585 (but leave open pending upstream fix).
+    Closes: #288844.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue, 11 Jan 2005 19:59:08 +1100
+
+xprint-xprintorg (0.1.0.alpha1-4) unstable; urgency=low
+
+  * Force /etc/init.d/xprint to use bash, since there are conflicts with
+    dash when it is /bin/sh.  Patch 91_enforce_bash. Closes: #288630. Also
+    closes #288585, but I will leave this open as a reminder to upstream to
+    fix the non-Posix code.
+  * On a related note, upstream simply no longer asks Linux systems to use ksh
+    at all, so 91_bash_before_ksh is deprecated.  Hence, "test -a" is no
+    longer used. Closes: #285056, #256241.
+  * xset is still being used in /etc/init.d/xprint to build the fontlist, so
+    XPROJECTROOT (or /usr/X11R6/bin) still needs to be defined.
+    Closes: #282723.
+  * Removed square brackets around \n, used by tr in /etc/init.d/xprint.
+    Patch 93_init_tr_fix.  Closes: #258419, #264983.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed,  5 Jan 2005 13:59:18 +1100
+
+xprint-xprintorg (0.1.0.alpha1-3) unstable; urgency=medium
+
+  * There have been enough positive reports about 1.0alpha1 in experimental
+    (contrasted with negative reports of the version in sarge),
+    that I think it is time to get it into unstable and sarge.
+  * I'll keep the "0.1.0" versioning for now. I'll almost certainly make the
+    final 1.0 version to be "1.0".
+  * Added Danish debconf translation. Thanks Morten Bo Johansen. 
+    Closes: #285957.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  3 Jan 2005 14:43:04 +1100
+
+xprint-xprintorg (0.1.0.alpha1-2) experimental; urgency=low
+
+  * Build-Depends: flex, bison.  Closes: #284920.
+  * amd64 support confirmed. Closes: #278510, #282655.
+  * I was joking about the cubes rotating on your paper. But the OpenGL
+    support is real.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 12 Dec 2004 00:29:23 +1100
+
+xprint-xprintorg (0.1.0.alpha1-1) experimental; urgency=low
+
+  * New upstream version: 1.0alpha1, preview of the forthcoming v1.0.
+  * Based on X.Org 6.8.2, with innumerable improvements:
+    - better handling of broken fonts
+    - OpenGL support (yes, rotating cubes on your printer paper)
+    - better greyscale support
+    - generally more stable
+    - supports amd64
+  * Recommended by upstream to go into sarge.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue,  7 Dec 2004 17:47:27 +1100
+
+xprint-xprintorg (0.0.9.final.001-9) unstable; urgency=medium
+
+  * Added patch 92_close_std_files to get /etc/init.d/xprint to close the
+    standard file descriptors (stdin/out/err) when Xprt is invoked. This
+    solves a number of problems, such as hanging sessions of dpkg-reconfigure,
+    ssh, chroot.  Thanks for the patch, Nicolas Boullis.
+    Closes: #233260, #265827, #234132. OK, #234132 also refers to the bash
+    shells, which are still there, but there are other bug reports dealing
+    with them.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue,  7 Dec 2004 10:03:30 +1100
+
+xprint-xprintorg (0.0.9.final.001-8) unstable; urgency=medium
+
+  * Added patch 93_check_default_start, which checks if START_XPRINT=0 in
+    /etc/default/xprint before starting Xprt. Thanks Anthony DeRobertis.
+    Closes: #281973.
+  * Created debian/default to be installed as /etc/default/xprint.
+  * Suggests: xbase-clients, since xset is used by /etc/init.d/xprint.
+    Closes: #282723.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu,  2 Dec 2004 19:00:42 +1100
+
+xprint-xprintorg (0.0.9.final.001-7) unstable; urgency=medium
+
+  * Added Czech translation for debconf templates.  Thanks Miroslav Kure.
+    Closes: #274073.
+  * Added Eugeniy Meshcheryakov's patch (93_xprint_fonts_fix) to improve
+    TrueType font handling.  Closes: #272368.
+  * Added new workaround to README.printing-problems for printing problem
+    with Debian home page: delete "font.name.serif.x-western" entry from
+    pref.js.
+  * Removed Recommends: xprt from xprt-common, since it Depends: on it.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri, 12 Nov 2004 14:37:23 +1100
+
+xprint-xprintorg (0.0.9.final.001-6) unstable; urgency=high
+
+  * Added another question to README.printing-problems to address the
+    problem when the image is printed too large or too small (default
+    printer resolution in /etc/Xprint/C/print/attributes/document
+    needs to be adjusted for your printer).  Closes: #262958, #267964.
+  * Removed man page for xpxmhelloworld: binary is not provided.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 12 Sep 2004 22:31:15 +1000
+
+xprint-xprintorg (0.0.9.final.001-5) unstable; urgency=high
+
+  * README.printing-problems needs to be added to debian/xprt-common.docs.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 22 Aug 2004 14:12:13 +1000
+
+xprint-xprintorg (0.0.9.final.001-4) unstable; urgency=high
+
+  * Added README.printing-problems, describing the printing problem of
+    words being run together without spaces.  The file suggests two
+    workarounds (remove Xprint's fonts directories, or add a
+    firefox/mozilla stylesheet). Thanks to Jan Willem Stumpel for the
+    CSS workaround and to Yaacov Akiba Slama for the fonts directory
+    workaround.
+  * Set urgency to high to get this workaround description into sarge.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 22 Aug 2004 12:30:57 +1000
+
+xprint-xprintorg (0.0.9.final.001-3) unstable; urgency=low
+
+  * Created patch (91_no_sh_suffix_in_Xsession.d) to not provide .sh
+    suffix to Xsession.d script.  Closes: #264978.
+  * Added Erik Schanze's German debconf translation. Closes: #264611.
+  * Added a note to README.Debian concerning the "could not open
+    default font 'fixed'" problem preventing Xprt from starting, which
+    has been reported by some users.  The bug has not yet been
+    reproduced on a system which does not already experience it,
+    making it difficult to fix it properly. A work-around ("sort -u -r" 
+    instead of "sort -u" in /etc/init.d/xprint) is suggested. This
+    concerns bugs such as #259281,  #257731, #259281. Apparently the
+    009.001 release did not help. Maybe v010 will get it at last?
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 15 Aug 2004 18:20:13 +1000
+
+xprint-xprintorg (0.0.9.final.001-2) unstable; urgency=low
+
+  * Added Brazilian Portuguese (pt_BR) debconf translation.
+    Thanks Andre Luis Lopes. Closes: #262554.
+  * Uses Dwayne C. Litzenberger's patch (92_xprint-security-holes-fix.patch)
+    to print to file into the user's $HOME directory instead of /tmp.
+    In subdirectory ../Xprintjobs.  Security patch.  Closes: #262871.
+  * xprt-xprintorg includes binaries and manpages for other auxiliary 
+    programs: xprehashprinterlist, xpsimplehelloworld, xpxthelloworld. 
+    The manpage for xpxmhelloworld is omitted since the binary is not built.
+    The general man page for Xprint is also included.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun,  8 Aug 2004 18:59:52 +1000
+
+xprint-xprintorg (0.0.9.final.001-1) unstable; urgency=low
+
+  * Upstream maintenance release v009.001.
+    - only use basic optimisation on PPC.  Closes: #252362, #258844.
+    - default printer resolution in /usr/share/Xprint/xserver/C/print/attributes/document
+      is now 600dpi not 300dpi. Closes: #254704, #256175.
+    - should no longer hang when using CUPS. Closes: #256850.
+    - /etc/init.d/xprint now has a simpler copyright statement, without
+      "all rights reserved".  Closes: #250887.
+    - incorporates lpr/CUPS patch (10-lpr-cups).
+  * Will hopefully deal with a number of TrueType-related font
+    problems (e.g. #259281,  #257731, #259281). Bugs will be closed in
+    the next upload, pending positive reports from bug reporters.
+  * Treat /usr/share/Xprint/xserver/C/print/Xprinters as a config file
+    (place in /etc/). Closes: #258413.
+  * Patch applied to use bash in preference to ksh. Bug #256241 will
+    be closed once the '-a' posix issue is appropriately settled.
+  * Patch 92_lsprinter_path checks command is executable, and adds
+    test for /usr/bin/xplsprinters.  Closes: #257750.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon, 19 Jul 2004 19:29:22 +1000
+
+xprint-xprintorg (0.0.9.final-3) unstable; urgency=low
+
+  * Applied patch (92_make_amd64) to enable building on AMD 64.
+    Closes: #254752.
+  * Added handling for DEB_BUILD_OPTIONS' noopt (i.e. -O0) in
+    debian/rules, using the code sample in Policy 10.1. turned on -g
+    by default (the debug keyword is deprecated, it should always be
+    on). See bug #252659 (but I think it's not yet passed to Xprint's
+    imake system). 
+
+ -- Drew Parsons <dparsons@debian.org>  Fri, 18 Jun 2004 19:13:09 +1000
+
+xprint-xprintorg (0.0.9.final-2) unstable; urgency=low
+
+  * Applied upstream patch to fix some lpr/CUPS problems
+    (see http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=608)
+    - BugZilla #608 ("Can not print on Debian/CUPS due to error |Xprt_64:
+        lpr: unable to print file: server-error-not-accepting-jobs|"):
+        Xprt did setup  the list of supplementary group ids, causing print
+        failure when the the calling user must be a member in a specific
+        group to be allowed to print.
+    (patch placed in debian/patches/10-lpr-cups)
+
+ -- Drew Parsons <dparsons@debian.org>  Sun,  9 May 2004 17:41:54 +1000
+
+xprint-xprintorg (0.0.9.final-1) unstable; urgency=low
+
+  * v0.9 official release (cvs20040322, released 28 March 2004).
+  * Rearranged debian/rules to build binary-indep and binary-arch
+    separately.  Closes: #241066.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri,  2 Apr 2004 20:45:33 +1000
+
+xprint-xprintorg (0.0.9.cvs20040301-1) unstable; urgency=low
+
+  * New upstream version: v009 release candidate 2.
+  * Partially addresses the complaints about extra processes alongside the
+    Xprt daemon:  tee no longer invoked for logging.  Closes: #224189.
+  * Users finally convinced me there's no point only having xprt-common
+    Recommends: xprt-xprintorg.  xprt-common is not required for client-only
+    setups (they only need XPSERVERLIST to be defined, which can be done
+    without /etc/init.d/xprint. Remember to switch off "-nolisten tcp" in the
+    Xprt server configuration if you want to do this).  So having xprt-common
+    installed without xprt-xprintorg is not in fact particularly useful,
+    unless you really want the config files stored on a different host to the
+    Xprt server, which seems somehow pointless.
+    So, xprt-common now Depends: xprt-xprintorg ( | xprt).
+    Closes: #195070, #211002, #238559.
+  * xprt-common only contains config files, so it should really be
+    Architecture: all.  Why wasn't this noticed before?
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 20 Mar 2004 17:06:20 +1100
+
+xprint-xprintorg (0.0.9.cvs20040216-2) unstable; urgency=low
+
+  * Updated the Japanese debconf translation. Closes: #234254.
+  * Replaced Build-Depends: xlibs-dev in favour of the new separated
+    X libraries.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 25 Feb 2004 19:54:26 +1100
+
+xprint-xprintorg (0.0.9.cvs20040216-1) unstable; urgency=low
+
+  * New upstream version: v009 release candidate 1.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 21 Feb 2004 12:02:12 +1100
+
+xprint-xprintorg (0.0.9.cvs20040114-3) unstable; urgency=low
+
+  * The "Now He Tells Me" release.
+  * Build-depends: xutils.  This provides mkfontdir, whose absence was the
+    real cause of the bug I tried to fix in -2.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu, 15 Jan 2004 17:18:09 +1030
+
+xprint-xprintorg (0.0.9.cvs20040114-2) unstable; urgency=low
+
+  * Build-depends: lesstif2-dev.  In order to compile xpxmhelloworld and allow
+    the build to proceed. Not that I package xpxmhelloworld, ho-hum.
+
+ -- Drew Parsons <dparsons@debian.org>  Thu, 15 Jan 2004 10:43:56 +1030
+
+xprint-xprintorg (0.0.9.cvs20040114-1) unstable; urgency=low
+
+  * New upstream version (0.0.9 gamma)
+    - fixes handling of missing xft servers (closes: #224952,#226642,#226703).
+  * Added Japanese template translation. Thanks Hideki Yamane!
+    Closes: #224180.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 14 Jan 2004 17:56:59 +1030
+
+xprint-xprintorg (0.0.9.cvs20031220-1) unstable; urgency=low
+
+  * New upstream version (0.0.9 beta).
+    - new improved font download engine.
+    - supports OpenType fonts. Closes: #211798, #216813.
+    - XFree86 config file is used to extract font paths (as well as standard
+      paths and the defoma directory).
+    - supports PDF output (find it in /tmp/Xprintjobs).
+    - improved CUPS support. cupsys-bsd is no longer mandatory (but still
+      works fine).  Closes: #206657.
+    - uses lockfiles for Xprint servers started via /etc/init.d/xprint.
+      Closes: #198745.
+  * xprt-common Recommends: xfonts-base, in order to find encodings.dir.
+    It is not a strict dependency since the location of the file can be set
+    as a configuration option in /etc/init.d/xprint.  Closes: #217524.
+  * xprt-xprintorg Provides: xprt.  Strictly speaking this is only valid if
+    we create a virtual package called xprt, but what the hell. 
+    "Future proofing"... ;)   Closes: #206655.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri,  5 Dec 2003 23:08:13 +1100
+
+xprint-xprintorg (0.0.8.cvs20030508-6) unstable; urgency=low
+
+  * Added defoma directory to font directory in /etc/init.d/xprint.
+    Closes: #206557.
+  * Applied upstream patch to improve printer spool (CUPS) handling.
+  * New standards version 3.6.1.
+
+ -- Drew Parsons <dparsons@debian.org>  Fri, 26 Sep 2003 09:33:31 +1000
+
+xprint-xprintorg (0.0.8.cvs20030508-5) unstable; urgency=low
+
+  * Something went awry with the changes in -4, so try again:
+    - French debconf translation. Closes: #199347.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 30 Jul 2003 20:25:03 +1000
+
+xprint-xprintorg (0.0.8.cvs20030508-4) unstable; urgency=low
+
+  * Updated upstream patch for /etc/init.d/xprint regarding LSB.
+  * French debconf translation provided by Christian Perrier. Closes: #199347.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon, 30 Jun 2003 18:49:09 +1000
+
+xprint-xprintorg (0.0.8.cvs20030508-3) unstable; urgency=low
+
+  * Applied upstream patch to make /etc/init.d/xprint compliant with LSB.
+  * Updated debconf template to new po format using debconf-gettextize.
+    Added Build-Depends: debhelper (>= 4.1.16). Tidied up some spaces and
+    formatting in template and Description in control.  Closes: #198287.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 22 Jun 2003 00:45:13 +1000
+
+xprint-xprintorg (0.0.8.cvs20030508-2) unstable; urgency=low
+
+  * Identify that Xprt is the server in question during stop/start
+    messages from /etc/init.d/xprint.  Closes: #194694, #196487.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 14 Jun 2003 13:37:50 +1000
+
+xprint-xprintorg (0.0.8.cvs20030508-1) unstable; urgency=low
+
+  * Final 0.0.8 release.  
+    No significant changes from previous release candidate (mainly fixes for
+    Solaris). 
+  * Description identifies that TrueType fonts are now supported in 0.0.8.
+    Closes: #190736.
+  * New standards version: 3.5.10.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 25 May 2003 12:47:06 +1000
+
+xprint-xprintorg (0.0.8.cvs20030416-1) unstable; urgency=low
+
+  * New upstream version: v0.0.8 release candidate #2.
+  * I forgot to mention last time, man pages were recompiled with docbook2man,
+    gives better results than docbook-to-man.
+
+ -- Drew Parsons <dparsons@debian.org>  Wed, 23 Apr 2003 13:12:31 +1000
+
+xprint-xprintorg (0.0.8.cvs20030403-1) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 12 Apr 2003 23:49:35 +1000
+
+xprint-xprintorg (0.0.8.cvs20030328-2) unstable; urgency=low
+
+  * Added libxaw7-dev to Build-Depends in debian/control. 
+    Closes: #186782, #186785.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 30 Mar 2003 09:56:21 +1000
+
+xprint-xprintorg (0.0.8.cvs20030328-1) unstable; urgency=low
+
+  * Upstream CVS. "Beta" version for release 0.0.8.
+  * Upstream changes include:
+    - Xsession.d script defines XPSERVERLIST for all X sessions,
+      removing the need to set it in profile files.
+      Closes: #171174, #177104.
+    - "-nolisten tcp" is now implemented, allowing for improved network
+      security when using Xprt.
+      Note that you may need to reset XPSERVERLIST (possibly by restarting X), 
+      since this improvement requires the Xprt "display" to be given as ":64"
+      rather than "localhost:64".
+      Closes: #162023.
+    - the use of TrueType fonts is now supported.
+    - man pages are now available for the Xprt and other support binaries.
+    - size of source tarball now reduced to about 10 MB.
+  * The Xprint FAQ is always updated fresh from each new upstream tarball.
+    Closes: #170903.
+  * The upstream source tarball is now handled using dbs, one of Debian's patch
+    handling tools.  This should facilitate the incorporation of one-off
+    patches in the future, such as the "-nolisten tcp" patch.
+    I decided in this context to use the pristine upstream tarball without
+    modification, rather than removing the www directory from it. The size
+    of www is not significant.
+  * Identify use of debhelper v4 via debian/compat.
+  * Standards version 3.5.9.
+
+ -- Drew Parsons <dparsons@debian.org>  Sat, 29 Mar 2003 02:53:12 +1100
+
+xprint-xprintorg (0.0.7.cvs20021203-1) unstable; urgency=low
+
+  * New upstream version (final release for v007).
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  9 Dec 2002 18:13:38 +1100
+
+xprint-xprintorg (0.0.7.cvs20021125-1) unstable; urgency=low
+
+  * New upstream version (final release candidate for v007).
+  * Standards version 3.5.8.
+  * Upstream tarball created by make_xprint_tarball (invoked in
+    debian/rules) for Debian systems now recognises it is building for
+    Debian and places config files in /usr/share/Xprint, not
+    /usr/X11R6/lib/X11.  debian/xprt-common.install changed accordingly.
+  * Added link from usr/share/Xprint/xserver/README to
+    usr/share/doc/xprt-common/README in debian/xprt-common.links.
+  * xserver/SecurityPolicy no longer exists, remove from
+    debian/xprt-common.links and debian/rules.
+  * Added attributes directory for en_US to config files in /etc/Xprint
+    (allows default paper for en_US to be letter, for everyone else A4).
+    Altered directory structure in /etc/Xprint to accomodate both C and en_US
+    locales.  Changes made in rules, xprt-common.dirs, xprt-common.links.
+    Debconf invoked to remove old config files, if user permits it.
+  * Removed xprt-common.conffiles, since dh_installdeb (v3 and higher)
+    automatically lists everything in /etc as a conffile.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon,  2 Dec 2002 18:11:04 +1100
+
+xprint-xprintorg (0.0.7.cvs20021101-1) unstable; urgency=low
+
+  * New upstream version.
+  * Debian patches incorporated upstream (thanks Roland!).
+  * /etc/init.d/xprint now provided in upstream source.
+    Note that upstream has set the Xprint "display" to :64, not :12.
+    You may have to refresh shell variable XPSERVERLIST by restarting client
+    programs such as mozilla or by relogging in again.
+  * Binary stripping switched off (dh_strip commented out in debian/rules)
+    by upstream's request, see Debian bug #164952.  Only temporary.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue,  5 Nov 2002 08:20:15 +1100
+
+xprint-xprintorg (0.0.7.cvs20021004-1) unstable; urgency=low
+
+  * New upstream version.
+  * Should facilitate build on sparc and mips.
+
+ -- Drew Parsons <dparsons@debian.org>  Tue,  8 Oct 2002 15:24:44 +1000
+
+xprint-xprintorg (0.0.7.cvs20020903-3) unstable; urgency=low
+
+  * Change reference in README.Debian from /etc/environment to /etc/profile
+    for setting variable XPSERVERLIST.
+
+ -- Drew Parsons <dparsons@debian.org>  Mon, 23 Sep 2002 22:38:35 +1000
+
+xprint-xprintorg (0.0.7.cvs20020903-2) unstable; urgency=low
+
+  * Moved check for Xprt binary to point where it is invoked in 
+    debian/xprt-common.xprint (i.e. /etc/init.d/xprint). 
+    Depends: on xprt[-xprintorg] should not be required, /etc/init.d/xprint may
+    complain, but this ought not to affect installation.
+    Closes: #161824.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 22 Sep 2002 11:09:43 +1000
+
+xprint-xprintorg (0.0.7.cvs20020903-1) unstable; urgency=low
+
+  * New package. Closes: #149658.
+  * 0.0.7 release branch from CVS tarball, 3 September 2002.
+  * Includes modified /etc/init.d/xprint script (v0.2) from
+    http://mozdev.org/bugs/show_bug.cgi?id=2037
+  * Standards Version 3.5.7.
+
+ -- Drew Parsons <dparsons@debian.org>  Sun, 15 Sep 2002 12:33:27 +1000
+
--- xorg-server-1.4.2.orig/debian/xserver-xephyr.docs
+++ xorg-server-1.4.2/debian/xserver-xephyr.docs
@@ -0,0 +1 @@
+hw/kdrive/ephyr/README
--- xorg-server-1.4.2.orig/debian/xprint-common.default
+++ xorg-server-1.4.2/debian/xprint-common.default
@@ -0,0 +1,10 @@
+# If you do not want Xprint to automatically start, then set START_XPRINT=0
+# By default, START_XPRINT=1, enabling Xprt, the Xprint server, to be started.
+
+# Note that this can be more effectively done by removing the start-up symlinks
+# to /etc/init.d/xprint, e.g.
+# 	rm /etc/rc[1-6].d/*xprint*
+
+# If you always want Xprint to run, you may safely remove this file.
+
+START_XPRINT=1
--- xorg-server-1.4.2.orig/debian/serverminver
+++ xorg-server-1.4.2/debian/serverminver
@@ -0,0 +1 @@
+2:1.4
--- xorg-server-1.4.2.orig/debian/xprint-common.docs
+++ xorg-server-1.4.2/debian/xprint-common.docs
@@ -0,0 +1,2 @@
+debian/xprint.changelog.Debian
+debian/README.printing-problems
--- xorg-server-1.4.2.orig/debian/xserver-xorg-core.NEWS
+++ xorg-server-1.4.2/debian/xserver-xorg-core.NEWS
@@ -0,0 +1,62 @@
+xorg-server (2:1.3.0.0.dfsg-3) unstable; urgency=low
+
+  * The server now includes a patch to always include the font paths
+    defined at compile-time by default. This will help prevent errors with
+    finding fonts when a xorg.conf has alternate font paths specified. 
+    
+    As a result of this, many of the font paths shipped in our default
+    xorg.conf are obsolete, and may be deleted. If you have no customized
+    your xorg.conf, a future update to the xserver-xorg package will
+    re-create the file from your stored preferences.
+
+    If for some reason you do not want the server to look in the default
+    font paths, you can set the boolean variable "UseDefaultFontPath" to
+    "False" in the ServerFlags section of your xorg.conf.
+
+ -- David Nusinow <dnusinow@debian.org>  Tue, 24 Apr 2007 00:18:04 -0400
+
+xorg-server (2:1.2.99.905-3) experimental; urgency=low
+
+ * This server update includes a patch to enable proper module defaults in
+   the server. A default set of modules will be loaded unless you
+   specifically specify that they don't load. You may do this in the module
+   section of your xorg.conf using the "Disable" instruction. Note that
+   this will only override the default, not an explicit "Load".
+
+   This change will not affect most users, however if you have a customized
+   xorg.conf in which you comment out "Load" lines to disable modules, you
+   will want to change those lines so that they are uncommented and say
+   "Disable" instead of "Load". The most notable example of this is the dri
+   module, which is now loaded by default. Those who experience crashes
+   when dri is enabled will want to make this change to ensure that their
+   system does not begin to crash again.
+
+ -- David Nusinow <dnusinow@debian.org>  Sat, 14 Apr 2007 12:41:37 -0400
+
+xserver-xorg-core (1:1.0.2-5) unstable; urgency=low
+
+  * Several users have reported an error on load like the following:
+
+     "(EE) Failed to load module "GLcore" (loader failed, 7)"
+
+    To resolve this error and the related ones in the logfile above it,
+    remove the line to load the glcore module in your /etc/X11/xorg.conf.
+    Other similar errors about module loading can be resolved the same way.
+    If you have not customized your config file by hand, you can run the
+    command "dpkg-reconfigure xserver-xorg" as root to do this for you.
+
+  -- David Nusinow <dnusinow@debian.org>  Wed, 12 Apr 2006 19:38:51 -0400
+
+xserver-xorg-core (1:1.0.2-3) unstable; urgency=low
+
+  * With the latest updates of Xorg, we have transitioned from X11R6 to
+    X11R7. Part of this transition involves changing the paths to the
+    xfonts and the xkb data files, as well as the modules loaded by the X
+    server. One way to automatically update the paths is to run
+    "dpkg-reconfigure xserver-xorg" as root and it will automatically
+    generate a new config file for you. Note that this will currently not
+    work for people who have customized config files due to a bug, so
+    you'll have to manually edit your config if you have customized it
+    previously.
+
+  -- David Nusinow <dnusinow@debian.org>  Wed, 12 Apr 2006 19:38:51 -0400
--- xorg-server-1.4.2.orig/debian/xprint-common.dirs
+++ xorg-server-1.4.2/debian/xprint-common.dirs
@@ -0,0 +1,4 @@
+etc/Xprint/C/print
+etc/Xprint/en_US/print
+etc/default
+usr/share/lintian/overrides
--- xorg-server-1.4.2.orig/debian/xserver-xorg-core.bug.script
+++ xorg-server-1.4.2/debian/xserver-xorg-core.bug.script
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+# $Id$
+
+PATH="/sbin:$PATH"
+CONFIG_DIR=/etc/X11
+SERVER_SYMLINK="$CONFIG_DIR/X"
+XORGCONFIG="$CONFIG_DIR/xorg.conf"
+CONFIG_AUX_DIR=/var/lib/x11
+SERVER_SYMLINK_CHECKSUM="$CONFIG_AUX_DIR/${SERVER_SYMLINK##*/}.md5sum"
+SERVER_SYMLINK_ROSTER="$CONFIG_AUX_DIR/${SERVER_SYMLINK##*/}.roster"
+XORGCONFIG_CHECKSUM="$CONFIG_AUX_DIR/${XORGCONFIG##*/}.md5sum"
+XORGCONFIG_ROSTER="$CONFIG_AUX_DIR/${XORGCONFIG##*/}.roster"
+
+exec >&3
+
+if [ -e "$SERVER_SYMLINK_ROSTER" ]; then
+    printf "Contents of $SERVER_SYMLINK_ROSTER:\n"
+    cat "$SERVER_SYMLINK_ROSTER"
+else
+    printf "$SERVER_SYMLINK_ROSTER does not exist.\n"
+fi
+
+printf "\n"
+
+if [ -e "$SERVER_SYMLINK" ]; then
+    if [ -e "$SERVER_SYMLINK_CHECKSUM" ]; then
+        if [ "$(readlink "$SERVER_SYMLINK" | md5sum)" = \
+             "$(cat "$SERVER_SYMLINK_CHECKSUM")" ]; then
+            printf "%s target unchanged from checksum in %s.\n" \
+              "$SERVER_SYMLINK" "$SERVER_SYMLINK_CHECKSUM"
+        else
+            printf "%s target does not match checksum in %s.\n" \
+              "$SERVER_SYMLINK" "$SERVER_SYMLINK_CHECKSUM"
+        fi
+    else
+        printf "$SERVER_SYMLINK_CHECKSUM does not exist.\n"
+    fi
+    printf "\n"
+    printf "X server symlink status:\n"
+    ls -dl "$SERVER_SYMLINK"
+    ls -dl "$(readlink "$SERVER_SYMLINK")"
+else
+    printf "$SERVER_SYMLINK does not exist.\n"
+fi
+
+if ! [ -L "$SERVER_SYMLINK" ]; then
+    printf "$SERVER_SYMLINK is not a symlink.\n"
+fi
+
+if ! [ -x "$SERVER_SYMLINK" ]; then
+    printf "$SERVER_SYMLINK is not executable.\n"
+fi
+
+printf "\n"
+
+if [ -e "$XORGCONFIG_ROSTER" ]; then
+    printf "Contents of $XORGCONFIG_ROSTER:\n"
+    cat "$XORGCONFIG_ROSTER"
+else
+    printf "$XORGCONFIG_ROSTER does not exist.\n"
+fi
+
+printf "\n"
+
+if which lspci > /dev/null 2>&1; then
+    printf "VGA-compatible devices on PCI bus:\n"
+    LC_ALL=C lspci | grep 'VGA compatible controller:'
+    LC_ALL=C lspci -n | grep 'Class 0300:'
+else
+    printf "The lspci command was not found; not including PCI data.\n"
+fi
+
+printf "\n"
+
+if [ -e "$XORGCONFIG" ]; then
+    if [ -e "$XORGCONFIG_CHECKSUM" ]; then
+        if [ "$(md5sum "$XORGCONFIG")" = "$(cat "$XORGCONFIG_CHECKSUM")" ]; then
+            printf "%s unchanged from checksum in %s.\n" "$XORGCONFIG" \
+              "$XORGCONFIG_CHECKSUM"
+        else
+            printf "%s does not match checksum in %s.\n" "$XORGCONFIG" \
+              "$XORGCONFIG_CHECKSUM"
+        fi
+    else
+        printf "$XORGCONFIG_CHECKSUM does not exist.\n"
+    fi
+    printf "\n"
+    printf "Xorg X server configuration file status:\n"
+    ls -dl "$XORGCONFIG"
+    printf "\n"
+    printf "Contents of $XORGCONFIG:\n"
+    iconv -c -t ascii "$XORGCONFIG"
+    printf "\n"
+else
+    printf "$XORGCONFIG does not exist.\n"
+fi
+
+printf "\n"
+
+XORG_LOGS=$(ls -dt /var/log/Xorg.*.log 2>/dev/null)
+
+if [ -n "$XORG_LOGS" ]; then
+    printf "Xorg X server log files on system:\n"
+    ls -dlrt /var/log/Xorg.*.log 2>/dev/null
+    printf "\n"
+    for LOG in $XORG_LOGS; do
+        if [ -f "$LOG" ]; then
+            printf "Contents of most recent Xorg X server log file\n"
+            printf "%s:\n" "$LOG"
+            cat "$LOG"
+            # the log files are large; only show the most recent
+            break
+        fi
+    done
+else
+    printf "No Xorg X server log files found.\n"
+fi
+
+printf "\n"
+
+# vim:set ai et sts=4 sw=4 tw=0:
--- xorg-server-1.4.2.orig/debian/xprint-common-overrides
+++ xorg-server-1.4.2/debian/xprint-common-overrides
@@ -0,0 +1,2 @@
+# xfonts-encodings is not a font package
+xprint-common binary: package-depends-on-an-x-font-package depends: xfonts-encodings
--- xorg-server-1.4.2.orig/debian/xprint-common.links
+++ xorg-server-1.4.2/debian/xprint-common.links
@@ -0,0 +1,5 @@
+etc/Xprint/C/print/attributes		usr/share/Xprint/xserver/C/print/attributes
+etc/Xprint/C/print/Xprinters		usr/share/Xprint/xserver/C/print/Xprinters
+etc/Xprint/C/print/ddx-config		usr/share/Xprint/xserver/C/print/ddx-config
+etc/Xprint/en_US/print/attributes	usr/share/Xprint/xserver/en_US/print/attributes
+usr/share/Xprint/xserver/README		usr/share/doc/xprint-common/README
--- xorg-server-1.4.2.orig/debian/xdmx-tools.install
+++ xorg-server-1.4.2/debian/xdmx-tools.install
@@ -0,0 +1,7 @@
+usr/bin/dmx*
+usr/bin/vdltodmx
+usr/bin/xdmx
+usr/bin/xdmxconfig
+usr/share/man/man1/vdltodmx.1
+usr/share/man/man1/dmxtodmx.1
+usr/share/man/man1/xdmxconfig.1
--- xorg-server-1.4.2.orig/debian/xserver-xorg-dev.install
+++ xorg-server-1.4.2/debian/xserver-xorg-dev.install
@@ -0,0 +1,3 @@
+usr/include/xorg/*
+usr/lib/pkgconfig/xorg-server.pc
+usr/share/aclocal/*
--- xorg-server-1.4.2.orig/debian/xprint-common.templates
+++ xorg-server-1.4.2/debian/xprint-common.templates
@@ -0,0 +1,21 @@
+# These templates have been reviewed by the debian-l10n-english
+# team
+#
+# If modifications/additions/rewording are needed, please ask
+# debian-l10n-english@lists.debian.org for advice.
+#
+# Even minor modifications require translation updates and such
+# changes should be coordinated with translators and reviewers.
+
+Template: xprint-common/default_printer_resolution
+Type: string
+Default: 600
+_Description: Default printer resolution:
+ By default, Xprint assumes a printer resolution of 600 dpi. This should be
+ well suited for the majority of printers.
+ .
+ On certain 1200 dpi printers, however, the image might appear squashed in the
+ corner of the page, or it might be blown up too large on 300 dpi printers. If
+ you are experiencing such printing problems, you may want to set
+ the default printer resolution to a more appropriate value. See
+ /usr/share/doc/xprint-common/README.printing-problems.gz for more details.
--- xorg-server-1.4.2.orig/debian/xprint.manpages
+++ xorg-server-1.4.2/debian/xprint.manpages
@@ -0,0 +1 @@
+debian/tmp/usr/share/man/man1/Xprt*
--- xorg-server-1.4.2.orig/debian/xvfb.install
+++ xorg-server-1.4.2/debian/xvfb.install
@@ -0,0 +1,4 @@
+usr/bin/Xvfb
+usr/bin/xvfb-run
+usr/share/man/man1/xvfb-run.1
+usr/share/man/man1/Xvfb.1
--- xorg-server-1.4.2.orig/debian/xnest.install
+++ xorg-server-1.4.2/debian/xnest.install
@@ -0,0 +1,2 @@
+usr/bin/Xnest
+usr/share/man/man1/Xnest.1
--- xorg-server-1.4.2.orig/debian/xprint.dirs
+++ xorg-server-1.4.2/debian/xprint.dirs
@@ -0,0 +1,3 @@
+usr/share/doc
+usr/bin
+usr/share/lintian/overrides
--- xorg-server-1.4.2.orig/debian/changelog
+++ xorg-server-1.4.2/debian/changelog
@@ -0,0 +1,1519 @@
+xorg-server (2:1.4.2-10.lenny4) lenny; urgency=low
+
+  * glx: don't crash in SwapBuffers if we don't have a context
+    (closes: #603015).
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 01 Aug 2011 20:24:37 +0200
+
+xorg-server (2:1.4.2-10.lenny3) stable; urgency=low
+
+  * Cherry-pick patch from upstream to set umask to a sane value in Xorg
+    before opening the log, so we don't create it world-writable (closes:
+    #555308).
+  * Add patch by Olivier Fourdan (Red Hat) to fix the mod() macro in fb and
+    mi.
+  * render: bounds check for nglyphs in ProcRenderAddGlyphs.
+  * fb: make isClipped always reject negative coordinates (closes: #320627)
+  * xvfb-run: don't pass the magic cookie to xauth on the command line
+    (CVE-2009-1573).  Thanks, Loïc Minier!
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 25 Sep 2010 12:25:53 +0200
+
+xorg-server (2:1.4.2-10.lenny2) stable; urgency=low
+
+  * Revert change from -10.lenny1.  If both PCI and fb drivers are loaded, the
+    server falls over, so the workaround doesn't work, and seems to break
+    other setups...  This closes: #527058, and reopens #488669.
+  * Cherry-pick patch from upstream to fix wakeup storm in the idletime xsync
+    counter.
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 08 Jun 2009 11:04:45 +0200
+
+xorg-server (2:1.4.2-10.lenny1) stable; urgency=low
+
+  * Work around a bug in the sparc PCI code by falling back to the fbdev
+    driver (closes: #488669).
+
+ -- Julien Cristau <jcristau@debian.org>  Sun, 08 Mar 2009 22:25:46 +0100
+
+xorg-server (2:1.4.2-10) unstable; urgency=medium
+
+  * Cherry-pick from upstream: GLcore: make googleearth not crash the server
+    on sw-rendering (closes: #495483).
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 09 Jan 2009 02:26:06 +0100
+
+xorg-server (2:1.4.2-9) unstable; urgency=low
+
+  * Cherry-pick patches from upstream to make xf86ScaleAxis() work correctly.
+  * Steal patch from Fedora: more sanity checks to stop vmmouse from
+    segfaulting the server (closes: #503459).
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 13 Nov 2008 23:32:47 +0100
+
+xorg-server (2:1.4.2-8) unstable; urgency=low
+
+  * Add patch from Petr Salinger to fix PCI domain support on kfreebsd
+    (closes: #499501).
+  * xfree86: xf86SetDepthBpp needs to respect the driver's depth24flags.
+    Instead of forcing a 32bpp framebuffer, we pick a value that the driver
+    actually supports (closes: #504819, #486925); cherry-picked from upstream
+    git.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 11 Nov 2008 20:46:52 +0100
+
+xorg-server (2:1.4.2-7) unstable; urgency=low
+
+  * Update debian/copyright to the SGI Free Software License B, version 2.0.
+    It now mirrors the free X11 license used by X.Org.
+    http://www.sgi.com/company_info/newsroom/press_releases/2008/september/opengl.html
+  * Not closing bug#211765 for now, because GL/glx/glxext.c and
+    hw/dmx/glxProxy/glxext.c are covered by the GLX Public License, which is
+    still not free.  SGI has since released their code under FreeB, but that
+    doesn't necessarily apply to contributions from other people.  Hopefully
+    this can be cleared up soon, though.
+  * xvfb-run: append to $ERRORFILE instead of truncating it, so the error
+    output from Xvfb is not deleted when we run 'xauth remove'.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 30 Sep 2008 00:39:58 +0200
+
+xorg-server (2:1.4.2-6) unstable; urgency=low
+
+  * Xevie: always set rep.length to 0 (closes: #497337).  Thanks, Thorvald
+    Natvig!
+  * Xevie: swap replies if necessary, to not confuse clients with a different
+    endianness.
+  * Cherry-picked from upstream git:
+    XF86VidMode: Correct a NULL pointer dereference (closes: #498289)
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 15 Sep 2008 01:21:13 +0200
+
+xorg-server (2:1.4.2-5) unstable; urgency=low
+
+  * Don't pretend we support randr 1.2 when queried by swapped clients.  The
+    dispatch code for RandR 1.2 requests would return BadImplementation anyway
+    (closes: #495833).
+  * Cherry-picked from upstream:
+    + exa: fix assert logic thinko.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 26 Aug 2008 19:27:34 +0200
+
+xorg-server (2:1.4.2-4) unstable; urgency=low
+
+  * Re-enable patch 47_fbdevhw_magic_numbers.diff, fixes xen framebuffer
+    (closes: #493901).  Thanks, Olivier Tétard!  If someone knows why I
+    disabled it a year ago, I'd love to know.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 15 Aug 2008 19:15:54 +0200
+
+xorg-server (2:1.4.2-3) unstable; urgency=low
+
+  * Add Romanian debconf translation (closes: #489069).  Thanks, Eddy
+    Petrișor!
+  * Update Dutch debconf translation (closes: #491663).  Thanks, Thĳs
+    Kinkhorst!
+  * Pull from server-1.4-branch:
+    - Xi: ChangeDeviceControl presence events should set the appropriate
+      devchange
+    - Fix potential crasher in xf86CrtcRotate()
+  * Cherry-picked from 1.5:
+    - Work around the DIX losing mmWidth/mmHeight for RandR 1.1 DDXen
+      (closes: #491526).
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 02 Aug 2008 23:22:32 +0200
+
+xorg-server (2:1.4.2-2) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * GLX: zero the buffer used in __glXDisp_GetVisualConfigs (backport from
+    upstream).
+
+  [ Brice Goglin ]
+  * Cherry-pick various patches from upstream:
+    - Fix incorrect test regarding keyboard map.
+    - xfree86: append, not prepend, new input devices to xf86InputDevs.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 18 Jul 2008 10:53:26 +0200
+
+xorg-server (2:1.4.2-1) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * New upstream release.
+  * Security fixes from the previous upload are included upstream.
+  * Cherry-pick patches from upstream git to make the LeftOf and Above options
+    in xorg.conf actually work (closes: #466526).
+  * 48_xaa_nooffscreenpixmaps.diff: disable XAA offscreen pixmaps by default;
+    they can be enabled with Option "XaaOffscreenPixmaps" (closes: #478277,
+    #433331).
+  * Cherry-pick various patches from upstream for Xorg's modes code:
+    - add quirks for monitors with broken EDID (closes: #473260)
+    - fix max clock computation
+    - inherit the preferred mode from the global configuration (so if you have
+      Modes "800x600" in the Display subsection the server will honor it
+      instead of ignoring it)
+  * Backport patch from upstream git to fix emulation of int1A PCI BIOS
+    services (closes: #404885).  Thanks, Robert de Bath!
+
+  [ Brice Goglin ]
+  * Update patches to not require -p0, closes: #485185.
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 26 Jun 2008 01:57:18 +0200
+
+xorg-server (2:1.4.1~git20080517-2) unstable; urgency=high
+
+  * High urgency upload for security fixes.
+  * New patch from upstream to fix multiple security issues reported by
+    iDefense:
+    CVE-2008-2360 - RENDER Extension heap buffer overflow
+    CVE-2008-2361 - RENDER Extension crash
+    CVE-2008-2362 - RENDER Extension memory corruption
+    CVE-2008-1379 - MIT-SHM arbitrary memory read
+    CVE-2008-1377 - RECORD and Security extensions memory corruption
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 09 Jun 2008 14:59:04 +0200
+
+xorg-server (2:1.4.1~git20080517-1) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * Pass -DPRE_RELEASE=0 in CPPFLAGS, so we don't print the pre-release
+    warning in the Xorg log.
+  * Pull from upstream server-1.4-branch
+    + drop patch 40_default_dpi_96.patch applied upstream
+    + refresh patches 03_auto_load_driver.diff and
+      04_auto_load_driver_no_conf.diff
+  * Don't build-depend on packages with a -1 debian revision.
+  * Drop the XS- prefix from Vcs-* control fields.
+  * Add x11-common to the Depends field of xnest, xvfb and xserver-xephyr (its
+    init script sets up the /tmp/.X11-unix directory).
+  * Re-enable the dmx DDX, and build the xdmx and xdmx-tools packages (the
+    build is now fixed upstream); closes: #449254.
+
+  [ Drew Parsons ]
+  * Patch 95_xprint_disable_dbus disables dbus in Xprint by providing
+    dummy config functions. Taken from upstream commit
+    2a3d1421e0cc18822ae8f478fcc272e16a9e9340, with removal of
+    CONFIG_LIB from configure.ac shifted to 94_xprint_XSERVER_LIBS.
+    Closes: #472180.
+  * Enable the xprint DDX, and build the xprint and xprint-common packages.
+
+ -- Julien Cristau <jcristau@debian.org>  Sun, 18 May 2008 13:36:11 +0200
+
+xorg-server (2:1.4.1~git20080507-1) unstable; urgency=low
+
+  * Pull from upstream server-1.4-branch, highlights:
+    - the server should now scale input events correctly
+    - xkb keymap failures now give an explanation instead of just a 'failed to
+      load' message
+  * Drop patch 51_xkb-and-loathing.diff, applied upstream
+  * Refresh patches 13_debian_add_xkbpath_env_variable.diff,
+    21_glx_align_fixes.patch, 46_reduce_wakeups_from_smart_scheduler.patch and
+    94_xprint_XSERVER_LIBS.
+  * chmod +x configure in debian/rules clean so we can build a git snapshot
+    where configure is not in the tarball.
+  * Cherry-pick fix from upstream's master branch to re-arm the DPMS timer
+    when re-enabling DPMS (closes: #397197).
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 08 May 2008 15:34:38 +0200
+
+xorg-server (2:1.4.1~git20080131-4) unstable; urgency=low
+
+  * fix AlwaysCore handling: enabling AlwaysCore in xorg.conf 1) is the
+    default, and 2) shouldn't prevent the device from sending core events
+    (closes: #461760).
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 29 Apr 2008 20:14:22 +0200
+
+xorg-server (2:1.4.1~git20080131-3) unstable; urgency=low
+
+  * XKB: Fix processInputProc wrapping (cherry-picked from upstream).
+    Thanks to Thomas Jaeger.  This should fix the bug with some keys getting
+    stuck (closes: #473165).
+  * xkb: when copying the keymap, make sure the structs default to 0/NULL
+    (cherry-picked from upstream).  Fixes a crash and closes: #461783.
+  * __glXDRIbindTexImage: Fail if no texture bound to pixmap's texture target
+    (cherry-picked from upstream).
+  * EXA: Fix off-by-one in polyline drawing (cherry-picked from upstream).
+  * EXA: Skip empty glyphs (cherry-picked from upstream).
+  * Fix overly-restrictive integer overflow check in EXA pixmap creation
+    (cherry-picked from upstream).  Fixes BadAlloc errors returned by
+    XCreatePixmap for pixmaps of width 8192 or greater (closes: #471782).
+
+  Following patches by Bart Trojanowski, stolen from the ubuntu package:
+  * 15_X86EMU-added-blacklist-for-I-O-port-in-0-0xFF-range.patch
+    - Restrict access to I/O ports in range 0-0xFF from x86emu.
+  * 16_X86EMU-pass-the-correct-bus-dev-fn-tag-to-pci-emula.patch
+    - Fix improper emulation of PCI access General Software BIOS.
+  * Add 17_x86emu_handle_cpuid.patch to fix X86EMU CPUID handling.
+    (closes: #451089).
+
+ -- Julien Cristau <jcristau@debian.org>  Wed, 02 Apr 2008 00:20:15 +0200
+
+xorg-server (2:1.4.1~git20080131-2) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 46_reduce_wakeups_from_smart_scheduler.patch to reduce
+    power consumption, closes: #462700.
+
+  [ Drew Parsons ]
+  * Restore Xprint, cherry-picking commits
+    f7f79724fdea0cc6fda0e90e56431df937d49335 and
+    d67e210f3458b62d7d4a6032aabfda0004d661c1 from master (xserver 1.5).
+    Include patch 94_xprint_XSERVER_LIBS to give new meaning of
+    XSERVER_LIBS as expected in configure.ac from master (see commit
+    a02db0d500cac20d0f0f107d27c064a175018421). Delete
+    94_xprint_XSERVER_LIBS when we upgrade to xserver 1.5.
+
+  [ Julien Cristau ]
+  * Re-enable patch 51_xkb-and-loathing.diff: ignore SIGALRM around calls to
+    Popen()/Pclose() to fix a hang when opening menus in OpenOffice.org
+    (once again closes: #433131)
+  * Refresh all patches to make patch-audit happy.
+  * Pull from upstream server-1.4-branch as of March 14th.
+  * 42_dont_break_grab_and_focus_for_window_when_redirecting.diff removed,
+    applied upstream.
+  * Don't build xprint just yet, because it needs NEW processing.
+
+  [ David Nusinow ]
+  * Add 11_dont_crash_on_bad_dri_mode. See bugzilla #13860
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 14 Mar 2008 15:18:16 +0100
+
+xorg-server (2:1.4.1~git20080131-1) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 45_only_XF86_APM_CAPABILITY_CHANGED_for_video_change_acpi_events.diff
+    to prevent XF86_APM_CAPABILITY_CHANGED from being issued for all ACPI
+    events, thanks Sjoerd Simons, closes: #461463.
+
+  [ David Nusinow ]
+  * Update Japanese translation from Hideki Yamane. closes: #462761
+  * New upstream pull
+    + Fixes crashes due to absent LED's being referenced
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 31 Jan 2008 21:43:12 -0500
+
+xorg-server (2:1.4.1~git20080118-1) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 42_dont_break_grab_and_focus_for_window_when_redirecting.diff
+    to prevent password authentication bypass, closes: #449108.
+
+  [ Julien Cristau ]
+  * New upstream snapshot
+    + includes the security fixes from the previous version
+    + fixes regression introduced by the fix for CVE-2007-6429 in the MIT-SHM
+      extension (closes: #461410)
+
+ -- Brice Goglin <bgoglin@debian.org>  Fri, 18 Jan 2008 22:20:32 +0100
+
+xorg-server (2:1.4.1~git20080105-2) unstable; urgency=low
+
+  [ David Nusinow ]
+  * Improve dpms logging patch to correctly label message type
+
+  [ Brice Goglin ]
+  * Grab upstream commit db9ae863536fff80b5463d99e71dc47ae587980d
+    to set DEFAULT_DPI to 96 instead of 75.
+
+  [ Julien Cristau ]
+  * Fix multiple security issues
+    + CVE-2007-6427: XInput Extension Memory Corruption
+    + CVE-2007-6428: TOG-CUP Extension Memory Corruption
+    + CVE-2007-6429: EVI Extension Integer Overflow,
+                     MIT-SHM Extension Integer Overflow
+    + CVE-2007-5760: XFree86-Misc Extension Invalid Array Index
+    + CVE-2007-5958: file existence disclosure
+    + CVE-2008-0006: PCF font parser buffer overflow
+  * Bump Standards-Version to 3.7.3 (no changes).
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 17 Jan 2008 15:10:03 +0100
+
+xorg-server (2:1.4.1~git20080105-1) unstable; urgency=low
+
+  * Don't reference non-existent bug-reporting.txt file in xvfb-run.1
+  * New upstream git pull, again from the server-1.4-branch
+    + Drop 08_xkb_infinite_loop.diff, it's upstream now
+  * Improve logging when DPMS is enabled implicitly
+    + Adds 08_better_dpms_logging.diff
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 06 Jan 2008 16:56:38 -0500
+
+xorg-server (2:1.4.1~git20071212-2) unstable; urgency=low
+
+  * Add patch 08_xkb_infinite_loop.diff from upstream bug#13511: papers over
+    an infinite loop in event processing (closes: #451989).
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 22 Dec 2007 00:02:01 +0100
+
+xorg-server (2:1.4.1~git20071212-1) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * debian/rules: Use lsb_release -i -s to get the vendor name, instead of
+    hardcoding "Debian".
+  * debian/control: build-dep on lsb-release.
+  * Cherry-pick commit f30abe30 from master: edid quirk for MAX 0x77e monitor.
+  * Add patch 44_preferredmode_infinite_loop.diff from upstream git: fixes an
+    infinite loop when PreferredMode is used in xorg.conf.
+
+  [ David Nusinow ]
+  * New upstream version. This is based on the server-1.4-branch, and includes
+    all the changes in the 1.4.0.90 (pre-)release as well as additional fixes.
+    This is primarily a bugfix release
+    + Remove 12_bgPixel_fix_64bit_issue.diff. Applied upstream
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 12 Dec 2007 20:19:11 -0500
+
+xorg-server (2:1.4.1~git20071119-1) unstable; urgency=low
+
+  * Ship a .orig.tar.gz that's been autoreconf'ed. Closes: #451891
+  * Re-enable validation of the screen section of xorg.conf
+    Modify 14_default_screen_section.diff. This also fixes a problem where the
+    server can't find the device section when it is specified in the screen
+    section. Closes: #451950
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 19 Nov 2007 20:38:04 -0500
+
+xorg-server (2:1.4.1~git20071117-1) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * Add conflict on xserver-xorg-input-wacom (<< 0.7.8) to xserver-xorg-core.
+    That driver is built against the old ABI, but doesn't provide
+    xserver-xorg-input.
+
+  [ David Nusinow ]
+  * Add 14_default_screen_section.diff. This allows you to not have a screen
+    section in your xorg.conf. A basic default one with a simple identifier
+    will be created for you in this case using all default values
+
+  [ Christian Perrier ]
+  * Debconf translations:
+  * Galician. Closes: #444764
+  * German. Closes: #444917
+  * Brazilian Portuguese. Closes: #445266
+  * Russian. Closes: #443859
+  * Portuguese. Closes: #445051
+  * Slovak. Closes: #446418, #448220
+
+  [ Brice Goglin ]
+  * Bump x11proto-core-dev build-dependency to >= 7.0.9,
+    thanks Max Kellermann, closes: #446869.
+
+  [ David Nusinow ]
+  * New upstream stable snapshot
+    + fixes a bunch of input-related bugs, notably keyboard leds
+      (closes: #440743 and its pile of duplicates)
+  * Remove patches merged in this snapshot
+    + 08_exa_fix_exaFillRegionTiled_fallback.diff
+    + 11_exa_no_negative_tile_offsets.diff
+    + 42_fix_RemoveGeneralSocket_crash_from_dbus.diff
+    + 44_XKB_mapping_changes_for_all_core-sending_devices.diff
+    + 45_GetKeyboardEvents_reject_out-of-range_keycodes.diff
+  * Make xephyr recommend xfonts-base. Closes: #451542
+
+ -- David Nusinow <dnusinow@debian.org>  Sat, 17 Nov 2007 18:54:02 -0500
+
+xorg-server (2:1.4-3) unstable; urgency=low
+
+  [ David Nusinow ]
+  * Minor cleanups of 03_autoload_drivers.diff. Thanks to Julien for
+    spotting all these ugly bits
+    + Newline after #else when picking the driver (this is the failsafe
+      choice)
+    + Change by hacked "ids" file name suffix check to use strncmp and check
+      for ".ids"
+    + Use strncpy instead of strncat unnecessarily
+  * Add support for a partially configured device section
+    Implemented in 03_autoload_driver.diff. Now if you have a device section
+    but lack a driver, it'll use the settings. This will allow you to just
+    have a device section and enable EXA but not have to specify the driver or
+    anything else.
+  * Add 07_autoconfig_screen_with_device_section.diff
+    This patch allows the Screen section to not specify a device section. If
+    this happens, the server will automatically use the first device section
+    listed in the xorg.conf instead
+
+  [ Brice Goglin ]
+  * Allow building the Xfbdev server in new package xserver-xfbdev, but leave
+    it disabled for now (see #439764).
+  * Add upstream commit 27ad5d74c20f01516a1bff73be283f8982fcf0fe as patch
+    44_XKB_mapping_changes_for_all_core-sending_devices.diff to fix broken
+    xmodmap invocation in .xsession, closes: #443044.
+  * Add upstream commit 0e800ca4651a947ccef239e6fe7bf64aab92257c as patch
+    45_GetKeyboardEvents_reject_out-of-range_keycodes.diff to fix crash
+    in GetKeyboardValuatorEvents, closes: #443697.
+
+  [ Christian Perrier ]
+  * Debconf templates and debian/control reviewed by the debian-l10n-
+    english team as part of the Smith review project. Closes: #442210
+  * Debconf translation updates:
+    - Swedish. Closes: #443047
+    - Czech. Closes: #443100
+    - French
+    - Vietnamese. Closes: #443174
+    - Italian. Closes: #422414
+  * New debconf translations
+    - Hungarian. Closes: #442956
+    - Thai. Closes: #442962
+    - Tamil. Closes: #443027
+    - Basque. Closes: #443156
+    - Hebrew. Closes: #443204
+    - Bulgarian. Closes: #443226
+    - Finnish. Closes: #443611
+
+  [ Julien Cristau ]
+  * Add patch backported from upstream commit
+    13949f997289068354e83bc83e50d97b8232efb1 to remove the type1 module: patch
+    05_kill_type1.diff replaces 48_disable_type1.diff, and is now enabled in
+    debian/patches/series.
+  * Don't build kdrive-based servers we're not shipping.
+  * Use ${binary:Version} instead of ${Source-Version}.
+  * Add 08_exa_fix_exaFillRegionTiled_fallback.diff by Michel Dänzer to punt
+    on fallback case not handled correctly in exaFillRegionTiled (backported
+    from master's c7d6d1f5); closes: #444203.
+  * Add 11_exa_no_negative_tile_offsets.diff by Michel Dänzer to make sure
+    tile offsets passed to drivers are never negative (backported from
+    master's 006f6525).
+  * Add 12_bgPixel_fix_64bit_issue.diff by Hong Liu: bgPixel (unsigned long)
+    is 64-bit on x86_64, so -1 != 0xffffffff (master's 9adea807).
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 29 Sep 2007 16:14:35 +0200
+
+xorg-server (2:1.4-2) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 42_fix_RemoveGeneralSocket_crash_from_dbus.diff to fix a crash
+    when leaving, closes: #440547.
+  * Add 43_allow_override_BIOS_EDID_preferred_mode.diff to allow overriding
+    BIOD/EDID preferred mode with Option PreferredMode in the config file.
+
+  [ David Nusinow ]
+  * Upload to unstable
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 16 Sep 2007 14:24:18 -0400
+
+xorg-server (2:1.4-1) experimental; urgency=low
+
+  * New upstream release (X.Org 7.3)
+    + RandR doesn't mark Xinerama as active when no crtcs are enabled
+      (closes: #431746)
+  * Add proper depends to xserver-xorg-dev:
+    x11proto-core-dev, x11proto-input-dev (>= 1.4), x11proto-xext-dev,
+    x11proto-video-dev, x11proto-randr-dev (>= 1.2), x11proto-render-dev (>=
+    2:0.9.3), x11proto-fonts-dev
+  * Bump serverminver to 2:1.4, videoabiver to 2, inputabiver to 2.
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 10 Sep 2007 14:35:38 +0200
+
+xorg-server (2:1.3.99.2-1) experimental; urgency=low
+
+  [ David Nusinow ]
+  * Refactor auto_load_driver patch to allow the same method to be used when
+    there is no xorg.conf present
+  * Add 04_auto_load_driver_no_config.diff to use my auto_load_driver method
+    when there's no xorg.conf present
+
+  [ Brice Goglin ]
+  * Simplify output redirections in the reportbug script,
+    thanks Justin Pryzby, closes: #358390.
+  * Add missing URL in long descriptions, update links to the upstream
+    module, fix some capitalization, thanks Christian Perrier.
+
+  [ Julien Cristau ]
+  * New upstream release candidate.
+    + bump build dep on renderproto to >= 0.9.3, and on pixman to >= 0.9.4-2.
+    + bump video abi version and serverminver.
+  * Drop the Conflict on fglrx-driver, which is taken care of by the abi
+    version.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 04 Sep 2007 17:32:19 +0200
+
+xorg-server (2:1.3.99.0-2) experimental; urgency=low
+
+  * Improve 03_auto_load_driver.diff
+    + Move memory cleanup and directory closing to after the end label to
+      prevent leaks. Thanks Julien.
+    + Allow a driver to claim everything from a specific vendor. It does so by
+      only specifying a vendor ID and leaving the latter four digits empty.
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 19 Aug 2007 16:06:54 -0400
+
+xorg-server (2:1.3.99.0-1) experimental; urgency=low
+
+  [ Julien Cristau, David Nusinow ]
+  * New upstream release candidate.
+    + X is now more tolerant of devices without a CtrlProc (closes: #269860).
+    + cvt(1) and gtf(1) typos fixed (closes: #432065).
+    + Make sure DRIScreenPrivIndex is -1 when no DRI screen private is
+      allocated. (closes: #413697).
+    + __glXDRIscreenProbe: Use drmOpen/CloseOnce (closes: #419614).
+    + segfault in swrast_Triangle fixed in mesa (closes: #407502).
+    + the Xvfb manpage doesn't refer to /usr/tmp anymore (closes: #270257).
+    + typos in Xserver(1) fixed (closes: #306688).
+
+  * Remove patches that were pushed upstream
+    + 03_xnest_manpage_overhaul.diff
+    + 04_read_rom_in_chunks.diff
+    + 05_module_defaults.diff
+    + 07_stolen_from_HEAD_xorgconf_manpage.diff
+    + 08_s390_servermd.diff
+    + 12_security_policy_in_etc.diff
+    + 16_s390_fix.diff
+    + 18_execinfo_configured.patch
+    + 23_kfreebsd_support.diff
+    + 24_hurd_ioperm_fix.diff
+    + 32_disable_sparc_pci_bridge.diff
+    + 39_alpha_build_flags.patch
+    + 40_consolidate_portPriv_pDraw_assignments.diff
+    + 42_only_run_special_key_behaviours_on_non-XKB.diff
+    + 44_fedora-xephyr-keysym-madness.diff (different fix applied upstream)
+    + 45_CVE-2007-2437.diff
+    + 46_export-ramdac-symbols.diff
+    + 49_map_keyboard_driver_to_kbd.diff
+    + 50_alpha_no_include_asm_pci.h.diff
+    + 94_use_default_font_path.diff
+    + 125_glx_remove-stray__GLinterface.diff,
+      126_glxproxy_remove-stray__GLinterface.diff and
+      127_mesa-6.5.3-compat.diff (obsolete)
+
+  * Update other patches:
+    + 09_debian_xserver_rtff.diff disabled (doesn't apply, and isn't even
+      used AFAICS;
+    + 11_define_XFree86Server.diff dropped, to be fixed in drivers instead;
+    + 13_debian_add_xkbpath_env_variable.diff refreshed;
+    + 21_glx_align_fixes.patch updated;
+    + 43_xephyr_crash_at_exit.diff dropped (doesn't apply);
+    + 47_fbdevhw_magic_numbers.diff disabled for now;
+    + 48_disable_type1.diff disabled for now;
+    + 51_xkb-and-loathing.diff disabled for now.
+
+  [ Julien Cristau ]
+  * Add build-dep on x11proto-input-dev (>= 1.4.2), libpixman-1-dev
+    (>= 0.9.0), libdbus-1-dev, libhal-dev (except on hurd-i386 for the last
+    two).
+  * Bump build-dep on mesa-swx11-source to >> 7.0.1~rc2-1.
+  * Bump serverminver to this version, videoabiver to 1.9, inputabiver to
+    0.9 (so this doesn't clash with a release and drivers have to be
+    rebuilt).
+  * Bump build-dep on compositeproto to >= 0.4.
+  * Install the upstream changelog.
+  * Disable the xprint and dmx DDX for now, they fail to build.
+  * xserver-xorg-dev needs a dependency on libpixman-1-dev.
+  * Add explanations about our tarball and upstream URL to debian/copyright.
+
+  [ Drew Parsons ]
+  * Update Xprint build to include pixman.
+
+  [ David Nusinow ]
+  * Add 03_auto_load_driver.diff. This patch allows the server to select a
+    driver and automatically create a Devices section when none is specified
+    in your xorg.conf. It chooses the driver based on a set of PCI ID's that
+    the driver itself provides in /usr/share/xserver-xorg/pci. If no driver
+    claims the PCI ID of your primary video card, then it will choose a
+    fallback based on your system.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 18 Aug 2007 18:28:49 +0200
+
+xorg-server (2:1.3.0.0.dfsg-13) UNRELEASED; urgency=low
+
+  [ Debconf templates translations ]
+  * Italian added. Closes: #422414
+  * Slovak added. Closes: #438578
+
+ -- Christian Perrier <bubulle@debian.org>  Sun, 26 Aug 2007 12:09:52 +0200
+
+xorg-server (2:1.3.0.0.dfsg-12) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 51_xkb-and-loathing.diff to fix a hang in OpenOffice.org
+    when opening menus, closes: #433131.
+  * Install the exa(4) and fbdevhw(4) manpages.
+
+  [ Julien Cristau ]
+  * Update the xorg.conf(5) manpage to get documentation for RandR 1.2
+    options:
+    + 07_stolen_from_HEAD_xorgconf_manpage.diff: new patch;
+    + 07_xorgconf_manpage_overhaul.diff dropped;
+    + 34_xorg.conf_man_typos.patch dropped;
+    + 05_module_defaults.diff, 94_use_default_font_path.diff: dropped hunks
+      applying to hw/xfree86/doc/man/xorg.conf.man.pre.
+  * Add patch 11_define_XFree86Server.diff: XFree86Server needs to be defined
+    in xorg-server.h and exported to drivers.
+  * Add patches 125_glx_remove-stray__GLinterface.diff
+    126_glxproxy_remove-stray__GLinterface.diff and 127_mesa-6.5.3-compat.diff
+    to build with mesa >= 6.5.3, and bump build-dependency on
+    mesa-swx11-source.
+  * Include the Debian package version in OSVENDOR to make it appear in the
+    X log.
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 09 Aug 2007 16:32:14 +0200
+
+xorg-server (2:1.3.0.0.dfsg-11) unstable; urgency=low
+
+  * Yet another alpha build fix: also remove the asm/pci.h include from
+    os-support/linux/lnx_axp.c.  Include "lnx.h" and <unistd.h> instead.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 14 Jul 2007 20:09:35 +0200
+
+xorg-server (2:1.3.0.0.dfsg-10) unstable; urgency=medium
+
+  * hw/xfree86/common/compiler.h and <sys/io.h> declare incompatible
+    prototypes for outb and friends, so change the patch from -9 to not
+    #include <sys/io.h> and rely on declarations in lnx.h itself for the
+    IOBASE_* macros.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 14 Jul 2007 18:06:14 +0200
+
+xorg-server (2:1.3.0.0.dfsg-9) unstable; urgency=medium
+
+  * Include <sys/io.h> instead of <asm/pci.h> in
+    hw/xfree86/os-support/linux/lnx.h, as the latter isn't exported to
+    userspace anymore; fixes FTBFS on alpha.  Thanks, Steve Langasek!
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 14 Jul 2007 12:17:10 +0200
+
+xorg-server (2:1.3.0.0.dfsg-8) unstable; urgency=medium
+
+  * Medium-urgency upload to get the fix for #428794 in testing faster,
+    hopefully.
+
+  [ Brice Goglin ]
+  * Add 47_fbdevhw_magic_numbers.diff: patch by Adam Jackson to keep the
+    fbdev2xfree_timing() function from changing the pixel clock value if the
+    fbdev driver claims that it is 0.
+
+  [ Julien Cristau ]
+  * Don't build the type1 font module.
+  * Add patch by Alan Coopersmith to map (case-insensitively) the old
+    "keyboard" input driver to "kbd" (addresses: #428794).  I'm not
+    reassigning the bug to xserver-xorg-core for now so as not to break
+    testing by letting xserver-xorg-input-keyboard transition before the fixed
+    xorg-server.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 14 Jul 2007 01:48:20 +0200
+
+xorg-server (2:1.3.0.0.dfsg-7) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 40_consolidate_portPriv_pDraw_assignments.diff to avoid a crash
+    in xf86XVReputVideo (closes: #424899, #431655).
+  * Add 41_vbe_filter_less.diff to not reject VESA modes early since
+    xf86ValidateModes should handle them just fine (closes: #424684).
+  * Add 42_only_run_special_key_behaviours_on_non-XKB.diff to fix special
+    keys in Xephyr (closes: #415025).
+  * Add 43_xephyr_crash_at_exit.diff to avoid crashing Xephyr when first
+    client disconnect (closes: #420421).
+
+ -- Julien Cristau <jcristau@debian.org>  Wed, 04 Jul 2007 23:42:40 +0200
+
+xorg-server (2:1.3.0.0.dfsg-6) unstable; urgency=low
+
+  * Change fglrx conflict to << 8.37.6 (closes: #424975).
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 01 Jun 2007 14:58:39 +0200
+
+xorg-server (2:1.3.0.0.dfsg-5) unstable; urgency=low
+
+  [ Brice Goglin ]
+  * Add 24_hurd_ioperm_fix.diff to fix xf86Enable/DisableIO on Hurd with
+    recent GNU Mach. Thanks Samuel Thibault!
+  * Add 06_use_proc_instead_of_sysfs_for_pci_domains.diff since sysfs-based
+    PCI management code is broken at least on sparc and powerpc.
+    Closes: #422077, #422095. Thanks to Jim Watson for testing!
+  * Install the Xephyr README, closes: #395888.
+  * Update 07_xorgconf_manpage_overhaul.diff to drop the reference to the
+    xorg.conf example which we do not install since Xserver 1.3 does automatic
+    configuration, the manpage is very well documented, and we generate a
+    config file during installation. Closes: #222932.
+  * Fix warning in /etc/init.d/xprint when /usr/lib/X11/fonts does not exist.
+    Closes: #422352. Thanks Cristian Ionescu-Idbohrn!
+  * Pull upstream commit 9c80eda826448822328bb678a7d284cc43fffb17 to disable
+    RandR's fake xinerama geometry when there's more than one protocol screen
+    (closes: #420679).
+
+  [ Julien Cristau ]
+  * Add patch to make sure that the ramdac symbols are present in the server
+    and drivers can use them (closes: #423129).
+  * xserver-xorg-core Conflicts with fglrx-driver, which broke with 1.3.
+    We'll need to make this versioned (or drop it) when fglrx is fixed.
+
+ -- Julien Cristau <jcristau@debian.org>  Wed, 16 May 2007 15:17:55 +0200
+
+xorg-server (2:1.3.0.0.dfsg-4) unstable; urgency=low
+
+  * Cherry-pick patch from upstream git to fix security issue in the Xrender
+    extension: malicious clients can cause a division by zero in the server
+    (closes: #422936). Reference: CVE-2007-2437. Thanks, Micah Anderson!
+
+ -- Julien Cristau <jcristau@debian.org>  Wed, 09 May 2007 02:11:08 +0200
+
+xorg-server (2:1.3.0.0.dfsg-3) unstable; urgency=low
+
+  * Include 94_use_default_font_path.diff. This patch is like Eugene's patch
+    to always look in the default font path from the past, but now we provide
+    an option to disable looking in the default font path at runtime. This
+    will allow people to specify additional font paths in their xorg.conf
+    without losing their current paths. This will also help avoid people
+    having ye olde "fixed font" problem.
+  * Fix compilation warnings for 05_module_defaults.diff. Previously the patch
+    used a generic pointer for the options record, but now we use the actual
+    XF86OptionsPtr type.
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 26 Apr 2007 22:39:52 -0400
+
+xorg-server (2:1.3.0.0.dfsg-2) unstable; urgency=low
+
+  * Add Brice Goglin's fix for 05_module_defaults.diff, so that it also works
+    when there is no module section at all. Thanks to Michel Dänzer for
+    helping also.
+
+ -- David Nusinow <dnusinow@debian.org>  Sat, 21 Apr 2007 09:34:12 -0400
+
+xorg-server (2:1.3.0.0.dfsg-1) unstable; urgency=low
+
+  * Upload to unstable.
+  * Add XS-Vcs-* to debian/control.
+  * Remove non-free file hw/xfree86/doc/README.DRI from the upstream tarball.
+  * Bump serverminver to 2:1.3.0.0.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 20 Apr 2007 07:54:14 +0200
+
+xorg-server (2:1.3.0.0-1) experimental; urgency=low
+
+  * New upstream release
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 19 Apr 2007 22:27:05 -0400
+
+xorg-server (2:1.2.99.905-3) experimental; urgency=low
+
+  [ Julien Cristau ]
+  * xvfb now Recommends: xfonts-base (closes: #314598).
+
+  [ David Nusinow ]
+  * Add 05_module_defaults.diff. This provides default modules loading
+    capabilities for the server that may be overrided easily. Previously the
+    server would load a set of default modules, but only if none were
+    specified in the xorg.conf, or if you didn't have a xorg.conf at all. This
+    patch provides a default set and you can add only the "Load" instructions
+    to xorg.conf that you want without losing the defaults. Similarly, if you
+    don't want to load a module that's loaded by default, you can add
+    "Disable modulename" to your xorg.conf (see man xorg.conf in this release
+    for details). See upstream bug #10541 for more.
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 15 Apr 2007 11:17:45 -0400
+
+xorg-server (2:1.2.99.905-2) experimental; urgency=low
+
+  * Install the cvt and gtf utilities and their manpages (closes: #414792).
+  * Build the xserver-xorg-core-dbg package, which contains debugging symbols
+    for Xorg and /usr/lib/xorg/modules/**/*.so
+
+ -- Julien Cristau <jcristau@debian.org>  Mon, 09 Apr 2007 20:38:22 +0200
+
+xorg-server (2:1.2.99.905-1) experimental; urgency=low
+
+  * New upstream release candidate.
+    + includes fix for CVE-2007-1003: XC-MISC Extension ProcXCMiscGetXIDList()
+      Memory Corruption.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 06 Apr 2007 12:05:40 +0200
+
+xorg-server (2:1.2.99.903-1) experimental; urgency=low
+
+  [ Drew Parsons ]
+  * Add exclude entries to dh_install in debian/rules.
+
+  [ Julien Cristau ]
+  * Prepare packaging to ship debugging symbols for xserver-xorg-core in
+    xserver-xorg-core-dbg, but leave it commented out so we can get rc3 in the
+    archive first.
+  * New upstream release candidate.
+    + bump serverminver to 2:1.2.99.903.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 27 Mar 2007 07:33:29 +0200
+
+xorg-server (2:1.2.99.902-1) experimental; urgency=low
+
+  [ Drew Parsons ]
+  * Bring xprint back into the xorg fold.
+    - include existing patches:
+      - 91_ttf2pt1 allows Xprint to use ttf2pt1 for Type1 font handling
+      	(but extract and apply manually the patch to
+       	hw/xprint/ps/Makefile.am so it may be applied by autoconf)
+      - 91_ttf2pt1_updates brings ttf2pt1 into the modern X11R7.1 world
+      - 92_xprint-security-holes-fix.patch places PS/PDF file output
+      	into the user's home directory (~/Xprintjobs), more secure than
+      	a shared /tmp/Xprintjobs
+      - 93_spooltodir_check_file_exists ensures output filenames are
+      	less than 256 characters in length
+      - 93_xprint_fonts_fix released references to font names after use.
+     - enable freetype support for Xprint.
+     - add descriptions to debian/control and Build-Dependency on
+       x11proto-print-dev
+  * Run autoreconf to update changes to hw/xprint/ps/Makefile.am.
+
+  [ Brice Goglin ]
+  * Apply patch from adrian@smop.co.uk to our xvfb-run wrapper
+    to check whether Xvfb started ok and fix its cleanup
+    (closes: #351042).
+
+  [ Julien Cristau ]
+  * New upstream release candidate.
+  * Bump serverminver to 2:1.2.99.902.
+  * Drop patch 42_build_int10_submodules.diff, and use x86emu on all
+    architectures instead (closes: #410879).
+  * Refresh patches:
+    + 12_security_policy_in_etc.diff
+    + 21_glx_align_fixes.patch
+    + 23_kfreebsd_support.diff
+  * Delete a few files generated by configure on clean, since they seem to
+    have been included in the tarball.
+
+ -- Julien Cristau <jcristau@debian.org>  Thu, 15 Mar 2007 04:28:00 +0100
+
+xorg-server (2:1.2.99.901-1) experimental; urgency=low
+
+  * New upstream release candidate.
+    + Remove patches 24 (hurd support), 35 (randr byteswap) and 43 (set damage
+      version), applied upstream.
+    + Bump build-dep on x11proto-randr-dev to >= 1.2, and on
+      x11proto-damage-dev to >= 1.1.
+
+ -- Julien Cristau <jcristau@debian.org>  Wed,  7 Mar 2007 19:58:53 +0100
+
+xorg-server (2:1.2.0-6) experimental; urgency=low
+
+  * Set videoabiver to 1.0, same as in xorg-server 1.1.
+
+ -- Julien Cristau <jcristau@debian.org>  Fri,  2 Mar 2007 16:38:12 +0100
+
+xorg-server (2:1.2.0-5) experimental; urgency=low
+
+  * Add input ABI versioning metadata. Rename serverabiver file to
+    videoabiver, and add inputabiver. Bump serverminver to 2:1.2.0-5 to deal
+    with this change.
+
+ -- David Nusinow <dnusinow@debian.org>  Thu,  1 Mar 2007 22:09:45 -0500
+
+xorg-server (2:1.2.0-4) experimental; urgency=low
+
+  [ Julien Cristau ]
+  * Don't strip modules when DEB_BUILD_OPTIONS contains nostrip.  Thanks,
+    Cyril Brulebois!
+
+  [ David Nusinow ]
+  * Move serverabiver file to serverminver. Use serverabiver to store the
+    actual video ABI version number (1.1 right now). This will allow drivers
+    to automatically generate their Provides: xserver-xorg-video-* line when
+    built against a particular server version. The rename of the files
+    is to better denote what they actually are.
+  * Bump the serverminver to 2:1.2.0-4 because of this change
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 21 Feb 2007 21:53:51 -0500
+
+xorg-server (2:1.2.0-3) experimental; urgency=low
+
+  [ Julien Cristau ]
+  * Pass --with-os-name and --with-os-vendor to configure.
+  * Bump serverabiver to 2:1.2.0-1.
+  * Add patch from upstream git to set the supported damage version from the
+    server, instead of from the damage headers.  xserver 1.2.0 supports damage
+    1.0, not 1.1.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 17 Feb 2007 12:03:03 +0100
+
+xorg-server (2:1.2.0-2) experimental; urgency=low
+
+  * Delete useless debian/substvars.
+  * Change my email address in debian/control.
+  * Fix patch 42_build_int10_submodules.diff.  The definition of
+    xf86InitInt10() was moved to int10/helper_exec.c between 1.1.1 and 1.2.0,
+    so we move it to int10/helper_mem.c, which we build in the main int10
+    module, not the vm86 and x86emu submodules.  Thanks to Cédric Augonnet and
+    Brice Goglin for the report and testing.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 10 Feb 2007 20:57:57 +0100
+
+xorg-server (2:1.2.0-1) experimental; urgency=low
+
+  * New upstream release.
+    + 40_xorg-xserver-1.1.0-dbe-render.diff dropped.
+    + 38_GetDrawableAttributes.patch dropped.
+    + 37_build-mesa-mipmap.patch dropped.
+    + 33_Xserver_man_typos.patch dropped.
+    + 24_hurd_support.diff massively reduced.
+    + 13_debian_add_xkbpath_env_variable.diff refreshed.
+    + 07_xorgconf_manpage_overhaul.diff updated.
+    + 42_build_int10_submodules.diff updated.
+  * Bump build-dep on mesa-swx11-source to >= 6.5.2.
+  * Version build-dependencies on x11proto-composite-dev and x11proto-kb-dev
+    to match configure.ac.
+  * Add build-dep on libxfixes-dev (needed for Xdmx).
+
+ -- Julien Cristau <jcristau@debian.org>  Fri,  9 Feb 2007 20:54:27 +0100
+
+xorg-server (2:1.1.99.903-1) experimental; urgency=low
+
+  * New upstream release candidate.
+  * Forward-port patches:
+    * 07_xorgconf_manpage_overhaul.diff: refresh
+    * 12_security_policy_in_etc.diff: refresh
+    * 21_glx_align_fixes.patch: refresh
+    * 23_kfreebsd_support.diff: refresh
+    * 24_hurd_support.diff: refresh
+    * 34_xorg.conf_man_typos.patch: refresh
+    * 36_fix_ffs.patch: remove, applied upstream
+  * Bump build-dependency on libdrm-dev to (>= 2.3.0) because that is the X
+    server's minimum requirement.
+
+ -- Thierry Reding <thierry@gilfi.de>  Sat,  2 Dec 2006 12:44:59 +0100
+
+xorg-server (2:1.1.99.902-1) experimental; urgency=low
+
+  * Update to latest upstream release candidate.
+  * Forward-port patches:
+    * 02_libvgahw_gcc4_volatile_fix.diff: update
+    * 04_read_rom_in_chunks.diff: update
+    * 05_arm_cache_flush.diff: remove, applied upstream
+    * 06_arm_is_not_x86_and_has_no_vga.diff: remove, applied upstream
+    * 07_xorgconf_manpage_overhaul.diff: update
+    * 08_s390_servermd.diff: update
+    * 09_debian_xserver_rtff.diff: update
+    * 12_security_policy_in_etc.diff: update
+    * 13_debian_add_xkbpath_env_variable.diff: update
+    * 15_symlink_mesa.diff: remove, fixed upstream
+    * 16_s390_fix.diff: update
+    * 17_ignoreabi.diff: remove, applied upstream
+    * 18_execinfo_only_for_backtrace.patch: remove, applied upstream
+    * 18_execinfo_configured.patch: remove, applied upstream
+    * 19_configurable_misc_utils.patch: remove, applied upstream
+    * 20_mesa_6.5.1.diff: remove, applied upstream
+    * 21_glx_align_fixes.patch: update
+    * 22_xkb_cycle_3layouts.diff: remove, applied upstream
+    * 23_kfreebsd_support.diff: update, partially applied upstream
+    * 24_hurd_support.diff: update, partially applied upstream
+    * 25_tfp_damage.diff: remove, applied upstream
+    * 26_aiglx_happy_vt_switch.diff: remove, applied upstream
+    * 27_aiglx_locking.diff: remove, applied upstream
+    * 28_mesa_copy_sub_buffer.diff: remove, applied upstream
+    * 29_mesa_reseed_makefile.diff: remove, fixed upstream
+    * 30_fix_vmode_switch.diff: remove, fixed upstream
+    * 31_blocksigio.diff: remove, fixed upstream
+    * 32_disable_sparc_pci_bridge.diff: update
+    * 34_xorg.conf_man_typos.patch: update
+    * 35_randr_byteswap.patch: update
+    * 36_fix_ffs.patch: update
+    * 37_Fix-__glXDRIbindTexImage-for-32-bpp-on-big-endian-platforms.diff:
+      remove, applied upstream
+  * Upstream no longer ships a changelog, so don't try to install it.
+  * Add 37_build-mesa-mipmap.patch that adds the missing mipmap.c to libmain's
+    sources.
+  * Add 38_GetDrawableAttributes.patch which readds support for the
+    GetDrawableAttributes extension that's needed for compiz to work properly.
+
+ -- Thierry Reding <thierry@gilfi.de>  Fri,  1 Dec 2006 20:32:34 +0100
+
+xorg-server (2:1.1.1-21) unstable; urgency=emergency
+
+  * Security update.
+  * Fix integer overflow in the ProcXCMiscGetXIDList() function in the XC-MISC
+    extension.  Reference: CVE-2007-1003.
+
+ -- Julien Cristau <jcristau@debian.org>  Wed, 04 Apr 2007 00:34:51 +0200
+
+xorg-server (2:1.1.1-20) unstable; urgency=low
+
+  * xephyr: Add patch from upstream git to fix memory leak in
+    ephyrScreenFini().  Thanks, Guillem Jover!
+
+ -- Julien Cristau <jcristau@debian.org>  Tue,  6 Mar 2007 22:20:14 +0100
+
+xorg-server (2:1.1.1-19) unstable; urgency=high
+
+  [ Drew Parsons ]
+  * Removed spurious space in default font line
+    (/usr/X11R6/lib/X11/fonts/Type1 not "/usr/X11R6/lib/  X11/fonts/Type1")
+
+  [ David Nusinow ]
+  * Conflict with and replace xserver-common, because that package used to 
+    provide the SecurityPolicy file. This is an RC bugfix because it breaks
+    upgrades, so it gets a high urgency. Thanks Christian Tsotras and Lionel
+    Elie Mamane for reporting and it. Closes: #402658
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 28 Feb 2007 21:48:19 -0500
+
+xorg-server (2:1.1.1-18) unstable; urgency=medium
+
+  * Add patch from Fedora to make xephyr work on 64bit architectures
+    (closes: #405928).
+
+ -- Julien Cristau <jcristau@debian.org>  Fri, 16 Feb 2007 22:20:08 +0100
+
+xorg-server (2:1.1.1-17) unstable; urgency=medium
+
+  * Make the int10 module usable on i386 with a 64bit kernel (closes: #409730).
+    + New patch 42_build_int10_submodules.diff, which allows us to build vm86
+      and x86emu as two separate submodules, and make the int10 module itself
+      fall back to loading x86emu if vm86 calls fail.
+    + Add workaround for https://bugs.freedesktop.org/show_bug.cgi?id=7299 to
+      the above patch: move definition of Int10Current from int10/xf86int10.c
+      to int10/helper_mem.c.
+    + Drop the part of 39_alpha_build_flags.patch applying to
+      hw/xfree86/os-support/linux/Makefile.in, and run autoreconf with all
+      patches applied.
+
+ -- Julien Cristau <jcristau@debian.org>  Wed,  7 Feb 2007 20:37:19 +0100
+
+xorg-server (2:1.1.1-16) unstable; urgency=medium
+
+  * New patch 41_xfree86_linux_acpi_fix_tokenizing.diff from upstream git to
+    fix a crash on acpi events (closes: #409443).
+
+ -- Julien Cristau <julien.cristau@ens-lyon.org>  Sat,  3 Feb 2007 22:56:04 +0100
+
+xorg-server (2:1.1.1-15) unstable; urgency=high
+
+  * High-urgency upload for security bugfix.
+  * New patch 40_xorg-xserver-1.1.0-dbe-render.diff to fix multiple integer
+    overflows in the dbe and render extensions.
+    CVE IDs: CVE-2006-6101 CVE-2006-6102 CVE-2006-6103
+  * Add myself to Uploaders, and remove Fabio and Branden, with their
+    permission.  They're of course welcome back when they have more time!
+
+ -- Julien Cristau <julien.cristau@ens-lyon.org>  Tue,  9 Jan 2007 15:45:46 +0100
+
+xorg-server (2:1.1.1-14) unstable; urgency=high
+
+  * The "let's drop 20 years of build logic and replace it with autoconf in a
+    single release, trust me, what could go wrong? <gibber, gibber>" release
+  * High-urgency upload for RC bugfix
+  * New patch 39_alpha_build_flags.patch: no really, when they said
+    lnx_ev56.c should be built with -mcpu=ev56, they really meant it.
+    Closes: #392500.
+
+ -- Steve Langasek <vorlon@debian.org>  Sun,  7 Jan 2007 15:19:08 -0800
+
+xorg-server (2:1.1.1-13) unstable; urgency=medium
+
+  [ Julien Cristau ]
+  * xserver-xorg-core recommends xfonts-base and suggests xfonts-100dpi |
+    xfonts-75dpi and xfonts-scalable.  Also add explanation about fonts to the
+    long description, stolen from the old xserver-common package (closes:
+    #400654).
+
+  [ David Nusinow ]
+  * This is important for upgrades to etch, and has no notable risk, so bump
+    priority to medium.
+
+ -- David Nusinow <dnusinow@debian.org>  Fri, 29 Dec 2006 19:57:51 -0500
+
+xorg-server (2:1.1.1-12) unstable; urgency=low
+
+  [ Julien Cristau ]
+  * Delete hw/xfree86/common/xf86Build.h in debian/rules clean, since it's
+    wrongly included in the upstream tarball.
+
+  [ David Nusinow ]
+  * Pull fix for the ignore_abi.diff patch. This one's a major brown bag on my
+    part. Thanks Michel Dänzer.
+  * Add 38_wait_for_something_force_timer_reset.diff which forces the server
+    to reset timers when they've overrun in some cases rather than wait
+    forever. Patch by Daniel Stone. Thanks Michel Dänzer for pointing the
+    changes out. Closes: #374026
+
+ -- David Nusinow <dnusinow@debian.org>  Tue, 12 Dec 2006 21:13:20 -0500
+
+xorg-server (2:1.1.1-11) unstable; urgency=low
+
+  [ Drew Parsons ]
+  * Patches 33_Xserver_man_typos.patch and 34_xorg.conf_man_typos.patch
+    fix minor typos in Xserver and xorg.conf man pages.
+    Closes: #364556, #308899.
+  * Add patch 35_randr_byteswap.patch from upstream. Fixes a client/server
+    byteswapping problem. Closes: #291100.
+
+  [ Julien Cristau ]
+  * Don't build-depend on libdrm-dev on hurd-i386 (closes: #358015). Thanks,
+    Samuel Thibault.
+  * Update hurd support patch (closes: #356300). Thanks, Samuel Thibault.
+  * Add reportbug script stolen from the monolith, to add the user's config
+    and log file in every bug report.
+  * Delete hw/xfree86/common/xf86Build.h from our source tree, so that the
+    build date is correctly calculated at build time, and not hardcoded to
+    07 July 2006.  Thanks to Jurij Smakov for noticing.
+  * Add patch 36_fix_ffs.patch by Jurij Smakov to fix infinite loop in ffs()
+    if called with an argument of 0 (closes: #395564).
+  * Add patch 37_Fix-__glXDRIbindTexImage-for-32-bpp-on-big-endian-platforms
+    from upstream git to fix color issue on big endian platforms
+    (closes: #392453). Thanks to Michel Dänzer for the patch!
+  * Fix typo in xvfb-run (closes: #337703).
+  * Install xdmxconfig and its manpage in xdmx-tools (closes: #393991).
+  * Add Replaces: xdmx (<= 2:1.1.1-10) to xdmx-tools because of the xmdxconfig
+    manpage move.
+
+ -- David Nusinow <dnusinow@debian.org>  Fri, 24 Nov 2006 15:44:52 -0500
+
+xorg-server (2:1.1.1-10) unstable; urgency=low
+
+  [ Denis Barbier ]
+  * Fix video mode switching.  Closes: #391052
+  * Fix FTBFS on kfreebsd-i386 and kfreebsd-amd64.  Thanks Petr Salinger.
+    Closes: #363517
+
+  [ David Nusinow ]
+  * Add depends on xserver-xorg so that /etc/X11/X gets installed. Thanks
+    Frans Pop. Closes: #392295
+  * Add 31_blocksigio.diff. This patch by Alan Hourihane, and it prevents a
+    race condition when a driver tries to set the cursor state when the server
+    is in the middle of switching resolution. Thanks to Frans Pop for
+    reporting the bug, Michel Dänzer for reading through the backtrace and
+    diagnosing the problem, and Alan for the final patch. Closes: #390646.
+
+  [ Jurij Smakov ]
+  * Add 32_disable_sparc_pci_bridge.diff. Disable PCI bridge handling on
+    sparc, which is broken and causes filesystem corruption (by poking
+    the PCI bus in the wrong places) on some machines. Closes: #392312.
+
+  [ Drew Parsons ]
+  * Use __appmansuffix__ not __mansuffix__ in
+    03_xnest_manpage_overhaul.diff.  Closes: #390599.
+  * Install upstream ChangeLog.  Closes: #365274.
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 16 Oct 2006 21:59:51 -0400
+
+xorg-server (2:1.1.1-9) unstable; urgency=low
+
+  [ Jurij Smakov ]
+  * Add 21_glx_align_fixes.patch to reintroduce the setting of __GLX_ALIGN64
+    variable, lost during the modular transition. This setting is essential
+    for architectures with strong alignment requirements. Patch affects
+    alpha, sparc, amd64, ia64 and s390, mimicking the behaviour of the
+    monolithic build. Closes: #388125.
+
+  [ Denis Barbier ]
+  * Add 22_xkb_cycle_3layouts.diff to fix layout switching when 3 layouts
+    are present.  Thanks Ivan Pascal for the patch.  Closes: #345803
+
+  [ David Nusinow ]
+  * Add kFreeBSD support patch (23). Thanks to Robert Millan, Petr Salinger,
+    Daniel Stone, and Michael Banck for input and patch writing.
+    Closes: #363517
+  * Add hurd support patch (24). Thanks Samuel Thibault, Daniel Stone, and
+    Michael Banck. Closes: #356300
+  * Disable the explicit enabling of dri in the configure. The configure
+    script autodetects whether or not to use this anyway, and enabling it
+    explicitly breaks the build on hurd. Thanks Samuel Thibault and Michael
+    Banck. Closes: #358015
+  * Add several patches written by Kristian Høgsberg for allowing compiz to
+    work with AIGLX. These patches were vetted by Theirry Reding with valuable
+    advice from Michel Dänzer, and feedback from Kristian himself.
+    - 25_tfp_damage.diff
+    - 26_aiglx_happy_vt_switch.diff
+    - 27_aiglx_locking.diff
+    - 28_mesa_copy_sub_buffer.diff
+    - 29_mesa_reseed_makefile.diff
+    - update of 20_mesa_6.5.1.diff
+  * Remove bizarre wholesale inclusion of another patch in the 23_kbsd patch
+
+  [ Eugene Konev ]
+  * Use --with-default-font-path instead of --with-fontdir.
+  * Set RGBPath through --with-rgb-path.
+  * Drop 11_debian_always_use_default_font_path.diff.
+  * Drop 14_debian_always_look_in_our_module_path.diff.
+  * Ship SecurityPolicy in xserver-xorg-core.
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 28 Sep 2006 23:59:35 -0400
+
+xorg-server (2:1.1.1-8) unstable; urgency=low
+
+  * Update mesa symlink patch to the latest from HEAD
+  * Add 20_mesa_6.5.1.diff to allow the server to build with mesa 6.5.1
+  * Bump build-dep versions on x11proto-gl to 1.4.8, and mesa to 6.5.1
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 25 Sep 2006 22:21:37 -0400
+
+xorg-server (2:1.1.1-7) unstable; urgency=low
+
+  * Fix s390 build issue. Thanks Bastian Blank for the report and Eugene Konev
+    for the patch. Closes: #388628.
+  * Disable build of various utilities that we don't ship anyway. Patch thanks
+    to Eugene Konev.
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 21 Sep 2006 23:07:16 -0400
+
+xorg-server (2:1.1.1-6) unstable; urgency=low
+
+  * Upload 7.1 to unstable.
+
+  [ Drew Parsons ]
+  * Added SGI FreeB licence to debian/copyright. Closes: #368563.
+  * Apply upstream patches 18_execinfo_only_for_backtrace.patch, to use
+    execinfo.h for and only for backtrace. Applied git patch
+    5a3488ccac8e5dabd9fc98bc41ef178ead1b2faf directly into configure scripts,
+    activated with autoreconf.  Closes: #363218.
+  * Only requires build-depends version of x11proto-gl-dev on 1.4.6.
+
+  [ Steve Langasek ]
+  * Add versioned build-depends on x11proto-fixes-dev (>= 4.0), to
+    ensure the package is built against the right protocol version.
+    Closes: #383778.
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 18 Sep 2006 18:30:07 -0400
+
+xorg-server (2:1.1.1-5) experimental; urgency=low
+
+  * Fix error in 16_s390_fix.diff caused by my idiot copying. Thanks Yannick
+    Roehlly and Daniel Stone.
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 27 Aug 2006 23:25:21 +0000
+
+xorg-server (2:1.1.1-4) experimental; urgency=low
+
+  [ Drew Parsons ]
+  * Tighten dependencies between X11R7.1 server and video drivers.
+    xserver-xorg-core no longer Depends: xserver-xorg-video-all
+    | xserver-xorg-video but instead Conflicts: xserver-xorg-video.
+    (closes: #383873)
+    The dependency on xserver-xorg-video-all | xserver-xorg-video-1.0 is
+    managed by the xserver-xorg binary package (not included here in
+    order to avoid circular dependencies). (closes: #362313)
+  * Likewise remove Depends: xserver-xorg-input-all | xserver-xorg-input
+    (again, handled by xserver-xorg) to avoid circular dependency with drivers.
+
+  [ David Nusinow ]
+  * Epoch bump
+  * Add 17_ignoreabi.diff to allow users to simply set a value in xorg.conf
+    rather than pass -ignoreABI to the server every time it starts
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 23 Aug 2006 22:03:06 +0000
+
+xorg-server (1:1.1.1-3) unstable; urgency=low
+
+  * Add 16_s390_fix.diff to fix FTBFS on s390. Thanks Bastian Blank.
+    (closes: #362641)
+  * Bump build-depends version of libgl1-mesa-dev to 6.5.x package we have in
+    experimental currently
+  * Bump build-depends version of x11proto-gl-dev to 1.4.7 or greater
+
+ -- David Nusinow <dnusinow@debian.org>  Tue, 22 Aug 2006 00:57:31 +0000
+
+xorg-server (1:1.1.1-2) experimental; urgency=low
+
+  [ Drew Parsons ]
+  * Updated mesa-swx11-source build-depends to (>> 6.5.0), required
+    for xserver 1.1.1. (closes: #383334)
+
+  [ David Nusinow ]
+  * Enable and ship xephyr
+  * Hack off the 'x' manpage suffix
+  * Install Xnest manpage
+  * Bump policy version to 3.7.2.0. No changes necessary.
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 16 Aug 2006 21:14:44 +0000
+
+xorg-server (1:1.1.1-1) experimental; urgency=low
+
+  [ David Nusinow ]
+  * New upstream release
+  * Move patch target call so that we don't try and build twice
+  * Remove obsolete 15_security_allocate_local.diff and
+    16_SECURITY_setuid.diff
+  * Add 15_symlink_mesa.diff
+
+ -- David Nusinow <dnusinow@debian.org>  Sun,  6 Aug 2006 16:12:25 +0000
+
+xorg-server (2:1.0.2-10) unstable; urgency=low
+
+  * Upload to unstable to fixed messed up last upload which was supposed to go
+    to experimental. Brown bag o' joy.
+
+ -- David Nusinow <dnusinow@debian.org>  Tue, 22 Aug 2006 19:31:08 +0000
+
+xorg-server (1:1.0.2-9) UNRELEASED; urgency=high
+
+  [ Denis Barbier ]
+  * Fix 13_debian_add_xkbpath_env_variable.diff, XKBPATH environment
+    variable was not always taken into account.
+
+  [ David Nusinow ]
+  * Remove two Ubuntu packaging holdovers. Have xvfb recommend xbase-clients
+    rather than xauth, and have xserver-xorg-core recommend xkb-data rather
+    than xkeyboard-config. Thanks Sterling MacNay.
+  * Security update. Fix for setuid privledge escalation vulernabilities.
+    See http://lists.freedesktop.org/archives/xorg/2006-June/016146.html for
+    the full advisory.
+
+  [ Jurij Smakov ]
+  * Stop including the non-existent asm/kbio.h header file in
+    hw/xfree86/os-support/linux/lnx_{io,kbd}.c to avoid the build failure
+    on sparc.
+
+ -- David Nusinow <dnusinow@debian.org>  Sat,  1 Jul 2006 17:20:45 -0400
+
+xorg-server (1:1.0.2-8) unstable; urgency=low
+
+  * Move xserverrc back to xbase-clients. Thanks Benjamin Mesing.
+  * Add 15_security_allocate_local.diff. This fixes Bug fd.o bug #6642.
+    Fix buffer overflow in Render.  (CVE 2006-1526). Patch by Eric Anholt.
+
+ -- David Nusinow <dnusinow@debian.org>  Tue,  2 May 2006 21:47:17 -0400
+
+xorg-server (1:1.0.2-7) unstable; urgency=low
+
+  * Ship xserverrc again in /etc/X11/xinit. Thanks Bastian Kleineidam and
+    Vasilis Vasaitis. (closes: #357713)
+
+ -- David Nusinow <dnusinow@debian.org>  Wed, 26 Apr 2006 00:01:16 -0400
+
+xorg-server (1:1.0.2-6) unstable; urgency=low
+
+  [ David Nusinow ]
+  * Use -DNO_INLINE on s390. Thanks Bastian Blank and Julien Cristau.
+    (closes: #362641)
+  * Re-add xvfb-run and manpage to xvfb package. Thanks Josselin Mouette and
+    Jamie Wilkinson. (closes: #363494)
+  * Add 014_debian_always_look_in_our_module_path.diff. This will cause the
+    server to always look in the default module path even if they've specified
+    an alternate path in their xorg.conf file via the ModulePath option. A
+    note to users: you should remove this part of your xorg.conf unless you
+    need it, as the server will look in the right place for modules if you
+    don't specify a location.
+  * Run dh_install with --list-missing
+  * Add missing manpages all around. Thanks Roland Mas and Jan Hudec.
+    (closes: #362489, #364199)
+  * Actually install apps to xdmx-tools. Thanks Xavier Bestel.
+    (closes: #356813)
+
+  [ Denis Barbier ]
+  * Add 13_debian_add_xkbpath_env_variable.diff so that the server takes
+    the XKBPATH environment variable into account. (closes: #363229)
+
+ -- David Nusinow <dnusinow@debian.org>  Sat, 22 Apr 2006 17:06:23 -0400
+
+xorg-server (1:1.0.2-5) unstable; urgency=low
+
+  * Add 11_debian_always_use_default_font_path.diff from Eugene Konev. This
+    patch causes the server to add the default font path to whatever the user
+    has specified. Right now, that's /usr/share/fonts/X11, as defined on
+    configure in debian/rules. Thanks Eugene, this will definitely go a long
+    way.
+  * Document how to get rid of error loading glcore (and other modules) in
+    NEWS.Debian. Thanks Matej Vela and others.
+  * Provide the virtual 'xserver' package. Thanks Steve Langasek and Daniel
+    Stone. (closes: #362750)
+  * Add 12_security_policy_in_etc.diff from Eugene Konev. This will allow us
+    to tell the server on configure to look in /etc/X11/xserver for the
+    SecurityPolicy file. Thanks Joey Hess and Eugene. (closes: #362246)
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 17 Apr 2006 00:34:08 -0400
+
+xorg-server (1:1.0.2-4) unstable; urgency=low
+
+  * Document the need to update paths in xserver-xorg-core's NEWS file.
+    (closes: #362077, #362244, #362431)
+  * Make xserver-xorg-core Architecture: any. (closes: #362150)
+  * Build with --with-fontdir=/usr/share/fonts/X11. Remove
+    --with-default-font-path option to make this work. Thanks Eugene Konev.
+
+ -- David Nusinow <dnusinow@debian.org>  Thu, 13 Apr 2006 23:54:06 -0400
+
+xorg-server (1:1.0.2-3) unstable; urgency=low
+
+  * Add build-conflicts on xlibs-static-dev. Thanks Zephaniah E. Hull.
+
+ -- David Nusinow <dnusinow@debian.org>  Tue, 11 Apr 2006 18:44:51 -0400
+
+xorg-server (1:1.0.2-2) unstable; urgency=low
+
+  * Upload to unstable
+  * Add versioned build-dep on libdmx-dev. Thanks Frank Lichtenheld.
+    (closes: #361752)
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 10 Apr 2006 19:34:04 -0400
+
+xorg-server (1:1.0.2-1) experimental; urgency=low
+
+  [ David Nusinow ]
+  * New upstream release. Fixes CVE-2006-0745
+
+  [ Denis Barbier ]
+  * Set XKB base path to /usr/share/X11/xkb.
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 20 Mar 2006 21:41:04 -0500
+
+xorg-server (1:1.0.1-2) experimental; urgency=low
+
+  [ David Nusinow ]
+  * Add versioned dependency on x11-common
+  * Remove old cruft in our patches directory
+  * Port patches from trunk
+    + 030_libvgahw_gcc4_volatile_fix.diff
+    + general/026_xc_programs_manpage_overhaul.diff
+    + arm/303_arm_cache_flush.diff
+    + arm/315_arm_is_not_x86_and_has_no_vga.diff
+    + general/099e_xorgconf_manpage_overhaul.diff
+    + s390/500_s390_support.diff
+    + debian/910_debian_Xserver_RTFF.diff
+  * add 04_read_rom_in_chunks.diff. This reads PCI ROM in large chunks rather
+    than one byte at a time. This patch by Alex Williamson and forwarded to us
+    by Dann Frazier. Thanks to both of them. (closes: #353168)
+  * Don't build xserver-xorg-core on s390. This means putting all the other
+    arches as being explicitly listed. Damn !s390.
+  * Version the conflict with xserver-xfree86 to allow for the transition
+    package to be installed
+  * Remove README.DRI, as it is non-free. Add it to prune list.
+  * Add 10_dont_look_in_home_for_config.diff to prevent looking in a user's
+    home directory for xorg.conf. Thanks Daniel Stone for the patch.
+
+ -- David Nusinow <dnusinow@debian.org>  Sun, 12 Mar 2006 16:18:13 -0500
+
+xorg-server (1:1.0.1-1) experimental; urgency=low
+
+  * First upload to Debian
+  * Add bison and flex to the build-depends
+  * Define INSTALL in debian/rules
+  * Add xserver-xorg-core dependency xserver-xorg-video-all |
+    xserver-xorg-video. The former is a metapackage that depends on all the
+    video drivers we ship and the latter is a virtual package that each video
+    driver provides. This scheme will install the metapackage by default but
+    will permit any single video driver to satsify the dependency. Do the same
+    thing for the input drivers.
+  * switch dpatch build-dependency to quilt
+  * Deal with mesa packaging rename: build-dep on mesa-swrast-source ->
+    mesa-swx11-source
+  * Change xserver-core depends to be on x11-common rather than xorg-common
+  * Have xserver-xorg-dev install the files in /usr/share/aclocal so we get
+    xorg-server.m4
+  * Manually set permissions on serverabiver installation
+  * Set the default font path to /usr/share/fonts/X11 instead of
+    /usr/share/X11/fonts. Thanks Eugene Konev.
+
+ -- David Nusinow <dnusinow@debian.org>  Mon, 20 Feb 2006 00:18:45 -0500
+
+xorg-server (1:0.99.2+cvs.20051025-3) dapper; urgency=low
+
+  * Version mesa-swrast-source Build-Dep to 6.4.0 or higher, so GLcore is a
+    little less crash-happy (e.g. when moving your glxgears window).
+  * Export /usr/share/xserver-xorg/serverabiver to xserver-xorg-dev, which
+    describes the relationship needed from a driver on xserver-xorg-core.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Fri, 28 Oct 2005 13:00:26 +1000
+
+xorg-server (1:0.99.2+cvs.20051025-2) dapper; urgency=low
+
+  * Add Build-Deps on libxaw7-dev, libxmu-dev, libxt-dev, libxpm-dev,
+    libx11-dev, libxtst-dev, and libxres-dev for DMX utils.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Wed, 26 Oct 2005 14:34:40 +1000
+
+xorg-server (1:0.99.2+cvs.20051025-1) dapper; urgency=low
+
+  * Update to new upstream version.
+  * All applicable patches have been committed upstream, bar #989 and #990.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Thu, 20 Oct 2005 10:26:33 +1000
+
+xorg-server (1:0.99.0+cvs.20050901-1) breezy; urgency=low
+
+  * First xorg-server release.
+
+ -- Daniel Stone <daniel.stone@ubuntu.com>  Wed,  6 Jul 2005 15:48:17 +1000
--- xorg-server-1.4.2.orig/debian/compat
+++ xorg-server-1.4.2/debian/compat
@@ -0,0 +1 @@
+4
--- xorg-server-1.4.2.orig/debian/xprint.links
+++ xorg-server-1.4.2/debian/xprint.links
@@ -0,0 +1 @@
+usr/share/doc/xprint-common usr/share/doc/xprint
--- xorg-server-1.4.2.orig/debian/xprint-overrides
+++ xorg-server-1.4.2/debian/xprint-overrides
@@ -0,0 +1,2 @@
+# piss-off
+xprint binary: description-starts-with-package-name
--- xorg-server-1.4.2.orig/debian/xdmx.install
+++ xorg-server-1.4.2/debian/xdmx.install
@@ -0,0 +1,2 @@
+usr/bin/Xdmx
+usr/share/man/man1/Xdmx.1
--- xorg-server-1.4.2.orig/debian/po/cs.po
+++ xorg-server-1.4.2/debian/po/cs.po
@@ -0,0 +1,56 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xprint-xprintorg\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-09-18 19:23+0200\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Výchozí rozlišení tiskárny:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint implicitně předpokládá rozlišení tiskárny 600 dpi. To by mělo "
+"vyhovovat většině dnešních tiskáren."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Na některých 1200 dpi tiskárnách může obraz vypadat příliš malý, zatímco na "
+"300 dpi tiskárnách se může obraz vytisknout příliš velký. Pokud zaznamenáte "
+"popsané problémy, měli byste nastavit výchozí rozlišení tiskárny na "
+"vhodnější hodnotu. Podrobnosti naleznete v souboru /usr/share/doc/xprint-"
+"common/README.printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/hu.po
+++ xorg-server-1.4.2/debian/po/hu.po
@@ -0,0 +1,44 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-09-18 08:21+0100\n"
+"Last-Translator: SZERVÁC Attila <sas@321.hu>\n"
+"Language-Team: Hungarian <debian-l10n-hungarian@lists.d.o>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Hungarian\n"
+"X-Poedit-Country: HUNGARY\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Alapértelmezett nyomtató felbontás:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Alapban az Xprint 600dpi-s nyomtató felbontást feltételez. Ez jó a legtöbb "
+"nyomtatóhoz."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Egyes 1200dpi-s nyomtatókon viszont a kép a sarokba kerülhet vagy kilóghat "
+"egyes 300dpi-s eszközökön. Hasonló hibáknál állítsd az alap nyomtató "
+"felbontást megfelelő értékre. Lásd a /usr/share/doc/xprint-common/README."
+"printing-problems.gz fájlt a részletekért."
--- xorg-server-1.4.2.orig/debian/po/pt.po
+++ xorg-server-1.4.2/debian/po/pt.po
@@ -0,0 +1,48 @@
+# Portuguese translation for xorg-server's debconf messages
+# Copyright (C) 2007 Miguel Figueiredo
+# This file is distributed under the same license as the xorg-server package.
+# Miguel Figueiredo <elmig@debianpt.org>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-10-02 21:27+0000\n"
+"Last-Translator: Miguel Figueiredo <elmig@debianpt.org>\n"
+"Language-Team: Portuguese <traduz@debianpt.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Resolução de impressão pré-definida:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Como pré-definição o Xprint assume que a resolução da sua impressora é de "
+"600 dpi. Isto deve ser adequado para a maioria das impressoras."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"No entanto, nalgumas impressoras de 1200 dpi a imagem pode parecer encolhida "
+"no canto da página, ou pode aparecer demasiado grande em impressoras de 300 "
+"dpi. Se estiver a ter estes problemas de impressão, você pode querer definir "
+"a resolução de impressão pré-definida para um valor mais apropriado. Para "
+"mais detalhes veja /usr/share/doc/xprint-common/README.printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/eu.po
+++ xorg-server-1.4.2/debian/po/eu.po
@@ -0,0 +1,50 @@
+# translation of xorg-server-templates.po to Euskara
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Piarres Beobide <pi@beobide.net>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server-templates\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-18 09:59+0200\n"
+"Last-Translator: Piarres Beobide <pi@beobide.net>\n"
+"Language-Team: Euskara <Librezale@librezale.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Lehenetsiko inprimagailu erresoluzioa:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Lehenespenez, Xprint-ek inprimagailu erresoluzioa 600 dpi-koa dela "
+"pentsatuko du. Balio hau egokia izan beharko litzateke inprimagailu "
+"gehienentzat."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"1200 dpi-ko zenbait inprimagailuetan hala ere irudia orriaren ertzean agertu "
+"daiteke edo handiegia izan liteke 300 dpi-ko inprimagailuentzat. Horrelako "
+"arazoak jasaten badituzu eta inprimagailu erresoluzioa beste balio "
+"erabilgarriago batetara aldatu nahi izanez gero irakurri /usr/share/doc/"
+"xprint-common/README.printing-problems.gz xehetasun gehiagorako."
--- xorg-server-1.4.2.orig/debian/po/nl.po
+++ xorg-server-1.4.2/debian/po/nl.po
@@ -0,0 +1,58 @@
+# Translation of xprint_1:0.1.0.alpha1-13_templates.po to dutch
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xprint_1:0.1.0.alpha1-13_nl\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2008-07-16 18:24\n"
+"Last-Translator: Thijs Kinkhorst <thijs@debian.org>\n"
+"Language-Team: Nederlands <debian-l10n-dutch@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.10.2\n"
+"Plural-Forms:  nplurals=2; plural=(n != 1);\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Standaard printerresolutie:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Standaard veronderstelt Xprint een printerresolutie van 600dpi. Dit zou voor "
+"het merendeel van de hedendaagse printers goed moeten zijn."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Op bepaalde 1200dpi-printers zou het beeld echter samengedrukt kunnen lijken "
+"in de hoek van de pagina, terwijl het op 300dpi-printers te groot zou kunnen "
+"worden opgeblazen. Als u dergelijke afdrukproblemen ervaart, kunt u de "
+"standaard printerresolutie naar een meer passende waarde veranderen. Zie /"
+"usr/share/doc/xprint-common/README.printing-problems.gz voor meer "
+"gedetailleerde informatie."
--- xorg-server-1.4.2.orig/debian/po/de.po
+++ xorg-server-1.4.2/debian/po/de.po
@@ -0,0 +1,58 @@
+# translation of xorg-server_2:1.3.0.0.dfsg-13_de.po to German
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Erik Schanze <eriks@debian.org>, 2004-2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server_2:1.3.0.0.dfsg-13_de\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-10-01 21:52+0200\n"
+"Last-Translator: Erik Schanze <eriks@debian.org>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms:  nplurals=2; plural=(n != 1);\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Standard-Druckerauflösung:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Standardmäßig verwendet Xprint eine Druckerauflösung von 600 dpi. Das "
+"funktioniert gut mit den meisten Druckern."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Trotzdem erscheint der Ausdruck bei bestimmten 1200-dpi-Druckern in die Ecke "
+"der Seite gequetscht oder er wird auf 300-dpi-Druckern zu groß dargestellt. "
+"Falls bei Ihnen diese Druckprobleme auftreten, sollten Sie die Standard-"
+"Druckerauflösung auf einen besser passenden Wert setzen. Einzelheiten finden "
+"Sie in der Datei /usr/share/doc/xprint-common/README.printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/fi.po
+++ xorg-server-1.4.2/debian/po/fi.po
@@ -0,0 +1,46 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: debconf: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-09-22 22:59+0200\n"
+"Last-Translator: Esko Arajärvi <edu@iki.fi>\n"
+"Language-Team: Finnish <debian-l10n-finnish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Finnish\n"
+"X-Poedit-Country: FINLAND\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Tulostimen oletusresoluutio:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint olettaa tulostimen resoluution olevan 600 dpi. Suurimmalle osalle "
+"tulostimista tämä oletus sopii hyvin."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Joillain 1200 dpi:n tulostimilla kuva saattaa tulostua hyvin pienenä paperin "
+"kulmaan ja joillain 300 dpi:n tulostimilla tulostua liian suurena. "
+"Tällaisten ongelmien ilmetessä saatat haluta asettaa oletusresoluutioksi "
+"jonkin sopivamman arvon. Lisätietoja löytyy dokumentista /usr/share/doc/"
+"xprint-common/README.printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/da.po
+++ xorg-server-1.4.2/debian/po/da.po
@@ -0,0 +1,60 @@
+# Danish translation of the Debconf po-template for xprint-xprintorg.
+# Morten Bo Johansen <mojo@mbjnet.dk>, 2004, 2005.
+msgid ""
+msgstr ""
+"Project-Id-Version: xprint-xprintorg_0.1.0.alpha1-8_da.po\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2005-03-17 01:15+0100\n"
+"Last-Translator: Morten Bo Johansen <mojo@mbjnet.dk>\n"
+"Language-Team: Danish <dansk@klid.dk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid "Default printer resolution"
+msgid "Default printer resolution:"
+msgstr "Printerens standardopl�sning"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid ""
+#| "By default Xprint assumes a printer resolution of 600dpi. This should be "
+#| "fine for the majority of printers today."
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint bruger en opl�sning p� 600dpi som standard. Dette skulle v�re "
+"passende for de fleste nyere printere."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid ""
+#| "On certain 1200dpi printers, however, the image might appear squashed in "
+#| "the corner of the page, or it might be blown up too large on 300dpi "
+#| "printers. If you are experiencing these kinds of printing problems, you "
+#| "may want to set the default printer resolution to a more appropriate "
+#| "value. See /usr/share/doc/xprint-common/README.printing-problems.gz for "
+#| "more details."
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"P� visse printere med en opl�sning p� 1200dpi kan billedet forekomme "
+"sammenpresset i hj�rnerne, eller det kan virke overforst�rret p� printere "
+"med en opl�sning p� 300dpi. Hvis du oplever s�danne udskrivningsproblemer, "
+"vil det v�re en god ide at s�tte printerens opl�sning til en mere passende "
+"v�rdi. Se /usr/share/doc/xprint-common/README.printing-problems.gz for flere "
+"detaljer."
--- xorg-server-1.4.2.orig/debian/po/bg.po
+++ xorg-server-1.4.2/debian/po/bg.po
@@ -0,0 +1,50 @@
+# translation of bg.po to Bulgarian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Damyan Ivanov <dam@modsoftsys.com>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-19 22:08+0300\n"
+"Last-Translator: Damyan Ivanov <dam@modsoftsys.com>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Подразбирана разделителна способност на принтера:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint използва по подразбиране разделителна способност от 600 dpi. Тази "
+"стойност би трябвало да е подгодяща за повечето принтери."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"При някои принтери с разделителна способност от 1200 dpi изображението може "
+"да е свито в ъгъла на страницата, а при други, използващи 300 dpi - да е "
+"твърде разтегнато. Ако имате подобни проблеми при печатането, може да се "
+"наложи да промените подразбираната разделителна способност на принтера с по-"
+"подходяща стойност. Вижте /usr/share/doc/xprint-commin/README.printing-"
+"problems.gz за повече информация."
--- xorg-server-1.4.2.orig/debian/po/vi.po
+++ xorg-server-1.4.2/debian/po/vi.po
@@ -0,0 +1,49 @@
+# Vietnamese translation for XOrg Server.
+# Copyright © 2007 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2005-2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server 2:1.3.0.0.dfsg-13\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-09-19 21:50+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: LocFactoryEditor 1.7b1\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Độ phân giải máy in mặc định:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Mặc định là trình Xprint giả sử độ phân giải của máy in là 600 chấm/insơ. "
+"Đây nên hữu ích cho phần lớn máy in."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Tuy nhiên, trên một số máy in 1200 chấm/insơ nào đó, ảnh có thể hình như bị "
+"nén vào góc trang, hoặc nó có thể bị phóng to quá nhiều trên máy in 300 chấm/"
+"insơ. Gặp khó khăn in như vậy thì bạn có thể muốn đặt độ phân giải máy in "
+"mặc định thành giá trị thích hợp hơn. Xem tập tin Đọc Đi « /usr/share/doc/"
+"xprint-common/README.printing-problems.gz » để tìm chi tiết."
--- xorg-server-1.4.2.orig/debian/po/th.po
+++ xorg-server-1.4.2/debian/po/th.po
@@ -0,0 +1,47 @@
+# Thai translation for xorg-server
+# Copyright (C) 2007 Software in the Public Interest, Inc.
+# This file is distributed under the same license as the xorg-server package.
+# Theppitak Karoonboonyanan <thep@linux.thai.net>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-18 13:54+0700\n"
+"Last-Translator: Theppitak Karoonboonyanan <thep@linux.thai.net>\n"
+"Language-Team: Thai <thai-l10n@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "ความละเอียดปริยายของเครื่องพิมพ์:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"โดยปกติ Xprint จะใช้ความละเอียด 600 dpi สำหรับเครื่องพิมพ์ ซึ่งน่าจะใช้ได้กับเครื่องพิมพ์ส่วนใหญ่"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"แต่สำหรับเครื่องพิมพ์ 1200 dpi บางรุ่นแล้ว ค่านี้อาจทำให้ภาพที่พิมพ์ออกมาเลอะที่มุมหน้ากระดาษ "
+"หรือถ้าเป็นเครื่องพิมพ์ 300 dpi ก็จะได้ภาพที่ใหญ่เกินไป ถ้าคุณพบปัญหาการพิมพ์ดังกล่าว "
+"คุณก็อาจกำหนดความละเอียดปริยายของเครื่องพิมพ์ให้เป็นค่าที่เหมาะสมได้ "
+"กรุณาอ่านรายละเอียดเพิ่มเติมได้จาก /usr/share/doc/xprint-common/README.printing-"
+"problems.gz"
--- xorg-server-1.4.2.orig/debian/po/gl.po
+++ xorg-server-1.4.2/debian/po/gl.po
@@ -0,0 +1,47 @@
+# Galician translation of xorg-server's debconf templates
+# This file is distributed under the same license as the xorg-server package.
+# Jacobo Tarrio <jtarrio@debian.org>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-30 18:53+0100\n"
+"Last-Translator: Jacobo Tarrio <jtarrio@debian.org>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Resolución de impresión por defecto:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Por defecto, Xprint supón unha resolución de impresión de 600 ppp. Este "
+"valor é axeitado para a maioría das impresoras."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Nembargantes, nalgunhas impresoras de 1200 ppp a imaxe pode aparecer "
+"aplastada nunha esquina da páxina, ou pode aparecer grande de máis en "
+"impresoras de 300 ppp. Se ten este tipo de problemas pode cambiar a "
+"resolución de impresión a un valor máis axeitado. Consulte /usr/share/doc/"
+"xprint-common/README.printing-problems.gz para ter máis detalles."
--- xorg-server-1.4.2.orig/debian/po/ta.po
+++ xorg-server-1.4.2/debian/po/ta.po
@@ -0,0 +1,49 @@
+# translation of xorg-server.po to TAMIL
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Dr.T.Vasudevan <agnihot3@gmail.com>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-18 13:59+0530\n"
+"Last-Translator: Dr.T.Vasudevan <agnihot3@gmail.com>\n"
+"Language-Team: TAMIL <ubuntu-l10n-tam@lists.ubuntu.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "முன்னிருப்பு அச்சு இயந்திர தௌதவுத்திறன்:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"முன்னிருப்பாக எக்ஸ் ப்ரின்ட் அச்சு இயந்திர தௌதவுத்திறன் ஆக 600 டிபிஐ ஐ புணைந்து கொள்ளும். "
+"பெரும்பாலான முன்னிருப்பு அச்சு இயந்திரங்களுக்கு இது சரியாகவே இருக்கும்."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"சில 1200 dpi அச்சு இயந்திரங்களில் பிம்பம் பக்கத்தின் மூலைகளில் நெருக்கப்பட்டு காணும். "
+"அல்லது 300 dpi இயந்திரங்களில் மிகப்பெரிதாக தெரியும். இப்படிப்பட்ட பிரச்சினைகள் வந்தால் "
+"நீங்கள் சரியான முன்னிருப்பு அச்சு இயந்திர தௌதவுத்திறன் ஐ அமைக்க வேண்டும். மேலும் "
+"தகவல்களுக்கு /usr/share/doc/xprint-common/README.printing-problems.gz ஐ "
+"பார்க்கவும்."
--- xorg-server-1.4.2.orig/debian/po/sv.po
+++ xorg-server-1.4.2/debian/po/sv.po
@@ -0,0 +1,55 @@
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+# Developers do not need to manually edit POT or PO files.
+# , fuzzy
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-18 11:08+0100\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <debian-l10n-swedish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Standarduppl�sning f�r skrivare:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Som standard antar Xprint att skrivaruppl�sningen �r 600 dpi. Detta borde "
+"passa fint f�r de flesta av dagens skrivare."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"P� vissa skrivare med 1200 dpi kan dock bilden verka hoptryckt i ett h�rn av "
+"sidan eller att den blir mycket f�rstorad p� skrivare med 300 dpi. Om du "
+"upplever s�dana problem kan du st�lla in standardskrivarens uppl�sning till "
+"ett mer l�mpligt v�rde. Se /usr/share/doc/xprint-common/README.printing-"
+"problems.gz f�r mer information."
--- xorg-server-1.4.2.orig/debian/po/ru.po
+++ xorg-server-1.4.2/debian/po/ru.po
@@ -0,0 +1,60 @@
+# translation of ru.po to Russian
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Yuri Kozlov <kozlov.y@gmail.com>, 2006, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: 2:1.3.0.0.dfsg-13\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-09-24 20:33+0400\n"
+"Last-Translator: Yuri Kozlov <kozlov.y@gmail.com>\n"
+"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Разрешение печати для принтера по умолчанию:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"По умолчанию, Xprint предполагает, что принтер имеет разрешение печати 600 "
+"dpi. Это значение приемлемо для большинства принтеров."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Однако, на принтерах с разрешением печати 1200 dpi изображение может "
+"оказаться сжатым в углу страницы или может стать слишком большим на "
+"принтерах с разрешением печати 300 dpi. Если у вас возникли подобные "
+"проблемы с печатью, установите более подходящее значение для разрешения "
+"печати принтера по умолчанию. Дополнительная информация представлена в "
+"файле /usr/share/doc/xprint-common/README.printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/sk.po
+++ xorg-server-1.4.2/debian/po/sk.po
@@ -0,0 +1,43 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server 2:1.3.0.0.dfsg-12\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-10-27 10:29+0100\n"
+"Last-Translator: Ivan Masár <helix84@centrum.sk>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Štandardné rozlíšenie tlačiarne:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint štandardne predpokladá rozlíšenie tlačiarne 600 dpi. To by malo byť v "
+"poriadku pre väčšinu dnešných tlačiarní."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Na istých tlačiarňach s 1200 dpi však môže obraz vyzerať stlačený do rohu "
+"stránky alebo na tlačiarňach s 300 dpi môže byť natiahnutý. Ak máte takýto "
+"problém, možno budete chcieť zmeniť štandardné rozlíšenie tlačiarne na "
+"vhodnejšiu hodnotu. Viac informácií v /usr/share/doc/xprint-common/README."
+"printing-problems.gz."
--- xorg-server-1.4.2.orig/debian/po/templates.pot
+++ xorg-server-1.4.2/debian/po/templates.pot
@@ -0,0 +1,42 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
--- xorg-server-1.4.2.orig/debian/po/it.po
+++ xorg-server-1.4.2/debian/po/it.po
@@ -0,0 +1,49 @@
+# Italian (it) translation of debconf templates for xorg-server
+# Copyright (C) 2007 Free Software Foundation, Inc.
+# This file is distributed under the same license as the xorg-server package.
+# Luca Monducci <luca.mo@tiscali.it>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server debconf templates\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-21 21:26+0200\n"
+"Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n"
+"Language-Team: Italian <debian-l10n-italian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Risoluzione predefinita della stampante:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Xprint assume che la risoluzione della stampante sia di 600 dpi. Questo "
+"valore dovrebbe essere adatto alla maggior parte delle stampanti."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Purtroppo su alcune stampanti a 1200 dpi l'immagine potrebbe apparire come "
+"schiacciata in un angolo della pagina oppure potrebbe essere troppo "
+"ingrandita su stampanti a 300 dpi. Nel caso si verificassero questi "
+"problemi, si può impostare la risoluzione di stampa predefinita a un valore "
+"più adatto. Si veda /usr/share/doc/xprint-common/README.printing-problems.gz "
+"per maggiori dettagli."
--- xorg-server-1.4.2.orig/debian/po/ro.po
+++ xorg-server-1.4.2/debian/po/ro.po
@@ -0,0 +1,48 @@
+# translation of xorg-server to Romanian
+# Copyright (C) 2007
+# This file is distributed under the same license as the xorg-server package.
+#
+# Igor Stirbu <igor.stirbu@gmail.com>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: ro\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-20 19:00+0300\n"
+"Last-Translator: Igor Stirbu <igor.stirbu@gmail.com>\n"
+"Language-Team: Romanian <debian-l10n-romanian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Rezoluția implicită a imprimantei:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr "Rezoluția implicită folosită de Xprint este de 600 dpi (dots per inch – puncte per țol). Această valoare ar trebui să fie potrivită pentru majoritatea imprimantelor."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr "Totuși, pe anumite imprimante cu rezoluția de 1200 dpi, ar putea să tipărească "
+"imaginea înghesuită în colțul paginii, sau, în cazul celor cu rezoluția de 300 dpi, ar putea să fie "
+"întinsă peste dimensiunile normale. Dacă întâmpinați asemenea probleme, "
+"puteți încerca să schimbați valoarea implicită a rezoluției imprimantei. A se vedea "
+"/usr/share/doc/xprint-common/README.printing-problems.gz "
+"pentru mai multe detalii."
+
--- xorg-server-1.4.2.orig/debian/po/he.po
+++ xorg-server-1.4.2/debian/po/he.po
@@ -0,0 +1,48 @@
+# translation of templates.po to Hebrew
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Lior Kaplan <kaplan@debian.org>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: templates\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-19 18:35+0200\n"
+"Last-Translator: Lior Kaplan <kaplan@debian.org>\n"
+"Language-Team: Hebrew <debian-hebrew-common@lists.alioth.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "רזולוציה ברית מחדל של המדפסת:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"כברירת מחדל, Xprint מניחה על רזולוציית המדפסת היא 600 dpi. ערך זה צריך "
+"להתאים היטב לרוב המדפסות."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"עבור מספר מדפסות 1200 dpi, התמונה עלולה להופיע מעוכה בפינת הדף, או שהיא "
+"תופיע בהגדלה רבה מידי במדפסות 300 dpi. אם ישנן כאלה בעיות, כדאי לקבוע את ערך "
+"רזולוציית ברירת המחדל לערך מתאים יותר. פרטים נוספים ישנם בקובץ /usr/share/"
+"doc/xprint-common/README.printing-problems.gz"
--- xorg-server-1.4.2.orig/debian/po/fr.po
+++ xorg-server-1.4.2/debian/po/fr.po
@@ -0,0 +1,61 @@
+# translation of fr.po to French
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Christian Perrier <bubulle@debian.org>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 07:46+0200\n"
+"PO-Revision-Date: 2007-09-18 07:47+0200\n"
+"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "Résolution par défaut de l'imprimante :"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Par défaut, XPrint utilise une résolution d'impression de 600 ppp (points "
+"par pouce ou « dpi »). Cette valeur convient pour la majorité des "
+"imprimantes actuelles."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Cependant, un document préparé en 600 ppp apparaîtra trop gros sur une "
+"imprimante dont la résolution est de 300 ppp ou trop petit (un quart de page "
+"occupée) sur une imprimante à 1200 ppp. Si vous rencontrez ce type de "
+"problèmes, vous devriez choisir une valeur plus adaptée comme résolution "
+"d'impression. Veuillez consulter le fichier /usr/share/doc/xprint-common/"
+"README.printing-problems.gz pour plus d'informations."
--- xorg-server-1.4.2.orig/debian/po/es.po
+++ xorg-server-1.4.2/debian/po/es.po
@@ -0,0 +1,61 @@
+# 
+# 
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: xprint-es\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2006-12-13 23:22+0100\n"
+"Last-Translator: Fernando Cerezal López <kryptos21@gmail.com>\n"
+"Language-Team: Spanish <debian-l10n-spanish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid "Default printer resolution"
+msgid "Default printer resolution:"
+msgstr "Resolución predeterminada de la impresora"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid ""
+#| "By default Xprint assumes a printer resolution of 600dpi. This should be "
+#| "fine for the majority of printers today."
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"Por omisión, Xprint asume una resolución de impresión de 600 ppp. Esto "
+"debería estar bien para la mayoría de las impresoras actuales."
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+#, fuzzy
+#| msgid ""
+#| "On certain 1200dpi printers, however, the image might appear squashed in "
+#| "the corner of the page, or it might be blown up too large on 300dpi "
+#| "printers. If you are experiencing these kinds of printing problems, you "
+#| "may want to set the default printer resolution to a more appropriate "
+#| "value. See /usr/share/doc/xprint-common/README.printing-problems.gz for "
+#| "more details."
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"Sin embargo, en ciertas impresoras de 1200 ppp, la imagen puede parecer "
+"aplastada en la esquina de la página, o puede parecer demasiado hinchada en "
+"impresoras de 300 ppp. Si experimenta este tipo de problemas de impresión, "
+"puede que quiera establecer la resolución predeterminada de la impresora a "
+"un valor más apropiado. Véase «/usr/share/doc/xprint-common/README.printing-"
+"problems.gz» para obtener más detalles."
--- xorg-server-1.4.2.orig/debian/po/pt_BR.po
+++ xorg-server-1.4.2/debian/po/pt_BR.po
@@ -0,0 +1,85 @@
+# portmap Brazilian Portuguese translation 
+# Copyright (C) 2007 THE portmap'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the portmap package.
+# Felipe Augusto van de Wiel (faw) <faw@debian.org>, 2007.
+# Eder L. Marques (frolic) <frolic@debian-ce.org>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: portmap 6.0-2\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2007-10-03 17:17-0300\n"
+"Last-Translator: Eder L. Marques (frolic) <frolic@debian-ce.org>\n"
+"Language-Team: l10n Portuguese <debian-l10n-portuguese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"pt_BR utf-8\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+
+#~ msgid "Should portmap be bound to the loopback address?"
+#~ msgstr "O portmap deveria escutar somente no endereço de loopback?"
+
+#~| msgid ""
+#~| "Portmap by default listens to all IP addresses. However, if you are not "
+#~| "providing network RPC services to remote clients (you are if you are "
+#~| "setting up a NFS or NIS server) you can safely bind it to the loopback  "
+#~| "IP address (127.0.0.1)"
+#~ msgid ""
+#~ "By default, portmap listens to all IP addresses. However, if this machine "
+#~ "does not provide network RPC services (such as NIS or NFS) to remote "
+#~ "clients, you can safely bind it to the loopback IP address (127.0.0.1)."
+#~ msgstr ""
+#~ "Por padrão, o portmap escuta em todos os endereços IP. Entretanto, se "
+#~ "esta máquina não provê serviços de rede RPC (como NIS ou NFS) para "
+#~ "clientes remotos, você pode, com segurança, restringí-lo somente ao "
+#~ "endereço IP de loopback (127.0.0.1)."
+
+#~| msgid ""
+#~| "This will allow RPC local services (like FAM) to work properly, while "
+#~| "preventing remote systems from accessing your RPC services."
+#~ msgid ""
+#~ "This will allow RPC local services (like FAM) to work properly, while "
+#~ "preventing remote systems from accessing the RPC services."
+#~ msgstr ""
+#~ "Isto permitirá que serviços RPC locais (como o FAM) funcionem "
+#~ "corretamente, enquanto previne que sistemas remotos acessem os serviços "
+#~ "RPC."
+
+#~| msgid ""
+#~| "You can also change this configuration by editing the OPTIONS line in "
+#~| "the /etc/default/portmap file. If you just don't specify the -i option "
+#~| "it will bind to all interfaces."
+#~ msgid ""
+#~ "This configuration can be changed by editing the OPTIONS line in the /etc/"
+#~ "default/portmap file and adapting the use of the -i option to your needs."
+#~ msgstr ""
+#~ "Esta configuração pode ser alterada editando a linha OPTIONS no arquivo /"
+#~ "etc/default/portmap e adaptando o uso da opção -i para as suas "
+#~ "necessidades."
--- xorg-server-1.4.2.orig/debian/po/POTFILES.in
+++ xorg-server-1.4.2/debian/po/POTFILES.in
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] xprint-common.templates
--- xorg-server-1.4.2.orig/debian/po/ja.po
+++ xorg-server-1.4.2/debian/po/ja.po
@@ -0,0 +1,58 @@
+# 
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+# 
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+# 
+#    Developers do not need to manually edit POT or PO files.
+# 
+# 
+msgid ""
+msgstr ""
+"Project-Id-Version: xorg-server 2:1.4.1~git20080118-1\n"
+"Report-Msgid-Bugs-To: debian-x@lists.debian.org\n"
+"POT-Creation-Date: 2007-09-18 20:35+0200\n"
+"PO-Revision-Date: 2008-01-27 19:52+0900\n"
+"Last-Translator: Hideki Yamane (Debian-JP) <henrich@debian.or.jp>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid "Default printer resolution:"
+msgstr "デフォルトのプリンタ解像度:"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"By default, Xprint assumes a printer resolution of 600 dpi. This should be "
+"well suited for the majority of printers."
+msgstr ""
+"デフォルトでは、Xprint はプリンタの解像度を 600dpi としています。ほとんどのプリン"
+"タでは、ほとんどこの値で良いでしょう。"
+
+#. Type: string
+#. Description
+#: ../xprint-common.templates:2001
+msgid ""
+"On certain 1200 dpi printers, however, the image might appear squashed in "
+"the corner of the page, or it might be blown up too large on 300 dpi "
+"printers. If you are experiencing such printing problems, you may want to "
+"set the default printer resolution to a more appropriate value. See /usr/"
+"share/doc/xprint-common/README.printing-problems.gz for more details."
+msgstr ""
+"しかし、1200dpi 固定のプリンタでは印刷された画像はページの隅に詰めて印刷され"
+"てしまいますし、300dpi のプリンタでは大きくなりすぎてしまいます。この様な印刷"
+"時の問題に遭遇した場合、プリンタの解像度をより適切な値に変更したくなるでしょう。"
+"詳細については、/usr/share/doc/xprint-common/README.printing-problems.gz "
+"を参照してください。"
+
--- xorg-server-1.4.2.orig/debian/xsfbs/xsfbs.mk
+++ xorg-server-1.4.2/debian/xsfbs/xsfbs.mk
@@ -0,0 +1,293 @@
+#!/usr/bin/make -f
+
+# Debian X Strike Force Build System (XSFBS): Make portion
+
+# Copyright 1996 Stephen Early
+# Copyright 1997 Mark Eichin
+# Copyright 1998-2005, 2007 Branden Robinson
+# Copyright 2005 David Nusinow
+#
+# Licensed under the GNU General Public License, version 2.  See the file
+# /usr/share/common-licenses/GPL or <http://www.gnu.org/copyleft/gpl.txt>.
+
+# Originally by Stephen Early <sde1000@debian.org>
+# Modified by Mark W. Eichin <eichin@kitten.gen.ma.us>
+# Modified by Adam Heath <doogie@debian.org>
+# Modified by Branden Robinson <branden@debian.org>
+# Modified by Fabio Massimo Di Nitto <fabbione@fabbione.net>
+# Modified by David Nusinow <dnusinow@debian.org>
+# Acknowledgements to Manoj Srivastava.
+
+# Pass $(DH_OPTIONS) into the environment for debhelper's benefit.
+export DH_OPTIONS
+
+# force quilt to not use ~/.quiltrc and to use debian/patches
+QUILT = QUILT_PATCHES=debian/patches quilt --quiltrc /dev/null
+
+# Set up parameters for the upstream build environment.
+
+# Determine (source) package name from Debian changelog.
+SOURCE_NAME:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Source:' | awk '{print $$2}')
+
+# Determine package version from Debian changelog.
+SOURCE_VERSION:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Version:' | awk '{print $$2}')
+
+# Determine upstream version number.
+UPSTREAM_VERSION:=$(shell echo $(SOURCE_VERSION) | sed 's/-.*//')
+
+# Determine the source version without the epoch for make-orig-tar-gz
+NO_EPOCH_VER:=$(shell echo $(UPSTREAM_VERSION) | sed 's/^.://')
+
+# Figure out who's building this package.
+BUILDER:=$(shell echo $${DEBEMAIL:-$${EMAIL:-$$(echo $$LOGNAME@$$(cat /etc/mailname 2>/dev/null))}})
+
+# Find out if this is an official build; an official build has nothing but
+# digits, dots, and/or the codename of a release in the Debian part of the
+# version number.  Anything else indicates an unofficial build.
+OFFICIAL_BUILD:=$(shell VERSION=$(SOURCE_VERSION); if ! expr "$$(echo $${VERSION\#\#*-} | sed 's/\(woody\|sarge\|etch\|lenny\)//g')" : ".*[^0-9.].*" >/dev/null 2>&1; then echo yes; fi)
+
+# Set up parameters for the Debian build environment.
+
+# Determine our architecture.
+BUILD_ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH)
+# Work around some old-time dpkg braindamage.
+BUILD_ARCH:=$(subst i486,i386,$(BUILD_ARCH))
+# The DEB_HOST_ARCH variable may be set per the Debian cross-compilation policy.
+ifdef DEB_HOST_ARCH
+ ARCH:=$(DEB_HOST_ARCH)
+else
+ # dpkg-cross sets the ARCH environment variable; if set, use it.
+ ifdef ARCH
+  ARCH:=$(ARCH)
+ else
+  ARCH:=$(BUILD_ARCH)
+ endif
+endif
+
+# $(STAMP_DIR) houses stamp files for complex targets.
+STAMP_DIR:=stampdir
+
+# $(DEBTREEDIR) is where all install rules are told (via $(DESTDIR)) to place
+# their files.
+DEBTREEDIR:=$(CURDIR)/debian/tmp
+
+# All "important" targets have four lines:
+#   1) A target name that is invoked by a package-building tool or the user.
+#      This consists of a dependency on a "$(STAMP_DIR)/"-prefixed counterpart.
+#   2) A line delcaring 1) as a phony target (".PHONY:").
+#   3) A "$(STAMP_DIR)/"-prefixed target which does the actual work, and may
+#   depend on other targets.
+#   4) A line declaring 3) as a member of the $(stampdir_targets) variable; the
+#   "$(STAMP_DIR)/" prefix is omitted.
+#
+# This indirection is needed so that the "stamp" files that signify when a rule
+# is done can be located in a separate "stampdir".  Recall that make has no way
+# to know when a goal has been met for a phony target (like "build" or
+# "install").
+#
+# At the end of each "$(STAMP_DIR)/" target, be sure to run the command ">$@"
+# so that the target will not be run again.  Removing the file will make Make
+# run the target over.
+
+# All phony targets should be declared as dependencies of .PHONY, even if they
+# do not have "($STAMP_DIR)/"-prefixed counterparts.
+
+# Define a harmless default rule to keep things from going nuts by accident.
+.PHONY: default
+default:
+
+# Set up the $(STAMP_DIR) directory.
+.PHONY: stampdir
+stampdir_targets+=stampdir
+stampdir: $(STAMP_DIR)/stampdir
+$(STAMP_DIR)/stampdir:
+	mkdir $(STAMP_DIR)
+	>$@
+
+# Set up the package build directory as quilt expects to find it.
+.PHONY: prepare
+stampdir_targets+=prepare
+prepare: $(STAMP_DIR)/prepare
+$(STAMP_DIR)/prepare: $(STAMP_DIR)/log $(STAMP_DIR)/genscripts
+	>$@
+
+.PHONY: log
+stampdir_targets+=log
+log: $(STAMP_DIR)/log
+$(STAMP_DIR)/log: $(STAMP_DIR)/stampdir
+	mkdir -p $(STAMP_DIR)/log
+
+# Apply all patches to the upstream source.
+.PHONY: patch
+stampdir_targets+=patch
+patch: $(STAMP_DIR)/patch
+$(STAMP_DIR)/patch: $(STAMP_DIR)/prepare
+	if ! [ `which quilt` ]; then \
+		echo "Couldn't find quilt. Please install it or add it to the build-depends for this package."; \
+		exit 1; \
+	fi; \
+	if $(QUILT) next >/dev/null 2>&1; then \
+	  echo -n "Applying patches..."; \
+	  if $(QUILT) push -a -v >$(STAMP_DIR)/log/patch 2>&1; then \
+	    cat $(STAMP_DIR)/log/patch; \
+	    echo "successful."; \
+	  else \
+	    cat $(STAMP_DIR)/log/patch; \
+	    echo "failed! (check $(STAMP_DIR)/log/patch for details)"; \
+	    exit 1; \
+	  fi; \
+	else \
+	  echo "No patches to apply"; \
+	fi; \
+	>$@
+
+# Revert all patches to the upstream source.
+.PHONY: unpatch
+unpatch: $(STAMP_DIR)/log
+	rm -f $(STAMP_DIR)/patch
+	@echo -n "Unapplying patches..."; \
+	if $(QUILT) applied >/dev/null 2>/dev/null; then \
+	  if $(QUILT) pop -a -v >$(STAMP_DIR)/log/unpatch 2>&1; then \
+	    cat $(STAMP_DIR)/log/unpatch; \
+	    echo "successful."; \
+	  else \
+	    cat $(STAMP_DIR)/log/unpatch; \
+	    echo "failed! (check $(STAMP_DIR)/log/unpatch for details)"; \
+	    exit 1; \
+	  fi; \
+	else \
+	  echo "nothing to do."; \
+	fi
+
+# Clean the generated maintainer scripts.
+.PHONY: cleanscripts
+cleanscripts:
+	rm -f $(STAMP_DIR)/genscripts
+	rm -f debian/*.config \
+	      debian/*.postinst \
+	      debian/*.postrm \
+	      debian/*.preinst \
+	      debian/*.prerm
+
+# Clean the package build tree.
+.PHONY: xsfclean
+xsfclean: cleanscripts unpatch
+	dh_testdir
+	rm -rf .pc
+	rm -rf $(STAMP_DIR) $(SOURCE_DIR)
+	rm -rf imports
+	dh_clean debian/shlibs.local \
+	         debian/po/pothead
+
+# Generate the debconf templates POT file header.
+debian/po/pothead: debian/po/pothead.in
+	sed -e 's/SOURCE_VERSION/$(SOURCE_VERSION)/' \
+	  -e 's/DATE/$(shell date "+%F %X%z"/)' <$< >$@
+
+# Update POT and PO files.
+.PHONY: updatepo
+updatepo: debian/po/pothead
+	debian/scripts/debconf-updatepo --pot-header=pothead --verbose
+
+# Remove files from the upstream source tree that we don't need, or which have
+# licensing problems.  It must be run before creating the .orig.tar.gz.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: prune-upstream-tree
+prune-upstream-tree:
+	# Ensure we're in the correct directory.
+	dh_testdir
+	grep -rvh '^#' debian/prune/ | xargs --no-run-if-empty rm -rf
+
+# Verify that there are no offsets or fuzz in the patches we apply.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: patch-audit
+patch-audit: prepare unpatch
+	@echo -n "Auditing patches..."; \
+	>$(STAMP_DIR)/log/patch; \
+	FUZZY=; \
+	while [ -n "$$($(QUILT) next)" ]; do \
+	  RESULT=$$($(QUILT) push -v | tee -a $(STAMP_DIR)/log/patch | grep ^Hunk | sed 's/^Hunk.*\(succeeded\|FAILED\).*/\1/');\
+	  case "$$RESULT" in \
+	    succeeded) \
+	      echo "fuzzy patch: $$($(QUILT) top)" \
+	        | tee -a $(STAMP_DIR)/log/$$($(QUILT) top); \
+	      FUZZY=yes; \
+	      ;; \
+	    FAILED) \
+	      echo "broken patch: $$($(QUILT) next)" \
+	        | tee -a $(STAMP_DIR)/log/$$($(QUILT) next); \
+	      exit 1; \
+	      ;; \
+	  esac; \
+	done; \
+	if [ -n "$$FUZZY" ]; then \
+	  echo "there were fuzzy patches; please fix."; \
+	  exit 1; \
+	else \
+	  echo "done."; \
+	fi
+
+# Generate the maintainer scripts.
+.PHONY: genscripts
+stampdir_targets+=genscripts
+genscripts: $(STAMP_DIR)/genscripts
+$(STAMP_DIR)/genscripts: $(STAMP_DIR)/stampdir
+	for FILE in debian/*.config.in \
+	            debian/*.postinst.in \
+	            debian/*.postrm.in \
+	            debian/*.preinst.in \
+	            debian/*.prerm.in; do \
+	  if [ -e "$$FILE" ]; then \
+	    MAINTSCRIPT=$$(echo $$FILE | sed 's/.in$$//'); \
+	    sed -n '1,/^#INCLUDE_SHELL_LIB#$$/p' <$$FILE \
+	      | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >$$MAINTSCRIPT.tmp; \
+	    cat debian/xsfbs/xsfbs.sh >>$$MAINTSCRIPT.tmp; \
+	    sed -n '/^#INCLUDE_SHELL_LIB#$$/,$$p' <$$FILE \
+	      | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >>$$MAINTSCRIPT.tmp; \
+	    sed -e 's/@SOURCE_VERSION@/$(SOURCE_VERSION)/' \
+	        -e 's/@OFFICIAL_BUILD@/$(OFFICIAL_BUILD)/' \
+	        -e 's/@DEFAULT_DCRESOLUTIONS@/$(DEFAULT_DCRESOLUTIONS)/' \
+	      <$$MAINTSCRIPT.tmp >$$MAINTSCRIPT; \
+	    rm $$MAINTSCRIPT.tmp; \
+	  fi; \
+	done
+	# Validate syntax of generated shell scripts.
+	#sh debian/scripts/validate-posix-sh debian/*.config \
+	#                                    debian/*.postinst \
+	#                                    debian/*.postrm \
+	#                                    debian/*.preinst \
+	#                                    debian/*.prerm
+	>$@
+
+# Generate the shlibs.local file.
+debian/shlibs.local:
+	cat debian/*.shlibs >$@
+
+SERVERMINVERS = $(shell cat /usr/share/xserver-xorg/serverminver 2>/dev/null)
+VIDEOABI = $(shell cat /usr/share/xserver-xorg/videoabiver 2>/dev/null)
+INPUTABI = $(shell cat /usr/share/xserver-xorg/inputabiver 2>/dev/null)
+SERVER_DEPENDS = xserver-xorg-core (>= $(SERVERMINVERS))
+VIDDRIVER_PROVIDES = xserver-xorg-video-$(VIDEOABI)
+INPDRIVER_PROVIDES = xserver-xorg-input-$(INPUTABI)
+ifeq ($(PACKAGE),)
+PACKAGE=$(shell awk '/^Package:/ { print $$2; exit }' < debian/control)
+endif
+
+.PHONY: serverabi
+serverabi: install
+ifeq ($(SERVERMINVERS),)
+	@echo error: xserver-xorg-dev needs to be installed
+	@exit 1
+else
+	echo "xserver:Depends=$(SERVER_DEPENDS)" >> debian/$(PACKAGE).substvars
+	echo "xviddriver:Provides=$(VIDDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+	echo "xinpdriver:Provides=$(INPDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+endif
+
+# vim:set noet ai sts=8 sw=8 tw=0:
--- xorg-server-1.4.2.orig/debian/xsfbs/xsfbs.sh
+++ xorg-server-1.4.2/debian/xsfbs/xsfbs.sh
@@ -0,0 +1,931 @@
+# $Id$
+
+# This is the X Strike Force shell library for X Window System package
+# maintainer scripts.  It serves to define shell functions commonly used by
+# such packages, and performs some error checking necessary for proper operation
+# of those functions.  By itself, it does not "do" much; the maintainer scripts
+# invoke the functions defined here to accomplish package installation and
+# removal tasks.
+
+# If you are reading this within a Debian package maintainer script (e.g.,
+# /var/lib/dpkg)info/PACKAGE.{config,preinst,postinst,prerm,postrm}), you can
+# skip past this library by scanning forward in this file to the string
+# "GOBSTOPPER".
+
+SOURCE_VERSION=@SOURCE_VERSION@
+OFFICIAL_BUILD=@OFFICIAL_BUILD@
+
+# Use special abnormal exit codes so that problems with this library are more
+# easily tracked down.
+SHELL_LIB_INTERNAL_ERROR=86
+SHELL_LIB_THROWN_ERROR=74
+SHELL_LIB_USAGE_ERROR=99
+
+# old -> new variable names
+if [ -z "$DEBUG_XORG_PACKAGE" ] && [ -n "$DEBUG_XFREE86_PACKAGE" ]; then
+  DEBUG_XORG_PACKAGE="$DEBUG_XFREE86_PACKAGE"
+fi
+if [ -z "$DEBUG_XORG_DEBCONF" ] && [ -n "$DEBUG_XFREE86_DEBCONF" ]; then
+  DEBUG_XORG_DEBCONF="$DEBUG_XFREE86_DEBCONF"
+fi
+
+# initial sanity checks
+if [ -z "$THIS_PACKAGE" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_PACKAGE shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of this package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+if [ -z "$THIS_SCRIPT" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_SCRIPT shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of the
+"$THIS_PACKAGE" package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+ARCHITECTURE="$(dpkg --print-installation-architecture)"
+
+if [ "$1" = "reconfigure" ] || [ -n "$DEBCONF_RECONFIGURE" ]; then
+  RECONFIGURE="true"
+else
+  RECONFIGURE=
+fi
+
+if ([ "$1" = "install" ] || [ "$1" = "configure" ]) && [ -z "$2" ]; then
+  FIRSTINST="yes"
+fi
+
+if [ -z "$RECONFIGURE" ] && [ -z "$FIRSTINST" ]; then
+  UPGRADE="yes"
+fi
+
+trap "message;\
+      message \"Received signal.  Aborting $THIS_PACKAGE package $THIS_SCRIPT script.\";\
+      message;\
+      exit 1" HUP INT QUIT TERM
+
+reject_nondigits () {
+  # syntax: reject_nondigits [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters other than decimal digits and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain anything but digits?
+    if ! expr "$1" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+      # can't use die(), because it wraps message() which wraps this function
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_nondigits() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+reject_whitespace () {
+  # syntax: reject_whitespace [ operand ]
+  #
+  # scan operand (typically a shell variable whose value cannot be trusted) for
+  # whitespace characters and barf if any are found
+  if [ -n "$1" ]; then
+    # does the operand contain any whitespace?
+    if expr "$1" : "[[:space:]]" > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_whitespace() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+  fi
+}
+
+reject_unlikely_path_chars () {
+  # syntax: reject_unlikely_path_chars [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters unlikely to be seen in a path and which the shell might
+  # interpret and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain any funny characters?
+    if expr "$1" : '.*[!$&()*;<>?|].*' > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_unlikely_path_chars()" \
+           "encountered possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+# Query the terminal to establish a default number of columns to use for
+# displaying messages to the user.  This is used only as a fallback in the
+# event the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while
+# the script is running, and this cannot, only being calculated once.)
+DEFCOLUMNS=$(stty size 2> /dev/null | awk '{print $2}') || true
+if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+  DEFCOLUMNS=80
+fi
+
+message () {
+  # pretty-print messages of arbitrary length
+  reject_nondigits "$COLUMNS"
+  echo "$*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} >&2
+}
+
+observe () {
+  # syntax: observe message ...
+  #
+  # issue observational message suitable for logging someday when support for
+  # it exists in dpkg
+  if [ -n "$DEBUG_XORG_PACKAGE" ]; then
+    message "$THIS_PACKAGE $THIS_SCRIPT note: $*"
+  fi
+}
+
+warn () {
+  # syntax: warn message ...
+  #
+  # issue warning message suitable for logging someday when support for
+  # it exists in dpkg; also send to standard error
+  message "$THIS_PACKAGE $THIS_SCRIPT warning: $*"
+}
+
+die () {
+  # syntax: die message ...
+  #
+  # exit script with error message
+  message "$THIS_PACKAGE $THIS_SCRIPT error: $*"
+  exit $SHELL_LIB_THROWN_ERROR
+}
+
+internal_error () {
+  # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message
+  message "internal error: $*"
+  if [ -n "$OFFICIAL_BUILD" ]; then
+    message "Please report a bug in the $THIS_SCRIPT script of the" \
+            "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+            "Tracking System.  Include all messages above that mention the" \
+            "$THIS_PACKAGE package.  Visit " \
+            "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+            "instructions, read the file" \
+            "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+            "package, or install the reportbug package and use the command of" \
+            "the same name to file a report."
+  fi
+  exit $SHELL_LIB_INTERNAL_ERROR
+}
+
+usage_error () {
+  message "usage error: $*"
+  message "Please report a bug in the $THIS_SCRIPT script of the" \
+          "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+          "Tracking System.  Include all messages above that mention the" \
+          "$THIS_PACKAGE package.  Visit " \
+          "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+          "instructions, read the file" \
+          "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+          "package, or install the reportbug package and use the command of" \
+          "the same name to file a report."
+  exit $SHELL_LIB_USAGE_ERROR
+}
+
+
+maplink () {
+  # returns what symlink should point to; i.e., what the "sane" answer is
+  # Keep this in sync with the debian/*.links files.
+  # This is only needed for symlinks to directories.
+  #
+  # XXX: Most of these look wrong in the X11R7 world and need to be fixed.
+  # If we've stopped using this function, fixing it might enable us to re-enable
+  # it again and catch more errors.
+  case "$1" in
+    /etc/X11/xkb/compiled) echo /var/lib/xkb ;;
+    /etc/X11/xkb/xkbcomp) echo /usr/X11R6/bin/xkbcomp ;;
+    /usr/X11R6/lib/X11/app-defaults) echo /etc/X11/app-defaults ;;
+    /usr/X11R6/lib/X11/fs) echo /etc/X11/fs ;;
+    /usr/X11R6/lib/X11/lbxproxy) echo /etc/X11/lbxproxy ;;
+    /usr/X11R6/lib/X11/proxymngr) echo /etc/X11/proxymngr ;;
+    /usr/X11R6/lib/X11/rstart) echo /etc/X11/rstart ;;
+    /usr/X11R6/lib/X11/twm) echo /etc/X11/twm ;;
+    /usr/X11R6/lib/X11/xdm) echo /etc/X11/xdm ;;
+    /usr/X11R6/lib/X11/xinit) echo /etc/X11/xinit ;;
+    /usr/X11R6/lib/X11/xkb) echo /etc/X11/xkb ;;
+    /usr/X11R6/lib/X11/xserver) echo /etc/X11/xserver ;;
+    /usr/X11R6/lib/X11/xsm) echo /etc/X11/xsm ;;
+    /usr/bin/X11) echo ../X11R6/bin ;;
+    /usr/bin/rstartd) echo ../X11R6/bin/rstartd ;;
+    /usr/include/X11) echo ../X11R6/include/X11 ;;
+    /usr/lib/X11) echo ../X11R6/lib/X11 ;;
+    *) internal_error "maplink() called with unknown path \"$1\"" ;;
+  esac
+}
+
+analyze_path () {
+  # given a supplied set of pathnames, break each one up by directory and do an
+  # ls -dl on each component, cumulatively; i.e.
+  # analyze_path /usr/X11R6/bin -> ls -dl /usr /usr/X11R6 /usr/X11R6/bin
+  # Thanks to Randolph Chung for this clever hack.
+
+  local f g
+
+  while [ -n "$1" ]; do
+    reject_whitespace "$1"
+    g=
+    message "Analyzing $1:"
+    for f in $(echo "$1" | tr / \  ); do
+      if [ -e /$g$f ]; then
+        ls -dl /$g$f /$g$f.dpkg-* 2> /dev/null || true
+        g=$g$f/
+      else
+        message "/$g$f: nonexistent; directory contents of /$g:"
+        ls -l /$g
+        break
+      fi
+    done
+    shift
+  done
+}
+
+find_culprits () {
+  local f p dpkg_info_dir possible_culprits smoking_guns bad_packages package \
+    msg
+
+  reject_whitespace "$1"
+  message "Searching for overlapping packages..."
+  dpkg_info_dir=/var/lib/dpkg/info
+  if [ -d $dpkg_info_dir ]; then
+    if [ "$(echo $dpkg_info_dir/*.list)" != "$dpkg_info_dir/*.list" ]; then
+      possible_culprits=$(ls -1 $dpkg_info_dir/*.list | egrep -v \
+        "(xbase-clients|x11-common|xfs|xlibs)")
+      if [ -n "$possible_culprits" ]; then
+        smoking_guns=$(grep -l "$1" $possible_culprits || true)
+        if [ -n "$smoking_guns" ]; then
+          bad_packages=$(printf "\\n")
+          for f in $smoking_guns; do
+            # too bad you can't nest parameter expansion voodoo
+            p=${f%*.list}      # strip off the trailing ".list"
+            package=${p##*/}   # strip off the directories
+            bad_packages=$(printf "%s\n%s" "$bad_packages" "$package")
+          done
+          msg=$(cat <<EOF
+The following packages appear to have file overlaps with the X.Org packages;
+these packages are either very old, or in violation of Debian Policy.  Try
+upgrading each of these packages to the latest available version if possible:
+for example, with the command "apt-get install".  If no newer version of a
+package is available, you will have to remove it; for example, with the command
+"apt-get remove".  If even the latest available version of the package has
+this file overlap, please file a bug against that package with the Debian Bug
+Tracking System.  You may want to refer the package maintainer to section 12.8
+of the Debian Policy manual.
+EOF
+)
+          message "$msg"
+          message "The overlapping packages are: $bad_packages"
+        else
+          message "no overlaps found."
+        fi
+      fi
+    else
+      message "cannot search; no matches for $dpkg_info_dir/*.list."
+    fi
+  else
+    message "cannot search; $dpkg_info_dir does not exist."
+  fi
+}
+
+# we require a readlink command or shell function
+if ! which readlink > /dev/null 2>&1; then
+  message "The readlink command was not found.  Please install version" \
+          "1.13.1 or later of the debianutils package."
+  readlink () {
+    # returns what symlink in $1 actually points to
+    perl -e '$l = shift; exit 1 unless -l $l; $r = readlink $l; exit 1 unless $r; print "$r\n"' "$1"
+  }
+fi
+
+check_symlink () {
+  # syntax: check_symlink symlink
+  #
+  # See if specified symlink points where it is supposed to.  Return 0 if it
+  # does, and 1 if it does not.
+  #
+  # Primarily used by check_symlinks_and_warn() and check_symlinks_and_bomb().
+
+  local symlink
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "check_symlink() called with wrong number of arguments;" \
+                "expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  symlink="$1"
+
+  if [ "$(maplink "$symlink")" = "$(readlink "$symlink")" ]; then
+    return 0
+  else
+    return 1
+  fi
+}
+
+check_symlinks_and_warn () {
+  # syntax: check_symlinks_and_warn symlink ...
+  #
+  # For each argument, check for symlink sanity, and warn if it isn't sane.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install".
+
+  local errmsg symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_warn() called with wrong number of" \
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        observe "$symlink symbolic link points to wrong location" \
+                "$(readlink "$symlink"); removing"
+        rm "$symlink"
+      fi
+    elif [ -e "$symlink" ]; then
+      errmsg="$symlink exists and is not a symbolic link; this package cannot"
+      errmsg="$errmsg be installed until this"
+      if [ -f "$symlink" ]; then
+        errmsg="$errmsg file"
+      elif [ -d "$symlink" ]; then
+        errmsg="$errmsg directory"
+      else
+        errmsg="$errmsg thing"
+      fi
+      errmsg="$errmsg is removed"
+      die "$errmsg"
+    fi
+    shift
+  done
+}
+
+check_symlinks_and_bomb () {
+  # syntax: check_symlinks_and_bomb symlink ...
+  #
+  # For each argument, check for symlink sanity, and bomb if it isn't sane.
+  #
+  # Call this function from a postinst script.
+
+  local problem symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_bomb() called with wrong number of"
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    problem=
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        problem=yes
+        warn "$symlink symbolic link points to wrong location" \
+             "$(readlink "$symlink")"
+      fi
+    elif [ -e "$symlink" ]; then
+      problem=yes
+      warn "$symlink is not a symbolic link"
+    else
+      problem=yes
+      warn "$symlink symbolic link does not exist"
+    fi
+    if [ -n "$problem" ]; then
+      analyze_path "$symlink" "$(readlink "$symlink")"
+      find_culprits "$symlink"
+      die "bad symbolic links on system"
+    fi
+    shift
+  done
+}
+
+font_update () {
+  # run $UPDATECMDS in $FONTDIRS
+
+  local dir cmd shortcmd x_font_dir_prefix
+
+  x_font_dir_prefix="/usr/share/fonts/X11"
+
+  if [ -z "$UPDATECMDS" ]; then
+    usage_error "font_update() called but \$UPDATECMDS not set"
+  fi
+  if [ -z "$FONTDIRS" ]; then
+    usage_error "font_update() called but \$FONTDIRS not set"
+  fi
+
+  reject_unlikely_path_chars "$UPDATECMDS"
+  reject_unlikely_path_chars "$FONTDIRS"
+
+  for dir in $FONTDIRS; do
+    if [ -d "$x_font_dir_prefix/$dir" ]; then
+      for cmd in $UPDATECMDS; do
+        if which "$cmd" > /dev/null 2>&1; then
+          shortcmd=${cmd##*/}
+          observe "running $shortcmd in $dir font directory"
+	  cmd_opts=
+          if [ "$shortcmd" = "update-fonts-alias" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-dir" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-scale" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          $cmd $cmd_opts $dir || warn "$cmd $cmd_opts $dir" \
+                              "failed; font directory data may not" \
+                              "be up to date"
+        else
+          warn "$cmd not found; not updating corresponding $dir font" \
+               "directory data"
+        fi
+      done
+    else
+      warn "$dir is not a directory; not updating font directory data"
+    fi
+  done
+}
+
+remove_conffile_prepare () {
+  # syntax: remove_conffile_prepare filename official_md5sum ...
+  #
+  # Check a conffile "filename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 2 ]; then
+    usage_error "remove_conffile_prepare() called with wrong number of" \
+                "arguments; expected at least 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+  shift
+
+  # does the conffile even exist?
+  if [ -e "$conffile" ]; then
+    # calculate its checksum
+    current_checksum=$(md5sum < "$conffile" | sed 's/[[:space:]].*//')
+    # compare it to each supplied checksum
+    while [ -n "$1" ]; do
+      if [ "$current_checksum" = "$1" ]; then
+        # we found a match; move the confffile and stop looking
+        observe "preparing obsolete conffile $conffile for removal"
+        mv "$conffile" "$conffile.$THIS_PACKAGE-tmp"
+        break
+      fi
+      shift
+    done
+  fi
+}
+
+remove_conffile_lookup () {
+  # syntax: remove_conffile_lookup package filename
+  #
+  # Lookup the md5sum of a conffile in dpkg's database, and prepare for removal
+  # if it matches the actual file's md5sum.
+  #
+  # Call this function when you would call remove_conffile_prepare but only
+  # want to check against dpkg's status database instead of known checksums.
+
+  local package conffile old_md5sum
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "remove_conffile_lookup() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  package="$1"
+  conffile="$2"
+
+  if ! [ -e "$conffile" ]; then
+    return
+  fi
+  old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$package" | \
+    awk '{ if (match($0, "^ '"$conffile"' ")) print $2}')"
+  if [ -n "$old_md5sum" ]; then
+    remove_conffile_prepare "$conffile" "$old_md5sum"
+  fi
+}
+
+remove_conffile_commit () {
+  # syntax: remove_conffile_commit filename
+  #
+  # Complete the removal of a conffile "filename" that has become obsolete.
+  #
+  # Call this function from a postinst script after having used
+  # remove_conffile_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_commit() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, remove it
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "committing removal of obsolete conffile $conffile"
+    rm "$conffile.$THIS_PACKAGE-tmp"
+  fi
+}
+
+remove_conffile_rollback () {
+  # syntax: remove_conffile_rollback filename
+  #
+  # Roll back the removal of a conffile "filename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" is  after having used remove_conffile_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_rollback() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, move it
+  # back
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "rolling back removal of obsolete conffile $conffile"
+    mv "$conffile.$THIS_PACKAGE-tmp" "$conffile"
+  fi
+}
+
+replace_conffile_with_symlink_prepare () {
+  # syntax: replace_conffile_with_symlink_prepare oldfilename newfilename \
+  # official_md5sum ...
+  #
+  # Check a conffile "oldfilename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails. Otherwise copy it
+  # to newfilename and let dpkg handle it through conffiles mechanism.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 3 ]; then
+    usage_error "replace_conffile_with_symlink_prepare() called with wrong" \
+                " number of arguments; expected at least 3, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  shift
+  newconffile="$1"
+  shift
+
+  remove_conffile_prepare "$_oldconffile" "$@"
+  # If $oldconffile still exists, then md5sums didn't match.
+  # Copy it to new one.
+  if [ -f "$oldconffile" ]; then
+    cp "$oldconffile" "$newconffile"
+  fi
+
+}
+
+replace_conffile_with_symlink_commit () {
+  # syntax: replace_conffile_with_symlink_commit oldfilename
+  #
+  # Complete the removal of a conffile "oldfilename" that has been
+  # replaced by a symlink.
+  #
+  # Call this function from a postinst script after having used
+  # replace_conffile_with_symlink_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "replace_conffile_with_symlink_commit() called with wrong" \
+                "number of arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  remove_conffile_commit "$conffile"
+}
+
+replace_conffile_with_symlink_rollback () {
+  # syntax: replace_conffile_with_symlink_rollback oldfilename newfilename
+  #
+  # Roll back the replacing of a conffile "oldfilename" with symlink to
+  # "newfilename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" and verify $2 to ensure the package failed to upgrade
+  # from a version (or install over a version removed-but-not-purged) prior
+  # to the one in which the conffile was obsoleted.
+  # You should have  used replace_conffile_with_symlink_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "replace_conffile_with_symlink_rollback() called with wrong" \
+                "number of arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  newconffile="$2"
+
+  remove_conffile_rollback "$_oldconffile"
+  if [ -f "$newconffile" ]; then
+    rm "$newconffile"
+  fi
+}
+
+run () {
+  # syntax: run command [ argument ... ]
+  #
+  # Run specified command with optional arguments and report its exit status.
+  # Useful for commands whose exit status may be nonzero, but still acceptable,
+  # or commands whose failure is not fatal to us.
+  #
+  # NOTE: Do *not* use this function with db_get or db_metaget commands; in
+  # those cases the return value of the debconf command *must* be checked
+  # before the string returned by debconf is used for anything.
+
+  local retval
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "run() called with wrong number of arguments; expected at" \
+                "least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  "$@" || retval=$?
+
+  if [ ${retval:-0} -ne 0 ]; then
+    observe "command \"$*\" exited with status $retval"
+  fi
+}
+
+register_x_lib_dir_with_ld_so () {
+  # syntax: register_x_lib_dir_with_ld_so
+  #
+  # Configure the dynamic loader ld.so to search /usr/X11R6/lib for shared
+  # libraries.
+  #
+  # Call this function from the postinst script of a package that places a
+  # shared library in /usr/X11R6/lib, before invoking ldconfig.
+
+  local dir ldsoconf
+
+  dir="/usr/X11R6/lib"
+  ldsoconf="/etc/ld.so.conf"
+
+  # is the line not already present?
+  if ! fgrep -qsx "$dir" "$ldsoconf"; then
+    observe "adding $dir directory to $ldsoconf"
+    echo "$dir" >> "$ldsoconf"
+  fi
+}
+
+deregister_x_lib_dir_with_ld_so () {
+  # syntax: deregister_x_lib_dir_with_ld_so
+  #
+  # Configure dynamic loader ld.so to not search /usr/X11R6/lib for shared
+  # libraries, if and only if no shared libaries remain there.
+  #
+  # Call this function from the postrm script of a package that places a shared
+  # library in /usr/X11R6/lib, in the event "$1" is "remove", and before
+  # invoking ldconfig.
+
+  local dir ldsoconf fgrep_status cmp_status
+
+  dir="/usr/X11R6/lib"
+  ldsoconf="/etc/ld.so.conf"
+
+  # is the line present?
+  if fgrep -qsx "$dir" "$ldsoconf"; then
+    # are there any shared objects in the directory?
+    if [ "$(echo "$dir"/lib*.so.*.*)" = "$dir/lib*.so.*.*" ]; then
+      # glob expansion produced nothing, so no shared libraries are present
+      observe "removing $dir directory from $ldsoconf"
+      # rewrite the file (very carefully)
+      set +e
+      fgrep -svx "$dir" "$ldsoconf" > "$ldsoconf.dpkg-tmp"
+      fgrep_status=$?
+      set -e
+      case $fgrep_status in
+        0|1) ;; # we don't actually care if any lines matched or not
+        *) die "error reading \"$ldsoconf\"; fgrep exited with status" \
+          "$fgrep_status" ;;
+      esac
+      set +e
+      cmp -s "$ldsoconf.dpkg-tmp" "$ldsoconf"
+      cmp_status=$?
+      set -e
+      case $cmp_status in
+        0) rm "$ldsoconf.dpkg-tmp" ;; # files are identical
+        1) mv "$ldsoconf.dpkg-tmp" "$ldsoconf" ;; # files differ
+        *) die "error comparing \"$ldsoconf.dpkg-tmp\" to \"$ldsoconf\";" \
+          "cmp exited with status $cmp_status" ;;
+      esac
+    fi
+  fi
+}
+
+make_symlink_sane () {
+  # syntax: make_symlink_sane symlink target
+  #
+  # Ensure that the symbolic link symlink exists, and points to target.
+  #
+  # If symlink does not exist, create it and point it at target.
+  #
+  # If symlink exists but is not a symbolic link, back it up.
+  #
+  # If symlink exists, is a symbolic link, but points to the wrong location, fix
+  # it.
+  #
+  # If symlink exists, is a symbolic link, and already points to target, do
+  # nothing.
+  #
+  # This function wouldn't be needed if ln had an -I, --idempotent option.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "make_symlink_sane() called with wrong number of arguments;" \
+      "expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local symlink target
+
+  symlink="$1"
+  target="$2"
+
+  if [ -L "$symlink" ] && [ "$(readlink "$symlink")" = "$target" ]; then
+      observe "link from $symlink to $target already exists"
+  else
+    observe "creating symbolic link from $symlink to $target"
+    mkdir -p "${target%/*}" "${symlink%/*}"
+    ln -s -b -S ".dpkg-old" "$target" "$symlink"
+  fi
+}
+
+migrate_dir_to_symlink () {
+  # syntax: migrate_dir_to_symlink old_location new_location
+  #
+  # Per Debian Policy section 6.5.4, "A directory will never be replaced by a
+  # symbolic link to a directory or vice versa; instead, the existing state
+  # (symlink or not) will be left alone and dpkg will follow the symlink if
+  # there is one."
+  #
+  # We have to do it ourselves.
+  #
+  # This function moves the contents of old_location, a directory, into
+  # new_location, a directory, then makes old_location a symbolic link to
+  # new_location.
+  #
+  # old_location need not exist, but if it does, it must be a directory (or a
+  # symlink to a directory).  If it is not, it is backed up.  If new_location
+  # exists already and is not a directory, it is backed up.
+  #
+  # This function should be called from a package's preinst so that other
+  # packages unpacked after this one --- but before this package's postinst runs
+  # --- are unpacked into new_location even if their payloads contain
+  # old_location filespecs.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "migrate_dir_to_symlink() called with wrong number of"
+                "arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local new old
+
+  old="$1"
+  new="$2"
+
+  # Is old location a symlink?
+  if [ -L "$old" ]; then
+    # Does it already point to new location?
+    if [ "$(readlink "$old")" = "$new" ]; then
+      # Nothing to do; migration has already been done.
+      observe "migration of $old to $new already done"
+      return 0
+    else
+      # Back it up.
+      warn "backing up symbolic link $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+    fi
+  fi
+
+  # Does old location exist, but is not a directory?
+  if [ -e "$old" ] && ! [ -d "$old" ]; then
+      # Back it up.
+      warn "backing up non-directory $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+  fi
+
+  observe "migrating $old to $new"
+
+  # Is new location a symlink?
+  if [ -L "$new" ]; then
+    # Does it point the wrong way, i.e., back to where we're migrating from?
+    if [ "$(readlink "$new")" = "$old" ]; then
+      # Get rid of it.
+      observe "removing symbolic link $new which points to $old"
+      rm "$new"
+    else
+      # Back it up.
+      warn "backing up symbolic link $new as $new.dpkg-old"
+      mv -b "$new" "$new.dpkg-old"
+    fi
+  fi
+
+  # Does new location exist, but is not a directory?
+  if [ -e "$new" ] && ! [ -d "$new" ]; then
+    warn "backing up non-directory $new as $new.dpkg-old"
+    mv -b "$new" "$new.dpkg-old"
+  fi
+
+  # Create new directory if it does not yet exist.
+  if ! [ -e "$new" ]; then
+    observe "creating $new"
+    mkdir -p "$new"
+  fi
+
+  # Copy files in old location to new location.  Back up any filenames that
+  # already exist in the new location with the extension ".dpkg-old".
+  observe "copying files from $old to $new"
+  if ! (cd "$old" && cp -a -b -S ".dpkg-old" . "$new"); then
+    die "error(s) encountered while copying files from $old to $new"
+  fi
+
+  # Remove files at old location.
+  observe "removing $old"
+  rm -r "$old"
+
+  # Create symlink from old location to new location.
+  make_symlink_sane "$old" "$new"
+}
+
+# vim:set ai et sw=2 ts=2 tw=80:
+
+# GOBSTOPPER: The X Strike Force shell library ends here.
--- xorg-server-1.4.2.orig/debian/prune/non-free
+++ xorg-server-1.4.2/debian/prune/non-free
@@ -0,0 +1 @@
+hw/xfree86/doc/README.DRI
--- xorg-server-1.4.2.orig/debian/patches/14_default_screen_section.diff
+++ xorg-server-1.4.2/debian/patches/14_default_screen_section.diff
@@ -0,0 +1,57 @@
+--- xorg-server.orig/hw/xfree86/common/xf86Config.c
++++ xorg-server/hw/xfree86/common/xf86Config.c
+@@ -1800,11 +1800,6 @@
+     if (!servlayoutp)
+ 	return FALSE;
+ 
+-    if (conf_screen == NULL) {
+-	xf86ConfigError("No Screen sections present\n");
+-	return FALSE;
+-    }
+-
+     /*
+      * which screen section is the active one?
+      *
+@@ -1892,6 +1887,12 @@
+     XF86ConfAdaptorLinkPtr conf_adaptor;
+     Bool defaultMonitor = FALSE;
+ 
++    if (!conf_screen) {
++        conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec));
++        conf_screen->scrn_identifier = "Default Screen Section";
++        xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n");
++    }
++
+     xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier,
+ 	    scrnum);
+     /*
+--- xorg-server.orig/hw/xfree86/parser/Screen.c
++++ xorg-server/hw/xfree86/parser/Screen.c
+@@ -498,12 +498,6 @@
+ 	XF86ConfDevicePtr device;
+ 	XF86ConfAdaptorLinkPtr adaptor;
+ 
+-	if (!screen)
+-	{
+-		xf86validationError ("At least one Screen section is required.");
+-		return (FALSE);
+-	}
+-
+ 	while (screen)
+ 	{
+ 		if (screen->scrn_obso_driver && !screen->scrn_identifier)
+@@ -512,13 +506,7 @@
+ 		monitor = xf86findMonitor (screen->scrn_monitor_str, p->conf_monitor_lst);
+ 		if (screen->scrn_monitor_str)
+ 		{
+-			if (!monitor)
+-			{
+-				xf86validationError (UNDEFINED_MONITOR_MSG,
+-						 	screen->scrn_monitor_str, screen->scrn_identifier);
+-				return (FALSE);
+-			}
+-			else
++			if (monitor)
+ 			{
+ 				screen->scrn_monitor = monitor;
+ 				if (!xf86validateMonitor(p, screen))
--- xorg-server-1.4.2.orig/debian/patches/04_auto_load_driver_no_conf.diff
+++ xorg-server-1.4.2/debian/patches/04_auto_load_driver_no_conf.diff
@@ -0,0 +1,28 @@
+Index: xorg-server/hw/xfree86/common/xf86AutoConfig.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86AutoConfig.c
++++ xorg-server/hw/xfree86/common/xf86AutoConfig.c
+@@ -225,22 +225,7 @@
+     char *driver = NULL;
+     ConfigStatus ret;
+ 
+-    /* Find the primary device, and get some information about it. */
+-    if (xf86PciVideoInfo) {
+-	for (pciptr = xf86PciVideoInfo; (info = *pciptr); pciptr++) {
+-	    if (xf86IsPrimaryPci(info)) {
+-		break;
+-	    }
+-	}
+-	if (!info) {
+-	    ErrorF("Primary device is not PCI\n");
+-	}
+-    } else {
+-	ErrorF("xf86PciVideoInfo is not set\n");
+-    }
+-
+-    if (info)
+-	driver = videoPtrToDriverName(info);
++    driver = chooseVideoDriver();
+ 
+     AppendToConfig(BUILTIN_MODULE_SECTION);
+     AppendToConfig(BUILTIN_MONITOR_SECTION);
--- xorg-server-1.4.2.orig/debian/patches/47_fbdevhw_magic_numbers.diff
+++ xorg-server-1.4.2/debian/patches/47_fbdevhw_magic_numbers.diff
@@ -0,0 +1,17 @@
+* Fri May 11 2007 Adam Jackson <ajax@redhat.com> 1.3.0.0-5
+- xserver-1.3.0-fbdevhw-magic-numbers.patch: If the fbdev driver claims to
+  have a zero pixel clock, believe it.  Fixes Xen paravirt. (#238451)
+
+Might fix #422430
+
+--- xorg-server-1.3.0.0/./hw/xfree86/fbdevhw/fbdevhw.c.jx	2007-03-26 23:32:36.000000000 -0400
++++ xorg-server-1.3.0.0/./hw/xfree86/fbdevhw/fbdevhw.c	2007-05-11 15:10:05.000000000 -0400
+@@ -258,7 +258,7 @@
+ static void
+ fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode)
+ {
+-	mode->Clock = var->pixclock ? 1000000000/var->pixclock : 28000000;
++	mode->Clock = var->pixclock ? 1000000000/var->pixclock : 0;
+ 	mode->HDisplay = var->xres;
+ 	mode->HSyncStart = mode->HDisplay+var->right_margin;
+ 	mode->HSyncEnd = mode->HSyncStart+var->hsync_len;
--- xorg-server-1.4.2.orig/debian/patches/11_dont_crash_on_bad_dri_mode.diff
+++ xorg-server-1.4.2/debian/patches/11_dont_crash_on_bad_dri_mode.diff
@@ -0,0 +1,66 @@
+Index: xorg-server/hw/xfree86/parser/Configint.h
+===================================================================
+--- xorg-server.orig/hw/xfree86/parser/Configint.h	2008-03-02 17:09:50.000000000 -0500
++++ xorg-server/hw/xfree86/parser/Configint.h	2008-03-02 18:33:14.000000000 -0500
+@@ -71,11 +71,14 @@
+ #include <stddef.h>
+ #include "xf86Parser.h"
+ 
++typedef enum { PARSE_DECIMAL, PARSE_OCTAL, PARSE_HEX } ParserNumType;
++
+ typedef struct
+ {
+ 	int num;		/* returned number */
+ 	char *str;		/* private copy of the return-string */
+ 	double realnum;		/* returned number as a real */
++        ParserNumType numType;  /* used to enforce correct number formatting */
+ }
+ LexRec, *LexPtr;
+ 
+@@ -215,6 +218,8 @@
+ "\ta numerical group id."
+ #define MULTIPLE_MSG \
+ "Multiple \"%s\" lines."
++#define MUST_BE_OCTAL_MSG \
++"The number \"%d\" given in this section must be in octal (0xxx) format."
+ 
+ /* Warning messages */
+ #define OBSOLETE_MSG \
+Index: xorg-server/hw/xfree86/parser/DRI.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/parser/DRI.c	2008-03-02 17:09:50.000000000 -0500
++++ xorg-server/hw/xfree86/parser/DRI.c	2008-03-02 18:33:14.000000000 -0500
+@@ -117,6 +117,8 @@
+ 	    case MODE:
+ 		if (xf86getSubToken (&(ptr->dri_comment)) != NUMBER)
+ 		    Error (NUMBER_MSG, "Mode");
++                if (val.numType != PARSE_OCTAL)
++                    Error (MUST_BE_OCTAL_MSG, val.num);
+ 		ptr->dri_mode = val.num;
+ 		break;
+ 	    case BUFFERS:
+Index: xorg-server/hw/xfree86/parser/scan.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/parser/scan.c	2008-03-02 18:33:23.000000000 -0500
++++ xorg-server/hw/xfree86/parser/scan.c	2008-03-02 18:33:29.000000000 -0500
+@@ -379,11 +379,20 @@
+ 			if (c == '0')
+ 				if ((configBuf[configPos] == 'x') ||
+ 					(configBuf[configPos] == 'X'))
++                                {
+ 					base = 16;
++                                        val.numType = PARSE_HEX; 
++                                }
+ 				else
++                                {
+ 					base = 8;
++                                        val.numType = PARSE_OCTAL;
++                                }
+ 			else
++                        {
+ 				base = 10;
++                                val.numType = PARSE_DECIMAL;
++                        }
+ 
+ 			configRBuf[0] = c;
+ 			i = 1;
--- xorg-server-1.4.2.orig/debian/patches/91_ttf2pt1
+++ xorg-server-1.4.2/debian/patches/91_ttf2pt1
@@ -0,0 +1,22165 @@
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/bdf.c xserver/hw/xprint/extras/ttf2pt1/bdf.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/bdf.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/bdf.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,660 @@
++/*
++ * The font parser for the BDF files
++ *
++ * Copyright (c) 2001 by the TTF2PT1 project
++ * Copyright (c) 2001 by Sergey Babkin
++ *
++ * see COPYRIGHT for the full copyright notice
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include "pt1.h"
++#include "global.h"
++
++/* prototypes of call entries */
++static void openfont(char *fname, char *arg);
++static void closefont( void);
++static int getnglyphs ( void);
++static int glnames( GLYPH *glyph_list);
++static void readglyphs( GLYPH *glyph_list);
++static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
++static void fnmetrics( struct font_metrics *fm);
++static void glpath( int glyphno, GLYPH *glyph_list);
++static void kerning( GLYPH *glyph_list);
++
++/* globals */
++
++/* front-end descriptor */
++struct frontsw bdf_sw = {
++	/*name*/       "bdf",
++	/*descr*/      "BDF bitmapped fonts",
++	/*suffix*/     { "bdf" },
++	/*open*/       openfont,
++	/*close*/      closefont,
++	/*nglyphs*/    getnglyphs,
++	/*glnames*/    glnames,
++	/*glmetrics*/  readglyphs,
++	/*glenc*/      glenc,
++	/*fnmetrics*/  fnmetrics,
++	/*glpath*/     glpath,
++	/*kerning*/    kerning,
++};
++
++/* statics */
++
++#define MAXLINE	10240 /* maximal line length in the input file */
++
++static int lineno; /* line number */
++
++#define GETLEN(s)	s, (sizeof(s)-1)
++#define LENCMP(str, txt)	strncmp(str, txt, sizeof(txt)-1)
++
++static FILE *bdf_file;
++static int nglyphs;
++static struct font_metrics fmet;
++
++/* many BDF fonts are of small pixel size, so we better try
++ * to scale them by an integer to keep the dimensions in
++ * whole pixels. However if the size is too big and a non-
++ * integer scaling is needed, we use the standard ttf2pt1's
++ * scaling abilities.
++ */
++static int pixel_size;
++static int scale;
++static int scale_external;
++
++static char *slant;
++static char xlfdname[201];
++static char *spacing;
++static char *charset_reg;
++static char *charset_enc;
++static char *fnwidth;
++static int is_unicode = 0;
++
++/* tempoary storage for returning data to ttf2pt1 later on request */
++static int maxenc = 0;
++static int *fontenc;
++static GENTRY **glpaths;
++
++static int got_glyphs = 0;
++static GLYPH *glyphs;
++static int curgl;
++
++static int readfile(FILE *f, int (*strfunc)(int len, char *str));
++
++/*
++ * Read the file and parse each string with strfunc(),
++ * until strfunc() returns !=0 or the end of file happens.
++ * Returns -1 on EOF or strfunc() returning <0, else 0
++ */
++
++static int
++readfile(
++	FILE *f,
++	int (*strfunc)(int len, char *str)
++)
++{
++	static char str[MAXLINE]; /* input line, maybe should be dynamic ? */
++	char *s;
++	int len, c, res;
++
++	len=0;
++	while(( c=getc(f) )!=EOF) {
++		if(c=='\n') {
++			str[len]=0;
++
++			res = strfunc(len, str);
++			lineno++;
++			if(res<0)
++				return -1;
++			else if(res!=0)
++				return 0;
++
++			len=0;
++		} else if(len<MAXLINE-1) {
++			if(c!='\r')
++				str[len++]=c;
++		} else {
++			fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1);
++			exit(1);
++		}
++	}
++	return -1; /* EOF */
++}
++
++/*
++ * Parse the header of the font file. 
++ * Stop after the line CHARS is encountered. Ignore the unknown lines.
++ */
++
++struct line {
++	char *name; /* property name with trailing space */
++	int namelen; /* length of the name string */
++	enum {
++		ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */
++		IS_SEEN = 0x02, /* this property has been seen already */
++		MUST_SEE = 0x04, /* this property must be seen */
++		IS_LAST = 0x08 /* this is the last property to be read */
++	} flags;
++	char *fmt; /* format string for the arguments, NULL means a string arg */
++	int nvals; /* number of values to be read by sscanf */
++	void *vp[4]; /* pointers to values to be read */
++};
++		
++static struct line header[] = {
++	{ GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} },
++	{ GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} },
++	{ GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4, 
++		{&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} },
++	{ GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} },
++	{ GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} },
++	{ GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} },
++	{ GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} },
++	{ GETLEN("SPACING "), 0, NULL, 1, {&spacing} },
++	{ GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} },
++	{ GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} },
++	{ GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} },
++	{ GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} },
++	{ GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} },
++
++	/* these 2 must go in this order for post-processing */
++	{ GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} },
++	{ GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} },
++
++	{ GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} },
++	{ NULL, 0, 0 } /* end mark: name==NULL */
++};
++
++static int
++handle_header(
++	int len,
++	char *str
++)
++{
++	struct line *cl;
++	char *s, *p;
++	int c;
++
++#if 0
++	fprintf(stderr, "line: %s\n", str);
++#endif
++	for(cl = header; cl->name != 0; cl++) {
++		if(strncmp(str, cl->name, cl->namelen))
++			continue;
++#if 0
++		fprintf(stderr, "match: %s\n", cl->name);
++#endif
++		if(cl->flags & IS_SEEN) {
++			if(cl->flags & ALLOW_REPEAT)
++				continue;
++			
++			fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name);
++			exit(1);
++		}
++		cl->flags |= IS_SEEN;
++		if(cl->fmt == 0) {
++			s = malloc(len - cl->namelen + 1);
++			if(s == 0) {
++				fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++				exit(255);
++			}
++			*((char **)(cl->vp[0])) = s;
++
++			/* skip until a quote */
++			for(p = str+cl->namelen; (c = *p)!=0; p++) {
++				if(c == '"') {
++					p++;
++					break;
++				}
++			}
++			for(; (c = *p)!=0; p++) {
++				if(c == '"') {
++					c = *++p;
++					if(c == '"')
++						*s++ = c;
++					else
++						break;
++				} else
++					*s++ = c;
++			}
++			*s = 0; /* end of line */
++		} else {
++			c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]);
++			if(c != cl->nvals) {
++				fprintf(stderr, "**** property %s at input line %d must have %d arguments\n", 
++					cl->name, lineno, cl->nvals);
++				exit(1);
++			}
++		}
++		if(cl->flags & IS_LAST)
++			return 1;
++		else
++			return 0;
++	}
++	return 0;
++}
++
++/*
++ * Parse the description of the glyphs
++ */
++
++static int
++handle_glyphs(
++	int len,
++	char *str
++)
++{
++	static int inbmap=0;
++	static char *bmap;
++	static int xsz, ysz, xoff, yoff;
++	static int curln;
++	int i, c;
++	char *p, *plim, *psz;
++
++	if(!LENCMP(str, "ENDFONT")) {
++		if(curgl < nglyphs) {
++			fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl);
++			exit(1);
++		} else
++			return 1;
++	}
++	if(curgl >= nglyphs) {
++		fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs);
++		exit(1);
++	}
++	if(!LENCMP(str, "STARTCHAR")) {
++		/* sizeof will count \0 instead of ' ' */
++		for(i=sizeof("STARTCHAR"); str[i] == ' '; i++) 
++			{}
++
++		glyphs[curgl].name = strdup(str + i);
++		if(glyphs[curgl].name == 0) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++	} else if(!LENCMP(str, "ENCODING")) {
++		if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) {
++			fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno);
++			exit(1);
++		}
++		if(fontenc[curgl] == -1)  /* compatibility format */
++			sscanf(str, "ENCODING -1 %d", &fontenc[curgl]);
++		if(fontenc[curgl] > maxenc)
++			maxenc = fontenc[curgl];
++	} else if(!LENCMP(str, "DWIDTH")) {
++		if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) {
++			fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno);
++			exit(1);
++		}
++		glyphs[curgl].width = xsz*scale;
++	} else if(!LENCMP(str, "BBX")) {
++		if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) {
++			fprintf(stderr,"**** weird BBX statement at line %d\n", lineno);
++			exit(1);
++		}
++		bmap=malloc(xsz*ysz);
++		if(bmap==0) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++		glyphs[curgl].lsb = -xoff*scale;
++		glyphs[curgl].xMin = -xoff*scale;
++		glyphs[curgl].xMax = (xsz-xoff)*scale;
++		glyphs[curgl].yMin = -yoff*scale;
++		glyphs[curgl].yMax = (ysz-xoff)*scale;
++	} else if(!LENCMP(str, "BITMAP")) {
++		inbmap=1; 
++		curln=ysz-1; /* the lowest line has index 0 */
++	} else if(!LENCMP(str, "ENDCHAR")) {
++		inbmap=0;
++		if(bmap) {
++			glyphs[curgl].lastentry = 0;
++			glyphs[curgl].path = 0;
++			glyphs[curgl].entries = 0;
++			bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff);
++			free(bmap);
++			/* remember in a static table or it will be erased */
++			glpaths[curgl] = glyphs[curgl].entries;
++			glyphs[curgl].entries = 0;
++
++			if(glpaths[curgl])
++				glyphs[curgl].ttf_pathlen = 1;
++			else
++				glyphs[curgl].ttf_pathlen = 0;
++		}
++		curgl++;
++	} else if(inbmap) {
++		if(curln<0) {
++			fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno);
++			exit(1);
++		}
++
++		i=0;
++		p=&bmap[curln*xsz]; psz=p+xsz;
++		while(i<len) {
++			c=str[i++];
++			if(!isxdigit(c)) {
++				fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno);
++				exit(1);
++			}
++			if(c<='9')
++				c-='0';
++			else 
++				c= tolower(c)-'a'+10;
++
++			for(plim=p+4; p<psz && p<plim; c<<=1) 
++				*p++ = (( c & 0x08 )!=0);
++		}
++		if(p<psz) {
++			fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno);
++			exit(1);
++		}
++		curln--;
++	}
++	return 0;
++}
++
++/*
++ * Read all the possible information about the glyphs
++ */
++
++static void
++readglyphs(
++	GLYPH *glyph_list
++)
++{
++	int i;
++	GLYPH *g;
++
++	if(got_glyphs)
++		return;
++
++	/* pass them to handle_glyphs() through statics */
++	glyphs = glyph_list;
++	curgl = 2; /* skip the empty glyph and .notdef */
++
++	/* initialize the empty glyph and .notdef */
++
++	for(i=0; i<2; i++) {
++		g = &glyphs[i];
++		g->lsb = 0;
++		g->width = fmet.bbox[2];
++		g->xMin = 0;
++		g->yMin = 0;
++	}
++	g = &glyphs[0];
++	g->name = ".notdef";
++	g->xMax = fmet.bbox[2]*4/5;
++	g->yMax = fmet.bbox[3]*4/5;
++	g->entries = g->path = g->lastentry = 0;
++	/* make it look as a black square */
++	fg_rmoveto(g, 0.0, 0.0);
++	fg_rlineto(g, 0.0, (double)g->yMax);
++	fg_rlineto(g, (double)g->xMax, (double)g->yMax);
++	fg_rlineto(g, (double)g->xMax, 0.0);
++	fg_rlineto(g, 0.0, 0.0);
++	g_closepath(g);
++	glpaths[0] = g->entries;
++	g->entries = 0;
++	g->ttf_pathlen = 4;
++
++	g = &glyphs[1];
++	g->name = ".null";
++	g->xMax = g->yMax = 0;
++	g->ttf_pathlen = 0;
++
++	if(readfile(bdf_file, handle_glyphs) < 0) {
++		fprintf(stderr, "**** file does not contain the ENDFONT line\n");
++		exit(1);
++	}
++	got_glyphs = 1;
++}
++
++/*
++ * Open font and prepare to return information to the main driver.
++ * May print error and warning messages.
++ * Exit on error.
++ */
++
++static void
++openfont(
++	char *fname,
++	char *arg /* unused now */
++)
++{
++	struct line *cl;
++	int i, l;
++
++	if ((bdf_file = fopen(fname, "r")) == NULL) {
++		fprintf(stderr, "**** Cannot open file '%s'\n", fname);
++		exit(1);
++	} else {
++		WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
++	}
++
++	lineno = 1;
++
++	for(cl = header; cl->name != 0; cl++)
++		cl->flags &= ~IS_SEEN;
++	if(readfile(bdf_file, handle_header) < 0) {
++		fprintf(stderr, "**** file does not contain the CHARS definition\n");
++		exit(1);
++	}
++	for(cl = header; cl->name != 0; cl++) {
++		if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) {
++			fprintf(stderr, "**** mandatory property %sis not found in the input line\n", 
++				cl->name); /* cl->name has a space at the end */
++			exit(1);
++		}
++
++		/* set a few defaults */
++		if( !(cl->flags & IS_SEEN) ) {
++			if(cl->vp[0] == &fmet.underline_thickness) {
++				fmet.underline_thickness = 1;
++			} else if(cl->vp[0] == &fmet.underline_position) {
++				fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness
++					- (pixel_size - fmet.bbox[3]);
++			} else if(cl->vp[0] == &fmet.ascender) {
++				fmet.ascender = fmet.bbox[2] + fmet.bbox[0];
++			} else if(cl->vp[0] == &fmet.descender) {
++				fmet.descender = fmet.bbox[0];
++			}
++		}
++	}
++
++	nglyphs += 2; /* add empty glyph and .notdef */
++
++	/* postprocessing to compensate for the differences in the metric formats */
++	fmet.bbox[2] += fmet.bbox[0];
++	fmet.bbox[3] += fmet.bbox[1];
++
++	scale = 1000/pixel_size; /* XXX ? */
++	if(scale*pixel_size < 950) {
++		scale = 1;
++		scale_external = 1;
++		fmet.units_per_em = pixel_size;
++	} else {
++		scale_external = 0;
++		fmet.units_per_em = scale*pixel_size;
++
++		fmet.underline_position *= scale;
++		fmet.underline_thickness *= scale;
++		fmet.ascender *= scale;
++		fmet.descender *= scale;
++		for(i=0; i<4; i++)
++			fmet.bbox[i] *= scale;
++	}
++
++	fmet.italic_angle = 0.0;
++	if(spacing == 0 /* possibly an old font */ 
++	|| toupper(spacing[0]) != 'P') /* or anything non-proportional */
++		fmet.is_fixed_pitch = 1;
++	else
++		fmet.is_fixed_pitch = 0;
++
++	if(fmet.name_copyright==NULL)
++		fmet.name_copyright = "";
++	
++	/* create the full name */
++	l = strlen(fmet.name_family) 
++		+ (fmet.name_style? strlen(fmet.name_style) : 0)
++		+ (fnwidth? strlen(fnwidth) : 0)
++		+ strlen("Oblique") + 1;
++
++	if(( fmet.name_full = malloc(l) )==NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++	strcpy(fmet.name_full, fmet.name_family);
++	if(fnwidth && strcmp(fnwidth, "Normal")) {
++		strcat(fmet.name_full, fnwidth);
++	}
++	if(fmet.name_style && strcmp(fmet.name_style, "Medium")) {
++		strcat(fmet.name_full, fmet.name_style);
++	}
++	switch(toupper(slant[0])) {
++	case 'O':
++		strcat(fmet.name_full, "Oblique");
++		break;
++	case 'I':
++		strcat(fmet.name_full, "Italic");
++		break;
++	}
++
++	fmet.name_ps = fmet.name_full;
++	fmet.name_version = "1.0";
++
++	if(charset_reg && charset_enc
++	&& !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1"))
++		is_unicode = 1;
++
++	if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++	for(i=0; i<nglyphs; i++)
++		fontenc[i] = -1;
++	if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++}
++
++/*
++ * Close font.
++ * Exit on error.
++ */
++
++static void
++closefont(
++	void
++)
++{
++	if(fclose(bdf_file) < 0) {
++		WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
++	}
++}
++
++/*
++ * Get the number of glyphs in font.
++ */
++
++static int
++getnglyphs (
++	void
++)
++{
++	return nglyphs;
++}
++
++/*
++ * Get the names of the glyphs.
++ * Returns 0 if the names were assigned, non-zero if the font
++ * provides no glyph names.
++ */
++
++static int
++glnames(
++	GLYPH *glyph_list
++)
++{
++	readglyphs(glyph_list);
++	return 0;
++}
++
++/*
++ * Get the original encoding of the font. 
++ * Returns 1 for if the original encoding is Unicode, 2 if the
++ * original encoding is other 16-bit, 0 if 8-bit.
++ */
++
++static int
++glenc(
++	GLYPH *glyph_list,
++	int *encoding,
++	int *unimap
++)
++{
++	int i, douni, e;
++
++	if(is_unicode || forcemap)
++		douni = 1;
++	else
++		douni = 0;
++
++	for(i=0; i<nglyphs; i++) {
++		e = fontenc[i];
++		if(douni)
++			e = unicode_rev_lookup(e);
++		if(e>=0 && e<ENCTABSZ && encoding[e] == -1)
++			encoding[e] = i;
++	}
++
++	if(is_unicode)
++		return 1;
++	else if(maxenc > 255)
++		return 2;
++	else
++		return 0;
++}
++	
++/*
++ * Get the font metrics
++ */
++static void 
++fnmetrics(
++	struct font_metrics *fm
++)
++{
++	*fm = fmet;
++}
++
++/*
++ * Get the path of contrours for a glyph.
++ */
++
++static void
++glpath(
++	int glyphno,
++	GLYPH *glyf_list
++)
++{
++	readglyphs(glyf_list);
++	glyf_list[glyphno].entries = glpaths[glyphno];
++	glpaths[glyphno] = 0;
++}
++
++/*
++ * Get the kerning data.
++ */
++
++static void
++kerning(
++	GLYPH *glyph_list
++)
++{
++	return; /* no kerning in BDF */
++}
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/bitmap.c xserver/hw/xprint/extras/ttf2pt1/bitmap.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/bitmap.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/bitmap.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,2633 @@
++/*
++ * Handling of the bitmapped glyphs
++ *
++ * Copyright (c) 2001 by the TTF2PT1 project
++ * Copyright (c) 2001 by Sergey Babkin
++ *
++ * see COPYRIGHT for the full copyright notice
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#include "pt1.h"
++#include "global.h"
++
++/* possible values of limits */
++#define L_NONE	0 /* nothing here */
++#define L_ON	1 /* black is on up/right */
++#define L_OFF	2 /* black is on down/left */
++
++static int warnedhints = 0;
++
++
++#ifdef USE_AUTOTRACE
++#include <autotrace/autotrace.h>
++
++/*
++ * Produce an autotraced outline from a bitmap.
++ * scale - factor to scale the sizes
++ * bmap - array of dots by lines, xsz * ysz
++ * xoff, yoff - offset of the bitmap's lower left corner
++ *              from the logical position (0,0)
++ */
++
++static void
++autotraced_bmp_outline(
++	GLYPH *g,
++	int scale,
++	char *bmap,
++	int xsz,
++	int ysz,
++	int xoff,
++	int yoff
++)
++{
++	at_bitmap_type atb;
++	at_splines_type *atsp;
++	at_fitting_opts_type *atoptsp;
++	at_spline_list_type *slp;
++	at_spline_type *sp;
++	int i, j, k;
++	double lastx, lasty;
++	double fscale;
++	char *xbmap;
++
++	fscale = (double)scale;
++
++	/* provide a white margin around the bitmap */
++	xbmap = malloc((ysz+2)*(xsz+2));
++	if(xbmap == 0)  {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++	memset(xbmap, 0, xsz+2);  /* top margin */
++	for(i=0, j=xsz+2; i<ysz; i++, j+=xsz+2) {
++		xbmap[j] = 0; /* left margin */
++		memcpy(&xbmap[j+1], &bmap[xsz*(ysz-1-i)], xsz); /* a line of bitmap */
++		xbmap[j+xsz+1] = 0; /* right margin */
++	}
++	memset(xbmap+j, 0, xsz+2);  /* bottom margin */
++	xoff--; yoff-=2; /* compensate for the margins */
++
++	atoptsp = at_fitting_opts_new();
++
++	atb.width = xsz+2;
++	atb.height = ysz+2;
++	atb.np = 1;
++	atb.bitmap = xbmap;
++
++	atsp = at_splines_new(&atb, atoptsp);
++
++	lastx = lasty = -1.;
++	for(i=0; i<atsp->length; i++) {
++		slp = &atsp->data[i];
++#if 0
++		fprintf(stderr, "%s: contour %d: %d entries clockwise=%d color=%02X%02X%02X\n",
++			g->name, i, slp->length, slp->clockwise, slp->color.r, slp->color.g, slp->color.b);
++#endif
++		if(slp->length == 0)
++			continue;
++#if 0
++		if(slp->color.r + slp->color.g + slp->color.b == 0)
++			continue;
++#endif
++		fg_rmoveto(g, fscale*(slp->data[0].v[0].x+xoff), fscale*(slp->data[0].v[0].y+yoff));
++		for(j=0; j<slp->length; j++) {
++#if 0
++			fprintf(stderr, "  ");
++			for(k=0; k<4; k++)
++				fprintf(stderr, "(%g %g) ", 
++					fscale*(slp->data[j].v[k].x+xoff), 
++					fscale*(ysz-slp->data[j].v[k].y+yoff)
++					);
++			fprintf(stderr, "\n");
++#endif
++			fg_rrcurveto(g,
++				fscale*(slp->data[j].v[1].x+xoff), fscale*(slp->data[j].v[1].y+yoff),
++				fscale*(slp->data[j].v[2].x+xoff), fscale*(slp->data[j].v[2].y+yoff),
++				fscale*(slp->data[j].v[3].x+xoff), fscale*(slp->data[j].v[3].y+yoff) );
++		}
++		g_closepath(g);
++	}
++
++	at_splines_free(atsp);
++	at_fitting_opts_free(atoptsp);
++	free(xbmap);
++}
++
++#endif /*USE_AUTOTRACE*/
++
++/* an extension of gentry for description of the fragments */
++typedef struct gex_frag GEX_FRAG;
++struct gex_frag {
++	/* indexes to len, the exact values and order are important */
++#define GEXFI_NONE	-1
++#define GEXFI_CONVEX	0
++#define GEXFI_CONCAVE	1
++#define GEXFI_LINE	2 /* a line with steps varying by +-1 pixel */
++#define GEXFI_EXACTLINE	3 /* a line with exactly the same steps */
++#define GEXFI_SERIF	4 /* small serifs at the ends of stemsi - must be last */
++#define GEXFI_COUNT	5 /* maximal index + 1 */
++	unsigned short len[GEXFI_COUNT]; /* length of various fragment types starting here */
++	unsigned short lenback[GEXFI_COUNT]; /* length back to the start of curve */
++
++	signed char ixstart; /* index of the frag type that starts here */
++	signed char ixcont; /* index of the frag type that continues here */
++
++	short flags;
++#define GEXFF_HLINE	0x0001 /* the exact line is longer in "horizontal" dimension */
++#define GEXFF_EXTR	0x0002 /* this gentry is an extremum in some direction */
++#define GEXFF_CIRC	0x0004 /* the joint at this gentry is for a circular curve */
++#define GEXFF_DRAWCURVE	0x0008 /* vect[] describes a curve to draw */
++#define GEXFF_DRAWLINE	0x0010 /* vect[] describes a line to draw */
++#define GEXFF_SPLIT	0x0020 /* is a result of splitting a line */
++#define GEXFF_SYMNEXT	0x0040 /* this subfrag is symmetric with next one */
++#define GEXFF_DONE	0x0080 /* this subfrag has been vectorized */
++#define GEXFF_LONG	0x0100 /* this gentry is longer than 1 pixel */
++
++	unsigned short aidx; /* index of gentry in the array representing the contour */
++	
++	unsigned short vectlen; /* number of gentries represented by vect[] */
++
++	/* coordinates for vectored replacement of this fragment */
++	/* (already scaled because it's needed for curve approximation) */
++	double vect[4 /*ref.points*/][2 /*X,Y*/];
++
++	double bbox[2 /*X,Y*/]; /* absolute sizes of bounding box of a subfragment */
++
++	/* used when splitting the curved frags into subfrags */
++	GENTRY *prevsub;  /* to gentries describing neighboring subfrags */
++	GENTRY *nextsub;
++	GENTRY *ordersub; /* single-linked list describing the order of calculation */
++
++	int sublen; /* length of this subfrag */
++	/* the symmetry across the subfrags */
++	int symaxis; /* the symmetry axis, with next subfrag */
++	int symxlen; /* min length of adjacent symmetric frags */
++	/* the symmetry within this subfrag (the axis is always diagonal) */
++	GENTRY *symge; /* symge->i{x,y}3 is the symmetry point of symge==0 if none */
++
++};
++#define	X_FRAG(ge)	((GEX_FRAG *)((ge)->ext))
++
++/* various interesting tables related to GEX_FRAG */
++static char *gxf_name[GEXFI_COUNT] = {"Convex", "Concave", "Line", "ExLine", "Serif"};
++static int gxf_cvk[2] = {-1, 1}; /* coefficients of concaveness */
++
++/*
++ * Dump the contents of X_EXT()->len and ->lenback for a contour
++ */
++static void
++gex_dump_contour(
++	GENTRY *ge,
++	int clen
++)
++{
++	int i, j;
++
++	for(j = 0; j < GEXFI_COUNT; j++) {
++		fprintf(stderr, "%-8s", gxf_name[j]);
++		for(i = 0; i < clen; i++, ge = ge->frwd)
++			fprintf(stderr, " %2d", X_FRAG(ge)->len[j]);
++		fprintf(stderr, " %p\n (back) ", ge);
++		for(i = 0; i < clen; i++, ge = ge->frwd)
++			fprintf(stderr, " %2d", X_FRAG(ge)->lenback[j]);
++		fprintf(stderr, "\n");
++	}
++}
++
++/*
++ * Calculate values of X_EXT()->lenback[] for all entries in
++ * a contour. The contour is identified by:
++ *  ge - any gentry of the contour
++ *  clen - contour length
++ */
++
++static void
++gex_calc_lenback(
++	GENTRY *ge,
++	int clen
++)
++{
++	int i, j;
++	int end;
++	GEX_FRAG *f;
++	int len[GEXFI_COUNT]; /* length of the most recent fragment */
++	int count[GEXFI_COUNT]; /* steps since beginning of the fragment */
++
++	for(j = 0; j < GEXFI_COUNT; j++)
++		len[j] = count[j] = 0;
++
++	end = clen;
++	for(i = 0; i < end; i++, ge = ge->frwd) {
++		f = X_FRAG(ge);
++		for(j = 0; j < GEXFI_COUNT; j++) {
++			if(len[j] != count[j]) {
++				f->lenback[j] = count[j]++;
++			} else
++				f->lenback[j] = 0;
++			if(f->len[j] != 0) {
++				len[j] = f->len[j];
++				count[j] = 1; /* start with the next gentry */
++				/* if the fragment will wrap over the start, process to its end */
++				if(i < clen && i + len[j] > end) 
++					end = i + len[j];
++			}
++		}
++	}
++	gex_dump_contour(ge, clen);
++}
++
++/* Limit a curve to not exceed the given coordinates
++ * at its given side
++ */
++
++static void
++limcurve(
++	double curve[4][2 /*X,Y*/],
++	double lim[2 /*X,Y*/],
++	int where /* 0 - start, 3 - end */
++)
++{
++	int other = 3-where; /* the other end */
++	int sgn[2 /*X,Y*/]; /* sign for comparison */
++	double t, from, to, nt, t2, nt2, tt[4];
++	double val[2 /*X,Y*/];
++	int i;
++
++	for(i=0; i<2; i++)
++		sgn[i] = fsign(curve[other][i] - curve[where][i]);
++
++#if 0
++	fprintf(stderr, "     limit (%g,%g)-(%g,%g) at %d by (%g,%g), sgn(%d,%d)\n",
++		curve[0][0], curve[0][1], curve[3][0], curve[3][1],
++		where, lim[0], lim[1], sgn[0], sgn[1]);
++#endif
++	/* a common special case */
++	if( sgn[0]*(curve[where][0] - lim[0]) >= 0.
++	&& sgn[1]*(curve[where][1] - lim[1]) >= 0. )
++		return; /* nothing to do */
++
++	if(other==0) {
++		from = 0.;
++		to = 1.;
++	} else {
++		from = 1.;
++		to = 0.;
++	}
++#if 0
++	fprintf(stderr, "t=");
++#endif
++	while( fabs(from-to) > 0.00001 ) {
++		t = 0.5 * (from+to);
++		t2 = t*t;
++		nt = 1.-t;
++		nt2 = nt*nt;
++		tt[0] = nt2*nt;
++		tt[1] = 3*nt2*t;
++		tt[2] = 3*nt*t2;
++		tt[3] = t*t2;
++		for(i=0; i<2; i++)
++			val[i] = curve[0][i]*tt[0] + curve[1][i]*tt[1]
++				+ curve[2][i]*tt[2] + curve[3][i]*tt[3];
++#if 0
++		fprintf(stderr, "%g(%g,%g) ", t, val[0], val[1]);
++#endif
++		if(fabs(val[0] - lim[0]) < 0.1
++		|| fabs(val[1] - lim[1]) < 0.1)
++			break;
++
++		if(sgn[0] * (val[0] - lim[0]) < 0.
++		|| sgn[1] * (val[1] - lim[1]) < 0.)
++			to = t;
++		else
++			from = t;
++	}
++	/* now t is the point of splitting */
++#define SPLIT(pt1, pt2)	( (pt1) + t*((pt2)-(pt1)) ) /* order is important! */
++	for(i=0; i<2; i++) {
++		double v11, v12, v13, v21, v22, v31; /* intermediate points */
++
++		v11 = SPLIT(curve[0][i], curve[1][i]);
++		v12 = SPLIT(curve[1][i], curve[2][i]);
++		v13 = SPLIT(curve[2][i], curve[3][i]);
++		v21 = SPLIT(v11, v12);
++		v22 = SPLIT(v12, v13);
++		v31 = SPLIT(v21, v22);
++		if(other==0) {
++			curve[1][i] = v11;
++			curve[2][i] = v21;
++			curve[3][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31;
++		} else {
++			curve[0][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31;
++			curve[1][i] = v22;
++			curve[2][i] = v13;
++		}
++	}
++#undef SPLIT
++#if 0
++	fprintf(stderr, "\n");
++#endif
++}
++
++/*
++ * Vectorize a subfragment of a curve fragment. All the data has been already
++ * collected by this time
++ */
++
++static void
++dosubfrag(
++	GLYPH *g,
++	int fti, /* fragment type index */
++	GENTRY *firstge, /* first gentry of fragment */
++	GENTRY *ge, /* first gentry of subfragment */
++	double fscale
++) 
++{
++	GENTRY *gel, *gei; /* last gentry of this subfrag */
++	GEX_FRAG *f, *ff, *lf, *pf, *xf;
++	/* maximal amount of space that can be used at the beginning and the end */
++	double fixfront[2], fixend[2]; /* fixed points - used to show direction */
++	double mvfront[2], mvend[2]; /* movable points */
++	double limfront[2], limend[2]; /* limit of movement for movabel points */
++	double sympt;
++	int outfront, outend; /* the beginning/end is going outwards */
++	int symfront, symend; /* a ready symmetric fragment is present at front/end */
++	int drnd[2 /*X,Y*/]; /* size of the round part */
++	int i, j, a1, a2, ndots;
++	double avg2, max2; /* squared distances */
++	struct dot_dist *dots, *usedots;
++
++	ff = X_FRAG(firstge);
++	f = X_FRAG(ge);
++	gel = f->nextsub;
++	lf = X_FRAG(gel);
++	if(f->prevsub != 0)
++		pf = X_FRAG(f->prevsub);
++	else
++		pf = 0;
++
++	for(i=0; i<2; i++)
++		drnd[i] = gel->bkwd->ipoints[i][2] - ge->ipoints[i][2];
++
++	if(f->prevsub==0 && f->ixcont == GEXFI_NONE) {
++		/* nothing to join with : may use the whole length */
++		for(i = 0; i < 2; i++)
++			limfront[i] = ge->bkwd->ipoints[i][2];
++	} else {
++		/* limit to a half */
++		for(i = 0; i < 2; i++)
++			limfront[i] = 0.5 * (ge->ipoints[i][2] + ge->bkwd->ipoints[i][2]);
++	}
++	if( (ge->ix3 == ge->bkwd->ix3) /* vert */
++	^ (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3))
++	^ (fti == GEXFI_CONCAVE) /* counter-clockwise */ ) {
++		/* the beginning is not a flat 90-degree end */
++		outfront = 1;
++		for(i = 0; i < 2; i++)
++			fixfront[i] = ge->frwd->ipoints[i][2];
++	} else {
++		outfront = 0;
++		for(i = 0; i < 2; i++)
++			fixfront[i] = ge->ipoints[i][2];
++	}
++
++	if(lf->nextsub==0 && lf->ixstart == GEXFI_NONE) {
++		/* nothing to join with : may use the whole length */
++		for(i = 0; i < 2; i++)
++			limend[i] = gel->ipoints[i][2];
++	} else {
++		/* limit to a half */
++		for(i = 0; i < 2; i++)
++			limend[i] = 0.5 * (gel->ipoints[i][2] + gel->bkwd->ipoints[i][2]);
++	}
++	gei = gel->bkwd->bkwd;
++	if( (gel->ix3 == gel->bkwd->ix3) /* vert */
++	^ (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3))
++	^ (fti == GEXFI_CONVEX) /* clockwise */ ) {
++		/* the end is not a flat 90-degree end */
++		outend = 1;
++		for(i = 0; i < 2; i++)
++			fixend[i] = gel->bkwd->bkwd->ipoints[i][2];
++	} else {
++		outend = 0;
++		for(i = 0; i < 2; i++)
++			fixend[i] = gel->bkwd->ipoints[i][2];
++	}
++
++	for(i = 0; i < 2; i++) {
++		fixfront[i] *= fscale;
++		limfront[i] *= fscale;
++		fixend[i] *= fscale;
++		limend[i] *= fscale;
++	}
++
++	fprintf(stderr, "    %d out(%d[%d %d %d],%d[%d %d %d]) drnd(%d, %d)\n", 
++		fti,
++		outfront, 
++			(ge->ix3 == ge->bkwd->ix3),
++			(isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)),
++			(fti == GEXFI_CONCAVE),
++		outend,
++			(gel->ix3 == gel->bkwd->ix3),
++			(isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)),
++			(fti == GEXFI_CONVEX),
++		drnd[0], drnd[1]);
++
++	/* prepare to calculate the distances */
++	ndots = f->sublen - 1;
++	dots = malloc(sizeof(*dots) * ndots);
++	if(dots == 0) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++	for(i = 0, gei = ge; i < ndots; i++, gei = gei->frwd) {
++		for(a1 = 0; a1 < 2; a1++)
++			dots[i].p[a1] = fscale * gei->ipoints[a1][2];
++	}
++
++	/* see if we can mirror a ready symmetric curve */
++
++	/* check symmetry with the fragment before this */
++	symfront = (pf != 0 && (pf->flags & GEXFF_SYMNEXT) && (pf->flags & GEXFF_DONE)
++		&& ( outend && f->sublen <= pf->sublen
++			|| ( pf->sublen == f->sublen 
++				&& (lf->sublen == 0
++					|| ( abs(limfront[0]-limend[0]) >= abs(pf->vect[0][0]-pf->vect[3][0])
++						&& abs(limfront[1]-limend[1]) >= abs(pf->vect[0][1]-pf->vect[3][1]) ))
++			)
++		)
++	);
++	/* check symmetry with the fragment after this */
++	symend = ( (f->flags & GEXFF_SYMNEXT) && (lf->flags & GEXFF_DONE)
++		&& ( outfront && f->sublen <= lf->sublen
++			|| ( lf->sublen == f->sublen 
++				&& (pf == 0 
++					|| ( abs(limfront[0]-limend[0]) >= abs(lf->vect[0][0]-lf->vect[3][0])
++						&& abs(limfront[1]-limend[1]) >= abs(lf->vect[0][1]-lf->vect[3][1]) )) 
++			)
++		)
++	);
++	if(symfront || symend) {
++		/* mirror the symmetric neighbour subfrag */
++		if(symfront) {
++			a1 = (ge->ix3 != ge->bkwd->ix3); /* the symmetry axis */
++			a2 = !a1; /* the other axis (goes along the extremum gentry) */
++
++			/* the symmetry point on a2 */
++			sympt = fscale * 0.5 * (ge->ipoints[a2][2] + ge->bkwd->ipoints[a2][2]);
++			xf = pf; /* the symmetric fragment */
++		} else {
++			a1 = (gel->ix3 != gel->bkwd->ix3); /* the symmetry axis */
++			a2 = !a1; /* the other axis (goes along the extremum gentry) */
++
++			/* the symmetry point on a2 */
++			sympt = fscale * 0.5 * (gel->ipoints[a2][2] + gel->bkwd->ipoints[a2][2]);
++			xf = lf; /* the symmetric fragment */
++		}
++		fprintf(stderr, "     sym with %p f=%d(%p) e=%d(%p) a1=%c a2=%c sympt=%g\n",
++			xf, symfront, pf, symend, lf,
++			a1 ? 'Y': 'X', a2 ? 'Y': 'X', sympt
++		);
++		for(i=0; i<4; i++) {
++			f->vect[3-i][a1] = xf->vect[i][a1];
++			f->vect[3-i][a2] = sympt - (xf->vect[i][a2]-sympt);
++		}
++		if(symfront) {
++			if(outend || lf->sublen==0)
++				limcurve(f->vect, limend, 3);
++		} else {
++			if(outfront || pf == 0)
++				limcurve(f->vect, limfront, 0);
++		}
++		avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2);
++		fprintf(stderr, "     avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale);
++		if(max2 <= fscale*fscale) {
++			f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
++			f->vectlen = f->sublen;
++			free(dots);
++			return;
++		}
++	}
++
++	if( !outfront && !outend && f->symge != 0) {
++		/* a special case: try a circle segment as an approximation */
++		double lenfront, lenend, len, maxlen;
++
++		/* coefficient for a Bezier approximation of a circle */
++#define CIRCLE_FRAC	0.55
++
++		a1 = (ge->ix3 == ge->bkwd->ix3); /* get the axis along the front */
++		a2 = !a1; /* axis along the end */
++
++		lenfront = fixfront[a1] - limfront[a1];
++		lenend = fixend[a2] - limend[a2];
++		if(fabs(lenfront) < fabs(lenend))
++			len = fabs(lenfront);
++		else
++			len = fabs(lenend);
++
++		/* make it go close to the round shape */
++		switch(f->sublen) {
++		case 2:
++			maxlen = fscale;
++			break;
++		case 4:
++		case 6:
++			maxlen = fscale * 2.;
++			break;
++		default:
++			maxlen = fscale * abs(ge->frwd->frwd->ipoints[a1][2] 
++				- ge->ipoints[a1][2]);
++			break;
++		}
++		if(len > maxlen)
++			len = maxlen;
++
++		mvfront[a1] = fixfront[a1] - fsign(lenfront) * len;
++		mvfront[a2] = limfront[a2];
++		mvend[a2] = fixend[a2] - fsign(lenend) * len;
++		mvend[a1] = limend[a1];
++
++		for(i=0; i<2; i++) {
++			f->vect[0][i] = mvfront[i];
++			f->vect[3][i] = mvend[i];
++		}
++		f->vect[1][a1] = mvfront[a1] + CIRCLE_FRAC*(mvend[a1]-mvfront[a1]);
++		f->vect[1][a2] = mvfront[a2];
++		f->vect[2][a1] = mvend[a1];
++		f->vect[2][a2] = mvend[a2] + CIRCLE_FRAC*(mvfront[a2]-mvend[a2]);
++
++		avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2);
++		fprintf(stderr, "     avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale);
++		if(max2 <= fscale*fscale) {
++			f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
++			f->vectlen = f->sublen;
++			free(dots);
++			return;
++		}
++#undef CIRCLE_FRAC
++	}
++	for(i=0; i<2; i++) {
++		f->vect[0][i] = limfront[i];
++		f->vect[1][i] = fixfront[i];
++		f->vect[2][i] = fixend[i];
++		f->vect[3][i] = limend[i];
++	}
++	usedots = dots;
++	if(outfront) {
++		usedots++; ndots--;
++	}
++	if(outend)
++		ndots--;
++	if( fcrossrayscv(f->vect, NULL, NULL) == 0) {
++		fprintf(stderr, "**** Internal error: rays must cross but don't at %p-%p\n",
++			ge, gel);
++		fprintf(stderr, "  (%g, %g) (%g, %g) (%g, %g) (%g, %g)\n", 
++			limfront[0], limfront[1],
++			fixfront[0], fixfront[1],
++			fixend[0], fixend[1],
++			limend[0], limend[1]
++		);
++		dumppaths(g, NULL, NULL);
++		exit(1);
++	} else {
++		if(ndots != 0)
++			fapproxcurve(f->vect, usedots, ndots);
++		f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE);
++		f->vectlen = f->sublen;
++	}
++	free(dots);
++}
++
++/*
++ * Subtract a list of gentries (covered by a fragment of higher
++ * priority) from the set of fragments of a given
++ * type.
++ *
++ * An example is subtraction of the long exact line fragments
++ * from the curve fragments which get overridden.
++ */
++
++static void
++frag_subtract(
++	GLYPH *g,
++	GENTRY **age, /* array of gentries for this contour */
++	int clen, /* length of the contour */
++	GENTRY *ge, /* first gentry to be subtracted */
++	int slen, /* number of gentries in the list to be subtracted */
++	int d /* type of fragments from which to subtract, as in GEXFI_... */
++)
++{
++	GENTRY *pge;
++	GEX_FRAG *f, *pf;
++	int len, i, j;
++
++	f = X_FRAG(ge);
++	len = slen; 
++
++	/* check if we overlap the end of some fragment */
++	if(f->lenback[d]) {
++		/* chop off the end of conflicting fragment */
++		len = f->lenback[d];
++		pge = age[(f->aidx + clen - len)%clen];
++		pf = X_FRAG(pge);
++		if(pf->len[d] == clen+1 && pf->flags & GEXFF_CIRC) {
++			/* the conflicting fragment is self-connected */
++
++			pf->len[d] = 0;
++			/* calculate the new value for lenback */
++			len = clen+1 - slen;
++			for(pge = ge; len > 0; pge = pge->bkwd, len--)
++				X_FRAG(pge)->lenback[d] = len;
++			/* now pge points to the last entry of the line,
++			 * which is also the new first entry of the curve
++			 */
++			X_FRAG(pge)->len[d] = clen+2 - slen;
++			/* clean lenback of gentries covered by the line */
++			for(pge = ge->frwd, j = slen-1; j > 0; pge = pge->frwd, j--)
++				X_FRAG(pge)->lenback[d] = 0;
++			fprintf(stderr, "    cut %s circular frag to %p-%p\n", 
++				gxf_name[d], pge, ge);
++			gex_dump_contour(ge, clen);
++		} else {
++			/* when we chop off a piece of fragment, we leave the remaining
++			 * piece(s) overlapping with the beginning and possibly the end 
++			 * of the line fragment under consideration
++			 */
++			fprintf(stderr, "    cut %s frag at %p from len=%d to len=%d (end %p)\n", 
++				gxf_name[d], pge, pf->len[d], len+1, ge);
++			j = pf->len[d] - len - 1; /* how many gentries are chopped off */
++			pf->len[d] = len + 1;
++			i = slen - 1;
++			for(pge = ge->frwd; j > 0 && i > 0; j--, i--, pge = pge->frwd)
++				X_FRAG(pge)->lenback[d] = 0;
++			gex_dump_contour(ge, clen);
++
++			if(j != 0) {
++				/* the conflicting fragment is split in two by this line
++				 * fragment, fix up its tail
++				 */
++
++				fprintf(stderr, "    end of %s frag len=%d %p-", 
++					gxf_name[d], j+1, pge->bkwd);
++				X_FRAG(pge->bkwd)->len[d] = j+1; /* the overlapping */
++				for(i = 1; j > 0; j--, i++, pge = pge->frwd)
++					X_FRAG(pge)->lenback[d] = i;
++				fprintf(stderr, "%p\n", pge->bkwd);
++				gex_dump_contour(ge, clen);
++			}
++		}
++	}
++	/* check if we overlap the beginning of some fragments */
++	i = slen-1; /* getntries remaining to consider */
++	j = 0; /* gentries remaining in the overlapping fragment */
++	for(pge = ge; i > 0; i--, pge = pge->frwd) {
++		if(j > 0) {
++			X_FRAG(pge)->lenback[d] = 0;
++			j--;
++		} 
++		/* the beginning of one fragment may be the end of another
++		 * fragment, in this case if j-- above results in 0, that will 
++		 * cause it to check the same gentry for the beginning
++		 */
++		if(j == 0) {
++			pf = X_FRAG(pge);
++			j = pf->len[d]; 
++			if(j != 0) {
++				fprintf(stderr, "    removed %s frag at %p len=%d\n", 
++					gxf_name[d], pge, j);
++				gex_dump_contour(ge, clen);
++				pf->len[d] = 0;
++				j--;
++			}
++		}
++	}
++	/* pge points at the last gentry of the line fragment */
++	if(j > 1) { /* we have the tail of a fragment left */
++		fprintf(stderr, "    end of %s frag len=%d %p-", 
++			gxf_name[d], j, pge);
++		X_FRAG(pge)->len[d] = j; /* the overlapping */
++		for(i = 0; j > 0; j--, i++, pge = pge->frwd)
++			X_FRAG(pge)->lenback[d] = i;
++		fprintf(stderr, "%p\n", pge->bkwd);
++		gex_dump_contour(ge, clen);
++	} else if(j == 1) {
++		X_FRAG(pge)->lenback[d] = 0;
++	}
++}
++
++/*
++ * Produce an outline from a bitmap.
++ * scale - factor to scale the sizes
++ * bmap - array of dots by lines, xsz * ysz
++ * xoff, yoff - offset of the bitmap's lower left corner
++ *              from the logical position (0,0)
++ */
++
++void
++bmp_outline(
++	GLYPH *g,
++	int scale,
++	char *bmap,
++	int xsz,
++	int ysz,
++	int xoff,
++	int yoff
++)
++{
++	char *hlm, *vlm; /* arrays of the limits of outlines */
++	char *amp; /* map of ambiguous points */
++	int x, y;
++	char *ip, *op;
++	double fscale;
++
++	if(xsz==0 || ysz==0)
++		return;
++
++#ifdef USE_AUTOTRACE
++	if(use_autotrace) {
++		autotraced_bmp_outline(g, scale, bmap, xsz, ysz, xoff, yoff);
++		return;
++	}
++#endif /*USE_AUTOTRACE*/
++
++	fscale = (double)scale;
++	g->flags &= ~GF_FLOAT; /* build it as int first */
++
++	if(!warnedhints) {
++		warnedhints = 1;
++		if(hints && subhints) {
++			WARNING_2 fprintf(stderr, 
++				"Use of hint substitution on bitmap fonts is not recommended\n");
++		}
++	}
++
++#if 0
++	printbmap(bmap, xsz, ysz, xoff, yoff);
++#endif
++
++	/* now find the outlines */
++	hlm=calloc( xsz, ysz+1 ); /* horizontal limits */
++	vlm=calloc( xsz+1, ysz ); /* vertical limits */
++	amp=calloc( xsz, ysz ); /* ambiguous points */
++
++	if(hlm==0 || vlm==0 || amp==0)  {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++
++	/*
++	 * hlm and vlm represent a grid of horisontal and
++	 * vertical lines. Each pixel is surrounded by the grid
++	 * from all the sides. The values of [hv]lm mark the
++	 * parts of grid where the pixel value switches from white
++	 * to black and back.
++	 */
++
++	/* find the horizontal limits */
++	ip=bmap; op=hlm;
++	/* 1st row */
++	for(x=0; x<xsz; x++) {
++		if(ip[x])
++			op[x]=L_ON;
++	}
++	ip+=xsz; op+=xsz;
++	/* internal rows */
++	for(y=1; y<ysz; y++) {
++		for(x=0; x<xsz; x++) {
++			if(ip[x]) {
++				if(!ip[x-xsz])
++					op[x]=L_ON;
++			} else {
++				if(ip[x-xsz])
++					op[x]=L_OFF;
++			}
++		}
++		ip+=xsz; op+=xsz;
++	}
++
++	/* last row */
++	ip-=xsz;
++	for(x=0; x<xsz; x++) {
++		if(ip[x])
++			op[x]=L_OFF;
++	}
++
++	/* find the vertical limits */
++	ip=bmap; op=vlm;
++	for(y=0; y<ysz; y++) {
++		if(ip[0])
++			op[0]=L_ON;
++		for(x=1; x<xsz; x++) {
++			if(ip[x]) {
++				if(!ip[x-1])
++					op[x]=L_ON;
++			} else {
++				if(ip[x-1])
++					op[x]=L_OFF;
++			}
++		}
++		if(ip[xsz-1])
++			op[xsz]=L_OFF;
++		ip+=xsz; op+=xsz+1; 
++	}
++
++	/*
++	 * Ambiguous points are the nodes of the grids
++	 * that are between two white and two black pixels
++	 * located in a checkerboard style. Actually
++	 * there are only two patterns that may be
++	 * around an ambiguous point:
++	 *
++	 *    X|.    .|X
++	 *    -*-    -*-
++	 *    .|X    X|.
++	 *
++	 * where "|" and "-" represent the grid (respectively members
++	 * of vlm and hlm), "*" represents an ambiguous point
++	 * and "X" and "." represent black and white pixels.
++	 *
++	 * If these sample pattern occur in the lower left corner
++	 * of the bitmap then this ambiguous point will be
++	 * located at amp[1][1] or in other words amp[1*xsz+1].
++	 *
++	 * These points are named "ambiguous" because it's
++	 * not easy to guess what did the font creator mean
++	 * at these points. So we are going to treat them 
++	 * specially, doing no aggressive smoothing.
++	 */
++
++	/* find the ambiguous points */
++	for(y=ysz-1; y>0; y--)
++		for(x=xsz-1; x>0; x--) {
++			if(bmap[y*xsz+x]) {
++				if( !bmap[y*xsz+x-1] && !bmap[y*xsz-xsz+x] && bmap[y*xsz-xsz+x-1] )
++					amp[y*xsz+x]=1;
++			} else {
++				if( bmap[y*xsz+x-1] && bmap[y*xsz-xsz+x] && !bmap[y*xsz-xsz+x-1] )
++					amp[y*xsz+x]=1;
++			}
++		}
++
++#if 0
++	printlimits(hlm, vlm, amp, xsz, ysz);
++#endif
++
++	/* generate the vectored (stepping) outline */
++
++	while(1) {
++		int found = 0;
++		int outer; /* flag: this is an outer contour */
++		int hor, newhor; /* flag: the current contour direction is horizontal */
++		int dir; /* previous direction of the coordinate, 1 - L_ON, 0 - L_OFF */
++		int startx, starty; /* start of a contour */
++		int firstx, firsty; /* start of the current line */
++		int newx, newy; /* new coordinates to try */
++		char *lm, val;
++		int maxx, maxy, xor;
++
++		for(y=ysz; !found &&  y>0; y--) 
++			for(x=0; x<xsz; x++) 
++				if(hlm[y*xsz+x] > L_NONE) 
++					goto foundcontour;
++		break; /* have no contours left */
++
++	foundcontour:
++		ig_rmoveto(g, x+xoff, y+yoff); /* intermediate as int */
++
++		startx = firstx = x;
++		starty = firsty = y;
++
++		if(hlm[y*xsz+x] == L_OFF) {
++			outer = 1; dir = 0;
++			hlm[y*xsz+x] = -hlm[y*xsz+x]; /* mark as seen */
++			hor = 1; x++;
++		} else {
++			outer = 0; dir = 0;
++			hor = 0; y--;
++			vlm[y*(xsz+1)+x] = -vlm[y*(xsz+1)+x]; /* mark as seen */
++		}
++
++		while(x!=startx || y!=starty) {
++#if 0
++			printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir);
++#endif
++
++			/* initialization common for try1 and try2 */
++			if(hor) {
++				lm = vlm; maxx = xsz+1; maxy = ysz; newhor = 0;
++			} else {
++				lm = hlm; maxx = xsz; maxy = ysz+1; newhor = 1;
++			}
++			xor = (outer ^ hor ^ dir);
++
++		try1:
++			/* first we try to change axis, to keep the
++			 * contour as long as possible
++			 */
++
++			newx = x; newy = y;
++			if(!hor && (!outer ^ dir))
++				newx--;
++			if(hor && (!outer ^ dir))
++				newy--;
++
++			if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
++				goto try2;
++
++			if(!xor)
++				val = L_ON;
++			else
++				val = L_OFF;
++#if 0
++			printf("try 1, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
++				(newhor ? 'h':'v'), newx, newy);
++#endif
++			if( lm[newy*maxx + newx] == val )
++				goto gotit;
++
++		try2:
++			/* try to change the axis anyway */
++
++			newx = x; newy = y;
++			if(!hor && (outer ^ dir))
++				newx--;
++			if(hor && (outer ^ dir))
++				newy--;
++
++			if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
++				goto try3;
++
++			if(xor)
++				val = L_ON;
++			else
++				val = L_OFF;
++#if 0
++			printf("try 2, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
++				(newhor ? 'h':'v'), newx, newy);
++#endif
++			if( lm[newy*maxx + newx] == val )
++				goto gotit;
++
++		try3:
++			/* try to continue in the old direction */
++
++			if(hor) {
++				lm = hlm; maxx = xsz; maxy = ysz+1;
++			} else {
++				lm = vlm; maxx = xsz+1; maxy = ysz;
++			}
++			newhor = hor;
++			newx = x; newy = y;
++			if(hor && dir)
++				newx--;
++			if(!hor && !dir)
++				newy--;
++
++			if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy)
++				goto badtry;
++
++			if(dir)
++				val = L_ON;
++			else
++				val = L_OFF;
++#if 0
++			printf("try 3, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx],
++				(newhor ? 'h':'v'), newx, newy);
++#endif
++			if( lm[newy*maxx + newx] == val )
++				goto gotit;
++
++		badtry:
++			fprintf(stderr, "**** Internal error in the contour detection code at (%d, %d)\n", x, y);
++			fprintf(stderr, "glyph='%s' outer=%d hor=%d dir=%d\n", g->name, outer, hor, dir);
++			fflush(stdout);
++			exit(1);
++
++		gotit:
++			if(hor != newhor) { /* changed direction, end the previous line */
++				ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */
++				firstx = x; firsty = y;
++			}
++			lm[newy*maxx + newx] = -lm[newy*maxx + newx];
++			hor = newhor;
++			dir = (val == L_ON);
++			if(newhor)
++				x -= (dir<<1)-1;
++			else
++				y += (dir<<1)-1;
++		}
++#if 0
++		printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir);
++#endif
++		ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */
++		g_closepath(g);
++	}
++
++
++	/* try to vectorize the curves and sloped lines in the bitmap */
++	if(vectorize) { 
++		GENTRY *ge, *pge, *cge, *loopge;
++		int i;
++		int skip;
++
++		dumppaths(g, NULL, NULL);
++
++		/* allocate the extensions */
++		for(cge=g->entries; cge!=0; cge=cge->next) {
++			cge->ext = calloc(1, sizeof(GEX_FRAG) );
++			if(cge->ext == 0)  {
++				fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++				exit(255);
++			}
++		}
++
++		for(cge=g->entries; cge!=0; cge=cge->next) {
++			if(cge->type != GE_MOVE)
++				continue;
++
++			/* we've found the beginning of a contour */
++			{
++				int d, vert, count, stepmore, delaystop;
++				int vdir, hdir, fullvdir, fullhdir, len;
++				int dx, dy, lastdx, lastdy; 
++				int k1, k2, reversal, smooth, good;
++				int line[2 /*H,V*/], maxlen[2 /*H,V*/], minlen[2 /*H,V*/];
++				GENTRY **age; /* array of gentries in a contour */
++				int clen; /* contour length, size of ths array */
++				int i, j;
++				GEX_FRAG *f;
++
++				/* we know that all the contours start at the top-left corner,
++				 * so at most it might be before/after the last element of
++				 * the last/first fragment
++				 */
++
++				ge = cge->next;
++				pge = ge->bkwd;
++				if(ge->ix3 == pge->ix3) { /* a vertical line */
++					/* we want to start always from a horizontal line because
++					 * then we always start from top and that is quaranteed to be a 
++					 * fragment boundary, so move the start point of the contour
++					 */
++					pge->prev->next = pge->next;
++					pge->next->prev = pge->prev;
++					cge->next = pge;
++					pge->prev = cge;
++					pge->next = ge;
++					ge->prev = pge;
++					ge = pge; pge = ge->bkwd;
++					cge->ix3 = pge->ix3; cge->iy3 = pge->iy3;
++				}
++
++				/* fill the array of gentries */
++				clen = 1;
++				for(ge = cge->next->frwd; ge != cge->next; ge = ge->frwd)
++					clen++;
++				age = (GENTRY **)malloc(sizeof(*age) * clen);
++				ge = cge->next;
++				count = 0;
++				do {
++					age[count] = ge;
++					X_FRAG(ge)->aidx = count++;
++
++					/* and by the way find the extremums */
++					for(i=0; i<2; i++) {
++						if( isign(ge->frwd->ipoints[i][2] - ge->ipoints[i][2])
++						* isign(ge->bkwd->bkwd->ipoints[i][2] - ge->bkwd->ipoints[i][2]) == 1) {
++							X_FRAG(ge)->flags |= GEXFF_EXTR;
++							fprintf(stderr, "  %s extremum at %p\n", (i?"vert":"hor"), ge);
++						}
++						if(abs(ge->ipoints[i][2] - ge->bkwd->ipoints[i][2]) > 1)
++							X_FRAG(ge)->flags |= GEXFF_LONG;
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++
++				/* Find the serif fragments, looking as either of:
++				 *           -+              |
++				 *            |              |        
++				 *          +-+            +-+        
++				 *          |              |          
++				 *          +--...         +--...
++				 * with the thickness of serifs being 1 pixel. We make no
++				 * difference between serifs on vertical and horizontal stems.
++				 */
++
++				ge = cge->next;
++				do {
++					GENTRY *nge;
++					int pdx, pdy, ndx, ndy;
++
++					/* two gentries of length 1 mean a potential serif */
++					pge = ge->bkwd;
++					nge = ge->frwd;
++
++					dx = nge->ix3 - pge->ix3;
++					dy = nge->iy3 - pge->iy3;
++
++					if(abs(dx) != 1 || abs(dy) != 1) /* 2 small ones */
++						continue;
++
++					if( 
++						(!(X_FRAG(ge)->flags & GEXFF_EXTR) 
++							|| !(X_FRAG(ge->bkwd)->flags & GEXFF_EXTR))
++						&& (!(X_FRAG(ge->frwd)->flags & GEXFF_EXTR) 
++							|| !(X_FRAG(ge->frwd->frwd)->flags & GEXFF_EXTR))
++					)
++						continue; /* either side must be a couple of extremums */
++
++					pdx = pge->ix3 - pge->bkwd->ix3;
++					pdy = pge->iy3 - pge->bkwd->iy3;
++					ndx = nge->frwd->ix3 - nge->ix3;
++					ndy = nge->frwd->iy3 - nge->iy3;
++
++					if(pdx*dx + pdy*dy > 0 && ndx*dx + ndy*dy > 0) 
++						continue; /* definitely not a serif but a round corner */
++
++					if(abs(pdx) + abs(pdy) == 1 || abs(ndx) + abs(ndy) == 1)
++						continue;
++
++					/* we've found a serif including this and next gentry */
++					X_FRAG(ge)->len[GEXFI_SERIF] = 2;
++
++				} while( (ge = ge->frwd) != cge->next );
++
++
++				/* Find the convex and concave fragments, defined as:
++				 * convex (clockwise): dy/dx <= dy0/dx0, 
++				 *  or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx > 0
++				 * concave (counter-clockwise): dy/dx >= dy0/dx0, 
++				 *  or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx < 0
++				 *
++				 * Where dx and dy are measured between the end of this gentry
++				 * and the start of the previous one (dx0 and dy0 are the same
++				 * thing calculated for the previous gentry and its previous one),
++				 * dxthis is between the end and begginning of this gentry.
++				 *
++				 * A reversal is a situation when the curve changes its direction
++				 * along the x axis, so it passes through a momentary vertical
++				 * direction.
++				 */
++				for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++					ge = cge->next;
++					pge = ge->bkwd; /* the beginning of the fragment */
++					count = 1;
++					lastdx = pge->ix3 - pge->bkwd->bkwd->ix3;
++					lastdy = pge->iy3 - pge->bkwd->bkwd->iy3;
++
++#define CHKCURVCONN(ge, msg)	do { \
++		dx = (ge)->ix3 - (ge)->bkwd->bkwd->ix3; \
++		dy = (ge)->iy3 - (ge)->bkwd->bkwd->iy3; \
++		if(0 && msg) { \
++			fprintf(stderr, "  %p: dx=%d dy=%d dx0=%d dy0=%d ", \
++				(ge), dx, dy, lastdx, lastdy); \
++		} \
++		k1 = X_FRAG(ge)->flags; \
++		k2 = X_FRAG((ge)->bkwd)->flags; \
++		if(0 && msg) { \
++			fprintf(stderr, "fl=%c%c%c%c ", \
++				(k1 & GEXFF_EXTR) ? 'X' : '-', \
++				(k1 & GEXFF_LONG) ? 'L' : '-', \
++				(k2 & GEXFF_EXTR) ? 'X' : '-', \
++				(k2 & GEXFF_LONG) ? 'L' : '-' \
++			); \
++		} \
++		if( (k1 & GEXFF_EXTR) && (k2 & GEXFF_LONG) \
++		|| (k2 & GEXFF_EXTR) && (k1 & GEXFF_LONG) ) { \
++			smooth = 0; \
++			good = reversal = -1; /* for debugging */ \
++		} else { \
++			k1 = dy * lastdx; \
++			k2 = lastdy * dx; \
++			smooth = (abs(dx)==1 || abs(dy)==1); \
++			good = (k1 - k2)*gxf_cvk[d] >= 0; \
++			if(smooth && !good) { \
++				reversal = (k1 == -k2 && abs((ge)->ix3 - (ge)->bkwd->ix3)==1  \
++					&& dy*dx*gxf_cvk[d] < 0); \
++			} else \
++				reversal = 0; \
++		} \
++		if(0 && msg) { \
++			fprintf(stderr, "k1=%d k2=%d pge=%p count=%d %s good=%d rev=%d\n", \
++				k1, k2, pge, count, gxf_name[d], good, reversal); \
++		} \
++	} while(0)
++
++					do {
++						CHKCURVCONN(ge, 1);
++
++						if(smooth && (good || reversal) )
++							count++;
++						else {
++							/* can't continue */
++#if 0
++							if(count >= 4) { /* worth remembering */
++								fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
++							}
++#endif
++							X_FRAG(pge)->len[d] = count;
++							if(smooth) {
++								pge = ge->bkwd;
++								count = 2;
++							} else {
++								pge = ge;
++								count = 1;
++							}
++						}
++						lastdx = dx; lastdy = dy;
++						ge = ge->frwd;
++					} while(ge != cge->next);
++
++					/* see if we can connect the last fragment to the first */
++					CHKCURVCONN(ge, 1);
++
++					if(smooth && (good || reversal) ) {
++						/* -1 to avoid ge->bkwd being counted twice */
++						if( X_FRAG(ge->bkwd)->len[d] >= 2 )
++							count += X_FRAG(ge->bkwd)->len[d] - 1;
++						else if(count == clen+1) {
++							/* we are joining a circular (closed) curve, check whether it
++							 * can be joined at any point or whether it has a discontinuity
++							 * at the point where we join it now
++							 */
++							lastdx = dx; lastdy = dy;
++							CHKCURVCONN(ge->frwd, 0);
++
++							if(smooth && (good || reversal) ) {
++								/* yes, the curve is truly a circular one and can be 
++								 * joined at any point
++								 */
++
++#if 0
++								fprintf(stderr, " found a circular joint point at %p\n", pge);
++#endif
++								/* make sure that in a circular fragment we start from an extremum */
++								while( ! (X_FRAG(pge)->flags & GEXFF_EXTR) )
++									pge = pge->frwd;
++								X_FRAG(pge)->flags |= GEXFF_CIRC;
++							}
++						}
++#if 0
++						fprintf(stderr, " %s joined %p to %p count=%d bk_count=%d\n", gxf_name[d], pge, ge->bkwd, 
++							count, X_FRAG(ge->bkwd)->len[d] );
++#endif
++						X_FRAG(ge->bkwd)->len[d] = 0;
++					} 
++					X_FRAG(pge)->len[d] = count;
++#if 0
++					if(count >= 4) { /* worth remembering */
++						fprintf(stderr, " %s last frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
++					}
++#endif
++#undef CHKCURVCONN
++
++					/* do postprocessing */
++					ge = cge->next;
++					do {
++						f = X_FRAG(ge);
++						len = f->len[d];
++#if 0
++						fprintf(stderr, "   %p %s len=%d clen=%d\n", ge, gxf_name[d], len, clen);
++#endif
++						if(len < 3) /* get rid of the fragments that are too short */
++							f->len[d] = 0;
++						else if(len == 3) {
++							/*                                                    _
++							 * drop the |_| - shaped fragments, leave alone the _|  - shaped
++							 * (and even those only if not too short in pixels),
++							 * those left alone are further filtered later
++							 */
++							k1 = (ge->ix3 == ge->bkwd->ix3); /* axis of the start */
++							if(isign(ge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2])
++								!= isign(ge->frwd->ipoints[k1][2] - ge->frwd->frwd->ipoints[k1][2])
++							&& abs(ge->frwd->frwd->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) > 2) {
++#if 0
++								fprintf(stderr, " %s frag %p count=%d good shape\n", 
++									gxf_name[d], ge, count);
++#endif
++							} else
++								f->len[d] = 0;
++						} else if(len == clen+1)
++							break;  /* a closed fragment, nothing else interesting */
++						else { /* only for open fragments */
++							GENTRY *gem, *gex, *gei, *ges;
++
++							ges = ge; /* the start entry */
++							gem = age[(f->aidx + f->len[d])%clen]; /* entry past the end of the fragment */
++
++							gei = ge->frwd;
++							if( (ge->ix3 == ge->bkwd->ix3) /* vert */
++							^ (isign(ge->bkwd->ix3 - gei->ix3)==isign(ge->bkwd->iy3 - gei->iy3))
++							^ !(d == GEXFI_CONVEX) /* counter-clockwise */ ) {
++
++#if 0
++								fprintf(stderr, " %p: %s potential spurious start\n", ge, gxf_name[d]);
++#endif
++								/* the beginning may be a spurious entry */
++
++								gex = 0; /* the extremum closest to the beginning - to be found */
++								for(gei = ge->frwd; gei != gem; gei = gei->frwd) {
++									if(X_FRAG(gei)->flags & GEXFF_EXTR) {
++										gex = gei;
++										break;
++									}
++								}
++								if(gex == 0)
++									gex = gem->bkwd; 
++
++								/* A special case: ignore the spurious ends on small curves that
++								 * either enclose an 1-pixel-wide extremum or are 1-pixel deep.
++								 * Any 5-or-less-pixel-long curve with extremum 2 steps away
++								 * qualifies for that.
++								 */
++
++								if(len <= 5 && gex == ge->frwd->frwd) {
++									good = 0;
++#if 0
++									fprintf(stderr, " E");
++#endif
++								} else {
++									good = 1; /* assume that ge is not spurious */
++
++									/* gei goes backwards, gex goes forwards from the extremum */
++									gei = gex;
++									/* i is the symmetry axis, j is the other axis (X=0 Y=1) */
++									i = (gex->ix3 != gex->bkwd->ix3);
++									j = !i;
++									for( ; gei!=ge && gex!=gem; gei=gei->bkwd, gex=gex->frwd) {
++										if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
++										|| gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
++											!= gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] 
++										) {
++											good = 0; /* no symmetry - must be spurious */
++#if 0
++											fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)",
++												gei, gex,
++												i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2],
++												j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2],
++												gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] );
++#endif
++											break;
++										}
++									}
++									if(gex == gem) { /* oops, the other side is too short */
++										good = 0;
++#if 0
++										fprintf(stderr, " X");
++#endif
++									}
++									if(good && gei == ge) {
++										if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
++										!= isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
++											good = 0; /* oops, goes into another direction */
++#if 0
++											fprintf(stderr, " D");
++#endif
++										}
++									}
++								}
++								if(!good) { /* it is spurious, drop it */
++#if 0
++									fprintf(stderr, " %p: %s spurious start\n", ge, gxf_name[d]);
++#endif
++									f->len[d] = 0;
++									ges = ge->frwd;
++									len--;
++									X_FRAG(ges)->len[d] = len;
++								}
++							}
++
++							gei = gem->bkwd->bkwd->bkwd;
++							if( (gem->ix3 != gem->bkwd->ix3) /* gem->bkwd is vert */
++							^ (isign(gem->bkwd->ix3 - gei->ix3)==isign(gem->bkwd->iy3 - gei->iy3))
++							^ (d == GEXFI_CONVEX) /* clockwise */ ) {
++								
++#if 0
++								fprintf(stderr, " %p: %s potential spurious end\n", gem->bkwd, gxf_name[d]);
++#endif
++								/* the end may be a spurious entry */
++
++								gex = 0; /* the extremum closest to the end - to be found */
++								for(gei = gem->bkwd->bkwd; gei != ges->bkwd; gei = gei->bkwd) {
++									if(X_FRAG(gei)->flags & GEXFF_EXTR) {
++										gex = gei;
++										break;
++									}
++								}
++								if(gex == 0)
++									gex = ges; 
++
++								good = 1; /* assume that gem->bkwd is not spurious */
++								/* gei goes backwards, gex goes forwards from the extremum */
++								gei = gex;
++								/* i is the symmetry axis, j is the other axis (X=0 Y=1) */
++								i = (gex->ix3 != gex->bkwd->ix3);
++								j = !i;
++								for( ; gei!=ges->bkwd && gex!=gem->bkwd; gei=gei->bkwd, gex=gex->frwd) {
++									if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
++									|| gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
++										!= gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] 
++									) {
++										good = 0; /* no symmetry - must be spurious */
++#if 0
++										fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)",
++											gei, gex,
++											i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2],
++											j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2],
++											gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] );
++#endif
++										break;
++									}
++								}
++								if(gei == ges->bkwd) { /* oops, the other side is too short */
++									good = 0;
++#if 0
++									fprintf(stderr, " X");
++#endif
++								}
++								if(good && gex == gem->bkwd) {
++									if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
++									!= isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
++										good = 0; /* oops, goes into another direction */
++#if 0
++										fprintf(stderr, " D");
++#endif
++									}
++								}
++								if(!good) { /* it is spurious, drop it */
++#if 0
++									fprintf(stderr, " %p: %s spurious end\n", gem->bkwd, gxf_name[d]);
++#endif
++									X_FRAG(ges)->len[d] = --len;
++								}
++							}
++							if(len < 4) {
++								X_FRAG(ges)->len[d] = 0;
++#if 0
++								fprintf(stderr, " %p: %s frag discarded, too small now\n", ge, gxf_name[d]);
++#endif
++							}
++							if(ges != ge) {
++								if(ges == cge->next)
++									break; /* went around the loop */
++								else {
++									ge = ges->frwd; /* don't look at this fragment twice */
++									continue;
++								}
++							}
++						}
++
++						ge = ge->frwd;
++					} while(ge != cge->next);
++				}
++
++				/* Find the straight line fragments.
++				 * Even though the lines are sloped, they are called
++				 * "vertical" or "horizontal" according to their longer
++				 * dimension. All the steps in the shother dimension must 
++				 * be 1 pixel long, all the steps in the longer dimension
++				 * must be within the difference of 1 pixel.
++				 */
++				for(d = GEXFI_LINE; d<= GEXFI_EXACTLINE; d++) {
++					ge = cge->next;
++					pge = ge->bkwd; /* the beginning of the fragment */
++					count = 1;
++					delaystop = 0;
++					do {
++						int h;
++
++						stepmore = 0;
++						hdir = isign(ge->ix3 - ge->bkwd->ix3);
++						vdir = isign(ge->iy3 - ge->bkwd->iy3);
++						vert = (hdir == 0);
++						if(count==1) {
++							/* at this point pge==ge->bkwd */
++							/* account for the previous gentry, which was !vert */
++							if(!vert) { /* prev was vertical */
++								maxlen[0] = minlen[0] = 0;
++								maxlen[1] = minlen[1] = abs(pge->iy3 - pge->bkwd->iy3);
++								line[0] = (maxlen[1] == 1);
++								line[1] = 1;
++								fullhdir = hdir;
++								fullvdir = isign(pge->iy3 - pge->bkwd->iy3);
++							} else {
++								maxlen[0] = minlen[0] = abs(pge->ix3 - pge->bkwd->ix3);
++								maxlen[1] = minlen[1] = 0;
++								line[0] = 1;
++								line[1] = (maxlen[0] == 1);
++								fullhdir = isign(pge->ix3 - pge->bkwd->ix3);
++								fullvdir = vdir;
++							}
++						}
++						h = line[0]; /* remember the prevalent direction */
++#if 0
++						fprintf(stderr, "  %p: v=%d(%d) h=%d(%d) vl(%d,%d,%d) hl=(%d,%d,%d) %s count=%d ",
++							ge, vdir, fullvdir, hdir, fullhdir, 
++							line[1], minlen[1], maxlen[1],
++							line[0], minlen[0], maxlen[0],
++							gxf_name[d], count);
++#endif
++						if(vert) {
++							if(vdir != fullvdir)
++								line[0] = line[1] = 0;
++							len = abs(ge->iy3 - ge->bkwd->iy3);
++						} else {
++							if(hdir != fullhdir)
++								line[0] = line[1] = 0;
++							len = abs(ge->ix3 - ge->bkwd->ix3);
++						}
++#if 0
++						fprintf(stderr, "len=%d\n", len);
++#endif
++						if(len != 1) /* this is not a continuation in the short dimension */
++							line[!vert] = 0;
++
++						/* can it be a continuation in the long dimension ? */
++						if( line[vert] ) {
++							if(maxlen[vert]==0)
++								maxlen[vert] = minlen[vert] = len;
++							else if(maxlen[vert]==minlen[vert]) {
++								if(d == GEXFI_EXACTLINE) {
++									if(len != maxlen[vert])
++										line[vert] = 0; /* it can't */
++								} else if(len < maxlen[vert]) {
++									if(len < minlen[vert]-1)
++										line[vert] = 0; /* it can't */
++									else
++										minlen[vert] = len;
++								} else {
++									if(len > maxlen[vert]+1)
++										line[vert] = 0; /* it can't */
++									else
++										maxlen[vert] = len;
++								}
++							} else if(len < minlen[vert] || len > maxlen[vert])
++								line[vert] = 0; /* it can't */
++						}
++
++						if(line[0] == 0 && line[1] == 0) {
++#if 0
++							if(count >= 3)
++								fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
++#endif
++							X_FRAG(pge)->len[d] = count;
++							if(d == GEXFI_EXACTLINE && h) {
++								X_FRAG(pge)->flags |= GEXFF_HLINE;
++							}
++							if(count == 1)
++								pge = ge;
++							else {
++								stepmore = 1; /* may reconsider the 1st gentry */
++								pge = ge = ge->bkwd;
++								count = 1;
++							}
++						} else
++							count++;
++
++						ge = ge->frwd;
++						if(ge == cge->next && !stepmore)
++							delaystop = 1; /* consider the first gentry again */
++					} while(stepmore || ge != cge->next ^ delaystop);
++					/* see if there is an unfinished line left */
++					if(count != 1) {
++#if 0
++						if(count >= 3)
++							fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count);
++#endif
++						X_FRAG(ge->bkwd->bkwd)->len[d] = 0;
++						X_FRAG(pge)->len[d] = count;
++					}
++				}
++
++				/* do postprocessing of the lines */
++#if 0
++				fprintf(stderr, "Line postprocessing\n");
++				gex_dump_contour(cge->next, clen);
++#endif
++
++				/* the non-exact line frags are related to exact line frags sort 
++				 * of like to individual gentries: two kinds of exact frags
++				 * must be interleaved, with one kind having the size of 3
++				 * and the other kind having the size varying within +-2.
++				 */
++
++				ge = cge->next;
++				do {
++					GEX_FRAG *pf, *lastf1, *lastf2;
++					int len1, len2, fraglen;
++
++					f = X_FRAG(ge);
++
++					fraglen = f->len[GEXFI_LINE];
++					if(fraglen >= 4) {
++
++						vert = 0; /* vert is a pseudo-directon */
++						line[0] = line[1] = 1;
++						maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0;
++						lastf2 = lastf1 = f;
++						len2 = len1 = 0;
++						for(pge = ge, i = 1; i < fraglen; i++, pge=pge->frwd) {
++							pf = X_FRAG(pge);
++							len = pf->len[GEXFI_EXACTLINE];
++#if 0
++							fprintf(stderr, "      pge=%p i=%d of %d ge=%p exLen=%d\n", pge, i, 
++								f->len[GEXFI_LINE], ge, len);
++#endif
++							len1++; len2++;
++							if(len==0) {
++								continue;
++							}
++							vert = !vert; /* alternate the pseudo-direction */
++							if(len > 3)
++								line[!vert] = 0;
++							if(maxlen[vert] == 0)
++								maxlen[vert] = minlen[vert] = len;
++							else if(maxlen[vert]-2 >= len && minlen[vert]+2 <= len) {
++								if(len > maxlen[vert])
++									maxlen[vert] = len;
++								else if(len < minlen[vert])
++									minlen[vert] = len;
++							} else
++								line[vert] = 0;
++							if(line[0] == 0 && line[1] == 0) {
++#if 0
++								fprintf(stderr, "  Line breaks at %p %c(%d, %d) %c(%d, %d) len=%d fl=%d l2=%d l1=%d\n",
++									pge, (!vert)?'*':' ', minlen[0], maxlen[0], 
++									vert?'*':' ', minlen[1], maxlen[1], len, fraglen, len2, len1);
++#endif
++								if(lastf2 != lastf1) {
++									lastf2->len[GEXFI_LINE] = len2-len1;
++								}
++								lastf1->len[GEXFI_LINE] = len1+1;
++								pf->len[GEXFI_LINE] = fraglen+1 - i;
++#if 0
++								gex_dump_contour(pge, clen);
++#endif
++
++								/* continue with the line */
++								vert = 0; /* vert is a pseudo-directon */
++								line[0] = line[1] = 1;
++								maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0;
++								lastf2 = lastf1 = f;
++								len2 = len1 = 0;
++							} else {
++								lastf1 = pf;
++								len1 = 0;
++							}
++						}
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++#if 0
++				fprintf(stderr, "Line postprocessing part 2\n");
++				gex_dump_contour(cge->next, clen);
++#endif
++
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++
++					if(f->len[GEXFI_LINE] >= 4) {
++						len = f->len[GEXFI_EXACTLINE];
++						/* if a non-exact line covers precisely two exact lines,
++						 * split it
++						 */
++						if(len > 0 && f->len[GEXFI_LINE] >= len+1) {
++							GEX_FRAG *pf;
++							pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */
++							pf = X_FRAG(pge);
++							if(f->len[GEXFI_LINE] + 1 == len + pf->len[GEXFI_EXACTLINE]) {
++								f->len[GEXFI_LINE] = len;
++								f->flags |= GEXFF_SPLIT;
++								pf->len[GEXFI_LINE] = pf->len[GEXFI_EXACTLINE];
++								pf->flags |= GEXFF_SPLIT;
++							}
++						}
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++#if 0
++				fprintf(stderr, "Line postprocessing part 2a\n");
++				gex_dump_contour(cge->next, clen);
++#endif
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++
++					/* too small lines are of no interest */
++					if( (f->flags & GEXFF_SPLIT)==0 && f->len[GEXFI_LINE] < 4)
++						f->len[GEXFI_LINE] = 0;
++
++					len = f->len[GEXFI_EXACTLINE];
++					/* too small exact lines are of no interest */
++					if(len < 3) /* exact lines may be shorter */
++						f->len[GEXFI_EXACTLINE] = 0;
++					/* get rid of inexact additions to the end of the exact lines */
++					else if(f->len[GEXFI_LINE] == len+1)
++						f->len[GEXFI_LINE] = len;
++					/* same at the beginning */
++					else {
++						int diff = X_FRAG(ge->bkwd)->len[GEXFI_LINE] - len;
++
++						if(diff == 1 || diff == 2) {
++							X_FRAG(ge->bkwd)->len[GEXFI_LINE] = 0;
++							f->len[GEXFI_LINE] = len;
++						}
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++#if 0
++				fprintf(stderr, "Line postprocessing is completed\n");
++				gex_dump_contour(cge->next, clen);
++#endif
++
++				gex_calc_lenback(cge->next, clen); /* prepare data */
++
++				/* resolve conflicts between lines and curves */
++
++				/*
++				 * the short (3-gentry) curve frags must have one of the ends
++				 * coinciding with another curve frag of the same type
++				 */
++
++				for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++					ge = cge->next;
++					do {
++						f = X_FRAG(ge);
++
++						if(f->len[d] == 3) {
++							pge = age[(f->aidx + 2)%clen]; /* last gentry of this frag */
++							if(f->lenback[d] == 0 && X_FRAG(pge)->len[d] == 0) {
++								fprintf(stderr, "    discarded small %s at %p-%p\n", gxf_name[d], ge, pge);
++								f->len[d] = 0;
++								X_FRAG(ge->frwd)->lenback[d] = 0;
++								X_FRAG(ge->frwd->frwd)->lenback[d] = 0;
++							}
++						}
++						ge = ge->frwd;
++					} while(ge != cge->next);
++				}
++
++				/* the serifs take priority over everything else */
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++
++					len = f->len[GEXFI_SERIF];
++					if(len == 0)
++						continue;
++
++					if(len != 2) { /* this is used in the code below */
++						fprintf(stderr, "Internal error at %s line %d: serif frags len is %d\n",
++							__FILE__, __LINE__, len);
++						exit(1);
++					}
++
++					for(d = 0; d < GEXFI_SERIF; d++) {
++						/* serifs may not have common ends with the other fragments,
++						 * this is expressed as extending them by 1 gentry on each side
++						 */
++						frag_subtract(g, age, clen, ge->bkwd, len+2, d);
++					}
++				} while( (ge = ge->frwd) != cge->next);
++
++				/*
++				 * longer exact lines take priority over curves; shorter lines
++				 * and inexact lines are resolved with convex/concave conflicts
++				 */
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++
++					len = f->len[GEXFI_EXACTLINE]; 
++
++					if(len < 6) { /* line is short */
++						ge = ge->frwd;
++						continue;
++					}
++
++					fprintf(stderr, "   line at %p len=%d\n", ge, f->len[GEXFI_EXACTLINE]);
++					for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++						frag_subtract(g, age, clen, ge, len, d);
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++
++				/*
++				 * The exact lines take priority over curves that coincide
++				 * with them or extend by only one gentry on either side
++				 * (but not both sides). By this time it applies only to the
++				 * small exact lines.
++				 *
++				 * An interesting general case is when a curve matches more
++				 * than one exact line going diamond-like.
++				 */
++
++				ge = cge->next;
++				do {
++					int done, len2;
++					int sharpness;
++					GEX_FRAG *pf;
++
++					f = X_FRAG(ge);
++
++					/* "sharpness" shows how a group of exact line frags is connected: if the gentries 
++					 * of some of them overlap, the curve matching requirement is loosened: it may
++					 * extend up to 1 gentry beyond each end of the group of exact line frags
++					 * (sharpness=2); otherwise it may extend to only one end (sharpness=1)
++					 */
++					sharpness = 1;
++
++					len = f->len[GEXFI_EXACTLINE];
++					if(len >= 4) {
++						while(len < clen) {
++							done = 0;
++							pf = X_FRAG(ge->bkwd);
++							for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++								if(f->len[d] == len || f->len[d] == len+1) {
++
++									fprintf(stderr, "    removed %s frag at %p len=%d linelen=%d\n", 
++										gxf_name[d], ge, f->len[d], len);
++									pge = ge->frwd;
++									for(i = f->len[d]; i > 1; i--, pge = pge->frwd)
++										X_FRAG(pge)->lenback[d] = 0;
++									f->len[d] = 0;
++									gex_dump_contour(ge, clen);
++									done = 1;
++								} else if(pf->len[d] == len+1 || pf->len[d] == len+sharpness) {
++									fprintf(stderr, "    removed %s frag at %p len=%d next linelen=%d\n", 
++										gxf_name[d], ge->bkwd, pf->len[d], len);
++									pge = ge;
++									for(i = pf->len[d]; i > 1; i--, pge = pge->frwd)
++										X_FRAG(pge)->lenback[d] = 0;
++									pf->len[d] = 0;
++									gex_dump_contour(ge, clen);
++									done = 1;
++								}
++							}
++							if(done)
++								break;
++
++							/* is there any chance to match a sequence of exect lines ? */
++							if(f->len[GEXFI_CONVEX] < len && f->len[GEXFI_CONCAVE] < len
++							&& pf->len[GEXFI_CONVEX] < len && pf->len[GEXFI_CONCAVE] < len)
++								break;
++
++							done = 1;
++							/* check whether the line is connected to another exact line at an extremum */
++							pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */
++							len2 = X_FRAG(pge)->len[GEXFI_EXACTLINE];
++							if(len2 > 0) {
++								if( len2 >= 4 && (X_FRAG(pge)->flags & GEXFF_EXTR) ) {
++									len += len2 - 1;
++									sharpness = 2;
++									done = 0;
++								}
++							} else {
++								/* see if the extremum is between two exact lines */
++								pge = pge->frwd;
++								if(X_FRAG(pge)->flags & GEXFF_EXTR) {
++									pge = pge->frwd;
++									len2 = X_FRAG(pge)->len[GEXFI_EXACTLINE];
++									if(len2 >= 4) {
++										len += len2 + 1;
++										done = 0;
++									}
++								}
++							}
++							if(done)
++								break;
++						}
++					}
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++
++				/* 
++				 * The lines may cover only whole curves (or otherwise empty space),
++				 * so cut them where they overlap parts of the curves. If 2 or less
++				 * gentries are left in the line, remove the line.
++				 * If a line and a curve fully coincide, remove the line.  Otherwise 
++				 * remove the curves that are completely covered by the lines.
++				 */
++
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++
++				reconsider_line:
++					len = f->len[GEXFI_LINE];
++
++					if(len == 0) {
++						ge = ge->frwd;
++						continue;
++					}
++
++					if(f->len[GEXFI_CONVEX] >= len 
++					|| f->len[GEXFI_CONCAVE] >= len) {
++				line_completely_covered:
++						fprintf(stderr, "    removed covered Line frag at %p len=%d\n", 
++							ge, len);
++						f->len[GEXFI_LINE] = 0;
++						for(pge = ge->frwd; len > 1; len--, pge = pge->frwd)
++							X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
++						gex_dump_contour(ge, clen);
++						ge = ge->frwd;
++						continue;
++					}
++					
++					k1 = 0; /* how much to cut at the front */
++					for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++						if(f->lenback[d]) {
++							pge = age[(f->aidx + clen - f->lenback[d])%clen];
++							i = X_FRAG(pge)->len[d] - f->lenback[d] - 1;
++							if(i > k1)
++								k1 = i;
++						}
++					}
++
++					k2 = 0; /* how much to cut at the end */
++					pge = age[(f->aidx + len)%clen]; /* gentry after the end */
++					for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++						i = X_FRAG(pge)->lenback[d] - 1;
++						if(i > k2)
++							k2 = i;
++					}
++
++					if(k1+k2 > 0 && k1+k2 >= len-3) {
++						fprintf(stderr, "    k1=%d k2=%d\n", k1, k2);
++						goto line_completely_covered;
++					}
++
++
++					if(k2 != 0) { /* cut the end */
++						len -= k2;
++						f->len[GEXFI_LINE] = len;
++						/* pge still points after the end */
++						for(i = k2, pge = pge->bkwd; i > 0; i--, pge = pge->bkwd)
++							X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
++					}
++					if(k1 != 0) { /* cut the beginning */
++						len -= k1;
++						f->len[GEXFI_LINE] = 0;
++						for(i = 1, pge = ge->frwd; i < k1; i++, pge = pge->frwd)
++							X_FRAG(pge)->lenback[GEXFI_LINE] = 0;
++						X_FRAG(pge)->len[GEXFI_LINE] = len;
++						for(i = 0; i < len; i++, pge = pge->frwd)
++							X_FRAG(pge)->lenback[GEXFI_LINE] = i;
++					}
++					if(k1 != 0 || k2 != 0) {
++						fprintf(stderr, "    cut Line frag at %p by (%d,%d) to len=%d\n", 
++							ge, k1, k2, len);
++						gex_dump_contour(ge, clen);
++
++						goto reconsider_line; /* the line may have to be cut again */
++					}
++					pge = age[(f->aidx + k1)%clen]; /* new beginning */
++					good = 1; /* flag: no need do do a debugging dump */
++					for(i=1; i<len; i++, pge = pge->frwd)
++						for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++							if(X_FRAG(pge)->len[d]) {
++								fprintf(stderr, "    removed %s frag at %p len=%d covered by line\n", 
++									gxf_name[d], pge, X_FRAG(pge)->len[d], len);
++								good = 0;
++							}
++							X_FRAG(pge)->len[d] = 0;
++						}
++					pge = age[(f->aidx + k1 + 1)%clen]; /* next after new beginning */
++					for(i=1; i<len; i++, pge = pge->frwd)
++						for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++)
++							X_FRAG(pge)->lenback[d] = 0;
++					if(!good)
++						gex_dump_contour(ge, clen);
++
++					ge = ge->frwd;
++				} while(ge != cge->next);
++
++				/* Resolve conflicts between curves */
++				for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) {
++					dx = (GEXFI_CONVEX + GEXFI_CONCAVE) - d; /* the other type */
++					ge = cge->next;
++					do {
++						GENTRY *sge;
++
++						f = X_FRAG(ge);
++						len = f->len[d];
++						if(len < 2) {
++							ge = ge->frwd;
++							continue;
++						}
++						sge = ge; /* the start of fragment */
++
++						i = f->len[dx];
++						if(i != 0) { /* two curved frags starting here */
++							/* should be i!=len because otherwise they would be
++							 * covered by an exact line
++							 */
++							if(i > len) {
++							curve_completely_covered:
++								/* remove the convex frag */
++								fprintf(stderr, "    removed %s frag at %p len=%d covered by %s\n", 
++									gxf_name[d], ge, len, gxf_name[dx]);
++								f->len[d] = 0;
++								for(pge = ge->frwd, j = 1; j < len; j++, pge = pge->frwd)
++									X_FRAG(pge)->lenback[d] = 0;
++								gex_dump_contour(ge, clen);
++
++								ge = ge->frwd; /* the frag is gone, nothing more to do */
++								continue;
++							} else {
++								/* remove the concave frag */
++								fprintf(stderr, "    removed %s frag at %p len=%d covered by %s\n", 
++									gxf_name[dx], ge, i, gxf_name[d]);
++								f->len[dx] = 0;
++								for(pge = ge->frwd, j = 1; j < i; j++, pge = pge->frwd)
++									X_FRAG(pge)->lenback[dx] = 0;
++								gex_dump_contour(ge, clen);
++							}
++						}
++
++
++						k1 = X_FRAG(ge->frwd)->lenback[dx];
++						if(k1 != 0) { /* conflict at the front */
++							GENTRY *gels, *gele, *gei;
++
++							pge = age[(f->aidx + clen - (k1-1))%clen]; /* first gentry of concave frag */
++							k2 = X_FRAG(pge)->len[dx]; /* its length */
++							
++							i = k2 - (k1-1); /* amount of overlap */
++							if(i > len)
++								i = len;
++							/* i >= 2 by definition */
++							if(i >= k2-1) { /* covers the other frag - maybe with 1 gentry showing */
++								fprintf(stderr, "    removed %s frag at %p len=%d covered by %s\n", 
++									gxf_name[dx], pge, k2, gxf_name[d]);
++								X_FRAG(pge)->len[dx] = 0;
++								for(pge = pge->frwd, j = 1; j < k2; j++, pge = pge->frwd)
++									X_FRAG(pge)->lenback[dx] = 0;
++								if(i >= len-1) { /* covers our frag too - maybe with 1 gentry showing */
++									/* our frag will be removed as well, prepare a line to replace it */
++									gels = ge;
++									gele = age[(f->aidx + i - 1)%clen];
++									fprintf(stderr, "    new Line frag at %p-%p len=%d\n", gels, gele, i);
++									X_FRAG(gels)->len[GEXFI_LINE] = i;
++									for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++)
++										X_FRAG(gei)->lenback[GEXFI_LINE] = j;
++								} else {
++									gex_dump_contour(ge, clen);
++									ge = ge->frwd;
++									continue;
++								}
++							}
++							if(i >= len-1) /* covers our frag - maybe with 1 gentry showing */
++								goto curve_completely_covered;
++
++							/* XXX need to do something better for the case when a curve frag
++							 * is actually nothing but an artifact of two other curves of
++							 * the opposite type touching each other, like on the back of "3"
++							 */
++
++							/* change the overlapping part to a line */
++							gels = ge;
++							gele = age[(f->aidx + i - 1)%clen];
++							/* give preference to local extremums */
++							if(X_FRAG(gels)->flags & GEXFF_EXTR) {
++								gels = gels->frwd;
++								i--;
++							}
++							if(X_FRAG(gele)->flags & GEXFF_EXTR) {
++								gele = gele->bkwd;
++								i--;
++							}
++							if(gels->bkwd == gele) { 
++								/* Oops the line became negative.  Probably should 
++								 * never happen but I can't think of any formal reasoning
++								 * leading to that, so check just in case. Restore
++								 * the previous state.
++								 */
++								gels = gele; gele = gels->frwd; i = 2;
++							}
++
++							j = X_FRAG(gels)->lenback[dx] + 1; /* new length */
++							if(j != k2) {
++								X_FRAG(pge)->len[dx] = j;
++								fprintf(stderr, "    cut %s frag at %p len=%d to %p len=%d end overlap with %s\n", 
++									gxf_name[dx], pge, k2, gels, j, gxf_name[d]);
++								for(gei = gels->frwd; j < k2; gei = gei->frwd, j++)
++									X_FRAG(gei)->lenback[dx] = 0;
++							}
++
++							if(gele != ge) {
++								sge = gele;
++								f->len[d] = 0;
++								fprintf(stderr, "    cut %s frag at %p len=%d ", gxf_name[d], ge, len);
++								len--;
++								for(gei = ge->frwd; gei != gele; gei = gei->frwd, len--)
++									X_FRAG(gei)->lenback[d] = 0;
++								X_FRAG(gele)->len[d] = len;
++								X_FRAG(gele)->lenback[d] = 0;
++								fprintf(stderr, "to %p len=%d start overlap with %s\n", 
++									sge, len, gxf_name[dx]);
++								for(gei = gei->frwd, j = 1; j < len; gei = gei->frwd, j++)
++									X_FRAG(gei)->lenback[d] = j;
++
++							}
++							if(i > 1) {
++								fprintf(stderr, "    new Line frag at %p-%p len=%d\n", gels, gele, i);
++								X_FRAG(gels)->len[GEXFI_LINE] = i;
++								for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++)
++									X_FRAG(gei)->lenback[GEXFI_LINE] = j;
++							}
++							gex_dump_contour(ge, clen);
++						}
++
++						ge = ge->frwd;
++					} while(ge != cge->next);
++				}
++
++				/* 
++				 * Assert that there are no conflicts any more and
++				 * for each gentry find the fragment types that start
++				 * and continue here.
++				 */
++				ge = cge->next;
++				do {
++					f = X_FRAG(ge);
++					dx = GEXFI_NONE; /* type that starts here */
++					dy = GEXFI_NONE; /* type that goes through here */
++					/* GEXFI_EXACTLINE and GEXFI_SERIF are auxiliary and don't
++					 * generate any actual lines/curves in the result
++					 */
++					for(d = GEXFI_CONVEX; d<= GEXFI_LINE; d++) {
++						if(f->len[d]) {
++							if(dx >= 0) {
++								fprintf(stderr, "**** Internal error in vectorization\n");
++								fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n",
++									g->name, ge, gxf_name[dx], gxf_name[d]);
++								dumppaths(g, cge->next, cge->next->bkwd);
++								gex_dump_contour(ge, clen);
++								exit(1);
++							}
++							dx = d;
++						}
++						if(f->lenback[d]) {
++							if(dy >= 0) {
++								fprintf(stderr, "**** Internal error in vectorization\n");
++								fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n",
++									g->name, ge, gxf_name[dy], gxf_name[d]);
++								dumppaths(g, cge->next, cge->next->bkwd);
++								gex_dump_contour(ge, clen);
++								exit(1);
++							}
++							dy = d;
++						}
++					}
++					f->ixstart = dx;
++					f->ixcont = dy;
++					ge = ge->frwd;
++				} while(ge != cge->next);
++
++				/*
++				 * make sure that the contour does not start in the
++				 * middle of a fragment
++				 */
++				ge = cge->next; /* old start of the contour */
++				f = X_FRAG(ge);
++				if(f->ixstart == GEXFI_NONE && f->ixcont != GEXFI_NONE) {
++					/* oops, it's mid-fragment, move the start */
++					GENTRY *xge;
++
++					xge = ge->bkwd->next; /* entry following the contour */
++
++					/* find the first gentry of this frag */
++					pge = age[(f->aidx + clen - f->lenback[f->ixcont])%clen]; 
++
++					ge->prev = ge->bkwd; 
++					ge->bkwd->next = ge;
++
++					cge->next = pge;
++					pge->prev = cge;
++
++					pge->bkwd->next = xge;
++					if(xge) 
++						xge->prev = pge->bkwd;
++
++					cge->ix3 = pge->bkwd->ix3; cge->iy3 = pge->bkwd->iy3;
++				}
++
++				/* vectorize each fragment separately 
++				 * make 2 passes: first handle the straight lines, then
++				 * the curves to allow the curver to be connected smoothly
++				 * to the straights
++				 */
++				ge = cge->next;
++				do { /* pass 1 */
++					f = X_FRAG(ge);
++					switch(f->ixstart) {
++					case GEXFI_LINE:
++						len = f->len[GEXFI_LINE];
++						pge = age[(f->aidx + len - 1)%clen]; /* last gentry */
++
++						if(ge->iy3 == ge->bkwd->iy3) { /* frag starts and ends horizontally */
++							k1 = 1/*Y*/ ; /* across the direction of start */
++							k2 = 0/*X*/ ; /* along the direction of start */
++						} else { /* frag starts and ends vertically */
++							k1 = 0/*X*/ ; /* across the direction of start */
++							k2 = 1/*Y*/ ; /* along the direction of start */
++						}
++
++						if(len % 2) {
++							/* odd number of entries in the frag */
++							double halfstep, halfend;
++
++							f->vect[0][k1] = fscale * ge->ipoints[k1][2];
++							f->vect[3][k1] = fscale * pge->ipoints[k1][2];
++
++							halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) 
++								* 0.5 / ((len+1)/2);
++							if(f->ixcont != GEXFI_NONE) {
++								halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5;
++								if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
++									halfstep = halfend;
++							}
++							if(X_FRAG(pge)->ixstart != GEXFI_NONE) {
++								halfend = (pge->ipoints[k2][2] - pge->bkwd->ipoints[k2][2]) * 0.5;
++								if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
++									halfstep = halfend;
++							}
++							f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep);
++							f->vect[3][k2] = fscale * (pge->ipoints[k2][2] - halfstep);
++						} else {
++							/* even number of entries */
++							double halfstep, halfend;
++
++							f->vect[0][k1] = fscale * ge->ipoints[k1][2];
++							halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) 
++								* 0.5 / (len/2);
++							if(f->ixcont != GEXFI_NONE) {
++								halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5;
++								if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
++									halfstep = halfend;
++							}
++							f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep);
++
++							halfstep = (pge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) 
++								* 0.5 / (len/2);
++							if(X_FRAG(pge)->ixstart != GEXFI_NONE) {
++								halfend = (pge->ipoints[k1][2] - pge->bkwd->ipoints[k1][2]) * 0.5;
++								if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */
++									halfstep = halfend;
++							}
++							f->vect[3][k1] = fscale * (pge->ipoints[k1][2] - halfstep);
++							f->vect[3][k2] = fscale * pge->ipoints[k2][2];
++						}
++						f->vectlen = len;
++						f->flags |= GEXFF_DRAWLINE;
++						break;
++					}
++				} while((ge = ge->frwd) != cge->next);
++
++				ge = cge->next;
++				do { /* pass 2 */
++					/* data for curves */
++					GENTRY *firstge, *lastge, *gef, *gel, *gei, *gex;
++					GENTRY *ordhd; /* head of the order list */
++					GENTRY **ordlast;
++					int nsub; /* number of subfrags */
++					GEX_FRAG *ff, *lf, *xf;
++
++					f = X_FRAG(ge);
++					switch(f->ixstart) {
++					case GEXFI_CONVEX:
++					case GEXFI_CONCAVE:
++						len = f->len[f->ixstart];
++						firstge = ge;
++						lastge = age[(f->aidx + len - 1)%clen]; /* last gentry */
++
++						nsub = 0;
++						gex = firstge;
++						xf = X_FRAG(gex);
++						xf->prevsub = 0;
++						xf->sublen = 1;
++						xf->flags &= ~GEXFF_DONE;
++						for(gei = firstge->frwd; gei != lastge; gei = gei->frwd) {
++							xf->sublen++;
++							if(X_FRAG(gei)->flags & GEXFF_EXTR) {
++									xf->nextsub = gei;
++									for(i=0; i<2; i++)
++										xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]);
++									nsub++;
++									xf = X_FRAG(gei);
++									xf->prevsub = gex;
++									xf->sublen = 1;
++									xf->flags &= ~GEXFF_DONE;
++									gex = gei;
++								}
++						}
++						xf->sublen++;
++						xf->nextsub = gei;
++						for(i=0; i<2; i++)
++							xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]);
++						nsub++;
++						ff = xf; /* remember the beginning of the last subfrag */
++						xf = X_FRAG(gei);
++						xf->prevsub = gex;
++						if(firstge != lastge) {
++							xf->nextsub = 0;
++							xf->sublen = 0;
++
++							/* correct the bounding box of the last and first subfrags for
++							 * intersections with other fragments 
++							 */
++							if(xf->ixstart != GEXFI_NONE) {
++								/* ff points to the beginning of the last subfrag */
++								for(i=0; i<2; i++)
++									ff->bbox[i] -= 0.5 * abs(lastge->ipoints[i][2] - lastge->bkwd->ipoints[i][2]);
++							}
++							ff = X_FRAG(firstge);
++							if(ff->ixcont != GEXFI_NONE) {
++								for(i=0; i<2; i++)
++									ff->bbox[i] -= 0.5 * abs(firstge->ipoints[i][2] - firstge->bkwd->ipoints[i][2]);
++							}
++						}
++
++						fprintf(stderr, " %s frag %p%s nsub=%d\n", gxf_name[f->ixstart],
++							ge, (f->flags&GEXFF_CIRC)?" circular":"", nsub);
++
++						/* find the symmetry between the subfragments */
++						for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
++							ff = X_FRAG(gef);
++							gex = ff->nextsub;
++							xf = X_FRAG(gex);
++							gel = xf->nextsub;
++							if(gel == 0) {
++								ff->flags &= ~GEXFF_SYMNEXT;
++								break; /* not a circular frag */
++							}
++							good = 1; /* assume that we have symmetry */
++							/* gei goes backwards, gex goes forwards from the extremum */
++							gei = gex;
++							/* i is the symmetry axis, j is the other axis (X=0 Y=1) */
++							ff->symaxis = i = (gex->ix3 != gex->bkwd->ix3);
++							j = !i;
++							for( ; gei!=gef && gex!=gel; gei=gei->bkwd, gex=gex->frwd) {
++								if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2]
++								|| gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]
++									!= gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] 
++								) {
++									good = 0; /* no symmetry */
++									break;
++								}
++							}
++							if(good) {
++								if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2])
++								!= isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) {
++									good = 0; /* oops, goes into another direction */
++								}
++							}
++							if(good)
++								ff->flags |= GEXFF_SYMNEXT;
++							else
++								ff->flags &= ~GEXFF_SYMNEXT;
++						}
++
++						for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
++							ff = X_FRAG(gef);
++							if((ff->flags & GEXFF_SYMNEXT)==0) {
++								ff->symxlen = 0;
++								continue;
++							}
++							gex = ff->prevsub;
++							if(gex == 0 || (X_FRAG(gex)->flags & GEXFF_SYMNEXT)==0) {
++								ff->symxlen = 0;
++								continue;
++							}
++							ff->symxlen = X_FRAG(gex)->sublen;
++							xf = X_FRAG(ff->nextsub);
++							if(xf->sublen < ff->symxlen)
++								ff->symxlen = xf->sublen;
++						}
++
++						/* find the symmetry inside the subfragments */
++						for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
++							ff = X_FRAG(gef);
++
++							if(ff->sublen % 2) {
++								/* we must have an even number of gentries for diagonal symmetry */
++								ff->symge = 0;
++								continue;
++							}
++
++							/* gei goes forwards from the front */
++							gei = gef->frwd;
++							/* gex goes backwards from the back */
++							gex = ff->nextsub->bkwd;
++
++							/* i is the direction of gei, j is the direction of gex */
++							i = (gei->iy3 != gei->bkwd->iy3);
++							j = !i;
++							for( ; gei->bkwd != gex; gei=gei->frwd, gex=gex->bkwd) {
++								if( abs(gei->bkwd->ipoints[i][2] - gei->ipoints[i][2])
++								!= abs(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) )
++									break; /* no symmetry */
++								i = j;
++								j = !j;
++							}
++							if(gei->bkwd == gex)
++								ff->symge = gex;
++							else
++								ff->symge = 0; /* no symmetry */
++						}
++
++						/* find the order of calculation:
++						 * prefer to start from long fragments that have the longest
++						 * neighbours symmetric with them, with all being equal prefer
++						 * the fragments that have smaller physical size
++						 */
++						ordhd = 0;
++						for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) {
++							ff = X_FRAG(gef);
++
++							for(ordlast = &ordhd; *ordlast != 0; ordlast = &xf->ordersub) {
++								xf = X_FRAG(*ordlast);
++								if(ff->sublen > xf->sublen)
++									break;
++								if(ff->sublen < xf->sublen)
++									continue;
++								if(ff->symxlen > xf->symxlen)
++									break;
++								if(ff->symxlen < xf->symxlen)
++									continue;
++								if(ff->bbox[0] < xf->bbox[0] || ff->bbox[1] < xf->bbox[1])
++									break;
++							}
++
++							ff->ordersub = *ordlast;
++							*ordlast = gef;
++						}
++
++						/* vectorize the subfragments */
++						for(gef = ordhd; gef != 0; gef = ff->ordersub) {
++
++							/* debugging stuff */
++							ff = X_FRAG(gef);
++							fprintf(stderr, "   %p-%p bbox[%g,%g] sym=%p %s len=%d xlen=%d\n",
++								gef, ff->nextsub, ff->bbox[0], ff->bbox[1], ff->symge, 
++								(ff->flags & GEXFF_SYMNEXT) ? "symnext" : "",
++								ff->sublen, ff->symxlen);
++
++							dosubfrag(g, f->ixstart, firstge, gef, fscale);
++						}
++
++						break;
++					}
++				} while((ge = ge->frwd) != cge->next);
++
++				free(age);
++
++			}
++
++		}
++
++		/* all the fragments are found, extract the vectorization */
++		pge = g->entries;
++		g->entries = g->lastentry = 0;
++		g->flags |= GF_FLOAT;
++		loopge = 0;
++		skip = 0;
++
++		for(ge = pge; ge != 0; ge = ge->next) {
++			GEX_FRAG *f, *pf;
++
++			switch(ge->type) {
++			case GE_LINE:
++				f = X_FRAG(ge);
++				if(skip == 0) {
++					if(f->flags & (GEXFF_DRAWLINE|GEXFF_DRAWCURVE)) {
++						/* draw a line to the start point */
++						fg_rlineto(g, f->vect[0][0], f->vect[0][1]);
++						/* draw the fragment */
++						if(f->flags & GEXFF_DRAWCURVE)
++							fg_rrcurveto(g, 
++								f->vect[1][0], f->vect[1][1],
++								f->vect[2][0], f->vect[2][1],
++								f->vect[3][0], f->vect[3][1]);
++						else
++							fg_rlineto(g, f->vect[3][0], f->vect[3][1]);
++						skip = f->vectlen - 2;
++					} else {
++						fg_rlineto(g, fscale * ge->ix3, fscale * ge->iy3);
++					}
++				} else
++					skip--;
++				break;
++			case GE_MOVE:
++				fg_rmoveto(g, -1e6, -1e6); /* will be fixed by GE_PATH */
++				skip = 0;
++				/* remember the reference to update it later */
++				loopge = g->lastentry;
++				break;
++			case GE_PATH:
++				/* update the first MOVE of this contour */
++				if(loopge) {
++					loopge->fx3 = g->lastentry->fx3;
++					loopge->fy3 = g->lastentry->fy3;
++					loopge = 0;
++				}
++				g_closepath(g);
++				break;
++			}
++		}
++		for(ge = pge; ge != 0; ge = cge) {
++			cge = ge->next;
++			free(ge->ext);
++			free(ge);
++		}
++		dumppaths(g, NULL, NULL);
++		
++		/* end of vectorization logic */
++	} else {
++		/* convert the data to float */
++		GENTRY *ge;
++		double x, y;
++
++		for(ge = g->entries; ge != 0; ge = ge->next) {
++			ge->flags |= GEF_FLOAT;
++			if(ge->type != GE_MOVE && ge->type != GE_LINE) 
++				continue;
++
++			x = fscale * ge->ix3;
++			y = fscale * ge->iy3;
++
++			ge->fx3 = x;
++			ge->fy3 = y;
++		}
++		g->flags |= GF_FLOAT;
++	}
++
++	free(hlm); free(vlm); free(amp);
++}
++
++#if 0
++/* print out the bitmap */
++printbmap(bmap, xsz, ysz, xoff, yoff)
++	char *bmap;
++	int xsz, ysz, xoff, yoff;
++{
++	int x, y;
++
++	for(y=ysz-1; y>=0; y--) {
++		putchar( (y%10==0) ? y/10+'0' : ' ' );
++		putchar( y%10+'0' );
++		for(x=0; x<xsz; x++)
++			putchar( bmap[y*xsz+x] ? 'X' : '.' );
++		if(-yoff==y)
++			putchar('_'); /* mark the baseline */
++		putchar('\n');
++	}
++	putchar(' '); putchar(' ');
++	for(x=0; x<xsz; x++)
++		putchar( x%10+'0' );
++	putchar('\n'); putchar(' '); putchar(' ');
++	for(x=0; x<xsz; x++)
++		putchar( (x%10==0) ? x/10+'0' : ' ' );
++	putchar('\n');
++}
++
++/* print out the limits of outlines */
++printlimits(hlm, vlm, amp, xsz, ysz)
++	char *hlm, *vlm, *amp;
++	int xsz, ysz;
++{
++	int x, y;
++	static char h_char[]={ ' ', '~', '^' };
++	static char v_char[]={ ' ', '(', ')' };
++
++	for(y=ysz-1; y>=0; y--) {
++		for(x=0; x<xsz; x++) {
++			if(amp[y*xsz+x])
++				putchar('!'); /* ambigouos point is always on a limit */
++			else
++				putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]);
++			putchar(h_char[ hlm[(y+1)*xsz+x] & (L_ON|L_OFF) ]);
++		}
++		putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]);
++		putchar('\n');
++	}
++	/* last line */
++	for(x=0; x<xsz; x++) {
++		putchar(' ');
++		putchar(h_char[ hlm[x] & (L_ON|L_OFF) ]);
++	}
++	putchar(' ');
++	putchar('\n');
++}
++#endif /* 0 */
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/byteorder.h xserver/hw/xprint/extras/ttf2pt1/byteorder.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/byteorder.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/byteorder.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,24 @@
++/*
++ * see COPYRIGHT
++ */
++
++/*	This defines the macroes ntohs and ntohl, which convert short and long
++	ints from network order (used on 68000 chips, and in TrueType font
++	files) to whatever order your computer uses. #define _BIG_ENDIAN or not
++	to control which set of definitions apply. If you don't know, try both. If
++	you have a peculiar machine you're on your own.
++*/
++
++#if defined(_BIG_ENDIAN)
++#define	ntohl(x)	(x)
++#define	ntohs(x)	(x)
++#else
++#define ntohs(x) \
++    ((USHORT)((((USHORT)(x) & 0x00ff) << 8) | \
++              (((USHORT)(x) & 0xff00) >> 8))) 
++#define ntohl(x) \
++    ((ULONG)((((ULONG)(x) & 0x000000ffU) << 24) | \
++             (((ULONG)(x) & 0x0000ff00U) <<  8) | \
++             (((ULONG)(x) & 0x00ff0000U) >>  8) | \
++             (((ULONG)(x) & 0xff000000U) >> 24)))  
++#endif
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/CHANGES.html xserver/hw/xprint/extras/ttf2pt1/CHANGES.html
+--- xserver-old/hw/xprint/extras/ttf2pt1/CHANGES.html	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/CHANGES.html	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,805 @@
++<HTML>
++<HEAD>
++<TITLE>
++TTF2PT1 -  CHANGES history
++</TITLE>
++</HEAD>
++<BODY>
++<H2>
++TTF2PT1 -  CHANGES history
++</H2>
++
++<! 
++(Do not edit this file, it is generated from CHANGES.html!!!)
++>
++
++<H4>
++3.4.4-SNAP-030526
++</H4>
++<!
++-------
++>
++
++<b>New features:</b>
++<ul>
++<li> Improved the auto-vectoring (-OV) alrogithm.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fix to build all the features on Windows MS C++, by Tomoo Amano.
++</ul>
++
++<H4>
++3.4.3 -- December 2, 2002
++</H4>
++<!
++-------
++>
++
++<b>New features:</b>
++<ul>
++<li> <tt>scripts/forceiso</tt> got an optional argument to select the
++  format of the names for glyphs without standard Latin-1 names.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Changed the glyph names in scripts/forceiso to match those in ttf2pt1.
++<li> Included the missing directory app/TeX.
++</ul>
++
++<H4>
++3.4.2 -- August 30, 2002
++</H4>
++<!
++-------
++>
++
++<b>New features:</b>
++<ul>
++<li> New map for T2A_compat encoding (for Cyrillic LaTeX) by Mikhail
++  Umorin.
++<li> Scripts supporting font conversion for CJK-LaTeX, by Mike Fabian
++  from SuSE.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Explicit owner/group/permissions are used to install directories.
++<li> In scripts/convert fixed the addition of encoding name to the font 
++  name for the external encoding maps, was missing "/" at the start.
++<li> Fixed the divergence between two copies of UniqueID.
++<li> Fixed the recovery after defective empty contours.
++</ul>
++
++<H4>
++3.4.1 -- June 13, 2002
++</H4>
++<!
++-------
++>
++
++<b>New features:</b>
++<ul>
++<li> Added Autotrace support for the bitmap fonts (-OZ). It's horrible.
++<li> Added vectorization of bitmap fonts (-OV) - functionally the same thing as 
++  autotrace but home-grown. Works mostly decently but still with large
++  space for impprovement.
++<li> Relaxed the conditions for warnings about long glyphs.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fix by Rob Kolstad for a crash in the new outline smoothing
++  code (on small thin contours) and diagnostic for another crash.
++<li> Fix by Holger Huesing for a crash on degenerate contours.
++<li> Fix for bitmaps of zero dimensions.
++<li> The BDF reader does not fail on redefintion of the properties.
++<li> Fix for reading of BDF glyphs with 0 size.
++<li> Fix for a hang when guessing the boldness of some fonts.
++<li> Fix by Adriano Konzen for scaling coefficients in composite glyphs.
++</ul>
++
++<H4>
++3.4.0 -- November 24, 2001
++</H4>
++<!
++-------
++>
++
++<b>New features:</b>
++<ul>
++<li> Parser for the BDF bitmap fonts.
++<li> Vastly improved the smoothing of the outlines.
++<li> The options are saved as a comment in the output file.
++<li> New script <tt>other/showdf</tt> for visual comparison of the fonts.
++<li> New option <b>-G</b> to select the file types to generate.
++<li> Creation of the dvips encoding files (by Rigel).
++<li> More glyphs in the Chinese maps (by Rigel).
++<li> Made the assignment of ISO8859/1 glyph names to the glyphs in the
++  fonts without PostScript names in them dependent on the original
++  encoding: no change for the 8-bit encodings, for the Unicode encoding
++  the names are assigned to the glyph with the codes 0-255 in Unicode,
++  and for the other 16-bit encodings the 8859/1 names are not assigned
++  at all.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Added a check for spaces in the PostScript font name in the FreeType
++  parser.
++<li> Made "-" a valid character in the glyph names.
++<li> Fixed handling of the Unicode names returned by FreeType, though
++  not perfectly.
++<li> Changed the build for FreeType-2.0.4.
++<li> Fixed the handling and printing of bad glyph names.
++<li> Fixed the bug with duplicated glyph names when more than 256 glyphs are 
++  extracted from a font that has no PostScript glyph names defined.
++<li> Added ability to map a glyph to more than one code when unisng the
++  native parser (-pttf).
++</ul>
++
++<H4>
++3.3.5 -- September 12, 2001
++</H4>
++<!
++-------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fixed the scaling of Ascender and Descender in the AFM file.
++<li> Fixed the brekage of "-l adobestd".
++</ul>
++
++<H4>
++3.3.4 -- June 4, 2001
++</H4>
++<!
++-------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Cyrillic (full set of glyphs) language tables (by Zvezdan Petkovic).
++  Now the languages "russian" and "bulgarian" are provided for compatibility
++  only, use the common language "cyrillic" instead.
++<li> More information in <a href="FONTS.html">FONTS</a> on using Cyrillic fonts with 
++  Netscape (by Zvezdan Petkovic)
++<li> In the Netscape print filter added removal of the clipping path command:
++  otherwise Netscape tends to cut off a large piece of the rightmost column
++  of the tables.
++<li> One more script for printing from Netscape (by Zvezdan Petkovic).
++<li> Added selection of the base TTF encoding by pid/eid in the external maps.
++<li> Improved the recognition of substituted stems for intersecting contours.
++<li> Improved the substituted hints to make the horizontal positioning of
++  the points at the same height more uniform at small pixel sizes.
++<li> Made the algorithm for calculation of standard stem widths more
++  selective.
++<li> Added link to the GnuWin32 project.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> TH: Print out metrics of un-encoded glyphs even without "-a" option.
++<li> Added missing "/" in Fontmap generation in convert (by Zvezdan Petkovic).
++<li> Removed unneccessary "\n" in messages in x2gs.
++<li> Removed the broken overoptimisation of "0 0 rmoveto".
++<li> Removed the useless warnings about multiple codes for a glyph.
++<li> Changed the FreeType2 include directory in the Makefile to match the
++  FreeType's default.
++</ul>
++
++<H4>
++3.3.3 -- March 4, 2001
++</H4>
++<!
++-------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> TH: Added printing of front-end parser in the header of the font file.
++<li> Tested build with FreeType 2.0 Release.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Changed the installation script which on some versions of bash
++  copied all files into the share directory.
++<li> Fixed the close sequences of html2man comments in the HTML files, 
++  now they should display correctly with <tt>lynx</tt>.
++<li> Restored the ability to include un-encoded characters into the
++  customised maps (those with codes over 255).
++<li> Fixed the Unicode mapping of the Cyrillic letters "YO" and  "yo" 
++  (by Yuri Shemanin).
++<li> Fixed the spurious aborts when the conversion-by-plane function
++  gets called for auto-guessing of encoding.
++</ul>
++
++<H4>
++3.3.2 -- November 20, 2000
++</H4>
++<!
++--------------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added generation of man pages.
++<li> Added "make install" and "make uninstall".
++<li> Added language option "-l plane".
++<li> In <tt>other/showg</tt> added better support of comparison files:
++<ul>
++  <li> printing of the comparison file legend;
++  <li> guessing of missing glyph names in a comparison file by code;
++  <li> bounding boxes of all comparison files are used for page layout.
++</ul>
++<li> Added ability to use external t1asm instead of compiling it in.
++<li> Renamed the fonts installation guide from INSTALL*html to FONTS*html
++  to avoid confusion with installation of ttf2pt1 itself.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Removed erroneous extra fclose(pfa_file).
++<li> Fixed random memory corruption that manifested with crash on Linux
++  when converting fonts not containing glyph names.
++<li> Removed from the output file the comments that confused dvips. Changed 
++  <tt>other/showg</tt> to work without them.
++<li> In <tt>other/showg</tt> added better checks for missing glyphs, now it
++  gives warnings about them and the output file does not crash PostScript.
++</ul>
++
++<b>Other:</b>
++<ul>
++<li> <tt>ttf2pfa</tt> is no longer included, people interested in history 
++  should look for it in the older versions. 
++</ul>
++
++<H4>
++3.3.1 -- October 22, 2000
++</H4>
++<!
++-------------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added front-end parser based on the FreeType-2 library. See Makefile
++for build instructions.
++<li> Changed the handling of encodings to accomodate the FreeType model.
++<li> Further cleaned up the front-end parser interface.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fixed a bug that caused core dump on Alpha machines.
++<li> Fixed a bug in the outline smoothing that occasionally caused core dump.
++<li> Cleaned up warnings from picky compilers
++<li> Fixed more bugs in the Windows port (by Stefan Bauer).
++<li> Fixed the RPM spec file (suggested by Brian Armstrong).
++</ul>
++<p>
++
++<H4>
++3.3.0 -- September 22, 2000
++</H4>
++<!
++---------------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Converted most of the outlines' processing to floating point
++arithmetic.
++<li> Added splitting of curves crossing the quadrant boundaries (no gross 
++damage is done any more to the Marvosym font and others like it).
++<li> Added modular interface for front-end font parsers and option to control
++their selection at run time.
++<li> Grouped the outline processing control options into one to reduce the
++options namespace pollution.
++<li> Thomas moved the Chinese maps into a separate module, chinese-maps.
++<li> Thomas added option -V to print version number. In addition, the version
++number is put in the header of the font file.
++<li> Added long option names (suggested by Thomas).
++<li> Added support for multi-level composite glyphs.
++<li> TH: Made &lt;fontname&gt; command-line argument optional; default to &lt;ttf-file&gt;
++with suffix replaced.
++<li> In <tt>other/showg</tt> added more ways to specify glyphs and the comparison option.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fixed the VC++ batch file, added batch file for Cygnus GCC on Windows.
++<li> Removed parentheses from the Version string in AFM files because it does
++not help StarOffice anyway. StarOffice 5.2 has been reported to have this
++bug fixed. Added paragraph on StarOffice in FONTS.html.
++<li> Made messages on the '?' option parameter more meaningful (by Johan Vromans).
++<li> Changed the latin1 encoding table to include the Euro sign, Z and z with
++caron (by Thomas Henlich).
++<li> Improved the smoothing code which occasionally had problems with
++joining curves. Also fixed a few minor bugs in it.
++</ul>
++
++<H4>
++3.22 -- May 23, 2000
++</H4>
++<!
++--------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Included windows support by Frank Siegert (somewhat amended)
++<li> Added control over verbosity of warnings.
++<li> Added arguments and initialization functions to the language
++translation routines.
++<li> Added support of planes determined by arguments to the external
++maps.
++<li> Added compact external maps format (primarily for Eastern fonts).
++<li> Added external maps for Chinese GBK and Big5 encodings (converted
++from ttf2pfb) as well as maps for other Chinese encodings by Wang Lei.
++<li> Added the idea of buckets to speed up the search in external maps.
++<li> Changed the grouping algorithm for substituted hints: now it creates
++a bit bigger files but requires smaller hint stack when being rendered.
++<li> Added maximal limit of hint stack depth, glyphs requiring bigger 
++stack get generation of substituted hints disabled. This makes substituted 
++hints safe to use, no more lost glyphs due to hint stack overflow.
++<li> Added the font dump program <tt>other/dumpf</tt>.
++<li> Changed the testing HTML generator <tt>other/lst.pl</tt> to use tables.
++<li> Added debugging script <tt>other/cntstems.pl</tt> to count required hint
++stack depth for the glyphs.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> Fixed printing of UID in script/trans. Changed the auto-generated UID to
++be in range 4000000-4999999 which is reserved by Adobe for private use.
++<li> Fixed handling of "cleartomark" in built-in t1asm.
++<li> Added handling of "can't happen" case in straighten() routine
++which actually happened on strange fonts and caused failure on assertion.
++<li> Made it always include the glyph .notdef in the resulting font.
++<li> Placed the version string in AFM file in parentheses, hopefully
++that would fix the problem with StarOffice.
++<li> Improved the smoothing code which occasionally had problems with
++joining curves.
++</ul>
++
++<H4>
++3.21 -- March 1, 2000
++</H4>
++<!
++---------------------
++>
++
++Sergey Babkin: committed the changes by Petr Titera and
++my bugfixes.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> New Unicode map format with glyph names, by Petr Titera.
++<li> Option to force the Unicode encoding by Petr Titera
++ (I changed it to work on any MS encoding, not only Symbol).
++<li> Slightly tweaked the calculation of hints, should be better now.
++</ul>
++
++<b>Bug fixes:</b>
++<ul>
++<li> The unicode-sample.map with description of the map formats
++ was lost in the release process, restored and enhanced.
++<li> Renamed the table ISOLatin1Encoding to Fmt3Encoding to reflect
++ the way it is used. Saved the original one for reference
++ purposes. In the new table renamed "quoteright" to "quotesingle"
++ as Thomas Henlich suggested (and he were right).
++<li> In the ISOLatinEncoding table renamed the glyph "grave"
++ at octal 0140 to "quoteleft", "quotesingle" at octal 047 to
++ "quoteright" to conform to the standard as suggested by 
++ Martin Trautner).
++<li> Fixed bug in scripts/trans that corrupted the UniqueID record
++ in the translated fonts.
++<li> Fixed bug in interaction of substituted hints with BlueZones.
++ Now the fonts with hint substitution seem to be always at least
++ not worse than without it (well, when they fit in the X11
++ file size limit).
++</ul>
++
++
++<H4>
++3.2 -- January 15, 2000
++</H4>
++<!
++-----------------------
++>
++
++Sergey Babkin: combined my changes with the changes by
++Thomas Henlich. The result deserves a not-so-minor version
++increase.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Support of the external Unicode re-encoding maps
++  (by Thomas).
++<li> Support for inclusion of all the glyphs from the
++  source file into the resulting file (inspired by
++  Thomas but I re-implemented it to remove the limitation
++  of his implementation: not more than 1024 glyphs).
++<li> The hints substitution. It's an experimental feature
++  yet and needs further work.
++<li> Support for UniqueID and its auto-generation.
++<li> Support for the name-based conversions from Unicode
++  in general and the adobestd "language" in particular.
++<li> Started the split of the source code into multiple
++  files. This needs more work to do it in a cleaner
++  way.
++<li> Better framework for the debugging printout
++  in the converter.
++<li> Utilities to install the fonts in Netscape 
++  Navigator/Communicator 4.x.
++<li> Patches for bigger font files in the X11 rasterizer.
++<li> Linux RPM spec-file (by Johan Vromans).
++<li> Added the COPYRIGHT file (BSD-style, as we discussed
++  on the mailing list earlier) and the CHANGES file.
++<li> Creation of the <tt>.pfb</tt> files from the <tt>convert</tt>
++  script.
++<li> Changed the <tt>.notdef</tt>-s in the built-in
++  ISOLatin1Encoding table to some valid names (by Thomas).
++  Thomas also suggested replacing `<tt>quoteright</tt>' by
++  `<tt>quotesingle</tt>' but this seems to be against the
++  Adobe ISOLatin1 table.
++<li> New aliases <tt>windows-1251</tt> and <tt>cp-866</tt> for
++  the Russian encodings: those are expected by Netscape
++  navigator.
++<li> The font comparison program <tt>other/cmpf</tt>.
++<li> The "magnifying glass" program for glyph outlines:
++  <tt>other/showg</tt>.
++<li> Other updates of the tools in the `<tt>other</tt>' subdirectory.
++<li> Added a link to T1LIB in README.
++<li> A few new options in <tt>convert.cfg</tt>.
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> A bug in the outline smoothing code that corrupted some
++  of the fonts (for example, Microsoft Verdana).
++<li> Added explicit `<tt>cleartomark</tt>' to the end of file,
++  this seems to be compatible with both old and new version
++  of <tt>t1asm</tt> (suggested by Thomas).
++<li> Added the <tt>FontEncoding</tt> statement to the AFM files
++  (techincally this was not a bug because this statement
++  is optional but some programs want it).
++<li> A coredump when the converter tried to print a warning
++  (rather ironically) about a weird glyph width.
++<li> Changed the underscores in the font names to dashes (this
++  has been proposed long time ago by Johan Vromans).
++<li> No more glyph names of font names staring with a digit.
++<li> The names of the fonts in font and AFM files are now the
++  same as in the generated Ghostscript <tt>Fontmap</tt> file.<br>
++  <b>Warning:</b> the names in <tt>Fontmap</tt> have been
++  changed.
++<li> The <tt>forceiso</tt> script does not corrupt the character
++  and kerning pairs counts any more, and is optional at all.
++<li> Fix for a loop going to 254 instead of 255 (by Thomas).
++<li> Added ':' in the font header (by Thomas).
++<li> A coredump when wrong language name is given (this was
++  also fixed by Thomas but I noticed it too late, after
++  I already fixed it by myself).
++<li> Fixed the links to the Adobe documents in README.
++</ul>
++
++
++<H4>
++3.13 -- October 18, 1999
++</H4>
++<!
++------------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> New option -v for automatic re-scaling based on the vertical size of the font 
++<li> Changed the code to use getopt() instead of a home-made version of it.
++<li> Latin2 language support by Szalay Tamas. 
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> Fix for the bug that made possible calls of malloc(0). 
++<li> Refinement of the option -w to prevent extra wide spacing 
++</ul>
++
++<H4>
++3.12 -- October 2, 1999
++</H4>
++<!
++-----------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added support for the Bulgarian language (actually, for now just an alias
++of Russian).                                                                    
++<li> Added option -w that tries to make sure that the character widths are not
++too narrow.                                                                     
++<li> Added the concept of aliased encodings.
++<li> Now the conversion scripts create and install the .afm files too.
++<li> The conversion script removes the intermediate files after installation.
++<li> Added tunables to the conversion script.
++<li> Installation of the Ghostscript fonts can now be done automatically
++together with the X11 fonts.
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> (FINALLY!!!) A correct fix for the infamous Red Hat 6.0 stdio "feature".
++<li> A number of little bugs discovered by a picky SGI compiler (well, maybe
++some day I'll try to run it through the UnixWare lint and see what happens).    
++<li> A diagnostic message about the empty encodings in the convert script was
++made less cryptic and a bug in the awk sub-script was fixed.                    
++<li> The .afm creation code now considers the option -t. 
++</ul>
++
++<H4>
++3.11 -- May 24, 1999
++</H4>
++<!
++--------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> It includes the Turkish (Latin5, ISO8859/9) 
++language support by Turgut Uyar and Baltic (ISO8859/4) languages support by
++Rihardas Hepas. 
++<li> Also the installation script got updated: the configuration parameters 
++are moved to a separate file and the generated fonts.dir files should now be
++compatible with Xfsft.
++</ul>
++
++<H4>
++3.1 -- March 28, 1999
++</H4>
++<!
++---------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Improved the interaction of the character-level hints and font-level hints
++</ul>
++
++
++<H4>
++3.0 -- March 6, 1999
++</H4>
++<!
++--------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added HTML documents.
++</ul>
++
++<H4>
++3.0beta2 -- February 14, 1999
++</H4>
++<!
++-----------------------------
++>
++
++Packaged by Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added ability to print the .afm file instead of the font to STDOUT.
++<li> Added the guessing of the /ForceBold parameter that proved to be useful.
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> Removed the force-fixed option that proved to be troublesome.
++</ul>
++
++<H4>
++3.0beta1 -- December 11, 1998
++</H4>
++<!
++-----------------------------
++>
++
++By Andrew Weeks.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added option (passed to t1asm) to create a compressed binary
++version of the font (A PFB file).
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> Versions of handle_post and handle_cmap that deal with some
++problems with buggy fonts.
++<li> Minor Bug Fixes.
++</ul>
++
++<H4>
++3.0beta-afm -- December 5, 1998
++</H4>
++<!
++-------------------------------
++>
++
++By Thomas Henlich.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Integration of AFM file creation.
++</ul>
++
++<H4>
++3.0beta -- November 15, 1998
++</H4>
++<!
++----------------------------
++>
++
++By Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Added the auto-calculation of the italic angle.
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> Fixed a couple of bugs.
++</ul>
++
++<H4>
++3.0alpha -- October 19, 1998
++</H4>
++<!
++----------------------------
++>
++
++By Sergey Babkin.
++<p>
++
++<b>New features:</b>
++<ul>
++<li> Improved (although still not perfect) handling of
++scaling in composite glyphs
++<li> Automatic correction of outlines to make them more
++smooth (to correct both rounding errors introduced
++during conversion and present in the original font)
++<li> Automatic generation of hints (still has lots of
++space for improvement)
++<li> Automatic generation of BlueValues etc.
++</ul>
++
++<b>Bux fixes:</b>
++<ul>
++<li> Scaling of fonts to 1000x1000 M-square required by
++Type1 standard
++<li> Printing out the contours in reverse direction, because
++TTF directions are different from Type1 ones (that was
++the major reason why the fonts generated by
++version 2.2 were rendered so badly in small sizes)
++</ul>
++
++<H4>
++June 22, 1998 (AKA 2.2)
++</H4>
++<!
++-------------
++>
++
++By Thomas Henlich.
++<p>
++
++<b>Bux fixes:</b>
++<ul>
++<li> "width" should be "short int" because otherwise:
++characters with negative widths (e.g. -4) become *very* wide (65532)
++<li> The number of /CharStrings is numglyphs and not numglyphs+1
++</ul>
++
++<H4>
++February 13, 1998
++</H4>
++<!
++-----------------
++>
++
++By Mark Heath.
++<p>
++
++<b>Bux fixes:</b>
++<ul>
++<li> An original Bug Reported by Frank, which was just incorrect syntax in the 
++Type 1 header, managed to creep back into the Feb 04 Version. This has been
++Fixed in the Feb 13 Version.
++</ul>
++
++<H4>
++February 4, 1998
++</H4>
++<!
++----------------
++>
++
++By Mark Heath.
++<p>
++
++<b>Bux fixes:</b>
++<ul>
++<li> A workaround was implemented in ttf2pfa by altering the matrix. I suspect 
++I will have to calculate the correct values, as matrix ops are probably not
++allowed in Type 1 format.
++</ul>
++
++<!
++---------------------------------------------
++>
++<H4>
++The older history seems to be lost.
++</H4>
++
++<I>
++(S.B.: The story how we got the version numbers is rather funny. Initially
++there were no version umbers, the releases were marked by dates. The version
++from June 22 1998 untarred itself into a directory "<tt>ttf2pt1-22</tt>". When I
++made my changes to it I assumed that this was the version number meaning
++version 2.2. Since Mark asked me to send him a complete archive I supposed 
++that I have to bump the version number. And I bumped it to 3.0 because the
++changes were rather extensive. Mark silently agreed and released the new
++version as 3.0. And that's the end of the story about how we got this
++Microsoft-like high version number.)
++</I>
++
++</BODY>
++</HTML>
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/COPYRIGHT xserver/hw/xprint/extras/ttf2pt1/COPYRIGHT
+--- xserver-old/hw/xprint/extras/ttf2pt1/COPYRIGHT	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/COPYRIGHT	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,87 @@
++The following copyright notice applies to all the files provided
++in this distribution unless explicitly noted otherwise
++(the most notable exception being t1asm.c).
++
++  Copyright (c) 1997-2002 by the AUTHORS:
++   Andrew Weeks <ccsaw@bath.ac.uk> 
++   Frank M. Siegert <fms@this.net> 
++   Mark Heath <mheath@netspace.net.au> 
++   Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
++   Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
++   Turgut Uyar <uyar@cs.itu.edu.tr>
++   Rihardas Hepas <rch@WriteMe.Com>
++   Szalay Tamas <tomek@elender.hu>
++   Johan Vromans <jvromans@squirrel.nl>
++   Petr Titera <P.Titera@sh.cvut.cz>
++   Lei Wang <lwang@amath8.amt.ac.cn>
++   Chen Xiangyang <chenxy@sun.ihep.ac.cn>
++   Zvezdan Petkovic <z.petkovic@computer.org>
++   Rigel <rigel863@yahoo.com>
++  All rights reserved.
++ 
++  Redistribution and use in source and binary forms, with or without
++  modification, are permitted provided that the following conditions
++  are met:
++  1. Redistributions of source code must retain the above copyright
++     notice, this list of conditions and the following disclaimer.
++  2. Redistributions in binary form must reproduce the above copyright
++     notice, this list of conditions and the following disclaimer in the
++     documentation and/or other materials provided with the distribution.
++  3. All advertising materials mentioning features or use of this software
++     must display the following acknowledgement:
++       This product includes software developed by the TTF2PT1 Project
++       and its contributors.
++ 
++  THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
++  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
++  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++  SUCH DAMAGE.
++
++For the approximate list of the AUTHORS' responsibilities see the
++project history.
++
++Other contributions to the project are:
++
++Turgut Uyar <uyar@cs.itu.edu.tr>
++ The Unicode translation table for the Turkish language.
++
++Rihardas Hepas <rch@WriteMe.Com>
++ The Unicode translation table for the Baltic languages.
++
++Szalay Tamas <tomek@elender.hu>
++ The Unicode translation table for the Central European languages.
++ 
++Johan Vromans <jvromans@squirrel.nl>
++ The RPM file.
++
++Petr Titera <P.Titera@sh.cvut.cz>
++ The Unicode map format with names, the forced Unicode option.
++
++Frank M. Siegert <frank@this.net>
++ Port to Windows
++
++Lei Wang <lwang@amath8.amt.ac.cn>
++Chen Xiangyang <chenxy@sun.ihep.ac.cn>
++ Translation maps for Chinese fonts.
++
++Zvezdan Petkovic <z.petkovic@computer.org>
++ The Unicode translation tables for the Cyrillic alphabet.
++
++Rigel <rigel863@yahoo.com>
++ Generation of the dvips encoding files, modification to the Chinese maps.
++
++I. Lee Hetherington <ilh@lcs.mit.edu>
++ The Type1 assembler (from the package 't1utils'), its full copyright
++ notice:
++  Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
++  Permission is hereby granted to use, modify, and distribute this program
++  for any purpose provided this copyright notice and the one below remain
++  intact.
++ 
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/cygbuild.sh xserver/hw/xprint/extras/ttf2pt1/cygbuild.sh
+--- xserver-old/hw/xprint/extras/ttf2pt1/cygbuild.sh	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/cygbuild.sh	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,8 @@
++:
++# this file should be run from Cygnus BASH
++# file to build ttf2pt1 with Cygnus GCC on Windows
++# don't forget to copy CYGWIN1.DLL into C:\WINDOWS
++
++gcc -o ttf2pt1 -DWINDOWS ttf2pt1.c pt1.c t1asm.c ttf.c -lm
++gcc -o t1asm -DWINDOWS -DSTANDALONE t1asm.c
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/FONTS.hpux.html xserver/hw/xprint/extras/ttf2pt1/FONTS.hpux.html
+--- xserver-old/hw/xprint/extras/ttf2pt1/FONTS.hpux.html	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/FONTS.hpux.html	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,197 @@
++<HTML>
++<HEAD>
++<TITLE>
++How to install new Type1 fonts on an HP-UX 10.20 machine
++</TITLE>
++</HEAD>
++<BODY>
++Sergey A. Babkin
++<br>
++<A HREF="mailto:babkin@bellatlantic.net">
++&lt;babkin@bellatlantic.net&gt;</A> or <A HREF="mailto:sab123@hotmail.com">&lt;sab123@hotmail.com&gt;</A>
++<p>
++<! 
++(Do not edit this file, it is generated from FONTS.hpux.html!!!)
++>
++
++<H3>
++How to install new Type1 fonts on an HP-UX 10.20 machine
++</H3>
++<!
++--------------------------------------------------------
++>
++
++1. Add the font files to <tt>/usr/lib/X11/fonts/type1.st/typefaces</tt>.
++<p>
++
++2. Add the font descriptions to 
++<tt>/usr/lib/X11/fonts/type1.st/typefaces/fonts.scale</tt>. Run `mkfontdir'
++in <tt>/usr/lib/X11/fonts/type1.st/typefaces</tt>. In the descriptions
++you have to specify the font manufacturer as `misc', like:
++<p>
++
++<tt>
++&nbsp;&nbsp;-misc-courier-...
++</tt>
++<p>
++
++3. Copy <tt>/usr/lib/X11/fonts/type1.st/typefaces/fonts.dir</tt> to
++<tt>/usr/lib/X11/fonts/type1.st/licenses/STSYSTEM/DISPLAYS/fonts.dir</tt>.
++Better yet, create a symbolic link.
++<p>
++
++4. For each font encoding you are going to use create a description
++file in <tt>/usr/lib/X11/fonts/stadmin/type1/charsets</tt>. Of course, if you
++are going to use the same fonts in several encodings, the best way
++would be to create fair descriptions of charsets and really store
++only one encoding in typefaces, all the others will be produced
++automatically. That's not difficult at all. 
++But the simplest way is to just copy the file <tt>cp.iso8859-1</tt> 
++to <tt>cp.<i>&lt;your-encoding-name&gt;</i></tt>, like <tt>cp.koi8-r</tt>.
++<p>
++
++5. Restart you X server and/or font server.
++<p>
++
++<H4>
++What if you don't have the `root' privileges ?
++</H4>
++<!
++----------------------------------------------
++>
++
++You still can run the font server and configure your X server
++to get the fonts from it. 
++<p>
++
++Further let's suppose that the name on which you are going
++to run the font server is named `somehost'. Login to it
++and configure the font server.
++<p>
++
++First, choose some unused port. Numbers around 9000 are a good
++choice. Verify that this port is not used by somebody else
++by entering
++<p>
++
++<blockquote><tt>
++	netstat -naf inet |grep 9000
++</tt></blockquote>
++
++and look what happens. If you get nothing, that's good, this
++port is unused. If you get some lines of data, try abother port.
++<p>
++
++Go to you home directory <tt>$HOME</tt> and create some directory for
++your font server, say, <tt>$HOME/fs</tt>. Copy the directory structure
++of <tt>/usr/lib/X11/fonts/type1.st</tt> into <tt>$HOME/fs</tt>, so that in result
++you get <tt>$HOME/fs/type1.st/<i>&lt;whatever was there&gt;</i></tt>. Copy the directory 
++structure of <tt>/usr/lib/X11/fonts/stadmin/type1/charsets</tt> into <tt>$HOME/fs</tt>, 
++so that in result you get <tt>$HOME/fs/charsets/<i>&lt;whatever was there&gt;</i></tt>.
++Install the new fonts in these directorues as described above.
++<p>
++
++Then create the fontserver configuration file, say, <tt>$HOME/fs/xfs.cfg</tt>.
++The sample contents (supposing that my <tt>$HOME</tt> is equal to <tt>/home/babkin</tt>) 
++is:
++<p>
++
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<hr>
++<tt>
++# font server configuration file                                    
++<br>
++# $XConsortium: config.cpp,v 1.7 91/08/22 11:39:59 rws Exp $        
++<br>
++                                                                    
++<br>
++rasterizers = /usr/lib/X11/fs/ufstrast.sl,/usr/lib/X11/fs/iforast.sl
++<br>
++                                                                    
++<br>
++clone-self = off                                                    
++<br>
++use-syslog = off                                                    
++<br>
++catalogue = /home/babkin/fs/type1.st              
++<br>
++# in decipoints                                                     
++<br>
++default-point-size = 120                                            
++<br>
++default-resolutions = 100,100,75,75
++<br>
++port=9000                                                           
++<br>
++error-file=/home/babkin/fs/fs.err                 
++</tt>
++<hr>
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<p>
++
++Then create the script to start your font server, say, <tt>$HOME/fs/runme</tt>:
++<p>
++
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<hr>
++<tt>
++TYPE1_CODEPAGE_DIR=$HOME/fs/charsets                                         
++<br>
++export TYPE1_CODEPAGE_DIR                                                 
++<br>
++kill `ps -ef | grep $HOME/\[f\]s/xfs.cfg | awk '{print $2}'`; 
++<br>
++nohup xfs -config $HOME/fs/xfs.cfg &
++</tt>
++<hr>
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<p>
++
++Don't forget to make <tt>$HOME/fs/runme</tt> executable. Then you can
++execute it manually or from you .profile.
++<p>
++
++After you get your font server running, just execute the following
++command (with proper host name and port number) in your X session
++<p>
++
++<blockquote><tt>
++	xset fp+ tcp/somehost:9000
++</tt></blockquote>
++
++to get the access to your private font server. You can add this
++information to the configuration data of your X server or just
++put it also into your .profile. In the latter case the best way
++to do that would be like:
++<p>
++
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<hr>
++<tt>
++...
++<br>
++$HOME/fs/runme
++<br>
++sleep 2 # give it some time to start
++<br>
++xset fp+ tcp/somehost:9000
++<br>
++...
++</tt>
++<hr>
++<!
++--------------8&lt;----------- cut here -----------------------------
++>
++<p>
++</BODY>
++</HTML>
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/FONTS.html xserver/hw/xprint/extras/ttf2pt1/FONTS.html
+--- xserver-old/hw/xprint/extras/ttf2pt1/FONTS.html	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/FONTS.html	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,708 @@
++<HTML>
++<HEAD>
++<TITLE>
++The ttf2pt1 font installation guide 
++</TITLE>
++</HEAD>
++<BODY>
++Sergey A. Babkin
++<br>
++<A HREF="mailto:babkin@users.sourceforge.net">
++&lt;babkin@bellatlantic.net&gt;</A> or <A HREF="mailto:sab123@hotmail.com">&lt;sab123@hotmail.com&gt;</A>
++<p>
++<! 
++(Do not edit this file, it is generated from FONTS.html!!!)
++>
++
++<!-- =defdoc cv ttf2pt1_convert 1 -->
++<!-- =defdoc gs ttf2pt1_x2gs 1 -->
++<H2>
++THE FONT INSTALLATION GUIDE 
++<br>
++for the TTF to Type1 converter and fonts generated by it
++</H2>
++<!
++========================================================
++>
++
++There is historically a number of problems with the support of the 8-bit
++character encodings. This installation guide pays a lot of attention
++to the 8-bit issues, because these issues are responsible for the
++most of troubles during the installation of fonts. But they are
++not the only things covered in this guide, so it's worth reading
++even if all you need is plain ASCII. For convenience of reading
++I have marked the paragraphs dealing solely with 8-bit problems
++with characters <FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT>.
++<p>
++
++To simplify this installation the distribution package of the
++converter contains a number of scripts written in shell and
++Perl. So, to run them you will need a shell interpreter (Bourne-shell,
++POSIX-shell, Korn-shell are OK, ba-shell is probably also OK but not 
++tested yet). The Perl scripts were tested with Perl5 but probably
++should work with Perl4 too. All the scripts are located in the
++`scripts' subdirectory.
++<p>
++
++This guide considers the following issues of installation of the 
++fonts:
++<p>
++
++<b>
++<ul>
++<li> <A HREF="#X11">X11</A><br>
++<li> <A HREF="#gs">Ghostscript</A><br>
++<li> <A HREF="#win">MS Windows</A><br>
++<li> <A HREF="#netscape">Netscape Navigator/Communicator</A><br>
++<li> <A HREF="#rpm">Linux RPM package</A><br>
++<li> <A HREF="#framemaker">FrameMaker</A><br>
++<li> <A HREF="#soffice">StarOffice</A><br>
++</ul>
++</b><p>
++
++<A NAME="X11"></A>
++<H3>
++X11
++</H3>
++<!
++===
++>
++
++<!-- =section cv NAME -->
++<!-- =text B&lt;ttf2pt1_convert&gt; - convenience font conversion script -->
++<!-- =stop -->
++To simplify the conversion a set of scripts is provided with <b>ttf2pt1</b>.
++They are collected in the `<TT>scripts</TT>' subdirectory. 
++<p>
++
++<!-- =section cv DESCRIPTION -->
++`<b>Convert</b>' is the master conversion script provided with ttf2pt1. 
++When installed into a public directory it's named `<b>ttf2pt1_convert</b>' 
++to avoid name collisions with the other programs.
++<p>
++<!-- =stop -->
++
++It's called as:
++<p>
++
++<!-- =section cv SYNOPSIS -->
++<!-- =text ttf2pt1_convert B&lt;[config-file]&gt; -->
++<!-- =stop -->
++<blockquote>
++  convert <i>[config-file]</i>
++</blockquote>
++
++<!-- =section cv DESCRIPTION -->
++If the configuration file is not specified as an argument then the file
++`<TT>convert.cfg</TT>' in the current directory is used. This file contains
++a set of configuration variables. The distribution contains a sample file
++file `<TT>convert.cfg.sample</TT>'. Please copy it to `<TT>convert.cfg</TT>',
++look inside it and change the configuration variables. The more stable
++configuration variables, such as the path names of the scripts and
++encoding files are located in `<TT>convert</TT>' itself, they are
++automatically updated when installing <b>ttf2pt1</b>.
++<p>
++
++Put all the TTF fonts you want to convert into some directory (this
++may be just the directory that already contains all the Windows
++fonts on a mounted FAT filesystem). If you have fonts in different
++source encoding then put the fonts in each of the encodings
++into a separate directory. Up to 10 source directories are
++supported. If you (in a rather unlikely case) have more source
++directories then you can make two separate runs of the converter,
++converting up to 10 directories at a time.
++<p>
++
++The variables in the configuration file are:
++<p>
++
++<!-- ==over 2 -->
++<!-- ==item * -->
++<B><tt>SRCDIRS</tt></B> - the list of directories (with absolute paths) with 
++  TTF fonts. Each line contains at least 3 fields: the name of the directory,
++  the language of the fonts in it (if you have fonts for different 
++  languages you have to put them into the separate directories) and the
++  encoding of the fonts. Again, if you have some of the TTF typefaces in 
++  one encoding, and some in another (say, CP-1251 and KOI-8), you have 
++  to put them into the separate source directories. Some lines may contain
++  4 fields. Then the fourth field is the name of the external map to
++  convert the Unicode fonts into the desirable encoding. This map is
++  used instead of the built-in map for the specified language.
++<p>
++
++<FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT>
++An interesting thing is that some languages have more than one
++widely used character encodings. For example, the widely used
++encodings for Russian are IBM CP-866 (MS-DOS and Unix), KOI-8
++(Unix and VAX, also the standard Internet encoding), IBM CP-1251 (MS Windows).
++That's why I have provided the means to generate the converted fonts
++in more than one encoding. See the file <A HREF="encodings/README.html">encodings/README</A> for 
++details about the encoding tables. Actually, if you plan to use
++these fonts with Netscape Navigator better use the aliases
++cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251
++because that's what Netscape wants.
++<p>
++
++<!-- ==item * -->
++<b><tt>DSTDIR</tt></b> - directory for the resulting Type1 fonts. Be careful!
++  This directory gets completely wiped out before conversion,
++  so don't use any already existing directory for this purpose.
++<p>
++
++<!-- ==item * -->
++<b><tt>DSTENC<i>{language}</i></tt></b> - the list of encodings in which the destination 
++  fonts will be generated for each language. Each font of that 
++  language will be generated in each of the specified
++  encodings. If you don't want any translation, just specify both
++  <tt>SRCENC</tt> and <tt>DSTENC</tt> as iso8859-1 (or if you want any other encoding
++  specified in the fonts.dir, copy the description of 8859-1 with
++  new name and use this new name for <tt>SRCENC</tt> and <tt>DSTENC</tt>).
++<p>
++
++<!-- ==item * -->
++<b><tt>FOUNDRY</tt></b> - the foundry name to be used in the fonts.dir file. I have
++  set it to `fromttf' to avoid name conflicts with any existing font for
++  sure. But this foundry name is not registered in X11 standards and
++  if you want to get the full standard compliance or have a font server
++  that enforces such a compliance, use `misc'.
++<p>
++<!-- ==back -->
++
++The next few parameters control the general behavior of the converter.
++They default values are set to something reasonable.
++<p>
++
++<!-- ==over 2 -->
++<!-- ==item * -->
++<b><tt>CORRECTWIDTH</tt></b> - if the value is set to <b><tt>YES</tt></b> then use the 
++  converter option <tt><b>-w</b></tt>, otherwise don't use it. See the description of 
++  this option in the <A HREF="README.html">README</A> file.
++<p>
++
++<!-- ==item * -->
++<b><tt>REMOVET1A</tt></b> - if the value is set to <b><tt>YES</tt></b> then after
++  conversion remove the un-encoded <tt>.t1a</tt> font files and the 
++  intermediate <tt>.xpfa</tt> font metric files.
++<p>
++
++<!-- ==item * -->
++<b><tt>INSTALLFONTMAP</tt></b> - a Ghostscript parameter, if the value is set to 
++  <b><tt>YES</tt></b> then install the entries for the new fonts
++  right into the main <tt>Fontmap</tt> file. Otherwise just leave
++  the file <tt>Fontmap.ttf</tt> in the Ghostscript configuration
++  directory.
++<p>
++
++<!-- ==item * -->
++<b><tt>HINTSUBST</tt></b> - if the value is set to <b><tt>YES</tt></b> use the option
++  <tt><b>-H</b></tt>, otherwise don't use it. This option enables the
++  hint substitution technique. If you have not installed the X11 patch
++  described above, use this option with great caution. See further 
++  description of this option in the <A HREF="README.html">README</A> file.
++<p>
++
++<!-- ==item * -->
++<b><tt>ENFORCEISO</tt></b> - if the value is set to <b><tt>YES</tt></b> then
++  disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically
++  this was neccessary due to the way the installer scripts created the
++  X11 font configuration files. It is not neccessary any more for this
++  purpose. But if you plan to use these fonts with some other application
++  that expects ISOLatin1 encoding then better enable this option.
++<p>
++
++<!-- ==item * -->
++<b><tt>ALLGLYPHS</tt></b> - if the value is set to <b><tt>YES</tt></b> then
++  include all the glyphs from the source fonts into the resulting fonts, even
++  if these glyphs are inaccessible. If it's set to <b><tt>NO</tt></b> then
++  include only the glyphs which have codes assigned to them. The glyphs
++  without codes can not be used directly. But some clever programs,
++  such as the Type 1 library from XFree86 3.9 and higher can change
++  the encoding on the fly and use another set of glyphs. If you have not 
++  installed the X11 patch described above, use this option with great 
++  caution. See further description of the option option <tt><b>-a</b></tt> in the 
++  <A HREF="README.html">README</A> file.
++<p>
++
++<!-- ==item * -->
++<b><tt>GENUID</tt></b> - if the value is set to <b><tt>YES</tt></b> then use
++  the option <tt><b>-uA</b></tt> of the converter to generate UniqueIDs for
++  the converted fonts. The standard X11 Type 1 library does not use
++  this ID, so it may only be neccessary for the other applications.
++  The script is clever enough to generate different UniqueID for the
++  same font converted to multiple encodings. Also after conversion it
++  checks all the fonts generacted during the session for duplicated
++  UniqueID and shows those. Still, this does not quarantee that these
++  UniqueIDs won't overlap with some other fonts. The UniqueIDs are
++  generated as hash values from the font names, so it's guaranteed
++  that if the `<tt>convert</tt>' script runs multiple times it will
++  generate the same UniqueIDs during each run. See further description 
++  of this option in the <A HREF="README.html">README</A> file.
++<p>
++
++<!-- ==item * -->
++<b><tt>GENUID</tt></b> - if the value is set to <b><tt>YES</tt></b> then create
++  the <tt>.pfb</tt> files, otherwise the <tt>.pfa</tt> files. The <tt>.pfb</tt>
++  files are more compact but contain binary data, so you may experience some
++  troubles when transferring them through the network.
++<p>
++<!-- ==back -->
++
++The following parameters are used to locate the other scripts and
++configuration files. By default the scripts do a bit of guessing for them:
++they search in the <b>ttf2pt1</b> installation directory if <b>ttf2pt1</b>
++was installed or otherwise suppose that you are running `<tt>convert</tt>' with
++`<tt>scripts</tt>' subdirectory being the current directory.
++<p>
++
++<!-- ==over 2 -->
++<!-- ==item * -->
++<b><tt>ENCDIR</tt></b> - directory containing the descriptions of encodings
++<br>
++<!-- ==item * -->
++<b><tt>MAPDIR</tt></b> - directory containing the external map files
++<p>
++<!-- ==back -->
++
++Besides that a few parameters are built into the `<tt>convert</tt>' script itself.
++You probably won't need to change them:
++<p>
++
++<!-- ==over 2 -->
++<!-- ==item * -->
++<tt><b>T1ASM</b></tt>, <tt><b>TTF2PT1</b></tt>, <tt><b>TRANS</b></tt>, <tt><b>T1FDIR</b></tt>, <tt><b>FORCEISO</b></tt> - paths to the other script
++<p>
++<!-- ==back -->
++
++Also there are a few parameters controlling the installation of
++fonts for Ghostscript. Please look at their description in the 
++<A HREF="#gs">Ghostscript</a> section of documentation or in the <b>ttf2pt1_x2gs(1)</b>
++manual page before running `<tt>convert</tt>'. If these parameters are
++set, `<tt>convert</tt>' will call the `<tt>x2gs</tt>' script automatically
++to install the newly converted fonts in Ghostscript.
++<p>
++
++After creating the configuration file run the `<tt>convert</tt>' script. Look at
++the result and the log file in <tt>DSTDIR</tt>.
++<p>
++
++Add the directory with newly converted fonts to the configuration
++of X server or font server. For most of the systems this step is
++very straightforward. For HP-UX it's rather tricky and poorly
++documented, so the file <A HREF="FONTS.hpux.html">FONTS.hpux</A> gives a short description.
++<p>
++
++If you don't have the privileges of the root user, you still can
++configure your private font server. Just use some non-standard
++port number (see <A HREF="FONTS.hpux.html">FONTS.hpux</A> for an example, exept that you won't
++need all the HP-related stuff on any other system).
++<p>
++<!-- =stop -->
++
++<H4>
++Known Problems
++</H4>
++<!
++--------------
++>
++<!-- =section cv BUGS -->
++<!-- ==head2 Known problems -->
++
++<ul>
++<li> One catch is that the X11 Type 1 font library has a rather low limit
++  on the font size. Because of this the fonts with  more complicated
++  outlines and the enabled hint substitution may not fit into
++  this limit. The same applies to the fonts with very complicated
++  outlines or with very many glyphs (especially the fonts with
++  over 256 glyphs). So you will need to excercise caution with
++  these options if you plan using these fonts with X11. Some vendors 
++  such as HP provide the Type 1 implementation licensed from Adobe 
++  which should have no such problem.
++<p>
++
++  But there is a solution even for the generic X11. A patch located
++  in the subdirectory `<tt>app/X11</tt>' fixes this problem as well
++  as some other minor problems. Its description is provided in
++  <A HREF="app/X11/README.html">app/X11/README</A>.
++<p>
++
++  To fix the X11 font library, you have to get the X11 sources. I
++  can recommend the ftp sites of the XFree86 project <A HREF="ftp://ftp.xfree86.org">ftp://ftp.xfree86.org</A>
++  or of the Open Group <A HREF="ftp://ftp.x.org">ftp://ftp.x.org</A>. This patch was made on the sources
++  of XFree86 so you may have better success with applying it to the
++  XFree86 distribution. After you have got the sources, make sure
++  that you can compile them. Then apply the patch as described.
++  Make sure that it was applied properly. Compile the sources again
++  (actually, you need only the fonts library, the fonts server, and
++  possibly the X server). It would be prudent now to save your old
++  font library, font server and, possibly, X server. Then install
++  the new recently compiled versions of these files. Of course,
++  if you know someone who already has compiled these files for the
++  same OS as yours, you can just copy the binary fles from him.
++<p>
++
++  Alas, building the X11 system from the source code is not the
++  easiest thing in the world and if you have no experience it
++  can be quite difficult. In this case just avoid the aforementioned
++  features or check each converted font to make sure that it
++  works properly.
++<p>
++
++<li> The Type1 font library from the standard X11 distribution
++  does not work on HP-UX (at least, up to 10.01). The font server
++  supplied with HP-UX up to 10.01 is also broken. Starting from 
++  HP-UX 10.20 (I don't know about 10.10) they supply a proprietary font 
++  library and the converted fonts work fine with it, provided that
++  they are configured properly (see the file <A HREF="FONTS.hpux.html">FONTS.hpux</A>).
++<p>
++
++<li> The <tt>fonts.scale</tt> files created by the older versions of the
++  <tt>ttf2pt1</tt> installation program (up to release 3.1) have conflicted 
++  with the language definitions of the <tt>Xfsft</tt> font server and
++  parts of it included into XFree86. To overcome this incompatibility
++  the never versions creats the <tt>fonts.scale</tt> file describing all the
++  fonts as belonging to the <tt>adobe-fontspecific</tt> encoding and
++  the <tt>fonts.alias</tt> file with the proper names. The drawback of
++  this solution is that <tt>xlsfonts</tt> gives the list of twice more
++  fonts. But as a side effect the option <tt><b>ENFORCEISO</b></tt> in
++  `<tt>convert.cfg</tt>' is not required for X11 any more.
++<p>
++
++<li> The conversion script has no support for Eastern multi-plane fonts.
++  Contribution of such a support would be welcome.
++<p>
++</ul>
++<!-- =stop -->
++<!-- =section cv FILES -->
++<!-- ==over 2 -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/scripts/convert.cfg.sample -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/scripts/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/README -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/FONTS -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_BINDIR/ttf2pt1 -->
++<!-- ==back -->
++<!-- =stop -->
++<!-- =section cv SEE ALSO -->
++<!-- ==over 4 -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1_x2gs(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;t1asm(1)&gt; -->
++<!-- ==back -->
++<!-- =stop -->
++
++<A NAME="gs"></A>
++<H3>
++Ghostscript
++</H3>
++<!
++===========
++>
++<!-- =section gs NAME -->
++<!-- =text B&lt;ttf2pt1_x2gs&gt; - font installer for Ghostscript -->
++<!-- =stop -->
++
++<!-- =section gs DESCRIPTION -->
++The fonts generated with <b>ttf2pt1</b> work fine with Ghostscript by
++themselves. The script `<b>x2gs</b>' (or `<b>ttf2pt1_x2gs</b>' when installed
++into a public directory, to avoid name conflicts with other
++programs) links the font files from the X11 direcotry into the Ghostscript 
++directory and automatically creates the description file (<tt>Fontmap</tt>) 
++in Ghostscript format.
++<!-- =stop -->
++
++It's called as:
++<p>
++
++<!-- =section gs SYNOPSIS -->
++<!-- =text ttf2pt1_x2gs B&lt;[config-file]&gt; -->
++<!-- =stop -->
++<blockquote>
++  x2gs <i>[config-file]</i>
++</blockquote>
++
++<!-- =section gs DESCRIPTION -->
++If the configuration file is not specified as an argument then the file
++`<TT>convert.cfg</TT>' in the current directory is used, just like the
++`<tt>convert</tt>' script does. Indeed, this configuration file is used for 
++both scripts.
++<p>
++
++The Ghostscript-related parameters in the configuration file are:
++<p>
++
++<b><tt>DSTDIR</tt></b> - the X11 font directory used by `<tt>x2gs</tt>' as the
++  source of the fonts. This parameter is common with the X11 
++  configuration.
++<p>
++
++<b><tt>GSDIR</tt></b> - the base directory of Ghostsript. If this
++  parameter is set to an empty string then `<tt>convert</tt>' won't
++  call `<tt>x2gs</tt>'. So if you want to get only the X11 fonts
++  installed then set this parameter to an empty string. This 
++  directory may vary on various system, so please check your 
++  system and set this value accordingly before running the script.
++<p>
++
++<b><tt>GSFONTDIR</tt></b> - the font directory of Ghostscript. In the standard
++  Ghostscript installation it's a subdirectory of <tt>GSDIR</tt> 
++  but some systems may use completely different directories.
++<p>
++
++<b><tt>GSCONFDIR</tt></b> - the configuration subdirectory of Ghostscript
++  that contains the <tt>Fontmap</tt> file.
++<p>
++
++<b><tt>INSTALLFONTMAP</tt></b> - if the value is set to <b><tt>YES</tt></b> then 
++  install the entries for the new fonts right into the main 
++  <tt>Fontmap</tt> file. Otherwise just leave the file <tt>Fontmap.ttf</tt> 
++  in the Ghostscript configuration directory.
++<p>
++
++
++After preparing the configuration file run the script. It symbolicaly links 
++all the font files and creates the description file <tt>Fontmap.ttf</tt> in 
++<tt>GSCONDFIR</tt>. After that there are two choices. 
++<p>
++
++If the option <tt>INSTALLFONTMAP</tt> was set to <tt>YES</tt> then 
++the font descriptions are also automatically installed into the
++master <tt>Fontmap</tt> file. The script is clever enough to
++detect if it was run multiple times with the same directories
++and if so it replaces the old <tt>Fontmap</tt> entries with
++the new ones instead of just accumulating all of them. You
++may also run it multiple times for multiple X11 directories
++and all the results will be properly collected in the <tt>Fontmap</tt>.
++But it's your responsibility to watch that the names of the
++font files don't overlap. If the X11 font directory gets
++renamed then you have to remove its font entries from the
++<tt>Fontmap</tt> and only after that re-run `<tt>x2gs</tt>'
++for the new directory. 
++<p>
++
++On the other hand if the option <tt>INSTALLFONTMAP</tt> was set to 
++<tt>NO</tt> then go to the <tt>GSCONFDIR</tt> directory and insert the 
++contents of <tt>Fontmap.ttf</tt> into the <tt>Fontmap</tt> file
++manually. This step may be left manual to make the installation
++a little bit more safe. 
++<p>
++
++After that you may also want to redefine some of the aliases in 
++<tt>Fontmap</tt> to refer to the newly installed fonts.
++But the redefinition of the aliases may be dangerous if the width of
++characters in the new font will be different from the old font.
++Alas, there is no visible solution of this problem yet.
++<p>
++<!-- =stop -->
++<!-- =section gs FILES -->
++<!-- ==over 2 -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/scripts/convert.cfg.sample -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/scripts/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/README -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/FONTS -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_BINDIR/ttf2pt1 -->
++<!-- ==back -->
++<!-- =stop -->
++<!-- =section gs SEE ALSO -->
++<!-- ==over 4 -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1_convert(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;t1asm(1)&gt; -->
++<!-- ==back -->
++<!-- =stop -->
++
++<A NAME="win"></A>
++<H3>
++MS Windows
++</H3>
++<!
++===========
++>
++
++<b>Ttf2pt1</b> can be built on Windows either with native compiler or in
++POSIX emulation mode.
++<p>
++
++Native MS Windows compilers require a different way to build the converter 
++instead of the Makefile (their <tt>make</tt> programs commonly are quite weird
++and limited in capabilities). An example of batch file <tt>winbuild.bat</tt> 
++is provided for MS Visual C/C++. Probably it can be easily adapted for other 
++32-bit Windows and DOS compilers. The important part is to define the 
++preprocessor symbol WINDOWS during compilation.
++<p>
++
++Cygnus <tt>make</tt> almost supports full Makefiles but not quite. Seems
++like its POSIX support is also of the same quality "almost but not quite".
++So another command file <tt>cygbuild.sh</tt> is provided for Cygnus GNU C, also 
++with the preprocessor symbol WINDOWS defined. It is intended to be run from
++the Cygnus BASH shell. To run the programs produced by the Cygnus compiler 
++the Cygnus library file <tt>CYGWIN1.DLL</tt> should be copied first into 
++<tt>C:\WINDOWS</tt>.
++<p>
++
++To run the accompanying scripts Perl for Windows will be required as well as 
++other tools from the Cygnus set.
++<p>
++
++The Windows support was not particularly tested, so in case of problems with
++building or running the converter please let us know.
++<p>
++
++The pre-built code (possibly of an older version) of ttf2pt1 for MS Windows is
++available from the GnuWin32 project from
++
++<A HREF="http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm">http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm</A>
++<p>
++
++<A NAME="netscape"></a>
++<H3>
++Netscape Navigator/Communicator
++</H3>
++<!
++===============================
++>
++
++Basically, the biggest problem with Netscape Navigator is that
++it has built-in fixed PostScript font names and built-in fixed 
++glyph tables for them. Oh, no, that's two! Let's start over: 
++basically the two biggest problems of Netscape Navigator are 
++that (one)it has built-in fixed PostScript font names and (two)
++built-in fixed glyph tables for them and (three) it always
++assumes that the fonts have ISOLatin1 encoding. OK, let's
++start over again: basically the three biggest problems of Netscape 
++Navigator are that (one) it has built-in fixed PostScript font names, 
++(two) built-in fixed glyph tables for them and (three) it always
++assumes that the fonts have ISOLatin1 encoding and (four) it
++does not remember the scaled font size between the sessions.
++You did not expect such a Spanish Inquisition, did you ? (<A HREF="#nsfn1">*</a>)
++<p>
++
++Luckily, we have solutions for all of these problems. They are
++located in the subdirectory `<tt>app/netscape</tt>' and described
++in <A HREF="app/netscape/README.html">app/netscape/README</a>.
++<p>
++
++<A NAME="nsfn1"></a>
++&nbsp;&nbsp;-------<br>
++&nbsp;&nbsp;<FONT SIZE=-1>*) See Monty Python's Flying Circus, episode 15</FONT></FONT>
++<p>
++
++<FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT>
++<H4>
++Netscape and cyrillic fonts<br>
++<!
++---------------------------
++>
++(courtesy of Zvezdan Petkovic)
++</H4>
++
++If you use TrueType fonts in your X, as I do, and you always get
++KOI8-R encoded pages, then your Netscape does not recognise windows-1251
++encoding.  Microsoft TrueType fonts simply declare all encodings they
++can support including KOI8-R.  For some reason, KOI8-R always wins over
++ISO-8859-5 in Netscape under X.  If you are reading other cyrillic
++languages besides Russian, you might want to either erase KOI8-R entries
++from the fonts.dir and fonts.scale files, or alternatively fix Netscape.
++I put this line in my .Xdefaults.
++<p>
++
++<blockquote><tt>
++    Netscape*documentFonts.charset*koi8-r:               iso-8859-5
++</tt></blockquote>
++<p>
++
++Notice that you can still read Russian sites without trouble because
++Netscape translates KOI8-R to ISO-8859-5 on the fly. I read both Russian
++and Serbian sites with no trouble.
++<p>
++
++<b>Note:</b> <i>If anybody knows the way to tell Netscape under Unix how to 
++recognise {windows,ibm,cp}-1251 encoded fonts, I'd like to hear about that.</i>
++<p>
++
++<A NAME="rpm"></a>
++<H3>
++Linux RPM package
++</H3>
++<!
++=================
++>
++
++The spec file for the creation of a Linux RPM package is located in 
++<tt>app/RPM</tt>. It has been contributed by Johan Vromans.  When 
++<tt>make all</tt> is ran in the main directory it among the other 
++things creates the version of itself adapted to Linux in <tt>app/RPM</tt>,
++you may want to copy that version back to the main directory.
++<p>
++
++<B>Warning:</B> Please note that the install section is incomplete, and 
++the installed scripts won't work until the paths inside them
++are corrected.
++<p>
++
++<A NAME="framemaker"></a>
++<H3>
++FrameMaker
++</H3>
++<!
++==========
++>
++
++The fonts and AFM files generated by the version 3.2 and higher 
++should work with Framemaker without problems. The AFM files 
++generated by the previous versions of the converter require a 
++line added to them:
++<p>
++
++&nbsp;&nbsp;<tt>EncodingScheme FontSpecific</tt>
++<p>
++
++And the underscores in the font names of the font and AFM files 
++generated by the older versions may need to be changed to dashes.
++<p>
++
++<B>NOTE by Jason Baietto:</B> Ignore the directions in the Frame on-line docs 
++that say to put a "serverdict begin 0 exitserver" line in the pfa files.  
++Doing this caused both my printer and ghostscript to choke on the resulting
++output from FrameMaker, so I would not advise doing this (though your
++mileage may vary).
++<p>
++
++<A NAME="soffice"></a>
++<H3>
++StarOffice
++</H3>
++<!
++==========
++>
++
++StarOffice 5.1x has been reported to crash if the <tt>.afm</tt> file contains
++spaces in the values of such statements as <b>Version</b>, <b>Weight</b> etc.
++These spaces are permitted by the Adobe spec, so this is a problem of
++StarOffice. The easiest way to fix these <tt>.afm</tt> files for StarOffice
++is to remove spaces in these strings or remove these strings (in case if
++they are optional) at all. This can be done automatically with a <tt>sed</tt>
++script. It seems that StarOffice 5.2 has this problem fixed, so we decided to
++spend no efforts on providing workarounds for 5.1 with <tt>ttf2pt1</tt>.
++<p>
++
++</BODY>
++</HTML>
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ft.c xserver/hw/xprint/extras/ttf2pt1/ft.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/ft.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ft.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,808 @@
++/*
++ * The font parser using the FreeType library version 2.
++ *
++ * see COPYRIGHT
++ *
++ */
++
++#ifdef USE_FREETYPE
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <sys/types.h>
++
++#include <ft2build.h>
++#include FT_FREETYPE_H
++#include FT_TRUETYPE_TABLES_H
++#include FT_BBOX_H
++#include FT_GLYPH_H
++
++#include FT_CONFIG_CONFIG_H
++#include FT_CONFIG_OPTIONS_H
++#include FT_ERRORS_H
++#include FT_SYSTEM_H
++#include FT_IMAGE_H
++#include FT_TYPES_H
++#include FT_OUTLINE_H
++#include FT_MODULE_H
++#include FT_RENDER_H
++#include FT_TYPE1_TABLES_H
++#include FT_TRUETYPE_IDS_H
++#include FT_TRUETYPE_TAGS_H
++#include FT_MULTIPLE_MASTERS_H
++#include FT_SFNT_NAMES_H
++
++#ifdef XP_PSTEXT
++#include "os.h"
++#include "Xproto.h"
++#include "font.h"
++#include "fontstruct.h"
++#include "fntfilst.h"
++#include "fontutil.h"
++#include "fontenc.h"
++#include "ft.h"
++#define NOT_IN_FTFUNCS
++#include "ftfuncs.h"
++#endif /* XP_PSTEXT */
++
++#include "pt1.h"
++#include "global.h"
++
++/* prototypes of call entries */
++static void openfont(char *fname, char *arg);
++static void closefont( void);
++static int getnglyphs ( void);
++static int glnames( GLYPH *glyph_list);
++static void glmetrics( GLYPH *glyph_list);
++static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
++static void fnmetrics( struct font_metrics *fm);
++static void glpath( int glyphno, GLYPH *glyph_list);
++static void kerning( GLYPH *glyph_list);
++
++/* globals */
++
++/* front-end descriptor */
++struct frontsw freetype_sw = {
++	/*name*/       "ft",
++	/*descr*/      "based on the FreeType2 library",
++	/*suffix*/     { "ttf", "ttc", "otf", "otc", "pfa", "pfb" },
++	/*open*/       openfont,
++	/*close*/      closefont,
++	/*nglyphs*/    getnglyphs,
++	/*glnames*/    glnames,
++	/*glmetrics*/  glmetrics,
++	/*glenc*/      glenc,
++	/*fnmetrics*/  fnmetrics,
++	/*glpath*/     glpath,
++	/*kerning*/    kerning,
++};
++
++/* statics */
++
++static char * dupcnstring( unsigned char *s, int len);
++
++#ifndef XP_PSTEXT
++static FT_Library library;
++#endif /* !XP_PSTEXT */
++static FT_Face face;
++
++static int enc_type, enc_found;
++
++/* SFNT functions do not seem to be included by default in FT2beta8 */
++#define ENABLE_SFNT
++
++/*
++ * Open font and prepare to return information to the main driver.
++ * May print error and warning messages.
++ * Exit on error.
++ */
++
++static void
++openfont(
++	char *fname,
++	char *arg /* unused now */
++)
++{
++	FT_Error error;
++
++#ifdef XP_PSTEXT
++    extern FT_Face    xp_pstext_ft_face;
++    extern FT_Library ftypeLibrary; /* defined in xc/lib/font/FreeType/ftfuncs.c */
++
++    face = xp_pstext_ft_face;
++#else
++	if( FT_Init_FreeType( &library ) ) {
++		fprintf(stderr, "** FreeType initialization failed\n");
++		exit(1);
++	}
++
++	if( error = FT_New_Face( library, fname, 0, &face ) ) {
++		if ( error == FT_Err_Unknown_File_Format )
++			fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
++		else
++			fprintf(stderr, "**** Cannot access %s ****\n", fname);
++		exit(1);
++	}
++#endif /* XP_PSTEXT */
++
++	if(FT_HAS_FIXED_SIZES(face)) {
++		WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
++	}
++	if(FT_HAS_MULTIPLE_MASTERS(face)) {
++		WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
++	}
++
++	if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
++
++	enc_found = 0;
++}
++
++/*
++ * Close font.
++ * Exit on error.
++ */
++
++static void
++closefont(
++	void
++)
++{
++#ifdef XP_PSTEXT
++        /* NOP */
++#else
++	if( FT_Done_Face(face) ) {
++		WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
++	}
++	if( FT_Done_FreeType(library) ) {
++		WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
++	}
++#endif /* XP_PSTEXT */
++}
++
++/*
++ * Get the number of glyphs in font.
++ */
++
++static int
++getnglyphs (
++	void
++)
++{
++	if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
++	return (int)face->num_glyphs;
++}
++
++/*
++ * Get the names of the glyphs.
++ * Returns 0 if the names were assigned, non-zero if the font
++ * provides no glyph names.
++ */
++
++static int
++glnames(
++	GLYPH *glyph_list
++)
++{
++#define MAX_NAMELEN	1024
++
++#ifdef XP_PSTEXT
++	char          buf[1024];
++	long          i;
++    FT_Error      error;
++
++#ifdef XP_ONLY_BLOCKS
++    extern unsigned long xp_font_block_offset;
++    extern FTFontPtr     xp_xtf;
++    int                  bc; /* block counter */
++    
++    
++    /* FixMe: This code should use PsOut_Get_FreeType_Glyph_Name() instead of
++     * duplicating the code
++     */
++    for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) {
++        /* Remap X11 font index to FreeType font index */
++        i = FTRemap(face, &xp_xtf->mapping, bc);
++        
++        if( i >= face->num_glyphs )
++          continue;
++#else
++	for(i=0; i < face->num_glyphs; i++) {
++#endif /* XP_ONLY_BLOCKS */
++        if( FT_Has_PS_Glyph_Names(face) ) {
++          error = FT_Get_Glyph_Name(face, i, buf, MAX_NAMELEN);
++        }
++        else
++        {
++          error = -1;
++        }
++    
++		if( error ) {
++          /* Check for unicode mapping
++           * See Adobe document "Unicode and Glyph Names"
++           * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp)
++           */
++          if( (xp_xtf->mapping.mapping->type == FONT_ENCODING_UNICODE) &&
++              (i < 0xFFFE) )
++          {
++            sprintf(buf, "uni%04lx", i);
++          }
++          else
++          {
++            sprintf(buf, "ch%02lx", i);
++          }
++		}
++		glyph_list[i].name = strdup(buf);
++		if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, buf);
++		if (glyph_list[i].name == NULL) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++	}
++
++	return 0;
++#else
++	char bf[1024];
++	long i;
++
++	if( ! FT_HAS_GLYPH_NAMES(face) ) {
++		WARNING_1 fprintf(stderr, "Font has no glyph names\n");
++		return 1;
++	}
++
++	for(i=0; i < face->num_glyphs; i++) {
++		if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
++			sprintf(bf, "_g_%d", i);
++			WARNING_2 fprintf(stderr,
++				"Glyph No. %d has no postscript name, becomes %s\n", i, bf);
++		}
++		glyph_list[i].name = strdup(bf);
++		if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
++		if (glyph_list[i].name == NULL) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++	}
++
++	return 0;
++#endif /* XP_PSTEXT */
++}
++
++/*
++ * Get the metrics of the glyphs.
++ */
++
++static void
++glmetrics(
++	GLYPH *glyph_list
++)
++{
++	GLYPH          *g;
++	int i;
++	FT_Glyph_Metrics *met;
++	FT_BBox bbox;
++	FT_Glyph gly;
++
++#ifdef XP_ONLY_BLOCKS
++    extern unsigned long xp_font_block_offset;
++    extern FTFontPtr     xp_xtf;
++    int                  bc; /* block counter */
++    
++    for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) {
++        /* Remap X11 font index to FreeType font index */
++        i = FTRemap(face, &xp_xtf->mapping, bc);
++        
++        if( i >= face->num_glyphs )
++          continue;
++        
++#else
++	for(i=0; i < face->num_glyphs; i++) {
++#endif /* XP_ONLY_BLOCKS */
++		g = &(glyph_list[i]);
++
++		if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
++			fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
++			continue;
++		}
++
++		met = &face->glyph->metrics;
++
++		if(FT_HAS_HORIZONTAL(face)) {
++			g->width = met->horiAdvance;
++			g->lsb = met->horiBearingX;
++		} else {
++			WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
++			g->width = met->width;
++			g->lsb = 0;
++		}
++
++		if( FT_Get_Glyph(face->glyph, &gly) ) {
++			fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
++			continue;
++		}
++
++		FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
++		g->xMin = bbox.xMin;
++		g->yMin = bbox.yMin;
++		g->xMax = bbox.xMax;
++		g->yMax = bbox.yMax;
++
++		g->ttf_pathlen = face->glyph->outline.n_points;
++	}
++}
++
++/*
++ * Get the original encoding of the font. 
++ * Returns 1 for if the original encoding is Unicode, 2 if the
++ * original encoding is other 16-bit, 0 if 8-bit.
++ */
++
++static int
++glenc(
++	GLYPH *glyph_list,
++	int *encoding,
++	int *unimap
++)
++{
++#ifdef XP_PSTEXT
++	int                  i,
++                         e;
++	unsigned             code;
++    extern FTFontPtr     xp_xtf;
++    extern unsigned long xp_font_block_offset;
++        
++    enc_found = 1;
++    enc_type  = 0;
++    
++	for(i=0; i<ENCTABSZ; i++) {
++		if(encoding[i] != -1)
++			continue;
++
++        /* Remap X11 font index to FreeType font index */
++        code = FTRemap(face, &xp_xtf->mapping, xp_font_block_offset+i);
++
++		if(code == 0)
++			continue; /* .notdef */
++
++		encoding[i] = code;
++	}
++        
++	return enc_type;
++#else
++	int i, e;
++	unsigned code;
++
++	if(ISDBG(FT)) 
++		for(e=0; e < face->num_charmaps; e++) {
++			fprintf(stderr, "found encoding pid=%d eid=%d\n", 
++				face->charmaps[e]->platform_id,
++				face->charmaps[e]->encoding_id);
++		}
++
++	if(enc_found)
++		goto populate_map;
++
++	enc_type = 0;
++
++	/* first check for an explicit PID/EID */
++
++	if(force_pid != -1) {
++		for(e=0; e < face->num_charmaps; e++) {
++			if(face->charmaps[e]->platform_id == force_pid
++			&& face->charmaps[e]->encoding_id == force_eid) {
++				WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
++					force_pid, force_eid);
++				if( FT_Set_Charmap(face, face->charmaps[e]) ) {
++					fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
++					exit(1);
++				}
++				enc_type = 1;
++				goto populate_map;
++			}
++		}
++		fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
++			force_pid, force_eid);
++		exit(1);
++	}
++
++	/* next check for a direct Adobe mapping */
++
++	if(!forcemap) {
++		for(e=0; e < face->num_charmaps; e++) {
++			if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
++				WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
++				if( FT_Set_Charmap(face, face->charmaps[e]) ) {
++					fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
++					exit(1);
++				}
++				goto populate_map;
++			}
++		}
++	}
++
++	for(e=0; e < face->num_charmaps; e++) {
++		if(face->charmaps[e]->platform_id == 3) {
++			switch(face->charmaps[e]->encoding_id) {
++			case 0:
++				WARNING_1 fputs("Found Symbol Encoding\n", stderr);
++				break;
++			case 1:
++				WARNING_1 fputs("Found Unicode Encoding\n", stderr);
++				enc_type = 1;
++				break;
++			default:
++				WARNING_1 {
++					fprintf(stderr,
++					"****MS Encoding ID %d not supported****\n",
++						face->charmaps[e]->encoding_id);
++					fputs("Treating it like Symbol encoding\n", stderr);
++				}
++				break;
++			}
++			break;
++		}
++	}
++	if(e >= face->num_charmaps) {
++		WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
++		e = 0;
++	}
++	
++	if( FT_Set_Charmap(face, face->charmaps[e]) ) {
++		fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
++		exit(1);
++	}
++
++populate_map:
++	enc_found = 1;
++	for(i=0; i<ENCTABSZ; i++) {
++		if(encoding[i] != -1)
++			continue;
++		if(enc_type == 1 || forcemap) {
++			code = unimap[i];
++			if(code == (unsigned) -1)
++				continue;
++		} else
++			code = i;
++
++		code = FT_Get_Char_Index(face, code);
++		if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
++		if(code == 0)
++			continue; /* .notdef */
++		encoding[i] = code;
++	}
++
++	return enc_type;
++#endif /* XP_PSTEXT */
++}
++
++/* duplicate a string with counter to a 0-terminated string */
++static char *
++dupcnstring(
++	unsigned char *s,
++	int len
++)
++{
++	char *res, *out;
++	int i, c;
++	static int warned=0;
++
++	if(( res = malloc(len+1) )==NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++
++	out = res;
++	for(i=0; i<len; i++) {
++		if(( c=s[i] )>=' ' && c!=127)
++			*out++ = c;
++		else if(!warned) {
++			warned=1;
++			WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n");
++		}
++	}
++	*out = 0;
++	return res;
++}
++
++/*
++ * Get the font metrics
++ */
++static void 
++fnmetrics(
++	struct font_metrics *fm
++)
++{
++	char *str;
++	static char *fieldstocheck[3];
++#ifdef ENABLE_SFNT
++	FT_SfntName sn;
++#endif /* ENABLE_SFNT */
++	int i;
++
++	fm->italic_angle = 0.0; /* FreeType hides the angle */
++	fm->underline_position = face->underline_position;
++	fm->underline_thickness = face->underline_thickness;
++	fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
++
++	fm->ascender = face->ascender;
++	fm->descender = face->descender;
++
++	fm->units_per_em =  face->units_per_EM;
++
++	fm->bbox[0] = face->bbox.xMin;
++	fm->bbox[1] = face->bbox.yMin;
++	fm->bbox[2] = face->bbox.xMax;
++	fm->bbox[3] = face->bbox.yMax;
++
++#ifdef ENABLE_SFNT
++	if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
++#endif /* ENABLE_SFNT */
++		fm->name_copyright = "";
++#ifdef ENABLE_SFNT
++	else
++		fm->name_copyright = dupcnstring(sn.string, sn.string_len);
++#endif /* ENABLE_SFNT */
++
++	fm->name_family = face->family_name;
++
++	fm->name_style = face->style_name;
++	if(fm->name_style == NULL)
++		fm->name_style = "";
++
++#ifdef ENABLE_SFNT
++	if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) 
++#endif /* ENABLE_SFNT */
++	{
++		int len;
++
++		len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
++		if(( fm->name_full = malloc(len) )==NULL) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++		strcpy(fm->name_full, fm->name_family);
++		if(strlen(fm->name_style) != 0) {
++			strcat(fm->name_full, " ");
++			strcat(fm->name_full, fm->name_style);
++		}
++	} 
++#ifdef ENABLE_SFNT
++	else
++		fm->name_full = dupcnstring(sn.string, sn.string_len);
++#endif /* ENABLE_SFNT */
++
++#ifdef ENABLE_SFNT
++	if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
++#endif /* ENABLE_SFNT */
++		fm->name_version = "1.0";
++#ifdef ENABLE_SFNT
++	else
++		fm->name_version = dupcnstring(sn.string, sn.string_len);
++#endif /* ENABLE_SFNT */
++
++#ifdef XP_PSTEXT
++    {
++      extern const char *xp_psfontname;
++      
++      fm->name_ps = strdup(xp_psfontname);
++
++      /* Handle the rare case if a family name was not provided by the TTF
++       * font (like Solaris TTF fonts in /usr/openwin/lib/locale/ko.UTF-8/X11/fonts/TrueType,
++       * /usr/openwin/lib/locale/ko/X11/fonts/TrueType) - in this case we
++       * have to generate a family name somehow... */
++      if(fm->name_family == NULL)
++        fm->name_family = fm->name_ps;
++    }
++#else
++
++#ifdef ENABLE_SFNT
++	if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
++#endif /* ENABLE_SFNT */
++		if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++#ifdef ENABLE_SFNT
++	} else
++		fm->name_ps = dupcnstring(sn.string, sn.string_len);
++#endif /* ENABLE_SFNT */
++
++#endif /* XP_PSTEXT */
++
++	for(i=0; fm->name_ps[i]!=0; i++)
++		if(fm->name_ps[i] == ' ')
++			fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m */
++
++	/* guess the boldness from the font names */
++	fm->force_bold=0;
++
++	fieldstocheck[0] = fm->name_style;
++	fieldstocheck[1] = fm->name_full;
++	fieldstocheck[2] = fm->name_ps;
++
++	for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
++		str=fieldstocheck[i];
++		for(i=0; str[i]!=0; i++) {
++			if( (str[i]=='B'
++				|| str[i]=='b' 
++					&& ( i==0 || !isalpha(str[i-1]) )
++				)
++			&& !strncmp("old",&str[i+1],3)
++			&& !islower(str[i+4])
++			) {
++				fm->force_bold=1;
++				break;
++			}
++		}
++	}
++}
++
++/*
++ * Functions to decompose the outlines
++ */
++
++static GLYPH *curg;
++static double lastx, lasty;
++
++static int
++outl_moveto(
++	FT_Vector *to,
++	void *unused
++)
++{
++	double tox, toy;
++
++	tox = fscale((double)to->x); toy = fscale((double)to->y);
++
++	/* FreeType does not do explicit closepath() */
++	if(curg->lastentry) {
++		g_closepath(curg);
++	}
++	fg_rmoveto(curg, tox, toy);
++	lastx = tox; lasty = toy;
++
++	return 0;
++}
++
++static int
++outl_lineto(
++	FT_Vector *to,
++	void *unused
++)
++{
++	double tox, toy;
++
++	tox = fscale((double)to->x); toy = fscale((double)to->y);
++
++	fg_rlineto(curg, tox, toy);
++	lastx = tox; lasty = toy;
++
++	return 0;
++}
++
++static int
++outl_conicto(
++	FT_Vector *control1,
++	FT_Vector *to,
++	void *unused
++)
++{
++	double c1x, c1y, tox, toy;
++
++	c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
++	tox = fscale((double)to->x); toy = fscale((double)to->y);
++
++	fg_rrcurveto(curg,
++		(lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
++		(2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
++		tox, toy );
++	lastx = tox; lasty = toy;
++
++	return 0;
++}
++
++static int
++outl_cubicto(
++	FT_Vector *control1,
++	FT_Vector *control2,
++	FT_Vector *to,
++	void *unused
++)
++{
++	double c1x, c1y, c2x, c2y, tox, toy;
++
++	c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
++	c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
++	tox = fscale((double)to->x); toy = fscale((double)to->y);
++
++	fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
++	lastx = tox; lasty = toy;
++
++	return 0;
++}
++
++static FT_Outline_Funcs ft_outl_funcs = {
++	outl_moveto,
++	outl_lineto,
++	outl_conicto,
++	outl_cubicto,
++	0,
++	0
++};
++
++/*
++ * Get the path of contrours for a glyph.
++ */
++
++static void
++glpath(
++	int glyphno,
++	GLYPH *glyf_list
++)
++{
++	FT_Outline *ol;
++
++	curg = &glyf_list[glyphno];
++
++	if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) 
++	|| face->glyph->format != ft_glyph_format_outline ) {
++		fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
++		return;
++	}
++
++	ol = &face->glyph->outline;
++	lastx = 0.0; lasty = 0.0;
++
++	if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
++		fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
++		return;
++	}
++
++	/* FreeType does not do explicit closepath() */
++	if(curg->lastentry) {
++		g_closepath(curg);
++	}
++
++	if(ol->flags & ft_outline_reverse_fill) {
++		assertpath(curg->entries, __FILE__, __LINE__, curg->name);
++		reversepaths(curg);
++	}
++}
++
++/*
++ * Get the kerning data.
++ */
++
++static void
++kerning(
++	GLYPH *glyph_list
++)
++{
++	int	i, j, n;
++	int	nglyphs = face->num_glyphs;
++	FT_Vector k;
++	GLYPH *gl;
++
++	if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
++        WARNING_1 fputs("No Kerning data\n", stderr);
++		return;
++	}
++
++	for(i=0; i<nglyphs; i++)  {
++		if( (glyph_list[i].flags & GF_USED) ==0)
++			continue;
++		for(j=0; j<nglyphs; j++) {
++			if( (glyph_list[j].flags & GF_USED) ==0)
++				continue;
++			if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
++				continue;
++			if( k.x == 0 )
++				continue;
++
++			addkernpair(i, j, k.x);
++		}
++	}
++}
++
++#endif
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/global.h xserver/hw/xprint/extras/ttf2pt1/global.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/global.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/global.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,174 @@
++/*
++ * see COPYRIGHT
++ */
++
++
++/* options */
++
++extern int      encode;	/* encode the resulting file */
++extern int      pfbflag;	/* produce compressed file */
++extern int      wantafm;	/* want to see .afm instead of .t1a on stdout */
++extern int      correctvsize;	/* try to correct the vertical size of characters */
++extern int      wantuid;	/* user wants UniqueID entry in the font */
++extern int      allglyphs;	/* convert all glyphs, not only 256 of them */
++extern int      warnlevel;	/* the level of permitted warnings */
++extern int      forcemap; /* do mapping even on non-Unicode fonts */
++/* options - maximal limits */
++extern int      max_stemdepth;	/* maximal depth of stem stack in interpreter */
++/* options - debugging */
++extern int      absolute;	/* print out in absolute values */
++extern int      reverse;	/* reverse font to Type1 path directions */
++/* options - suboptions of Outline Processing */
++extern int      optimize;	/* enables space optimization */
++extern int      smooth;	/* enable smoothing of outlines */
++extern int      transform;	/* enables transformation to 1000x1000 matrix */
++extern int      hints;	/* enables autogeneration of hints */
++extern int      subhints;	/* enables autogeneration of substituted hints */
++extern int      trybold;	/* try to guess whether the font is bold */
++extern int      correctwidth;	/* try to correct the character width */
++extern int      vectorize;	/* vectorize the bitmaps */
++extern int      use_autotrace;	/* use the autotrace library on bitmap */
++/* options - suboptions of File Generation */
++extern int      gen_pfa;	/* generate the font file */
++extern int      gen_afm;	/* generate the metrics file */
++extern int      gen_dvienc;	/* generate the dvips encoding file */
++
++/* not quite options to select a particular source encoding */
++extern int      force_pid; /* specific platform id */
++extern int      force_eid; /* specific encoding id */
++
++/* other globals */
++extern FILE    *null_file, *pfa_file, *afm_file, *dvienc_file;
++extern int      numglyphs;
++
++/* warnings */
++
++#define WARNING_1	if(warnlevel >= 1)
++#define WARNING_2	if(warnlevel >= 2)
++#define WARNING_3	if(warnlevel >= 3)
++#define WARNING_4	if(warnlevel >= 4)
++
++/*
++ * Bitmap control macros
++ */
++
++#define BITMAP_BYTES(size)	(((size)+7)>>3)
++#define DEF_BITMAP(name, size)	unsigned char name[BITMAP_BYTES(size)]
++#define SET_BITMAP(name, bit)	( name[(bit)>>3] |= (1<<((bit)&7)) )
++#define CLR_BITMAP(name, bit)	( name[(bit)>>3] &= ~(1<<((bit)&7)) )
++#define IS_BITMAP(name, bit)	( name[(bit)>>3] & (1<<((bit)&7)) )
++
++/* debugging */
++
++/* debug flags */
++#define DEBUG_UNICODE	0x00000001 /* unicode to 8-bit code conversion */
++#define DEBUG_MAINSTEMS	0x00000002 /* glyph-wide main stem generation */
++#define DEBUG_SUBSTEMS	0x00000004 /* substituted stem generation */
++#define DEBUG_STEMS	(DEBUG_MAINSTEMS|DEBUG_SUBSTEMS)
++#define DEBUG_REVERSAL	0x00000008 /* reversal of the paths */
++#define DEBUG_FIXCVDIR	0x00000010 /* fixcvdir() */
++#define DEBUG_STEMOVERLAP	0x00000020 /* stemoverlap() */
++#define DEBUG_BLUESTEMS	0x00000040 /* markbluestems() */
++#define DEBUG_STRAIGHTEN	0x00000080 /* markbluestems() */
++#define DEBUG_EXTMAP	0x00000100 /* parsing of external map */
++#define DEBUG_TOINT	0x00000200 /* conversion of path to integer */
++#define DEBUG_BUILDG	0x00000400 /* building of glyph path */
++#define DEBUG_QUAD	0x00000800 /* splitting curves by quadrants */
++#define DEBUG_SQEQ	0x00001000 /* square equation solver */
++#define DEBUG_COMPOSITE	0x00002000 /* handling of composite glyphs */
++#define DEBUG_FCONCISE	0x00004000 /* normalization of curves */
++#define DEBUG_FT		0x00008000 /* FreeType front-end */
++#define DEBUG_BITMAP	0x00010000 /* conversion from bitmap */
++#define DEBUG_DISABLED	0x80000000 /* special flag: temporary disable debugging */
++
++#if 0
++/* at what we want to look now */
++#ifndef DEBUG
++#	define DEBUG (DEBUG_BITMAP)
++#endif
++
++/* uncomment the next line if debugging data is wanted for one glyph only */
++#define DBG_GLYPH	"C118"  /* */
++#endif
++
++#if 1
++#	define ISDBG(name)	(0)
++#	define ENABLEDBG(condition) (0)
++#	define DISABLEDBG(condition) (0)
++#else
++	extern int debug; /* collection of the flags */
++/* this ISDBG will only work on ANSI C, not K&R */
++#	define ISDBG(name)	( (debug & DEBUG_DISABLED) ? 0 : (debug & (DEBUG_##name)) )
++#	define ENABLEDBG(condition) ( (condition) ? (debug&=~DEBUG_DISABLED) : 0 )
++#	define DISABLEDBG(condition) ( (condition) ? (debug|=DEBUG_DISABLED) : 0 )
++#endif
++
++#ifdef DBG_GLYPH
++#	define DBG_TO_GLYPH(g) DISABLEDBG( strcmp( (g)->name, DBG_GLYPH ) )
++#	define DBG_FROM_GLYPH(g) ENABLEDBG(1)
++#else
++#	define DBG_TO_GLYPH(g) (0)
++#	define DBG_FROM_GLYPH(g) (0)
++#endif
++
++/* prototypes */
++int iscale( int val);
++double fscale( double val);
++int unicode_rev_lookup( int unival);
++void bmp_outline( GLYPH *g, int scale, char *bmap,
++	int xsz, int ysz, int xoff, int yoff);
++int isign( int x);
++int fsign( double x);
++
++/* global metrics for a font */
++
++struct font_metrics {
++	/* post */
++	double	italic_angle;
++	short	underline_position;
++	short	underline_thickness;
++	short	is_fixed_pitch;
++
++	/* hhea */
++	short	ascender; 
++	short	descender;
++
++	/* head */
++	unsigned short	units_per_em;
++	short   bbox[4];
++
++	/* name */
++	char	*name_copyright;
++	char	*name_family;
++	char	*name_style;
++	char	*name_full;
++	char	*name_version;
++	char	*name_ps;
++
++	/* other */
++	int		force_bold;
++};
++
++/* size of the encoding table - glyphs beyond 255 are actually unnumbered */
++
++#define ENCTABSZ	1024
++
++/* switch table structure for front-ends */
++
++#define MAXSUFFIX	10
++
++struct frontsw {
++	char  *name; /* name of the front end */
++	char  *descr; /* description of the front end */
++	char  *suffix[MAXSUFFIX]; /* possible file name suffixes */
++
++	void  (*open)(char *fname, char *arg); /* open font file */
++	void  (*close)(void); /* close font file */
++	int   (*nglyphs)(void); /* get the number of glyphs */
++	int   (*glnames)(GLYPH *glyphs); /* get the names of glyphs */
++	void  (*glmetrics)(GLYPH *glyphs); /* get the metrics of glyphs */
++	int   (*glenc)(GLYPH *glyphs, int *enc, int *unimap); /* get the encoding */
++	void  (*fnmetrics)(struct font_metrics *fm); /* get the font metrics */
++	void  (*glpath)(int glyphno, GLYPH *glyphs); /* get the glyph path */
++	void  (*kerning)(GLYPH *glyph_list); /* extract the kerning data */
++};
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/Makefile xserver/hw/xprint/extras/ttf2pt1/Makefile
+--- xserver-old/hw/xprint/extras/ttf2pt1/Makefile	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/Makefile	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,279 @@
++
++# This file should be configured before running `make'.
++# Uncomment or change the values that are relevant for your OS.
++
++# The preferred C compiler (by default use the OS-specific default value).
++# For BSD/OS, FreeBSD, Linux (all flavors), NetBSD, OpenBSD the default
++# compiler is GNU C. 
++# (Note please the politically correct ordering by alphabet ! :-)
++#
++# Use GNU C even if it's not the default compiler
++#
++#CC=gcc
++#
++# Use the standard ANSI C compiler on HP-UX even if it's not default
++#
++#CC=c89
++
++#
++# The system-dependent flags for the C compiler
++#
++# Default
++
++CFLAGS_SYS= -O
++
++# For GNU C
++#
++#CFLAGS_SYS= -O2
++#
++# For GNU C with long options support library (Linux etc.)
++#
++#CFLAGS_SYS= -O2 -D_GNU_SOURCE
++#
++# For GNU C on HP-UX/PA-RISC 1.1
++#
++#CFLAGS_SYS= -O2 -Wa,-w
++#
++# For the standard ANSI C on HP-UX
++#
++#CFLAGS_SYS= +O2 -D_HPUX_SOURCE
++
++#
++# The system-dependent libraries
++#
++# Defalut (for the BSD-style OSes)
++
++LIBS_SYS= -lm
++
++# For SystemV (such as SCO, UnixWare, Solaris, but _NOT_ Linux or HP-UX)
++#
++#LIBS_SYS= -lm -lsocket
++
++#
++# The flags for C compiler for the FreeType-2 library (disabled by default). 
++# This WON'T BUILD with FT2-beta8, use the FreeType release 2.0.4
++# http://download.sourceforge.net/freetype/freetype-2.0.4.tar.gz
++
++CFLAGS_FT= 
++
++# To enable use of the FreeType-2 library
++# (if the include and lib directory do not match your installation,
++# modify them), also uncomment LIBS_FT
++#
++#CFLAGS_FT = -DUSE_FREETYPE -I/usr/local/include/freetype2 -I/usr/local/include
++
++# 
++# The FreeType-2 library flags (disabled by default)
++
++LIBS_FT=
++
++# To enable use of the FreeType-2 library
++# (if the include and lib directory do not match your installation,
++# modify them), also uncomment CFLAGS_FT
++#
++#LIBS_FT= -L/usr/local/lib -lfreetype
++
++#
++# The flags for C compiler for the Autotrace library (disabled by default). 
++# USE OF THIS FEATURE IS STRONGLY DISCOURAGED, THE BUILT-IN TRACING
++# (AKA VECTORIZATION) PROVIDES MUCH BETTER RESULTS.
++# The tested version is 0.29a (and the fonts produced with it are
++# absolutely not usable).
++# http://download.sourceforge.net/autotrace/autotrace-0.29.tar.gz
++
++CFLAGS_AT= 
++
++# To enable use of the Autotrace library
++# (if the include and lib directory do not match your installation,
++# modify them), also uncomment LIBS_AT
++#
++#CFLAGS_AT = -DUSE_AUTOTRACE -I/usr/local/include
++
++# 
++# The Autotrace library flags (disabled by default)
++
++LIBS_AT=
++
++# To enable use of the Autotrace library
++# (if the include and lib directory do not match your installation,
++# modify them), also uncomment CFLAGS_AT
++#
++#LIBS_AT= -L/usr/local/lib -lautotrace
++
++#
++# Preference of front-ends if multiple parsers match a file
++# (by default the build-in front-end takes preference over FreeType)
++
++CFLAGS_PREF=
++
++# To prefer FreeType (if enabled):
++#
++#CFLAGS_PREF= -DPREFER_FREETYPE
++
++# Uncomment the second line to not compile t1asm into ttf2pt1
++CFLAGS_EXTT1ASM=
++#CFLAGS_EXTT1ASM= -DEXTERNAL_T1ASM
++
++CFLAGS= $(CFLAGS_SYS) $(CFLAGS_FT) $(CFLAGS_AT) $(CFLAGS_PREF)
++LIBS= $(LIBS_SYS) $(LIBS_FT) $(LIBS_AT)
++
++# Installation-related stuff
++# 
++# The base dir for installation and subdirs in it
++INSTDIR = /usr/local
++# for binaries
++BINDIR = $(INSTDIR)/bin
++# for binaries of little general interest
++LIBXDIR = $(INSTDIR)/libexec/ttf2pt1
++# for scripts, maps/encodings etc.
++SHAREDIR = $(INSTDIR)/share/ttf2pt1
++MANDIR = $(INSTDIR)/man
++
++# owner and group of installed files
++OWNER = root
++GROUP = bin
++
++# After you have configured the Makefile, comment out the following
++# definition:
++warning: docs
++	@echo >&2
++	@echo "  You have to configure the Makefile before running make!" >&2
++	@echo "(or if you are lazy and hope that it will work as is run \`make all')">&2
++	@echo >&2
++
++DOCS=CHANGES README FONTS FONTS.hpux encodings/README other/README \
++	app/X11/README app/netscape/README app/TeX/README
++
++SUBDIRS = app encodings maps scripts other
++TXTFILES = README* FONTS* CHANGES* COPYRIGHT
++
++MANS1=ttf2pt1.1 ttf2pt1_convert.1 ttf2pt1_x2gs.1
++MANS=$(MANS1) $(MANS5)
++
++all:	t1asm ttf2pt1 docs mans rpm
++
++docs: $(DOCS)
++
++mans: $(MANS) 
++
++clean:
++	rm -f t1asm ttf2pt1 *.o app/RPM/Makefile app/RPM/*.spec *.core core.* core
++	( cd other && make clean; )
++	( cd app/netscape && make clean; )
++
++veryclean: clean
++	rm -f $(DOCS) $(MANS)
++
++rpm: app/RPM/Makefile app/RPM/ttf2pt1.spec
++
++ttf2pt1.1: README.html
++	scripts/html2man . . <README.html
++
++ttf2pt1_convert.1 ttf2pt1_x2gs.1: FONTS.html
++	scripts/html2man . . <FONTS.html
++
++app/RPM/Makefile: Makefile
++	sed 's/^CFLAGS_SYS.*=.*$$/CFLAGS_SYS= -O2 -D_GNU_SOURCE/;/warning:/,/^$$/s/^/#/' <Makefile >app/RPM/Makefile
++
++app/RPM/ttf2pt1.spec: app/RPM/ttf2pt1.spec.src version.h
++	sed 's/^Version:.*/Version: '`grep TTF2PT1_VERSION version.h| cut -d\" -f2`'/' <app/RPM/ttf2pt1.spec.src  >$@
++
++t1asm: t1asm.c
++	$(CC) $(CFLAGS) -o t1asm -DSTANDALONE t1asm.c $(LIBS)
++
++ttf2pt1.o: ttf2pt1.c ttf.h pt1.h global.h version.h
++	$(CC) $(CFLAGS) -c ttf2pt1.c
++
++pt1.o: pt1.c ttf.h pt1.h global.h
++	$(CC) $(CFLAGS) -c pt1.c
++
++ttf.o: ttf.c ttf.h pt1.h global.h
++	$(CC) $(CFLAGS) -c ttf.c
++
++ft.o: ft.c pt1.h global.h
++	$(CC) $(CFLAGS) -c ft.c
++
++bdf.o: bdf.c pt1.h global.h
++	$(CC) $(CFLAGS) -c bdf.c
++
++bitmap.o: bitmap.c pt1.h global.h
++	$(CC) $(CFLAGS) -c bitmap.c
++
++runt1asm.o: runt1asm.c global.h
++	$(CC) $(CFLAGS) $(CFLAGS_EXTT1ASM) -c runt1asm.c
++
++ttf2pt1:	ttf2pt1.o pt1.o runt1asm.o ttf.o ft.o bdf.o bitmap.o
++	$(CC) $(CFLAGS) -o ttf2pt1 ttf2pt1.o pt1.o runt1asm.o ttf.o ft.o bdf.o bitmap.o $(LIBS)
++
++CHANGES: CHANGES.html
++	scripts/unhtml <CHANGES.html >CHANGES
++
++README: README.html
++	scripts/unhtml <README.html >README
++
++encodings/README: encodings/README.html
++	scripts/unhtml <encodings/README.html >encodings/README
++
++other/README: other/README.html
++	scripts/unhtml <other/README.html >other/README
++
++app/X11/README: app/X11/README.html
++	scripts/unhtml <app/X11/README.html >app/X11/README
++
++app/netscape/README: app/netscape/README.html
++	scripts/unhtml <app/netscape/README.html >app/netscape/README
++
++app/TeX/README: app/TeX/README.html
++	scripts/unhtml <app/TeX/README.html >app/TeX/README
++
++FONTS: FONTS.html
++	scripts/unhtml <FONTS.html >FONTS
++
++FONTS.hpux: FONTS.hpux.html
++	scripts/unhtml <FONTS.hpux.html >FONTS.hpux
++
++install: all
++	scripts/inst_dir $(BINDIR) $(OWNER) $(GROUP) 0755
++	scripts/inst_dir $(LIBXDIR) $(OWNER) $(GROUP) 0755
++	scripts/inst_dir $(SHAREDIR) $(OWNER) $(GROUP) 0755
++	scripts/inst_dir $(MANDIR)/man1 $(OWNER) $(GROUP) 0755
++	scripts/inst_dir $(MANDIR)/man5 $(OWNER) $(GROUP) 0755
++	cp -R $(TXTFILES) $(SUBDIRS) $(SHAREDIR)
++	chown -R $(OWNER) $(SHAREDIR)
++	chgrp -R $(GROUP) $(SHAREDIR)
++	chmod -R go-w $(SHAREDIR)
++	scripts/inst_file ttf2pt1 $(BINDIR)/ttf2pt1 $(OWNER) $(GROUP) 0755
++	[ -f $(BINDIR)/t1asm ] || scripts/inst_file t1asm $(LIBXDIR)/t1asm $(OWNER) $(GROUP) 0755
++	sed 's|^TTF2PT1_BINDIR=$$|TTF2PT1_BINDIR=$(BINDIR)|;\
++		s|^TTF2PT1_LIBXDIR=$$|TTF2PT1_LIBXDIR=$(LIBXDIR)|;\
++		s|^TTF2PT1_SHAREDIR=$$|TTF2PT1_SHAREDIR=$(SHAREDIR)|;' <scripts/convert >cvt.tmp
++	scripts/inst_file cvt.tmp $(BINDIR)/ttf2pt1_convert $(OWNER) $(GROUP) 0755
++	scripts/inst_file cvt.tmp $(SHAREDIR)/scripts/convert $(OWNER) $(GROUP) 0755
++	rm cvt.tmp
++	scripts/inst_file scripts/x2gs $(BINDIR)/ttf2pt1_x2gs $(OWNER) $(GROUP) 0755
++	for i in $(MANS1); do { \
++		sed 's|TTF2PT1_BINDIR|$(BINDIR)|;\
++			s|TTF2PT1_LIBXDIR|$(LIBXDIR)|;\
++			s|TTF2PT1_SHAREDIR|$(SHAREDIR)|;' <$$i >$(MANDIR)/man1/$$i \
++		&& chown $(OWNER) $(MANDIR)/man1/$$i \
++		&& chgrp $(GROUP) $(MANDIR)/man1/$$i \
++		&& chmod 0644 $(MANDIR)/man1/$$i \
++		|| exit 1; \
++	} done
++
++uninstall:
++	rm -f $(BINDIR)/ttf2pt1 $(BINDIR)/ttf2pt1_convert $(BINDIR)/ttf2pt1_x2gs
++	rm -rf $(LIBXDIR)
++	rm -rf $(SHAREDIR)
++	for i in $(MANS1); do { \
++		rm -f $(MANDIR)/man1/$$i $(MANDIR)/man1/$$i.gz; \
++	} done
++	
++
++# targets for automatic generation of releases and snapshots
++
++snapshot:
++	scripts/mkrel snapshot
++
++release:
++	scripts/mkrel release
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/pt1.c xserver/hw/xprint/extras/ttf2pt1/pt1.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/pt1.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/pt1.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,7374 @@
++/*
++ * see COPYRIGHT
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <time.h>
++#include <ctype.h>
++#include <math.h>
++
++#ifndef WINDOWS
++#	include <netinet/in.h>
++#	include <unistd.h>
++#else
++#	include "windows.h"
++#endif
++
++#include "ttf.h"
++#include "pt1.h"
++#include "global.h"
++
++/* big and small values for comparisons */
++#define FBIGVAL	(1e20)
++#define FEPS	(100000./FBIGVAL)
++
++/* names of the axes */
++#define X	0
++#define	Y	1
++
++/* the GENTRY extension structure used in fforceconcise() */
++
++struct gex_con {
++	double d[2 /*X, Y*/]; /* sizes of curve */
++	double sin2; /* squared sinus of the angle to the next gentry */
++	double len2; /* squared distance between the endpoints */
++
++/* number of reference dots taken from each curve */
++#define NREFDOTS	3
++
++	double dots[NREFDOTS][2]; /* reference dots */
++
++	int flags; /* flags for gentry and tits joint to the next gentry */
++/* a vertical or horizontal line may be in 2 quadrants at once */
++#define GEXF_QUL	0x00000001 /* in up-left quadrant */
++#define GEXF_QUR	0x00000002 /* in up-right quadrant */
++#define GEXF_QDR	0x00000004 /* in down-right quadrant */
++#define GEXF_QDL	0x00000008 /* in down-left quadrant */
++#define GEXF_QMASK	0x0000000F /* quadrant mask */
++
++/* if a line is nearly vertical or horizontal, we remember that idealized quartant too */
++#define GEXF_QTO_IDEAL(f)	(((f)&0xF)<<4)
++#define GEXF_QFROM_IDEAL(f)	(((f)&0xF0)>>4)
++#define GEXF_IDQ_L	0x00000090 /* left */
++#define GEXF_IDQ_R	0x00000060 /* right */
++#define GEXF_IDQ_U	0x00000030 /* up */
++#define GEXF_IDQ_D	0x000000C0 /* down */
++
++/* possibly can be joined with conditions: 
++ * (in order of increasing preference, the numeric order is important) 
++ */
++#define GEXF_JLINE	0x00000100 /* into one line */
++#define GEXF_JIGN	0x00000200 /* if one entry's tangent angle is ignored */
++#define GEXF_JID	0x00000400 /* if one entry is idealized to hor/vert */
++#define GEXF_JFLAT	0x00000800 /* if one entry is flattened */
++#define GEXF_JGOOD	0x00001000 /* perfectly, no additional maodifications */
++
++#define GEXF_JMASK	0x00001F00 /* the mask of all above */
++#define GEXF_JCVMASK	0x00001E00 /* the mask of all above except JLINE */
++
++/* which entry needs to be modified for conditional joining */
++#define GEXF_JIGN1	0x00002000
++#define GEXF_JIGN2	0x00004000
++#define GEXF_JIGNDIR(dir)	(GEXF_JIGN1<<(dir))
++#define GEXF_JID1	0x00008000
++#define GEXF_JID2	0x00010000
++#define GEXF_JIDDIR(dir)	(GEXF_JID1<<(dir))
++#define GEXF_JFLAT1	0x00020000
++#define GEXF_JFLAT2	0x00040000
++#define GEXF_JFLATDIR(dir)	(GEXF_JFLAT1<<(dir))
++
++#define GEXF_VERT	0x00100000 /* is nearly vertical */
++#define GEXF_HOR	0x00200000 /* is nearly horizontal */
++#define GEXF_FLAT	0x00400000 /* is nearly flat */
++
++#define GEXF_VDOTS	0x01000000 /* the dots are valid */
++
++	signed char isd[2 /*X,Y*/]; /* signs of the sizes */
++};
++typedef struct gex_con GEX_CON;
++
++/* convenience macros */
++#define	X_CON(ge)	((GEX_CON *)((ge)->ext))
++#define X_CON_D(ge)	(X_CON(ge)->d)
++#define X_CON_DX(ge)	(X_CON(ge)->d[0])
++#define X_CON_DY(ge)	(X_CON(ge)->d[1])
++#define X_CON_ISD(ge)	(X_CON(ge)->isd)
++#define X_CON_ISDX(ge)	(X_CON(ge)->isd[0])
++#define X_CON_ISDY(ge)	(X_CON(ge)->isd[1])
++#define X_CON_SIN2(ge)	(X_CON(ge)->sin2)
++#define X_CON_LEN2(ge)	(X_CON(ge)->len2)
++#define X_CON_F(ge)	(X_CON(ge)->flags)
++
++/* performance statistics about guessing the concise curves */
++static int ggoodcv=0, ggoodcvdots=0, gbadcv=0, gbadcvdots=0;
++
++int      stdhw, stdvw;	/* dominant stems widths */
++int      stemsnaph[12], stemsnapv[12];	/* most typical stem width */
++
++int      bluevalues[14];
++int      nblues;
++int      otherblues[10];
++int      notherb;
++int      bbox[4];	/* the FontBBox array */
++double   italic_angle;
++
++GLYPH   *glyph_list;
++int    encoding[ENCTABSZ];	/* inverse of glyph[].char_no */
++int    kerning_pairs = 0;
++
++/* prototypes */
++static void fixcvdir( GENTRY * ge, int dir);
++static void fixcvends( GENTRY * ge);
++static int fgetcvdir( GENTRY * ge);
++static int igetcvdir( GENTRY * ge);
++static int fiszigzag( GENTRY *ge);
++static int iiszigzag( GENTRY *ge);
++static GENTRY * freethisge( GENTRY *ge);
++static void addgeafter( GENTRY *oge, GENTRY *nge );
++static GENTRY * newgentry( int flags);
++static void debugstems( char *name, STEM * hstems, int nhs, STEM * vstems, int nvs);
++static int addbluestems( STEM *s, int n);
++static void sortstems( STEM * s, int n);
++static int stemoverlap( STEM * s1, STEM * s2);
++static int steminblue( STEM *s);
++static void markbluestems( STEM *s, int nold);
++static int joinmainstems( STEM * s, int nold, int useblues);
++static void joinsubstems( STEM * s, short *pairs, int nold, int useblues);
++static void fixendpath( GENTRY *ge);
++static void fdelsmall( GLYPH *g, double minlen);
++static void alloc_gex_con( GENTRY *ge);
++static double fjointsin2( GENTRY *ge1, GENTRY *ge2);
++#if 0
++static double fcvarea( GENTRY *ge);
++#endif
++static double fcvval( GENTRY *ge, int axis, double t);
++static void fsampledots( GENTRY *ge, double dots[][2], int ndots);
++static void fnormalizege( GENTRY *ge);
++static void fanalyzege( GENTRY *ge);
++static void fanalyzejoint( GENTRY *ge);
++static void fconcisecontour( GLYPH *g, GENTRY *ge);
++static double fclosegap( GENTRY *from, GENTRY *to, int axis,
++	double gap, double *ret);
++
++int
++isign(
++     int x
++)
++{
++	if (x > 0)
++		return 1;
++	else if (x < 0)
++		return -1;
++	else
++		return 0;
++}
++
++int
++fsign(
++     double x
++)
++{
++	if (x > 0.0)
++		return 1;
++	else if (x < 0.0)
++		return -1;
++	else
++		return 0;
++}
++
++static GENTRY *
++newgentry(
++	int flags
++)
++{
++	GENTRY         *ge;
++
++	ge = calloc(1, sizeof(GENTRY));
++
++	if (ge == 0) {
++		fprintf(stderr, "***** Memory allocation error *****\n");
++		exit(255);
++	}
++	ge->stemid = -1;
++	ge->flags = flags;
++	/* the rest is set to 0 by calloc() */
++	return ge;
++}
++
++/*
++ * Routines to print out Postscript functions with optimization
++ */
++
++void
++rmoveto(
++	int dx,
++	int dy
++)
++{
++	if (optimize && dx == 0)
++		fprintf(pfa_file, "%d vmoveto\n", dy);
++	else if (optimize && dy == 0)
++		fprintf(pfa_file, "%d hmoveto\n", dx);
++	else
++		fprintf(pfa_file, "%d %d rmoveto\n", dx, dy);
++}
++
++void
++rlineto(
++	int dx,
++	int dy
++)
++{
++	if (optimize && dx == 0 && dy == 0)	/* for special pathologic
++						 * case */
++		return;
++	else if (optimize && dx == 0)
++		fprintf(pfa_file, "%d vlineto\n", dy);
++	else if (optimize && dy == 0)
++		fprintf(pfa_file, "%d hlineto\n", dx);
++	else
++		fprintf(pfa_file, "%d %d rlineto\n", dx, dy);
++}
++
++void
++rrcurveto(
++	  int dx1,
++	  int dy1,
++	  int dx2,
++	  int dy2,
++	  int dx3,
++	  int dy3
++)
++{
++	/* first two ifs are for crazy cases that occur surprisingly often */
++	if (optimize && dx1 == 0 && dx2 == 0 && dx3 == 0)
++		rlineto(0, dy1 + dy2 + dy3);
++	else if (optimize && dy1 == 0 && dy2 == 0 && dy3 == 0)
++		rlineto(dx1 + dx2 + dx3, 0);
++	else if (optimize && dy1 == 0 && dx3 == 0)
++		fprintf(pfa_file, "%d %d %d %d hvcurveto\n",
++			dx1, dx2, dy2, dy3);
++	else if (optimize && dx1 == 0 && dy3 == 0)
++		fprintf(pfa_file, "%d %d %d %d vhcurveto\n",
++			dy1, dx2, dy2, dx3);
++	else
++		fprintf(pfa_file, "%d %d %d %d %d %d rrcurveto\n",
++			dx1, dy1, dx2, dy2, dx3, dy3);
++}
++
++void
++closepath(void)
++{
++	fprintf(pfa_file, "closepath\n");
++}
++
++/*
++ * Many of the path processing routines exist (or will exist) in
++ * both floating-point and integer version. Fimally most of the
++ * processing will go in floating point and the integer processing
++ * will become legacy.
++ * The names of floating routines start with f, names of integer 
++ * routines start with i, and those old routines existing in one 
++ * version only have no such prefix at all.
++ */
++
++/*
++** Routine that checks integrity of the path, for debugging
++*/
++
++void
++assertpath(
++	   GENTRY * from,
++	   char *file,
++	   int line,
++	   char *name
++)
++{
++	GENTRY         *first, *pe, *ge;
++	int	isfloat;
++
++	if(from==0)
++		return;
++	isfloat = (from->flags & GEF_FLOAT);
++	pe = from->prev;
++	for (ge = from; ge != 0; pe = ge, ge = ge->next) {
++		if( (ge->flags & GEF_FLOAT) ^ isfloat ) {
++			fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++			fprintf(stderr, "float flag changes from %s to %s at 0x%p (type %c, prev type %c)\n",
++				(isfloat ? "TRUE" : "FALSE"), (isfloat ? "FALSE" : "TRUE"), ge, ge->type, pe->type);
++			abort();
++		}
++		if (pe != ge->prev) {
++			fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++			fprintf(stderr, "unidirectional chain 0x%x -next-> 0x%x -prev-> 0x%x \n",
++				pe, ge, ge->prev);
++			abort();
++		}
++
++		switch(ge->type) {
++		case GE_MOVE:
++			break;
++		case GE_PATH:
++			if (ge->prev == 0) {
++				fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++				fprintf(stderr, "empty path at 0x%x \n", ge);
++				abort();
++			}
++			break;
++		case GE_LINE:
++		case GE_CURVE:
++			if(ge->frwd->bkwd != ge) {
++				fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++				fprintf(stderr, "unidirectional chain 0x%x -frwd-> 0x%x -bkwd-> 0x%x \n",
++					ge, ge->frwd, ge->frwd->bkwd);
++				abort();
++			}
++			if(ge->prev->type == GE_MOVE) {
++				first = ge;
++				if(ge->bkwd->next->type != GE_PATH) {
++					fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++					fprintf(stderr, "broken first backlink 0x%x -bkwd-> 0x%x -next-> 0x%x \n",
++						ge, ge->bkwd, ge->bkwd->next);
++					abort();
++				}
++			}
++			if(ge->next->type == GE_PATH) {
++				if(ge->frwd != first) {
++					fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name);
++					fprintf(stderr, "broken loop 0x%x -...-> 0x%x -frwd-> 0x%x \n",
++						first, ge, ge->frwd);
++					abort();
++				}
++			}
++			break;
++		}
++
++	}
++}
++
++void
++assertisfloat(
++	GLYPH *g,
++	char *msg
++)
++{
++	if( !(g->flags & GF_FLOAT) ) {
++		fprintf(stderr, "**! Glyph %s is not float: %s\n", g->name, msg);
++		abort();
++	}
++	if(g->lastentry) {
++		if( !(g->lastentry->flags & GEF_FLOAT) ) {
++			fprintf(stderr, "**! Glyphs %s last entry is int: %s\n", g->name, msg);
++			abort();
++		}
++	}
++}
++
++void
++assertisint(
++	GLYPH *g,
++	char *msg
++)
++{
++	if( (g->flags & GF_FLOAT) ) {
++		fprintf(stderr, "**! Glyph %s is not int: %s\n", g->name, msg);
++		abort();
++	}
++	if(g->lastentry) {
++		if( (g->lastentry->flags & GEF_FLOAT) ) {
++			fprintf(stderr, "**! Glyphs %s last entry is float: %s\n", g->name, msg);
++			abort();
++		}
++	}
++}
++
++
++/*
++ * Routines to save the generated data about glyph
++ */
++
++void
++fg_rmoveto(
++	  GLYPH * g,
++	  double x,
++	  double y)
++{
++	GENTRY         *oge;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: f rmoveto(%g, %g)\n", g->name, x, y);
++
++	assertisfloat(g, "adding float MOVE");
++
++	if ((oge = g->lastentry) != 0) {
++		if (oge->type == GE_MOVE) {	/* just eat up the first move */
++			oge->fx3 = x;
++			oge->fy3 = y;
++		} else if (oge->type == GE_LINE || oge->type == GE_CURVE) {
++			fprintf(stderr, "Glyph %s: MOVE in middle of path\n", g->name);
++		} else {
++			GENTRY         *nge;
++
++			nge = newgentry(GEF_FLOAT);
++			nge->type = GE_MOVE;
++			nge->fx3 = x;
++			nge->fy3 = y;
++
++			oge->next = nge;
++			nge->prev = oge;
++			g->lastentry = nge;
++		}
++	} else {
++		GENTRY         *nge;
++
++		nge = newgentry(GEF_FLOAT);
++		nge->type = GE_MOVE;
++		nge->fx3 = x;
++		nge->fy3 = y;
++		nge->bkwd = (GENTRY*)&g->entries;
++		g->entries = g->lastentry = nge;
++	}
++
++	if (0 && ISDBG(BUILDG))
++		dumppaths(g, NULL, NULL);
++}
++
++void
++ig_rmoveto(
++	  GLYPH * g,
++	  int x,
++	  int y)
++{
++	GENTRY         *oge;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: i rmoveto(%d, %d)\n", g->name, x, y);
++
++	assertisint(g, "adding int MOVE");
++
++	if ((oge = g->lastentry) != 0) {
++		if (oge->type == GE_MOVE) {	/* just eat up the first move */
++			oge->ix3 = x;
++			oge->iy3 = y;
++		} else if (oge->type == GE_LINE || oge->type == GE_CURVE) {
++			fprintf(stderr, "Glyph %s: MOVE in middle of path, ignored\n", g->name);
++		} else {
++			GENTRY         *nge;
++
++			nge = newgentry(0);
++			nge->type = GE_MOVE;
++			nge->ix3 = x;
++			nge->iy3 = y;
++
++			oge->next = nge;
++			nge->prev = oge;
++			g->lastentry = nge;
++		}
++	} else {
++		GENTRY         *nge;
++
++		nge = newgentry(0);
++		nge->type = GE_MOVE;
++		nge->ix3 = x;
++		nge->iy3 = y;
++		nge->bkwd = (GENTRY*)&g->entries;
++		g->entries = g->lastentry = nge;
++	}
++
++}
++
++void
++fg_rlineto(
++	  GLYPH * g,
++	  double x,
++	  double y)
++{
++	GENTRY         *oge, *nge;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: f rlineto(%g, %g)\n", g->name, x, y);
++
++	assertisfloat(g, "adding float LINE");
++
++	nge = newgentry(GEF_FLOAT);
++	nge->type = GE_LINE;
++	nge->fx3 = x;
++	nge->fy3 = y;
++
++	if ((oge = g->lastentry) != 0) {
++		if (x == oge->fx3 && y == oge->fy3) {	/* empty line */
++			/* ignore it or we will get in troubles later */
++			free(nge);
++			return;
++		}
++		if (g->path == 0) {
++			g->path = nge;
++			nge->bkwd = nge->frwd = nge;
++		} else {
++			oge->frwd = nge;
++			nge->bkwd = oge;
++			g->path->bkwd = nge;
++			nge->frwd = g->path;
++		}
++
++		oge->next = nge;
++		nge->prev = oge;
++		g->lastentry = nge;
++	} else {
++		WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name);
++		free(nge);
++	}
++
++	if (0 && ISDBG(BUILDG))
++		dumppaths(g, NULL, NULL);
++}
++
++void
++ig_rlineto(
++	  GLYPH * g,
++	  int x,
++	  int y)
++{
++	GENTRY         *oge, *nge;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: i rlineto(%d, %d)\n", g->name, x, y);
++
++	assertisint(g, "adding int LINE");
++
++	nge = newgentry(0);
++	nge->type = GE_LINE;
++	nge->ix3 = x;
++	nge->iy3 = y;
++
++	if ((oge = g->lastentry) != 0) {
++		if (x == oge->ix3 && y == oge->iy3) {	/* empty line */
++			/* ignore it or we will get in troubles later */
++			free(nge);
++			return;
++		}
++		if (g->path == 0) {
++			g->path = nge;
++			nge->bkwd = nge->frwd = nge;
++		} else {
++			oge->frwd = nge;
++			nge->bkwd = oge;
++			g->path->bkwd = nge;
++			nge->frwd = g->path;
++		}
++
++		oge->next = nge;
++		nge->prev = oge;
++		g->lastentry = nge;
++	} else {
++		WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name);
++		free(nge);
++	}
++
++}
++
++void
++fg_rrcurveto(
++	    GLYPH * g,
++	    double x1,
++	    double y1,
++	    double x2,
++	    double y2,
++	    double x3,
++	    double y3)
++{
++	GENTRY         *oge, *nge;
++
++	oge = g->lastentry;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: f rrcurveto(%g, %g, %g, %g, %g, %g)\n"
++			,g->name, x1, y1, x2, y2, x3, y3);
++
++	assertisfloat(g, "adding float CURVE");
++
++	if (oge && oge->fx3 == x1 && x1 == x2 && x2 == x3)	/* check if it's
++								 * actually a line */
++		fg_rlineto(g, x1, y3);
++	else if (oge && oge->fy3 == y1 && y1 == y2 && y2 == y3)
++		fg_rlineto(g, x3, y1);
++	else {
++		nge = newgentry(GEF_FLOAT);
++		nge->type = GE_CURVE;
++		nge->fx1 = x1;
++		nge->fy1 = y1;
++		nge->fx2 = x2;
++		nge->fy2 = y2;
++		nge->fx3 = x3;
++		nge->fy3 = y3;
++
++		if (oge != 0) {
++			if (x3 == oge->fx3 && y3 == oge->fy3) {
++				free(nge);	/* consider this curve empty */
++				/* ignore it or we will get in troubles later */
++				return;
++			}
++			if (g->path == 0) {
++				g->path = nge;
++				nge->bkwd = nge->frwd = nge;
++			} else {
++				oge->frwd = nge;
++				nge->bkwd = oge;
++				g->path->bkwd = nge;
++				nge->frwd = g->path;
++			}
++
++			oge->next = nge;
++			nge->prev = oge;
++			g->lastentry = nge;
++		} else {
++			WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name);
++			free(nge);
++		}
++	}
++
++	if (0 && ISDBG(BUILDG))
++		dumppaths(g, NULL, NULL);
++}
++
++void
++ig_rrcurveto(
++	    GLYPH * g,
++	    int x1,
++	    int y1,
++	    int x2,
++	    int y2,
++	    int x3,
++	    int y3)
++{
++	GENTRY         *oge, *nge;
++
++	oge = g->lastentry;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: i rrcurveto(%d, %d, %d, %d, %d, %d)\n"
++			,g->name, x1, y1, x2, y2, x3, y3);
++
++	assertisint(g, "adding int CURVE");
++
++	if (oge && oge->ix3 == x1 && x1 == x2 && x2 == x3)	/* check if it's
++								 * actually a line */
++		ig_rlineto(g, x1, y3);
++	else if (oge && oge->iy3 == y1 && y1 == y2 && y2 == y3)
++		ig_rlineto(g, x3, y1);
++	else {
++		nge = newgentry(0);
++		nge->type = GE_CURVE;
++		nge->ix1 = x1;
++		nge->iy1 = y1;
++		nge->ix2 = x2;
++		nge->iy2 = y2;
++		nge->ix3 = x3;
++		nge->iy3 = y3;
++
++		if (oge != 0) {
++			if (x3 == oge->ix3 && y3 == oge->iy3) {
++				free(nge);	/* consider this curve empty */
++				/* ignore it or we will get in troubles later */
++				return;
++			}
++			if (g->path == 0) {
++				g->path = nge;
++				nge->bkwd = nge->frwd = nge;
++			} else {
++				oge->frwd = nge;
++				nge->bkwd = oge;
++				g->path->bkwd = nge;
++				nge->frwd = g->path;
++			}
++
++			oge->next = nge;
++			nge->prev = oge;
++			g->lastentry = nge;
++		} else {
++			WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name);
++			free(nge);
++		}
++	}
++}
++
++void
++g_closepath(
++	    GLYPH * g
++)
++{
++	GENTRY         *oge, *nge;
++
++	if (ISDBG(BUILDG))
++		fprintf(stderr, "%s: closepath\n", g->name);
++
++	oge = g->lastentry;
++
++	if (g->path == 0) {
++		WARNING_1 fprintf(stderr, "Warning: **** closepath on empty path in glyph \"%s\" ****\n",
++			g->name);
++		if (oge == 0) {
++			WARNING_1 fprintf(stderr, "No previois entry\n");
++		} else {
++			WARNING_1 fprintf(stderr, "Previous entry type: %c\n", oge->type);
++			if (oge->type == GE_MOVE) {
++				g->lastentry = oge->prev;
++				if (oge->prev == 0)
++					g->entries = 0;
++				else
++					g->lastentry->next = 0;
++				free(oge);
++			}
++		}
++		return;
++	}
++
++	nge = newgentry(oge->flags & GEF_FLOAT); /* keep the same type */
++	nge->type = GE_PATH;
++
++	g->path = 0;
++
++	oge->next = nge;
++	nge->prev = oge;
++	g->lastentry = nge;
++
++	if (0 && ISDBG(BUILDG))
++		dumppaths(g, NULL, NULL);
++}
++
++/*
++ * * SB * Routines to smooth and fix the glyphs
++ */
++
++/*
++** we don't want to see the curves with coinciding middle and
++** outer points
++*/
++
++static void
++fixcvends(
++	  GENTRY * ge
++)
++{
++	int             dx, dy;
++	int             x0, y0, x1, y1, x2, y2, x3, y3;
++
++	if (ge->type != GE_CURVE)
++		return;
++
++	if(ge->flags & GEF_FLOAT) {
++		fprintf(stderr, "**! fixcvends(0x%x) on floating entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	x0 = ge->prev->ix3;
++	y0 = ge->prev->iy3;
++	x1 = ge->ix1;
++	y1 = ge->iy1;
++	x2 = ge->ix2;
++	y2 = ge->iy2;
++	x3 = ge->ix3;
++	y3 = ge->iy3;
++
++
++	/* look at the start of the curve */
++	if (x1 == x0 && y1 == y0) {
++		dx = x2 - x1;
++		dy = y2 - y1;
++
++		if ((dx == 0 && dy == 0)
++		    || (x2 == x3 && y2 == y3)) {
++			/* Oops, we actually have a straight line */
++			/*
++			 * if it's small, we hope that it will get optimized
++			 * later
++			 */
++			if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) {
++				ge->ix1 = x3;
++				ge->iy1 = y3;
++				ge->ix2 = x0;
++				ge->iy2 = y0;
++			} else {/* just make it a line */
++				ge->type = GE_LINE;
++			}
++		} else {
++			if (abs(dx) < 4 && abs(dy) < 4) {	/* consider it very
++								 * small */
++				ge->ix1 = x2;
++				ge->iy1 = y2;
++			} else if (abs(dx) < 8 && abs(dy) < 8) {	/* consider it small */
++				ge->ix1 += dx / 2;
++				ge->iy1 += dy / 2;
++			} else {
++				ge->ix1 += dx / 4;
++				ge->iy1 += dy / 4;
++			}
++			/* make sure that it's still on the same side */
++			if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) {
++				if (abs(x3 - x0) * abs(ge->iy1 - y0) > abs(y3 - y0) * abs(ge->ix1 - x0))
++					ge->ix1 += isign(dx);
++			} else {
++				if (abs(x3 - x0) * abs(ge->iy1 - y0) < abs(y3 - y0) * abs(ge->ix1 - x0))
++					ge->iy1 += isign(dy);
++			}
++
++			ge->ix2 += (x3 - x2) / 8;
++			ge->iy2 += (y3 - y2) / 8;
++			/* make sure that it's still on the same side */
++			if (abs(x3 - x0) * abs(y3 - y2) < abs(y3 - y0) * abs(x3 - x2)) {
++				if (abs(x3 - x0) * abs(y3 - ge->iy2) > abs(y3 - y0) * abs(x3 - ge->ix2))
++					ge->iy1 -= isign(y3 - y2);
++			} else {
++				if (abs(x3 - x0) * abs(y3 - ge->iy2) < abs(y3 - y0) * abs(x3 - ge->ix2))
++					ge->ix1 -= isign(x3 - x2);
++			}
++
++		}
++	} else if (x2 == x3 && y2 == y3) {
++		dx = x1 - x2;
++		dy = y1 - y2;
++
++		if (dx == 0 && dy == 0) {
++			/* Oops, we actually have a straight line */
++			/*
++			 * if it's small, we hope that it will get optimized
++			 * later
++			 */
++			if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) {
++				ge->ix1 = x3;
++				ge->iy1 = y3;
++				ge->ix2 = x0;
++				ge->iy2 = y0;
++			} else {/* just make it a line */
++				ge->type = GE_LINE;
++			}
++		} else {
++			if (abs(dx) < 4 && abs(dy) < 4) {	/* consider it very
++								 * small */
++				ge->ix2 = x1;
++				ge->iy2 = y1;
++			} else if (abs(dx) < 8 && abs(dy) < 8) {	/* consider it small */
++				ge->ix2 += dx / 2;
++				ge->iy2 += dy / 2;
++			} else {
++				ge->ix2 += dx / 4;
++				ge->iy2 += dy / 4;
++			}
++			/* make sure that it's still on the same side */
++			if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) {
++				if (abs(x3 - x0) * abs(ge->iy2 - y3) > abs(y3 - y0) * abs(ge->ix2 - x3))
++					ge->ix2 += isign(dx);
++			} else {
++				if (abs(x3 - x0) * abs(ge->iy2 - y3) < abs(y3 - y0) * abs(ge->ix2 - x3))
++					ge->iy2 += isign(dy);
++			}
++
++			ge->ix1 += (x0 - x1) / 8;
++			ge->iy1 += (y0 - y1) / 8;
++			/* make sure that it's still on the same side */
++			if (abs(x3 - x0) * abs(y0 - y1) < abs(y3 - y0) * abs(x0 - x1)) {
++				if (abs(x3 - x0) * abs(y0 - ge->iy1) > abs(y3 - y0) * abs(x0 - ge->ix1))
++					ge->iy1 -= isign(y0 - y1);
++			} else {
++				if (abs(x3 - x0) * abs(y0 - ge->iy1) < abs(y3 - y0) * abs(x0 - ge->ix1))
++					ge->ix1 -= isign(x0 - x1);
++			}
++
++		}
++	}
++}
++
++/*
++** After transformations we want to make sure that the resulting
++** curve is going in the same quadrant as the original one,
++** because rounding errors introduced during transformations
++** may make the result completeley wrong.
++**
++** `dir' argument describes the direction of the original curve,
++** it is the superposition of two values for the front and
++** rear ends of curve:
++**
++** >EQUAL - goes over the line connecting the ends
++** =EQUAL - coincides with the line connecting the ends
++** <EQUAL - goes under the line connecting the ends
++**
++** See CVDIR_* for exact definitions.
++*/
++
++static void
++fixcvdir(
++	 GENTRY * ge,
++	 int dir
++)
++{
++	int             a, b, c, d;
++	double          kk, kk1, kk2;
++	int             changed;
++	int             fdir, rdir;
++
++	if(ge->flags & GEF_FLOAT) {
++		fprintf(stderr, "**! fixcvdir(0x%x) on floating entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	fdir = (dir & CVDIR_FRONT) - CVDIR_FEQUAL;
++	if ((dir & CVDIR_REAR) == CVDIR_RSAME)
++		rdir = fdir; /* we need only isign, exact value doesn't matter */
++	else
++		rdir = (dir & CVDIR_REAR) - CVDIR_REQUAL;
++
++	fixcvends(ge);
++
++	c = isign(ge->ix3 - ge->prev->ix3);	/* note the direction of
++						 * curve */
++	d = isign(ge->iy3 - ge->prev->iy3);
++
++	a = ge->iy3 - ge->prev->iy3;
++	b = ge->ix3 - ge->prev->ix3;
++	kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++	a = ge->iy1 - ge->prev->iy3;
++	b = ge->ix1 - ge->prev->ix3;
++	kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++	a = ge->iy3 - ge->iy2;
++	b = ge->ix3 - ge->ix2;
++	kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++
++	changed = 1;
++	while (changed) {
++		if (ISDBG(FIXCVDIR)) {
++			/* for debugging */
++			fprintf(stderr, "fixcvdir %d %d (%d %d %d %d %d %d) %f %f %f\n",
++				fdir, rdir,
++				ge->ix1 - ge->prev->ix3,
++				ge->iy1 - ge->prev->iy3,
++				ge->ix2 - ge->ix1,
++				ge->iy2 - ge->iy1,
++				ge->ix3 - ge->ix2,
++				ge->iy3 - ge->iy2,
++				kk1, kk, kk2);
++		}
++		changed = 0;
++
++		if (fdir > 0) {
++			if (kk1 > kk) {	/* the front end has problems */
++				if (c * (ge->ix1 - ge->prev->ix3) > 0) {
++					ge->ix1 -= c;
++					changed = 1;
++				} if (d * (ge->iy2 - ge->iy1) > 0) {
++					ge->iy1 += d;
++					changed = 1;
++				}
++				/* recalculate the coefficients */
++				a = ge->iy3 - ge->prev->iy3;
++				b = ge->ix3 - ge->prev->ix3;
++				kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++				a = ge->iy1 - ge->prev->iy3;
++				b = ge->ix1 - ge->prev->ix3;
++				kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++			}
++		} else if (fdir < 0) {
++			if (kk1 < kk) {	/* the front end has problems */
++				if (c * (ge->ix2 - ge->ix1) > 0) {
++					ge->ix1 += c;
++					changed = 1;
++				} if (d * (ge->iy1 - ge->prev->iy3) > 0) {
++					ge->iy1 -= d;
++					changed = 1;
++				}
++				/* recalculate the coefficients */
++				a = ge->iy1 - ge->prev->iy3;
++				b = ge->ix1 - ge->prev->ix3;
++				kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++				a = ge->iy3 - ge->prev->iy3;
++				b = ge->ix3 - ge->prev->ix3;
++				kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++			}
++		}
++		if (rdir > 0) {
++			if (kk2 < kk) {	/* the rear end has problems */
++				if (c * (ge->ix2 - ge->ix1) > 0) {
++					ge->ix2 -= c;
++					changed = 1;
++				} if (d * (ge->iy3 - ge->iy2) > 0) {
++					ge->iy2 += d;
++					changed = 1;
++				}
++				/* recalculate the coefficients */
++				a = ge->iy3 - ge->prev->iy3;
++				b = ge->ix3 - ge->prev->ix3;
++				kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++				a = ge->iy3 - ge->iy2;
++				b = ge->ix3 - ge->ix2;
++				kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++			}
++		} else if (rdir < 0) {
++			if (kk2 > kk) {	/* the rear end has problems */
++				if (c * (ge->ix3 - ge->ix2) > 0) {
++					ge->ix2 += c;
++					changed = 1;
++				} if (d * (ge->iy2 - ge->iy1) > 0) {
++					ge->iy2 -= d;
++					changed = 1;
++				}
++				/* recalculate the coefficients */
++				a = ge->iy3 - ge->prev->iy3;
++				b = ge->ix3 - ge->prev->ix3;
++				kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++				a = ge->iy3 - ge->iy2;
++				b = ge->ix3 - ge->ix2;
++				kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a));
++			}
++		}
++	}
++	fixcvends(ge);
++}
++
++/* Get the directions of ends of curve for further usage */
++
++/* expects that the previous element is also float */
++
++static int
++fgetcvdir(
++	 GENTRY * ge
++)
++{
++	double          a, b;
++	double          k, k1, k2;
++	int             dir = 0;
++
++	if( !(ge->flags & GEF_FLOAT) ) {
++		fprintf(stderr, "**! fgetcvdir(0x%x) on int entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	a = fabs(ge->fy3 - ge->prev->fy3);
++	b = fabs(ge->fx3 - ge->prev->fx3);
++	k = a < FEPS ? (b < FEPS ? 1. : 100000.) : ( b / a);
++
++	a = fabs(ge->fy1 - ge->prev->fy3);
++	b = fabs(ge->fx1 - ge->prev->fx3);
++	if(a < FEPS) {
++		if(b < FEPS) {
++			a = fabs(ge->fy2 - ge->prev->fy3);
++			b = fabs(ge->fx2 - ge->prev->fx3);
++			k1 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a);
++		} else
++			k1 = FBIGVAL;
++	} else
++		k1 = b / a;
++
++	a = fabs(ge->fy3 - ge->fy2);
++	b = fabs(ge->fx3 - ge->fx2);
++	if(a < FEPS) {
++		if(b < FEPS) {
++			a = fabs(ge->fy3 - ge->fy1);
++			b = fabs(ge->fx3 - ge->fx1);
++			k2 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a);
++		} else
++			k2 = FBIGVAL;
++	} else
++		k2 = b / a;
++
++	if(fabs(k1-k) < 0.0001)
++		dir |= CVDIR_FEQUAL;
++	else if (k1 < k)
++		dir |= CVDIR_FUP;
++	else
++		dir |= CVDIR_FDOWN;
++
++	if(fabs(k2-k) < 0.0001)
++		dir |= CVDIR_REQUAL;
++	else if (k2 > k)
++		dir |= CVDIR_RUP;
++	else
++		dir |= CVDIR_RDOWN;
++
++	return dir;
++}
++
++
++/* expects that the previous element is also int */
++
++static int
++igetcvdir(
++	 GENTRY * ge
++)
++{
++	int             a, b;
++	double          k, k1, k2;
++	int             dir = 0;
++
++	if(ge->flags & GEF_FLOAT) {
++		fprintf(stderr, "**! igetcvdir(0x%x) on floating entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	a = ge->iy3 - ge->prev->iy3;
++	b = ge->ix3 - ge->prev->ix3;
++	k = (a == 0) ? (b == 0 ? 1. : 100000.) : fabs((double) b / (double) a);
++
++	a = ge->iy1 - ge->prev->iy3;
++	b = ge->ix1 - ge->prev->ix3;
++	if(a == 0) {
++		if(b == 0) {
++			a = ge->iy2 - ge->prev->iy3;
++			b = ge->ix2 - ge->prev->ix3;
++			k1 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a);
++		} else
++			k1 = FBIGVAL;
++	} else
++		k1 = fabs((double) b / (double) a);
++
++	a = ge->iy3 - ge->iy2;
++	b = ge->ix3 - ge->ix2;
++	if(a == 0) {
++		if(b == 0) {
++			a = ge->iy3 - ge->iy1;
++			b = ge->ix3 - ge->ix1;
++			k2 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a);
++		} else
++			k2 = FBIGVAL;
++	} else
++		k2 = fabs((double) b / (double) a);
++
++	if(fabs(k1-k) < 0.0001)
++		dir |= CVDIR_FEQUAL;
++	else if (k1 < k)
++		dir |= CVDIR_FUP;
++	else
++		dir |= CVDIR_FDOWN;
++
++	if(fabs(k2-k) < 0.0001)
++		dir |= CVDIR_REQUAL;
++	else if (k2 > k)
++		dir |= CVDIR_RUP;
++	else
++		dir |= CVDIR_RDOWN;
++
++	return dir;
++}
++
++#if 0
++/* a function just to test the work of fixcvdir() */
++static void
++testfixcvdir(
++	     GLYPH * g
++)
++{
++	GENTRY         *ge;
++	int             dir;
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if (ge->type == GE_CURVE) {
++			dir = igetcvdir(ge);
++			fixcvdir(ge, dir);
++		}
++	}
++}
++#endif
++
++static int
++iround(
++	double val
++)
++{
++	return (int) (val > 0 ? val + 0.5 : val - 0.5);
++}
++	
++/* for debugging - dump the glyph
++ * mark with a star the entries from start to end inclusive
++ * (start == NULL means don't mark any, end == NULL means to the last)
++ */
++
++void
++dumppaths(
++	GLYPH *g,
++	GENTRY *start,
++	GENTRY *end
++)
++{
++	GENTRY *ge;
++	int i;
++	char mark=' ';
++
++	fprintf(stderr, "Glyph %s:\n", g->name);
++
++	/* now do the conversion */
++	for(ge = g->entries; ge != 0; ge = ge->next) {
++		if(ge == start)
++			mark = '*';
++		fprintf(stderr, " %c %8x", mark, ge);
++		switch(ge->type) {
++		case GE_MOVE:
++		case GE_LINE:
++			if(ge->flags & GEF_FLOAT)
++				fprintf(stderr," %c float (%g, %g)\n", ge->type, ge->fx3, ge->fy3);
++			else
++				fprintf(stderr," %c int (%d, %d)\n", ge->type, ge->ix3, ge->iy3);
++			break;
++		case GE_CURVE:
++			if(ge->flags & GEF_FLOAT) {
++				fprintf(stderr," C float ");
++				for(i=0; i<3; i++)
++					fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]);
++				fprintf(stderr,"\n");
++			} else {
++				fprintf(stderr," C int ");
++				for(i=0; i<3; i++)
++					fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
++				fprintf(stderr,"\n");
++			}
++			break;
++		default:
++			fprintf(stderr, " %c\n", ge->type);
++			break;
++		}
++		if(ge == end)
++			mark = ' ';
++	}
++}
++
++/*
++ * Routine that converts all entries in the path from float to int
++ */
++
++void
++pathtoint(
++	GLYPH *g
++)
++{
++	GENTRY *ge;
++	int x[3], y[3];
++	int i;
++
++
++	if(ISDBG(TOINT))
++		fprintf(stderr, "TOINT: glyph %s\n", g->name);
++	assertisfloat(g, "converting path to int\n");
++
++	fdelsmall(g, 1.0); /* get rid of sub-pixel contours */
++	assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++	/* 1st pass, collect the directions of the curves: have
++	 * to do that in advance, while everyting is float
++	 */
++	for(ge = g->entries; ge != 0; ge = ge->next) {
++		if( !(ge->flags & GEF_FLOAT) ) {
++			fprintf(stderr, "**! glyphs %s has int entry, found in conversion to int\n",
++				g->name);
++			exit(1);
++		}
++		if(ge->type == GE_CURVE) {
++			ge->dir = fgetcvdir(ge);
++		}
++	}
++
++	/* now do the conversion */
++	for(ge = g->entries; ge != 0; ge = ge->next) {
++		switch(ge->type) {
++		case GE_MOVE:
++		case GE_LINE:
++			if(ISDBG(TOINT))
++				fprintf(stderr," %c float x=%g y=%g\n", ge->type, ge->fx3, ge->fy3);
++			x[0] = iround(ge->fx3);
++			y[0] = iround(ge->fy3);
++			for(i=0; i<3; i++) { /* put some valid values everywhere, for convenience */
++				ge->ixn[i] = x[0];
++				ge->iyn[i] = y[0];
++			}
++			if(ISDBG(TOINT))
++				fprintf(stderr,"   int   x=%d y=%d\n", ge->ix3, ge->iy3);
++			break;
++		case GE_CURVE:
++			if(ISDBG(TOINT))
++				fprintf(stderr," %c float ", ge->type);
++
++			for(i=0; i<3; i++) {
++				if(ISDBG(TOINT))
++					fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]);
++				x[i] = iround(ge->fxn[i]);
++				y[i] = iround(ge->fyn[i]);
++			}
++
++			if(ISDBG(TOINT))
++				fprintf(stderr,"\n   int   ");
++
++			for(i=0; i<3; i++) {
++				ge->ixn[i] = x[i];
++				ge->iyn[i] = y[i];
++				if(ISDBG(TOINT))
++					fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
++			}
++			ge->flags &= ~GEF_FLOAT; /* for fixcvdir */
++			fixcvdir(ge, ge->dir);
++
++			if(ISDBG(TOINT)) {
++				fprintf(stderr,"\n   fixed ");
++				for(i=0; i<3; i++)
++					fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]);
++				fprintf(stderr,"\n");
++			}
++
++			break;
++		}
++		ge->flags &= ~GEF_FLOAT;
++	}
++	g->flags &= ~GF_FLOAT;
++}
++
++
++/* check whether we can fix up the curve to change its size by (dx,dy) */
++/* 0 means NO, 1 means YES */
++
++/* for float: if scaling would be under 10% */
++
++int
++fcheckcv(
++	GENTRY * ge,
++	double dx,
++	double dy
++)
++{
++	if( !(ge->flags & GEF_FLOAT) ) {
++		fprintf(stderr, "**! fcheckcv(0x%x) on int entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	if (ge->type != GE_CURVE)
++		return 0;
++
++	if( fabs(ge->fx3 - ge->prev->fx3) < fabs(dx) * 10 )
++		return 0;
++
++	if( fabs(ge->fy3 - ge->prev->fy3) < fabs(dy) * 10 )
++		return 0;
++
++	return 1;
++}
++
++/* for int: if won't create new zigzags at the ends */
++
++int
++icheckcv(
++	GENTRY * ge,
++	int dx,
++	int dy
++)
++{
++	int             xdep, ydep;
++
++	if(ge->flags & GEF_FLOAT) {
++		fprintf(stderr, "**! icheckcv(0x%x) on floating entry, ABORT\n", ge);
++		abort(); /* dump core */
++	}
++
++	if (ge->type != GE_CURVE)
++		return 0;
++
++	xdep = ge->ix3 - ge->prev->ix3;
++	ydep = ge->iy3 - ge->prev->iy3;
++
++	if (ge->type == GE_CURVE
++	    && (xdep * (xdep + dx)) > 0
++	    && (ydep * (ydep + dy)) > 0) {
++		return 1;
++	} else
++		return 0;
++}
++
++/* float connect the ends of open contours */
++
++void
++fclosepaths(
++	   GLYPH * g
++)
++{
++	GENTRY         *ge, *fge, *xge, *nge;
++	int             i;
++
++	assertisfloat(g, "fclosepaths float\n");
++
++	for (xge = g->entries; xge != 0; xge = xge->next) {
++		if( xge->type != GE_PATH )
++			continue;
++
++		ge = xge->prev;
++		if(ge == 0 || (ge->type != GE_LINE && ge->type!= GE_CURVE)) {
++			fprintf(stderr, "**! Glyph %s got empty path\n",
++				g->name);
++			exit(1);
++		}
++
++		fge = ge->frwd;
++		if (fge->prev == 0 || fge->prev->type != GE_MOVE) {
++			fprintf(stderr, "**! Glyph %s got strange beginning of path\n",
++				g->name);
++			exit(1);
++		}
++		fge = fge->prev;
++		if (fge->fx3 != ge->fx3 || fge->fy3 != ge->fy3) {
++			/* we have to fix this open path */
++
++			WARNING_4 fprintf(stderr, "Glyph %s got path open by dx=%g dy=%g\n",
++			g->name, fge->fx3 - ge->fx3, fge->fy3 - ge->fy3);
++
++
++			/* add a new line */
++			nge = newgentry(GEF_FLOAT);
++			(*nge) = (*ge);
++			nge->fx3 = fge->fx3;
++			nge->fy3 = fge->fy3;
++			nge->type = GE_LINE;
++
++			addgeafter(ge, nge);
++
++			if (fabs(ge->fx3 - fge->fx3) <= 2 && fabs(ge->fy3 - fge->fy3) <= 2) {
++				/*
++				 * small change, try to get rid of the new entry
++				 */
++
++				double df[2];
++
++				for(i=0; i<2; i++) {
++					df[i] = ge->fpoints[i][2] - fge->fpoints[i][2];
++					df[i] = fclosegap(nge, nge, i, df[i], NULL);
++				}
++
++				if(df[0] == 0. && df[1] == 0.) {
++					/* closed gap successfully, remove the added entry */
++					freethisge(nge);
++				}
++			}
++		}
++	}
++}
++
++void
++smoothjoints(
++	     GLYPH * g
++)
++{
++	GENTRY         *ge, *ne;
++	int             dx1, dy1, dx2, dy2, k;
++	int             dir;
++
++	return; /* this stuff seems to create problems */
++
++	assertisint(g, "smoothjoints int");
++
++	if (g->entries == 0)	/* nothing to do */
++		return;
++
++	for (ge = g->entries->next; ge != 0; ge = ge->next) {
++		ne = ge->frwd;
++
++		/*
++		 * although there should be no one-line path * and any path
++		 * must end with CLOSEPATH, * nobody can say for sure
++		 */
++
++		if (ge == ne || ne == 0)
++			continue;
++
++		/* now handle various joints */
++
++		if (ge->type == GE_LINE && ne->type == GE_LINE) {
++			dx1 = ge->ix3 - ge->prev->ix3;
++			dy1 = ge->iy3 - ge->prev->iy3;
++			dx2 = ne->ix3 - ge->ix3;
++			dy2 = ne->iy3 - ge->iy3;
++
++			/* check whether they have the same direction */
++			/* and the same slope */
++			/* then we can join them into one line */
++
++			if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 && dx1 * dy2 == dy1 * dx2) {
++				/* extend the previous line */
++				ge->ix3 = ne->ix3;
++				ge->iy3 = ne->iy3;
++
++				/* and get rid of the next line */
++				freethisge(ne);
++			}
++		} else if (ge->type == GE_LINE && ne->type == GE_CURVE) {
++			fixcvends(ne);
++
++			dx1 = ge->ix3 - ge->prev->ix3;
++			dy1 = ge->iy3 - ge->prev->iy3;
++			dx2 = ne->ix1 - ge->ix3;
++			dy2 = ne->iy1 - ge->iy3;
++
++			/* if the line is nearly horizontal and we can fix it */
++			if (dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0
++			    && icheckcv(ne, 0, -dy1)
++			    && abs(dy1) <= 4) {
++				dir = igetcvdir(ne);
++				ge->iy3 -= dy1;
++				ne->iy1 -= dy1;
++				fixcvdir(ne, dir);
++				if (ge->next != ne)
++					ne->prev->iy3 -= dy1;
++				dy1 = 0;
++			} else if (dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0
++				   && icheckcv(ne, -dx1, 0)
++				   && abs(dx1) <= 4) {
++				/* the same but vertical */
++				dir = igetcvdir(ne);
++				ge->ix3 -= dx1;
++				ne->ix1 -= dx1;
++				fixcvdir(ne, dir);
++				if (ge->next != ne)
++					ne->prev->ix3 -= dx1;
++				dx1 = 0;
++			}
++			/*
++			 * if line is horizontal and curve begins nearly
++			 * horizontally
++			 */
++			if (dy1 == 0 && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0) {
++				dir = igetcvdir(ne);
++				ne->iy1 -= dy2;
++				fixcvdir(ne, dir);
++				dy2 = 0;
++			} else if (dx1 == 0 && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0) {
++				/* the same but vertical */
++				dir = igetcvdir(ne);
++				ne->ix1 -= dx2;
++				fixcvdir(ne, dir);
++				dx2 = 0;
++			}
++		} else if (ge->type == GE_CURVE && ne->type == GE_LINE) {
++			fixcvends(ge);
++
++			dx1 = ge->ix3 - ge->ix2;
++			dy1 = ge->iy3 - ge->iy2;
++			dx2 = ne->ix3 - ge->ix3;
++			dy2 = ne->iy3 - ge->iy3;
++
++			/* if the line is nearly horizontal and we can fix it */
++			if (dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0
++			    && icheckcv(ge, 0, dy2)
++			    && abs(dy2) <= 4) {
++				dir = igetcvdir(ge);
++				ge->iy3 += dy2;
++				ge->iy2 += dy2;
++				fixcvdir(ge, dir);
++				if (ge->next != ne)
++					ne->prev->iy3 += dy2;
++				dy2 = 0;
++			} else if (dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0
++				   && icheckcv(ge, dx2, 0)
++				   && abs(dx2) <= 4) {
++				/* the same but vertical */
++				dir = igetcvdir(ge);
++				ge->ix3 += dx2;
++				ge->ix2 += dx2;
++				fixcvdir(ge, dir);
++				if (ge->next != ne)
++					ne->prev->ix3 += dx2;
++				dx2 = 0;
++			}
++			/*
++			 * if line is horizontal and curve ends nearly
++			 * horizontally
++			 */
++			if (dy2 == 0 && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0) {
++				dir = igetcvdir(ge);
++				ge->iy2 += dy1;
++				fixcvdir(ge, dir);
++				dy1 = 0;
++			} else if (dx2 == 0 && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0) {
++				/* the same but vertical */
++				dir = igetcvdir(ge);
++				ge->ix2 += dx1;
++				fixcvdir(ge, dir);
++				dx1 = 0;
++			}
++		} else if (ge->type == GE_CURVE && ne->type == GE_CURVE) {
++			fixcvends(ge);
++			fixcvends(ne);
++
++			dx1 = ge->ix3 - ge->ix2;
++			dy1 = ge->iy3 - ge->iy2;
++			dx2 = ne->ix1 - ge->ix3;
++			dy2 = ne->iy1 - ge->iy3;
++
++			/*
++			 * check if we have a rather smooth joint at extremal
++			 * point
++			 */
++			/* left or right extremal point */
++			if (abs(dx1) <= 4 && abs(dx2) <= 4
++			    && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0
++			    && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0
++			    && ((ge->iy3 < ge->prev->iy3 && ne->iy3 < ge->iy3)
++				|| (ge->iy3 > ge->prev->iy3 && ne->iy3 > ge->iy3))
++			  && (ge->ix3 - ge->prev->ix3) * (ne->ix3 - ge->ix3) < 0
++				) {
++				dir = igetcvdir(ge);
++				ge->ix2 += dx1;
++				dx1 = 0;
++				fixcvdir(ge, dir);
++				dir = igetcvdir(ne);
++				ne->ix1 -= dx2;
++				dx2 = 0;
++				fixcvdir(ne, dir);
++			}
++			/* top or down extremal point */
++			else if (abs(dy1) <= 4 && abs(dy2) <= 4
++				 && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0
++				 && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0
++				 && ((ge->ix3 < ge->prev->ix3 && ne->ix3 < ge->ix3)
++				|| (ge->ix3 > ge->prev->ix3 && ne->ix3 > ge->ix3))
++				 && (ge->iy3 - ge->prev->iy3) * (ne->iy3 - ge->iy3) < 0
++				) {
++				dir = igetcvdir(ge);
++				ge->iy2 += dy1;
++				dy1 = 0;
++				fixcvdir(ge, dir);
++				dir = igetcvdir(ne);
++				ne->iy1 -= dy2;
++				dy2 = 0;
++				fixcvdir(ne, dir);
++			}
++			/* or may be we just have a smooth junction */
++			else if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0
++				 && 10 * abs(k = abs(dx1 * dy2) - abs(dy1 * dx2)) < (abs(dx1 * dy2) + abs(dy1 * dx2))) {
++				int             tries[6][4];
++				int             results[6];
++				int             i, b;
++
++				/* build array of changes we are going to try */
++				/* uninitalized entries are 0 */
++				if (k > 0) {
++					static int      t1[6][4] = {
++						{0, 0, 0, 0},
++						{-1, 0, 1, 0},
++						{-1, 0, 0, 1},
++						{0, -1, 1, 0},
++						{0, -1, 0, 1},
++					{-1, -1, 1, 1}};
++					memcpy(tries, t1, sizeof tries);
++				} else {
++					static int      t1[6][4] = {
++						{0, 0, 0, 0},
++						{1, 0, -1, 0},
++						{1, 0, 0, -1},
++						{0, 1, -1, 0},
++						{0, 1, 0, -1},
++					{1, 1, -1, -1}};
++					memcpy(tries, t1, sizeof tries);
++				}
++
++				/* now try the changes */
++				results[0] = abs(k);
++				for (i = 1; i < 6; i++) {
++					results[i] = abs((abs(dx1) + tries[i][0]) * (abs(dy2) + tries[i][1]) -
++							 (abs(dy1) + tries[i][2]) * (abs(dx2) + tries[i][3]));
++				}
++
++				/* and find the best try */
++				k = abs(k);
++				b = 0;
++				for (i = 1; i < 6; i++)
++					if (results[i] < k) {
++						k = results[i];
++						b = i;
++					}
++				/* and finally apply it */
++				if (dx1 < 0)
++					tries[b][0] = -tries[b][0];
++				if (dy2 < 0)
++					tries[b][1] = -tries[b][1];
++				if (dy1 < 0)
++					tries[b][2] = -tries[b][2];
++				if (dx2 < 0)
++					tries[b][3] = -tries[b][3];
++
++				dir = igetcvdir(ge);
++				ge->ix2 -= tries[b][0];
++				ge->iy2 -= tries[b][2];
++				fixcvdir(ge, dir);
++				dir = igetcvdir(ne);
++				ne->ix1 += tries[b][3];
++				ne->iy1 += tries[b][1];
++				fixcvdir(ne, dir);
++			}
++		}
++	}
++}
++
++/* debugging: print out stems of a glyph */
++static void
++debugstems(
++	   char *name,
++	   STEM * hstems,
++	   int nhs,
++	   STEM * vstems,
++	   int nvs
++)
++{
++	int             i;
++
++	fprintf(pfa_file, "%% %s\n", name);
++	fprintf(pfa_file, "%% %d horizontal stems:\n", nhs);
++	for (i = 0; i < nhs; i++)
++		fprintf(pfa_file, "%% %3d    %d (%d...%d) %c %c%c%c%c\n", i, hstems[i].value,
++			hstems[i].from, hstems[i].to,
++			((hstems[i].flags & ST_UP) ? 'U' : 'D'),
++			((hstems[i].flags & ST_END) ? 'E' : '-'),
++			((hstems[i].flags & ST_FLAT) ? 'F' : '-'),
++			((hstems[i].flags & ST_ZONE) ? 'Z' : ' '),
++			((hstems[i].flags & ST_TOPZONE) ? 'T' : ' '));
++	fprintf(pfa_file, "%% %d vertical stems:\n", nvs);
++	for (i = 0; i < nvs; i++)
++		fprintf(pfa_file, "%% %3d    %d (%d...%d) %c %c%c\n", i, vstems[i].value,
++			vstems[i].from, vstems[i].to,
++			((vstems[i].flags & ST_UP) ? 'U' : 'D'),
++			((vstems[i].flags & ST_END) ? 'E' : '-'),
++			((vstems[i].flags & ST_FLAT) ? 'F' : '-'));
++}
++
++/* add pseudo-stems for the limits of the Blue zones to the stem array */
++static int
++addbluestems(
++	STEM *s,
++	int n
++)
++{
++	int i;
++
++	for(i=0; i<nblues && i<2; i+=2) { /* baseline */
++		s[n].value=bluevalues[i];
++		s[n].flags=ST_UP|ST_ZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i;
++		n++;
++		s[n].value=bluevalues[i+1];
++		s[n].flags=ST_ZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i+1;
++		n++;
++	}
++	for(i=2; i<nblues; i+=2) { /* top zones */
++		s[n].value=bluevalues[i];
++		s[n].flags=ST_UP|ST_ZONE|ST_TOPZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i;
++		n++;
++		s[n].value=bluevalues[i+1];
++		s[n].flags=ST_ZONE|ST_TOPZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i+1;
++		n++;
++	}
++	for(i=0; i<notherb; i+=2) { /* bottom zones */
++		s[n].value=otherblues[i];
++		s[n].flags=ST_UP|ST_ZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i+nblues;
++		n++;
++		s[n].value=otherblues[i+1];
++		s[n].flags=ST_ZONE;
++		/* don't overlap with anything */
++		s[n].origin=s[n].from=s[n].to= -10000+i+1+nblues;
++		n++;
++	}
++	return n;
++}
++
++/* sort stems in array */
++static void
++sortstems(
++	  STEM * s,
++	  int n
++)
++{
++	int             i, j;
++	STEM            x;
++
++
++	/* a simple sorting */
++	/* hm, the ordering criteria are not quite simple :-) 
++	 * if the values are tied
++	 * ST_UP always goes under not ST_UP
++	 * ST_ZONE goes on the most outer side
++	 * ST_END goes towards inner side after ST_ZONE
++	 * ST_FLAT goes on the inner side
++	 */
++
++	for (i = 0; i < n; i++)
++		for (j = i + 1; j < n; j++) {
++			if(s[i].value < s[j].value)
++				continue;
++			if(s[i].value == s[j].value) {
++				if( (s[i].flags & ST_UP) < (s[j].flags & ST_UP) )
++					continue;
++				if( (s[i].flags & ST_UP) == (s[j].flags & ST_UP) ) {
++					if( s[i].flags & ST_UP ) {
++						if(
++						((s[i].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT)
++							>
++						((s[j].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT)
++						)
++							continue;
++					} else {
++						if(
++						((s[i].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT)
++							<
++						((s[j].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT)
++						)
++							continue;
++					}
++				}
++			}
++			x = s[j];
++			s[j] = s[i];
++			s[i] = x;
++		}
++}
++
++/* check whether two stem borders overlap */
++
++static int
++stemoverlap(
++	    STEM * s1,
++	    STEM * s2
++)
++{
++	int             result;
++
++	if ((s1->from <= s2->from && s1->to >= s2->from)
++	    || (s2->from <= s1->from && s2->to >= s1->from))
++		result = 1;
++	else
++		result = 0;
++
++	if (ISDBG(STEMOVERLAP))
++		fprintf(pfa_file, "%% overlap %d(%d..%d)x%d(%d..%d)=%d\n",
++			s1->value, s1->from, s1->to, s2->value, s2->from, s2->to, result);
++	return result;
++}
++
++/* 
++ * check if the stem [border] is in an appropriate blue zone
++ * (currently not used)
++ */
++
++static int
++steminblue(
++	STEM *s
++)
++{
++	int i, val;
++
++	val=s->value;
++	if(s->flags & ST_UP) {
++		/* painted size up, look at lower zones */
++		if(nblues>=2 && val>=bluevalues[0] && val<=bluevalues[1] )
++			return 1;
++		for(i=0; i<notherb; i++) {
++			if( val>=otherblues[i] && val<=otherblues[i+1] )
++				return 1;
++		}
++	} else {
++		/* painted side down, look at upper zones */
++		for(i=2; i<nblues; i++) {
++			if( val>=bluevalues[i] && val<=bluevalues[i+1] )
++				return 1;
++		}
++	}
++
++	return 0;
++}
++
++/* mark the outermost stem [borders] in the blue zones */
++
++static void
++markbluestems(
++	STEM *s,
++	int nold
++)
++{
++	int i, j, a, b, c;
++	/*
++	 * traverse the list of Blue Values, mark the lowest upper
++	 * stem in each bottom zone and the topmost lower stem in
++	 * each top zone with ST_BLUE
++	 */
++
++	/* top zones */
++	for(i=2; i<nblues; i+=2) {
++		a=bluevalues[i]; b=bluevalues[i+1];
++		if(ISDBG(BLUESTEMS))
++			fprintf(pfa_file, "%% looking at blue zone %d...%d\n", a, b);
++		for(j=nold-1; j>=0; j--) {
++			if( s[j].flags & (ST_ZONE|ST_UP|ST_END) )
++				continue;
++			c=s[j].value;
++			if(c<a) /* too low */
++				break;
++			if(c<=b) { /* found the topmost stem border */
++				/* mark all the stems with the same value */
++				if(ISDBG(BLUESTEMS))
++					fprintf(pfa_file, "%% found D BLUE at %d\n", s[j].value);
++				/* include ST_END values */
++				while( s[j+1].value==c && (s[j+1].flags & ST_ZONE)==0 )
++					j++;
++				s[j].flags |= ST_BLUE;
++				for(j--; j>=0 && s[j].value==c 
++						&& (s[j].flags & (ST_UP|ST_ZONE))==0 ; j--)
++					s[j].flags |= ST_BLUE;
++				break;
++			}
++		}
++	}
++	/* baseline */
++	if(nblues>=2) {
++		a=bluevalues[0]; b=bluevalues[1];
++		for(j=0; j<nold; j++) {
++			if( (s[j].flags & (ST_ZONE|ST_UP|ST_END))!=ST_UP )
++				continue;
++			c=s[j].value;
++			if(c>b) /* too high */
++				break;
++			if(c>=a) { /* found the lowest stem border */
++				/* mark all the stems with the same value */
++				if(ISDBG(BLUESTEMS))
++					fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value);
++				/* include ST_END values */
++				while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 )
++					j--;
++				s[j].flags |= ST_BLUE;
++				for(j++; j<nold && s[j].value==c
++						&& (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++)
++					s[j].flags |= ST_BLUE;
++				break;
++			}
++		}
++	}
++	/* bottom zones: the logic is the same as for baseline */
++	for(i=0; i<notherb; i+=2) {
++		a=otherblues[i]; b=otherblues[i+1];
++		for(j=0; j<nold; j++) {
++			if( (s[j].flags & (ST_UP|ST_ZONE|ST_END))!=ST_UP )
++				continue;
++			c=s[j].value;
++			if(c>b) /* too high */
++				break;
++			if(c>=a) { /* found the lowest stem border */
++				/* mark all the stems with the same value */
++				if(ISDBG(BLUESTEMS))
++					fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value);
++				/* include ST_END values */
++				while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 )
++					j--;
++				s[j].flags |= ST_BLUE;
++				for(j++; j<nold && s[j].value==c
++						&& (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++)
++					s[j].flags |= ST_BLUE;
++				break;
++			}
++		}
++	}
++}
++
++/* Eliminate invalid stems, join equivalent lines and remove nested stems
++ * to build the main (non-substituted) set of stems.
++ * XXX add consideration of the italic angle
++ */
++static int
++joinmainstems(
++	  STEM * s,
++	  int nold,
++	  int useblues /* do we use the blue values ? */
++)
++{
++#define MAX_STACK	1000
++	STEM            stack[MAX_STACK];
++	int             nstack = 0;
++	int             sbottom = 0;
++	int             nnew;
++	int             i, j, k;
++	int             a, b, c, w1, w2, w3;
++	int             fw, fd;
++	/*
++	 * priority of the last found stem: 
++	 * 0 - nothing found yet 
++	 * 1 - has ST_END in it (one or more) 
++	 * 2 - has no ST_END and no ST_FLAT, can override only one stem 
++	 *     with priority 1 
++	 * 3 - has no ST_END and at least one ST_FLAT, can override one 
++	 *     stem with priority 2 or any number of stems with priority 1
++	 * 4 (handled separately) - has ST_BLUE, can override anything
++	 */
++	int             readystem = 0;
++	int             pri;
++	int             nlps = 0;	/* number of non-committed
++					 * lowest-priority stems */
++
++
++	for (i = 0, nnew = 0; i < nold; i++) {
++		if (s[i].flags & (ST_UP|ST_ZONE)) {
++			if(s[i].flags & ST_BLUE) {
++				/* we just HAVE to use this value */
++				if (readystem)
++					nnew += 2;
++				readystem=0;
++
++				/* remember the list of Blue zone stems with the same value */
++				for(a=i, i++; i<nold && s[a].value==s[i].value
++					&& (s[i].flags & ST_BLUE); i++)
++					{}
++				b=i; /* our range is a <= i < b */
++				c= -1; /* index of our best guess up to now */
++				pri=0;
++				/* try to find a match, don't cross blue zones */
++				for(; i<nold && (s[i].flags & ST_BLUE)==0; i++) {
++					if(s[i].flags & ST_UP) {
++						if(s[i].flags & ST_TOPZONE)
++							break;
++						else
++							continue;
++					}
++					for(j=a; j<b; j++) {
++						if(!stemoverlap(&s[j], &s[i]) )
++							continue;
++						/* consider priorities */
++						if( ( (s[j].flags|s[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) {
++							c=i;
++							goto bluematch;
++						}
++						if( ((s[j].flags|s[i].flags) & ST_END)==0 )  {
++							if(pri < 2) {
++								c=i; pri=2;
++							}
++						} else {
++							if(pri == 0) {
++								c=i; pri=1;
++							}
++						}
++					}
++				}
++			bluematch:
++				/* clean up the stack */
++				nstack=sbottom=0;
++				readystem=0;
++				/* add this stem */
++				s[nnew++]=s[a];
++				if(c<0) { /* make one-dot-wide stem */
++					if(nnew>=b) { /* have no free space */
++						for(j=nold; j>=b; j--) /* make free space */
++							s[j]=s[j-1];
++						b++;
++						nold++;
++					}
++					s[nnew]=s[a];
++					s[nnew].flags &= ~(ST_UP|ST_BLUE);
++					nnew++;
++					i=b-1;
++				} else {
++					s[nnew++]=s[c];
++					i=c; /* skip up to this point */
++				}
++				if (ISDBG(MAINSTEMS))
++					fprintf(pfa_file, "%% +stem %d...%d U BLUE\n",
++						s[nnew-2].value, s[nnew-1].value);
++			} else {
++				if (nstack >= MAX_STACK) {
++					WARNING_1 fprintf(stderr, "Warning: **** converter's stem stack overflow ****\n");
++					nstack = 0;
++				}
++				stack[nstack++] = s[i];
++			}
++		} else if(s[i].flags & ST_BLUE) {
++			/* again, we just HAVE to use this value */
++			if (readystem)
++				nnew += 2;
++			readystem=0;
++
++			/* remember the list of Blue zone stems with the same value */
++			for(a=i, i++; i<nold && s[a].value==s[i].value
++				&& (s[i].flags & ST_BLUE); i++)
++				{}
++			b=i; /* our range is a <= i < b */
++			c= -1; /* index of our best guess up to now */
++			pri=0;
++			/* try to find a match */
++			for (i = nstack - 1; i >= 0; i--) {
++				if( (stack[i].flags & ST_UP)==0 ) {
++					if( (stack[i].flags & (ST_ZONE|ST_TOPZONE))==ST_ZONE )
++						break;
++					else
++						continue;
++				}
++				for(j=a; j<b; j++) {
++					if(!stemoverlap(&s[j], &stack[i]) )
++						continue;
++					/* consider priorities */
++					if( ( (s[j].flags|stack[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) {
++						c=i;
++						goto bluedownmatch;
++					}
++					if( ((s[j].flags|stack[i].flags) & ST_END)==0 )  {
++						if(pri < 2) {
++							c=i; pri=2;
++						}
++					} else {
++						if(pri == 0) {
++							c=i; pri=1;
++						}
++					}
++				}
++			}
++		bluedownmatch:
++			/* if found no match make a one-dot-wide stem */
++			if(c<0) {
++				c=0;
++				stack[0]=s[b-1];
++				stack[0].flags |= ST_UP;
++				stack[0].flags &= ~ST_BLUE;
++			}
++			/* remove all the stems conflicting with this one */
++			readystem=0;
++			for(j=nnew-2; j>=0; j-=2) {
++				if (ISDBG(MAINSTEMS))
++					fprintf(pfa_file, "%% ?stem %d...%d -- %d\n",
++						s[j].value, s[j+1].value, stack[c].value);
++				if(s[j+1].value < stack[c].value) /* no conflict */
++					break;
++				if(s[j].flags & ST_BLUE) {
++					/* oops, we don't want to spoil other blue zones */
++					stack[c].value=s[j+1].value+1;
++					break;
++				}
++				if( (s[j].flags|s[j+1].flags) & ST_END ) {
++					if (ISDBG(MAINSTEMS))
++						fprintf(pfa_file, "%% -stem %d...%d p=1\n",
++							s[j].value, s[j+1].value);
++					continue; /* pri==1, silently discard it */
++				}
++				/* we want to discard no nore than 2 stems of pri>=2 */
++				if( ++readystem > 2 ) {
++					/* change our stem to not conflict */
++					stack[c].value=s[j+1].value+1;
++					break;
++				} else {
++					if (ISDBG(MAINSTEMS))
++						fprintf(pfa_file, "%% -stem %d...%d p>=2\n",
++							s[j].value, s[j+1].value);
++					continue;
++				}
++			}
++			nnew=j+2;
++			/* add this stem */
++			if(nnew>=b-1) { /* have no free space */
++				for(j=nold; j>=b-1; j--) /* make free space */
++					s[j]=s[j-1];
++				b++;
++				nold++;
++			}
++			s[nnew++]=stack[c];
++			s[nnew++]=s[b-1];
++			/* clean up the stack */
++			nstack=sbottom=0;
++			readystem=0;
++			/* set the next position to search */
++			i=b-1;
++			if (ISDBG(MAINSTEMS))
++				fprintf(pfa_file, "%% +stem %d...%d D BLUE\n",
++					s[nnew-2].value, s[nnew-1].value);
++		} else if (nstack > 0) {
++
++			/*
++			 * check whether our stem overlaps with anything in
++			 * stack
++			 */
++			for (j = nstack - 1; j >= sbottom; j--) {
++				if (s[i].value <= stack[j].value)
++					break;
++				if (stack[j].flags & ST_ZONE)
++					continue;
++
++				if ((s[i].flags & ST_END)
++				    || (stack[j].flags & ST_END))
++					pri = 1;
++				else if ((s[i].flags & ST_FLAT)
++					 || (stack[j].flags & ST_FLAT))
++					pri = 3;
++				else
++					pri = 2;
++
++				if ((pri < readystem && s[nnew + 1].value >= stack[j].value)
++				    || !stemoverlap(&stack[j], &s[i]))
++					continue;
++
++				if (readystem > 1 && s[nnew + 1].value < stack[j].value) {
++					nnew += 2;
++					readystem = 0;
++					nlps = 0;
++				}
++				/*
++				 * width of the previous stem (if it's
++				 * present)
++				 */
++				w1 = s[nnew + 1].value - s[nnew].value;
++
++				/* width of this stem */
++				w2 = s[i].value - stack[j].value;
++
++				if (readystem == 0) {
++					/* nothing yet, just add a new stem */
++					s[nnew] = stack[j];
++					s[nnew + 1] = s[i];
++					readystem = pri;
++					if (pri == 1)
++						nlps = 1;
++					else if (pri == 2)
++						sbottom = j;
++					else {
++						sbottom = j + 1;
++						while (sbottom < nstack
++						       && stack[sbottom].value <= stack[j].value)
++							sbottom++;
++					}
++					if (ISDBG(MAINSTEMS))
++						fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
++							stack[j].value, s[i].value, pri, nlps);
++				} else if (pri == 1) {
++					if (stack[j].value > s[nnew + 1].value) {
++						/*
++						 * doesn't overlap with the
++						 * previous one
++						 */
++						nnew += 2;
++						nlps++;
++						s[nnew] = stack[j];
++						s[nnew + 1] = s[i];
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
++								stack[j].value, s[i].value, pri, nlps);
++					} else if (w2 < w1) {
++						/* is narrower */
++						s[nnew] = stack[j];
++						s[nnew + 1] = s[i];
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d %d->%d\n",
++								stack[j].value, s[i].value, pri, nlps, w1, w2);
++					}
++				} else if (pri == 2) {
++					if (readystem == 2) {
++						/* choose the narrower stem */
++						if (w1 > w2) {
++							s[nnew] = stack[j];
++							s[nnew + 1] = s[i];
++							sbottom = j;
++							if (ISDBG(MAINSTEMS))
++								fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
++									stack[j].value, s[i].value, pri, nlps);
++						}
++						/* else readystem==1 */
++					} else if (stack[j].value > s[nnew + 1].value) {
++						/*
++						 * value doesn't overlap with
++						 * the previous one
++						 */
++						nnew += 2;
++						nlps = 0;
++						s[nnew] = stack[j];
++						s[nnew + 1] = s[i];
++						sbottom = j;
++						readystem = pri;
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
++								stack[j].value, s[i].value, pri, nlps);
++					} else if (nlps == 1
++						   || stack[j].value > s[nnew - 1].value) {
++						/*
++						 * we can replace the top
++						 * stem
++						 */
++						nlps = 0;
++						s[nnew] = stack[j];
++						s[nnew + 1] = s[i];
++						readystem = pri;
++						sbottom = j;
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
++								stack[j].value, s[i].value, pri, nlps);
++					}
++				} else if (readystem == 3) {	/* that means also
++								 * pri==3 */
++					/* choose the narrower stem */
++					if (w1 > w2) {
++						s[nnew] = stack[j];
++						s[nnew + 1] = s[i];
++						sbottom = j + 1;
++						while (sbottom < nstack
++						       && stack[sbottom].value <= stack[j].value)
++							sbottom++;
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n",
++								stack[j].value, s[i].value, pri, nlps);
++					}
++				} else if (pri == 3) {
++					/*
++					 * we can replace as many stems as
++					 * neccessary
++					 */
++					nnew += 2;
++					while (nnew > 0 && s[nnew - 1].value >= stack[j].value) {
++						nnew -= 2;
++						if (ISDBG(MAINSTEMS))
++							fprintf(pfa_file, "%% -stem %d..%d\n",
++								s[nnew].value, s[nnew + 1].value);
++					}
++					nlps = 0;
++					s[nnew] = stack[j];
++					s[nnew + 1] = s[i];
++					readystem = pri;
++					sbottom = j + 1;
++					while (sbottom < nstack
++					       && stack[sbottom].value <= stack[j].value)
++						sbottom++;
++					if (ISDBG(MAINSTEMS))
++						fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n",
++							stack[j].value, s[i].value, pri, nlps);
++				}
++			}
++		}
++	}
++	if (readystem)
++		nnew += 2;
++
++	/* change the 1-pixel-wide stems to 20-pixel-wide stems if possible 
++	 * the constant 20 is recommended in the Type1 manual 
++	 */
++	if(useblues) {
++		for(i=0; i<nnew; i+=2) {
++			if(s[i].value != s[i+1].value)
++				continue;
++			if( ((s[i].flags ^ s[i+1].flags) & ST_BLUE)==0 )
++				continue;
++			if( s[i].flags & ST_BLUE ) {
++				if(nnew>i+2 && s[i+2].value<s[i].value+22)
++					s[i+1].value=s[i+2].value-2; /* compensate for fuzziness */
++				else
++					s[i+1].value+=20;
++			} else {
++				if(i>0 && s[i-1].value>s[i].value-22)
++					s[i].value=s[i-1].value+2; /* compensate for fuzziness */
++				else
++					s[i].value-=20;
++			}
++		}
++	}
++	/* make sure that no stem it stretched between
++	 * a top zone and a bottom zone
++	 */
++	if(useblues) {
++		for(i=0; i<nnew; i+=2) {
++			a=10000; /* lowest border of top zone crosing the stem */
++			b= -10000; /* highest border of bottom zone crossing the stem */
++
++			for(j=2; j<nblues; j++) {
++				c=bluevalues[j];
++				if( c>=s[i].value && c<=s[i+1].value && c<a )
++					a=c;
++			}
++			if(nblues>=2) {
++				c=bluevalues[1];
++				if( c>=s[i].value && c<=s[i+1].value && c>b )
++					b=c;
++			}
++			for(j=1; j<notherb; j++) {
++				c=otherblues[j];
++				if( c>=s[i].value && c<=s[i+1].value && c>b )
++					b=c;
++			}
++			if( a!=10000 && b!= -10000 ) { /* it is stretched */
++				/* split the stem into 2 ghost stems */
++				for(j=nnew+1; j>i+1; j--) /* make free space */
++					s[j]=s[j-2];
++				nnew+=2;
++
++				if(s[i].value+22 >= a)
++					s[i+1].value=a-2; /* leave space for fuzziness */
++				else
++					s[i+1].value=s[i].value+20;
++
++				if(s[i+3].value-22 <= b)
++					s[i+2].value=b+2; /* leave space for fuzziness */
++				else
++					s[i+2].value=s[i+3].value-20;
++
++				i+=2;
++			}
++		}
++	}
++	/* look for triple stems */
++	for (i = 0; i < nnew; i += 2) {
++		if (nnew - i >= 6) {
++			a = s[i].value + s[i + 1].value;
++			b = s[i + 2].value + s[i + 3].value;
++			c = s[i + 4].value + s[i + 5].value;
++
++			w1 = s[i + 1].value - s[i].value;
++			w2 = s[i + 3].value - s[i + 2].value;
++			w3 = s[i + 5].value - s[i + 4].value;
++
++			fw = w3 - w1;	/* fuzz in width */
++			fd = ((c - b) - (b - a));	/* fuzz in distance
++							 * (doubled) */
++
++			/* we are able to handle some fuzz */
++			/*
++			 * it doesn't hurt if the declared stem is a bit
++			 * narrower than actual unless it's an edge in
++			 * a blue zone
++			 */
++			if (abs(abs(fd) - abs(fw)) * 5 < w2
++			    && abs(fw) * 20 < (w1 + w3)) {	/* width dirrerence <10% */
++
++				if(useblues) { /* check that we don't disturb any blue stems */
++					j=c; k=a;
++					if (fw > 0) {
++						if (fd > 0) {
++							if( s[i+5].flags & ST_BLUE )
++								continue;
++							j -= fw;
++						} else {
++							if( s[i+4].flags & ST_BLUE )
++								continue;
++							j += fw;
++						}
++					} else if(fw < 0) {
++						if (fd > 0) {
++							if( s[i+1].flags & ST_BLUE )
++								continue;
++							k -= fw;
++						} else {
++							if( s[i].flags & ST_BLUE )
++								continue;
++							k += fw;
++						}
++					}
++					pri = ((j - b) - (b - k));
++
++					if (pri > 0) {
++						if( s[i+2].flags & ST_BLUE )
++							continue;
++					} else if(pri < 0) {
++						if( s[i+3].flags & ST_BLUE )
++							continue;
++					}
++				}
++
++				/*
++				 * first fix up the width of 1st and 3rd
++				 * stems
++				 */
++				if (fw > 0) {
++					if (fd > 0) {
++						s[i + 5].value -= fw;
++						c -= fw;
++					} else {
++						s[i + 4].value += fw;
++						c += fw;
++					}
++				} else {
++					if (fd > 0) {
++						s[i + 1].value -= fw;
++						a -= fw;
++					} else {
++						s[i].value += fw;
++						a += fw;
++					}
++				}
++				fd = ((c - b) - (b - a));
++
++				if (fd > 0) {
++					s[i + 2].value += abs(fd) / 2;
++				} else {
++					s[i + 3].value -= abs(fd) / 2;
++				}
++
++				s[i].flags |= ST_3;
++				i += 4;
++			}
++		}
++	}
++
++	return (nnew & ~1);	/* number of lines must be always even */
++}
++
++/*
++ * these macros and function allow to set the base stem,
++ * check that it's not empty and subtract another stem
++ * from the base stem (possibly dividing it into multiple parts)
++ */
++
++/* pairs for pieces of the base stem */
++static short xbstem[MAX_STEMS*2]; 
++/* index of the last point */
++static int xblast= -1; 
++
++#define setbasestem(from, to) \
++	(xbstem[0]=from, xbstem[1]=to, xblast=1)
++#define isbaseempty()	(xblast<=0)
++
++/* returns 1 if was overlapping, 0 otherwise */
++static int
++subfrombase(
++	int from,
++	int to
++) 
++{
++	int a, b;
++	int i, j;
++
++	if(isbaseempty())
++		return 0;
++
++	/* handle the simple case simply */
++	if(from > xbstem[xblast] || to < xbstem[0])
++		return 0;
++
++	/* the binary search may be more efficient */
++	/* but for now the linear search is OK */
++	for(b=1; from > xbstem[b]; b+=2) {} /* result: from <= xbstem[b] */
++	for(a=xblast-1; to < xbstem[a]; a-=2) {} /* result: to >= xbstem[a] */
++
++	/* now the interesting examples are:
++	 * (it was hard for me to understand, so I looked at the examples)
++	 * 1
++	 *     a|-----|          |-----|b   |-----|     |-----|
++	 *              f|-----|t
++	 * 2
++	 *     a|-----|b         |-----|    |-----|     |-----|
++	 *      f|--|t
++	 * 3
++	 *     a|-----|b         |-----|    |-----|     |-----|
++	 *           f|-----|t
++	 * 4
++	 *      |-----|b        a|-----|    |-----|     |-----|
++	 *          f|------------|t
++	 * 5
++	 *      |-----|          |-----|b   |-----|    a|-----|
++	 *                   f|-----------------------------|t
++	 * 6
++	 *      |-----|b         |-----|    |-----|    a|-----|
++	 *   f|--------------------------------------------------|t
++	 * 7
++	 *      |-----|b         |-----|   a|-----|     |-----|
++	 *          f|--------------------------|t
++	 */
++
++	if(a < b-1) /* hits a gap  - example 1 */
++		return 0;
++
++	/* now the subtraction itself */
++
++	if(a==b-1 && from > xbstem[a] && to < xbstem[b]) {
++		/* overlaps with only one subrange and splits it - example 2 */
++		j=xblast; i=(xblast+=2);
++		while(j>=b)
++			xbstem[i--]=xbstem[j--];
++		xbstem[b]=from-1;
++		xbstem[b+1]=to+1;
++		return 1;
++	/* becomes
++	 * 2a
++	 *     a|b   ||          |-----|    |-----|     |-----|
++	 *      f|--|t
++	 */
++	}
++
++	if(xbstem[b-1] < from) {
++		/* cuts the back of this subrange - examples 3, 4, 7 */
++		xbstem[b] = from-1;
++		b+=2;
++	/* becomes
++	 * 3a
++	 *     a|----|           |-----|b   |-----|     |-----|
++	 *           f|-----|t
++	 * 4a
++	 *      |---|           a|-----|b   |-----|     |-----|
++	 *          f|------------|t
++	 * 7a
++	 *      |---|            |-----|b  a|-----|     |-----|
++	 *          f|--------------------------|t
++	 */
++	}
++
++	if(xbstem[a+1] > to) {
++		/* cuts the front of this subrange - examples 4a, 5, 7a */
++		xbstem[a] = to+1;
++		a-=2;
++	/* becomes
++	 * 4b
++	 *     a|---|              |---|b   |-----|     |-----|
++	 *          f|------------|t
++	 * 5b
++	 *      |-----|          |-----|b  a|-----|          ||
++	 *                   f|-----------------------------|t
++	 * 7b
++	 *      |---|           a|-----|b        ||     |-----|
++	 *          f|--------------------------|t
++	 */
++	}
++
++	if(a < b-1) /* now after modification it hits a gap - examples 3a, 4b */
++		return 1; /* because we have removed something */
++
++	/* now remove the subranges completely covered by the new stem */
++	/* examples 5b, 6, 7b */
++	i=b-1; j=a+2;
++	/* positioned as:
++	 * 5b                    i                           j
++	 *      |-----|          |-----|b  a|-----|          ||
++	 *                   f|-----------------------------|t
++	 * 6    i                                             xblast  j
++	 *      |-----|b         |-----|    |-----|    a|-----|
++	 *   f|--------------------------------------------------|t
++	 * 7b                    i               j
++	 *      |---|           a|-----|b        ||     |-----|
++	 *          f|--------------------------|t
++	 */
++	while(j <= xblast)
++		xbstem[i++]=xbstem[j++];
++	xblast=i-1;
++	return 1;
++}
++
++/* for debugging */
++static void
++printbasestem(void)
++{
++	int i;
++
++	printf("( ");
++	for(i=0; i<xblast; i+=2)
++		printf("%d-%d ", xbstem[i], xbstem[i+1]);
++	printf(") %d\n", xblast);
++}
++
++/*
++ * Join the stem borders to build the sets of substituted stems
++ * XXX add consideration of the italic angle
++ */
++static void
++joinsubstems(
++	  STEM * s,
++	  short *pairs,
++	  int nold,
++	  int useblues /* do we use the blue values ? */
++)
++{
++	int i, j, x;
++	static unsigned char mx[MAX_STEMS][MAX_STEMS];
++
++	/* we do the substituted groups of stems first
++	 * and it looks like it's going to be REALLY SLOW 
++	 * AND PAINFUL but let's bother about it later
++	 */
++
++	/* for the substituted stems we don't bother about [hv]stem3 -
++	 * anyway the X11R6 rasterizer does not bother about hstem3
++	 * at all and is able to handle only one global vstem3
++	 * per glyph 
++	 */
++
++	/* clean the used part of matrix */
++	for(i=0; i<nold; i++)
++		for(j=0; j<nold; j++)
++			mx[i][j]=0;
++
++	/* build the matrix of stem pairs */
++	for(i=0; i<nold; i++) {
++		if( s[i].flags & ST_ZONE )
++			continue;
++		if(s[i].flags & ST_BLUE)
++			mx[i][i]=1; /* allow to pair with itself if no better pair */
++		if(s[i].flags & ST_UP) { /* the down-stems are already matched */
++			setbasestem(s[i].from, s[i].to);
++			for(j=i+1; j<nold; j++) {
++				if(s[i].value==s[j].value
++				|| s[j].flags & ST_ZONE ) {
++					continue;
++				}
++				x=subfrombase(s[j].from, s[j].to);
++
++				if(s[j].flags & ST_UP) /* match only up+down pairs */
++					continue;
++
++				mx[i][j]=mx[j][i]=x;
++
++				if(isbaseempty()) /* nothing else to do */
++					break;
++			}
++		}
++	}
++
++	if(ISDBG(SUBSTEMS)) {
++		fprintf(pfa_file, "%%     ");
++		for(j=0; j<nold; j++)
++			putc( j%10==0 ? '0'+(j/10)%10 : ' ', pfa_file);
++		fprintf(pfa_file, "\n%%     ");
++		for(j=0; j<nold; j++)
++			putc('0'+j%10, pfa_file);
++		putc('\n', pfa_file);
++		for(i=0; i<nold; i++) {
++			fprintf(pfa_file, "%% %3d ",i);
++			for(j=0; j<nold; j++)
++				putc( mx[i][j] ? 'X' : '.', pfa_file);
++			putc('\n', pfa_file);
++		}
++	}
++
++	/* now use the matrix to find the best pair for each stem */
++	for(i=0; i<nold; i++) {
++		int pri, lastpri, v, f;
++
++		x= -1; /* best pair: none */
++		lastpri=0;
++
++		v=s[i].value;
++		f=s[i].flags;
++
++		if(f & ST_ZONE) {
++			pairs[i]= -1;
++			continue;
++		}
++
++		if(f & ST_UP) {
++			for(j=i+1; j<nold; j++) {
++				if(mx[i][j]==0)
++					continue;
++
++				if( (f | s[j].flags) & ST_END )
++					pri=1;
++				else if( (f | s[j].flags) & ST_FLAT )
++					pri=3;
++				else
++					pri=2;
++
++				if(lastpri==0
++				|| ( pri > lastpri  
++				&& ( lastpri==1 || s[j].value-v<20 || (s[x].value-v)*2 >= s[j].value-v ) ) ) {
++					lastpri=pri;
++					x=j;
++				}
++			}
++		} else {
++			for(j=i-1; j>=0; j--) {
++				if(mx[i][j]==0)
++					continue;
++
++				if( (f | s[j].flags) & ST_END )
++					pri=1;
++				else if( (f | s[j].flags) & ST_FLAT )
++					pri=3;
++				else
++					pri=2;
++
++				if(lastpri==0
++				|| ( pri > lastpri  
++				&& ( lastpri==1 || v-s[j].value<20 || (v-s[x].value)*2 >= v-s[j].value ) ) ) {
++					lastpri=pri;
++					x=j;
++				}
++			}
++		}
++		if(x== -1 && mx[i][i])
++			pairs[i]=i; /* a special case */
++		else
++			pairs[i]=x;
++	}
++
++	if(ISDBG(SUBSTEMS)) {
++		for(i=0; i<nold; i++) {
++			j=pairs[i];
++			if(j>0)
++				fprintf(pfa_file, "%% %d...%d  (%d x %d)\n", s[i].value, s[j].value, i, j);
++		}
++	}
++}
++
++/*
++ * Make all the stems originating at the same value get the
++ * same width. Without this the rasterizer may move the dots
++ * randomly up or down by one pixel, and that looks bad.
++ * The prioritisation is the same as in findstemat().
++ */
++static void
++uniformstems(
++	  STEM * s,
++	  short *pairs,
++	  int ns
++)
++{
++	int i, j, from, to, val, dir;
++	int pri, prevpri[2], wd, prevwd[2], prevbest[2];
++
++	for(from=0; from<ns; from=to) {
++		prevpri[0] = prevpri[1] = 0;
++		prevwd[0] = prevwd[1] = 0;
++		prevbest[0] = prevbest[1] = -1;
++		val = s[from].value;
++
++		for(to = from; to<ns && s[to].value == val; to++) {
++			dir = ((s[to].flags & ST_UP)!=0);
++
++			i=pairs[to]; /* the other side of this stem */
++			if(i<0 || i==to)
++				continue; /* oops, no other side */
++			wd=abs(s[i].value-val);
++			if(wd == 0)
++				continue;
++			pri=1;
++			if( (s[to].flags | s[i].flags) & ST_END )
++				pri=0;
++			if( prevbest[dir] == -1 || pri > prevpri[dir] || wd<prevwd[dir] ) {
++				prevbest[dir]=i;
++				prevpri[dir]=pri;
++				prevwd[dir]=wd;
++			}
++		}
++
++		for(i=from; i<to; i++) {
++			dir = ((s[i].flags & ST_UP)!=0);
++			if(prevbest[dir] >= 0) {
++				if(ISDBG(SUBSTEMS)) {
++					fprintf(stderr, "at %d (%s %d) pair %d->%d(%d)\n", i, 
++						(dir ? "UP":"DOWN"), s[i].value, pairs[i], prevbest[dir],
++						s[prevbest[dir]].value);
++				}
++				pairs[i] = prevbest[dir];
++			}
++		}
++	}
++}
++
++/* 
++ * Find the best stem in the array at the specified (value, origin),
++ * related to the entry ge.
++ * Returns its index in the array sp, -1 means "none".
++ * prevbest is the result for the other end of the line, we must 
++ * find something better than it or leave it as it is.
++ */
++static int
++findstemat(
++	int value,
++	int origin,
++	GENTRY *ge,
++	STEM *sp,
++	short *pairs,
++	int ns,
++	int prevbest /* -1 means "none" */
++)
++{
++	int i, min, max;
++	int v, si;
++	int pri, prevpri; /* priority, 0 = has ST_END, 1 = no ST_END */
++	int wd, prevwd; /* stem width */
++
++	si= -1; /* nothing yet */
++
++	/* stems are ordered by value, binary search */
++	min=0; max=ns; /* min <= i < max */
++	while( min < max ) {
++		i=(min+max)/2;
++		v=sp[i].value;
++		if(v<value)
++			min=i+1;
++		else if(v>value)
++			max=i;
++		else {
++			si=i; /* temporary value */
++			break;
++		}
++	}
++
++	if( si < 0 ) /* found nothing this time */
++		return prevbest;
++
++	/* find the priority of the prevbest */
++	/* we expect that prevbest has a pair */
++	if(prevbest>=0) {
++		i=pairs[prevbest];
++		prevpri=1;
++		if( (sp[prevbest].flags | sp[i].flags) & ST_END )
++			prevpri=0; 
++		prevwd=abs(sp[i].value-value);
++	}
++
++	/* stems are not ordered by origin, so now do the linear search */
++
++	while( si>0 && sp[si-1].value==value ) /* find the first one */
++		si--;
++
++	for(; si<ns && sp[si].value==value; si++) {
++		if(sp[si].origin != origin) 
++			continue;
++		if(sp[si].ge != ge) {
++			if(ISDBG(SUBSTEMS)) {
++				fprintf(stderr, 
++					"dbg: possible self-intersection at v=%d o=%d exp_ge=0x%x ge=0x%x\n",
++					value, origin, ge, sp[si].ge);
++			}
++			continue;
++		}
++		i=pairs[si]; /* the other side of this stem */
++		if(i<0)
++			continue; /* oops, no other side */
++		pri=1;
++		if( (sp[si].flags | sp[i].flags) & ST_END )
++			pri=0;
++		wd=abs(sp[i].value-value);
++		if( prevbest == -1 || pri >prevpri 
++		|| (pri==prevpri && prevwd==0) || (wd!=0 && wd<prevwd) ) {
++			prevbest=si;
++			prevpri=pri;
++			prevwd=wd;
++			continue;
++		}
++	}
++
++	return prevbest;
++}
++
++/* add the substems for one glyph entry 
++ * (called from groupsubstems())
++ * returns 0 if all OK, 1 if too many groups
++ */
++
++static int gssentry_lastgrp=0; /* reset to 0 for each new glyph */
++
++static int
++gssentry( /* crazy number of parameters */
++	GENTRY *ge,
++	STEM *hs, /* horizontal stems, sorted by value */
++	short *hpairs,
++	int nhs,
++	STEM *vs, /* vertical stems, sorted by value */
++	short *vpairs,
++	int nvs,
++	STEMBOUNDS *s,
++	short *egp,
++	int *nextvsi, 
++	int *nexthsi /* -2 means "check by yourself" */
++) {
++	enum {
++		SI_VP,	/* vertical primary */
++		SI_HP,	/* horizontal primary */
++		SI_SIZE /* size of the array */
++	};
++	int si[SI_SIZE]; /* indexes of relevant stems */
++
++	/* the bounds of the existing relevant stems */
++	STEMBOUNDS r[ sizeof(si) / sizeof(si[0]) * 2 ];
++	char rexpand; /* by how much we need to expand the group */
++	int nr; /* and the number of them */
++
++	/* yet more temporary storage */
++	short lb, hb, isvert;
++	int conflict, grp;
++	int i, j, x, y;
++
++
++	/* for each line or curve we try to find a horizontal and
++	 * a vertical stem corresponding to its first point
++	 * (corresponding to the last point of the previous
++	 * glyph entry), because the directions of the lines
++	 * will be eventually reversed and it will then become the last
++	 * point. And the T1 rasterizer applies the hints to 
++	 * the last point.
++	 *
++	 */
++
++	/* start with the common part, the first point */
++	x=ge->prev->ix3;
++	y=ge->prev->iy3;
++
++	if(*nextvsi == -2)
++		si[SI_VP]=findstemat(x, y, ge, vs, vpairs, nvs, -1);
++	else {
++		si[SI_VP]= *nextvsi; *nextvsi= -2;
++	}
++	if(*nexthsi == -2)
++		si[SI_HP]=findstemat(y, x, ge, hs, hpairs, nhs, -1);
++	else {
++		si[SI_HP]= *nexthsi; *nexthsi= -2;
++	}
++
++	/*
++	 * For the horizontal lines we make sure that both
++	 * ends of the line have the same horizontal stem,
++	 * and the same thing for vertical lines and stems.
++	 * In both cases we enforce the stem for the next entry.
++	 * Otherwise unpleasant effects may arise.
++	 */
++
++	if(ge->type==GE_LINE) {
++		if(ge->ix3==x) { /* vertical line */
++			*nextvsi=si[SI_VP]=findstemat(x, ge->iy3, ge->frwd, vs, vpairs, nvs, si[SI_VP]);
++		} else if(ge->iy3==y) { /* horizontal line */
++			*nexthsi=si[SI_HP]=findstemat(y, ge->ix3, ge->frwd, hs, hpairs, nhs, si[SI_HP]);
++		}
++	}
++
++	if(si[SI_VP]+si[SI_HP] == -2) /* no stems, leave it alone */
++		return 0;
++
++	/* build the array of relevant bounds */
++	nr=0;
++	for(i=0; i< sizeof(si) / sizeof(si[0]); i++) {
++		STEM *sp;
++		short *pairs;
++		int step;
++		int f;
++		int nzones, firstzone, binzone, einzone;
++		int btype, etype;
++
++		if(si[i] < 0)
++			continue;
++
++		if(i<SI_HP) {
++			r[nr].isvert=1; sp=vs; pairs=vpairs;
++		} else {
++			r[nr].isvert=0; sp=hs; pairs=hpairs;
++		}
++
++		r[nr].low=sp[ si[i] ].value;
++		r[nr].high=sp[ pairs[ si[i] ] ].value;
++
++		if(r[nr].low > r[nr].high) {
++			j=r[nr].low; r[nr].low=r[nr].high; r[nr].high=j;
++			step= -1;
++		} else {
++			step=1;
++		}
++
++		/* handle the interaction with Blue Zones */
++
++		if(i>=SI_HP) { /* only for horizontal stems */
++			if(si[i]==pairs[si[i]]) {
++				/* special case, the outermost stem in the
++				 * Blue Zone without a pair, simulate it to 20-pixel
++				 */
++				if(sp[ si[i] ].flags & ST_UP) {
++					r[nr].high+=20;
++					for(j=si[i]+1; j<nhs; j++)
++						if( (sp[j].flags & (ST_ZONE|ST_TOPZONE))
++						== (ST_ZONE|ST_TOPZONE) ) {
++							if(r[nr].high > sp[j].value-2)
++								r[nr].high=sp[j].value-2;
++							break;
++						}
++				} else {
++					r[nr].low-=20;
++					for(j=si[i]-1; j>=0; j--)
++						if( (sp[j].flags & (ST_ZONE|ST_TOPZONE))
++						== (ST_ZONE) ) {
++							if(r[nr].low < sp[j].value+2)
++								r[nr].low=sp[j].value+2;
++							break;
++						}
++				}
++			}
++
++			/* check that the stem borders don't end up in
++			 * different Blue Zones */
++			f=sp[ si[i] ].flags;
++			nzones=0; einzone=binzone=0;
++			for(j=si[i]; j!=pairs[ si[i] ]; j+=step) {
++				if( (sp[j].flags & ST_ZONE)==0 )
++					continue;
++				/* if see a zone border going in the same direction */
++				if( ((f ^ sp[j].flags) & ST_UP)==0 ) {
++					if( ++nzones == 1 ) {
++						firstzone=sp[j].value; /* remember the first one */
++						etype=sp[j].flags & ST_TOPZONE;
++					}
++					einzone=1;
++
++				} else { /* the opposite direction */
++					if(nzones==0) { /* beginning is in a blue zone */
++						binzone=1;
++						btype=sp[j].flags & ST_TOPZONE;
++					}
++					einzone=0;
++				}
++			}
++
++			/* beginning and end are in Blue Zones of different types */
++			if( binzone && einzone && (btype ^ etype)!=0 ) {
++				if( sp[si[i]].flags & ST_UP ) {
++					if(firstzone > r[nr].low+22)
++						r[nr].high=r[nr].low+20;
++					else
++						r[nr].high=firstzone-2;
++				} else {
++					if(firstzone < r[nr].high-22)
++						r[nr].low=r[nr].high-20;
++					else
++						r[nr].low=firstzone+2;
++				}
++			}
++		}
++
++		if(ISDBG(SUBSTEMS))
++			fprintf(pfa_file, "%%  at(%d,%d)[%d,%d] %d..%d %c (%d x %d)\n", x, y, i, nr,
++				r[nr].low, r[nr].high, r[nr].isvert ? 'v' : 'h',
++				si[i], pairs[si[i]]);
++
++		nr++;
++	}
++
++	/* now try to find a group */
++	conflict=0; /* no conflicts found yet */
++	for(j=0; j<nr; j++)
++		r[j].already=0;
++
++	/* check if it fits into the last group */
++	grp = gssentry_lastgrp;
++	i = (grp==0)? 0 : egp[grp-1];
++	for(; i<egp[grp]; i++) {
++		lb=s[i].low; hb=s[i].high; isvert=s[i].isvert;
++		for(j=0; j<nr; j++)
++			if( r[j].isvert==isvert  /* intersects */
++			&& r[j].low <= hb && r[j].high >= lb ) {
++				if( r[j].low == lb && r[j].high == hb ) /* coincides */
++					r[j].already=1;
++				else
++					conflict=1;
++			}
++
++		if(conflict) 
++			break;
++	}
++
++	if(conflict) { /* nope, check all the groups */
++		for(j=0; j<nr; j++)
++			r[j].already=0;
++
++		for(i=0, grp=0; i<egp[NSTEMGRP-1]; i++) {
++			if(i == egp[grp]) { /* checked all stems in a group */
++				if(conflict) {
++					grp++; conflict=0; /* check the next group */
++					for(j=0; j<nr; j++)
++						r[j].already=0;
++				} else
++					break; /* insert into this group */
++			}
++
++			lb=s[i].low; hb=s[i].high; isvert=s[i].isvert;
++			for(j=0; j<nr; j++)
++				if( r[j].isvert==isvert  /* intersects */
++				&& r[j].low <= hb && r[j].high >= lb ) {
++					if( r[j].low == lb && r[j].high == hb ) /* coincides */
++						r[j].already=1;
++					else
++						conflict=1;
++				}
++
++			if(conflict) 
++				i=egp[grp]-1; /* fast forward to the next group */
++		}
++	}
++
++	/* do we have any empty group ? */
++	if(conflict && grp < NSTEMGRP-1) {
++		grp++; conflict=0;
++		for(j=0; j<nr; j++)
++			r[j].already=0;
++	}
++
++	if(conflict) { /* oops, can't find any group to fit */
++		return 1;
++	}
++
++	/* OK, add stems to this group */
++
++	rexpand = nr;
++	for(j=0; j<nr; j++)
++		rexpand -= r[j].already;
++
++	if(rexpand > 0) {
++		for(i=egp[NSTEMGRP-1]-1; i>=egp[grp]; i--)
++			s[i+rexpand]=s[i];
++		for(i=0; i<nr; i++)
++			if(!r[i].already)
++				s[egp[grp]++]=r[i];
++		for(i=grp+1; i<NSTEMGRP; i++)
++			egp[i]+=rexpand;
++	}
++
++	ge->stemid = gssentry_lastgrp = grp;
++	return 0;
++}
++
++/*
++ * Create the groups of substituted stems from the list.
++ * Each group will be represented by a subroutine in the Subs
++ * array.
++ */
++
++static void
++groupsubstems(
++	GLYPH *g,
++	STEM *hs, /* horizontal stems, sorted by value */
++	short *hpairs,
++	int nhs,
++	STEM *vs, /* vertical stems, sorted by value */
++	short *vpairs,
++	int nvs
++)
++{
++	GENTRY *ge;
++	int i, j;
++
++	/* temporary storage */
++	STEMBOUNDS s[MAX_STEMS*2];
++	/* indexes in there, pointing past the end each stem group */
++	short egp[NSTEMGRP]; 
++
++	int nextvsi, nexthsi; /* -2 means "check by yourself" */
++
++	for(i=0; i<NSTEMGRP; i++)
++		egp[i]=0;
++
++	nextvsi=nexthsi= -2; /* processed no horiz/vert line */
++
++	gssentry_lastgrp = 0; /* reset the last group for new glyph */
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if(ge->type!=GE_LINE && ge->type!=GE_CURVE) {
++			nextvsi=nexthsi= -2; /* next path is independent */
++			continue;
++		}
++
++		if( gssentry(ge, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) {
++			WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n",
++				g->name, NSTEMGRP);
++			/* it's better to have no substituted hints at all than have only part */
++			for (ge = g->entries; ge != 0; ge = ge->next)
++				ge->stemid= -1;
++			g->nsg=0; /* just to be safe, already is 0 by initialization */
++			return;
++		}
++
++		/*
++		 * handle the last vert/horiz line of the path specially,
++		 * correct the hint for the first entry of the path
++		 */
++		if(ge->frwd != ge->next && (nextvsi != -2 || nexthsi != -2) ) {
++			if( gssentry(ge->frwd, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) {
++				WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n",
++					g->name, NSTEMGRP);
++				/* it's better to have no substituted hints at all than have only part */
++				for (ge = g->entries; ge != 0; ge = ge->next)
++					ge->stemid= -1;
++				g->nsg=0; /* just to be safe, already is 0 by initialization */
++				return;
++			}
++		}
++
++	}
++
++	/* find the index of the first empty group - same as the number of groups */
++	if(egp[0]>0) {
++		for(i=1; i<NSTEMGRP && egp[i]!=egp[i-1]; i++)
++			{}
++		g->nsg=i;
++	} else
++		g->nsg=0;
++
++	if(ISDBG(SUBSTEMS)) {
++		fprintf(pfa_file, "%% %d substem groups (%d %d %d)\n", g->nsg,
++			g->nsg>1 ? egp[g->nsg-2] : -1,
++			g->nsg>0 ? egp[g->nsg-1] : -1,
++			g->nsg<NSTEMGRP ? egp[g->nsg] : -1 );
++		j=0;
++		for(i=0; i<g->nsg; i++) {
++			fprintf(pfa_file, "%% grp %3d:      ", i);
++			for(; j<egp[i]; j++) {
++				fprintf(pfa_file, " %4d...%-4d %c  ", s[j].low, s[j].high,
++					s[j].isvert ? 'v' : 'h');
++			}
++			fprintf(pfa_file, "\n");
++		}
++	}
++
++	if(g->nsg==1) { /* it would be the same as the main stems */
++		/* so erase it */
++		for (ge = g->entries; ge != 0; ge = ge->next)
++			ge->stemid= -1;
++		g->nsg=0;
++	}
++
++	if(g->nsg>0) {
++		if( (g->nsbs=malloc(g->nsg * sizeof (egp[0]))) == 0 ) {
++			fprintf(stderr, "**** not enough memory for substituted hints ****\n");
++			exit(255);
++		}
++		memmove(g->nsbs, egp, g->nsg * sizeof(short));
++		if( (g->sbstems=malloc(egp[g->nsg-1] * sizeof (s[0]))) == 0 ) {
++			fprintf(stderr, "**** not enough memory for substituted hints ****\n");
++			exit(255);
++		}
++		memmove(g->sbstems, s, egp[g->nsg-1] * sizeof(s[0]));
++	}
++}
++
++void
++buildstems(
++	   GLYPH * g
++)
++{
++	STEM            hs[MAX_STEMS], vs[MAX_STEMS];	/* temporary working
++							 * storage */
++	short	hs_pairs[MAX_STEMS], vs_pairs[MAX_STEMS]; /* best pairs for these stems */
++	STEM           *sp;
++	GENTRY         *ge, *nge, *pge;
++	int             nx, ny;
++	int ovalue;
++	int totals, grp, lastgrp;
++
++	assertisint(g, "buildstems int");
++
++	g->nhs = g->nvs = 0;
++	memset(hs, 0, sizeof hs);
++	memset(vs, 0, sizeof vs);
++
++	/* first search the whole character for possible stem points */
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if (ge->type == GE_CURVE) {
++
++			/*
++			 * SURPRISE! 
++			 * We consider the stems bound by the
++			 * H/V ends of the curves as flat ones.
++			 *
++			 * But we don't include the point on the
++			 * other end into the range.
++			 */
++
++			/* first check the beginning of curve */
++			/* if it is horizontal, add a hstem */
++			if (ge->iy1 == ge->prev->iy3) {
++				hs[g->nhs].value = ge->iy1;
++
++				if (ge->ix1 < ge->prev->ix3)
++					hs[g->nhs].flags = ST_FLAT | ST_UP;
++				else
++					hs[g->nhs].flags = ST_FLAT;
++
++				hs[g->nhs].origin = ge->prev->ix3;
++				hs[g->nhs].ge = ge;
++
++				if (ge->ix1 < ge->prev->ix3) {
++					hs[g->nhs].from = ge->ix1+1;
++					hs[g->nhs].to = ge->prev->ix3;
++					if(hs[g->nhs].from > hs[g->nhs].to)
++						hs[g->nhs].from--;
++				} else {
++					hs[g->nhs].from = ge->prev->ix3;
++					hs[g->nhs].to = ge->ix1-1;
++					if(hs[g->nhs].from > hs[g->nhs].to)
++						hs[g->nhs].to++;
++				}
++				if (ge->ix1 != ge->prev->ix3)
++					g->nhs++;
++			}
++			/* if it is vertical, add a vstem */
++			else if (ge->ix1 == ge->prev->ix3) {
++				vs[g->nvs].value = ge->ix1;
++
++				if (ge->iy1 > ge->prev->iy3)
++					vs[g->nvs].flags = ST_FLAT | ST_UP;
++				else
++					vs[g->nvs].flags = ST_FLAT;
++
++				vs[g->nvs].origin = ge->prev->iy3;
++				vs[g->nvs].ge = ge;
++
++				if (ge->iy1 < ge->prev->iy3) {
++					vs[g->nvs].from = ge->iy1+1;
++					vs[g->nvs].to = ge->prev->iy3;
++					if(vs[g->nvs].from > vs[g->nvs].to)
++						vs[g->nvs].from--;
++				} else {
++					vs[g->nvs].from = ge->prev->iy3;
++					vs[g->nvs].to = ge->iy1-1;
++					if(vs[g->nvs].from > vs[g->nvs].to)
++						vs[g->nvs].to++;
++				}
++
++				if (ge->iy1 != ge->prev->iy3)
++					g->nvs++;
++			}
++			/* then check the end of curve */
++			/* if it is horizontal, add a hstem */
++			if (ge->iy3 == ge->iy2) {
++				hs[g->nhs].value = ge->iy3;
++
++				if (ge->ix3 < ge->ix2)
++					hs[g->nhs].flags = ST_FLAT | ST_UP;
++				else
++					hs[g->nhs].flags = ST_FLAT;
++
++				hs[g->nhs].origin = ge->ix3;
++				hs[g->nhs].ge = ge->frwd;
++
++				if (ge->ix3 < ge->ix2) {
++					hs[g->nhs].from = ge->ix3;
++					hs[g->nhs].to = ge->ix2-1;
++					if( hs[g->nhs].from > hs[g->nhs].to )
++						hs[g->nhs].to++;
++				} else {
++					hs[g->nhs].from = ge->ix2+1;
++					hs[g->nhs].to = ge->ix3;
++					if( hs[g->nhs].from > hs[g->nhs].to )
++						hs[g->nhs].from--;
++				}
++
++				if (ge->ix3 != ge->ix2)
++					g->nhs++;
++			}
++			/* if it is vertical, add a vstem */
++			else if (ge->ix3 == ge->ix2) {
++				vs[g->nvs].value = ge->ix3;
++
++				if (ge->iy3 > ge->iy2)
++					vs[g->nvs].flags = ST_FLAT | ST_UP;
++				else
++					vs[g->nvs].flags = ST_FLAT;
++
++				vs[g->nvs].origin = ge->iy3;
++				vs[g->nvs].ge = ge->frwd;
++
++				if (ge->iy3 < ge->iy2) {
++					vs[g->nvs].from = ge->iy3;
++					vs[g->nvs].to = ge->iy2-1;
++					if( vs[g->nvs].from > vs[g->nvs].to )
++						vs[g->nvs].to++;
++				} else {
++					vs[g->nvs].from = ge->iy2+1;
++					vs[g->nvs].to = ge->iy3;
++					if( vs[g->nvs].from > vs[g->nvs].to )
++						vs[g->nvs].from--;
++				}
++
++				if (ge->iy3 != ge->iy2)
++					g->nvs++;
++			} else {
++
++				/*
++				 * check the end of curve for a not smooth
++				 * local extremum
++				 */
++				nge = ge->frwd;
++
++				if (nge == 0)
++					continue;
++				else if (nge->type == GE_LINE) {
++					nx = nge->ix3;
++					ny = nge->iy3;
++				} else if (nge->type == GE_CURVE) {
++					nx = nge->ix1;
++					ny = nge->iy1;
++				} else
++					continue;
++
++				/* check for vertical extremums */
++				if ((ge->iy3 > ge->iy2 && ge->iy3 > ny)
++				|| (ge->iy3 < ge->iy2 && ge->iy3 < ny)) {
++					hs[g->nhs].value = ge->iy3;
++					hs[g->nhs].from
++						= hs[g->nhs].to
++						= hs[g->nhs].origin = ge->ix3;
++					hs[g->nhs].ge = ge->frwd;
++
++					if (ge->ix3 < ge->ix2
++					    || nx < ge->ix3)
++						hs[g->nhs].flags = ST_UP;
++					else
++						hs[g->nhs].flags = 0;
++
++					if (ge->ix3 != ge->ix2 || nx != ge->ix3)
++						g->nhs++;
++				}
++				/*
++				 * the same point may be both horizontal and
++				 * vertical extremum
++				 */
++				/* check for horizontal extremums */
++				if ((ge->ix3 > ge->ix2 && ge->ix3 > nx)
++				|| (ge->ix3 < ge->ix2 && ge->ix3 < nx)) {
++					vs[g->nvs].value = ge->ix3;
++					vs[g->nvs].from
++						= vs[g->nvs].to
++						= vs[g->nvs].origin = ge->iy3;
++					vs[g->nvs].ge = ge->frwd;
++
++					if (ge->iy3 > ge->iy2
++					    || ny > ge->iy3)
++						vs[g->nvs].flags = ST_UP;
++					else
++						vs[g->nvs].flags = 0;
++
++					if (ge->iy3 != ge->iy2 || ny != ge->iy3)
++						g->nvs++;
++				}
++			}
++
++		} else if (ge->type == GE_LINE) {
++			nge = ge->frwd;
++
++			/* if it is horizontal, add a hstem */
++			/* and the ends as vstems if they brace the line */
++			if (ge->iy3 == ge->prev->iy3
++			&& ge->ix3 != ge->prev->ix3) {
++				hs[g->nhs].value = ge->iy3;
++				if (ge->ix3 < ge->prev->ix3) {
++					hs[g->nhs].flags = ST_FLAT | ST_UP;
++					hs[g->nhs].from = ge->ix3;
++					hs[g->nhs].to = ge->prev->ix3;
++				} else {
++					hs[g->nhs].flags = ST_FLAT;
++					hs[g->nhs].from = ge->prev->ix3;
++					hs[g->nhs].to = ge->ix3;
++				}
++				hs[g->nhs].origin = ge->ix3;
++				hs[g->nhs].ge = ge->frwd;
++
++				pge = ge->bkwd;
++
++				/* add beginning as vstem */
++				vs[g->nvs].value = pge->ix3;
++				vs[g->nvs].origin
++					= vs[g->nvs].from
++					= vs[g->nvs].to = pge->iy3;
++				vs[g->nvs].ge = ge;
++
++				if(pge->type==GE_CURVE)
++					ovalue=pge->iy2;
++				else
++					ovalue=pge->prev->iy3;
++
++				if (pge->iy3 > ovalue)
++					vs[g->nvs].flags = ST_UP | ST_END;
++				else if (pge->iy3 < ovalue)
++					vs[g->nvs].flags = ST_END;
++				else
++					vs[g->nvs].flags = 0;
++
++				if( vs[g->nvs].flags != 0 )
++					g->nvs++;
++
++				/* add end as vstem */
++				vs[g->nvs].value = ge->ix3;
++				vs[g->nvs].origin
++					= vs[g->nvs].from
++					= vs[g->nvs].to = ge->iy3;
++				vs[g->nvs].ge = ge->frwd;
++
++				if(nge->type==GE_CURVE)
++					ovalue=nge->iy1;
++				else
++					ovalue=nge->iy3;
++
++				if (ovalue > ge->iy3)
++					vs[g->nvs].flags = ST_UP | ST_END;
++				else if (ovalue < ge->iy3)
++					vs[g->nvs].flags = ST_END;
++				else
++					vs[g->nvs].flags = 0;
++
++				if( vs[g->nvs].flags != 0 )
++					g->nvs++;
++
++				g->nhs++;
++			}
++			/* if it is vertical, add a vstem */
++			/* and the ends as hstems if they brace the line  */
++			else if (ge->ix3 == ge->prev->ix3 
++			&& ge->iy3 != ge->prev->iy3) {
++				vs[g->nvs].value = ge->ix3;
++				if (ge->iy3 > ge->prev->iy3) {
++					vs[g->nvs].flags = ST_FLAT | ST_UP;
++					vs[g->nvs].from = ge->prev->iy3;
++					vs[g->nvs].to = ge->iy3;
++				} else {
++					vs[g->nvs].flags = ST_FLAT;
++					vs[g->nvs].from = ge->iy3;
++					vs[g->nvs].to = ge->prev->iy3;
++				}
++				vs[g->nvs].origin = ge->iy3;
++				vs[g->nvs].ge = ge->frwd;
++
++				pge = ge->bkwd;
++
++				/* add beginning as hstem */
++				hs[g->nhs].value = pge->iy3;
++				hs[g->nhs].origin
++					= hs[g->nhs].from
++					= hs[g->nhs].to = pge->ix3;
++				hs[g->nhs].ge = ge;
++
++				if(pge->type==GE_CURVE)
++					ovalue=pge->ix2;
++				else
++					ovalue=pge->prev->ix3;
++
++				if (pge->ix3 < ovalue)
++					hs[g->nhs].flags = ST_UP | ST_END;
++				else if (pge->ix3 > ovalue)
++					hs[g->nhs].flags = ST_END;
++				else
++					hs[g->nhs].flags = 0;
++
++				if( hs[g->nhs].flags != 0 )
++					g->nhs++;
++
++				/* add end as hstem */
++				hs[g->nhs].value = ge->iy3;
++				hs[g->nhs].origin
++					= hs[g->nhs].from
++					= hs[g->nhs].to = ge->ix3;
++				hs[g->nhs].ge = ge->frwd;
++
++				if(nge->type==GE_CURVE)
++					ovalue=nge->ix1;
++				else
++					ovalue=nge->ix3;
++
++				if (ovalue < ge->ix3)
++					hs[g->nhs].flags = ST_UP | ST_END;
++				else if (ovalue > ge->ix3)
++					hs[g->nhs].flags = ST_END;
++				else
++					hs[g->nhs].flags = 0;
++
++				if( hs[g->nhs].flags != 0 )
++					g->nhs++;
++
++				g->nvs++;
++			}
++			/*
++			 * check the end of line for a not smooth local
++			 * extremum
++			 */
++			nge = ge->frwd;
++
++			if (nge == 0)
++				continue;
++			else if (nge->type == GE_LINE) {
++				nx = nge->ix3;
++				ny = nge->iy3;
++			} else if (nge->type == GE_CURVE) {
++				nx = nge->ix1;
++				ny = nge->iy1;
++			} else
++				continue;
++
++			/* check for vertical extremums */
++			if ((ge->iy3 > ge->prev->iy3 && ge->iy3 > ny)
++			|| (ge->iy3 < ge->prev->iy3 && ge->iy3 < ny)) {
++				hs[g->nhs].value = ge->iy3;
++				hs[g->nhs].from
++					= hs[g->nhs].to
++					= hs[g->nhs].origin = ge->ix3;
++				hs[g->nhs].ge = ge->frwd;
++
++				if (ge->ix3 < ge->prev->ix3
++				    || nx < ge->ix3)
++					hs[g->nhs].flags = ST_UP;
++				else
++					hs[g->nhs].flags = 0;
++
++				if (ge->ix3 != ge->prev->ix3 || nx != ge->ix3)
++					g->nhs++;
++			}
++			/*
++			 * the same point may be both horizontal and vertical
++			 * extremum
++			 */
++			/* check for horizontal extremums */
++			if ((ge->ix3 > ge->prev->ix3 && ge->ix3 > nx)
++			|| (ge->ix3 < ge->prev->ix3 && ge->ix3 < nx)) {
++				vs[g->nvs].value = ge->ix3;
++				vs[g->nvs].from
++					= vs[g->nvs].to
++					= vs[g->nvs].origin = ge->iy3;
++				vs[g->nvs].ge = ge->frwd;
++
++				if (ge->iy3 > ge->prev->iy3
++				    || ny > ge->iy3)
++					vs[g->nvs].flags = ST_UP;
++				else
++					vs[g->nvs].flags = 0;
++
++				if (ge->iy3 != ge->prev->iy3 || ny != ge->iy3)
++					g->nvs++;
++			}
++		}
++	}
++
++	g->nhs=addbluestems(hs, g->nhs);
++	sortstems(hs, g->nhs);
++	sortstems(vs, g->nvs);
++
++	if (ISDBG(STEMS))
++		debugstems(g->name, hs, g->nhs, vs, g->nvs);
++
++	/* find the stems interacting with the Blue Zones */
++	markbluestems(hs, g->nhs);
++
++	if(subhints) {
++		if (ISDBG(SUBSTEMS))
++			fprintf(pfa_file, "%% %s: joining subst horizontal stems\n", g->name);
++		joinsubstems(hs, hs_pairs, g->nhs, 1);
++		uniformstems(hs, hs_pairs, g->nhs);
++
++		if (ISDBG(SUBSTEMS))
++			fprintf(pfa_file, "%% %s: joining subst vertical stems\n", g->name);
++		joinsubstems(vs, vs_pairs, g->nvs, 0);
++
++		groupsubstems(g, hs, hs_pairs, g->nhs, vs, vs_pairs, g->nvs);
++	}
++
++	if (ISDBG(MAINSTEMS))
++		fprintf(pfa_file, "%% %s: joining main horizontal stems\n", g->name);
++	g->nhs = joinmainstems(hs, g->nhs, 1);
++	if (ISDBG(MAINSTEMS))
++		fprintf(pfa_file, "%% %s: joining main vertical stems\n", g->name);
++	g->nvs = joinmainstems(vs, g->nvs, 0);
++
++	if (ISDBG(MAINSTEMS))
++		debugstems(g->name, hs, g->nhs, vs, g->nvs);
++
++	if(g->nhs > 0) {
++		if ((sp = malloc(sizeof(STEM) * g->nhs)) == 0) {
++			fprintf(stderr, "**** not enough memory for hints ****\n");
++			exit(255);
++		}
++		g->hstems = sp;
++		memcpy(sp, hs, sizeof(STEM) * g->nhs);
++	} else
++		g->hstems = 0;
++
++	if(g->nvs > 0) {
++		if ((sp = malloc(sizeof(STEM) * g->nvs)) == 0) {
++			fprintf(stderr, "**** not enough memory for hints ****\n");
++			exit(255);
++		}
++		g->vstems = sp;
++		memcpy(sp, vs, sizeof(STEM) * g->nvs);
++	} else
++		g->vstems = 0;
++
++	/* now check that the stems won't overflow the interpreter's stem stack:
++	 * some interpreters (like X11) push the stems on each change into
++	 * stack and pop them only after the whole glyphs is completed.
++	 */
++
++	totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */
++	lastgrp = -1;
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		grp=ge->stemid;
++		if(grp >= 0 && grp != lastgrp)  {
++			if(grp==0)
++				totals += g->nsbs[0];
++			else
++				totals += g->nsbs[grp] - g->nsbs[grp-1];
++
++			lastgrp = grp;
++		}
++	}
++
++	/* be on the safe side, check for >= , not > */
++	if(totals >= max_stemdepth) {  /* oops, too deep */
++		WARNING_2 {
++			fprintf(stderr, "Warning: glyph %s needs hint stack depth %d\n", g->name, totals);
++			fprintf(stderr, "  (limit %d): removed the substituted hints from it\n", max_stemdepth);
++		}
++		if(g->nsg > 0) {
++			for (ge = g->entries; ge != 0; ge = ge->next)
++				ge->stemid = -1;
++			free(g->sbstems); g->sbstems = 0;
++			free(g->nsbs); g->nsbs = 0;
++			g->nsg = 0;
++		}
++	}
++
++	/* now check if there are too many main stems */
++	totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */
++	if(totals >= max_stemdepth) { 
++		/* even worse, too much of non-substituted stems */
++		WARNING_2 {
++			fprintf(stderr, "Warning: glyph %s has %d main hints\n", g->name, totals);
++			fprintf(stderr, "  (limit %d): removed the hints from it\n", max_stemdepth);
++		}
++		if(g->vstems) {
++			free(g->vstems); g->vstems = 0; g->nvs = 0;
++		}
++		if(g->hstems) {
++			free(g->hstems); g->hstems = 0; g->nhs = 0;
++		}
++	}
++}
++
++/* convert weird curves that are close to lines into lines.
++*/
++
++void
++fstraighten(
++	   GLYPH * g
++)
++{
++	GENTRY         *ge, *pge, *nge, *ige;
++	double          df;
++	int             dir;
++	double          iln, oln;
++	int             svdir, i, o;
++
++	for (ige = g->entries; ige != 0; ige = ige->next) {
++		if (ige->type != GE_CURVE)
++			continue;
++
++		ge = ige;
++		pge = ge->bkwd;
++		nge = ge->frwd;
++
++		df = 0.;
++
++		/* look for vertical then horizontal */
++		for(i=0; i<2; i++) {
++			o = !i; /* other axis */
++
++			iln = fabs(ge->fpoints[i][2] - pge->fpoints[i][2]);
++			oln = fabs(ge->fpoints[o][2] - pge->fpoints[o][2]);
++			/*
++			 * if current curve is almost a vertical line, and it
++			 * doesn't begin or end horizontally (and the prev/next
++			 * line doesn't join smoothly ?)
++			 */
++			if( oln < 1.
++			|| ge->fpoints[o][2] == ge->fpoints[o][1] 
++			|| ge->fpoints[o][0] == pge->fpoints[o][2]
++			|| iln > 2.
++			|| (iln > 1.  && iln/oln > 0.1) )
++				continue;
++
++
++			if(ISDBG(STRAIGHTEN)) 
++				fprintf(stderr,"** straighten almost %s\n", (i? "horizontal":"vertical"));
++
++			df = ge->fpoints[i][2] - pge->fpoints[i][2];
++			dir = fsign(ge->fpoints[o][2] - pge->fpoints[o][2]);
++			ge->type = GE_LINE;
++
++			/*
++			 * suck in all the sequence of such almost lines
++			 * going in the same direction but not deviating
++			 * too far from vertical
++			 */
++			iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]);
++			oln = nge->fpoints[o][2] - ge->fpoints[o][2];
++
++			while (fabs(df) <= 5 && nge->type == GE_CURVE
++			&& dir == fsign(oln) /* that also gives oln != 0 */
++			&& iln <= 2.
++			&& ( iln <= 1.  || iln/fabs(oln) <= 0.1 ) ) {
++				ge->fx3 = nge->fx3;
++				ge->fy3 = nge->fy3;
++
++				if(ISDBG(STRAIGHTEN))
++					fprintf(stderr,"** straighten collapsing %s\n", (i? "horizontal":"vertical"));
++				freethisge(nge);
++				fixendpath(ge);
++				pge = ge->bkwd;
++				nge = ge->frwd;
++
++				df = ge->fpoints[i][2] - pge->fpoints[i][2];
++
++				iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]);
++				oln = nge->fpoints[o][2] - ge->fpoints[o][2];
++			}
++
++			/* now check what do we have as previous/next line */
++
++			if(ge != pge) { 
++				if( pge->type == GE_LINE && pge->fpoints[i][2] == pge->prev->fpoints[i][2]
++				&& fabs(pge->fpoints[o][2] != pge->prev->fpoints[o][2]) ) {
++					if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with previous 0x%x 0x%x\n", pge, ge);
++					/* join the previous line with current */
++					pge->fx3 = ge->fx3;
++					pge->fy3 = ge->fy3;
++
++					ige = freethisge(ge)->prev; /* keep the iterator valid */
++					ge = pge;
++					fixendpath(ge);
++					pge = ge->bkwd;
++				}
++			}
++
++			if(ge != nge) { 
++				if (nge->type == GE_LINE && nge->fpoints[i][2] == ge->fpoints[i][2]
++				&& fabs(nge->fpoints[o][2] != ge->fpoints[o][2]) ) {
++					if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with next 0x%x 0x%x\n", ge, nge);
++					/* join the next line with current */
++					ge->fx3 = nge->fx3;
++					ge->fy3 = nge->fy3;
++
++					freethisge(nge);
++					fixendpath(ge);
++					pge = ge->bkwd;
++					nge = ge->frwd;
++
++				}
++			}
++
++			if(ge != pge) { 
++				/* try to align the lines if neccessary */
++				if(df != 0.)
++					fclosegap(ge, ge, i, df, NULL);
++			} else {
++				/* contour consists of only one line, get rid of it */
++				ige = freethisge(ge); /* keep the iterator valid */
++				if(ige == 0) /* this was the last contour */
++					return;
++				ige = ige->prev;
++			}
++
++			break; /* don't bother looking at the other axis */
++		}
++	}
++}
++
++/* solve a square equation,
++ * returns the number of solutions found, the solutions
++ * are stored in res which should point to array of two doubles.
++ * min and max limit the area for solutions
++ */
++
++static int
++fsqequation(
++	double a,
++	double b,
++	double c,
++	double *res,
++	double min,
++	double max
++)
++{
++	double D;
++	int n;
++
++	if(ISDBG(SQEQ)) fprintf(stderr, "sqeq(%g,%g,%g) [%g;%g]\n", a, b, c, min, max);
++
++	if(fabs(a) < 0.000001) { /* if a linear equation */
++		n=0;
++		if(fabs(b) < 0.000001) /* not an equation at all */
++			return 0;
++		res[0] = -c/b;
++		if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: linear t=%g\n", res[0]);
++		if(res[0] >= min && res[0] <= max)
++			n++;
++		return n;
++	}
++
++	D = b*b - 4.0*a*c;
++	if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: D=%g\n", D);
++	if(D<0)
++		return 0;
++
++	D = sqrt(D);
++
++	n=0;
++	res[0] = (-b+D) / (2*a);
++	if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t1=%g\n", res[0]);
++	if(res[0] >= min && res[0] <= max)
++		n++;
++
++	res[n] = (-b-D) / (2*a);
++	if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t2=%g\n", res[n]);
++	if(res[n] >= min && res[n] <= max)
++		n++;
++
++	/* return 2nd solution only if it's different enough */
++	if(n==2 && fabs(res[0]-res[1])<0.000001)
++		n=1;
++
++	return n;
++}
++
++/* check that the curves don't cross quadrant boundary */
++/* (float) */
++
++/*
++  Here we make sure that the curve does not continue past
++  horizontal or vertical extremums. The horizontal points are
++  explained, vertical points are by analogy.
++
++  The horizontal points are where the derivative
++  dy/dx is equal to 0. But the Bezier curves are defined by
++  parametric formulas
++   x=fx(t)
++   y=fy(t)
++  so finding this derivative is complicated.
++  Also even if we find some point (x,y) splitting at this point
++  is far not obvious. Fortunately we can use dy/dt = 0 instead,
++  this gets to a rather simple square equation and splitting
++  at a known value of t is simple.
++
++  The formulas are:
++
++  y = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3
++  y = (-A+3*B-3*C+D)*t^3 + (3*A-6*B+3*C)*t^2 + (-3*A+3*B)*t + A
++  dy/dt = 3*(-A+3*B-3*C+D)*t^2 + 2*(3*A-6*B+3*C)*t + (-3*A+3*B)
++ */
++
++void
++ffixquadrants(
++	GLYPH *g
++)
++{
++	GENTRY         *ge, *nge;
++	int	i, j, np, oldnp;
++	double	sp[5]; /* split points, last one empty */
++	char dir[5]; /* for debugging, direction by which split happened */
++	double a, b, *pts; /* points of a curve */
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if (ge->type != GE_CURVE)
++			continue;
++		
++	doagain:
++		np = 0; /* no split points yet */
++		if(ISDBG(QUAD)) {
++			fprintf(stderr, "%s: trying 0x%x (%g %g) (%g %g) (%g %g) (%g %g)\n  ", g->name,
++				ge,  ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2,
++				ge->fx3, ge->fy3);
++		}
++		for(i=0; i<2; i++) { /* first for x then for y */
++			/* find the cooridnates of control points */
++			a = ge->prev->fpoints[i][2];
++			pts = &ge->fpoints[i][0];
++
++			oldnp = np;
++			np += fsqequation(
++				3.0*(-a + 3.0*pts[0] - 3.0*pts[1] + pts[2]),
++				6.0*(a - 2.0*pts[0] + pts[1]),
++				3.0*(-a + pts[0]),
++				&sp[np],
++				0.0, 1.0); /* XXX range is [0;1] */
++
++			if(np == oldnp)
++				continue;
++
++			if(ISDBG(QUAD))
++				fprintf(stderr, "%s: 0x%x: %d pts(%c): ", 
++					g->name, ge, np-oldnp, i? 'y':'x');
++
++			/* remove points that are too close to the ends 
++			 * because hor/vert ends are permitted, also
++			 * if the split point is VERY close to the ends
++			 * but not exactly then just flatten it and check again.
++			 */
++			for(j = oldnp; j<np; j++) {
++				dir[j] = i;
++				if(ISDBG(QUAD))
++					fprintf(stderr, "%g ", sp[j]);
++				if(sp[j] < 0.03) { /* front end of curve */
++					if(ge->fpoints[i][0] != ge->prev->fpoints[i][2]) {
++						ge->fpoints[i][0] = ge->prev->fpoints[i][2];
++						if(ISDBG(QUAD)) fprintf(stderr, "flattened at front\n");
++						goto doagain;
++					}
++					if( ge->fpoints[i][1] != ge->fpoints[i][0]
++					&& fsign(ge->fpoints[i][2] - ge->fpoints[i][1])
++							!= fsign(ge->fpoints[i][1] - ge->fpoints[i][0]) ) {
++						ge->fpoints[i][1] = ge->fpoints[i][0];
++						if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at front\n");
++						goto doagain;
++					}
++					sp[j] = sp[j+1]; np--; j--;
++					if(ISDBG(QUAD)) fprintf(stderr, "(front flat)  ");
++				} else if(sp[j] > 0.97) { /* rear end of curve */
++					if(ge->fpoints[i][1] != ge->fpoints[i][2]) {
++						ge->fpoints[i][1] = ge->fpoints[i][2];
++						if(ISDBG(QUAD)) fprintf(stderr, "flattened at rear\n");
++						goto doagain;
++					}
++					if( ge->fpoints[i][0] != ge->fpoints[i][1]
++					&& fsign(ge->prev->fpoints[i][2] - ge->fpoints[i][0])
++							!= fsign(ge->fpoints[i][0] - ge->fpoints[i][1]) ) {
++						ge->fpoints[i][0] = ge->fpoints[i][1];
++						if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at rear\n");
++						goto doagain;
++					}
++					sp[j] = sp[j+1]; np--; j--;
++					if(ISDBG(QUAD)) fprintf(stderr, "(rear flat)  ");
++				} 
++			}
++			if(ISDBG(QUAD)) fprintf(stderr, "\n");
++		}
++
++		if(np==0) /* no split points, leave it alone */
++			continue;
++
++		if(ISDBG(QUAD)) {
++			fprintf(stderr, "%s: splitting 0x%x (%g %g) (%g %g) (%g %g) (%g %g) at %d points\n  ", g->name,
++				ge,  ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2,
++				ge->fx3, ge->fy3, np);
++			for(i=0; i<np; i++)
++				fprintf(stderr, "%g(%c) ", sp[i], dir[i] ? 'y':'x');
++			fprintf(stderr, "\n");
++		}
++
++		/* sort the points ascending */
++		for(i=0; i<np; i++)
++			for(j=i+1; j<np; j++)
++				if(sp[i] > sp[j]) {
++					a = sp[i]; sp[i] = sp[j]; sp[j] = a;
++				}
++
++		/* now finally do the split on each point */
++		for(j=0; j<np; j++) {
++			double k1, k2, c;
++
++			k1 = sp[j];
++			k2 = 1 - k1;
++
++			if(ISDBG(QUAD)) fprintf(stderr, "   0x%x %g/%g\n", ge, k1, k2);
++
++			nge = newgentry(GEF_FLOAT);
++			(*nge) = (*ge);
++
++#define SPLIT(pt1, pt2)	( (pt1) + k1*((pt2)-(pt1)) ) /* order is important! */
++			for(i=0; i<2; i++) { /* for x and y */
++				a = ge->fpoints[i][0]; /* get the middle points */
++				b = ge->fpoints[i][1];
++
++				/* calculate new internal points */
++				c = SPLIT(a, b);
++
++				ge->fpoints[i][0] = SPLIT(ge->prev->fpoints[i][2], a);
++				ge->fpoints[i][1] = SPLIT(ge->fpoints[i][0], c);
++
++				nge->fpoints[i][1] = SPLIT(b, nge->fpoints[i][2]);
++				nge->fpoints[i][0] = SPLIT(c, nge->fpoints[i][1]);
++
++				ge->fpoints[i][2] = SPLIT(ge->fpoints[i][1],
++					+ nge->fpoints[i][0]);
++			}
++#undef SPLIT
++
++			addgeafter(ge, nge);
++
++			/* go to the next part, adjust remaining points */
++			ge = nge;
++			for(i=j+1; i<np; i++)
++				sp[i] = (sp[i]-k1) / k2;
++		}
++	}
++
++}
++
++/* check if a curve is a zigzag */
++
++static int
++iiszigzag(
++	GENTRY *ge
++) 
++{
++	double          k, k1, k2;
++	int             a, b;
++
++	if (ge->type != GE_CURVE)
++		return 0;
++
++	a = ge->iy2 - ge->iy1;
++	b = ge->ix2 - ge->ix1;
++	if(a == 0) {
++		if(b == 0) {
++			return 0;
++		} else
++			k = FBIGVAL;
++	} else
++		k = fabs((double) b / (double) a);
++
++	a = ge->iy1 - ge->prev->iy3;
++	b = ge->ix1 - ge->prev->ix3;
++	if(a == 0) {
++		if(b == 0) {
++			return 0;
++		} else
++			k1 = FBIGVAL;
++	} else
++		k1 = fabs((double) b / (double) a);
++
++	a = ge->iy3 - ge->iy2;
++	b = ge->ix3 - ge->ix2;
++	if(a == 0) {
++		if(b == 0) {
++			return 0;
++		} else
++			k2 = FBIGVAL;
++	} else
++		k2 = fabs((double) b / (double) a);
++
++	/* if the curve is not a zigzag */
++	if ((k1+0.0001 >= k && k2 <= k+0.0001) || (k1 <= k+0.0001 && k2+0.0001 >= k))
++		return 0;
++	else
++		return 1;
++}
++
++/* check if a curve is a zigzag - floating */
++
++static int
++fiszigzag(
++	GENTRY *ge
++) 
++{
++	double          k, k1, k2;
++	double          a, b;
++
++	if (ge->type != GE_CURVE)
++		return 0;
++
++	a = fabs(ge->fy2 - ge->fy1);
++	b = fabs(ge->fx2 - ge->fx1);
++	if(a < FEPS) {
++		if(b < FEPS) {
++			return 0;
++		} else
++			k = FBIGVAL;
++	} else
++		k = b / a;
++
++	a = fabs(ge->fy1 - ge->prev->fy3);
++	b = fabs(ge->fx1 - ge->prev->fx3);
++	if(a < FEPS) {
++		if(b < FEPS) {
++			return 0;
++		} else
++			k1 = FBIGVAL;
++	} else
++		k1 = b / a;
++
++	a = fabs(ge->fy3 - ge->fy2);
++	b = fabs(ge->fx3 - ge->fx2);
++	if(a < FEPS) {
++		if(b < FEPS) {
++			return 0;
++		} else
++			k2 = FBIGVAL;
++	} else
++		k2 = b / a;
++
++	/* if the curve is not a zigzag */
++	if ((k1+0.0001 >= k && k2 <= k+0.0001) || (k1 <= k+0.0001 && k2+0.0001 >= k))
++		return 0;
++	else
++		return 1;
++}
++
++/* split the zigzag-like curves into two parts */
++
++void
++fsplitzigzags(
++	     GLYPH * g
++)
++{
++	GENTRY         *ge, *nge;
++	double          a, b, c, d;
++
++	assertisfloat(g, "splitting zigzags");
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if (ge->type != GE_CURVE)
++			continue;
++
++		/* if the curve is not a zigzag */
++		if ( !fiszigzag(ge) ) {
++			continue;
++		}
++
++		if(ISDBG(FCONCISE)) {
++			double maxsc1, maxsc2; 
++			fprintf(stderr, "split a zigzag ");
++			fnormalizege(ge);
++			if( fcrossraysge(ge, ge, &maxsc1, &maxsc2, NULL) ) {
++				fprintf(stderr, "sc1=%g sc2=%g\n", maxsc1, maxsc2);
++			} else {
++				fprintf(stderr, "(rays don't cross)\n");
++			}
++		}
++		/* split the curve by t=0.5 */
++		nge = newgentry(GEF_FLOAT);
++		(*nge) = (*ge);
++		nge->type = GE_CURVE;
++
++		a = ge->prev->fx3;
++		b = ge->fx1;
++		c = ge->fx2;
++		d = ge->fx3;
++		nge->fx3 = d;
++		nge->fx2 = (c + d) / 2.;
++		nge->fx1 = (b + 2. * c + d) / 4.;
++		ge->fx3 = (a + b * 3. + c * 3. + d) / 8.;
++		ge->fx2 = (a + 2. * b + c) / 4.;
++		ge->fx1 = (a + b) / 2.;
++
++		a = ge->prev->fy3;
++		b = ge->fy1;
++		c = ge->fy2;
++		d = ge->fy3;
++		nge->fy3 = d;
++		nge->fy2 = (c + d) / 2.;
++		nge->fy1 = (b + 2. * c + d) / 4.;
++		ge->fy3 = (a + b * 3. + c * 3. + d) / 8.;
++		ge->fy2 = (a + 2. * b + c) / 4.;
++		ge->fy1 = (a + b) / 2.;
++
++		addgeafter(ge, nge);
++
++		if(ISDBG(FCONCISE)) {
++			dumppaths(g, ge, nge);
++		}
++	}
++}
++
++/* free this GENTRY, returns what was ge->next
++ * (ge must be of type GE_LINE or GE_CURVE)
++ * works on both float and int entries
++ */
++
++static GENTRY *
++freethisge(
++	GENTRY *ge
++)
++{
++	GENTRY *xge;
++
++	if (ge->bkwd != ge->prev) {
++		/* at beginning of the contour */
++
++		xge = ge->bkwd;
++		if(xge == ge) { /* was the only line in contour */
++			/* remove the contour completely */
++			/* prev is GE_MOVE, next is GE_PATH, remove them all */
++
++			/* may be the first contour, then ->bkwd points to ge->entries */
++			if(ge->prev->prev == 0)
++				*(GENTRY **)(ge->prev->bkwd) = ge->next->next;
++			else
++				ge->prev->prev->next = ge->next->next;
++
++			if(ge->next->next) {
++				ge->next->next->prev = ge->prev->prev;
++				ge->next->next->bkwd = ge->prev->bkwd;
++			}
++
++			xge = ge->next->next;
++			free(ge->prev); free(ge->next); free(ge);
++			return xge;
++		}
++
++		/* move the start point of the contour */
++		if(ge->flags & GEF_FLOAT) {
++			ge->prev->fx3 = xge->fx3;
++			ge->prev->fy3 = xge->fy3;
++		} else {
++			ge->prev->ix3 = xge->ix3;
++			ge->prev->iy3 = xge->iy3;
++		}
++	} else if(ge->frwd != ge->next) {
++		/* at end of the contour */
++
++		xge = ge->frwd->prev;
++		/* move the start point of the contour */
++		if(ge->flags & GEF_FLOAT) {
++			xge->fx3 = ge->bkwd->fx3;
++			xge->fy3 = ge->bkwd->fy3;
++		} else {
++			xge->ix3 = ge->bkwd->ix3;
++			xge->iy3 = ge->bkwd->iy3;
++		}
++	}
++
++	ge->prev->next = ge->next;
++	ge->next->prev = ge->prev;
++	ge->bkwd->frwd = ge->frwd;
++	ge->frwd->bkwd = ge->bkwd;
++
++	xge = ge->next;
++	free(ge);
++	return xge;
++}
++
++/* inserts a new gentry (LINE or CURVE) after another (MOVE
++ * or LINE or CURVE)
++ * corrects the first GE_MOVE if neccessary
++ */
++
++static void
++addgeafter(
++	GENTRY *oge, /* after this */
++	GENTRY *nge /* insert this */
++)
++{
++	if(oge->type == GE_MOVE) {
++		/* insert before next */
++		if(oge->next->type == GE_PATH) {
++			/* first and only GENTRY in path */
++			nge->frwd = nge->bkwd = nge;
++		} else {
++			nge->frwd = oge->next;
++			nge->bkwd = oge->next->bkwd;
++			oge->next->bkwd->frwd = nge;
++			oge->next->bkwd = nge;
++		}
++	} else {
++		nge->frwd = oge->frwd;
++		nge->bkwd = oge;
++		oge->frwd->bkwd = nge;
++		oge->frwd = nge;
++	}
++
++	nge->next = oge->next;
++	nge->prev = oge;
++	oge->next->prev = nge;
++	oge->next = nge;
++
++	if(nge->frwd->prev->type == GE_MOVE) {
++		/* fix up the GE_MOVE entry */
++		if(nge->flags & GEF_FLOAT) {
++			nge->frwd->prev->fx3 = nge->fx3;
++			nge->frwd->prev->fy3 = nge->fy3;
++		} else {
++			nge->frwd->prev->ix3 = nge->ix3;
++			nge->frwd->prev->iy3 = nge->iy3;
++		}
++	}
++}
++
++/*
++ * Check if this GENTRY happens to be at the end of path
++ * and fix the first MOVETO accordingly
++ * handles both int and float
++ */
++
++static void
++fixendpath(
++	GENTRY *ge
++)
++{
++	GENTRY *mge;
++
++	mge = ge->frwd->prev;
++	if(mge->type == GE_MOVE) {
++		if(ge->flags & GEF_FLOAT) {
++			mge->fx3 = ge->fx3;
++			mge->fy3 = ge->fy3;
++		} else {
++			mge->ix3 = ge->ix3;
++			mge->iy3 = ge->iy3;
++		}
++	}
++}
++
++/*
++ * This function adjusts the rest of path (the part from...to is NOT changed)
++ * to cover the specified gap by the specified axis (0 - X, 1 - Y).
++ * Gap is counted in direction (end_of_to - beginning_of_from).
++ * Returns by how much the gap was not closed (0.0 if it was fully closed).
++ * Ret contains by how much the first and last points of [from...to]
++ * were moved to bring them in consistence to the rest of the path.
++ * If ret==NULL then this info is not returned.
++ */
++
++static double
++fclosegap(
++	GENTRY *from,
++	GENTRY *to,
++	int axis,
++	double gap,
++	double *ret
++)
++{
++#define TIMESLARGER 10.	/* how many times larger must be a curve to not change too much */
++	double rm[2];
++	double oldpos[2];
++	double times, limit, df, dx;
++	int j, k;
++	GENTRY *xge, *pge, *nge, *bge[2];
++
++	/* remember the old points to calculate ret */
++	oldpos[0] = from->prev->fpoints[axis][2];
++	oldpos[1] = to->fpoints[axis][2];
++
++	rm[0] = rm[1] = gap / 2. ;
++
++	bge[0] = from; /* this is convenient for iterations */
++	bge[1] = to;
++
++	/* first try to modify large curves but if have none then settle for small */
++	for(times = (TIMESLARGER-1); times > 0.1; times /= 2. ) {
++
++		if(rm[0]+rm[1] == 0.)
++			break;
++
++		/* iterate in both directions, backwards then forwards */
++		for(j = 0; j<2; j++) {
++
++			if(rm[j] == 0.) /* if this direction is exhausted */
++				continue;
++
++			limit = fabs(rm[j]) * (1.+times);
++
++			for(xge = bge[j]->cntr[j]; xge != bge[!j]; xge = xge->cntr[j]) {
++				dx = xge->fpoints[axis][2] - xge->prev->fpoints[axis][2];
++				df = fabs(dx) - limit;
++				if( df <= FEPS ) /* curve is too small to change */
++					continue;
++
++				if( df >= fabs(rm[j]) )
++					df = rm[j];
++				else 
++					df *= fsign(rm[j]); /* we may cover this part of rm */
++
++				rm[j] -= df;
++				limit = fabs(rm[j]) * (1.+times);
++
++				if(xge->type == GE_CURVE) { /* correct internal points */
++					double scale = ((dx+df) / dx) - 1.;
++					double base;
++
++					if(j)
++						base = xge->fpoints[axis][2];
++					else
++						base = xge->prev->fpoints[axis][2];
++
++					for(k = 0; k<2; k++)
++						xge->fpoints[axis][k] += scale * 
++							(xge->fpoints[axis][k] - base);
++				}
++
++				/* move all the intermediate lines */
++				if(j) {
++					df = -df; /* absolute direction */
++					pge = bge[1]->bkwd;
++					nge = xge->bkwd;
++				} else {
++					xge->fpoints[axis][2] += df;
++					pge = bge[0];
++					nge = xge->frwd;
++				}
++				while(nge != pge) {
++					if(nge->type == GE_CURVE) {
++						nge->fpoints[axis][0] +=df;
++						nge->fpoints[axis][1] +=df;
++					}
++					nge->fpoints[axis][2] += df;
++					if(nge->next != nge->frwd) { /* last entry of contour */
++						nge->frwd->prev->fpoints[axis][2] += df;
++					}
++					nge = nge->cntr[!j];
++				}
++
++				if(rm[j] == 0.)
++					break;
++			}
++		}
++	}
++
++	/* find the difference */
++	oldpos[0] -= from->prev->fpoints[axis][2];
++	oldpos[1] -= to->fpoints[axis][2];
++
++	if(ret) {
++		ret[0] = oldpos[0] - from->prev->fpoints[axis][2];
++		ret[1] = oldpos[1] - to->fpoints[axis][2];
++	}
++
++#if 0
++	if( rm[0]+rm[1] != gap - oldpos[1] + oldpos[0]) {
++		fprintf(stderr, "** gap=%g rm[0]=%g rm[1]=%g o[0]=%g o[1]=%g rg=%g og=%g\n",
++			gap, rm[0], rm[1], oldpos[0], oldpos[1], rm[0]+rm[1], 
++			gap - oldpos[1] + oldpos[0]);
++	}
++#endif
++
++	return rm[0]+rm[1];
++#undef TIMESLARGER
++}
++
++/* remove the lines or curves smaller or equal to the size limit */
++
++static void
++fdelsmall(
++	GLYPH *g,
++	double minlen
++)
++{
++	GENTRY  *ge, *nge, *pge, *xge, *next;
++	int i, k;
++	double dx, dy, d2, d2m;
++	double minlen2;
++#define TIMESLARGER 10.	/* how much larger must be a curve to not change too much */
++
++	minlen2 = minlen*minlen;
++
++	for (ge = g->entries; ge != 0; ge = next) {
++		next = ge->next;
++
++		if (ge->type != GE_CURVE && ge->type != GE_LINE)
++			continue;
++
++		d2m = 0;
++		for(i= (ge->type==GE_CURVE? 0: 2); i<3; i++) {
++			dx = ge->fxn[i] - ge->prev->fx3;
++			dy = ge->fyn[i] - ge->prev->fy3;
++			d2 = dx*dx + dy*dy;
++			if(d2m < d2)
++				d2m = d2;
++		}
++
++		if( d2m > minlen2 ) { /* line is not too small */
++			/* XXX add more normalization here */
++			continue;
++		}
++
++		/* if the line is too small */
++
++		/* check forwards if we have a whole sequence of them */
++		nge = ge;
++		for(xge = ge->frwd; xge != ge; xge = xge->frwd) {
++			d2m = 0;
++			for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) {
++				dx = xge->fxn[i] - xge->prev->fx3;
++				dy = xge->fyn[i] - xge->prev->fy3;
++				d2 = dx*dx + dy*dy;
++				if(d2m < d2)
++					d2m = d2;
++			}
++			if( d2m > minlen2 ) /* line is not too small */
++				break;
++			nge = xge;
++			if(next == nge) /* move the next step past this sequence */
++				next = next->next;
++		}
++
++		/* check backwards if we have a whole sequence of them */
++		pge = ge;
++		for(xge = ge->bkwd; xge != ge; xge = xge->bkwd) {
++			d2m = 0;
++			for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) {
++				dx = xge->fxn[i] - xge->prev->fx3;
++				dy = xge->fyn[i] - xge->prev->fy3;
++				d2 = dx*dx + dy*dy;
++				if(d2m < d2)
++					d2m = d2;
++			}
++			if( d2m > minlen2 ) /* line is not too small */
++				break;
++			pge = xge;
++		}
++
++		/* now we have a sequence of small fragments in pge...nge (inclusive) */
++
++		if(ISDBG(FCONCISE))  {
++			fprintf(stderr, "glyph %s has very small fragments(%x..%x..%x)\n", 
++			g->name, pge, ge, nge);
++			dumppaths(g, pge, nge);
++		}
++
++		/* reduce whole sequence to one part and remember the middle point */
++		if(pge != nge) {
++			while(1) {
++				xge = pge->frwd;
++				if(xge == nge) {
++					pge->fx1 = pge->fx2 = pge->fx3;
++					pge->fx3 = nge->fx3;
++					pge->fy1 = pge->fy2 = pge->fy3;
++					pge->fy3 = nge->fy3;
++					pge->type = GE_CURVE;
++					freethisge(nge);
++					break;
++				}
++				if(xge == nge->bkwd) {
++					pge->fx1 = pge->fx2 = (pge->fx3+xge->fx3)/2.;
++					pge->fx3 = nge->fx3;
++					pge->fy1 = pge->fy2 = (pge->fy3+xge->fy3)/2.;
++					pge->fy3 = nge->fy3;
++					pge->type = GE_CURVE;
++					freethisge(nge);
++					freethisge(xge);
++					break;
++				}
++				freethisge(pge); pge = xge;
++				xge = nge->bkwd; freethisge(nge); nge = xge;
++			}
++		}
++		ge = pge;
++
++		/* check if the whole sequence is small */
++		dx = ge->fx3 - ge->prev->fx3;
++		dy = ge->fy3 - ge->prev->fy3;
++		d2 = dx*dx + dy*dy;
++
++		if( d2 > minlen2 ) { /* no, it is not */
++			double b, d;
++
++			WARNING_3 fprintf(stderr, "glyph %s had a sequence of fragments < %g points each, reduced to one curve\n",
++				g->name, minlen);
++
++			/* check that we did not create a monstrosity spanning quadrants */
++			if(fsign(ge->fx1 - ge->prev->fx1) * fsign(ge->fx3 - ge->fx1) < 0
++			|| fsign(ge->fy1 - ge->prev->fy1) * fsign(ge->fy3 - ge->fy1) < 0 ) { 
++				/* yes, we did; are both parts of this thing big enough ? */
++				dx = ge->fx1 - ge->prev->fx3;
++				dy = ge->fy1 - ge->prev->fy3;
++				d2 = dx*dx + dy*dy;
++
++				dx = ge->fx3 - ge->fx1;
++				dy = ge->fy3 - ge->fy1;
++				d2m = dx*dx + dy*dy;
++
++				if(d2 > minlen2 && d2m > minlen2) { /* make two straights */
++					nge = newgentry(GEF_FLOAT);
++					*nge = *ge;
++					
++					for(i=0; i<2; i++) {
++						ge->fpoints[i][2] = ge->fpoints[i][0];
++						b = nge->fpoints[i][0];
++						d = nge->fpoints[i][2] - b;
++						nge->fpoints[i][0] = b + 0.1*d;
++						nge->fpoints[i][1] = b + 0.9*d;
++					}
++				}
++				for(i=0; i<2; i++) { /* make one straight or first of two straights */
++					b = ge->prev->fpoints[i][2];
++					d = ge->fpoints[i][2] - b;
++					ge->fpoints[i][0] = b + 0.1*d;
++					ge->fpoints[i][1] = b + 0.9*d;
++				}
++			}
++			continue; 
++		}
++
++		if(ge->frwd == ge) { /* points to itself, just remove the path completely */
++			WARNING_3 fprintf(stderr, "glyph %s had a path made of fragments < %g points each, removed\n",
++				g->name, minlen);
++
++			next = freethisge(ge);
++			continue;
++		} 
++
++		/* now close the gap by x and y */
++		for(i=0; i<2; i++) {
++			double gap;
++
++			gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
++			if( fclosegap(ge, ge, i, gap, NULL) != 0.0 ) {
++				double scale, base;
++
++				/* not good, as the last resort just scale the next line */
++				gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
++
++				if(ISDBG(FCONCISE)) 
++					fprintf(stderr, "    last resort on %c: closing next by %g\n",
++					(i==0 ? 'x' : 'y'), gap);
++
++				nge = ge->frwd;
++				base = nge->fpoints[i][2];
++				dx = ge->fpoints[i][2] - base;
++				if(fabs(dx) < FEPS)
++					continue;
++
++				scale = ((dx-gap) / dx);
++
++				if(nge->type == GE_CURVE)
++					for(k = 0; k<2; k++)
++						nge->fpoints[i][k] = base + 
++							scale * (nge->fpoints[i][k] - base);
++
++				ge->fpoints[i][2] -= gap;
++			}
++		}
++
++		/* OK, the gap is closed - remove this useless GENTRY */
++		freethisge(ge);
++	}
++#undef TIMESLARGER
++}
++
++/* find the point where two rays continuing vectors cross
++ * returns 1 if they cross, 0 if they don't
++ * If they cross optionally (if the pointers are not NULL) returns 
++ * the maximal scales for both vectors and also optionally the point 
++ * where the rays cross (twice).
++ * Expects that the curves are normalized.
++ *
++ * For convenience there are 2 front-end functions taking
++ * arguments in different formats
++ */
++
++struct ray {
++	double x1, y1, x2, y2;
++	int isvert;
++	double k, b; /* lines are represented as y = k*x + b */
++	double *maxp;
++};
++static struct ray ray[3];
++
++/* the back-end doing the actual work
++ * the rays are defined in the static array ray[]
++ */
++
++static int
++fcrossraysxx(
++	double crossdot[2][2]
++)
++{
++	double x, y, max;
++	int i;
++
++	for(i=0; i<2; i++) {
++		if(ray[i].x1 == ray[i].x2) 
++			ray[i].isvert = 1;
++		else {
++			ray[i].isvert = 0;
++			ray[i].k = (ray[i].y2 - ray[i].y1) / (ray[i].x2 - ray[i].x1);
++			ray[i].b = ray[i].y2 - ray[i].k * ray[i].x2;
++		}
++	}
++
++	if(ray[0].isvert && ray[1].isvert) {
++		if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: both vertical\n");
++		return 0; /* both vertical, don't cross */
++	}
++
++	if(ray[1].isvert) {
++		ray[2] = ray[0]; /* exchange them */
++		ray[0] = ray[1];
++		ray[1] = ray[2];
++	}
++
++	if(ray[0].isvert) {
++		x = ray[0].x1;
++	} else {
++		if( fabs(ray[0].k - ray[1].k) < FEPS) {
++			if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: parallel lines, k = %g, %g\n",
++				ray[0].k, ray[1].k);
++			return 0; /* parallel lines */
++		}
++		x = (ray[1].b - ray[0].b) / (ray[0].k - ray[1].k) ;
++	}
++	y = ray[1].k * x + ray[1].b;
++
++	for(i=0; i<2; i++) {
++		if(ray[i].isvert)
++			max = (y - ray[i].y1) / (ray[i].y2 - ray[i].y1);
++		else
++			max = (x - ray[i].x1) / (ray[i].x2 - ray[i].x1);
++		/* check if wrong sides of rays cross */
++		if( max < 0 ) {
++			if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: %c scale=%g @(%g,%g) (%g,%g)<-(%g,%g)\n",
++				(i?'Y':'X'), max, x, y, ray[i].x2, ray[i].y2, ray[i].x1, ray[i].y1);
++			return 0;
++		}
++		if(ray[i].maxp)
++			*ray[i].maxp = max;
++	}
++	if(crossdot != 0) {
++		crossdot[0][0] = crossdot[1][0] = x;
++		crossdot[0][1] = crossdot[1][1] = y;
++	}
++	return 1;
++}
++
++/* the front-end getting the arguments from 4 dots defining
++ * a curve in the same format as for fapproxcurve():
++ * rays are defined as beginning and end of the curve,
++ * the crossdot is inserted as the two middle dots of the curve
++ */
++
++int
++fcrossrayscv(
++	double curve[4][2 /*X,Y*/],
++	double *max1,
++	double *max2
++)
++{
++	ray[0].x1 = curve[0][X];
++	ray[0].y1 = curve[0][Y];
++	ray[0].x2 = curve[1][X];
++	ray[0].y2 = curve[1][Y];
++	ray[0].maxp = max1;
++
++	ray[1].x1 = curve[2][X];
++	ray[1].y1 = curve[2][Y];
++	ray[1].x2 = curve[3][X];
++	ray[1].y2 = curve[3][Y];
++	ray[1].maxp = max2;
++
++	return fcrossraysxx(&curve[1]);
++}
++
++/* the front-end getting the arguments from gentries:
++ * rays are defined as beginning of curve1 and end of curve 2
++ */
++
++int
++fcrossraysge(
++	GENTRY *ge1,
++	GENTRY *ge2,
++	double *max1,
++	double *max2,
++	double crossdot[2][2]
++)
++{
++	ray[0].x1 = ge1->prev->fx3;
++	ray[0].y1 = ge1->prev->fy3;
++	ray[0].x2 = ge1->fpoints[X][ge1->ftg];
++	ray[0].y2 = ge1->fpoints[Y][ge1->ftg];
++	ray[0].maxp = max1;
++
++	ray[1].x1 = ge2->fx3;
++	ray[1].y1 = ge2->fy3;
++	if(ge2->rtg < 0) {
++		ray[1].x2 = ge2->prev->fx3;
++		ray[1].y2 = ge2->prev->fy3;
++	} else {
++		ray[1].x2 = ge2->fpoints[X][ge2->rtg];
++		ray[1].y2 = ge2->fpoints[Y][ge2->rtg];
++	}
++	ray[1].maxp = max2;
++
++	return fcrossraysxx(crossdot);
++}
++
++/* debugging printout functions */
++
++#if defined(DEBUG_DOTSEG) || defined(DEBUG_DOTCURVE) || defined(DEBUG_APPROXCV)
++
++/* for debugging */
++static
++printdot(
++	double dot[2]
++)
++{
++	fprintf(stderr, "(%g,%g)", dot[0], dot[1]);
++}
++
++static
++printseg(
++	double seg[2][2]
++)
++{
++	putc('[', stderr);
++	printdot(seg[0]);
++	putc(' ', stderr);
++	printdot(seg[1]);
++	putc(']', stderr);
++}
++
++#endif /* DEBUG_* */
++
++/*
++ * Find squared distance from a dot to a line segment
++ */
++
++double
++fdotsegdist2(
++	double seg[2][2 /*X,Y*/],
++	double dot[2 /*X,Y*/]
++)
++{
++#define x1	seg[0][X]
++#define y1	seg[0][Y]
++#define x2	seg[1][X]
++#define y2	seg[1][Y]
++#define xdot	dot[X]
++#define ydot	dot[Y]
++
++	double dx, dy; /* segment dimensions */
++	double kline, bline; /* segment line formula is y=k*x+b */
++	double kperp, bperp; /* perpendicular from the dot to the line */
++	double xcross, ycross; /* where the perpendicular crosses the segment */
++
++/* handle the situation where the nearest point of the segment is its end */
++#define HANDLE_LIMITS(less12, lesscr1, lesscr2)	\
++	if( less12 ) { \
++		if( lesscr1 ) { \
++			xcross = x1; \
++			ycross = y1; \
++		} else if( !(lesscr2) ) { \
++			xcross = x2; \
++			ycross = y2; \
++		} \
++	} else { \
++		if( !(lesscr1) ) { \
++			xcross = x1; \
++			ycross = y1; \
++		} else if( lesscr2 ) { \
++			xcross = x2; \
++			ycross = y2; \
++		} \
++	} \
++	/* end of macro */
++
++
++	dx = x2 - x1;
++	dy = y2 - y1;
++
++	if(fabs(dx) < FEPS) {
++		/* special case - vertical line */
++#ifdef DEBUG_DOTSEG
++		printf("vertical line!\n");
++#endif
++		xcross = x1;
++		ycross = ydot;
++		HANDLE_LIMITS( y1 < y2, ycross < y1, ycross < y2);
++	} else if(fabs(dy) < FEPS) {
++		/* special case - horizontal line */
++#ifdef DEBUG_DOTSEG
++		printf("horizontal line!\n");
++#endif
++		xcross = xdot;
++		ycross = y1;
++		HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2)
++	} else {
++		kline = dy/dx;
++		bline = y1 - x1*kline;
++		kperp = -1./kline;
++		bperp = ydot - xdot*kperp;
++
++		xcross = (bline-bperp) / (kperp-kline);
++		ycross = kline*xcross + bline;
++
++		HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2)
++	}
++#ifdef DEBUG_DOTSEG
++	printf("crossover at (%g,%g)\n", xcross, ycross);
++#endif
++
++	dx = xdot-xcross;
++	dy = ydot-ycross;
++	return dx*dx+dy*dy;
++#undef x1
++#undef y1
++#undef x2
++#undef y2
++#undef xdot
++#undef ydot
++#undef HANDLE_LIMITS
++}
++
++/* find the weighted quadratic average for the distance of a set
++ * of dots from the curve; also fills out the individual distances
++ * for each dot; if maxp!=NULL then returns the maximal squared
++ * distance in there
++ */
++
++double
++fdotcurvdist2(
++	double curve[4][2 /*X,Y*/ ],
++	struct dot_dist *dots,
++	int ndots, /* number of entries in dots */
++	double *maxp
++)
++{
++	/* a curve is approximated by this many straight segments */
++#define NAPSECT	16
++	/* a curve is divided into this many sections with equal weight each */
++#define NWSECT	4
++	/* table of coefficients for finding the dots on the curve */
++	/* tt[0] is left unused */
++	static double tt[NAPSECT][4];
++	static int havett = 0; /* flag: tt is initialized */
++	/* dots on the curve */
++	double cvd[NAPSECT+1][2 /*X,Y*/];
++	/* sums by sections */
++	double sum[NWSECT];
++	/* counts by sections */
++	double count[NWSECT];
++	int d, i, j;
++	int id1, id2;
++	double dist1, dist2, dist3, dx, dy, x, y;
++	double max = 0.;
++
++	if(!havett) {
++		double t, nt, t2, nt2, step;
++
++		havett++;
++		step = 1. / NAPSECT;
++		t = 0;
++		for(i=1; i<NAPSECT; i++) {
++			t += step;
++			nt = 1 - t;
++			t2 = t*t;
++			nt2 = nt*nt;
++			tt[i][0] = nt2*nt; /* (1-t)^3 */
++			tt[i][1] = 3*nt2*t; /* 3*(1-t)^2*t */
++			tt[i][2] = 3*nt*t2; /* 3*(1-t)*t^2 */
++			tt[i][3] = t2*t; /* t^3 */
++		}
++	}
++
++	for(i=0; i<NWSECT; i++) {
++		sum[i] = 0.;
++		count[i] = 0;
++	}
++
++	/* split the curve into segments */
++	for(d=0; d<2; d++) { /* X and Y */
++		cvd[0][d] = curve[0][d]; /* endpoints */
++		cvd[NAPSECT][d] = curve[3][d];
++		for(i=1; i<NAPSECT; i++) {
++			cvd[i][d] = curve[0][d] * tt[i][0]
++				+ curve[1][d] * tt[i][1]
++				+ curve[2][d] * tt[i][2]
++				+ curve[3][d] * tt[i][3];
++		}
++	}
++
++	for(d=0; d<ndots; d++) {
++#ifdef DEBUG_DOTCURVE
++		printf("dot %d ", d); printdot(dots[d].p); printf(":\n");
++
++		/* for debugging */
++		for(i=0; i< NAPSECT; i++) {
++			dist1 = fdotsegdist2(&cvd[i], dots[d].p);
++			printf("  seg %d ",i); printseg(&cvd[i]); printf(" dist=%g\n", sqrt(dist1));
++		}
++#endif
++
++		x = dots[d].p[X];
++		y = dots[d].p[Y];
++
++		/* find the nearest dot on the curve
++		 * there may be up to 2 local minimums - so we start from the
++		 * ends of curve and go to the center
++		 */
++
++		id1 = 0;
++		dx = x - cvd[0][X];
++		dy = y - cvd[0][Y];
++		dist1 = dx*dx + dy*dy;
++#ifdef DEBUG_DOTCURVE
++		printf("  dot 0 "); printdot(cvd[id1]); printf(" dist=%g\n", sqrt(dist1));
++#endif
++		for(i = 1; i<=NAPSECT; i++) {
++			dx = x - cvd[i][X];
++			dy = y - cvd[i][Y];
++			dist3 = dx*dx + dy*dy;
++#ifdef DEBUG_DOTCURVE
++			printf("  dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3));
++#endif
++			if(dist3 < dist1) {
++				dist1 = dist3;
++				id1 = i;
++			} else
++				break;
++		}
++
++		if(id1 < NAPSECT-1) {
++			id2 = NAPSECT;
++			dx = x - cvd[NAPSECT][X];
++			dy = y - cvd[NAPSECT][Y];
++			dist2 = dx*dx + dy*dy;
++#ifdef DEBUG_DOTCURVE
++			printf("  +dot %d ", id2); printdot(cvd[id2]); printf(" dist=%g\n", sqrt(dist2));
++#endif
++			for(i = NAPSECT-1; i>id1+1; i--) {
++				dx = x - cvd[i][X];
++				dy = y - cvd[i][Y];
++				dist3 = dx*dx + dy*dy;
++#ifdef DEBUG_DOTCURVE
++				printf("  dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3));
++#endif
++				if(dist3 < dist2) {
++					dist2 = dist3;
++					id2 = i;
++				} else
++					break;
++			}
++
++			/* now find which of the local minimums is smaller */
++			if(dist2 < dist1) {
++				id1 = id2;
++			}
++		}
++
++		/* the nearest segment must include the nearest dot */
++		if(id1==0) {
++			dots[d].seg = 0;
++			dots[d].dist2 = fdotsegdist2(&cvd[0], dots[d].p);
++		} else if(id1==NAPSECT) {
++			dots[d].seg = NAPSECT-1;
++			dots[d].dist2 = fdotsegdist2(&cvd[NAPSECT-1], dots[d].p);
++		} else {
++			dist1 = fdotsegdist2(&cvd[id1], dots[d].p);
++			dist2 = fdotsegdist2(&cvd[id1-1], dots[d].p);
++			if(dist2 < dist1) {
++				dots[d].seg = id1-1;
++				dots[d].dist2 = dist2;
++			} else {
++				dots[d].seg = id1;
++				dots[d].dist2 = dist1;
++			}
++		}
++
++		i = dots[d].seg % NWSECT;
++		sum[i] += dots[d].dist2;
++		if(dots[d].dist2 > max)
++			max = dots[d].dist2;
++		count[i]++;
++#ifdef DEBUG_DOTCURVE
++		printf(" best seg %d sect %d dist=%g\n", dots[d].seg, i, sqrt(dots[d].dist2));
++#endif
++	}
++
++	/* calculate the weighted average */
++	id1=0;
++	dist1=0.;
++	for(i=0; i<NWSECT; i++) {
++		if(count[i]==0)
++			continue;
++		id1++;
++		dist1 += sum[i]/count[i];
++	}
++	if(maxp)
++		*maxp = max;
++	if(id1==0) /* no dots, strange */
++		return 0.;
++	else 
++		return dist1/id1; /* to get the average distance apply sqrt() */
++}
++	
++/*
++ * Approximate a curve matching the giving set of points and with
++ * middle reference points going along the given segments (and no farther
++ * than these segments).
++ */
++
++void
++fapproxcurve(
++	double cv[4][2 /*X,Y*/ ], /* points 0-3 are passed in, points 1,2 - out */
++	struct dot_dist *dots, /* the dots to approximate - distances returned 
++		* there may be invalid */
++	int ndots
++)
++{
++	/* b and c are the middle control points */
++#define	B	0
++#define	C	1
++	/* maximal number of sections on each axis - used for the first step */
++#define MAXSECT	2
++	/* number of sections used for the other steps */
++#define NORMSECT 2
++	/* when the steps become less than this many points, it's time to stop */
++#define STEPEPS	1.
++	double from[2 /*B,C*/], to[2 /*B,C*/];
++	double middf[2 /*B,C*/][2 /*X,Y*/], df;
++	double coef[2 /*B,C*/][MAXSECT]; 
++	double res[MAXSECT][MAXSECT], thisres, bestres, goodres;
++	int ncoef[2 /*B,C*/], best[2 /*B,C*/], good[2 /*B,C*/];
++	int i, j, k, keepsym;
++	char bc[]="BC";
++	char xy[]="XY";
++
++#ifdef DEBUG_APPROXCV
++	fprintf(stderr, "Curve points:");
++	for(i=0; i<4; i++) {
++		fprintf(stderr, " ");
++		printdot(cv[i]); 
++	}
++	fprintf(stderr, "\nDots:");
++	for(i=0; i<ndots; i++) {
++		fprintf(stderr, " ");
++		printdot(dots[i].p); 
++	}
++	fprintf(stderr, "\n");
++#endif
++
++	/* load the endpoints and calculate differences */
++	for(i=0; i<2; i++) {
++		/* i is X, Y */
++		middf[B][i] = cv[1][i]-cv[0][i];
++		middf[C][i] = cv[2][i]-cv[3][i];
++
++		/* i is B, C */
++		from[i] = 0.;
++		to[i] = 1.;
++		ncoef[i] = MAXSECT;
++	}
++
++	while(ncoef[B] != 1 || ncoef[C] != 1) {
++		/* prepare the values of coefficients */
++		for(i=0; i<2; i++) { /*B,C*/
++#ifdef DEBUG_APPROXCV
++			fprintf(stderr, "Coefficients by %c(%g,%g):", bc[i], from[i], to[i]);
++#endif
++			df = (to[i]-from[i]) / (ncoef[i]*2);
++			for(j=0; j<ncoef[i]; j++) {
++				coef[i][j] = from[i] + df*(2*j+1);
++#ifdef DEBUG_APPROXCV
++				fprintf(stderr, " %g", coef[i][j]);
++#endif
++			}
++#ifdef DEBUG_APPROXCV
++			fprintf(stderr, "\n");
++#endif
++		}
++		bestres = FBIGVAL;
++		/* i iterates by ncoef[B], j iterates by ncoef[C] */
++		for(i=0; i<ncoef[B]; i++) {
++			for(j=0; j<ncoef[C]; j++) {
++				for(k=0; k<2; k++) { /*X, Y*/
++					cv[1][k] = cv[0][k] + middf[B][k]*coef[B][i];
++					cv[2][k] = cv[3][k] + middf[C][k]*coef[C][j];
++				}
++				res[i][j] = thisres = fdotcurvdist2(cv, dots, ndots, NULL);
++				if(thisres < bestres) {
++					goodres = bestres;
++					good[B] = best[B];
++					good[C] = best[C];
++					bestres = thisres;
++					best[B] = i;
++					best[C] = j;
++				} else if(thisres < goodres) {
++					goodres = thisres;
++					good[B] = i;
++					good[C] = j;
++				}
++#ifdef DEBUG_APPROXCV
++				fprintf(stderr, " at (%g,%g) dist=%g %s\n", coef[B][i], coef[C][j], sqrt(thisres),
++					(best[B]==i && best[C]==j)? "(BEST)":"");
++#endif
++			}
++		}
++#ifdef DEBUG_APPROXCV
++		fprintf(stderr, " best: at (%g, %g) dist=%g\n",
++			coef[B][best[B]], coef[C][best[C]], sqrt(bestres));
++		fprintf(stderr, " B:%d,%d C:%d,%d -- 2nd best: at (%g, %g) dist=%g\n",
++			best[B], good[B], best[C], good[C], coef[B][good[B]], coef[C][good[C]], sqrt(goodres));
++#endif
++
++		if(bestres < (0.1*0.1)) { /* consider it close enough */
++			/* calculate the coordinates to return */
++			for(k=0; k<2; k++) { /*X, Y*/
++				cv[1][k] = cv[0][k] + middf[B][k]*coef[B][best[B]];
++				cv[2][k] = cv[3][k] + middf[C][k]*coef[C][best[C]];
++			}
++#ifdef DEBUG_APPROXCV
++			fprintf(stderr, "quick approximated middle points "); printdot(cv[1]); 
++			fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n");
++#endif
++			return;
++		}
++		keepsym = 0;
++		if(best[B] != best[C] && best[B]-best[C] == good[C]-good[B]) {
++			keepsym = 1;
++#ifdef DEBUG_APPROXCV
++			fprintf(stderr, "keeping symmetry!\n");
++#endif
++		}
++		for(i=0; i<2; i++) { /*B,C*/
++			if(ncoef[i]==1)
++				continue;
++			if(keepsym) {
++				/* try to keep the symmetry */
++				if(best[i] < good[i]) {
++					from[i] = coef[i][best[i]];
++					to[i] = coef[i][good[i]];
++				} else {
++					from[i] = coef[i][good[i]];
++					to[i] = coef[i][best[i]];
++				}
++			} else {
++				df = (to[i]-from[i]) / ncoef[i];
++				from[i] += df*best[i];
++				to[i] = from[i] + df;
++			}
++			if( fabs(df*middf[i][0]) < STEPEPS && fabs(df*middf[i][1]) < STEPEPS) {
++				/* this side has converged */
++				from[i] = to[i] = (from[i]+to[i]) / 2.;
++				ncoef[i] = 1;
++			} else 
++				ncoef[i] = NORMSECT;
++		}
++
++	}
++	/* calculate the coordinates to return */
++	for(k=0; k<2; k++) { /*X, Y*/
++		cv[1][k] = cv[0][k] + middf[B][k]*from[B];
++		cv[2][k] = cv[3][k] + middf[C][k]*from[C];
++	}
++#ifdef DEBUG_APPROXCV
++	fprintf(stderr, "approximated middle points "); printdot(cv[1]); 
++	fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n");
++#endif
++#undef B
++#undef C
++#undef MAXSECT
++#undef NORMSECT
++#undef STEPEPS
++}
++
++/*
++ * Find the squared value of the sinus of the angle between the
++ * end of ge1 and the beginning of ge2
++ * The curve must be normalized.
++ */
++
++static double
++fjointsin2(
++	GENTRY *ge1,
++	GENTRY *ge2
++)
++{
++	double d[3][2 /*X,Y*/];
++	double scale1, scale2, len1, len2;
++	int axis;
++	
++	if(ge1->rtg < 0) {
++		d[1][X] = ge1->fx3 - ge1->prev->fx3;
++		d[1][Y] = ge1->fy3 - ge1->prev->fy3;
++	} else {
++		d[1][X] = ge1->fx3 - ge1->fpoints[X][ge1->rtg];
++		d[1][Y] = ge1->fy3 - ge1->fpoints[Y][ge1->rtg];
++	}
++	d[2][X] = ge2->fpoints[X][ge2->ftg] - ge2->prev->fx3;
++	d[2][Y] = ge2->fpoints[Y][ge2->ftg] - ge2->prev->fy3;
++
++	len1 = sqrt( d[1][X]*d[1][X] + d[1][Y]*d[1][Y] );
++	len2 = sqrt( d[2][X]*d[2][X] + d[2][Y]*d[2][Y] );
++	/* scale the 2nd segment to the length of 1
++	 * and to make sure that the 1st segment is longer scale it to
++	 * the length of 2 and extend to the same distance backwards
++	 */
++	scale1 = 2./len1;
++	scale2 = 1./len2;
++
++	for(axis=0; axis <2; axis++) {
++		d[0][axis] = -( d[1][axis] *= scale1 );
++		d[2][axis] *= scale2;
++	}
++	return fdotsegdist2(d, d[2]);
++}
++
++#if 0
++/* find the area covered by the curve
++ * (limited by the projections to the X axis)
++ */
++
++static double
++fcvarea(
++	GENTRY *ge
++)
++{
++	double Ly, My, Ny, Py, Qx, Rx, Sx;
++	double area;
++
++	/* y = Ly*t^3 + My*t^2 + Ny*t + Py */
++	Ly = -ge->prev->fy3 + 3*(ge->fy1 - ge->fy2) + ge->fy3;
++	My = 3*ge->prev->fy3 - 6*ge->fy1 + 3*ge->fy2;
++	Ny = 3*(-ge->prev->fy3 + ge->fy1);
++	Py = ge->prev->fy3;
++
++	/* dx/dt = Qx*t^2 + Rx*t + Sx */
++	Qx = 3*(-ge->prev->fx3 + 3*(ge->fx1 - ge->fx2) + ge->fx3);
++	Rx = 6*(ge->prev->fx3 - 2*ge->fx1 + ge->fx2);
++	Sx = 3*(-ge->prev->fx3 + ge->fx1);
++
++	/* area is integral[from 0 to 1]( y(t) * dx(t)/dt *dt) */
++	area = 1./6.*(Ly*Qx) + 1./5.*(Ly*Rx + My*Qx) 
++		+ 1./4.*(Ly*Sx + My*Rx + Ny*Qx) + 1./3.*(My*Sx + Ny*Rx + Py*Qx)
++		+ 1./2.*(Ny*Sx + Py*Rx) + Py*Sx;
++
++	return area;
++}
++#endif
++
++/* find the value of point on the curve at the given parameter t,
++ * along the given axis (0 - X, 1 - Y).
++ */
++
++static double
++fcvval(
++	GENTRY *ge,
++	int axis,
++	double t
++)
++{
++	double t2, mt, mt2;
++
++	/* val = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 */
++	t2 = t*t;
++	mt = 1-t;
++	mt2 = mt*mt;
++	
++	return ge->prev->fpoints[axis][2]*mt2*mt 
++		+ 3*(ge->fpoints[axis][0]*mt2*t + ge->fpoints[axis][1]*mt*t2)
++		+ ge->fpoints[axis][2]*t*t2;
++}
++
++/*
++ * Find ndots equally spaced dots on a curve or line and fill 
++ * their coordinates into the dots array
++ */
++
++static void
++fsampledots(
++	GENTRY *ge, 
++	double dots[][2], /* the dots to fill */
++	int ndots
++)
++{
++	int i, axis;
++	double t, nf, dx, d[2];
++
++	nf = ndots+1;
++	if(ge->type == GE_CURVE) {
++		for(i=0; i<ndots; i++) {
++			t = (i+1)/nf;
++			for(axis=0; axis<2; axis++)
++				dots[i][axis] = fcvval(ge, axis, t);
++		}
++	} else { /* line */
++		d[0] = ge->fx3 - ge->prev->fx3;
++		d[1] = ge->fy3 - ge->prev->fy3;
++		for(i=0; i<ndots; i++) {
++			t = (i+1)/nf;
++			for(axis=0; axis<2; axis++)
++				dots[i][axis] = ge->prev->fpoints[axis][2] 
++					+ t*d[axis];
++		}
++	}
++}
++
++/*
++ * Allocate a structure gex_con
++ */
++
++static void
++alloc_gex_con(
++	GENTRY *ge
++)
++{
++	ge->ext = (void*)calloc(1, sizeof(GEX_CON));
++	if(ge->ext == 0) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++}
++
++/*
++ * Normalize a gentry for fforceconcise() : find the points that
++ * can be used to calculate the tangents.
++ */
++
++static void
++fnormalizege(
++	GENTRY *ge
++)
++{
++	int midsame, frontsame, rearsame;
++
++	if(ge->type == GE_LINE) {
++		ge->ftg = 2;
++		ge->rtg = -1;
++	} else { /* assume it's a curve */
++		midsame = (fabs(ge->fx1-ge->fx2)<FEPS && fabs(ge->fy1-ge->fy2)<FEPS);
++		frontsame = (fabs(ge->fx1-ge->prev->fx3)<FEPS && fabs(ge->fy1-ge->prev->fy3)<FEPS);
++		rearsame = (fabs(ge->fx3-ge->fx2)<FEPS && fabs(ge->fy3-ge->fy2)<FEPS);
++
++		if(midsame && (frontsame || rearsame) ) {
++			/* essentially a line */
++			ge->ftg = 2;
++			ge->rtg = -1;
++		} else { 
++			if(frontsame) {
++				ge->ftg = 1;
++			} else {
++				ge->ftg = 0;
++			}
++			if(rearsame) {
++				ge->rtg = 0;
++			} else {
++				ge->rtg = 1;
++			}
++		}
++	}
++}
++
++/* various definition for the processing of outlines */
++
++/* maximal average quadratic distance from the original curve
++ * (in dots) to consider the joined curve good
++ */
++#define CVEPS	1.5
++#define CVEPS2	(CVEPS*CVEPS)
++/* squared sinus of the maximal angle that we consider a smooth joint */
++#define SMOOTHSIN2 0.25 /* 0.25==sin(30 degrees)^2 */
++/* squared line length that we consider small */
++#define SMALL_LINE2 (15.*15.)
++/* how many times a curve must be bigger than a line to join, squared */
++#define TIMES_LINE2 (3.*3.)
++
++/*
++ * Normalize and analyse a gentry for fforceconcise() and fill out the gex_con
++ * structure
++ */
++
++static void
++fanalyzege(
++	GENTRY *ge
++)
++{
++	int i, ix, iy;
++	double avsd2, dots[3][2 /*X,Y*/];
++	GEX_CON *gex;
++
++	gex = X_CON(ge);
++	memset(gex, 0, sizeof *gex);
++
++	gex->len2 = 0;
++	for(i=0; i<2; i++) {
++		avsd2 = gex->d[i] = ge->fpoints[i][2] - ge->prev->fpoints[i][2];
++		gex->len2 += avsd2*avsd2;
++	}
++	gex->sin2 = fjointsin2(ge, ge->frwd);
++	if(ge->type == GE_CURVE) {
++		ge->dir = fgetcvdir(ge);
++		for(i=0; i<2; i++) {
++			dots[0][i] = ge->prev->fpoints[i][2];
++			dots[1][i] = ge->fpoints[i][2];
++			dots[2][i] = fcvval(ge, i, 0.5);
++		}
++		avsd2 = fdotsegdist2(dots, dots[2]);
++		if(avsd2 <= CVEPS2) {
++			gex->flags |= GEXF_FLAT;
++		}
++	} else {
++		ge->dir = CVDIR_FEQUAL|CVDIR_REQUAL;
++		gex->flags |= GEXF_FLAT;
++	}
++	if(gex->flags & GEXF_FLAT) {
++		if( fabs(gex->d[X]) > FEPS && fabs(gex->d[Y]) < 5.
++		&& fabs(gex->d[Y] / gex->d[X]) < 0.2)
++			gex->flags |= GEXF_HOR;
++		else if( fabs(gex->d[Y]) > FEPS && fabs(gex->d[X]) < 5.
++		&& fabs(gex->d[X] / gex->d[Y]) < 0.2)
++			gex->flags |= GEXF_VERT;
++	}
++	ix = gex->isd[X] = fsign(gex->d[X]);
++	iy = gex->isd[Y] = fsign(gex->d[Y]);
++	if(ix <= 0) {
++		if(iy <= 0) 
++			gex->flags |= GEXF_QDL;
++		if(iy >= 0) 
++			gex->flags |= GEXF_QUL;
++		if(gex->flags & GEXF_HOR)
++			gex->flags |= GEXF_IDQ_L;
++	}
++	if(ix >= 0) {
++		if(iy <= 0) 
++			gex->flags |= GEXF_QDR;
++		if(iy >= 0) 
++			gex->flags |= GEXF_QUR;
++		if(gex->flags & GEXF_HOR)
++			gex->flags |= GEXF_IDQ_R;
++	}
++	if(gex->flags & GEXF_VERT) {
++		if(iy <= 0) {
++			gex->flags |= GEXF_IDQ_U;
++		} else { /* supposedly there is no 0-sized entry */
++			gex->flags |= GEXF_IDQ_D;
++		}
++	}
++}
++
++/*
++ * Analyse a joint between this and following gentry for fforceconcise() 
++ * and fill out the corresponding parts of the gex_con structure
++ * Bothe entries must be analyzed first.
++ */
++
++static void
++fanalyzejoint(
++	GENTRY *ge
++)
++{
++	GENTRY *nge = ge->frwd;
++	GENTRY tge;
++	GEX_CON *gex, *ngex;
++	double avsd2, dots[3][2 /*X,Y*/];
++	int i;
++
++	gex = X_CON(ge); ngex = X_CON(nge);
++
++	/* look if they can be joined honestly */
++
++	/* if any is flat, they should join smoothly */
++	if( (gex->flags & GEXF_FLAT || ngex->flags & GEXF_FLAT)
++	&& gex->sin2 > SMOOTHSIN2)
++		goto try_flatboth;
++
++	if(ge->type == GE_LINE) {
++		if(nge->type == GE_LINE) {
++			if(gex->len2 > SMALL_LINE2 || ngex->len2 > SMALL_LINE2)
++				goto try_flatboth;
++		} else {
++			if(gex->len2*TIMES_LINE2 > ngex->len2)
++				goto try_flatboth;
++		}
++	} else if(nge->type == GE_LINE) {
++		if(ngex->len2*TIMES_LINE2 > gex->len2)
++			goto try_flatboth;
++	}
++
++	/* if curve changes direction */
++	if( gex->isd[X]*ngex->isd[X]<0 || gex->isd[Y]*ngex->isd[Y]<0)
++		goto try_idealone;
++
++	/* if would create a zigzag */
++	if( ((ge->dir&CVDIR_FRONT)-CVDIR_FEQUAL) * ((nge->dir&CVDIR_REAR)-CVDIR_REQUAL) < 0 )
++		goto try_flatone;
++
++	if( fcrossraysge(ge, nge, NULL, NULL, NULL) )
++		gex->flags |= GEXF_JGOOD;
++
++try_flatone:
++	/* look if they can be joined by flatting out one of the entries */
++
++	/* at this point we know that the general direction of the
++	 * gentries is OK
++	 */
++
++	if( gex->flags & GEXF_FLAT ) {
++		tge = *ge;
++		tge.fx1 = tge.fx3;
++		tge.fy1 = tge.fy3;
++		fnormalizege(&tge);
++		if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JFLAT|GEXF_JFLAT1;
++	}
++	if( ngex->flags & GEXF_FLAT ) {
++		tge = *nge;
++		tge.fx2 = ge->fx3;
++		tge.fy2 = ge->fy3;
++		fnormalizege(&tge);
++		if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JFLAT|GEXF_JFLAT2;
++	}
++
++try_idealone:
++	/* look if one of the entries can be brought to an idealized
++	 * horizontal or vertical position and then joined
++	 */
++	if( gex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) {
++		tge = *ge;
++		tge.fx1 = tge.fx3;
++		tge.fy1 = ge->prev->fy3; /* force horizontal */
++		fnormalizege(&tge);
++		if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JID|GEXF_JID1;
++	} else if( gex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) {
++		tge = *ge;
++		tge.fx1 = ge->prev->fx3; /* force vertical */
++		tge.fy1 = tge.fy3;
++		fnormalizege(&tge);
++		if( fcrossraysge(&tge, nge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JID|GEXF_JID1;
++	}
++	if( ngex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) {
++		tge = *nge;
++		tge.fx2 = ge->fx3;
++		tge.fy2 = nge->fy3; /* force horizontal */
++		fnormalizege(&tge);
++		if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JID|GEXF_JID2;
++	} else if( ngex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) {
++		tge = *nge;
++		tge.fx2 = nge->fx3; /* force vertical */
++		tge.fy2 = ge->fy3;
++		fnormalizege(&tge);
++		if( fcrossraysge(ge, &tge, NULL, NULL, NULL) )
++			gex->flags |= GEXF_JID|GEXF_JID2;
++	}
++
++try_flatboth:
++	/* look if we can change them to one line */
++	if(gex->flags & GEXF_FLAT && ngex->flags & GEXF_FLAT) {
++		for(i=0; i<2; i++) {
++			dots[0][i] = ge->prev->fpoints[i][2];
++			dots[1][i] = nge->fpoints[i][2];
++			dots[2][i] = ge->fpoints[i][2];
++		}
++		if( fdotsegdist2(dots, dots[2]) <= CVEPS2)
++			gex->flags |= GEXF_JLINE;
++	}
++}
++
++/*
++ * Force conciseness of one contour in the glyph,
++ * the contour is indicated by one entry from it.
++ */
++
++static void
++fconcisecontour(
++	GLYPH *g,
++	GENTRY *startge
++)
++{
++/* initial maximal number of dots to be used as reference */
++#define MAXDOTS	((NREFDOTS+1)*12)
++
++	GENTRY *ge, *pge, *nge, *ige;
++	GEX_CON *gex, *pgex, *ngex, *nngex;
++	GENTRY tpge, tnge;
++	int quad, qq, i, j, ndots, maxdots;
++	int found[2];
++	int joinmask, pflag, nflag;
++	struct dot_dist *dots;
++	double avsd2, maxd2, eps2;
++	double apcv[4][2];
++
++	if(startge == 0) {
++		fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
++			__FILE__, __LINE__);
++		fprintf(stderr, "Strange contour in glyph %s\n", g->name);
++		dumppaths(g, NULL, NULL);
++		return;
++	}
++
++	if(startge->type != GE_CURVE && startge->type != GE_LINE)
++		return; /* probably a degenerate contour */
++
++	if(ISDBG(FCONCISE))
++		fprintf(stderr, "processing contour 0x%p of glyph %s\n", startge, g->name);
++
++	maxdots = MAXDOTS;
++	dots = (struct dot_dist *)malloc(sizeof(*dots)*maxdots);
++	if(dots == NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++
++	ge = startge;
++	joinmask = GEXF_JGOOD;
++	while(1) {
++	restart:
++		gex = X_CON(ge);
++		if((gex->flags & GEXF_JMASK) > ((joinmask<<1)-1)) {
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "found higher flag (%x>%x) at 0x%p\n", 
++					gex->flags & GEXF_JMASK, ((joinmask<<1)-1), ge);
++			joinmask <<= 1;
++			startge = ge; /* have to redo the pass */
++			continue;
++		}
++		if(( gex->flags & joinmask )==0)
++			goto next;
++
++		/* if we happen to be in the middle of a string of
++		 * joinable entries, find its beginning
++		 */
++		if( gex->flags & (GEXF_JCVMASK^GEXF_JID) )
++			quad = gex->flags & X_CON_F(ge->frwd) & GEXF_QMASK;
++		else if( gex->flags & GEXF_JID2 )
++			quad = gex->flags & GEXF_QFROM_IDEAL(X_CON_F(ge->frwd)) & GEXF_QMASK;
++		else /* must be GEXF_JID1 */
++			quad = GEXF_QFROM_IDEAL(gex->flags) & X_CON_F(ge->frwd) & GEXF_QMASK;
++
++		pge = ge;
++		pgex = X_CON(pge->bkwd);
++
++		if(ISDBG(FCONCISE))
++			fprintf(stderr, "ge %p prev -> 0x%p ", ge, pge);
++
++		while(pgex->flags & GEXF_JCVMASK) {
++			if( !(pgex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID2)) )
++				qq = GEXF_QFROM_IDEAL(pgex->flags);
++			else 
++				qq = pgex->flags & GEXF_QMASK;
++
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "(%x?%x)", quad, qq);
++
++			if( !(quad & qq) ) {
++				if( !(X_CON_F(pge) & (GEXF_JCVMASK^GEXF_JID))
++				&& pgex->flags & (GEXF_JCVMASK^GEXF_JID) ) {
++					/* the previos entry is definitely a better match */
++					if(pge == ge) {
++						if(ISDBG(FCONCISE))
++							fprintf(stderr, "\nprev is a better match at %p\n", pge);
++						startge = ge;
++						goto next;
++					} else
++						pge = pge->frwd;
++				}
++				break;
++			}
++
++			quad &= qq;
++			pge = pge->bkwd;
++			pgex = X_CON(pge->bkwd);
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "0x%p ", pge);
++		}
++
++		/* collect as many entries for joining as possible */
++		nge = ge->frwd;
++		ngex = X_CON(nge); 
++		nngex = X_CON(nge->frwd); 
++
++		if(ISDBG(FCONCISE))
++			fprintf(stderr, ": 0x%x\nnext -> 0x%p ", pge, nge);
++
++		while(ngex->flags & GEXF_JCVMASK) {
++			if( !(ngex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID1)) )
++				qq = GEXF_QFROM_IDEAL(nngex->flags);
++			else 
++				qq = nngex->flags & GEXF_QMASK;
++
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "(%x?%x)", quad, qq);
++			if( !(quad & qq) ) {
++				if( !(X_CON_F(nge->bkwd) & (GEXF_JCVMASK^GEXF_JID))
++				&& ngex->flags & (GEXF_JCVMASK^GEXF_JID) ) {
++					/* the next-next entry is definitely a better match */
++					if(nge == ge->frwd) {
++						if(ISDBG(FCONCISE))
++							fprintf(stderr, "\nnext %x is a better match than %x at %p (jmask %x)\n", 
++								ngex->flags & GEXF_JCVMASK, gex->flags & GEXF_JCVMASK, nge, joinmask);
++						goto next;
++					} else
++						nge = nge->bkwd;
++				}
++				break;
++			}
++
++			quad &= qq;
++			nge = nge->frwd;
++			ngex = nngex; 
++			nngex = X_CON(nge->frwd);
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "0x%p ", nge);
++		}
++
++		if(ISDBG(FCONCISE))
++			fprintf(stderr, ": 0x%x\n", nge);
++
++		/* XXX add splitting of last entries if neccessary */
++
++		/* make sure that all the reference dots are valid */
++		for(ige = pge; ige != nge->frwd; ige = ige->frwd) {
++			nngex = X_CON(ige);
++			if( !(nngex->flags & GEXF_VDOTS) ) {
++				fsampledots(ige, nngex->dots, NREFDOTS);
++				nngex->flags |= GEXF_VDOTS;
++			}
++		}
++
++		/* do the actual joining */
++		while(1) {
++			pgex = X_CON(pge);
++			ngex = X_CON(nge->bkwd);
++			/* now the segments to be joined are pge...nge */
++
++			ndots = 0;
++			for(ige = pge; ige != nge->frwd; ige = ige->frwd) {
++				if(maxdots < ndots+(NREFDOTS+1)) {
++					maxdots += MAXDOTS;
++					dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots);
++					if(dots == NULL) {
++						fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++						exit(255);
++					}
++				}
++				nngex = X_CON(ige);
++				for(i=0; i<NREFDOTS; i++) {
++					for(j=0; j<2; j++)
++						dots[ndots].p[j] = nngex->dots[i][j];
++					ndots++;
++				}
++				for(j=0; j<2; j++)
++					dots[ndots].p[j] = ige->fpoints[j][2];
++				ndots++;
++			}
++			ndots--; /* the last point is not interesting */
++
++			tpge = *pge;
++			pflag = pgex->flags;
++			if(pflag & (GEXF_JGOOD|GEXF_JFLAT2|GEXF_JID2)) {
++				/* nothing */
++			} else if(pflag & GEXF_JFLAT) {
++				tpge.fx1 = tpge.fx3;
++				tpge.fy1 = tpge.fy3;
++			} else if(pflag & GEXF_JID) {
++				if(pflag & GEXF_HOR)
++					tpge.fy1 = tpge.bkwd->fy3;
++				else
++					tpge.fx1 = tpge.bkwd->fx3;
++			}
++
++			tnge = *nge;
++			nflag = ngex->flags;
++			if(nflag & (GEXF_JGOOD|GEXF_JFLAT1|GEXF_JID)
++			&& !(nflag & GEXF_JID2)) {
++				/* nothing */
++			} else if(nflag & GEXF_JFLAT) {
++				tnge.fx2 = tnge.bkwd->fx3;
++				tnge.fy2 = tnge.bkwd->fy3;
++			} else if(nflag & GEXF_JID) {
++				if(X_CON_F(nge) & GEXF_HOR)
++					tnge.fy2 = tnge.fy3;
++				else
++					tnge.fx2 = tnge.fx3;
++			}
++
++			fnormalizege(&tpge);
++			fnormalizege(&tnge);
++			if( fcrossraysge(&tpge, &tnge, NULL, NULL, &apcv[1]) ) {
++				apcv[0][X] = tpge.bkwd->fx3;
++				apcv[0][Y] = tpge.bkwd->fy3;
++				/* apcv[1] and apcv[2] were filled by fcrossraysge() */
++				apcv[3][X] = tnge.fx3;
++				apcv[3][Y] = tnge.fy3;
++
++				/* calculate the precision depending on the smaller dimension of the curve */
++				maxd2 = apcv[3][X]-apcv[0][X];
++				maxd2 *= maxd2;
++				eps2 = apcv[3][Y]-apcv[0][Y];
++				eps2 *= eps2;
++				if(maxd2 < eps2)
++					eps2 = maxd2;
++				eps2 *= (CVEPS2*4.) / (400.*400.);
++				if(eps2 < CVEPS2)
++					eps2 = CVEPS2;
++				else if(eps2 > CVEPS2*4.)
++					eps2 = CVEPS2*4.;
++
++				fapproxcurve(apcv, dots, ndots);
++
++				avsd2 = fdotcurvdist2(apcv, dots, ndots, &maxd2); 
++				if(ISDBG(FCONCISE))
++					fprintf(stderr, "avsd = %g, maxd = %g, ", sqrt(avsd2), sqrt(maxd2));
++				if(avsd2 <= eps2 && maxd2 <= eps2*2.) {
++					/* we've guessed a curve that is close enough */
++					ggoodcv++; ggoodcvdots += ndots;
++
++					if(ISDBG(FCONCISE)) {
++						fprintf(stderr, "in %s joined %p-%p to ", g->name, pge, nge);
++						for(i=0; i<4; i++) {
++							fprintf(stderr, " (%g, %g)", apcv[i][X], apcv[i][Y]);
++						}
++						fprintf(stderr, " from\n");
++						dumppaths(g, pge, nge);
++					}
++					for(i=0; i<3; i++) {
++						pge->fxn[i] = apcv[i+1][X];
++						pge->fyn[i] = apcv[i+1][Y];
++					}
++					pge->type = GE_CURVE;
++					ge = pge;
++					for(ige = pge->frwd; ; ige = pge->frwd) {
++						if(ige == pge) {
++							fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
++								__FILE__, __LINE__);
++							free(dots);
++							return;
++						}
++						if(startge == ige)
++							startge = pge;
++						free(ige->ext);
++						freethisge(ige);
++						if(ige == nge)
++							break;
++					}
++					fnormalizege(ge);
++					if(ISDBG(FCONCISE)) {
++						fprintf(stderr, "normalized ");
++						for(i=0; i<3; i++) {
++							fprintf(stderr, " (%g, %g)", ge->fpoints[X][i], ge->fpoints[Y][i]);
++						}
++						fprintf(stderr, "\n");
++					}
++					fanalyzege(ge);
++					fanalyzejoint(ge);
++					fanalyzege(ge->bkwd);
++					fanalyzejoint(ge->bkwd);
++
++					/* the results of this join will have to be reconsidered */
++					startge = ge = ge->frwd;
++					goto restart;
++				} else {
++					gbadcv++; gbadcvdots += ndots;
++				}
++			}
++
++			/* if we're down to 2 entries then the join has failed */
++			if(pge->frwd == nge) {
++				pgex->flags &= ~joinmask;
++				if(ISDBG(FCONCISE))
++					fprintf(stderr, "no match\n");
++				goto next;
++			}
++
++			/* reduce the number of entries by dropping one at some end,
++			 * should never drop the original ge from the range
++			 */
++
++			if(nge->bkwd == ge 
++			|| (pge != ge && (pgex->flags & GEXF_JCVMASK) <= (ngex->flags & GEXF_JCVMASK)) ) {
++				pge = pge->frwd;
++			} else {
++				nge = nge->bkwd;
++			}
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "next try: %p to %p\n", pge, nge);
++		}
++
++next:
++		ge = ge->frwd;
++		if(ge == startge) {
++			joinmask = (joinmask >> 1) & GEXF_JCVMASK;
++			if(joinmask == 0)
++				break;
++		}
++	}
++
++	/* join flat segments into lines */
++	/* here ge==startge */
++	while(1) {
++		gex = X_CON(ge);
++		if( !(gex->flags & GEXF_JLINE) )
++			goto next2;
++
++		ndots = 0;
++		dots[ndots].p[X] = ge->fx3;
++		dots[ndots].p[Y] = ge->fy3;
++		ndots++;
++
++		pge = ge->bkwd;
++		nge = ge->frwd;
++
++		if(ISDBG(FCONCISE))
++			fprintf(stderr, "joining LINE from %p-%p\n", ge, nge);
++
++		while(pge!=nge) {
++			pgex = X_CON(pge);
++			ngex = X_CON(nge); 
++			if(ISDBG(FCONCISE))
++				fprintf(stderr, "(p=%p/%x n=0x%x/%x) ", pge, pgex->flags & GEXF_JLINE, 
++					nge, ngex->flags & GEXF_JLINE);
++			if( !((pgex->flags | ngex->flags) & GEXF_JLINE) ) {
++				if(ISDBG(FCONCISE))
++					fprintf(stderr, "(end p=%p n=%p) ", pge, nge);
++				break;
++			}
++
++			if(maxdots < ndots+2) {
++				maxdots += MAXDOTS;
++				dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots);
++				if(dots == NULL) {
++					fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++					exit(255);
++				}
++			}
++			if( pgex->flags & GEXF_JLINE ) {
++				for(i=0; i<2; i++) {
++					apcv[0][i] = pge->bkwd->fpoints[i][2];
++					apcv[1][i] = nge->fpoints[i][2];
++					dots[ndots].p[i] = pge->fpoints[i][2];
++				}
++				ndots++;
++				for(i=0; i<ndots; i++) {
++					avsd2 = fdotsegdist2(apcv, dots[i].p);
++					if(avsd2 > CVEPS2)
++						break;
++				}
++				if(i<ndots) { /* failed to join */
++					if(ISDBG(FCONCISE))
++						fprintf(stderr, "failed to join prev %p ", pge);
++					ndots--;
++					pgex->flags &= ~GEXF_JLINE;
++				} else {
++					pge = pge->bkwd;
++					if(pge == nge) {
++						if(ISDBG(FCONCISE))
++							fprintf(stderr, "intersected at prev %p ", pge);
++						break; /* oops, tried to self-intersect */
++					}
++				}
++			} else if(ISDBG(FCONCISE))
++				fprintf(stderr, "(p=%p) ", pge);
++
++			if( ngex->flags & GEXF_JLINE ) {
++				for(i=0; i<2; i++) {
++					apcv[0][i] = pge->fpoints[i][2]; /* pge points before the 1st segment */
++					apcv[1][i] = nge->frwd->fpoints[i][2];
++					dots[ndots].p[i] = nge->fpoints[i][2];
++				}
++				ndots++;
++				for(i=0; i<ndots; i++) {
++					avsd2 = fdotsegdist2(apcv, dots[i].p);
++					if(avsd2 > CVEPS2)
++						break;
++				}
++				if(i<ndots) { /* failed to join */
++					if(ISDBG(FCONCISE))
++						fprintf(stderr, "failed to join next %p ", nge->frwd);
++					ndots--;
++					ngex->flags &= ~GEXF_JLINE;
++				} else {
++					nge = nge->frwd;
++				}
++			} else if(ISDBG(FCONCISE))
++				fprintf(stderr, "(n=%p) ", nge);
++		}
++
++		pge = pge->frwd;  /* now the limits are pge...nge inclusive */
++		if(pge == nge) /* a deeply perversive contour */
++			break;
++
++		if(ISDBG(FCONCISE)) {
++			fprintf(stderr, "\nin %s joined LINE %p-%p from\n", g->name, pge, nge);
++			dumppaths(g, pge, nge);
++		}
++		pge->type = GE_LINE;
++		for(i=0; i<2; i++) {
++			pge->fpoints[i][2] = nge->fpoints[i][2];
++		}
++		fnormalizege(pge);
++		X_CON_F(pge) &= ~GEXF_JLINE;
++
++		ge = pge;
++		for(ige = pge->frwd; ; ige = pge->frwd) {
++			if(ige == pge) {
++				fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n",
++					__FILE__, __LINE__);
++				free(dots);
++				return;
++			}
++			if(startge == ige)
++				startge = pge;
++			free(ige->ext);
++			freethisge(ige);
++			if(ige == nge)
++				break;
++		}
++next2:
++		ge = ge->frwd;
++		if(ge == startge)
++			break;
++	}
++
++	free(dots);
++}
++
++/* force conciseness: substitute 2 or more curves going in the
++** same quadrant with one curve
++** in floating point
++*/
++
++void
++fforceconcise(
++	     GLYPH * g
++)
++{
++
++	GENTRY         *ge, *nge, *endge, *xge;
++
++	assertisfloat(g, "enforcing conciseness");
++
++	fdelsmall(g, 0.05);
++	assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++	if(ISDBG(FCONCISE))
++		dumppaths(g, NULL, NULL);
++
++	/* collect more information about each gentry and their joints */
++	for (ge = g->entries; ge != 0; ge = ge->next)
++		if (ge->type == GE_CURVE || ge->type == GE_LINE)
++			fnormalizege(ge);
++
++	for (ge = g->entries; ge != 0; ge = ge->next)
++		if (ge->type == GE_CURVE || ge->type == GE_LINE) {
++			alloc_gex_con(ge);
++			fanalyzege(ge);
++		}
++
++	/* see what we can do about joining */
++	for (ge = g->entries; ge != 0; ge = ge->next)
++		if (ge->type == GE_CURVE || ge->type == GE_LINE)
++			fanalyzejoint(ge);
++
++	/* now do the joining */
++	for (ge = g->entries; ge != 0; ge = ge->next)
++		if(ge->type == GE_MOVE)
++			fconcisecontour(g, ge->next);
++
++	for (ge = g->entries; ge != 0; ge = ge->next)
++		if (ge->type == GE_CURVE || ge->type == GE_LINE)
++			free(ge->ext);
++}
++
++void
++print_glyph(
++	   int glyphno
++)
++{
++	GLYPH          *g;
++	GENTRY         *ge;
++	int             x = 0, y = 0;
++	int             i;
++	int             grp, lastgrp= -1;
++
++	if(ISDBG(FCONCISE) && glyphno == 0) {
++		fprintf(stderr, "Guessed curves: bad %d/%d good %d/%d\n",
++			gbadcv, gbadcvdots, ggoodcv, ggoodcvdots);
++	}
++
++	g = &glyph_list[glyphno];
++
++	fprintf(pfa_file, "/%s { \n", g->name);
++
++	/* consider widths >MAXLEGALWIDTH as bugs */
++	if( g->scaledwidth <= MAXLEGALWIDTH ) {
++		fprintf(pfa_file, "0 %d hsbw\n", g->scaledwidth);
++	} else {
++		fprintf(pfa_file, "0 1000 hsbw\n");
++		WARNING_2 fprintf(stderr, "glyph %s: width %d seems to be buggy, set to 1000\n",
++			g->name, g->scaledwidth);
++	}
++
++#if 0
++	fprintf(pfa_file, "%% contours: ");
++	for (i = 0; i < g->ncontours; i++)
++		fprintf(pfa_file, "%s(%d,%d) ", (g->contours[i].direction == DIR_OUTER ? "out" : "in"),
++			g->contours[i].xofmin, g->contours[i].ymin);
++	fprintf(pfa_file, "\n");
++
++	if (g->rymin < 5000)
++		fprintf(pfa_file, "%d lower%s\n", g->rymin, (g->flatymin ? "flat" : "curve"));
++	if (g->rymax > -5000)
++		fprintf(pfa_file, "%d upper%s\n", g->rymax, (g->flatymax ? "flat" : "curve"));
++#endif
++
++	if (g->hstems)
++		for (i = 0; i < g->nhs; i += 2) {
++			if (g->hstems[i].flags & ST_3) {
++				fprintf(pfa_file, "%d %d %d %d %d %d hstem3\n",
++					g->hstems[i].value,
++				g->hstems[i + 1].value - g->hstems[i].value,
++					g->hstems[i + 2].value,
++					g->hstems[i + 3].value - g->hstems[i + 2].value,
++					g->hstems[i + 4].value,
++					g->hstems[i + 5].value - g->hstems[i + 4].value
++					);
++				i += 4;
++			} else {
++				fprintf(pfa_file, "%d %d hstem\n", g->hstems[i].value,
++				g->hstems[i + 1].value - g->hstems[i].value);
++			}
++		}
++
++	if (g->vstems)
++		for (i = 0; i < g->nvs; i += 2) {
++			if (g->vstems[i].flags & ST_3) {
++				fprintf(pfa_file, "%d %d %d %d %d %d vstem3\n",
++					g->vstems[i].value,
++				g->vstems[i + 1].value - g->vstems[i].value,
++					g->vstems[i + 2].value,
++					g->vstems[i + 3].value - g->vstems[i + 2].value,
++					g->vstems[i + 4].value,
++					g->vstems[i + 5].value - g->vstems[i + 4].value
++					);
++				i += 4;
++			} else {
++				fprintf(pfa_file, "%d %d vstem\n", g->vstems[i].value,
++				g->vstems[i + 1].value - g->vstems[i].value);
++			}
++		}
++
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if(g->nsg>0) {
++			grp=ge->stemid;
++			if(grp >= 0 && grp != lastgrp)  {
++				fprintf(pfa_file, "%d 4 callsubr\n", grp+g->firstsubr);
++				lastgrp=grp;
++			}
++		}
++
++		switch (ge->type) {
++		case GE_MOVE:
++			if (absolute)
++				fprintf(pfa_file, "%d %d amoveto\n", ge->ix3, ge->iy3);
++			else
++				rmoveto(ge->ix3 - x, ge->iy3 - y);
++			if (0)
++				fprintf(stderr, "Glyph %s: print moveto(%d, %d)\n",
++					g->name, ge->ix3, ge->iy3);
++			x = ge->ix3;
++			y = ge->iy3;
++			break;
++		case GE_LINE:
++			if (absolute)
++				fprintf(pfa_file, "%d %d alineto\n", ge->ix3, ge->iy3);
++			else
++				rlineto(ge->ix3 - x, ge->iy3 - y);
++			x = ge->ix3;
++			y = ge->iy3;
++			break;
++		case GE_CURVE:
++			if (absolute)
++				fprintf(pfa_file, "%d %d %d %d %d %d arcurveto\n",
++					ge->ix1, ge->iy1, ge->ix2, ge->iy2, ge->ix3, ge->iy3);
++			else
++				rrcurveto(ge->ix1 - x, ge->iy1 - y,
++					  ge->ix2 - ge->ix1, ge->iy2 - ge->iy1,
++					  ge->ix3 - ge->ix2, ge->iy3 - ge->iy2);
++			x = ge->ix3;
++			y = ge->iy3;
++			break;
++		case GE_PATH:
++			closepath();
++			break;
++		default:
++			WARNING_1 fprintf(stderr, "**** Glyph %s: unknown entry type '%c'\n",
++				g->name, ge->type);
++			break;
++		}
++	}
++
++	fprintf(pfa_file, "endchar } ND\n");
++}
++
++/* print the subroutines for this glyph, returns the number of them */
++int
++print_glyph_subs(
++	   int glyphno,
++	   int startid /* start numbering subroutines from this id */
++)
++{
++	GLYPH *g;
++	int i, grp;
++
++	g = &glyph_list[glyphno];
++
++	if(!hints || !subhints || g->nsg<1)
++		return 0;
++
++	g->firstsubr=startid;
++
++#if 0
++	fprintf(pfa_file, "%% %s %d\n", g->name, g->nsg);
++#endif
++	for(grp=0; grp<g->nsg; grp++) {
++		fprintf(pfa_file, "dup %d {\n", startid++);
++		for(i= (grp==0)? 0 : g->nsbs[grp-1]; i<g->nsbs[grp]; i++)
++			fprintf(pfa_file, "\t%d %d %cstem\n", g->sbstems[i].low, 
++				g->sbstems[i].high-g->sbstems[i].low,
++				g->sbstems[i].isvert ? 'v' : 'h');
++		fprintf(pfa_file, "\treturn\n\t} NP\n");
++	}
++
++	return g->nsg;
++}
++
++void
++print_glyph_metrics(
++	   int code,
++	   int glyphno
++)
++{
++	GLYPH *g;
++
++	g = &glyph_list[glyphno];
++
++	if(transform)
++	  fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n",
++		  code, g->scaledwidth, g->name,
++		  iscale(g->xMin), iscale(g->yMin), iscale(g->xMax), iscale(g->yMax));
++	else
++	  fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n",
++		  code, g->scaledwidth, g->name,
++		  g->xMin, g->yMin, g->xMax, g->yMax);
++}
++
++/*
++ SB:
++ An important note about the BlueValues.
++
++ The Adobe documentation says that the maximal width of a Blue zone
++ is connected to the value of BlueScale, which is by default 0.039625.
++ The BlueScale value defines, at which point size the overshoot
++ suppression be disabled.
++
++ The formula for it that is given in the manual is:
++
++  BlueScale=point_size/240, for a 300dpi device
++
++ that makes us wonder what is this 240 standing for. Incidentally
++ 240=72*1000/300, where 72 is the relation between inches and points,
++ 1000 is the size of the glyph matrix, and 300dpi is the resolution of
++ the output device. Knowing that we can recalculate the formula for
++ the font size in pixels rather than points:
++
++  BlueScale=pixel_size/1000
++
++ That looks a lot simpler than the original formula, does not it ?
++ And the limitation about the maximal width of zone also looks
++ a lot simpler after the transformation:
++
++  max_width < 1000/pixel_size
++
++ that ensures that even at the maximal pixel size when the overshoot
++ suppression is disabled the zone width will be less than one pixel.
++ This is important, failure to comply to this limit will result in
++ really ugly fonts (been there, done that). But knowing the formula
++ for the pixel width, we see that in fact we can use the maximal width
++ of 24, not 23 as specified in the manual.
++
++*/
++
++#define MAXBLUEWIDTH (24)
++
++/*
++ * Find the indexes of the most frequent values
++ * in the hystogram, sort them in ascending order, and save which one
++ * was the best one (if asked).
++ * Returns the number of values found (may be less than maximal because
++ * we ignore the zero values)
++ */
++
++#define MAXHYST	(2000)		/* size of the hystogram */
++#define HYSTBASE 500
++
++static int
++besthyst(
++	 int *hyst,		/* the hystogram */
++	 int base,		/* the base point of the hystogram */
++	 int *best,		/* the array for indexes of best values */
++	 int nbest,		/* its allocated size */
++	 int width,		/* minimal difference between indexes */
++	 int *bestindp		/* returned top point */
++)
++{
++	unsigned char   hused[MAXHYST / 8 + 1];
++	int             i, max, j, w, last = 0;
++	int             nf = 0;
++
++	width--;
++
++	memset(hused, 0 , sizeof hused);
++
++	max = 1;
++	for (i = 0; i < nbest && max != 0; i++) {
++		best[i] = 0;
++		max = 0;
++		for (j = 1; j < MAXHYST - 1; j++) {
++			w = hyst[j];
++
++			if (w > max && (hused[j>>3] & (1 << (j & 0x07))) == 0) {
++				best[i] = j;
++				max = w;
++			}
++		}
++		if (max != 0) {
++			if (max < last/2) {
++				/* do not pick the too low values */
++				break;
++			}
++			for (j = best[i] - width; j <= best[i] + width; j++) {
++				if (j >= 0 && j < MAXHYST)
++					hused[j >> 3] |= (1 << (j & 0x07));
++			}
++			last = max;
++			best[i] -= base;
++			nf = i + 1;
++		}
++	}
++
++	if (bestindp)
++		*bestindp = best[0];
++
++	/* sort the indexes in ascending order */
++	for (i = 0; i < nf; i++) {
++		for (j = i + 1; j < nf; j++)
++			if (best[j] < best[i]) {
++				w = best[i];
++				best[i] = best[j];
++				best[j] = w;
++			}
++	}
++
++	return nf;
++}
++
++/*
++ * Find the next best Blue zone in the hystogram.
++ * Return the weight of the found zone.
++ */
++
++static int
++bestblue(
++	 short *zhyst,		/* the zones hystogram */
++	 short *physt,		/* the points hystogram */
++	 short *ozhyst,		/* the other zones hystogram */
++	 int *bluetab		/* where to put the found zone */
++)
++{
++	int             i, j, w, max, ind, first, last;
++
++	/* find the highest point in the zones hystogram */
++	/* if we have a plateau, take its center */
++	/* if we have multiple peaks, take the first one */
++
++	max = -1;
++	first = last = -10;
++	for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
++		w = zhyst[i];
++		if (w > max) {
++			first = last = i;
++			max = w;
++		} else if (w == max) {
++			if (last == i - 1)
++				last = i;
++		}
++	}
++	ind = (first + last) / 2;
++
++	if (max == 0)		/* no zones left */
++		return 0;
++
++	/* now we reuse `first' and `last' as inclusive borders of the zone */
++	first = ind;
++	last = ind + (MAXBLUEWIDTH - 1);
++
++	/* our maximal width is far too big, so we try to make it narrower */
++	w = max;
++	j = (w & 1);		/* a pseudo-random bit */
++	while (1) {
++		while (physt[first] == 0)
++			first++;
++		while (physt[last] == 0)
++			last--;
++		if (last - first < (MAXBLUEWIDTH * 2 / 3) || (max - w) * 10 > max)
++			break;
++
++		if (physt[first] < physt[last]
++		    || (physt[first] == physt[last] && j)) {
++			if (physt[first] * 20 > w)	/* if weight is >5%,
++							 * stop */
++				break;
++			w -= physt[first];
++			first++;
++			j = 0;
++		} else {
++			if (physt[last] * 20 > w)	/* if weight is >5%,
++							 * stop */
++				break;
++			w -= physt[last];
++			last--;
++			j = 1;
++		}
++	}
++
++	/* save our zone */
++	bluetab[0] = first - HYSTBASE;
++	bluetab[1] = last - HYSTBASE;
++
++	/* invalidate all the zones overlapping with this one */
++	/* the constant of 2 is determined by the default value of BlueFuzz */
++	for (i = first - (MAXBLUEWIDTH - 1) - 2; i <= last + 2; i++)
++		if (i >= 0 && i < MAXHYST) {
++			zhyst[i] = 0;
++			ozhyst[i] = 0;
++		}
++	return w;
++}
++
++/*
++ * Try to find the Blue Values, bounding box and italic angle
++ */
++
++void
++findblues(void)
++{
++	/* hystograms for upper and lower zones */
++	short           hystl[MAXHYST];
++	short           hystu[MAXHYST];
++	short           zuhyst[MAXHYST];
++	short           zlhyst[MAXHYST];
++	int             nchars;
++	int             i, j, k, w, max;
++	GENTRY         *ge;
++	GLYPH          *g;
++	double          ang;
++
++	/* find the lowest and highest points of glyphs */
++	/* and by the way build the values for FontBBox */
++	/* and build the hystogram for the ItalicAngle */
++
++	/* re-use hystl for the hystogram of italic angle */
++
++	bbox[0] = bbox[1] = 5000;
++	bbox[2] = bbox[3] = -5000;
++
++	for (i = 0; i < MAXHYST; i++)
++		hystl[i] = 0;
++
++	nchars = 0;
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		if (g->flags & GF_USED) {
++			nchars++;
++
++			g->rymin = 5000;
++			g->rymax = -5000;
++			for (ge = g->entries; ge != 0; ge = ge->next) {
++				if (ge->type == GE_LINE) {
++
++					j = ge->iy3 - ge->prev->iy3;
++					k = ge->ix3 - ge->prev->ix3;
++					if (j > 0)
++						ang = atan2(-k, j) * 180.0 / M_PI;
++					else
++						ang = atan2(k, -j) * 180.0 / M_PI;
++
++					k /= 100;
++					j /= 100;
++					if (ang > -45.0 && ang < 45.0) {
++						/*
++						 * be careful to not overflow
++						 * the counter
++						 */
++						hystl[HYSTBASE + (int) (ang * 10.0)] += (k * k + j * j) / 4;
++					}
++					if (ge->iy3 == ge->prev->iy3) {
++						if (ge->iy3 <= g->rymin) {
++							g->rymin = ge->iy3;
++							g->flatymin = 1;
++						}
++						if (ge->iy3 >= g->rymax) {
++							g->rymax = ge->iy3;
++							g->flatymax = 1;
++						}
++					} else {
++						if (ge->iy3 < g->rymin) {
++							g->rymin = ge->iy3;
++							g->flatymin = 0;
++						}
++						if (ge->iy3 > g->rymax) {
++							g->rymax = ge->iy3;
++							g->flatymax = 0;
++						}
++					}
++				} else if (ge->type == GE_CURVE) {
++					if (ge->iy3 < g->rymin) {
++						g->rymin = ge->iy3;
++						g->flatymin = 0;
++					}
++					if (ge->iy3 > g->rymax) {
++						g->rymax = ge->iy3;
++						g->flatymax = 0;
++					}
++				}
++				if (ge->type == GE_LINE || ge->type == GE_CURVE) {
++					if (ge->ix3 < bbox[0])
++						bbox[0] = ge->ix3;
++					if (ge->ix3 > bbox[2])
++						bbox[2] = ge->ix3;
++					if (ge->iy3 < bbox[1])
++						bbox[1] = ge->iy3;
++					if (ge->iy3 > bbox[3])
++						bbox[3] = ge->iy3;
++				}
++			}
++		}
++	}
++
++	/* get the most popular angle */
++	max = 0;
++	w = 0;
++	for (i = 0; i < MAXHYST; i++) {
++		if (hystl[i] > w) {
++			w = hystl[i];
++			max = i;
++		}
++	}
++	ang = (double) (max - HYSTBASE) / 10.0;
++	WARNING_2 fprintf(stderr, "Guessed italic angle: %f\n", ang);
++	if (italic_angle == 0.0)
++		italic_angle = ang;
++
++	/* build the hystogram of the lower points */
++	for (i = 0; i < MAXHYST; i++)
++		hystl[i] = 0;
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		if ((g->flags & GF_USED)
++		    && g->rymin + HYSTBASE >= 0 && g->rymin < MAXHYST - HYSTBASE) {
++			hystl[g->rymin + HYSTBASE]++;
++		}
++	}
++
++	/* build the hystogram of the upper points */
++	for (i = 0; i < MAXHYST; i++)
++		hystu[i] = 0;
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		if ((g->flags & GF_USED)
++		    && g->rymax + HYSTBASE >= 0 && g->rymax < MAXHYST - HYSTBASE) {
++			hystu[g->rymax + HYSTBASE]++;
++		}
++	}
++
++	/* build the hystogram of all the possible lower zones with max width */
++	for (i = 0; i < MAXHYST; i++)
++		zlhyst[i] = 0;
++
++	for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
++		for (j = 0; j < MAXBLUEWIDTH; j++)
++			zlhyst[i] += hystl[i + j];
++	}
++
++	/* build the hystogram of all the possible upper zones with max width */
++	for (i = 0; i < MAXHYST; i++)
++		zuhyst[i] = 0;
++
++	for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) {
++		for (j = 0; j < MAXBLUEWIDTH; j++)
++			zuhyst[i] += hystu[i + j];
++	}
++
++	/* find the baseline */
++	w = bestblue(zlhyst, hystl, zuhyst, &bluevalues[0]);
++	if (0)
++		fprintf(stderr, "BaselineBlue zone %d%% %d...%d\n", w * 100 / nchars,
++				bluevalues[0], bluevalues[1]);
++
++	if (w == 0)		/* no baseline, something weird */
++		return;
++
++	/* find the upper zones */
++	for (nblues = 2; nblues < 14; nblues += 2) {
++		w = bestblue(zuhyst, hystu, zlhyst, &bluevalues[nblues]);
++
++		if (0)
++			fprintf(stderr, "Blue zone %d%% %d...%d\n", w * 100 / nchars, 
++				bluevalues[nblues], bluevalues[nblues+1]);
++
++		if (w * 20 < nchars)
++			break;	/* don't save this zone */
++	}
++
++	/* find the lower zones */
++	for (notherb = 0; notherb < 10; notherb += 2) {
++		w = bestblue(zlhyst, hystl, zuhyst, &otherblues[notherb]);
++
++		if (0)
++			fprintf(stderr, "OtherBlue zone %d%% %d...%d\n", w * 100 / nchars,
++				otherblues[notherb], otherblues[notherb+1]);
++
++
++		if (w * 20 < nchars)
++			break;	/* don't save this zone */
++	}
++
++}
++
++/*
++ * Find the actual width of the glyph and modify the
++ * description to reflect it. Not guaranteed to do
++ * any good, may make character spacing too wide.
++ */
++
++void
++docorrectwidth(void)
++{
++	int             i;
++	GENTRY         *ge;
++	GLYPH          *g;
++	int             xmin, xmax;
++	int             maxwidth, minsp;
++
++	/* enforce this minimal spacing,
++	 * we limit the amount of the enforced spacing to avoid
++	 * spacing the bold wonts too widely
++	 */
++	minsp = (stdhw>60 || stdhw<10)? 60 : stdhw;
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		g->oldwidth=g->scaledwidth; /* save the old width, will need for AFM */
++
++		if (correctwidth && g->flags & GF_USED) {
++			xmin = 5000;
++			xmax = -5000;
++			for (ge = g->entries; ge != 0; ge = ge->next) {
++				if (ge->type != GE_LINE && ge->type != GE_CURVE) 
++					continue;
++
++				if (ge->ix3 <= xmin) {
++					xmin = ge->ix3;
++				}
++				if (ge->ix3 >= xmax) {
++					xmax = ge->ix3;
++				}
++			}
++
++			maxwidth=xmax+minsp;
++			if( g->scaledwidth < maxwidth ) {
++				g->scaledwidth = maxwidth;
++				WARNING_3 fprintf(stderr, "glyph %s: extended from %d to %d\n",
++					g->name, g->oldwidth, g->scaledwidth );
++			}
++		}
++	}
++
++}
++
++/*
++ * Try to find the typical stem widths
++ */
++
++void
++stemstatistics(void)
++{
++#define MINDIST	10 /* minimal distance between the widths */
++	int             hyst[MAXHYST+MINDIST*2];
++	int             best[12];
++	int             i, j, k, w;
++	int             nchars;
++	int             ns;
++	STEM           *s;
++	GLYPH          *g;
++
++	/* start with typical stem width */
++
++	nchars=0;
++
++	/* build the hystogram of horizontal stem widths */
++	memset(hyst, 0, sizeof hyst);
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		if (g->flags & GF_USED) {
++			nchars++;
++			s = g->hstems;
++			for (j = 0; j < g->nhs; j += 2) {
++				if ((s[j].flags | s[j + 1].flags) & ST_END)
++					continue;
++				w = s[j + 1].value - s[j].value+1;
++				if(w==20) /* split stems should not be counted */
++					continue;
++				if (w > 0 && w < MAXHYST - 1) {
++					/*
++					 * handle some fuzz present in
++					 * converted fonts
++					 */
++					hyst[w+MINDIST] += MINDIST-1;
++					for(k=1; k<MINDIST-1; k++) {
++						hyst[w+MINDIST + k] += MINDIST-1-k;
++						hyst[w+MINDIST - k] += MINDIST-1-k;
++					}
++				}
++			}
++		}
++	}
++
++	/* find 12 most frequent values */
++	ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdhw);
++
++	/* store data in stemsnaph */
++	for (i = 0; i < ns; i++)
++		stemsnaph[i] = best[i];
++	if (ns < 12)
++		stemsnaph[ns] = 0;
++
++	/* build the hystogram of vertical stem widths */
++	memset(hyst, 0, sizeof hyst);
++
++	for (i = 0, g = glyph_list; i < numglyphs; i++, g++) {
++		if (g->flags & GF_USED) {
++			s = g->vstems;
++			for (j = 0; j < g->nvs; j += 2) {
++				if ((s[j].flags | s[j + 1].flags) & ST_END)
++					continue;
++				w = s[j + 1].value - s[j].value+1;
++				if (w > 0 && w < MAXHYST - 1) {
++					/*
++					 * handle some fuzz present in
++					 * converted fonts
++					 */
++					hyst[w+MINDIST] += MINDIST-1;
++					for(k=1; k<MINDIST-1; k++) {
++						hyst[w+MINDIST + k] += MINDIST-1-k;
++						hyst[w+MINDIST - k] += MINDIST-1-k;
++					}
++				}
++			}
++		}
++	}
++
++	/* find 12 most frequent values */
++	ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdvw);
++
++	/* store data in stemsnaph */
++	for (i = 0; i < ns; i++)
++		stemsnapv[i] = best[i];
++	if (ns < 12)
++		stemsnapv[ns] = 0;
++
++#undef MINDIST
++}
++
++/*
++ * SB
++ * A funny thing: TTF paths are going in reverse direction compared
++ * to Type1. So after all (because the rest of logic uses TTF
++ * path directions) we have to reverse the paths.
++ *
++ * It was a big headache to discover that.
++ */
++
++/* works on both int and float paths */
++
++void
++reversepathsfromto(
++		   GENTRY * from,
++		   GENTRY * to
++)
++{
++	GENTRY         *ge, *nge, *pge;
++	GENTRY         *cur, *next;
++	int i, n, ilast[2];
++	double flast[2], f;
++
++	for (ge = from; ge != 0 && ge != to; ge = ge->next) {
++		if(ge->type == GE_LINE || ge->type == GE_CURVE) {
++			if (ISDBG(REVERSAL))
++				fprintf(stderr, "reverse path 0x%x <- 0x%x, 0x%x\n", ge, ge->prev, ge->bkwd);
++
++			/* cut out the path itself */
++			pge = ge->prev; /* GE_MOVE */
++			if (pge == 0) {
++				fprintf(stderr, "**! No MOVE before line !!! Fatal. ****\n");
++				exit(1);
++			}
++			nge = ge->bkwd->next; /* GE_PATH */
++			pge->next = nge;
++			nge->prev = pge;
++			ge->bkwd->next = 0; /* mark end of chain */
++
++			/* remember the starting point */
++			if(ge->flags & GEF_FLOAT) {
++				flast[0] = pge->fx3;
++				flast[1] = pge->fy3;
++			} else {
++				ilast[0] = pge->ix3;
++				ilast[1] = pge->iy3;
++			}
++
++			/* then reinsert them in backwards order */
++			for(cur = ge; cur != 0; cur = next ) {
++				next = cur->next; /* or addgeafter() will screw it up */
++				if(cur->flags & GEF_FLOAT) {
++					for(i=0; i<2; i++) {
++						/* reverse the direction of path element */
++						f = cur->fpoints[i][0];
++						cur->fpoints[i][0] = cur->fpoints[i][1];
++						cur->fpoints[i][1] = f;
++						f = flast[i];
++						flast[i] = cur->fpoints[i][2];
++						cur->fpoints[i][2] = f;
++					}
++				} else {
++					for(i=0; i<2; i++) {
++						/* reverse the direction of path element */
++						n = cur->ipoints[i][0];
++						cur->ipoints[i][0] = cur->ipoints[i][1];
++						cur->ipoints[i][1] = n;
++						n = ilast[i];
++						ilast[i] = cur->ipoints[i][2];
++						cur->ipoints[i][2] = n;
++					}
++				}
++				addgeafter(pge, cur);
++			}
++
++			/* restore the starting point */
++			if(ge->flags & GEF_FLOAT) {
++				pge->fx3 = flast[0];
++				pge->fy3 = flast[1];
++			} else {
++				pge->ix3 = ilast[0];
++				pge->iy3 = ilast[1];
++			}
++
++			ge = nge;
++		}
++
++	}
++}
++
++void
++reversepaths(
++	     GLYPH * g
++)
++{
++	reversepathsfromto(g->entries, NULL);
++}
++
++/* add a kerning pair information, scales the value */
++
++void
++addkernpair(
++	unsigned id1,
++	unsigned id2,
++	int unscval
++)
++{
++	static unsigned char *bits = 0;
++	static int lastid;
++	GLYPH *g = &glyph_list[id1];
++	int i, n;
++	struct kern *p;
++
++	if(unscval == 0 || id1 >= numglyphs || id2 >= numglyphs)
++		return;
++
++	if( (glyph_list[id1].flags & GF_USED)==0
++	|| (glyph_list[id2].flags & GF_USED)==0 )
++		return;
++
++	if(bits == 0) {
++		bits = calloc( BITMAP_BYTES(numglyphs), 1);
++		if (bits == NULL) {
++			fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++			exit(255);
++		}
++		lastid = id1;
++	}
++
++	if(lastid != id1) {
++		/* refill the bitmap cache */
++		memset(bits, 0,BITMAP_BYTES(numglyphs));
++		p = g->kern;
++		for(i=g->kerncount; i>0; i--) {
++			n = (p++)->id;
++			SET_BITMAP(bits, n);
++		}
++		lastid = id1;
++	}
++
++	if(IS_BITMAP(bits, id2))
++		return; /* duplicate */
++
++	if(g->kerncount <= g->kernalloc) {
++		g->kernalloc += 8;
++		p = realloc(g->kern, sizeof(struct kern) * g->kernalloc);
++		if(p == 0) {
++			fprintf (stderr, "** realloc failed, kerning data will be incomplete\n");
++		}
++		g->kern = p;
++	}
++
++	SET_BITMAP(bits, id2);
++	p = &g->kern[g->kerncount];
++	p->id = id2;
++	p->val = iscale(unscval) - (g->scaledwidth - g->oldwidth);
++	g->kerncount++;
++	kerning_pairs++;
++}
++
++/* print out the kerning information */
++
++void
++print_kerning(
++	FILE *afm_file
++)
++{
++	int	i, j, n;
++	GLYPH *g;
++	struct kern *p;
++
++	if( kerning_pairs == 0 ) 
++		return;
++
++	fprintf(afm_file, "StartKernData\n");
++	fprintf(afm_file, "StartKernPairs %hd\n", kerning_pairs);
++
++	for(i=0; i<numglyphs; i++)  {
++		g = &glyph_list[i];
++		if( (g->flags & GF_USED) ==0)
++			continue;
++		p = g->kern;
++		for(j=g->kerncount; j>0; j--, p++) {
++			fprintf(afm_file, "KPX %s %s %d\n", g->name, 
++				glyph_list[ p->id ].name, p->val );
++		}
++	}
++
++	fprintf(afm_file, "EndKernPairs\n");
++	fprintf(afm_file, "EndKernData\n");
++}
++
++
++#if 0
++
++/*
++** This function is commented out because the information
++** collected by it is not used anywhere else yet. Now
++** it only collects the directions of contours. And the
++** direction of contours gets fixed already in draw_glyf().
++**
++***********************************************
++**
++** Here we expect that the paths are already closed.
++** We also expect that the contours do not intersect
++** and that curves doesn't cross any border of quadrant.
++**
++** Find which contours go inside which and what is
++** their proper direction. Then fix the direction
++** to make it right.
++**
++*/
++
++#define MAXCONT	1000
++
++void
++fixcontours(
++	    GLYPH * g
++)
++{
++	CONTOUR         cont[MAXCONT];
++	short           ymax[MAXCONT];	/* the highest point */
++	short           xofmax[MAXCONT];	/* X-coordinate of any point
++						 * at ymax */
++	short           ymin[MAXCONT];	/* the lowest point */
++	short           xofmin[MAXCONT];	/* X-coordinate of any point
++						 * at ymin */
++	short           count[MAXCONT];	/* count of lines */
++	char            dir[MAXCONT];	/* in which direction they must go */
++	GENTRY         *start[MAXCONT], *minptr[MAXCONT], *maxptr[MAXCONT];
++	int             ncont;
++	int             i;
++	int             dx1, dy1, dx2, dy2;
++	GENTRY         *ge, *nge;
++
++	/* find the contours and their most upper/lower points */
++	ncont = 0;
++	ymax[0] = -5000;
++	ymin[0] = 5000;
++	for (ge = g->entries; ge != 0; ge = ge->next) {
++		if (ge->type == GE_LINE || ge->type == GE_CURVE) {
++			if (ge->iy3 > ymax[ncont]) {
++				ymax[ncont] = ge->iy3;
++				xofmax[ncont] = ge->ix3;
++				maxptr[ncont] = ge;
++			}
++			if (ge->iy3 < ymin[ncont]) {
++				ymin[ncont] = ge->iy3;
++				xofmin[ncont] = ge->ix3;
++				minptr[ncont] = ge;
++			}
++		}
++		if (ge->frwd != ge->next) {
++			start[ncont++] = ge->frwd;
++			ymax[ncont] = -5000;
++			ymin[ncont] = 5000;
++		}
++	}
++
++	/* determine the directions of contours */
++	for (i = 0; i < ncont; i++) {
++		ge = minptr[i];
++		nge = ge->frwd;
++
++		if (ge->type == GE_CURVE) {
++			dx1 = ge->ix3 - ge->ix2;
++			dy1 = ge->iy3 - ge->iy2;
++
++			if (dx1 == 0 && dy1 == 0) {	/* a pathological case */
++				dx1 = ge->ix3 - ge->ix1;
++				dy1 = ge->iy3 - ge->iy1;
++			}
++			if (dx1 == 0 && dy1 == 0) {	/* a more pathological
++							 * case */
++				dx1 = ge->ix3 - ge->prev->ix3;
++				dy1 = ge->iy3 - ge->prev->iy3;
++			}
++		} else {
++			dx1 = ge->ix3 - ge->prev->ix3;
++			dy1 = ge->iy3 - ge->prev->iy3;
++		}
++		if (nge->type == GE_CURVE) {
++			dx2 = ge->ix3 - nge->ix1;
++			dy2 = ge->iy3 - nge->iy1;
++			if (dx1 == 0 && dy1 == 0) {	/* a pathological case */
++				dx2 = ge->ix3 - nge->ix2;
++				dy2 = ge->iy3 - nge->iy2;
++			}
++			if (dx1 == 0 && dy1 == 0) {	/* a more pathological
++							 * case */
++				dx2 = ge->ix3 - nge->ix3;
++				dy2 = ge->iy3 - nge->iy3;
++			}
++		} else {
++			dx2 = ge->ix3 - nge->ix3;
++			dy2 = ge->iy3 - nge->iy3;
++		}
++
++		/* compare angles */
++		cont[i].direction = DIR_INNER;
++		if (dy1 == 0) {
++			if (dx1 < 0)
++				cont[i].direction = DIR_OUTER;
++		} else if (dy2 == 0) {
++			if (dx2 > 0)
++				cont[i].direction = DIR_OUTER;
++		} else if (dx2 * dy1 < dx1 * dy2)
++			cont[i].direction = DIR_OUTER;
++
++		cont[i].ymin = ymin[i];
++		cont[i].xofmin = xofmin[i];
++	}
++
++	/* save the information that may be needed further */
++	g->ncontours = ncont;
++	if (ncont > 0) {
++		g->contours = malloc(sizeof(CONTOUR) * ncont);
++		if (g->contours == 0) {
++			fprintf(stderr, "***** Memory allocation error *****\n");
++			exit(255);
++		}
++		memcpy(g->contours, cont, sizeof(CONTOUR) * ncont);
++	}
++}
++
++#endif
++
++/*
++ *
++ */
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/pt1.h xserver/hw/xprint/extras/ttf2pt1/pt1.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/pt1.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/pt1.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,257 @@
++/*
++ * see COPYRIGHT
++ */
++
++
++/* glyph entry, one drawing command */
++typedef struct gentry {
++	/* this list links all GENTRYs of a GLYPH sequentially */
++	struct gentry  *next;	/* double linked list */
++	struct gentry  *prev;
++
++	/* this list links all GENTRYs of one contour - 
++	 * of types GE_LINE and GE_CURVE only
++	 * bkwd is also reused: in the very first entry (normally
++	 * of type GE_MOVE) it points to g->entries
++	 */
++	struct gentry  *cntr[2]; /* double-linked circular list */
++/* convenience handles */
++#define bkwd cntr[0]
++#define frwd cntr[1]
++
++	/* various extended structures used at some stage of transformation */
++	void *ext; 
++
++	union {
++		struct {
++			int  val[2][3];	/* integer values */
++		} i;
++		struct {
++			double  val[2][3];	/* floating values */
++		} f;
++	} points; /* absolute values, NOT deltas */
++/* convenience handles */
++#define ipoints	points.i.val
++#define fpoints	points.f.val
++#define ixn ipoints[0]
++#define iyn ipoints[1]
++#define fxn fpoints[0]
++#define fyn fpoints[1]
++#define ix1	ixn[0]
++#define ix2 ixn[1]
++#define ix3 ixn[2]
++#define iy1	iyn[0]
++#define iy2 iyn[1]
++#define iy3 iyn[2]
++#define fx1	fxn[0]
++#define fx2 fxn[1]
++#define fx3 fxn[2]
++#define fy1	fyn[0]
++#define fy2 fyn[1]
++#define fy3 fyn[2]
++
++	char            flags; 
++#define GEF_FLOAT	0x02 /* entry contains floating point data */
++#define GEF_LINE	0x04 /* entry looks like a line even if it's a curve */
++
++	unsigned char	dir; /* used to temporarily store the values for
++				* the directions of the ends of curves */
++/* front end */
++#define CVDIR_FUP	0x02	/* goes over the line connecting the ends */
++#define CVDIR_FEQUAL	0x01	/* coincides with the line connecting the
++				 * ends */
++#define CVDIR_FDOWN	0x00	/* goes under the line connecting the ends */
++#define CVDIR_FRONT	0x0F	/* mask of all front directions */
++/* rear end */
++#define CVDIR_RSAME	0x30	/* is the same as for the front end */
++#define CVDIR_RUP	0x20	/* goes over the line connecting the ends */
++#define CVDIR_REQUAL	0x10	/* coincides with the line connecting the
++				 * ends */
++#define CVDIR_RDOWN	0x00	/* goes under the line connecting the ends */
++#define CVDIR_REAR	0xF0	/* mask of all rear directions */
++
++	signed char     stemid; /* connection to the substituted stem group */
++	char            type;
++#define GE_HSBW	'B'
++#define GE_MOVE 'M'
++#define GE_LINE 'L'
++#define GE_CURVE 'C'
++#define GE_PATH 'P'
++
++	/* indexes of the points to be used for calculation of the tangents */
++	signed char     ftg; /* front tangent */
++	signed char     rtg; /* rear tangent, -1 means "idx 2 of the previous entry" */
++}               GENTRY;
++
++/* stem structure, describes one [hv]stem  */
++/* acually, it describes one border of a stem */
++/* the whole stem is a pair of these structures */
++
++typedef struct stem {
++	short           value;	/* value of X or Y coordinate */
++	short           origin;	/* point of origin for curve stems */
++	GENTRY         *ge; /* entry that has (value, origin) as its first dot */
++		/* also for all the stems the couple (value, origin)
++		 * is used to determine whether a stem is relevant for a
++		 * line, it's considered revelant if this tuple is
++		 * equal to any of the ends of the line.
++		 * ge is also used to resolve ambiguity if there is more than
++		 * one line going through certain pointi, it is used to 
++		 * distinguish these lines.
++		 */
++	 
++	short           from, to;	/* values of other coordinate between
++					 * which this stem is valid */
++
++	short           flags;
++	/* ordering of ST_END, ST_FLAT, ST_ZONE is IMPORTANT for sorting */
++#define ST_END		0x01	/* end of line, lowest priority */
++#define ST_FLAT		0x02	/* stem is defined by a flat line, not a
++				 * curve */
++#define ST_ZONE		0x04	/* pseudo-stem, the limit of a blue zone */
++#define ST_UP		0x08	/* the black area is to up or right from
++				 * value */
++#define ST_3		0x20	/* first stem of [hv]stem3 */
++#define ST_BLUE		0x40	/* stem is in blue zone */
++#define ST_TOPZONE	0x80	/* 1 - top zone, 0 - bottom zone */
++#define ST_VERT     0x100	/* vertical stem (used in substitutions) */
++}               STEM;
++
++#define MAX_STEMS	2000	/* we can't have more stems than path
++				 * elements (or hope so) */
++#define NSTEMGRP	50	/* maximal number of the substituted stem groups */
++
++/* structure for economical representation of the
++ * substituted stems
++ */
++
++typedef struct stembounds {
++	short low; /* low bound */
++	short high; /* high bound */
++	char isvert; /* 1 - vertical, 0 - horizontal */
++	char already; /* temp. flag: is aleready included */
++} STEMBOUNDS;
++
++struct kern {
++	unsigned id; /* ID of the second glyph */
++	int val; /* kerning value */
++};
++
++typedef struct contour {
++	short           ymin, xofmin;
++	short           inside;	/* inside which contour */
++	char            direction;
++#define DIR_OUTER 1
++#define DIR_INNER 0
++}               CONTOUR;
++
++typedef struct glyph {
++	int             char_no;/* Encoding of glyph */
++	int             orig_code;/* code of glyph in the font's original encoding */
++	char           *name;	/* Postscript name of glyph */
++	int             xMin, yMin, xMax, yMax;	/* values from TTF dictionary */
++	int             lsb; /* left sidebearing */
++	int             ttf_pathlen; /* total length of TTF paths */
++	short           width;
++	short           flags;
++#define GF_USED	0x0001		/* whether is this glyph used in T1 font */
++#define GF_FLOAT 0x0002		/* thys glyph contains floating point entries */
++
++	GENTRY         *entries;/* doube linked list of entries */
++	GENTRY         *lastentry;	/* the last inserted entry */
++	GENTRY         *path;	/* beggining of the last path */
++	int             oldwidth; /* actually also scaled */
++	int             scaledwidth;
++#define	MAXLEGALWIDTH	10000 
++
++	struct kern    *kern; /* kerning data */
++	int             kerncount; /* number of kerning pairs */
++	int             kernalloc; /* for how many pairs we have space */
++
++	STEM           *hstems; /* global horiz. and vert. stems */
++	STEM           *vstems;
++	int             nhs, nvs;	/* numbers of stems */
++
++	STEMBOUNDS     *sbstems; /* substituted stems for all the groups */
++	short          *nsbs; /* indexes of the group ends in the common array */
++	int             nsg; /* actual number of the stem groups */
++	int             firstsubr; /* first substistuted stems subroutine number */
++
++	CONTOUR        *contours;	/* it is not used now */
++	int             ncontours;
++
++	int             rymin, rymax;	/* real values */
++	/* do we have flat surfaces on top/bottom */
++	char            flatymin, flatymax;
++
++}               GLYPH;
++
++/* description of a dot for calculation of its distance to a curve */
++
++struct dot_dist {
++	double p[2 /*X,Y*/]; /* coordinates of a dot */
++	double dist2; /* squared distance from the dot to the curve */
++	short seg; /* the closest segment of the curve */
++};
++
++extern int      stdhw, stdvw;	/* dominant stems widths */
++extern int      stemsnaph[12], stemsnapv[12];	/* most typical stem width */
++
++extern int      bluevalues[14];
++extern int      nblues;
++extern int      otherblues[10];
++extern int      notherb;
++extern int      bbox[4];	/* the FontBBox array */
++extern double   italic_angle;
++
++extern GLYPH   *glyph_list;
++extern int    encoding[];	/* inverse of glyph[].char_no */
++
++/* prototypes of functions */
++void rmoveto( int dx, int dy);
++void rlineto( int dx, int dy);
++void rrcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
++void assertpath( GENTRY * from, char *file, int line, char *name);
++
++void fg_rmoveto( GLYPH * g, double x, double y);
++void ig_rmoveto( GLYPH * g, int x, int y);
++void fg_rlineto( GLYPH * g, double x, double y);
++void ig_rlineto( GLYPH * g, int x, int y);
++void fg_rrcurveto( GLYPH * g, double x1, double y1,
++	double x2, double y2, double x3, double y3);
++void ig_rrcurveto( GLYPH * g, int x1, int y1,
++	int x2, int y2, int x3, int y3);
++void g_closepath( GLYPH * g);
++
++void pathtoint( GLYPH *g);
++void ffixquadrants( GLYPH *g);
++void flattencurves( GLYPH * g);
++int checkcv( GENTRY * ge, int dx, int dy);
++void iclosepaths( GLYPH * g);
++void fclosepaths( GLYPH * g);
++void smoothjoints( GLYPH * g);
++void buildstems( GLYPH * g);
++void fstraighten( GLYPH * g);
++void istraighten( GLYPH * g, int zigonly);
++void isplitzigzags( GLYPH * g);
++void fsplitzigzags( GLYPH * g);
++void fforceconcise( GLYPH * g);
++void iforceconcise( GLYPH * g);
++void reversepathsfromto( GENTRY * from, GENTRY * to);
++void reversepaths( GLYPH * g);
++void dumppaths( GLYPH * g, GENTRY *start, GENTRY *end);
++void print_glyph( int glyphno);
++int print_glyph_subs( int glyphno, int startid);
++void print_glyph_metrics( int code, int glyphno);
++void findblues(void);
++void stemstatistics(void);
++void docorrectwidth(void);
++void addkernpair( unsigned id1, unsigned id2, int unscval);
++void print_kerning( FILE *afm_file);
++
++int fcrossrayscv( double curve[4][2], double *max1, double *max2);
++int fcrossraysge( GENTRY *ge1, GENTRY *ge2, double *max1, double *max2,
++	double crossdot[2][2]);
++double fdotsegdist2( double seg[2][2], double dot[2]);
++double fdotcurvdist2( double curve[4][2], struct dot_dist *dots, int ndots, double *maxp);
++void fapproxcurve( double cv[4][2], struct dot_dist *dots, int ndots);
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/README.FIRST xserver/hw/xprint/extras/ttf2pt1/README.FIRST
+--- xserver-old/hw/xprint/extras/ttf2pt1/README.FIRST	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/README.FIRST	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,4 @@
++To get the plain-text README and installation guides run:  
++  
++  make docs
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/README.html xserver/hw/xprint/extras/ttf2pt1/README.html
+--- xserver-old/hw/xprint/extras/ttf2pt1/README.html	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/README.html	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,1182 @@
++<HTML>
++<HEAD>
++<TITLE>
++TTF2PT1 - A True Type to PostScript Type 1 Converter 
++</TITLE>
++</HEAD>
++<BODY>
++<!-- =defdoc t1 ttf2pt1 1 -->
++<H2>
++<!-- =section t1 NAME -->
++TTF2PT1 - A True Type to PostScript Type 1 Font Converter 
++<!-- =stop -->
++</H2>
++
++<! 
++(Do not edit this file, it is generated from README.html!!!)
++>
++<TT>
++[
++<blockquote>
++<!-- =section t1 HISTORY -->
++  Based on ttf2pfa by Andrew Weeks, and help from Frank Siegert.
++<BR>
++  Modification by Mark Heath.
++<BR>
++  Further modification by Sergey Babkin.
++<BR>
++  The Type1 assembler by I. Lee Hetherington with modifications by 
++  Kai-Uwe Herbing.
++<!-- =stop -->
++</blockquote>
++]
++</TT>
++<p>
++
++Ever wanted to install a particular font on your XServer but only could find 
++the font you are after in True Type Format?
++<p>
++
++Ever asked <TT>comp.fonts</TT> for a True Type to Type 1 converter and got a List 
++of Commercial software that doesn't run on your Operating System?
++<p>
++
++Well, this program should be the answer.  This program is written in C (so it
++should be portable)  and therefore should run on any OS.  The only limitation
++is that the program requires some method of converting Big endian integers into
++local host integers so the network functions ntohs and ntohl are used. These 
++can be replaced by macros if your platform doesn't have them. 
++Of course the target platform requires a C compiler and command line ability.
++<p>
++
++<!-- =section t1 DESCRIPTION -->
++Ttf2pt1 is a font converter from the True Type format (and some other formats
++supported by the FreeType library as well) to the Adobe Type1 format.
++<p>
++
++The versions 3.0 and later got rather extensive post-processing algorithm that 
++brings the converted fonts to the requirements of the Type1 standard, tries to
++correct the rounding errors introduced during conversions and some simple
++kinds of bugs that are typical for the public domain TTF fonts. It
++also generates the hints that enable much better rendering of fonts in
++small sizes that are typical for the computer displays. But everything
++has its price, and some of the optimizations may not work well for certain
++fonts. That's why the options were added to the converter, to control
++the performed optimizations.
++<p>
++<!-- =stop -->
++
++The converter is simple to run, just:
++<p>
++
++<!-- =section t1 SYNOPSIS -->
++<blockquote>
++	<tt>ttf2pt1 <i>[-options] ttffont.ttf [Fontname]</i></tt>
++</blockquote>
++or
++<blockquote>
++	<tt>ttf2pt1 <i>[-options] ttffont.ttf -</i></tt>
++</blockquote>
++<!-- =stop -->
++<p>
++
++<!-- =section t1 OPTIONS -->
++The first variant creates the file <tt>Fontname.pfa</tt> (or <tt>Fontname.pfb</tt> if the 
++option '<b>-b</b>' was used) with the converted font and <tt>Fontname.afm</tt> with the 
++font metrics, the second one prints the font or another file (if the option
++'<b>-G</b>' was used) on the standard output from where it can be immediately
++piped through some filter. If no <tt>Fontname</tt> is specified for the first
++variant, the name is generated from <tt>ttffont</tt> by replacing the <tt>.ttf</tt>
++filename suffix.
++<p>
++
++Most of the time no options are neccessary (with a possible exception
++of '<b>-e</b>'). But if there are some troubles with the resulting font, they 
++may be used to control the conversion.
++The <B>options</B> are:
++<p>
++
++<!-- ==over 2 -->
++<!-- ==item * -->
++<TT><B>-a</TT></B> - Include all the glyphs from the source file into the converted
++   file. If this option is not specified then only the glyphs that have
++   been assigned some encoding are included, because the rest of glyphs
++   would be inaccessible anyway and would only consume the disk space. 
++   But some applications are clever enough to change the encoding on
++   the fly and thus use the other glyphs, in this case they could
++   benefit from using this option. But there is a catch: the X11 library
++   has rather low limit for the font size. Including more glyphs increases
++   the file size and thus increases the chance of hitting this limit.
++   See <A HREF="app/X11/README.html"><tt>app/X11/README</tt></A> for the description of a 
++   patch to X11 which fixes this problem.
++<p>
++
++<!-- ==item * -->
++<TT><B>-b</TT></B> - Encode the resulting font to produce a ready <tt>.pfb</tt> file.
++<p>
++
++<!-- ==item * -->
++<TT><B>-d <i>suboptions</i></TT></B> - Debugging options. The suboptions are:
++<p>
++
++<blockquote>
++   <TT><B>a</TT></B> - Print out the absolute coordinates of dots in outlines. Such
++   a font can not be used by any program (that's why this option is
++   incompatible with '<b>-e</b>') but it has proven to be a valuable debuging 
++   information.
++<p>
++
++   <TT><B>r</TT></B> - Do not reverse the direction of outlines. The TTF fonts have
++   the standard direction of outlines opposite to the Type1 fonts. So
++   they should be reversed during proper conversion. This option
++   may be used for debugging or to handle a TTF font with wrong
++   direction of outlines (possibly, converted in a broken way from
++   a Type1 font). The first signs of the wrong direction are the
++   letters like "P" or "B" without the unpainted "holes" inside.
++<p>
++</blockquote>
++
++<!-- ==item * -->
++<TT><B>-e</TT></B> - Assemble the resulting font to produce a ready <tt>.pfa</tt> file.
++<I>
++   [ </I>S.B.<I>: Personally I don't think that this option is particularly useful.
++   The same result may be achieved by piping the unassembled data
++   through t1asm, the Type 1 assembler. And, anyways, it's good to
++   have the t1utils package handy. But Mark and many users think that 
++   this functionality is good and it took not much time to add this option. ]
++</I>
++<p>
++
++<!-- ==item * -->
++<TT><B>-F</TT></B> - Force the Unicode encoding: any type of MS encoding specified
++   in the font is ignored and the font is treated like it has Unicode
++   encoding. <B>WARNING:</B> <I>this option is intended for buggy fonts
++   which actually are in Unicode but are marked as something else. The
++   effect on the other fonts is unpredictable.</I>
++<p>
++
++<!-- ==item * -->
++<TT><B>-G <i>suboptions</i></TT></B> - File generation options. The suboptions may be lowercase 
++   or uppercase, the lowercase ones disable the generation of particular 
++   files, the corresponding uppercase suboptions enable the generation of the 
++   same kind of files. If the result of ttf2pt1 is requested to be printed on
++   the standard output, the last enabling suboption of <b>-G</b> determines
++   which file will be written to the standard output and the rest of files
++   will be discarded. For example, <b>-G A</b> will request the AFM file.
++   The suboptions to disable/enable the generation of the files are:
++<p>
++
++<blockquote>
++   <TT><B>f/F</TT></B> - The font file. Depending on the other options this file
++   will have one of the suffixes <tt>.t1a</tt>, <tt>.pfa</tt> or <tt>.pfb</tt>. If the conversion result
++   is requested on the standard output ('<tt>-</tt>' is used as the output file name)
++   then the font file will also be written there by default, if not overwritten
++   by another suboption of <b>-G</b>.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>a/A</TT></B> - The Adobe font metrics file (<tt>.afm</tt>).
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>e/E</TT></B> - The dvips encoding file (<tt>.enc</tt>).
++   <b>Default: disabled</b>
++<p>
++
++</blockquote>
++
++<!-- ==item * -->
++<TT><B>-l <I>language</I>[+<I>argument</I>]</TT></B> - Extract the fonts for the specified language from a
++   multi-language Unicode font. If this option is not used the converter
++   tries to guess the language by the values of the shell variable LANG.
++   If it is not able to guess the language by LANG it tries all the
++   languages in the order they are listed. 
++<p>
++
++   After the plus sign an optional argument for the language extractor
++   may be specified. The format of the argument is absolutely up to
++   the particular language converter. The primary purpose of the
++   argument is to support selection of planes for the multi-plane
++   Eastern encodings but it can also be used in any other way. The 
++   language extractor may decide to add the plane name in some form
++   to the name of the resulting font. None of the currently supported 
++   languages make any use of the argument yet.
++<p>
++
++   As of now the following languages are supported:
++<br>
++   &nbsp;&nbsp;<TT>latin1</TT> - for all the languages using the Latin-1 encoding
++<br>
++   &nbsp;&nbsp;<TT>latin2</TT> - for the Central European languages
++<br>
++   &nbsp;&nbsp;<TT>latin4</TT> - for the Baltic languages
++<br>
++   &nbsp;&nbsp;<TT>latin5</TT> - for the Turkish language
++<br>
++   &nbsp;&nbsp;<TT>cyrillic</TT> - for the languages with Cyrillic alphabet
++<br>
++   &nbsp;&nbsp;<TT>russian</TT> - historic synonym for cyrillic
++<br>
++   &nbsp;&nbsp;<TT>bulgarian</TT> - historic synonym for cyrillic
++<br>
++   &nbsp;&nbsp;<TT>adobestd</TT> - for the AdobeStandard encoding used by TeX
++<br>
++   &nbsp;&nbsp;<TT>plane+<i>argument</i></TT> - to select one plane from a multi-byte encoding
++<p>
++
++   The argument of the "<tt>plane</tt>" language may be in one of three forms:
++<p>
++   &nbsp;&nbsp;<tt>plane+<b>pid=</b><i>&lt;pid&gt;</i><b>,eid=</b><i>&lt;eid&gt;</i></tt>
++<br>
++   &nbsp;&nbsp;<tt>plane+<b>pid=</b><i>&lt;pid&gt;</i><b>,eid=</b><i>&lt;eid&gt;</i><b>,</b><i>&lt;plane_number&gt;</i></tt>
++<br>
++   &nbsp;&nbsp;<tt>plane+<i>&lt;plane_number&gt;</i></tt>
++<p>
++
++   Pid (TTF platform id) and eid (TTF encoding id) select a particular 
++   TTF encoding table in the original font. They are specified as decimal
++   numbers. If this particular encoding table is not present in the font
++   file then the conversion fails. The native ("ttf") front-end parser supports
++   only pid=3 (Windows platform), the FreeType-based ("ft") front-end supports 
++   any platform. If pid/eid is not specified then the TTF encoding table is 
++   determined as usual: Unicode encoding if it's first or an 8-bit encoding
++   if not (and for an 8-bit encoding the plane number is silently ignored). 
++   To prevent the converter from falling back to an 8-bit encoding, specify
++   the Unicode pid/eid value explicitly.
++<p>
++
++   Plane_number is a hexadecimal (if starts with "<b>0x</b>") or decimal number.
++   It gives the values of upper bytes for which 256 characters will be 
++   selected. If not specified, defaults to 0. It is also used as a font
++   name suffix (the leading "0x" is not included into the suffix).
++<p>
++
++<!-- =stop -->
++   <B>NOTE:</B>
++<!-- =section t1 BUGS -->
++   It seems that many Eastern fonts use features of the TTF format that are 
++   not supported by the ttf2pt1's built-in front-end parser. Because of
++   this for now we recommend using the FreeType-based parser (option
++   '<b>-p ft</b>') with the "<tt>plane</tt>" language.
++<p>
++<!-- =stop -->
++
++<!-- =section t1 OPTIONS -->
++<I>
++   <B>NOTE:</B>
++   You may notice that the language names are not uniform: some are the
++   names of particular languages and some are names of encodings. This
++   is because of the different approaches. The original idea was to
++   implement a conversion from Unicode to the appropriate Windows
++   encoding for a given language. And then use the translation tables
++   to generate the fonts in whatever final encodings are needed. This
++   would allow to pile together the Unicode fonts and the non-Unicode
++   Windows fonts for that language and let the program to sort them out
++   automatically. And then generate fonts in all the possible encodings
++   for that language. An example of this approach is the Russian language
++   support. But if there is no multiplicity of encodings used for some 
++   languages and if the non-Unicode fonts are not considered important 
++   by the users, another way would be simpler to implement: just provide
++   only one table for extraction of the target encoding from Unicode
++   and don't bother with the translation tables. The </I>latin*<I> "languages"
++   are examples of this approach. If somebody feels that he needs the
++   Type1 fonts both in Latin-* and Windows encodings he or she is absolutely
++   welcome to submit the code to implement it.
++</I><p>
++
++   <B>WARNING:</B>
++   Some of the glyphs included into the AdobeStandard encoding are not
++   included into the Unicode standard. The most typical examples of such
++   glyphs are ligatures like 'fi', 'fl' etc. Because of this the font 
++   designers may place them at various places. The converter tries to
++   do its best, if the glyphs have honest Adobe names and/or are
++   placed at the same codes as in the Microsoft fonts they will be
++   picked up. Otherwise a possible solution is to use the option '<b>-L</b>'
++   with an external map. 
++<p>
++
++<!-- ==item * -->
++<TT><B>-L <I>file</I>[+[pid=<I>&lt;pid&gt;</I>,eid=<I>&lt;eid&gt;</I>,][<I>plane</I>]]</TT></B> - Extract the fonts for the specified 
++   language from a multi-language font using the map from this file. This is
++   rather like the option '<b>-l</b>' but the encoding map is not 
++   compiled into the program, it's taken from that file, so it's
++   easy to edit. Examples of such files are provided in 
++   <tt>maps/adobe-standard-encoding.map</tt>, <tt>CP1250.map</tt>. (<b>NOTE:</b>
++   <I>the 'standard encoding' map does not include all the glyphs of the 
++   AdobeStandard encoding, it's provided only as an example</I>.) The 
++   description of the supported map formats is in the file 
++   <tt>maps/unicode-sample.map</tt>.
++<p>
++
++   Likewise to '<b>-l</b>', an argument may be specified after the map file
++   name. But in this case the argument has fixed meaning: it selects the 
++   original TTF encoding table (the syntax is the same as in '<b>-l plane</b>')
++   and/or a plane of the map file. The plane name also gets added after dash 
++   to the font name. The plane is a concept used in the Eastern fonts with big 
++   number of glyphs: one TTF font gets divided into multiple Type1 fonts, 
++   each containing one plane of up to 256 glyphs. But with a little 
++   creativity this concept may be used for other purposes of combining 
++   multiple translation maps into one file.  To extract multiple planes 
++   from a TTF font <tt>ttf2pt1</tt> must be run multiple times, each time with 
++   a different plane name specified.
++<p>
++
++   The default original TTF encoding table used for the option '<b>-L</b>' is
++   Unicode. The map files may include directives to specify different original 
++   TTF encodings. However if the pid/eid pair is specified with
++   it overrides any original encoding specified in the map file.
++<p>
++
++<!-- ==item * -->
++<TT><B>-m <i>type</i>=<i>value</i></TT></B> - Set maximal or minimal limits of resources.
++   These limits control the the font generation by limiting the resources
++   that the font is permitted to require from the PostScript interpreter.
++   The currently supported types of limits are:
++<p>
++
++<blockquote>
++   <TT><B>h</TT></B> - the maximal hint stack depth for the substituted hints. 
++   The default value is 128, according to the limitation in X11. This seems to
++   be the lowest (and thus the safest) widespread value. To display the
++   hint stack depth required by each glyph in a <tt>.t1a</tt> file use the script
++   <tt>scripts/cntstems.pl</tt>.
++<p>
++</blockquote>
++
++<!-- ==item * -->
++<TT><B>-O <i>suboptions</i></TT></B> - Outline processing options. The suboptions
++   may be lowercase or uppercase, the lowercase ones disable the features,
++   the corresponding uppercase suboptions enable the same features.
++   The suboptions to disable/enable features are:
++<p>
++
++<blockquote>
++   <TT><B>b/B</TT></B> - Guessing of the ForceBold parameter. This parameter helps
++   the Type1 engine to rasterize the bold fonts properly at small sizes.
++   But the algorithm used to guess the proper value of this flag makes
++   that guess based solely on the font name. In rare cases that may cause
++   errors, in these cases you may want to disable this guessing. 
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>h/H</TT></B> - Autogeneration of hints. The really complex outlines
++   may confuse the algorithm, so theoretically it may be useful
++   sometimes to disable them. Although up to now it seems that
++   even bad hints are better than no hints at all.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>u/U</TT></B> - Hint substitution. Hint substitution is a technique 
++   permitting generation of more detailed hints for the rasterizer. It allows 
++   to use different sets of hints for different parts of a glyph and change 
++   these sets as neccessary during rasterization (that's why "substituted").  
++   So it should improve the quality of the fonts rendered at small sizes.  
++   But there are two catches: First, the X11 library has rather low limit for 
++   the font size. More detailed hints increase the file size and thus increase 
++   the chance of hitting this limit (that does not mean that you shall hit it
++   but you may if your fonts are particularly big). This is especially 
++   probable for Unicode fonts converted with option '<b>-a</b>', so you may want to 
++   use '<b>-a</b>' together with '<b>-Ou</b>'. See <A HREF="app/X11/README.html"><tt>app/X11/README</tt></A> for the description of 
++   a patch to X11 which fixes this problem. Second, some rasterizers (again,
++   X11 is the typical example) have a limitation for total number of hints
++   used when drawing a glyph (also known as the hint stack depth). If that
++   stack overflows the glyph is ignored. Starting from version 3.22 <tt>ttf2pt1</tt>
++   uses algorithms to minimizing this depth, with the trade-off of slightly
++   bigger font files. The glyphs which still exceed the limit set by option
++   '<b>-mh</b>' have all the substituted hints removed and only base hints left.
++   The algorithms seem to have been refined far enough to make the fonts with
++   substituted hints look better than the fonts without them or at least the 
++   same. Still if the original fonts are not well-designed the detailed 
++   hinting may emphasize the defects of the design, such as non-even thickness 
++   of lines. So provided that you are not afraid of the X11 bug the best idea 
++   would be to generate a font with this feature and without it, then compare 
++   the results using the program <tt>other/cmpf</tt> (see the description 
++   in <A HREF="other/README.html"><tt>other/README</tt></A>) and decide which one looks better.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>o/O</TT></B> - Space optimization of the outlines' code. This kind of optimization
++   never hurts, and the only reason to disable this feature is for comparison 
++   of the generated fonts with the fonts generated by the previous versions of 
++   converter. Well, it _almost_ never hurts. As it turned out there exist
++   some brain-damaged printers which don't understand it. Actually this
++   feature does not change the outlines at all. The Type 1 font manual 
++   provides a set of redundant operators that make font description shorter,
++   such as '10 hlineto' instead of '0 10 rlineto' to describe a horizontal
++   line. This feature enables use of these operators.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>s/S</TT></B> - Smoothing of outlines. If the font is broken in some
++   way (even the ones that are not easily noticeable), such smoothing 
++   may break it further. So disabling this feature is the first thing to be 
++   tried if some font looks odd. But with smoothing off the hint generation
++   algorithms may not work properly too.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>t/T</TT></B> - Auto-scaling to the 1000x1000 Type1 standard matrix. The
++   TTF fonts are described in terms of an arbitrary matrix up to
++   4000x4000. The converted fonts must be scaled to conform to
++   the Type1 standard. But the scaling introduces additional rounding
++   errors, so it may be curious sometimes to look at the font in its
++   original scale.
++   <b>Default: enabled</b>
++<p>
++
++   <TT><B>v/V</TT></B> - Do vectorization on the bitmap fonts. Functionally
++   "vectorization" is the same thing as "autotracing", a different word is
++   used purely to differentiate it from the Autotrace library. It tries to
++   produce nice smooth outlines from bitmaps. This feature is still a work
++   in progress though the results are already mostly decent.
++   <b>Default: disabled</b>
++<p>
++
++   <TT><B>w/W</TT></B> - Glyphs' width corection. This option is designed to be
++   used on broken fonts which specify too narrow widths for the 
++   letters. You can tell that a font can benefit from this option
++   if you see that the characters are smashed together without
++   any whitespace between them. This option causes the converter
++   to set the character widths to the actual width of this character
++   plus the width of a typical vertical stem. But on the other hand
++   the well-designed fonts may have characters that look better if
++   their widths are set slightly narrower. Such well-designed fonts
++   will benefit from disabling this feature. You may want to convert
++   a font with and without this feature, compare the results and
++   select the better one. This feature may be used only on proportional
++   fonts, it has no effect on the fixed-width fonts.
++   <b>Default: disabled</b>
++<p>
++
++   <TT><B>z/Z</TT></B> - Use the Autotrace library on the bitmap fonts. The results 
++   are horrible and <b>the use of this option is not recommended</b>. This option is 
++   present for experimental purposes. It may change or be removed in the
++   future. The working tracing can be achieved with option <tt><b>-OV</b></tt>.
++   <b>Default: disabled</b>
++<p>
++</blockquote>
++
++<!-- ==item * -->
++<TT><B>-p <I>parser_name</I></TT></B> - Use the specified front-end parser to read the font file.
++   If this option is not used, ttf2pt1 selects the parser automatically based
++   on the suffix of the font file name, it uses the first parser in its
++   list that supports this font type. Now two parsers are supported:
++<p>
++
++   &nbsp;&nbsp;<TT>ttf</TT> - built-in parser for the ttf files (suffix <tt>.ttf</tt>)
++<br>
++   &nbsp;&nbsp;<TT>bdf</TT> - built-in parser for the BDF files (suffix <tt>.bdf</tt>)
++<br>
++   &nbsp;&nbsp;<TT>ft</TT> - parser based on the FreeType-2 library (suffixes <tt>.ttf</tt>,
++       <tt>.otf</tt>, <tt>.pfa</tt>, <tt>.pfb</tt>)
++<p>
++
++   The parser <tt>ft</tt> is <b>NOT</b> linked in by default. See <tt>Makefile</tt>
++   for instructions how to enable it. We do no support this parser on
++   Windows: probably it will work but nobody tried and nobody knows how
++   to build it. 
++<p>
++
++   The conversion of the bitmap fonts (such as BDF) is simplistic yet,
++   producing jagged outlines.  When converting such fonts, it might be 
++   a good idea to turn off the hint substitution (using option <b>-Ou</b>) 
++   because the hints produced will be huge but not adding much to the
++   quality of the fonts.
++<p>
++
++<!-- ==item * -->
++<TT><B>-u <I>number</I></TT></B> - Mark the font with this value as its
++   UniqueID. The UniqueID is used by the printers with the hard disks
++   to cache the rasterized characters and thus significantly
++   speed-up the printing. Some of those printers just can't
++   store the fonts without UniqueID on their disk.The problem
++   is that the ID is supposed to be unique, as it name says. And
++   there is no easy way to create a guaranteed unique ID. Adobe specifies
++   the range 4000000-4999999 for private IDs but still it's difficult
++   to guarantee the uniqueness within it. So if you don't really need the 
++   UniqueID don't use it, it's optional. Luckily there are a few millions of 
++   possible IDs, so the chances of collision are rather low. 
++   If instead of the number a special value '<tt><b>A</b></tt>' is given
++   then the converter generates the value of UniqueID automatically,
++   as a hash of the font name. (<b>NOTE:</b> <i> in the version 3.22 the
++   algorithm for autogeneration of UniqueID was changed to fit the values
++   into the Adobe-spacified range. This means that if UniqueIDs were used 
++   then the printer's cache may need to be flushed before replacing the 
++   fonts converted by an old version with fonts converted by a newer version</i>).
++   A simple way to find if any of the fonts in a given directory have
++   duplicated UniqueIDs is to use the command:
++<p>
++
++   <tt>&nbsp;&nbsp;cat *.pf[ab] | grep UniqueID | sort | uniq -c | grep -v ' 1 '</tt>
++<p>
++
++   Or if you use <tt>scripts/convert</tt> it will do that for you automatically 
++   plus it will also give the exact list of files with duplicate UIDs.
++<p>
++
++<!-- ==item * -->
++<TT><B>-v <I>size</I></TT></B> - Re-scale the font to get the size of a typical uppercase
++   letter somewhere around the specified size. Actually, it re-scales
++   the whole font to get the size of one language-dependent letter to be
++   at least of the specified size. Now this letter is "A" in all the
++   supported languages. The size is specified in the points of the
++   Type 1 coordinate grids, the maximal value is 1000. This is an
++   experimental option and should be used with caution. It tries to
++   increase the visible font size for a given point size and thus make
++   the font more readable. But if overused it may cause the fonts to
++   look out of scale. As of now the interesting values of size for
++   this option seem to be located mostly between 600 and 850. This
++   re-scaling may be quite useful but needs more experience to
++   understand the balance of its effects.
++<p>
++
++<!-- ==item * -->
++<TT><B>-W <i>level</i></TT></B> - Select the verbosity level of the warnings.
++   Currently the levels from 0 to 4 are supported. Level 0 means no warnings
++   at all, level 4 means all the possible warnings. The default level is 3.
++   Other levels may be added in the future, so using the level number 99 is
++   recommended to get all the possible warnings. Going below level 2 is
++   not generally recommended because you may miss valuable information about
++   the problems with the fonts being converted.
++<p>
++
++<!-- ==item * -->
++<B>Obsolete option:</B>
++<TT><B>-A</TT></B> - Print the font metrics (.afm file) instead of the font on STDOUT.
++   Use <b>-GA</b> instead.
++<p>
++
++<!-- ==item * -->
++<B>Very obsolete option:</B>
++<br>
++   The algorithm that implemented the forced fixed width had major
++   flaws, so it was disabled. The code is still in the program and
++   some day it will be refined and returned back. Meanwhile the 
++   option name '<b>-f</b>' was reused for another option. The old version was:
++<br>
++<TT><B>-f</TT></B> - Don't try to force the fixed width of font. Normally the converter
++   considers the fonts in which the glyph width deviates by not more
++   than 5% as buggy fixed width fonts and forces them to have really
++   fixed width. If this is undesirable, it can be disabled by this option.
++<p>
++<!-- ==back -->
++
++The <tt>.pfa</tt> font format supposes that the description of the characters
++is binary encoded and encrypted. This converter does not encode or
++encrypt the data by default, you have to specify the option '<b>-e</b>'
++or use the <tt>t1asm</tt> program to assemble (that means, encode and
++encrypt) the font program. The <tt>t1asm</tt> program that is included with
++the converter is actually a part of the <tt>t1utils</tt> package, rather old
++version of which may be obtained from
++<p>
++
++<blockquote>
++<A HREF="http://ttf2pt1.sourceforge.net/t1utils.tar.gz">
++	http://ttf2pt1.sourceforge.net/t1utils.tar.gz
++</A>
++</blockquote>
++<p>
++
++Note that <tt>t1asm</tt> from the old version of that package won't work properly
++with the files generated by <tt>ttf2pt1</tt> version 3.20 and later. Please use
++<tt>t1asm</tt> packaged with <tt>ttf2pt1</tt> or from the new version <tt>t1utils</tt>
++instead. For a newer version of <tt>t1utils</tt> please look at
++<p>
++
++<blockquote>
++<A HREF="http://www.lcdf.org/~eddietwo/type/">
++	http://www.lcdf.org/~eddietwo/type/
++</A>
++</blockquote>
++<p>
++<!-- =stop -->
++
++<!-- =section t1 EXAMPLES -->
++So, the following command lines:
++<p>
++
++<blockquote>
++	<tt>ttf2pt1 -e ttffont.ttf t1font</tt>
++<br>
++	<tt>ttf2pt1 ttffont.ttf - | t1asm &gt;t1font.pfa</tt>
++</blockquote>
++<p>
++
++represent two ways to get a working font. The benefit of the second form 
++is that other filters may be applied to the font between the converter
++and assembler.
++<p>
++<!-- =stop -->
++
++<H4>
++Installation and deinstallation of the converter
++</H4>
++<!
++------------------------------------------------
++>
++
++The converter may be easily installed systemwide with
++
++<blockquote>
++	<tt>make install</tt>
++</blockquote>
++
++and uninstalled with
++
++<blockquote>
++	<tt>make uninstall</tt>
++</blockquote>
++
++By default the <tt>Makefile</tt> is configured to install in the hierarchy
++of directory <tt>/usr/local</tt>. This destination directory as well as
++the structure of the hierarchy may be changed by editing the <tt>Makefile</tt>.
++
++<H4>
++Installation of the fonts
++</H4>
++<!
++-------------------------
++>
++
++Running the converter manually becomes somewhat boring if it has to 
++be applied to a few hundreds of fonts and then you have to generate the 
++<tt>fonts.scale</tt> and/or <tt>Fontmap</tt> files. The <A HREF="FONTS.html"><tt>FONTS</tt></A> file describes how to use 
++the supplied scripts to handle such cases easily. It also discusses
++the installation of the fonts for a few widespread programs.
++<p>
++
++<H4>
++Other utilities
++</H4>
++<!
++---------------
++>
++
++A few other small interesting programs that allow a cloase look at
++the fonts are located in the subdirectory '<tt>other</tt>'. They
++are described shortly in <A HREF="other/README.html">others/README</a>.
++<p>
++
++<H4>
++Optional packages
++</H4>
++<!
++-----------------
++>
++
++Some auxiliary files are not needed by everyone and are big enough that
++moving them to a separate package speeds up the downloads of the main
++package significantly. As of now we have one such optional package:
++<p>
++
++&nbsp;&nbsp;<b>ttf2pt1-chinese</b> - contains the Chinese conversion maps
++<p>
++
++The general versioning policy for the optional packages is the following:
++These packages may have no direct dependency on the ttf2pt1 version.
++But they may be updated in future, as well as some versions of optional
++packages may have dependencies on certain versions of ttf2pt1.
++To avoid unneccessary extra releases on one hand and keep the updates in 
++sync with the ttf2pt1 itself on the other hand, a new version of an optional 
++package will be released only if there are any changes to it and it will be 
++given the same version number as ttf2pt1 released at the same time. So not 
++every release of ttf2pt1 would have a corresponding release of all optional 
++packages. For example, to get the correct version of optional packages for an 
++imaginary release 8.3.4 of ttf2pt1 you would need to look for optional 
++packages of the highest version not higher than (but possibly equal to) 8.3.4.
++<p>
++
++<H4>
++TO DO:
++</H4>
++<!
++------
++>
++
++<ul>
++<li> Improve hinting.
++<li> Improve the auto-tracing of bitmaps.
++<li> Implement the family-level hints.
++<li> Add generation of CID-fonts.
++<li> Handle the composite glyphs with relative base points.
++<li> Preserve the relative width of stems during scaling to 1000x1000 matrix.
++<li> Add support for bitmap TTF fonts.
++<li> Implement better support of Asian encodings.
++<li> Implement automatic creation of ligatures.
++</ul>
++
++<H4>
++TROUBLESHOOTING AND BUG REPORTS
++</H4>
++<!
++-------------------------------
++>
++<!-- =section t1 BUGS -->
++<!-- ==head2 Troubleshooting and bug reports -->
++
++Have problems with conversion of some font ? The converter dumps core ? Or your
++printer refuses to understand the converted fonts ? Or some characters are 
++missing ? Or some characters look strange ?
++<p>
++
++Send the bug reports to the ttf2pt1 development mailing list at
++<A HREF="mailto:ttf2pt1-devel@lists.sourceforge.net">ttf2pt1-devel@lists.sourceforge.net</A>.
++<p>
++
++Try to collect more information about the problem and include it into
++the bug report. (Of course, even better if you would provide a ready
++fix, but just a detailed bug report is also good). Provide detailed
++information about your problem, this will speed up the response greatly.
++Don't just write "this font looks strange after conversion" but describe
++what's exactly wrong with it: for example, what characters look wrong
++and what exactly is wrong about their look. Providing a link to the
++original font file would be also a good idea. Try to do a little
++troublehooting and report its result. This not only would help with
++the fix but may also give you a temporary work-around for the bug.
++<p>
++
++First, enable full warnings with option '<b>-W99</b>', save them to
++a file and read carefully. Sometimes the prolem is with a not implemented
++feature which is reported in the warnings. Still, reporting about such
++problems may be a good idea: some features were missed to cut corners,
++in hope that no real font is using them. So a report about a font using
++such a feature may motivate someone to implement it. Of course, you
++may be the most motivated person: after all, you are the one wishing
++to convert that font. ;-) Seriously, the philosophy "scrath your own itch"
++seems to be the strongest moving force behind the Open Source software.
++<p>
++
++The next step is playing with the options. This serves a dual purpose:
++on one hand, it helps to localize the bug, on the other hand you may be
++able to get a working version of the font for the meantime while the
++bug is being fixed. The typical options to try out are: first '<b>-Ou</b>', if
++it does not help then '<b>-Os</b>', then '<b>-Oh</b>', then '<b>-Oo</b>'.
++They are described in a bit more detail above. Try them one by one
++and in combinations. See if with them the resulting fonts look better.
++<p>
++
++On some fonts ttf2pt1 just crashes. Commonly that happens because the
++font being converted is highly defective (although sometimes the bug
++is in ttf2pt1 itself). In any case it should not crash, so the reports
++about such cases will help to handle these defects properly in future.
++<p>
++
++We try to respond to the bug reports in a timely fashion but alas, this 
++may not always be possible, especially if the problem is complex.
++This is a volunteer project and its resources are limited. Because
++of this we would appreciate bug reports as detailed as possible,
++and we would appreciate the ready fixes and contributions even more.
++<p>
++<!-- =stop -->
++<!-- =section t1 FILES -->
++<!-- ==over 2 -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_LIBXDIR/t1asm -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/scripts/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/other/* -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/README -->
++<!-- ==item * -->
++<!-- =text TTF2PT1_SHAREDIR/FONTS -->
++<!-- ==back -->
++<!-- =stop -->
++
++<H4>
++CONTACTS
++</H4>
++<!
++--------
++>
++<!-- =section t1 SEE ALSO -->
++<!-- ==over 4 -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1_convert(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;ttf2pt1_x2gs(1)&gt; -->
++<!-- ==item * -->
++<!-- =text L&lt;t1asm(1)&gt; -->
++
++<!-- ==item * -->
++<A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce">
++ttf2pt1-announce@lists.sourceforge.net
++</A><br>
++  The mailing list with announcements about ttf2pt1. It is a moderated mailing
++  with extremely low traffic. Everyone is encouraged to subscribe to keep in 
++  touch with the current status of project. To subscribe use the Web interface
++  at <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce</A>.
++  If you have only e-mail access to the Net then send a subscribe request to 
++  the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
++  will help you with subscription.
++<p>
++
++<!-- ==item * -->
++<A HREF="mailto:ttf2pt1-devel@lists.sourceforge.net">
++ttf2pt1-devel@lists.sourceforge.net
++</A><br>
++<A HREF="mailto:ttf2pt1-users@lists.sourceforge.net">
++ttf2pt1-users@lists.sourceforge.net
++</A><br>
++  The ttf2pt1 mailing lists for development and users issues. They have not
++  that much traffic either. To subscribe use the Web interface at
++  <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel</A>
++  and <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users</A>.
++  If you have only e-mail access to the Net then send a subscribe request to 
++  the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
++  will help you with subscription.
++<p>
++
++<!-- =stop -->
++<A HREF="mailto:mheath@netspace.net.au">
++mheath@netspace.net.au
++</A><br>
++  Mark Heath
++<p>
++
++<A HREF="mailto:A.Weeks@mcc.ac.uk">
++A.Weeks@mcc.ac.uk
++</A><br>
++  Andrew Weeks
++<p>
++
++<A HREF="mailto:babkin@users.sourceforge.net">
++babkin@users.sourceforge.net</A> (preferred)<br>
++<A HREF="mailto:sab123@hotmail.com">
++sab123@hotmail.com
++</A><br>
++<A HREF="http://members.bellatlantic.net/~babkin">
++http://members.bellatlantic.net/~babkin
++</A><br>
++  Sergey Babkin
++<p>
++
++<H4>
++SEE ALSO
++</H4>
++<!
++--------
++>
++
++<!-- =section t1 SEE ALSO -->
++<!-- ==item * -->
++<A HREF="http://ttf2pt1.sourceforge.net">
++http://ttf2pt1.sourceforge.net
++</A><br>
++  The main page of the project.
++<p>
++
++<A HREF="http://www.netspace.net.au/~mheath/ttf2pt1/">
++http://www.netspace.net.au/~mheath/ttf2pt1/
++</A><br>
++  The old main page of the project.
++<p>
++<!-- ==back -->
++<!-- =stop -->
++
++<A HREF="http://sourceforge.net/projects/gnuwin32">
++http://sourceforge.net/projects/gnuwin32
++</A><br>
++  Precompiled binaries for Windows.
++<p>
++
++<A HREF="http://www.lcdf.org/~eddietwo/type/">
++http://www.lcdf.org/~eddietwo/type/
++</a><br>
++  The home page of the Type 1 utilities package.
++<p>
++
++<A HREF="http://www.rightbrain.com/pages/books.html">
++http://www.rightbrain.com/pages/books.html
++</a><br>
++  The first book about PostScript on the Web, "Thinking in PostScript".
++<p>
++
++<A HREF="http://fonts.apple.com/TTRefMan/index.html">
++http://fonts.apple.com/TTRefMan/index.html
++</a><br>
++  The True Type reference manual.
++<p>
++
++<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
++http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf
++</a><br>
++  Adobe PostScript reference manual.
++<p>
++
++<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF">
++http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF
++</a><br>
++  Specification of the Type 1 font format.
++<p>
++
++<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5015.Type1_Supp.pdf">
++http://partners.adobe.com/asn/developer/PDFS/TN/5015.Type1_Supp.pdf
++</a><br>
++  The Type 1 font format supplement.
++<p>
++
++<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5004.AFM_Spec.pdf">
++http://partners.adobe.com/asn/developer/PDFS/TN/5004.AFM_Spec.pdf
++</A><BR>
++  Specification of the Adobe font metrics file format.
++<p>
++
++<A HREF="http://www.cs.wpi.edu/~matt/courses/cs563/talks/surface/bez_surf.html">
++http://www.cs.wpi.edu/~matt/courses/cs563/talks/surface/bez_surf.html
++</A><BR>
++<A HREF="http://www.cs.wpi.edu/~matt/courses/cs563/talks/curves.html">
++http://www.cs.wpi.edu/~matt/courses/cs563/talks/curves.html
++</A><BR>
++  Information about the Bezier curves.
++<p>
++
++<A HREF="http://www.neuroinformatik.ruhr-uni-bochum.de/ini/PEOPLE/rmz/t1lib/t1lib.html">
++http://www.neuroinformatik.ruhr-uni-bochum.de/ini/PEOPLE/rmz/t1lib/t1lib.html
++</A><br>
++  A stand-alone library supporting the Type1 fonts. Is neccessary
++  to compile the programs <tt>other/cmpf</tt> and <tt>other/dmpf</tt>.
++<p>
++
++<A HREF="http://www.freetype.org">
++http://www.freetype.org
++</A><br>
++  A library supporting the TTF fonts. Also many useful TTF programs
++  are included with it.
++<p>
++
++<A HREF="http://heliotrope.homestead.com/files/printsoft.html">
++http://heliotrope.homestead.com/files/printsoft.html
++</A><br>
++  Moses Gold's collection of links to printing software.
++<p>
++
++<A HREF="http://linuxartist.org/fonts/">
++http://linuxartist.org/fonts/
++</A><br>
++  Collection of font-related links.
++<p>
++
++<HR>
++<HR>
++<!
++----------------------------------------------------------------------
++----------------------------------------------------------------------
++>
++
++Following is the Readme of <tt>ttf2pfa</tt> (true type to type 3 font converter) It 
++covers other issues regarding the use of this software. Please note that
++although <tt>ttf2pfa</tt> is a public domain software, <tt>ttf2pt1</tt>
++is instead covered by an Open Source license. See the <tt>COPYRIGHT</tt>
++file for details.
++<p>
++
++Please note also that <tt>ttf2pfa</tt> has not been maintained for a long time.
++All of its functionality has been integrated into <tt>ttf2pt1</tt> and all the
++development moved to <tt>ttf2pt1</tt>, including Andrew Weeks, the author of
++<tt>ttf2pfa</tt>. <tt>Ttf2pfa</tt> is provided for historical reasons only. Please use
++<tt>ttf2pt1</tt> instead.
++
++<HR>
++<!
++----------------------------------------------------------------------
++>
++
++<H3>
++True Type to Postscript Font converter
++</H3>
++<!
++--------------------------------------
++>
++
++My mind is still reeling from the discovery that I was able to write
++this program. What it does is it reads a Microsoft TrueType font and
++creates a Postscript font. '<I>_A_</I> postscript font', that is, not necessarily
++the same font, you understand, but a fair imitation.
++<p>
++
++Run it like this:
++<p>
++
++<blockquote><tt>
++	ttf2pfa fontfile.ttf fontname
++</tt></blockquote>
++<p>
++
++The first parameter is the truetype filename, the second is a stem for
++the output file names. The program will create a <tt>fontname.pfa</tt> containing
++the Postscript font and a <tt>fontname.afm</tt> containing the metrics.
++<p>
++
++The motivation behind this is that in Linux if you do not have a
++Postscript printer, but only some other printer, you can only print
++Postscript by using Ghostscript. But the fonts that come with
++Ghostscript are very poor (they are converted from bitmaps and look
++rather lumpy). This is rather frustrating as the PC running Linux
++probably has MS-Windows as well and will therefore have truetype fonts,
++but which are quite useless with Linux, X or Ghostscript.
++<p>
++
++The program has been tested on over a hundred different TrueType fonts
++from various sources, and seems to work fairly well. The converted
++characters look OK, and the program doesn't seem to crash any more. I'm
++not sure about the AFM files though, as I have no means to test them.
++<p>
++
++The fonts generated will not work with X, as the font rasterizer that
++comes with X only copes with Type 1 fonts. If I have the time I may
++modify ttf2pfa to generate Type 1s.
++<p>
++
++<H4>
++Copyright issues
++</H4>
++<!
++----------------
++>
++
++I am putting this program into the public domain, so don't bother
++sending me any money, I'd only have to declare it for income tax.
++<p>
++
++Copyright on fonts, however, is a difficult legal question. Any
++copyright statements found in a font will be preserved in the output.
++Whether you are entitled to translate them at all I don't know.
++<p>
++
++If you have a license to run a software package, like say MS-Windows, on
++your PC, then you probably have a right to use any part of it, including
++fonts, on that PC, even if not using that package for its intended
++purpose.
++<p>
++
++I am not a lawyer, however, so this is not a legal opinion, and may be
++garbage.
++<p>
++
++There shouldn't be a any problem with public domain fonts.
++<p>
++
++<H4>
++About the Program
++</H4>
++<!
++-----------------
++>
++
++It was written in C on a IBM PC running Linux.
++<p>
++
++The TrueType format was originally developed by Apple for the MAC, which
++has opposite endianness to the PC, so to ensure compatibility 16 and 32
++bit fields are the wrong way round from the PC's point of view. This is
++the reason for all the 'ntohs' and 'ntohl' calls. Doing it this way
++means the program will also work on big-endian machines like Suns.
++<p>
++
++I doubt whether it will work on a DOS-based PC though.
++<p>
++
++The program produces what technically are Type 3 rather than Type 1
++fonts. They are not compressed or encrypted and are plain text. This is
++so I (and you) can see what's going on, and (if you're a Postscript guru
++and really want to) can alter the outlines.
++<p>
++
++I only translate the outlines, not the 'instructions' that come with
++them. This latter task is probably virtually impossible anyway. TrueType
++outlines are B-splines rather than the Bezier curves that Postscript
++uses. I believe that my conversion algorithm is reasonably correct, if
++nothing else because the characters look right.
++<p>
++
++<H4>
++Problems that may occur
++</H4>
++<!
++-----------------------
++>
++
++Most seriously, very complex characters (with lots of outline segments)
++can make Ghostscript releases 2.x.x fail with a 'limitcheck' error. It
++is possible that this may happen with some older Postscript printers as
++well. Such characters will be flagged by the program and there are
++basically two things you can do. First is to edit the <tt>.pfa</tt> file to
++simplify or remove the offending character. This is not really
++recommended. The second is to use Ghostscript release 3, if you can get
++it. This has much larger limits and does not seem to have any problems
++with complex characters.
++<p>
++
++Then there are buggy fonts (yes, a font can have bugs). I try to deal
++with these in as sane a manner as possible, but it's not always
++possible.
++<p>
++
++<H4>
++Encodings
++</H4>
++<!
++---------
++>
++
++A postscript font must have a 256 element array, called an encoding,
++each element of which is a name, which is also the name of a procedure
++contained within the font. The 'BuildChar' command takes a byte and uses
++it to index the encoding array to find a character name, and then looks
++that up in the font's procedure table find the commands to draw the
++glyph. However, not all characters need be in the encoding array. Those
++that are not cannot be drawn (at least not using 'show'), however it is
++possible to 're-encode' the font to enable these characters. There are
++several standard encodings: Adobe's original, ISO-Latin1 and Symbol
++being the most commonly encountered.
++<p>
++
++TrueType fonts are organised differently. As well as the glyph
++descriptions there are a number of tables. One of these is a mapping
++from a character set into the glyph array, and another is a mapping from
++the glyph array into a set of Postscript character names. The problems
++are:
++<p>
++	1)	Microsoft uses Unicode, a 16-bit system, to encode the font.
++<br>
++	2)	that more than one glyph is given the same Postscript name.
++<p>
++
++I deal with (1) by assuming a Latin1 encoding. The MS-Windows and
++Unicode character sets are both supersets of ISO-8859-1. This usually
++means that most characters will be properly encoded, but you should be
++warned that some software may assume that fonts have an Adobe encoding.
++Symbol, or Dingbat, fonts are in fact less of a problem, as they have
++private encodings starting at 0xF000. It is easy to just lose the top
++byte.
++<p>
++
++Postscript fonts can be re-encoded, either manually, or by software.
++Groff, for example, generates postscript that re-encodes fonts with the
++Adobe encoding. The problem here is that not all characters in the Adobe
++set are in the MS-Windows set. In particular there are no fi and fl
++ligatures. This means that conversions of the versions of
++Times-New-Roman and Arial that come with MS-Windows cannot be used
++blindly as replacements for Adobe Times-Roman and Helvetica. You can get
++expanded versions of MS fonts from Microsoft's web site which do contain
++these ligatures (and a lot else besides).
++<p>
++
++I deal with (2) by creating new character names. This can be error-prone
++because I do not know which of them is the correct glyph to give the
++name to. Some (buggy) fonts have large numbers of blank glyphs, all with
++the same name.
++<p>
++
++(almost every TrueType font has three glyphs called <tt>.notdef</tt>, one of them
++is usually an empty square shape, one has no outline and has zero width,
++and one has no outline and a positive width. This example is not really
++a problem with well formed fonts since the <tt>.notdef</tt> characters are only
++used for unprintable characters, which shouldn't occur in your documents
++anyway).
++<p>
++</BODY>
++</HTML>
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/runt1asm.c xserver/hw/xprint/extras/ttf2pt1/runt1asm.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/runt1asm.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/runt1asm.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,61 @@
++/*
++ * Wrap-around code to either compile in t1asm or call it externally
++ *
++ * Copyright (C) 2000 by Sergey Babkin
++ * Copyright (C) 2000 by The TTF2PT1 Project
++ *
++ * See COPYRIGHT for full license
++ */
++
++#ifdef EXTERNAL_T1ASM
++
++#include <stdio.h>
++#include <errno.h>
++
++FILE *ifp;
++FILE *ofp;
++
++int 
++runt1asm(
++	int pfbflag
++)
++{
++	char *cmd;
++	int id, od;
++	int error;
++
++	/* first make a copy in case some of then is already stdin/stdout */
++	if(( id = dup(fileno(ifp)) )<0) {
++		perror("** Re-opening input file for t1asm");
++		exit(1);
++	}
++	if(( od = dup(fileno(ofp)) )<0) {
++		perror("** Re-opening output file for t1asm");
++		exit(1);
++	}
++	fclose(ifp); fclose(ofp);
++	close(0);
++	if(( dup(id) )!=0) {
++		perror("** Re-directing input file for t1asm");
++		exit(1);
++	}
++	close(1);
++	if(( dup(od) )!=1) {
++		perror("** Re-directing output file for t1asm");
++		exit(1);
++	}
++	close(id); close(od);
++
++	if(pfbflag)
++		error = execlp("t1asm", "t1asm", "-b", NULL);
++	else
++		error = execlp("t1asm", "t1asm", NULL);
++
++	perror("** Calling t1asm");
++	
++	exit(1);
++}
++
++#else
++#	include "t1asm.c"
++#endif
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/t1asm.c xserver/hw/xprint/extras/ttf2pt1/t1asm.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/t1asm.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/t1asm.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,606 @@
++/* t1asm
++ *
++ * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript
++ * form into either PFB or PFA format.  The human readable/editable input is
++ * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font
++ * Format' version 1.1 (the `black book').  There is a companion program,
++ * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript
++ * file.
++ *
++ * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.
++ *
++ * Permission is hereby granted to use, modify, and distribute this program
++ * for any purpose provided this copyright notice and the one below remain
++ * intact.
++ *
++ * I. Lee Hetherington (ilh@lcs.mit.edu)
++ *
++ * Revision 1.2  92/05/22  11:54:45  ilh
++ * Fixed bug where integers larger than 32000 could not be encoded in
++ * charstrings.  Now integer range is correct for four-byte
++ * twos-complement integers: -(1<<31) <= i <= (1<<31)-1.  Bug detected by
++ * Piet Tutelaers (rcpt@urc.tue.nl).
++ *
++ * Revision 1.1  92/05/22  11:48:46  ilh
++ * initial version
++ *
++ * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by
++ * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code
++ * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS
++ * ... #endif, where _MSDOS is an identifier, which is automatically
++ * defined, if you compile with the Microsoft C/C++ Compiler.
++ *
++ */
++
++#ifndef lint
++static char copyright[] =
++  "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved.";
++#ifdef _MSDOS
++static char portnotice[] =
++  "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de).";
++#endif
++#endif
++
++/* Note: this is ANSI C. */
++
++#ifdef _MSDOS
++  #include <fcntl.h>
++  #include <getopt.h>
++  #include <io.h>
++#endif
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <limits.h>
++
++#ifdef WINDOWS
++#	ifdef STANDALONE
++#		define WINDOWS_FUNCTIONS
++#		include "windows.h"
++#	endif
++#endif
++
++/* int32 must be at least 32-bit and uint16 must be at least 16-bit */
++#ifndef AIXV3
++#if INT_MAX >= 0x7FFFFFFFUL
++typedef int int32;
++#else
++typedef long int32;
++#endif
++#endif /* !AIXV3 */
++#if USHRT_MAX >= 0xFFFFUL
++typedef unsigned short uint16;
++#else
++typedef unsigned int uint16;
++#endif
++
++#define LINESIZE 256
++
++#define MAXBLOCKLEN ((1L<<17)-6)
++#define MINBLOCKLEN ((1L<<8)-6)
++
++#define MARKER   128
++#define ASCII    1
++#define BINARY   2
++#define DONE     3
++
++typedef unsigned char byte;
++
++/* must be visible from outside */
++FILE *ifp;
++FILE *ofp;
++
++/* flags */
++static int pfb = 0;
++static int active = 0;
++static int start_charstring = 0;
++static int in_eexec = 0;
++
++static char line[LINESIZE];
++
++/* lenIV and charstring start command */
++static int lenIV = 4;
++static char cs_start[10];
++
++/* for charstring buffering */
++static byte charstring_buf[65535];
++static byte *charstring_bp;
++
++/* for PFB block buffering */
++static byte blockbuf[MAXBLOCKLEN];
++static int32 blocklen = MAXBLOCKLEN;
++static int32 blockpos = -1;
++static int blocktyp = ASCII;
++
++/* decryption stuff */
++static uint16 er, cr;
++static uint16 c1 = 52845, c2 = 22719;
++
++/* table of charstring commands */
++static struct command {
++  char *name;
++  int one, two;
++} command_table[] = {
++  { "callothersubr", 12, 16 },
++  { "callsubr", 10, -1 },
++  { "closepath", 9, -1 },
++  { "div", 12, 12 },
++  { "dotsection", 12, 0 },
++  { "endchar", 14, -1 },
++  { "hlineto", 6, -1 },
++  { "hmoveto", 22, -1 },
++  { "hsbw", 13, -1 },
++  { "hstem", 1, -1 },
++  { "hstem3", 12, 2 },
++  { "hvcurveto", 31, -1 },
++  { "pop", 12, 17 },
++  { "return", 11, -1 },
++  { "rlineto", 5, -1 },
++  { "rmoveto", 21, -1 },
++  { "rrcurveto", 8, -1 },
++  { "sbw", 12, 7 },
++  { "seac", 12, 6 },
++  { "setcurrentpoint", 12, 33 },
++  { "vhcurveto", 30, -1 },
++  { "vlineto", 7, -1 },
++  { "vmoveto", 4, -1 },
++  { "vstem", 3, -1 },
++  { "vstem3", 12, 1 },
++};                                                /* alphabetical */
++
++/* Two separate encryption functions because eexec and charstring encryption
++   must proceed in parallel. */
++
++static byte eencrypt(byte plain)
++{
++  byte cipher;
++
++  cipher = (byte) (plain ^ (er >> 8));
++  er = (uint16) ((cipher + er) * c1 + c2);
++  return cipher;
++}
++
++static byte cencrypt(byte plain)
++{
++  byte cipher;
++
++  cipher = (byte) (plain ^ (cr >> 8));
++  cr = (uint16) ((cipher + cr) * c1 + c2);
++  return cipher;
++}
++
++/* This function flushes a buffered PFB block. */
++
++static void output_block()
++{
++  int32 i;
++
++  /* output four-byte block length */
++  fputc((int) (blockpos & 0xff), ofp);
++  fputc((int) ((blockpos >> 8) & 0xff), ofp);
++  fputc((int) ((blockpos >> 16) & 0xff), ofp);
++  fputc((int) ((blockpos >> 24) & 0xff), ofp);
++
++  /* output block data */
++  for (i = 0; i < blockpos; i++)
++    fputc(blockbuf[i], ofp);
++
++  /* mark block buffer empty and uninitialized */
++  blockpos =  -1;
++}
++
++/* This function outputs a single byte.  If output is in PFB format then output
++   is buffered through blockbuf[].  If output is in PFA format, then output
++   will be hexadecimal if in_eexec is set, ASCII otherwise. */
++
++static void output_byte(byte b)
++{
++  static char *hexchar = "0123456789ABCDEF";
++  static int hexcol = 0;
++
++  if (pfb) {
++    /* PFB */
++    if (blockpos < 0) {
++      fputc(MARKER, ofp);
++      fputc(blocktyp, ofp);
++      blockpos = 0;
++    }
++    blockbuf[blockpos++] = b;
++    if (blockpos == blocklen)
++      output_block();
++  } else {
++    /* PFA */
++    if (in_eexec) {
++      /* trim hexadecimal lines to 64 columns */
++      if (hexcol >= 64) {
++        fputc('\n', ofp);
++        hexcol = 0;
++      }
++      fputc(hexchar[(b >> 4) & 0xf], ofp);
++      fputc(hexchar[b & 0xf], ofp);
++      hexcol += 2;
++    } else {
++      fputc(b, ofp);
++    }
++  }
++}
++
++/* This function outputs a byte through possible eexec encryption. */
++
++static void eexec_byte(byte b)
++{
++  if (in_eexec)
++    output_byte(eencrypt(b));
++  else
++    output_byte(b);
++}
++
++/* This function outputs a null-terminated string through possible eexec
++   encryption. */
++
++static void eexec_string(char *string)
++{
++  while (*string)
++    eexec_byte((byte) *string++);
++}
++
++/* This function gets ready for the eexec-encrypted data.  If output is in
++   PFB format then flush current ASCII block and get ready for binary block.
++   We start encryption with four random (zero) bytes. */
++
++static void eexec_start()
++{
++  eexec_string(line);
++  if (pfb) {
++    output_block();
++    blocktyp = BINARY;
++  }
++
++  in_eexec = 1;
++  er = 55665;
++  eexec_byte(0);
++  eexec_byte(0);
++  eexec_byte(0);
++  eexec_byte(0);
++}
++
++/* This function wraps-up the eexec-encrypted data.
++   If output is in PFB format then this entails flushing binary block and
++   starting an ASCII block. */
++
++static void eexec_end()
++{
++  int i, j;
++
++  if (pfb) {
++    output_block();
++    blocktyp = ASCII;
++  } else {
++    fputc('\n', ofp);
++  }
++  in_eexec = 0;
++  for (i = 0; i < 8; i++) {
++    for (j = 0; j < 64; j++)
++      eexec_byte('0');
++    eexec_byte('\n');
++  }
++#if 0
++  eexec_string("cleartomark\n");
++#endif
++}
++
++/* This function writes ASCII trailer.
++   If output is in PFB format then this entails flushing binary block and
++   starting an ASCII block. */
++
++static void file_end()
++{
++  if (pfb) {
++    output_block();
++    fputc(MARKER, ofp);
++    fputc(DONE, ofp);
++  }
++}
++/* This function returns an input line of characters.  A line is terminated by
++   length (including terminating null) greater than LINESIZE, a newline \n, or
++   when active (looking for charstrings) by '{'.  When terminated by a newline
++   the newline is put into line[].  When terminated by '{', the '{' is not put
++   into line[], and the flag start_charstring is set to 1. */
++
++static void t1asm_getline()
++{
++  int c;
++  char *p = line;
++  int comment = 0;
++
++  start_charstring = 0;
++  while (p < line + LINESIZE) {
++    c = fgetc(ifp);
++    if (c == EOF)
++      break;
++    if (c == '%')
++      comment = 1;
++    if (active && !comment && c == '{') {
++      start_charstring = 1;
++      break;
++    }
++    *p++ = (char) c;
++    if (c == '\n')
++      break;
++  }
++  *p = '\0';
++}
++
++/* This function is used by the binary search, bsearch(), for command names in
++   the command table. */
++
++static int command_compare(const void *key, const void *item)
++{
++  return strcmp((char *) key, ((struct command *) item)->name);
++}
++
++/* This function returns 1 if the string is an integer and 0 otherwise. */
++
++static int is_integer(char *string)
++{
++  if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') {
++    while (*++string && isdigit(*string))
++      ;                                           /* deliberately empty */
++    if (!*string)
++      return 1;
++  }
++  return 0;
++}
++
++/* This function initializes charstring encryption.  Note that this is called
++   at the beginning of every charstring. */
++
++static void charstring_start()
++{
++  int i;
++
++  charstring_bp = charstring_buf;
++  cr = 4330;
++  for (i = 0; i < lenIV; i++)
++    *charstring_bp++ = cencrypt((byte) 0);
++}
++
++/* This function encrypts and buffers a single byte of charstring data. */
++
++static void charstring_byte(int v)
++{
++  byte b = (byte) (v & 0xff);
++
++  if (charstring_bp - charstring_buf > sizeof(charstring_buf)) {
++    fprintf(stderr, "error: charstring_buf full (%d bytes)\n",
++            sizeof(charstring_buf));
++    exit(1);
++  }
++  *charstring_bp++ = cencrypt(b);
++}
++
++/* This function outputs buffered, encrypted charstring data through possible
++   eexec encryption. */
++
++static void charstring_end()
++{
++  byte *bp;
++
++  sprintf(line, "%d ", charstring_bp - charstring_buf);
++  eexec_string(line);
++  sprintf(line, "%s ", cs_start);
++  eexec_string(line);
++  for (bp = charstring_buf; bp < charstring_bp; bp++)
++    eexec_byte(*bp);
++}
++
++/* This function generates the charstring representation of an integer. */
++
++static void charstring_int(int num)
++{
++  int x;
++
++  if (num >= -107 && num <= 107) {
++    charstring_byte(num + 139);
++  } else if (num >= 108 && num <= 1131) {
++    x = num - 108;
++    charstring_byte(x / 256 + 247);
++    charstring_byte(x % 256);
++  } else if (num >= -1131 && num <= -108) {
++    x = abs(num) - 108;
++    charstring_byte(x / 256 + 251);
++    charstring_byte(x % 256);
++  } else if (num >= (-2147483647-1) && num <= 2147483647) {
++    charstring_byte(255);
++    charstring_byte(num >> 24);
++    charstring_byte(num >> 16);
++    charstring_byte(num >> 8);
++    charstring_byte(num);
++  } else {
++    fprintf(stderr,
++            "error: cannot format the integer %d, too large\n", num);
++    exit(1);
++  }
++}
++
++/* This function parses an entire charstring into integers and commands,
++   outputting bytes through the charstring buffer. */
++
++static void parse_charstring()
++{
++  struct command *cp;
++
++  charstring_start();
++  while (fscanf(ifp, "%s", line) == 1) {
++    if (line[0] == '%') {
++      /* eat comment to end of line */
++      while (fgetc(ifp) != '\n' && !feof(ifp))
++        ;                                         /* deliberately empty */
++      continue;
++    }
++    if (line[0] == '}')
++      break;
++    if (is_integer(line)) {
++      charstring_int(atoi(line));
++    } else {
++      cp = (struct command *)
++        bsearch((void *) line, (void *) command_table,
++                sizeof(command_table) / sizeof(struct command),
++                sizeof(struct command),
++                command_compare);
++      if (cp) {
++        charstring_byte(cp->one);
++        if (cp->two >= 0)
++          charstring_byte(cp->two);
++      } else {
++        fprintf(stderr, "error: cannot use `%s' in charstring\n",line);
++        exit(1);
++      }
++    }
++  }
++  charstring_end();
++}
++
++static void usage()
++{
++  fprintf(stderr,
++          "usage: t1asm [-b] [-l block-length] [input [output]]\n");
++  fprintf(stderr,
++          "\n-b means output in PFB format, otherwise PFA format.\n");
++  fprintf(stderr,
++          "The block length applies to the length of blocks in the\n");
++  fprintf(stderr,
++          "PFB output file; the default is to use the largest possible.\n");
++  exit(1);
++}
++
++static void print_banner()
++{
++  static char rcs_revision[] = ""; /* removed RCS */
++  static char revision[20];
++
++  if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1)
++    revision[0] = '\0';
++  fprintf(stderr, "This is t1asm %s.\n", revision);
++}
++
++#ifdef STANDALONE
++int main(int argc, char **argv)
++{
++  char *p, *q, *r;
++  int c;
++
++  extern char *optarg;
++  extern int optind;
++
++  ifp = stdin;
++  ofp = stdout;
++
++  print_banner();
++
++  /* interpret command line arguments using getopt */
++  while ((c = getopt(argc, argv, "bl:")) != -1)
++    switch (c) {
++    case 'b':
++      pfb = 1;
++      break;
++    case 'l':
++      blocklen = atoi(optarg);
++      if (blocklen < MINBLOCKLEN) {
++        blocklen = MINBLOCKLEN;
++        fprintf(stderr,
++                "warning: using minimum block length of %d\n",
++                blocklen);
++      } else if (blocklen > MAXBLOCKLEN) {
++        blocklen = MAXBLOCKLEN;
++        fprintf(stderr,
++                "warning: using maximum block length of %d\n",
++                blocklen);
++      }
++      break;
++    default:
++      usage();
++      break;
++    }
++  if (argc - optind > 2)
++    usage();
++
++  /* possibly open input & output files */
++  if (argc - optind >= 1) {
++    ifp = fopen(argv[optind], "r");
++    if (!ifp) {
++      fprintf(stderr, "error: cannot open %s for reading\n", argv[1]);
++      exit(1);
++    }
++  }
++  if (argc - optind >= 2) {
++    ofp = fopen(argv[optind + 1], "w");
++    if (!ofp) {
++      fprintf(stderr, "error: cannot open %s for writing\n", argv[2]);
++      exit(1);
++    }
++  }
++
++#else
++int runt1asm(int pfbflag)
++{
++  char *p, *q, *r;
++
++  pfb = pfbflag;
++#endif
++
++  #ifdef _MSDOS
++    /* If we are processing a PFB (binary) output */
++    /* file, we must set its file mode to binary. */
++    if (pfb)
++      _setmode(_fileno(ofp), _O_BINARY);
++  #endif
++
++  /* Finally, we loop until no more input.  Some special things to look for
++     are the `currentfile eexec' line, the beginning of the `/Subrs'
++     definition, the definition of `/lenIV', and the definition of the
++     charstring start command which has `...string currentfile...' in it. */
++
++  while (!feof(ifp) && !ferror(ifp)) {
++    t1asm_getline();
++    if (strcmp(line, "currentfile eexec\n") == 0) {
++      eexec_start();
++      continue;
++    } else if (strstr(line, "/Subrs") && isspace(line[6])) {
++      active = 1;
++    } else if ((p = strstr(line, "/lenIV"))) {
++      sscanf(p, "%*s %d", &lenIV);
++    } else if ((p = strstr(line, "string currentfile"))) {
++      /* locate the name of the charstring start command */
++      *p = '\0';                                  /* damage line[] */
++      q = strrchr(line, '/');
++      if (q) {
++        r = cs_start;
++        ++q;
++        while (!isspace(*q) && *q != '{')
++          *r++ = *q++;
++        *r = '\0';
++      }
++      *p = 's';                                   /* repair line[] */
++    }
++    /* output line data */
++    eexec_string(line);
++	if ((p = strstr(line, "currentfile closefile"))) {
++		eexec_end();
++	}
++    if (start_charstring) {
++      if (!cs_start[0]) {
++        fprintf(stderr, "error: couldn't find charstring start command\n");
++        exit(1);
++      }
++      parse_charstring();
++    }
++  }
++  file_end();
++
++  fclose(ifp);
++  fclose(ofp);
++
++  return 0;
++}
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1.1 xserver/hw/xprint/extras/ttf2pt1/ttf2pt1.1
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1.1	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf2pt1.1	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,828 @@
++.rn '' }`
++''' $RCSfile$$Revision$$Date$
++'''
++''' $Log$
++''' Revision 1.1.4.1  2004/04/21 10:03:13  gisburn
++''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT
++'''
++''' Revision 1.1  2003/06/04 00:33:54  roland
++''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ...
++'''
++'''
++.de Sh
++.br
++.if t .Sp
++.ne 5
++.PP
++\fB\\$1\fR
++.PP
++..
++.de Sp
++.if t .sp .5v
++.if n .sp
++..
++.de Ip
++.br
++.ie \\n(.$>=3 .ne \\$3
++.el .ne 3
++.IP "\\$1" \\$2
++..
++.de Vb
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve
++.ft R
++
++.fi
++..
++'''
++'''
++'''     Set up \*(-- to give an unbreakable dash;
++'''     string Tr holds user defined translation string.
++'''     Bell System Logo is used as a dummy character.
++'''
++.tr \(*W-|\(bv\*(Tr
++.ie n \{\
++.ds -- \(*W-
++.ds PI pi
++.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
++.ds L" ""
++.ds R" ""
++'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
++'''   \*(L" and \*(R", except that they are used on ".xx" lines,
++'''   such as .IP and .SH, which do another additional levels of
++'''   double-quote interpretation
++.ds M" """
++.ds S" """
++.ds N" """""
++.ds T" """""
++.ds L' '
++.ds R' '
++.ds M' '
++.ds S' '
++.ds N' '
++.ds T' '
++'br\}
++.el\{\
++.ds -- \(em\|
++.tr \*(Tr
++.ds L" ``
++.ds R" ''
++.ds M" ``
++.ds S" ''
++.ds N" ``
++.ds T" ''
++.ds L' `
++.ds R' '
++.ds M' `
++.ds S' '
++.ds N' `
++.ds T' '
++.ds PI \(*p
++'br\}
++.\"	If the F register is turned on, we'll generate
++.\"	index entries out stderr for the following things:
++.\"		TH	Title 
++.\"		SH	Header
++.\"		Sh	Subsection 
++.\"		Ip	Item
++.\"		X<>	Xref  (embedded
++.\"	Of course, you have to process the output yourself
++.\"	in some meaninful fashion.
++.if \nF \{
++.de IX
++.tm Index:\\$1\t\\n%\t"\\$2"
++..
++.nr % 0
++.rr F
++.\}
++.TH TTF2PT1 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter"
++.UC
++.if n .hy 0
++.if n .na
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.de CQ          \" put $1 in typewriter font
++.ft CW
++'if n "\c
++'if t \\&\\$1\c
++'if n \\&\\$1\c
++'if n \&"
++\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
++'.ft R
++..
++.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
++.	\" AM - accent mark definitions
++.bd B 3
++.	\" fudge factors for nroff and troff
++.if n \{\
++.	ds #H 0
++.	ds #V .8m
++.	ds #F .3m
++.	ds #[ \f1
++.	ds #] \fP
++.\}
++.if t \{\
++.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++.	ds #V .6m
++.	ds #F 0
++.	ds #[ \&
++.	ds #] \&
++.\}
++.	\" simple accents for nroff and troff
++.if n \{\
++.	ds ' \&
++.	ds ` \&
++.	ds ^ \&
++.	ds , \&
++.	ds ~ ~
++.	ds ? ?
++.	ds ! !
++.	ds /
++.	ds q
++.\}
++.if t \{\
++.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
++.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
++.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
++.\}
++.	\" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
++.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
++.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
++.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++.ds oe o\h'-(\w'o'u*4/10)'e
++.ds Oe O\h'-(\w'O'u*4/10)'E
++.	\" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++.	\" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++.	ds : e
++.	ds 8 ss
++.	ds v \h'-1'\o'\(aa\(ga'
++.	ds _ \h'-1'^
++.	ds . \h'-1'.
++.	ds 3 3
++.	ds o a
++.	ds d- d\h'-1'\(ga
++.	ds D- D\h'-1'\(hy
++.	ds th \o'bp'
++.	ds Th \o'LP'
++.	ds ae ae
++.	ds Ae AE
++.	ds oe oe
++.	ds Oe OE
++.\}
++.rm #[ #] #H #V #F C
++.SH "NAME"
++TTF2PT1 \- A True Type to PostScript Type 1 Font Converter 
++.SH "SYNOPSIS"
++\f(CWttf2pt1 \fI[-options] ttffont.ttf [Fontname]\fR\fR
++.PP
++or
++.PP
++\f(CWttf2pt1 \fI[-options] ttffont.ttf -\fR\fR
++.SH "DESCRIPTION"
++Ttf2pt1 is a font converter from the True Type format (and some other formats
++supported by the FreeType library as well) to the Adobe Type1 format.
++.PP
++The versions 3.0 and later got rather extensive post-processing algorithm that 
++brings the converted fonts to the requirements of the Type1 standard, tries to
++correct the rounding errors introduced during conversions and some simple
++kinds of bugs that are typical for the public domain TTF fonts. It
++also generates the hints that enable much better rendering of fonts in
++small sizes that are typical for the computer displays. But everything
++has its price, and some of the optimizations may not work well for certain
++fonts. That's why the options were added to the converter, to control
++the performed optimizations.
++.SH "OPTIONS"
++The first variant creates the file \f(CWFontname.pfa\fR (or \f(CWFontname.pfb\fR if the 
++option \*(L'\fB\-b\fR\*(R' was used) with the converted font and \f(CWFontname.afm\fR with the 
++font metrics, the second one prints the font or another file (if the option
++\&\*(R'\fB\-G\fR\*(R' was used) on the standard output from where it can be immediately
++piped through some filter. If no \f(CWFontname\fR is specified for the first
++variant, the name is generated from \f(CWttffont\fR by replacing the \f(CW.ttf\fR
++filename suffix.
++.PP
++Most of the time no options are neccessary (with a possible exception
++of \*(L'\fB\-e\fR'). But if there are some troubles with the resulting font, they 
++may be used to control the conversion.
++The \fBoptions\fR are:
++.Ip "\(bu" 2
++\f(CW\fB-a\fR\fR \- Include all the glyphs from the source file into the converted
++file. If this option is not specified then only the glyphs that have
++been assigned some encoding are included, because the rest of glyphs
++would be inaccessible anyway and would only consume the disk space. 
++But some applications are clever enough to change the encoding on
++the fly and thus use the other glyphs, in this case they could
++benefit from using this option. But there is a catch: the X11 library
++has rather low limit for the font size. Including more glyphs increases
++the file size and thus increases the chance of hitting this limit.
++See \f(CWapp/X11/README\fR for the description of a 
++patch to X11 which fixes this problem.
++.Ip "\(bu" 2
++\f(CW\fB-b\fR\fR \- Encode the resulting font to produce a ready \f(CW.pfb\fR file.
++.Ip "\(bu" 2
++\f(CW\fB-d \fIsuboptions\fR\fR\fR \- Debugging options. The suboptions are:
++.Sp
++\f(CW\fBa\fR\fR \- Print out the absolute coordinates of dots in outlines. Such
++a font can not be used by any program (that's why this option is
++incompatible with \*(L'\fB\-e\fR') but it has proven to be a valuable debuging 
++information.
++.Sp
++\f(CW\fBr\fR\fR \- Do not reverse the direction of outlines. The \s-1TTF\s0 fonts have
++the standard direction of outlines opposite to the Type1 fonts. So
++they should be reversed during proper conversion. This option
++may be used for debugging or to handle a \s-1TTF\s0 font with wrong
++direction of outlines (possibly, converted in a broken way from
++a Type1 font). The first signs of the wrong direction are the
++letters like \*(L"P\*(R" or \*(L"B\*(R" without the unpainted \*(L"holes\*(R" inside.
++.Ip "\(bu" 2
++\f(CW\fB-e\fR\fR \- Assemble the resulting font to produce a ready \f(CW.pfa\fR file.
++.Sp
++[ S.B.: Personally I don't think that this option is particularly useful.
++The same result may be achieved by piping the unassembled data
++through t1asm, the Type 1 assembler. And, anyways, it's good to
++have the t1utils package handy. But Mark and many users think that 
++this functionality is good and it took not much time to add this option. ]
++.Ip "\(bu" 2
++\f(CW\fB-F\fR\fR \- Force the Unicode encoding: any type of \s-1MS\s0 encoding specified
++in the font is ignored and the font is treated like it has Unicode
++encoding. \fB\s-1WARNING\s0:\fR this option is intended for buggy fonts
++which actually are in Unicode but are marked as something else. The
++effect on the other fonts is unpredictable.
++.Ip "\(bu" 2
++\f(CW\fB-G \fIsuboptions\fR\fR\fR \- File generation options. The suboptions may be lowercase 
++or uppercase, the lowercase ones disable the generation of particular 
++files, the corresponding uppercase suboptions enable the generation of the 
++same kind of files. If the result of ttf2pt1 is requested to be printed on
++the standard output, the last enabling suboption of \fB\-G\fR determines
++which file will be written to the standard output and the rest of files
++will be discarded. For example, \fB\-G A\fR will request the \s-1AFM\s0 file.
++The suboptions to disable/enable the generation of the files are:
++.Sp
++\f(CW\fBf/F\fR\fR \- The font file. Depending on the other options this file
++will have one of the suffixes \f(CW.t1a\fR, \f(CW.pfa\fR or \f(CW.pfb\fR. If the conversion result
++is requested on the standard output ('\f(CW-\fR\*(R' is used as the output file name)
++then the font file will also be written there by default, if not overwritten
++by another suboption of \fB\-G\fR.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBa/A\fR\fR \- The Adobe font metrics file (\f(CW.afm\fR).
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBe/E\fR\fR \- The dvips encoding file (\f(CW.enc\fR).
++\fBDefault: disabled\fR
++.Ip "\(bu" 2
++\f(CW\fB-l \fIlanguage\fR[+\fIargument\fR]\fR\fR \- Extract the fonts for the specified language from a
++multi-language Unicode font. If this option is not used the converter
++tries to guess the language by the values of the shell variable \s-1LANG\s0.
++If it is not able to guess the language by \s-1LANG\s0 it tries all the
++languages in the order they are listed. 
++.Sp
++After the plus sign an optional argument for the language extractor
++may be specified. The format of the argument is absolutely up to
++the particular language converter. The primary purpose of the
++argument is to support selection of planes for the multi-plane
++Eastern encodings but it can also be used in any other way. The 
++language extractor may decide to add the plane name in some form
++to the name of the resulting font. None of the currently supported 
++languages make any use of the argument yet.
++.Sp
++As of now the following languages are supported:
++.Sp
++\ \ \f(CWlatin1\fR \- for all the languages using the Latin-1 encoding
++.Sp
++\ \ \f(CWlatin2\fR \- for the Central European languages
++.Sp
++\ \ \f(CWlatin4\fR \- for the Baltic languages
++.Sp
++\ \ \f(CWlatin5\fR \- for the Turkish language
++.Sp
++\ \ \f(CWcyrillic\fR \- for the languages with Cyrillic alphabet
++.Sp
++\ \ \f(CWrussian\fR \- historic synonym for cyrillic
++.Sp
++\ \ \f(CWbulgarian\fR \- historic synonym for cyrillic
++.Sp
++\ \ \f(CWadobestd\fR \- for the AdobeStandard encoding used by TeX
++.Sp
++\ \ \f(CWplane+\fIargument\fR\fR \- to select one plane from a multi-byte encoding
++.Sp
++The argument of the \*(L"\f(CWplane\fR\*(R" language may be in one of three forms:
++.Sp
++\ \ \f(CWplane+\fBpid=\fR\fI<pid>\fR\fB,eid=\fR\fI<eid>\fR\fR
++.Sp
++\ \ \f(CWplane+\fBpid=\fR\fI<pid>\fR\fB,eid=\fR\fI<eid>\fR\fB,\fR\fI<plane_number>\fR\fR
++.Sp
++\ \ \f(CWplane+\fI<plane_number>\fR\fR
++.Sp
++Pid (\s-1TTF\s0 platform id) and eid (\s-1TTF\s0 encoding id) select a particular 
++\s-1TTF\s0 encoding table in the original font. They are specified as decimal
++numbers. If this particular encoding table is not present in the font
++file then the conversion fails. The native ("ttf") front-end parser supports
++only pid=3 (Windows platform), the FreeType-based ("ft") front-end supports 
++any platform. If pid/eid is not specified then the \s-1TTF\s0 encoding table is 
++determined as usual: Unicode encoding if it's first or an 8-bit encoding
++if not (and for an 8-bit encoding the plane number is silently ignored). 
++To prevent the converter from falling back to an 8-bit encoding, specify
++the Unicode pid/eid value explicitly.
++.Sp
++Plane_number is a hexadecimal (if starts with \*(L"\fB0x\fR") or decimal number.
++It gives the values of upper bytes for which 256 characters will be 
++selected. If not specified, defaults to 0. It is also used as a font
++name suffix (the leading \*(L"0x\*(R" is not included into the suffix).
++.Sp
++\fB\s-1NOTE\s0:\fR
++You may notice that the language names are not uniform: some are the
++names of particular languages and some are names of encodings. This
++is because of the different approaches. The original idea was to
++implement a conversion from Unicode to the appropriate Windows
++encoding for a given language. And then use the translation tables
++to generate the fonts in whatever final encodings are needed. This
++would allow to pile together the Unicode fonts and the non-Unicode
++Windows fonts for that language and let the program to sort them out
++automatically. And then generate fonts in all the possible encodings
++for that language. An example of this approach is the Russian language
++support. But if there is no multiplicity of encodings used for some 
++languages and if the non-Unicode fonts are not considered important 
++by the users, another way would be simpler to implement: just provide
++only one table for extraction of the target encoding from Unicode
++and don't bother with the translation tables. The latin* \*(L"languages\*(R"
++are examples of this approach. If somebody feels that he needs the
++Type1 fonts both in Latin-* and Windows encodings he or she is absolutely
++welcome to submit the code to implement it.
++.Sp
++\fB\s-1WARNING\s0:\fR
++Some of the glyphs included into the AdobeStandard encoding are not
++included into the Unicode standard. The most typical examples of such
++glyphs are ligatures like \*(L'fi\*(R', \*(L'fl\*(R' etc. Because of this the font 
++designers may place them at various places. The converter tries to
++do its best, if the glyphs have honest Adobe names and/or are
++placed at the same codes as in the Microsoft fonts they will be
++picked up. Otherwise a possible solution is to use the option \*(L'\fB\-L\fR\*(R'
++with an external map. 
++.Ip "\(bu" 2
++\f(CW\fB-L \fIfile\fR[+[pid=\fI<pid>\fR,eid=\fI<eid>\fR,][\fIplane\fR]]\fR\fR \- Extract the fonts for the specified 
++language from a multi-language font using the map from this file. This is
++rather like the option \*(L'\fB\-l\fR\*(R' but the encoding map is not 
++compiled into the program, it's taken from that file, so it's
++easy to edit. Examples of such files are provided in 
++\f(CWmaps/adobe-standard-encoding.map\fR, \f(CWCP1250.map\fR. (\fB\s-1NOTE\s0:\fR
++the \*(L'standard encoding\*(R' map does not include all the glyphs of the 
++AdobeStandard encoding, it's provided only as an example.) The 
++description of the supported map formats is in the file 
++\f(CWmaps/unicode-sample.map\fR.
++.Sp
++Likewise to \*(L'\fB\-l\fR\*(R', an argument may be specified after the map file
++name. But in this case the argument has fixed meaning: it selects the 
++original \s-1TTF\s0 encoding table (the syntax is the same as in \*(L'\fB\-l plane\fR')
++and/or a plane of the map file. The plane name also gets added after dash 
++to the font name. The plane is a concept used in the Eastern fonts with big 
++number of glyphs: one \s-1TTF\s0 font gets divided into multiple Type1 fonts, 
++each containing one plane of up to 256 glyphs. But with a little 
++creativity this concept may be used for other purposes of combining 
++multiple translation maps into one file.  To extract multiple planes 
++from a \s-1TTF\s0 font \f(CWttf2pt1\fR must be run multiple times, each time with 
++a different plane name specified.
++.Sp
++The default original \s-1TTF\s0 encoding table used for the option \*(L'\fB\-L\fR\*(R' is
++Unicode. The map files may include directives to specify different original 
++\s-1TTF\s0 encodings. However if the pid/eid pair is specified with
++it overrides any original encoding specified in the map file.
++.Ip "\(bu" 2
++\f(CW\fB-m \fItype\fR=\fIvalue\fR\fR\fR \- Set maximal or minimal limits of resources.
++These limits control the the font generation by limiting the resources
++that the font is permitted to require from the PostScript interpreter.
++The currently supported types of limits are:
++.Sp
++\f(CW\fBh\fR\fR \- the maximal hint stack depth for the substituted hints. 
++The default value is 128, according to the limitation in X11. This seems to
++be the lowest (and thus the safest) widespread value. To display the
++hint stack depth required by each glyph in a \f(CW.t1a\fR file use the script
++\f(CWscripts/cntstems.pl\fR.
++.Ip "\(bu" 2
++\f(CW\fB-O \fIsuboptions\fR\fR\fR \- Outline processing options. The suboptions
++may be lowercase or uppercase, the lowercase ones disable the features,
++the corresponding uppercase suboptions enable the same features.
++The suboptions to disable/enable features are:
++.Sp
++\f(CW\fBb/B\fR\fR \- Guessing of the ForceBold parameter. This parameter helps
++the Type1 engine to rasterize the bold fonts properly at small sizes.
++But the algorithm used to guess the proper value of this flag makes
++that guess based solely on the font name. In rare cases that may cause
++errors, in these cases you may want to disable this guessing. 
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBh/H\fR\fR \- Autogeneration of hints. The really complex outlines
++may confuse the algorithm, so theoretically it may be useful
++sometimes to disable them. Although up to now it seems that
++even bad hints are better than no hints at all.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBu/U\fR\fR \- Hint substitution. Hint substitution is a technique 
++permitting generation of more detailed hints for the rasterizer. It allows 
++to use different sets of hints for different parts of a glyph and change 
++these sets as neccessary during rasterization (that's why \*(L"substituted").  
++So it should improve the quality of the fonts rendered at small sizes.  
++But there are two catches: First, the X11 library has rather low limit for 
++the font size. More detailed hints increase the file size and thus increase 
++the chance of hitting this limit (that does not mean that you shall hit it
++but you may if your fonts are particularly big). This is especially 
++probable for Unicode fonts converted with option \*(L'\fB\-a\fR\*(R', so you may want to 
++use \*(L'\fB\-a\fR\*(R' together with \*(L'\fB\-Ou\fR\*(R'. See \f(CWapp/X11/README\fR for the description of 
++a patch to X11 which fixes this problem. Second, some rasterizers (again,
++X11 is the typical example) have a limitation for total number of hints
++used when drawing a glyph (also known as the hint stack depth). If that
++stack overflows the glyph is ignored. Starting from version 3.22 \f(CWttf2pt1\fR
++uses algorithms to minimizing this depth, with the trade-off of slightly
++bigger font files. The glyphs which still exceed the limit set by option
++\&\*(R'\fB\-mh\fR\*(R' have all the substituted hints removed and only base hints left.
++The algorithms seem to have been refined far enough to make the fonts with
++substituted hints look better than the fonts without them or at least the 
++same. Still if the original fonts are not well-designed the detailed 
++hinting may emphasize the defects of the design, such as non-even thickness 
++of lines. So provided that you are not afraid of the X11 bug the best idea 
++would be to generate a font with this feature and without it, then compare 
++the results using the program \f(CWother/cmpf\fR (see the description 
++in \f(CWother/README\fR) and decide which one looks better.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBo/O\fR\fR \- Space optimization of the outlines\*(R' code. This kind of optimization
++never hurts, and the only reason to disable this feature is for comparison 
++of the generated fonts with the fonts generated by the previous versions of 
++converter. Well, it _almost_ never hurts. As it turned out there exist
++some brain-damaged printers which don't understand it. Actually this
++feature does not change the outlines at all. The Type 1 font manual 
++provides a set of redundant operators that make font description shorter,
++such as \*(L'10 hlineto\*(R' instead of \*(L'0 10 rlineto\*(R' to describe a horizontal
++line. This feature enables use of these operators.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBs/S\fR\fR \- Smoothing of outlines. If the font is broken in some
++way (even the ones that are not easily noticeable), such smoothing 
++may break it further. So disabling this feature is the first thing to be 
++tried if some font looks odd. But with smoothing off the hint generation
++algorithms may not work properly too.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBt/T\fR\fR \- Auto-scaling to the 1000x1000 Type1 standard matrix. The
++\s-1TTF\s0 fonts are described in terms of an arbitrary matrix up to
++4000x4000. The converted fonts must be scaled to conform to
++the Type1 standard. But the scaling introduces additional rounding
++errors, so it may be curious sometimes to look at the font in its
++original scale.
++\fBDefault: enabled\fR
++.Sp
++\f(CW\fBv/V\fR\fR \- Do vectorization on the bitmap fonts. Functionally
++\*(L"vectorization\*(R" is the same thing as \*(L"autotracing\*(R", a different word is
++used purely to differentiate it from the Autotrace library. It tries to
++produce nice smooth outlines from bitmaps. This feature is still a work
++in progress though the results are already mostly decent.
++\fBDefault: disabled\fR
++.Sp
++\f(CW\fBw/W\fR\fR \- Glyphs\*(R' width corection. This option is designed to be
++used on broken fonts which specify too narrow widths for the 
++letters. You can tell that a font can benefit from this option
++if you see that the characters are smashed together without
++any whitespace between them. This option causes the converter
++to set the character widths to the actual width of this character
++plus the width of a typical vertical stem. But on the other hand
++the well-designed fonts may have characters that look better if
++their widths are set slightly narrower. Such well-designed fonts
++will benefit from disabling this feature. You may want to convert
++a font with and without this feature, compare the results and
++select the better one. This feature may be used only on proportional
++fonts, it has no effect on the fixed-width fonts.
++\fBDefault: disabled\fR
++.Sp
++\f(CW\fBz/Z\fR\fR \- Use the Autotrace library on the bitmap fonts. The results 
++are horrible and \fBthe use of this option is not recommended\fR. This option is 
++present for experimental purposes. It may change or be removed in the
++future. The working tracing can be achieved with option \f(CW\fB-OV\fR\fR.
++\fBDefault: disabled\fR
++.Ip "\(bu" 2
++\f(CW\fB-p \fIparser_name\fR\fR\fR \- Use the specified front-end parser to read the font file.
++If this option is not used, ttf2pt1 selects the parser automatically based
++on the suffix of the font file name, it uses the first parser in its
++list that supports this font type. Now two parsers are supported:
++.Sp
++\ \ \f(CWttf\fR \- built-in parser for the ttf files (suffix \f(CW.ttf\fR)
++.Sp
++\ \ \f(CWbdf\fR \- built-in parser for the \s-1BDF\s0 files (suffix \f(CW.bdf\fR)
++.Sp
++\ \ \f(CWft\fR \- parser based on the FreeType-2 library (suffixes \f(CW.ttf\fR,
++\&\f(CW.otf\fR, \f(CW.pfa\fR, \f(CW.pfb\fR)
++.Sp
++The parser \f(CWft\fR is \fB\s-1NOT\s0\fR linked in by default. See \f(CWMakefile\fR
++for instructions how to enable it. We do no support this parser on
++Windows: probably it will work but nobody tried and nobody knows how
++to build it. 
++.Sp
++The conversion of the bitmap fonts (such as \s-1BDF\s0) is simplistic yet,
++producing jagged outlines.  When converting such fonts, it might be 
++a good idea to turn off the hint substitution (using option \fB\-Ou\fR) 
++because the hints produced will be huge but not adding much to the
++quality of the fonts.
++.Ip "\(bu" 2
++\f(CW\fB-u \fInumber\fR\fR\fR \- Mark the font with this value as its
++UniqueID. The UniqueID is used by the printers with the hard disks
++to cache the rasterized characters and thus significantly
++speed-up the printing. Some of those printers just can't
++store the fonts without UniqueID on their disk.The problem
++is that the \s-1ID\s0 is supposed to be unique, as it name says. And
++there is no easy way to create a guaranteed unique \s-1ID\s0. Adobe specifies
++the range 4000000-4999999 for private IDs but still it's difficult
++to guarantee the uniqueness within it. So if you don't really need the 
++UniqueID don't use it, it's optional. Luckily there are a few millions of 
++possible IDs, so the chances of collision are rather low. 
++If instead of the number a special value \*(L'\f(CW\fBA\fR\fR\*(R' is given
++then the converter generates the value of UniqueID automatically,
++as a hash of the font name. (\fB\s-1NOTE\s0:\fR  in the version 3.22 the
++algorithm for autogeneration of UniqueID was changed to fit the values
++into the Adobe-spacified range. This means that if UniqueIDs were used 
++then the printer's cache may need to be flushed before replacing the 
++fonts converted by an old version with fonts converted by a newer version).
++A simple way to find if any of the fonts in a given directory have
++duplicated UniqueIDs is to use the command:
++.Sp
++\f(CW\ \ cat *.pf[ab] | grep UniqueID | sort | uniq -c | grep -v ' 1 '\fR
++.Sp
++Or if you use \f(CWscripts/convert\fR it will do that for you automatically 
++plus it will also give the exact list of files with duplicate UIDs.
++.Ip "\(bu" 2
++\f(CW\fB-v \fIsize\fR\fR\fR \- Re-scale the font to get the size of a typical uppercase
++letter somewhere around the specified size. Actually, it re-scales
++the whole font to get the size of one language-dependent letter to be
++at least of the specified size. Now this letter is \*(L"A\*(R" in all the
++supported languages. The size is specified in the points of the
++Type 1 coordinate grids, the maximal value is 1000. This is an
++experimental option and should be used with caution. It tries to
++increase the visible font size for a given point size and thus make
++the font more readable. But if overused it may cause the fonts to
++look out of scale. As of now the interesting values of size for
++this option seem to be located mostly between 600 and 850. This
++re-scaling may be quite useful but needs more experience to
++understand the balance of its effects.
++.Ip "\(bu" 2
++\f(CW\fB-W \fIlevel\fR\fR\fR \- Select the verbosity level of the warnings.
++Currently the levels from 0 to 4 are supported. Level 0 means no warnings
++at all, level 4 means all the possible warnings. The default level is 3.
++Other levels may be added in the future, so using the level number 99 is
++recommended to get all the possible warnings. Going below level 2 is
++not generally recommended because you may miss valuable information about
++the problems with the fonts being converted.
++.Ip "\(bu" 2
++\fBObsolete option:\fR
++\f(CW\fB-A\fR\fR \- Print the font metrics (.afm file) instead of the font on \s-1STDOUT\s0.
++Use \fB\-\s-1GA\s0\fR instead.
++.Ip "\(bu" 2
++\fBVery obsolete option:\fR
++.Sp
++The algorithm that implemented the forced fixed width had major
++flaws, so it was disabled. The code is still in the program and
++some day it will be refined and returned back. Meanwhile the 
++option name \*(L'\fB\-f\fR\*(R' was reused for another option. The old version was:
++.Sp
++\f(CW\fB-f\fR\fR \- Don't try to force the fixed width of font. Normally the converter
++considers the fonts in which the glyph width deviates by not more
++than 5% as buggy fixed width fonts and forces them to have really
++fixed width. If this is undesirable, it can be disabled by this option.
++.PP
++The \f(CW.pfa\fR font format supposes that the description of the characters
++is binary encoded and encrypted. This converter does not encode or
++encrypt the data by default, you have to specify the option \*(L'\fB\-e\fR\*(R'
++or use the \f(CWt1asm\fR program to assemble (that means, encode and
++encrypt) the font program. The \f(CWt1asm\fR program that is included with
++the converter is actually a part of the \f(CWt1utils\fR package, rather old
++version of which may be obtained from
++.PP
++http://ttf2pt1.sourceforge.net/t1utils.tar.gz
++.PP
++Note that \f(CWt1asm\fR from the old version of that package won't work properly
++with the files generated by \f(CWttf2pt1\fR version 3.20 and later. Please use
++\f(CWt1asm\fR packaged with \f(CWttf2pt1\fR or from the new version \f(CWt1utils\fR
++instead. For a newer version of \f(CWt1utils\fR please look at
++.PP
++http://www.lcdf.org/~eddietwo/type/
++.SH "EXAMPLES"
++So, the following command lines:
++.PP
++\f(CWttf2pt1 -e ttffont.ttf t1font\fR
++.PP
++\f(CWttf2pt1 ttffont.ttf - | t1asm >t1font.pfa\fR
++.PP
++represent two ways to get a working font. The benefit of the second form 
++is that other filters may be applied to the font between the converter
++and assembler.
++.SH "FILES"
++.Ip "\(bu" 2
++\s-1TTF2PT1_LIBXDIR/\s0t1asm
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR\s0/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0scripts/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0other/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/README\s0
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/FONTS\s0
++.SH "SEE ALSO"
++.Ip "\(bu" 4
++the \fIttf2pt1_convert(1)\fR manpage
++.Ip "\(bu" 4
++the \fIttf2pt1_x2gs(1)\fR manpage
++.Ip "\(bu" 4
++the \fIt1asm(1)\fR manpage
++.Ip "\(bu" 4
++ttf2pt1-announce@lists.sourceforge.net
++.Sp
++The mailing list with announcements about ttf2pt1. It is a moderated mailing
++with extremely low traffic. Everyone is encouraged to subscribe to keep in 
++touch with the current status of project. To subscribe use the Web interface
++at http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce.
++If you have only e-mail access to the Net then send a subscribe request to 
++the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
++will help you with subscription.
++.Ip "\(bu" 4
++ttf2pt1-devel@lists.sourceforge.net
++.Sp
++ttf2pt1-users@lists.sourceforge.net
++.Sp
++The ttf2pt1 mailing lists for development and users issues. They have not
++that much traffic either. To subscribe use the Web interface at
++http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel
++and http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users.
++If you have only e-mail access to the Net then send a subscribe request to 
++the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody
++will help you with subscription.
++.Ip "\(bu" 4
++http://ttf2pt1.sourceforge.net
++.Sp
++The main page of the project.
++.Sp
++http://www.netspace.net.au/~mheath/ttf2pt1/
++.Sp
++The old main page of the project.
++.SH "BUGS"
++It seems that many Eastern fonts use features of the TTF format that are 
++not supported by the ttf2pt1's built-in front-end parser. Because of
++this for now we recommend using the FreeType-based parser (option
++\&\*(R'\fB\-p ft\fR') with the \*(L"\f(CWplane\fR\*(R" language.
++.Sh "Troubleshooting and bug reports"
++Have problems with conversion of some font ? The converter dumps core ? Or your
++printer refuses to understand the converted fonts ? Or some characters are 
++missing ? Or some characters look strange ?
++.PP
++Send the bug reports to the ttf2pt1 development mailing list at
++ttf2pt1-devel@lists.sourceforge.net.
++.PP
++Try to collect more information about the problem and include it into
++the bug report. (Of course, even better if you would provide a ready
++fix, but just a detailed bug report is also good). Provide detailed
++information about your problem, this will speed up the response greatly.
++Don't just write \*(L"this font looks strange after conversion\*(R" but describe
++what's exactly wrong with it: for example, what characters look wrong
++and what exactly is wrong about their look. Providing a link to the
++original font file would be also a good idea. Try to do a little
++troublehooting and report its result. This not only would help with
++the fix but may also give you a temporary work-around for the bug.
++.PP
++First, enable full warnings with option \*(L'\fB\-W99\fR\*(R', save them to
++a file and read carefully. Sometimes the prolem is with a not implemented
++feature which is reported in the warnings. Still, reporting about such
++problems may be a good idea: some features were missed to cut corners,
++in hope that no real font is using them. So a report about a font using
++such a feature may motivate someone to implement it. Of course, you
++may be the most motivated person: after all, you are the one wishing
++to convert that font. ;\-) Seriously, the philosophy \*(L"scrath your own itch\*(R"
++seems to be the strongest moving force behind the Open Source software.
++.PP
++The next step is playing with the options. This serves a dual purpose:
++on one hand, it helps to localize the bug, on the other hand you may be
++able to get a working version of the font for the meantime while the
++bug is being fixed. The typical options to try out are: first \*(L'\fB\-Ou\fR\*(R', if
++it does not help then \*(L'\fB\-Os\fR\*(R', then \*(L'\fB\-Oh\fR\*(R', then \*(L'\fB\-Oo\fR\*(R'.
++They are described in a bit more detail above. Try them one by one
++and in combinations. See if with them the resulting fonts look better.
++.PP
++On some fonts ttf2pt1 just crashes. Commonly that happens because the
++font being converted is highly defective (although sometimes the bug
++is in ttf2pt1 itself). In any case it should not crash, so the reports
++about such cases will help to handle these defects properly in future.
++.PP
++We try to respond to the bug reports in a timely fashion but alas, this 
++may not always be possible, especially if the problem is complex.
++This is a volunteer project and its resources are limited. Because
++of this we would appreciate bug reports as detailed as possible,
++and we would appreciate the ready fixes and contributions even more.
++.SH "HISTORY"
++Based on ttf2pfa by Andrew Weeks, and help from Frank Siegert.
++.PP
++Modification by Mark Heath.
++.PP
++Further modification by Sergey Babkin.
++.PP
++The Type1 assembler by I. Lee Hetherington with modifications by 
++Kai-Uwe Herbing.
++
++.rn }` ''
++.IX Title "TTF2PT1 1"
++.IX Name "TTF2PT1 - A True Type to PostScript Type 1 Font Converter"
++
++.IX Header "NAME"
++
++.IX Header "SYNOPSIS"
++
++.IX Header "DESCRIPTION"
++
++.IX Header "OPTIONS"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "EXAMPLES"
++
++.IX Header "FILES"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "SEE ALSO"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "BUGS"
++
++.IX Subsection "Troubleshooting and bug reports"
++
++.IX Header "HISTORY"
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1.c xserver/hw/xprint/extras/ttf2pt1/ttf2pt1.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf2pt1.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,2722 @@
++/*
++ * True Type Font to Adobe Type 1 font converter 
++ * By Mark Heath <mheath@netspace.net.au> 
++ * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
++ * With help from Frank M. Siegert <fms@this.net> 
++ *
++ * see COPYRIGHT for full copyright notice
++ *
++***********************************************************************
++ *
++ * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com>
++ *
++ * Added post-processing of resulting outline to correct the errors
++ * both introduced during conversion and present in the original font,
++ * autogeneration of hints (has yet to be improved though) and BlueValues,
++ * scaling to 1000x1000 matrix, option to print the result on STDOUT,
++ * support of Unicode to CP1251 conversion, optimization  of the
++ * resulting font code by space (that improves the speed too). Excluded
++ * the glyphs that are unaccessible through the encoding table from
++ * the output file. Added the built-in Type1 assembler (taken from
++ * the `t1utils' package).
++ *
++***********************************************************************
++ *
++ * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
++ *
++ * Added generation of .afm file (font metrics)
++ * Read encoding information from encoding description file
++ * Fixed bug in error message about unknown language ('-l' option)
++ * Added `:' after %%!PS-AdobeFont-1.0
++ * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128...
++ *
++***********************************************************************
++ *
++ * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de>
++ *
++ * Added generation of .afm file (font metrics)
++ *
++***********************************************************************
++ *
++ * Bug Fixes: 
++************************************************************************
++ *
++ * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de> 
++ * 1. "width" should be "short int" because otherwise: 
++ *     characters with negative widths (e.g. -4) become *very* wide (65532) 
++ * 2. the number of /CharStrings is numglyphs and not numglyphs+1 
++ *
++***********************************************************************
++ *
++ *
++ *
++ * The resultant font file produced by this program still needs to be ran
++ * through t1asm (from the t1utils archive) to produce a completely valid
++ * font. 
++ *
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <time.h>
++#include <ctype.h>
++#include <math.h>
++
++#ifdef _GNU_SOURCE
++#include <getopt.h>
++#endif
++
++#ifndef WINDOWS
++#	include <unistd.h>
++#	include <netinet/in.h>
++#	define BITBUCKET "/dev/null"
++#	include <sys/wait.h>
++#else
++#	define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */
++#	include "windows.h"
++#	define BITBUCKET "NUL"
++#	define snprintf _snprintf
++#endif
++
++#ifdef XP_PSTEXT
++#include <ft2build.h>
++#include FT_FREETYPE_H
++#include FT_TRUETYPE_TABLES_H
++#include FT_BBOX_H
++#include FT_GLYPH_H
++
++#include FT_CONFIG_CONFIG_H
++#include FT_CONFIG_OPTIONS_H
++#include FT_ERRORS_H
++#include FT_SYSTEM_H
++#include FT_IMAGE_H
++#include FT_TYPES_H
++#include FT_OUTLINE_H
++#include FT_MODULE_H
++#include FT_RENDER_H
++#include FT_TYPE1_TABLES_H
++#include FT_TRUETYPE_IDS_H
++#include FT_TRUETYPE_TAGS_H
++#include FT_MULTIPLE_MASTERS_H
++#include FT_SFNT_NAMES_H
++
++#include "os.h"
++#include <X11/Xproto.h>
++#include <X11/fonts/font.h>
++#include <X11/fonts/fontstruct.h>
++#include <X11/fonts/fntfilst.h>
++#include <X11/fonts/fontutil.h>
++#include <X11/fonts/fontenc.h>
++#include <X11/fonts/ft.h>
++#define NOT_IN_FTFUNCS
++#include <X11/fonts/ftfuncs.h>
++#endif /* XP_PSTEXT */
++
++#include "pt1.h"
++#include "global.h"
++#include "version.h"
++
++/* globals */
++
++/* table of front-ends */
++
++#ifdef USE_TTF
++extern struct frontsw ttf_sw;
++#endif /* USE_TTF */
++#ifdef USE_BDF
++extern struct frontsw bdf_sw;
++#endif /* USE_BDF */
++#if defined(USE_FREETYPE)
++	extern struct frontsw freetype_sw;
++#endif
++
++struct frontsw *frontswtab[] = {
++#ifdef USE_BDF
++	&bdf_sw,
++#endif /* USE_BDF */
++#if defined(USE_FREETYPE) && defined(PREFER_FREETYPE)
++	&freetype_sw,
++#endif
++#ifdef USE_TTF
++	&ttf_sw,
++#endif /* USE_TTF */
++#if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE)
++	&freetype_sw,
++#endif
++	NULL /* end of table */
++};
++
++struct frontsw *cursw=0; /* the active front end */
++char *front_arg=""; /* optional argument */
++
++/* options */
++int      encode = 0;	/* encode the resulting file */
++int      pfbflag = 0;	/* produce compressed file */
++int      wantafm=0;	/* want to see .afm instead of .t1a on stdout */
++int      correctvsize=0;	/* try to correct the vertical size of characters */
++int      wantuid = 0;	/* user wants UniqueID entry in the font */
++int      allglyphs = 0;	/* convert all glyphs, not only 256 of them */
++int      warnlevel = 3;	/* the level of permitted warnings */
++int      forcemap = 0; /* do mapping even on non-Unicode fonts */
++/* options - maximal limits */
++int      max_stemdepth = 128;	/* maximal depth of stem stack in interpreter (128 - limit from X11) */
++/* options - debugging */
++int      absolute = 0;	/* print out in absolute values */
++int      reverse = 1;	/* reverse font to Type1 path directions */
++/* options - suboptions of Outline Processing, defaults are set in table */
++int      optimize;	/* enables space optimization */
++int      smooth;	/* enable smoothing of outlines */
++int      transform;	/* enables transformation to 1000x1000 matrix */
++int      hints;	/* enables autogeneration of hints */
++int      subhints;	/* enables autogeneration of substituted hints */
++int      trybold;	/* try to guess whether the font is bold */
++int      correctwidth;	/* try to correct the character width */
++int      vectorize;	/* vectorize the bitmaps */
++int      use_autotrace;	/* use the autotrace library on bitmap */
++/* options - suboptions of File Generation, defaults are set in table */
++int      gen_pfa;	/* generate the font file */
++int      gen_afm;	/* generate the metrics file */
++int      gen_dvienc;	/* generate the dvips encoding file */
++
++/* not quite options to select a particular source encoding */
++int      force_pid = -1; /* specific platform id */
++int      force_eid = -1; /* specific encoding id */
++
++/* structure to define the sub-option lists controlled by the
++ * case: uppercase enables them, lowercase disables
++ */
++struct subo_case {
++	char disbl; /* character to disable - enforced lowercase */
++	char enbl;  /* character to enable - auto-set as toupper(disbl) */
++	int *valp; /* pointer to the actual variable containing value */
++	int  dflt; /* default value */
++	char *descr; /* description */
++};
++
++#ifdef DEBUG
++int      debug = DEBUG;	/* debugging flag */
++#else
++int      debug = 0;
++#endif /* DEBUG */
++
++FILE    *null_file, *pfa_file, *afm_file, *dvienc_file;
++int      numglyphs;
++struct font_metrics fontm;
++
++/* non-globals */
++static char    *strUID = 0;	/* user-supplied UniqueID */
++static unsigned long numUID;	/* auto-generated UniqueID */
++
++static int      ps_fmt_3 = 0;
++static double   scale_factor, original_scale_factor;
++
++static char	*glyph_rename[ENCTABSZ];
++
++/* the names assigned if the original font
++ * does not specify any
++ */
++
++static char    *Fmt3Encoding[256] = {
++	"c0", "c1", "c2", "c3",
++	"c4", "c5", "c6", "c7",
++	"c8", "c9", "c10", "c11",
++	"c12", "CR", "c14", "c15",
++	"c16", "c17", "c18", "c19",
++	"c20", "c21", "c22", "c23",
++	"c24", "c25", "c26", "c27",
++	"c28", "c29", "c30", "c31",
++	"space", "exclam", "quotedbl", "numbersign",
++	"dollar", "percent", "ampersand", "quotesingle",
++	"parenleft", "parenright", "asterisk", "plus",
++	"comma", "hyphen", "period", "slash",
++	"zero", "one", "two", "three",
++	"four", "five", "six", "seven",
++	"eight", "nine", "colon", "semicolon",
++	"less", "equal", "greater", "question",
++	"at", "A", "B", "C",
++	"D", "E", "F", "G",
++	"H", "I", "J", "K",
++	"L", "M", "N", "O",
++	"P", "Q", "R", "S",
++	"T", "U", "V", "W",
++	"X", "Y", "Z", "bracketleft",
++	"backslash", "bracketright", "asciicircum", "underscore",
++	"grave", "a", "b", "c",
++	"d", "e", "f", "g",
++	"h", "i", "j", "k",
++	"l", "m", "n", "o",
++	"p", "q", "r", "s",
++	"t", "u", "v", "w",
++	"x", "y", "z", "braceleft",
++	"bar", "braceright", "asciitilde", "c127",
++	"c128", "c129", "quotesinglbase", "florin",
++	"quotedblbase", "ellipsis", "dagger", "daggerdbl",
++	"circumflex", "perthousand", "Scaron", "guilsinglleft",
++	"OE", "c141", "c142", "c143",
++	"c144", "quoteleft", "quoteright", "quotedblleft",
++	"quotedblright", "bullet", "endash", "emdash",
++	"tilde", "trademark", "scaron", "guilsinglright",
++	"oe", "c157", "c158", "Ydieresis",
++	"nbspace", "exclamdown", "cent", "sterling",
++	"currency", "yen", "brokenbar", "section",
++	"dieresis", "copyright", "ordfeminine", "guillemotleft",
++	"logicalnot", "sfthyphen", "registered", "macron",
++	"degree", "plusminus", "twosuperior", "threesuperior",
++	"acute", "mu", "paragraph", "periodcentered",
++	"cedilla", "onesuperior", "ordmasculine", "guillemotright",
++	"onequarter", "onehalf", "threequarters", "questiondown",
++	"Agrave", "Aacute", "Acircumflex", "Atilde",
++	"Adieresis", "Aring", "AE", "Ccedilla",
++	"Egrave", "Eacute", "Ecircumflex", "Edieresis",
++	"Igrave", "Iacute", "Icircumflex", "Idieresis",
++	"Eth", "Ntilde", "Ograve", "Oacute",
++	"Ocircumflex", "Otilde", "Odieresis", "multiply",
++	"Oslash", "Ugrave", "Uacute", "Ucircumflex",
++	"Udieresis", "Yacute", "Thorn", "germandbls",
++	"agrave", "aacute", "acircumflex", "atilde",
++	"adieresis", "aring", "ae", "ccedilla",
++	"egrave", "eacute", "ecircumflex", "edieresis",
++	"igrave", "iacute", "icircumflex", "idieresis",
++	"eth", "ntilde", "ograve", "oacute",
++	"ocircumflex", "otilde", "odieresis", "divide",
++	"oslash", "ugrave", "uacute", "ucircumflex",
++	"udieresis", "yacute", "thorn", "ydieresis"
++};
++
++#ifdef notdef /* { */
++/* This table is not used anywhere in the code
++ * so it's ifdef-ed out by default but left in
++ * the source code for reference purposes (and
++ * possibly for future use)
++ */
++
++static char    *ISOLatin1Encoding[256] = {
++	".null", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", "CR", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	"space", "exclam", "quotedbl", "numbersign",
++	"dollar", "percent", "ampersand", "quoteright",
++	"parenleft", "parenright", "asterisk", "plus",
++	"comma", "hyphen", "period", "slash",
++	"zero", "one", "two", "three",
++	"four", "five", "six", "seven",
++	"eight", "nine", "colon", "semicolon",
++	"less", "equal", "greater", "question",
++	"at", "A", "B", "C",
++	"D", "E", "F", "G",
++	"H", "I", "J", "K",
++	"L", "M", "N", "O",
++	"P", "Q", "R", "S",
++	"T", "U", "V", "W",
++	"X", "Y", "Z", "bracketleft",
++	"backslash", "bracketright", "asciicircum", "underscore",
++	"grave", "a", "b", "c",
++	"d", "e", "f", "g",
++	"h", "i", "j", "k",
++	"l", "m", "n", "o",
++	"p", "q", "r", "s",
++	"t", "u", "v", "w",
++	"x", "y", "z", "braceleft",
++	"bar", "braceright", "asciitilde", "c127",
++	"c128", "c129", "quotesinglbase", "florin",
++	"quotedblbase", "ellipsis", "dagger", "daggerdbl",
++	"circumflex", "perthousand", "Scaron", "guilsinglleft",
++	"OE", "c141", "c142", "c143",
++	"c144", "quoteleft", "quoteright", "quotedblleft",
++	"quotedblright", "bullet", "endash", "emdash",
++	"tilde", "trademark", "scaron", "guilsinglright",
++	"oe", "c157", "c158", "Ydieresis",
++	"nbspace", "exclamdown", "cent", "sterling",
++	"currency", "yen", "brokenbar", "section",
++	"dieresis", "copyright", "ordfeminine", "guillemotleft",
++	"logicalnot", "sfthyphen", "registered", "macron",
++	"degree", "plusminus", "twosuperior", "threesuperior",
++	"acute", "mu", "paragraph", "periodcentered",
++	"cedilla", "onesuperior", "ordmasculine", "guillemotright",
++	"onequarter", "onehalf", "threequarters", "questiondown",
++	"Agrave", "Aacute", "Acircumflex", "Atilde",
++	"Adieresis", "Aring", "AE", "Ccedilla",
++	"Egrave", "Eacute", "Ecircumflex", "Edieresis",
++	"Igrave", "Iacute", "Icircumflex", "Idieresis",
++	"Eth", "Ntilde", "Ograve", "Oacute",
++	"Ocircumflex", "Otilde", "Odieresis", "multiply",
++	"Oslash", "Ugrave", "Uacute", "Ucircumflex",
++	"Udieresis", "Yacute", "Thorn", "germandbls",
++	"agrave", "aacute", "acircumflex", "atilde",
++	"adieresis", "aring", "ae", "ccedilla",
++	"egrave", "eacute", "ecircumflex", "edieresis",
++	"igrave", "iacute", "icircumflex", "idieresis",
++	"eth", "ntilde", "ograve", "oacute",
++	"ocircumflex", "otilde", "odieresis", "divide",
++	"oslash", "ugrave", "uacute", "ucircumflex",
++	"udieresis", "yacute", "thorn", "ydieresis"
++};
++
++#endif /* } notdef */
++
++static char    *adobe_StandardEncoding[256] = {
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	"space", "exclam", "quotedbl", "numbersign",
++	"dollar", "percent", "ampersand", "quoteright",
++	"parenleft", "parenright", "asterisk", "plus",
++	"comma", "hyphen", "period", "slash",
++	"zero", "one", "two", "three",
++	"four", "five", "six", "seven",
++	"eight", "nine", "colon", "semicolon",
++	"less", "equal", "greater", "question",
++	"at", "A", "B", "C", "D", "E", "F", "G",
++	"H", "I", "J", "K", "L", "M", "N", "O",
++	"P", "Q", "R", "S", "T", "U", "V", "W",
++	"X", "Y", "Z", "bracketleft",
++	"backslash", "bracketright", "asciicircum", "underscore",
++	"quoteleft", "a", "b", "c", "d", "e", "f", "g",
++	"h", "i", "j", "k", "l", "m", "n", "o",
++	"p", "q", "r", "s", "t", "u", "v", "w",
++	"x", "y", "z", "braceleft",
++	"bar", "braceright", "asciitilde", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", "exclamdown", "cent", "sterling",
++	"fraction", "yen", "florin", "section",
++	"currency", "quotesingle", "quotedblleft", "guillemotleft",
++	"guilsinglleft", "guilsinglright", "fi", "fl",
++	".notdef", "endash", "dagger", "daggerdbl",
++	"periodcentered", ".notdef", "paragraph", "bullet",
++	"quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
++	"ellipsis", "perthousand", ".notdef", "questiondown",
++	".notdef", "grave", "acute", "circumflex",
++	"tilde", "macron", "breve", "dotaccent",
++	"dieresis", ".notdef", "ring", "cedilla",
++	".notdef", "hungarumlaut", "ogonek", "caron",
++	"emdash", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", "AE", ".notdef", "ordfeminine",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	"Lslash", "Oslash", "OE", "ordmasculine",
++	".notdef", ".notdef", ".notdef", ".notdef",
++	".notdef", "ae", ".notdef", ".notdef",
++	".notdef", "dotlessi", ".notdef", ".notdef",
++	"lslash", "oslash", "oe", "germandbls",
++	".notdef", ".notdef", ".notdef", ".notdef"
++};
++
++/*
++ * Decription of the supported conversions from Unicode
++ *
++ * SB
++ * Yes, I know that the compiled-in conversion is stupid but
++ * it is simple to implement and allows not to worry about the
++ * filesystem context. After all, the source is always available
++ * and adding another language to it is easy.
++ *
++ * The language name is expected to be the same as the subdirectory name 
++ * in the `encodings' directory (for possible future extensions). 
++ * The primary use of the aliases is for guessing based on the current 
++ * locale.
++ */
++
++#define MAXUNIALIAS 10
++#define MAXUNITABLES 3
++
++/* the character used as the language argument separator */
++#define LANG_ARG_SEP '+'
++
++
++/*
++ * Types of language-related routines. Arguments are:
++ * name is the glyph name
++ * arg is the user-specified language-dependent argument
++ *   which can for example select the subfont plane for Eastern fonts.
++ *   If none is supplied by user then an empty string ("") is passed.
++ *   If no language is specified by user and auto-guessing happens
++ *   then NULL is passed.
++ * when shows if the conversion by name was called before conversion by
++ *   map or after (it's called twice)
++ */
++
++/* type of the Unicode map initialization routine */
++typedef void uni_init_t(char *arg);
++
++/* type of Unicode converter-by-name function
++ * it's called for each glyph twice: one time for each glyph
++ * before doing conversion by map and one time after
++ */
++typedef int uni_conv_t(char *name, char *arg, int when);
++#define UNICONV_BYNAME_BEFORE 0
++#define UNICONV_BYNAME_AFTER 1
++
++struct uni_language {
++	uni_init_t	*init[MAXUNITABLES]; /* map initialization routines */
++	uni_conv_t	*convbyname; /* the name-based conversion function */
++	char *name; /* the language name */
++	char *descr; /* description */
++	char *alias[MAXUNIALIAS]; /* aliases of the language name */
++	int sample_upper; /* code of some uppercase character for correctvsize() */
++};
++
++/* the converter routines have an option of adding this suffix to the font name */
++static char *uni_font_name_suffix = ""; /* empty by default */
++/* this buffer may be used to store the suffix */
++#define UNI_MAX_SUFFIX_LEN	100
++static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1];
++
++/*
++ * Prototypes of the conversion routines
++ */
++
++static uni_init_t unicode_latin1;
++static uni_init_t unicode_latin2;
++static uni_init_t unicode_latin4;
++static uni_init_t unicode_latin5;
++static uni_init_t unicode_cyrillic;
++static uni_init_t unicode_adobestd;
++static uni_init_t unicode_plane;
++static uni_conv_t unicode_adobestd_byname;
++
++static uni_init_t unicode_init_user;
++
++/*
++ * The order of descriptions is important: if we can't guess the
++ * language we just call all the conversion routines in order until
++ * we find one that understands this glyph.
++ */
++static struct uni_language uni_lang[]= {
++	/* pseudo-language for all the languages using Latin1 */
++	{
++		{ unicode_latin1 },
++		0, /* no name-based mapping */
++		"latin1",
++		"works for most of the Western languages",
++		{ "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" },
++		'A'
++	},
++	{ /* by Szalay Tamas <tomek@elender.hu> */
++		{ unicode_latin2 },
++		0, /* no name-based mapping */
++		"latin2",
++		"works for Central European languages",
++		{ "hu_","pl_","cz_","si_","sk_" },
++		'A'
++	},
++	{ /* by Ri�ardas �epas <rch@WriteMe.Com> */
++		{ unicode_latin4 }, 
++		0, /* no name-based mapping */
++		"latin4",
++		"works for Baltic languages",
++		{ "lt_", "lv_" }, /* doubt about ee_ */
++		'A'
++	},
++	{ /* by Turgut Uyar <uyar@cs.itu.edu.tr> */
++		{ unicode_latin5 }, 
++		0, /* no name-based mapping */
++		"latin5",
++		"for Turkish",
++		{ "tr_" },
++		'A'
++	},
++	{ /* by Zvezdan Petkovic <z.petkovic@computer.org> */
++		{ unicode_cyrillic, unicode_latin1 },
++		0, /* no name-based mapping */
++		"cyrillic",
++		"in Windows encoding",
++		{ "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" },
++		'A'
++	},
++	{
++		{ unicode_cyrillic, unicode_latin1 },
++		0, /* no name-based mapping */
++		"russian",
++		"obsolete, use cyrillic instead",
++		{ 0 },
++		'A'
++	},
++	{
++		{ unicode_cyrillic, unicode_latin1 },
++		0, /* no name-based mapping */
++		"bulgarian",
++		"obsolete, use cyrillic instead",
++		{ 0 },
++		'A'
++	},
++	{
++		{ unicode_adobestd },
++		unicode_adobestd_byname,
++		"adobestd",
++		"Adobe Standard, expected by TeX",
++		{ NULL },
++		'A'
++	},
++	{
++		{ unicode_plane },
++		0, /* no name-based mapping */
++		"plane",
++		"one plane of Unicode or other multi-byte encoding as is",
++		{ NULL },
++		0 /* no easy way to predict the capital letters */
++	},
++};
++
++static struct uni_language uni_lang_user = {
++	{ unicode_init_user }, 
++	0, /* no name-based mapping */
++	0, /* no name */
++	0, /* no description */
++	{ 0 },
++	0 /* no sample */
++};
++
++static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */
++static int uni_sample='A'; /* sample of an uppercase character */
++static char *uni_lang_arg=""; /* user-supplied language-dependent argument */
++
++extern int      runt1asm(int);
++
++/*
++ * user-defined loadable maps
++ */
++
++
++/* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table.
++ * All the 16-bit unicode space is divided between a number of equal-sized buckets.
++ * Initially all the buckets are marked with 0. Then if any code in the bucket is
++ * used it's marked with 1. Later during translation we check the code's bucket first
++ * and it it's 0 then return failure right away. This may be useful for
++ * Chinese fonts with many thousands of glyphs.
++ */
++
++#define BUCKET_ID_BITS	11
++#define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
++#define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS))
++
++static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS);
++
++static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */
++static int enctabsz = 256; /* actual number of codes used */
++
++static void
++unicode_init_user(
++		 char *path
++)
++{
++	FILE           *unicode_map_file;
++#define UNIBFSZ	256
++	char            buffer[UNIBFSZ];
++	unsigned        code, unicode, curpos, unicode2;
++	char           *arg, *p;
++	int             enabled, found, sawplane;
++	int             lineno, cnt, n, nchars;
++	char            next;
++	int             pid, eid, overid=0;
++
++	/* check if we have an argument (plane name) */
++	arg = strrchr(path, LANG_ARG_SEP);
++	if(arg != 0) {
++		*arg++ = 0;
++		if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) {
++			force_pid = pid; force_eid = eid; overid = 1;
++			WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid);
++			forcemap = 1;
++			arg += nchars;
++			if(*arg == ',')
++				arg++;
++		}
++		if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1) 
++			arg = NULL;
++		else {
++			sprintf(uni_suffix_buf, "-%s", arg);
++			uni_font_name_suffix = uni_suffix_buf;
++		}
++	} 
++
++	/* now read in the encoding description file, if requested */
++	if ((unicode_map_file = fopen(path, "r")) == NULL) {
++		fprintf(stderr, "**** Cannot access map file '%s' ****\n", path);
++		exit(1);
++	}
++
++	sawplane = 0;
++	if(arg==NULL)
++		enabled = found = 1;
++	else
++		enabled = found = 0;
++
++	lineno=0; curpos=0;
++	while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) {
++		char name[UNIBFSZ];
++
++		lineno++;
++
++		if(sscanf(buffer, "plane %s", name)==1) {
++			sawplane = 1;
++			if(arg == 0) {
++				fprintf(stderr, "**** map file '%s' requires plane name\n", path);
++				fprintf(stderr, "for example:\n");
++				fprintf(stderr, "  ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n", 
++					path, LANG_ARG_SEP, name);
++				fprintf(stderr, "to select plane '%s'\n", name);
++				exit(1);
++			}
++			if( !strcmp(arg, name) ) {
++				enabled = found = 1; 
++				curpos = 0;
++			} else {
++				enabled = 0;
++				if(found) /* no need to read further */
++					break;
++			}
++			continue;
++		}
++
++		if(sscanf(buffer, "id %d %d", &pid, &eid)==2) {
++			if( !overid /* only if the user has not overriden */
++			&& (enabled || !sawplane) ) { 
++				force_pid = pid; force_eid = eid;
++				forcemap = 1;
++			}
++			continue;
++		}
++
++		if( !enabled )
++			continue; /* skip to the next plane */
++
++		if( sscanf(buffer, "at %i", &curpos) == 1 ) {
++			if(curpos > 255) {
++				fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno);
++				exit(1);
++			}
++			if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos);
++			continue;
++		}
++
++		/* try the format of Roman Czyborra's files */
++		if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2
++		/* try the format of Linux locale charmap file */
++		|| sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) {
++			if (code < ENCTABSZ) {
++				if(code >= enctabsz) enctabsz=code+1;
++				unicode_map[code] = unicode;
++				glyph_rename[code] = NULL;
++			}
++		}
++		/* try the format with glyph renaming */
++		else if (sscanf (buffer, " !%x U+%4x %128s", &code,
++			&unicode, name) == 3) {
++			if (code < ENCTABSZ) {
++				if(code >= enctabsz) enctabsz=code+1;
++				unicode_map[code] = unicode;
++				glyph_rename[code] = strdup(name);
++			}
++		}
++		/* try the compact sequence format */
++		else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) {
++			p = buffer;
++			do {
++				if(curpos > 255) {
++					fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", 
++						path, lineno, unicode);
++					exit(1);
++				}
++				if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode);
++				unicode_map[curpos++] = unicode;
++				p += cnt;
++				if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) {
++					if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next);
++					p += cnt;
++					if( next == '-' ) { /* range */
++						if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) {
++							fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno);
++							exit(1);
++						}
++						p += cnt;
++						if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2);
++						for(unicode++; unicode <= unicode2; unicode++) {
++							if(curpos > 255) {
++								fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", 
++									path, lineno, unicode2);
++								exit(1);
++							}
++							if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode);
++							unicode_map[curpos++] = unicode;
++						}
++					}
++				}
++			} while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 );
++		}
++
++	}
++
++	fclose (unicode_map_file);
++
++	if( !found ) {
++		fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg);
++		exit(1);
++	}
++
++	if(unicode_map['A'] == 'A')
++		uni_sample = 'A'; /* seems to be compatible with Latin */
++	else
++		uni_sample = 0; /* don't make any assumptions */
++}
++
++/*
++ * by Zvezdan Petkovic <z.petkovic@computer.org> 
++ */
++static void
++unicode_cyrillic(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int cyrillic_unicode_map[] = {
++		0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
++		0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,  /* 88 */
++		0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
++		0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,  /* 98 */
++		0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,  /* A0 */
++		0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,  /* A8 */
++		0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,  /* B0 */
++		0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,  /* B8 */
++	};
++
++	for(i=0; i<=0x7F; i++)
++		unicode_map[i] = i;
++
++	for(i=0x80; i<=0xBF; i++)
++		unicode_map[i] = cyrillic_unicode_map[i-0x80];
++
++	for(i=0xC0; i<=0xFF; i++)
++		unicode_map[i] = i+0x350;
++
++}
++
++static void
++unicode_latin1(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int latin1_unicode_map[] = {
++		0x20ac,     -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
++		0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,  /* 88 */
++		0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
++		0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,  /* 98 */
++	};
++
++	for(i=0; i<=0x7F; i++)
++		unicode_map[i] = i;
++
++	for(i=0x80; i<=0x9F; i++)
++		unicode_map[i] = latin1_unicode_map[i-0x80];
++
++	for(i=0xA0; i<=0xFF; i++)
++		unicode_map[i] = i;
++}
++
++static void
++unicode_adobestd(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int adobestd_unicode_map[] = {
++			-1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7,  /* A0 */
++		0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02,  /* A8 */
++			-1, 0x2013, 0x2020, 0x2021, 0x2219,     -1, 0x00b6, 0x2022,  /* B0 */
++		0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030,     -1, 0x00bf,  /* B8 */
++			-1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9,  /* C0 */
++		0x00a8,     -1, 0x02da, 0x00b8,     -1, 0x02dd, 0x02db, 0x02c7,  /* C8 */
++		0x2014,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D0 */
++			-1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,  /* D8 */
++			-1, 0x00c6,     -1, 0x00aa,     -1,     -1,     -1,     -1,  /* E0 */
++		0x0141, 0x00d8, 0x0152, 0x00ba,     -1,     -1,     -1,     -1,  /* E8 */
++			-1, 0x00e6,     -1,     -1,     -1, 0x0131,     -1,     -1,  /* F0 */
++		0x0142, 0x00f8, 0x0153, 0x00df,     -1,     -1,     -1,     -1,  /* F8 */
++	};
++
++	for(i=0; i<=0x7F; i++)
++		unicode_map[i] = i;
++
++	unicode_map[0x27] = 0x2019;
++	unicode_map[0x60] = -1;
++
++	/* 0x80 to 0x9F is a hole */
++
++	for(i=0xA0; i<=0xFF; i++)
++		unicode_map[i] = adobestd_unicode_map[i-0xA0];
++}
++
++/*
++ * Not all of the Adobe glyphs are in the Unicode
++ * standard maps, so the font creators have
++ * different ideas about their codes. Because
++ * of this we try to map based on the glyph
++ * names instead of Unicode codes. If there are
++ * no glyph names (ps_fmt_3!=0) we fall back
++ * to the code-based scheme.
++ */
++
++static int
++unicode_adobestd_byname(
++		 char *name,
++		 char *arg,
++		 int where
++)
++{
++	int i;
++
++	/* names always take precedence over codes */
++	if(where == UNICONV_BYNAME_AFTER)
++		return -1;
++
++	for(i=32; i<256; i++) {
++		if(!strcmp(name, adobe_StandardEncoding[i]))
++			return i;
++	}
++	return -1;
++
++}
++
++static void
++unicode_latin2(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int latin2_unicode_map[] = {
++		0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7,  /* A0 */
++		0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,  /* A8 */
++		0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7,  /* B0 */
++		0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,  /* B8 */
++		0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,  /* C0 */
++		0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,  /* C8 */
++		0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,  /* D0 */
++		0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,  /* D8 */
++		0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,  /* E0 */
++		0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,  /* E8 */
++		0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,  /* F0 */
++		0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,  /* F8 */
++	};
++
++	for(i=0; i<=0x7E; i++)
++		unicode_map[i] = i;
++
++	/* 7F-9F are unused */
++
++	for(i=0xA0; i<=0xFF; i++)
++		unicode_map[i] = latin2_unicode_map[i-0xA0];
++}
++
++static void
++unicode_latin4(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int latin4_unicode_map[] = {
++		0x0080, 0x0081, 0x201a, 0x0192,     -1, 0x2026, 0x2020, 0x2021,  /* 80 */
++		0x02c6, 0x2030,     -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
++		0x201e, 0x201c, 0x2019,     -1, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
++		0x02dc, 0x2122,     -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
++		0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7,  /* A0 */
++		0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,  /* A8 */
++		0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7,  /* B0 */
++		0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,  /* B8 */
++		0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e,  /* C0 */
++		0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,  /* C8 */
++		0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
++		0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,  /* D8 */
++		0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f,  /* E0 */
++		0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,  /* E8 */
++		0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
++		0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9,  /* F8 */
++	};
++
++	for(i=0; i<=0x7F; i++)
++		unicode_map[i] = i;
++
++	for(i=0x80; i<=0xFF; i++)
++		unicode_map[i] = latin4_unicode_map[i-0x80];
++
++#if 0 /* for documentation purposes only */
++	case 0x201e: return 0x90; /* these two quotes are a hack only */
++	case 0x201c: return 0x91; /* these two quotes are a hack only */
++	case 0x00A0: return 0xA0; /*  NO-BREAK SPACE */
++	case 0x0104: return 0xA1; /*  LATIN CAPITAL LETTER A WITH OGONEK */
++	case 0x0138: return 0xA2; /*  LATIN SMALL LETTER KRA */
++	case 0x0156: return 0xA3; /*  LATIN CAPITAL LETTER R WITH CEDILLA */
++	case 0x00A4: return 0xA4; /*  CURRENCY SIGN */
++	case 0x0128: return 0xA5; /*  LATIN CAPITAL LETTER I WITH TILDE */
++	case 0x013B: return 0xA6; /*  LATIN CAPITAL LETTER L WITH CEDILLA */
++	case 0x00A7: return 0xA7; /*  SECTION SIGN */
++	case 0x00A8: return 0xA8; /*  DIAERESIS */
++	case 0x0160: return 0xA9; /*  LATIN CAPITAL LETTER S WITH CARON */
++	case 0x0112: return 0xAA; /*  LATIN CAPITAL LETTER E WITH MACRON */
++	case 0x0122: return 0xAB; /*  LATIN CAPITAL LETTER G WITH CEDILLA */
++	case 0x0166: return 0xAC; /*  LATIN CAPITAL LETTER T WITH STROKE */
++	case 0x00AD: return 0xAD; /*  SOFT HYPHEN */
++	case 0x017D: return 0xAE; /*  LATIN CAPITAL LETTER Z WITH CARON */
++	case 0x00AF: return 0xAF; /*  MACRON */
++	case 0x00B0: return 0xB0; /*  DEGREE SIGN */
++	case 0x0105: return 0xB1; /*  LATIN SMALL LETTER A WITH OGONEK */
++	case 0x02DB: return 0xB2; /*  OGONEK */
++	case 0x0157: return 0xB3; /*  LATIN SMALL LETTER R WITH CEDILLA */
++	case 0x00B4: return 0xB4; /*  ACUTE ACCENT */
++	case 0x0129: return 0xB5; /*  LATIN SMALL LETTER I WITH TILDE */
++	case 0x013C: return 0xB6; /*  LATIN SMALL LETTER L WITH CEDILLA */
++	case 0x02C7: return 0xB7; /*  CARON */
++	case 0x00B8: return 0xB8; /*  CEDILLA */
++	case 0x0161: return 0xB9; /*  LATIN SMALL LETTER S WITH CARON */
++	case 0x0113: return 0xBA; /*  LATIN SMALL LETTER E WITH MACRON */
++	case 0x0123: return 0xBB; /*  LATIN SMALL LETTER G WITH CEDILLA */
++	case 0x0167: return 0xBC; /*  LATIN SMALL LETTER T WITH STROKE */
++	case 0x014A: return 0xBD; /*  LATIN CAPITAL LETTER ENG */
++	case 0x017E: return 0xBE; /*  LATIN SMALL LETTER Z WITH CARON */
++	case 0x014B: return 0xBF; /*  LATIN SMALL LETTER ENG */
++	case 0x0100: return 0xC0; /*  LATIN CAPITAL LETTER A WITH MACRON */
++	case 0x00C1: return 0xC1; /*  LATIN CAPITAL LETTER A WITH ACUTE */
++	case 0x00C2: return 0xC2; /*  LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
++	case 0x00C3: return 0xC3; /*  LATIN CAPITAL LETTER A WITH TILDE */
++	case 0x00C4: return 0xC4; /*  LATIN CAPITAL LETTER A WITH DIAERESIS */
++	case 0x00C5: return 0xC5; /*  LATIN CAPITAL LETTER A WITH RING ABOVE */
++	case 0x00C6: return 0xC6; /*  LATIN CAPITAL LIGATURE AE */
++	case 0x012E: return 0xC7; /*  LATIN CAPITAL LETTER I WITH OGONEK */
++	case 0x010C: return 0xC8; /*  LATIN CAPITAL LETTER C WITH CARON */
++	case 0x00C9: return 0xC9; /*  LATIN CAPITAL LETTER E WITH ACUTE */
++	case 0x0118: return 0xCA; /*  LATIN CAPITAL LETTER E WITH OGONEK */
++	case 0x00CB: return 0xCB; /*  LATIN CAPITAL LETTER E WITH DIAERESIS */
++	case 0x0116: return 0xCC; /*  LATIN CAPITAL LETTER E WITH DOT ABOVE */
++	case 0x00CD: return 0xCD; /*  LATIN CAPITAL LETTER I WITH ACUTE */
++	case 0x00CE: return 0xCE; /*  LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
++	case 0x012A: return 0xCF; /*  LATIN CAPITAL LETTER I WITH MACRON */
++	case 0x0110: return 0xD0; /*  LATIN CAPITAL LETTER D WITH STROKE */
++	case 0x0145: return 0xD1; /*  LATIN CAPITAL LETTER N WITH CEDILLA */
++	case 0x014C: return 0xD2; /*  LATIN CAPITAL LETTER O WITH MACRON */
++	case 0x0136: return 0xD3; /*  LATIN CAPITAL LETTER K WITH CEDILLA */
++	case 0x00D4: return 0xD4; /*  LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
++	case 0x00D5: return 0xD5; /*  LATIN CAPITAL LETTER O WITH TILDE */
++	case 0x00D6: return 0xD6; /*  LATIN CAPITAL LETTER O WITH DIAERESIS */
++	case 0x00D7: return 0xD7; /*  MULTIPLICATION SIGN */
++	case 0x00D8: return 0xD8; /*  LATIN CAPITAL LETTER O WITH STROKE */
++	case 0x0172: return 0xD9; /*  LATIN CAPITAL LETTER U WITH OGONEK */
++	case 0x00DA: return 0xDA; /*  LATIN CAPITAL LETTER U WITH ACUTE */
++	case 0x00DB: return 0xDB; /*  LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
++	case 0x00DC: return 0xDC; /*  LATIN CAPITAL LETTER U WITH DIAERESIS */
++	case 0x0168: return 0xDD; /*  LATIN CAPITAL LETTER U WITH TILDE */
++	case 0x016A: return 0xDE; /*  LATIN CAPITAL LETTER U WITH MACRON */
++	case 0x00DF: return 0xDF; /*  LATIN SMALL LETTER SHARP S */
++	case 0x0101: return 0xE0; /*  LATIN SMALL LETTER A WITH MACRON */
++	case 0x00E1: return 0xE1; /*  LATIN SMALL LETTER A WITH ACUTE */
++	case 0x00E2: return 0xE2; /*  LATIN SMALL LETTER A WITH CIRCUMFLEX */
++	case 0x00E3: return 0xE3; /*  LATIN SMALL LETTER A WITH TILDE */
++	case 0x00E4: return 0xE4; /*  LATIN SMALL LETTER A WITH DIAERESIS */
++	case 0x00E5: return 0xE5; /*  LATIN SMALL LETTER A WITH RING ABOVE */
++	case 0x00E6: return 0xE6; /*  LATIN SMALL LIGATURE AE */
++	case 0x012F: return 0xE7; /*  LATIN SMALL LETTER I WITH OGONEK */
++	case 0x010D: return 0xE8; /*  LATIN SMALL LETTER C WITH CARON */
++	case 0x00E9: return 0xE9; /*  LATIN SMALL LETTER E WITH ACUTE */
++	case 0x0119: return 0xEA; /*  LATIN SMALL LETTER E WITH OGONEK */
++	case 0x00EB: return 0xEB; /*  LATIN SMALL LETTER E WITH DIAERESIS */
++	case 0x0117: return 0xEC; /*  LATIN SMALL LETTER E WITH DOT ABOVE */
++	case 0x00ED: return 0xED; /*  LATIN SMALL LETTER I WITH ACUTE */
++	case 0x00EE: return 0xEE; /*  LATIN SMALL LETTER I WITH CIRCUMFLEX */
++	case 0x012B: return 0xEF; /*  LATIN SMALL LETTER I WITH MACRON */
++	case 0x0111: return 0xF0; /*  LATIN SMALL LETTER D WITH STROKE */
++	case 0x0146: return 0xF1; /*  LATIN SMALL LETTER N WITH CEDILLA */
++	case 0x014D: return 0xF2; /*  LATIN SMALL LETTER O WITH MACRON */
++	case 0x0137: return 0xF3; /*  LATIN SMALL LETTER K WITH CEDILLA */
++	case 0x00F4: return 0xF4; /*  LATIN SMALL LETTER O WITH CIRCUMFLEX */
++	case 0x00F5: return 0xF5; /*  LATIN SMALL LETTER O WITH TILDE */
++	case 0x00F6: return 0xF6; /*  LATIN SMALL LETTER O WITH DIAERESIS */
++	case 0x00F7: return 0xF7; /*  DIVISION SIGN */
++	case 0x00F8: return 0xF8; /*  LATIN SMALL LETTER O WITH STROKE */
++	case 0x0173: return 0xF9; /*  LATIN SMALL LETTER U WITH OGONEK */
++	case 0x00FA: return 0xFA; /*  LATIN SMALL LETTER U WITH ACUTE */
++	case 0x00FB: return 0xFB; /*  LATIN SMALL LETTER U WITH CIRCUMFLEX */
++	case 0x00FC: return 0xFC; /*  LATIN SMALL LETTER U WITH DIAERESIS */
++	case 0x0169: return 0xFD; /*  LATIN SMALL LETTER U WITH TILDE */
++	case 0x016B: return 0xFE; /*  LATIN SMALL LETTER U WITH MACRON */
++	case 0x02D9: return 0xFF; /*  DOT ABOVE */
++#endif
++}
++
++static void
++unicode_latin5(
++		 char *arg
++)
++{
++	int i;
++	static unsigned int latin5_unicode_map1[] = {
++		0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,  /* 80 */
++		0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,  /* 88 */
++		0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,  /* 90 */
++		0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,  /* 98 */
++	};
++	static unsigned int latin5_unicode_map2[] = {
++		0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,  /* D0 */
++		0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,  /* D8 */
++		0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,  /* E0 direct */
++		0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,  /* E8 direct */
++		0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,  /* F0 */
++		0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff,  /* F8 */
++	};
++
++	for(i=0; i<=0x7F; i++)
++		unicode_map[i] = i;
++
++	for(i=0x80; i<=0x9F; i++)
++		unicode_map[i] = latin5_unicode_map1[i-0x80];
++
++	for(i=0xA0; i<=0xCF; i++)
++		unicode_map[i] = i;
++
++	for(i=0xD0; i<=0xFF; i++)
++		unicode_map[i] = latin5_unicode_map2[i-0xD0];
++}
++
++/* a way to select one 256-character plane from Unicode 
++ * or other multi-byte encoding
++ */
++
++static void
++unicode_plane(
++		 char *arg
++)
++{
++	static unsigned plane;
++	int nchars;
++	int c1, c2, i;
++
++	if(uni_lang_selected == 0)
++		return; /* don't participate in auto-guessing */
++
++	plane = 0; force_pid = force_eid = -1;
++
++	c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars);
++	if(c1 == 2) {
++		arg += nchars;
++		if(*arg == ',')
++			arg++;
++	}
++	if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) {
++		arg += 2;
++		c2 = sscanf(arg, "%x", &plane);
++	} else {
++		c2 = sscanf(arg, "%d", &plane);
++	}
++
++	if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) {
++		fprintf(stderr, "**** option -l plane expects one of the following formats:\n");
++		fprintf(stderr, "  -l plane+0xNN - select hexadecimal number of plane of Unicode\n");
++		fprintf(stderr, "  -l plane+NN - select decimal number of plane of Unicode\n");
++		fprintf(stderr, "  -l plane+pid=N,eid=N - select plane 0 of specified encoding\n");
++		fprintf(stderr, "  -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n");
++		fprintf(stderr, "  -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n");
++		exit(1);
++	}
++
++	if(c2!=0) {
++		if(strlen(arg) > sizeof(uni_suffix_buf)-2) {
++			fprintf(stderr, "**** plane number is too large\n");
++		}
++
++		sprintf(uni_suffix_buf, "-%s", arg);
++		uni_font_name_suffix = uni_suffix_buf;
++	} else {
++		uni_font_name_suffix = "";
++	}
++
++	plane <<= 8;
++	for(i=0; i<=0xFF; i++)
++		unicode_map[i] = plane | i;
++}
++
++/* look up the 8-bit code by unicode */
++
++int
++unicode_rev_lookup(
++		 int unival
++)
++{
++	int res;
++
++	if( ! IS_UNI_BUCKET(unival) )
++		return -1;
++
++	for (res = 0; res < enctabsz; res++)
++		if (unicode_map[res] == unival)
++			return res;
++	return -1;
++}
++
++/* mark the buckets for quick lookup */
++
++static void
++unicode_prepare_buckets(
++	void
++)
++{
++	int i;
++
++	memset(uni_user_buckets, 0, sizeof uni_user_buckets);
++	for(i=0; i<enctabsz; i++) {
++		if(unicode_map[i] != (unsigned) -1)
++			MARK_UNI_BUCKET(unicode_map[i]);
++	}
++}
++
++/*
++ * When we print errors about bad names we want to print these names in
++ * some decent-looking form
++ */
++
++static char *
++nametoprint(
++	unsigned char *s
++)
++{
++	static char res[50];
++	int c, i;
++
++	for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) {
++		if(c < ' ' || c > 126) {
++			sprintf(res+i, "\\x%02X", c);
++			i+=4;
++		} else {
++			res[i++] = c;
++		}
++	}
++	if(*s != 0) {
++		res[i++] = '.';
++		res[i++] = '.';
++		res[i++] = '.';
++	}
++	res[i++] = 0;
++	return res;
++}
++
++/*
++ * Scale the values according to the scale_factor
++ */
++
++double
++fscale(
++      double val
++)
++{
++	return scale_factor * val;
++}
++
++int
++iscale(
++      int val
++)
++{
++	return (int) (val > 0 ? scale_factor * val + 0.5
++		      : scale_factor * val - 0.5);
++}
++
++/*
++ * Try to force fixed width of characters
++ */
++
++static void
++alignwidths(void)
++{
++	int             i;
++	int             n = 0, avg, max = 0, min = 3000, sum = 0, x;
++
++	for (i = 0; i < numglyphs; i++) {
++		if (glyph_list[i].flags & GF_USED) {
++			x = glyph_list[i].width;
++
++			if (x != 0) {
++				if (x < min)
++					min = x;
++				if (x > max)
++					max = x;
++
++				sum += x;
++				n++;
++			}
++		}
++	}
++
++	if (n == 0)
++		return;
++
++	avg = sum / n;
++
++	WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min);
++
++	/* if less than 5% variation from average */
++	/* force fixed width */
++	if (20 * (avg - min) < avg && 20 * (max - avg) < avg) {
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].flags & GF_USED)
++				glyph_list[i].width = avg;
++		}
++		fontm.is_fixed_pitch = 1;
++	}
++}
++
++static void
++convert_glyf(
++	int	glyphno
++)
++{
++	GLYPH          *g;
++	int ncurves;
++
++	g = &glyph_list[glyphno];
++
++
++	g->scaledwidth = iscale(g->width);
++
++	g->entries = 0;
++	g->lastentry = 0;
++	g->path = 0;
++	if (g->ttf_pathlen != 0) {
++		cursw->glpath(glyphno, glyph_list);
++		g->lastentry = 0;
++
++		if(ISDBG(BUILDG))
++			dumppaths(g, NULL, NULL);
++
++		assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++		fclosepaths(g);
++		assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++		/* float processing */
++		if(smooth) {
++			ffixquadrants(g);
++			assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++			fsplitzigzags(g);
++			assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++			fforceconcise(g);
++			assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++			fstraighten(g);
++			assertpath(g->entries, __FILE__, __LINE__, g->name);
++		}
++
++		pathtoint(g); 
++		/* all processing past this point expects integer path */
++		assertpath(g->entries, __FILE__, __LINE__, g->name);
++
++#if 0
++		fixcontours(g);
++		testfixcvdir(g);
++#endif
++
++		/* int processing */
++		if (smooth) {
++			smoothjoints(g);
++			assertpath(g->entries, __FILE__, __LINE__, g->name);
++		}
++
++		ncurves = 0;
++		{
++			GENTRY *ge;
++			for(ge = g->entries; ge; ge = ge->next)
++				ncurves++;
++		}
++		if (ncurves > 200) {
++			WARNING_3 fprintf(stderr,
++			"** Glyph %s is too long, may display incorrectly\n",
++				g->name);
++		}
++	} else {
++		/* for buildstems */
++		g->flags &= ~GF_FLOAT;
++	}
++}
++
++static void
++handle_gnames(void)
++{
++	int             i, n, found, c, type;
++
++	/* get the names from the font file */
++	ps_fmt_3 = cursw->glnames(glyph_list);
++
++/* These checks are not required by Xprt's PS DDX... */
++#ifndef XP_PSTEXT
++	/* check for names with wrong characters */
++	for (n = 0; n < numglyphs; n++) {
++		int             c;
++		for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) {
++			if (!(isalnum(c) || c == '.' || c == '_' || c == '-') 
++			|| i==0 && isdigit(c)) { /* must not start with a digit */
++				WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ",
++					n, isdigit(c) ? "name starts with a digit" : 
++						"has bad characters in name",
++					nametoprint(glyph_list[n].name));
++				glyph_list[n].name = malloc(16);
++				sprintf(glyph_list[n].name, "_b_%d", n);
++				WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name);
++				break;
++			}
++		}
++	}
++
++	if( !ps_fmt_3 ) {
++		/* check for duplicate names */
++		for (n = 0; n < numglyphs; n++) {
++			found = 0;
++			for (i = 0; i < n && !found; i++) {
++				if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) {
++					if (( glyph_list[n].name = malloc(16) )==0) {
++						fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++						exit(255);
++					}
++					sprintf(glyph_list[n].name, "_d_%d", n);
++
++					/* if the font has no names in it (what the native parser
++					 * recognises as ps_fmt_3), FreeType returns all the 
++					 * names as .notdef, so don't complain in this case
++					 */
++					if(strcmp(glyph_list[i].name, ".notdef")) {
++						WARNING_3 fprintf(stderr,
++							"Glyph %d has the same name as %d: (%s), changing to %s\n",
++							n, i,
++							glyph_list[i].name,
++							glyph_list[n].name);
++					}
++					found = 1;
++				}
++			}
++		}
++
++	}
++#endif /* !XP_PSTEXT */
++
++	/* start the encoding stuff */
++	for (i = 0; i < ENCTABSZ; i++) {
++		encoding[i] = -1;
++	}
++
++	/* do the 1st round of encoding by name */
++	if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) {
++		for (n = 0; n < numglyphs; n++) {
++			c = uni_lang_selected->convbyname(glyph_list[n].name, 
++				uni_lang_arg, UNICONV_BYNAME_BEFORE);
++			if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
++				encoding[c] = n;
++		}
++	}
++
++	/* now do the encoding by table */
++	if(uni_lang_selected) {
++		for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) {
++			for (n = 0; n < ENCTABSZ; n++)
++				unicode_map[n] = -1;
++			uni_lang_selected->init[i](uni_lang_arg);
++			unicode_prepare_buckets();
++			type = cursw->glenc(glyph_list, encoding, unicode_map);
++			if( type == 0 )
++				/* if we have an 8-bit encoding we don't need more tries */
++				break;
++		}
++	} else {
++		/* language is unknown, try the first table of each */
++		for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) {
++			if(uni_lang[i].init[0] == NULL)
++				continue;
++			for (n = 0; n < ENCTABSZ; n++)
++				unicode_map[n] = -1;
++			uni_lang[i].init[0](uni_lang_arg);
++			unicode_prepare_buckets();
++			type = cursw->glenc(glyph_list, encoding, unicode_map);
++			if( type == 0 )
++				/* if we have an 8-bit encoding we don't need more tries */
++				break;
++		}
++	}
++
++	if (ps_fmt_3) {
++		/* get rid of the old names, they are all "UNKNOWN" anyawy */
++		for (i = 0; i < numglyphs; i++) {
++			glyph_list[i].name = 0;
++		}
++		if(type == 0) { 
++			/* 8-bit - give 8859/1 names to the first 256 glyphs */
++			for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
++				if (encoding[i] > 0) {
++					glyph_list[encoding[i]].name = Fmt3Encoding[i];
++				}
++			}
++		} else if(type == 1) {
++			/* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */
++			for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */
++				i = unicode_rev_lookup(n);
++				if (i>=0 && encoding[i] > 0) {
++					glyph_list[encoding[i]].name = Fmt3Encoding[i];
++				}
++			}
++		} /* for other types of encodings just give generated names */
++		/* assign unique names to the rest of the glyphs */
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].name == 0) {
++				if (( glyph_list[i].name = malloc(16) )==0) {
++					fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++					exit(255);
++				}
++				sprintf(glyph_list[i].name, "_d_%d", i);
++			}
++		}
++	}
++
++	/* do the 2nd round of encoding by name */
++	if(uni_lang_selected && uni_lang_selected->convbyname) {
++		for (n = 0; n < numglyphs; n++) {
++			c = uni_lang_selected->convbyname(glyph_list[n].name, 
++				uni_lang_arg, UNICONV_BYNAME_AFTER);
++			if(c>=0 && c<ENCTABSZ && encoding[c] == -1)
++				encoding[c] = n;
++		}
++	}
++	/* all the encoding things are done */
++
++	for (i = 0; i < ENCTABSZ; i++)
++		if(encoding[i] == -1) {
++			/* check whether this character might be a duplicate 
++			 * (in which case it would be missed by unicode_rev_lookup())
++			 */
++			c = unicode_map[i];
++			if((type != 0 || forcemap) && c != -1) {
++				for(n = 0; n < i; n++) {
++					if(unicode_map[n] == c) {
++						encoding[i] = encoding[n];
++					}
++				}
++			}
++			if(encoding[i] == -1) /* still not found, defaults to .notdef */
++				encoding[i] = 0;
++		}
++
++	for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */
++		glyph_list[encoding[i]].char_no = i;
++
++#ifndef XP_PSTEXT
++	/* enforce two special cases defined in TTF manual */
++	if(numglyphs > 0)
++		glyph_list[0].name = ".notdef";
++	if(numglyphs > 1)
++		glyph_list[1].name = ".null";
++#endif /* !XP_PSTEXT */
++
++ 	for (i = 0; i < ENCTABSZ; i++) {
++ 		if ((encoding[i] != 0) && glyph_rename[i]) {
++ 		    glyph_list[encoding[i]].name = glyph_rename[i];
++ 		}
++ 	}
++}
++
++static void
++usage(void)
++{
++
++#ifdef XP_PSTEXT
++    fputs("ft2pt1: Internal startup error\n", stderr);
++#else
++
++#ifdef _GNU_SOURCE
++#	define fplop(txt)	fputs(txt, stderr);
++#else
++#	define fplop(txt)
++#endif
++
++	fputs("Use:\n", stderr);
++	fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr);
++	fputs("  or\n", stderr);
++	fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr);
++	fputs("  or\n", stderr);
++	fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr);
++
++	fplop("\n");
++	fplop("This build supports both short and long option names,\n");
++	fplop("the long options are listed before corresponding short ones\n");
++
++	fplop(" --all-glyphs\n");
++	fputs("  -a - include all glyphs, even those not in the encoding table\n", stderr);
++	fplop(" --pfb\n");
++	fputs("  -b - produce a compressed .pfb file\n", stderr);
++	fplop(" --debug dbg_suboptions\n");
++	fputs("  -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr);
++	fplop(" --encode\n");
++	fputs("  -e - produce a fully encoded .pfa file\n", stderr);
++	fplop(" --force-unicode\n");
++	fputs("  -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); 
++	fplop(" --generate suboptions\n");
++	fputs("  -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr);
++	fplop(" --language language\n");
++	fputs("  -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr);
++	fplop(" --language-map file\n");
++	fputs("  -L file - convert Unicode according to encoding description file\n", stderr);
++	fplop(" --limit <type>=<value>\n");
++	fputs("  -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr);
++	fputs("      h - maximal hint stack depth in the PostScript interpreter\n", stderr);
++	fplop(" --processing suboptions\n");
++	fputs("  -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr);
++	fplop(" --parser name\n");
++	fputs("  -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr);
++	fplop(" --uid id\n");
++	fputs("  -u id - use this UniqueID, -u A means autogeneration\n", stderr);
++	fplop(" --vertical-autoscale size\n");
++	fputs("  -v size - scale the font to make uppercase letters >size/1000 high\n", stderr);
++	fplop(" --version\n");
++	fputs("  -V - print ttf2pt1 version number\n", stderr);
++	fplop(" --warning number\n");
++	fputs("  -W number - set the level of permitted warnings (0 - disable)\n", stderr);
++	fputs("Obsolete options (will be removed in future releases):\n", stderr);
++	fplop(" --afm\n");
++	fputs("  -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr);
++	fputs("  -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr);
++	fputs("  -h - disable autogeneration of hints, now -Oh\n", stderr);
++	fputs("  -H - disable hint substitution, now -Ou\n", stderr);
++	fputs("  -o - disable outline optimization, now -Oo\n", stderr);
++	fputs("  -s - disable outline smoothing, now -Os\n", stderr);
++	fputs("  -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr);
++	fputs("  -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr);
++	fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr);
++	fputs("The last '-' means 'use STDOUT'.\n", stderr);
++
++#undef fplop
++
++#endif /* XP_PSTEXT */
++}
++
++static void
++printversion(void)
++{
++  fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION);
++}
++
++/* initialize a table of suboptions */
++static void
++init_subo_tbl(
++	struct subo_case *tbl
++)
++{
++	int i;
++
++	for(i=0; tbl[i].disbl != 0; i++) {
++		tbl[i].disbl = tolower(tbl[i].disbl);
++		tbl[i].enbl = toupper(tbl[i].disbl);
++		*(tbl[i].valp) = tbl[i].dflt;
++	}
++}
++  
++/* print the default value of the suboptions */
++static void
++print_subo_dflt(
++	FILE *f,
++	struct subo_case *tbl
++)
++{
++	int i;
++
++	for(i=0; tbl[i].disbl != 0; i++) {
++		if(tbl[i].dflt)
++			putc(tbl[i].enbl, f);
++		else
++			putc(tbl[i].disbl, f);
++	}
++}
++  
++/* print the usage message for the suboptions */
++static void
++print_subo_usage(
++	FILE *f,
++	struct subo_case *tbl
++)
++{
++#ifdef XP_PSTEXT
++    fputs("ft2pt1: Internal startup error\n", stderr);
++#else
++	int i;
++
++	fprintf(f,"The lowercase suboptions disable features, corresponding\n");
++	fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n");
++	fprintf(f,"their default states and the features they control are:\n");
++	for(i=0; tbl[i].disbl != 0; i++) {
++		fprintf(f,"   %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl,
++			tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr);
++	}
++#endif /* XP_PSTEXT */
++}
++
++/* find and set the entry according to suboption,
++ * return the found entry (or if not found return NULL)
++ */
++struct subo_case *
++set_subo(
++	struct subo_case *tbl,
++	int subopt
++)
++{
++	int i;
++
++	for(i=0; tbl[i].disbl != 0; i++) {
++		if(subopt == tbl[i].disbl) {
++			*(tbl[i].valp) = 0;
++			return &tbl[i];
++		} else if(subopt == tbl[i].enbl) {
++			*(tbl[i].valp) = 1;
++			return &tbl[i];
++		} 
++	}
++	return NULL;
++}
++
++
++#ifdef XP_PSTEXT
++FT_Face         xp_pstext_ft_face     = NULL; /* used by ft.c */
++FontPtr       xp_xtf                = NULL;
++const char     *xp_psfontname         = NULL;
++unsigned long   xp_font_block_offset  = 0UL;
++
++int
++ft2pt1_main(
++     int            argc,
++     char         **argv,
++     FTFontPtr      tf,
++     const char    *download_psfontname,
++     unsigned long  download_font_block_offset
++)
++#else
++int
++main(
++     int argc,
++     char **argv
++)
++#endif /* XP_PSTEXT */
++{
++	long            i, j;
++	time_t          now;
++	char            filename[4096];
++	int             c,nchars,nmetrics;
++	int             ws;
++	int             forcebold= -1; /* -1 means "don't know" */
++	char           *lang;
++	int             oc;
++	int             subid;
++	char           *cmdline;
++#ifdef _GNU_SOURCE
++#	define ttf2pt1_getopt(a, b, c, d, e)	getopt_long(a, b, c, d, e)
++	static struct option longopts[] = {
++		{ "afm", 0, NULL, 'A' },
++		{ "all-glyphs", 0, NULL, 'a' },
++		{ "pfb", 0, NULL, 'b' },
++		{ "debug", 1, NULL, 'd' },
++		{ "encode", 0, NULL, 'e' },
++		{ "force-unicode", 0, NULL, 'F' },
++		{ "generate", 1, NULL, 'G' },
++		{ "language", 1, NULL, 'l' },
++		{ "language-map", 1, NULL, 'L' },
++		{ "limit", 1, NULL, 'm' },
++		{ "processing", 1, NULL, 'O' },
++		{ "parser", 1, NULL, 'p' },
++		{ "uid", 1, NULL, 'u' },
++		{ "vertical-autoscale", 1, NULL, 'v' },
++		{ "version", 0, NULL, 'V' },
++		{ "warning", 1, NULL, 'W' },
++		{ NULL, 0, NULL, 0 }
++	};
++#else
++#	define ttf2pt1_getopt(a, b, c, d, e)	getopt(a, b, c)
++#endif
++	/* table of Outline Processing (may think also as Optimization) options */
++	static struct subo_case opotbl[] = {
++		{ 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" },
++		{ 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" },
++		{ 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" },
++		{ 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" },
++		{ 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" },
++		{ 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" },
++		{ 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" },
++		{ 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" },
++#ifdef USE_AUTOTRACE
++		{ 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" },
++#endif /*USE_AUTOTRACE*/
++		{ 0, 0, 0, 0, 0} /* terminator */
++	};
++	/* table of the File Generation options */
++	static struct subo_case fgotbl[] = {
++		{ 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" },
++		{ 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" },
++		{ 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" },
++		{ 0, 0, 0, 0, 0} /* terminator */
++	};
++	int *genlast = NULL;
++
++#ifdef XP_PSTEXT
++        xp_pstext_ft_face    = tf->instance->face->face;
++        xp_xtf               = tf;
++        xp_psfontname        = download_psfontname;
++        xp_font_block_offset = download_font_block_offset;
++#endif /* XP_PSTEXT */
++
++	init_subo_tbl(opotbl); /* initialize sub-options of -O */
++	init_subo_tbl(fgotbl); /* initialize sub-options of -G */
++
++	/* save the command line for the record 
++	 * (we don't bother about escaping the shell special characters)
++	 */
++
++	j = 0;
++	for(i=1; i<argc; i++) {
++		j += strlen(argv[i])+1;
++	}
++	if ((cmdline = malloc(j+1)) == NULL) {
++		fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++		exit(255);
++	}
++	cmdline[0] = 0;
++	for(i=1; i<argc; i++) {
++		strcat(cmdline, argv[i]);
++		strcat(cmdline, " ");
++	}
++	for(i=0; (j=cmdline[i])!=0; i++)
++		if(j == '\n')
++			cmdline[i] = ' ';
++
++
++	while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:",
++			longopts, NULL) )!= -1) {
++		switch(oc) {
++		case 'W':
++			if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) {
++				fprintf(stderr, "**** warning level must be a positive number\n");
++				exit(1);
++			}
++			break;
++		case 'F':
++			forcemap = 1;
++			break;
++		case 'o':
++			fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr);
++			optimize = 0;
++			break;
++		case 'e':
++			encode = 1;
++			break;
++		case 'b':
++			encode = pfbflag = 1;
++			break;
++		case 'A':
++			fputs("Warning: option -A is obsolete, use -GA instead\n", stderr);
++			wantafm = 1;
++			break;
++		case 'a':
++			allglyphs = 1;
++			break;
++		case 's':
++			fputs("Warning: option -s is obsolete, use -Os instead\n", stderr);
++			smooth = 0;
++			break;
++		case 't':
++			fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr);
++			transform = 0;
++			break;
++		case 'd':
++			for(i=0; optarg[i]!=0; i++)
++				switch(optarg[i]) {
++				case 'a':
++					absolute = 1;
++					break;
++				case 'r':
++					reverse = 0;
++					break;
++				default:
++					if (optarg[i] != '?')
++					  fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]);
++					fputs("The recognized debugging options are:\n", stderr);
++					fputs("  a - enable absolute coordinates\n", stderr);
++					fputs("  r - do not reverse font outlines directions\n", stderr);
++					exit(1);
++					break;
++				};
++			break;
++		case 'm':
++		{
++			char subopt;
++			int val;
++
++			if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) {
++				fprintf(stderr, "**** Misformatted maximal limit ****\n");
++				fprintf(stderr, "spaces around the equal sign are not allowed\n");
++				fprintf(stderr, "good examples: -mh=100 -m h=100\n");
++				fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n");
++				exit(1);
++				break;
++			}
++			switch(subopt) {
++			case 'h':
++				max_stemdepth = val;
++				break;
++			default:
++				if (subopt != '?')
++				  fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt);
++				fputs("The recognized limit types are:\n", stderr);
++				fputs("  h - maximal hint stack depth in the PostScript interpreter\n", stderr);
++				exit(1);
++				break;
++			}
++			break;
++		}
++		case 'O':
++		{
++			char *p;
++			for(p=optarg; *p != 0; p++) {
++				if(set_subo(opotbl, *p) == NULL) { /* found no match */
++					if (*p != '?')
++						fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
++					fprintf(stderr,"The general form of the outline processing option is:\n");
++					fprintf(stderr,"   -O suboptions\n");
++					fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n");
++					print_subo_usage(stderr, opotbl);
++					fprintf(stderr, "The default state corresponds to the option -O ");
++					print_subo_dflt(stderr, opotbl);
++					fprintf(stderr, "\n");
++					exit(1);
++				}
++			}
++			break;
++		}
++		case 'G':
++		{
++			char *p;
++			struct subo_case *s;
++
++			for(p=optarg; *p != 0; p++) {
++				if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */
++					if (*p != '?')
++						fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p);
++					fprintf(stderr,"The general form of the file generation option is:\n");
++					fprintf(stderr,"   -G suboptions\n");
++					print_subo_usage(stderr, fgotbl);
++					fprintf(stderr, "The default state corresponds to the option -G ");
++					print_subo_dflt(stderr, fgotbl);
++					fprintf(stderr, "\n");
++					fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n");
++					fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n");
++					exit(1);
++				}
++				if( *(s->valp) )
++					genlast = s->valp;
++			}
++			break;
++		}
++		case 'h':
++			fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr);
++			hints = 0;
++			break;
++		case 'H':
++			fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr);
++			fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr);
++			subhints = 0;
++			break;
++		case 'f':
++			fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr);
++			trybold = 0;
++			break;
++		case 'w':
++			fputs("Warning: option -w is obsolete, use -OW instead\n", stderr);
++			correctwidth = 1;
++			break;
++		case 'u':
++			if(wantuid) {
++				fprintf(stderr, "**** UniqueID may be specified only once ****\n");
++				exit(1);
++			}
++			wantuid = 1; 
++			if(optarg[0]=='A' && optarg[1]==0)
++				strUID=0; /* will be generated automatically */
++			else {
++				strUID=optarg;
++				for(i=0; optarg[i]!=0; i++)
++					if( !isdigit(optarg[i]) ) {
++						fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n");
++						exit(1);
++					}
++			}
++			break;
++		case 'v':
++			correctvsize = atoi(optarg);
++			if(correctvsize <= 0 && correctvsize > 1000) {
++				fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize);
++				correctvsize=0;
++			}
++			break;
++		case 'p':
++			if(cursw!=0) {
++				fprintf(stderr, "**** only one front-end parser be used ****\n");
++				exit(1);
++			}
++
++			{ /* separate parser from parser-specific argument */
++				char *p = strchr(optarg, LANG_ARG_SEP);
++				if(p != 0) {
++					*p = 0;
++					front_arg = p+1;
++				} else
++					front_arg = "";
++			}
++			for(i=0; frontswtab[i] != NULL; i++)
++				if( !strcmp(frontswtab[i]->name, optarg) ) {
++					cursw = frontswtab[i];
++					break;
++				}
++
++			if(cursw==0) {
++				if (strcmp(optarg, "?"))
++				  fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg);
++				fputs("the following front-ends are supported now:\n", stderr);
++				for(i=0; frontswtab[i] != NULL; i++) {
++					fprintf(stderr,"  %s (%s)\n   file suffixes: ", 
++						frontswtab[i]->name,
++						frontswtab[i]->descr ? frontswtab[i]->descr : "no description"
++					);
++					for(j=0; j<MAXSUFFIX; j++)
++						if(frontswtab[i]->suffix[j])
++							fprintf(stderr, "%s ", frontswtab[i]->suffix[j]);
++					fprintf(stderr, "\n");
++				}
++				exit(1);
++			}
++			break;
++		case 'l':
++			if(uni_lang_selected!=0) {
++				fprintf(stderr, "**** only one language option may be used ****\n");
++				exit(1);
++			}
++
++			{ /* separate language from language-specific argument */
++				char *p = strchr(optarg, LANG_ARG_SEP);
++				if(p != 0) {
++					*p = 0;
++					uni_lang_arg = p+1;
++				} else
++					uni_lang_arg = "";
++			}
++			for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
++				if( !strcmp(uni_lang[i].name, optarg) ) {
++					uni_lang_selected = &uni_lang[i];
++					uni_sample = uni_lang[i].sample_upper;
++					break;
++				}
++
++			if(uni_lang_selected==0) {
++				if (strcmp(optarg, "?"))
++					fprintf(stderr, "**** unknown language '%s' ****\n", optarg);
++				fputs("       the following languages are supported now:\n", stderr);
++				for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++)
++					fprintf(stderr,"         %s (%s)\n", 
++						uni_lang[i].name,
++						uni_lang[i].descr ? uni_lang[i].descr : "no description"
++					);
++				exit(1);
++			}
++			break;
++		case 'L':
++			if(uni_lang_selected!=0) {
++				fprintf(stderr, "**** only one language option may be used ****\n");
++				exit(1);
++			}
++			uni_lang_selected = &uni_lang_user;
++			uni_lang_arg = optarg;
++			break;
++		case 'V':
++			printversion();
++			exit(0);
++			break;
++		default:
++			usage();
++			exit(1);
++			break;
++		}
++	}
++	argc-=optind-1; /* the rest of code counts from argv[0] */
++	argv+=optind-1;
++
++	if (absolute && encode) {
++		fprintf(stderr, "**** options -a and -e are incompatible ****\n");
++		exit(1);
++	}
++        if ((argc != 2) && (argc != 3)) {
++		usage();
++		exit(1);
++	}
++
++	/* try to guess the language by the locale used */
++	if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) {
++		for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
++			if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) {
++				uni_lang_selected = &uni_lang[i];
++				goto got_a_language;
++			}
++		}
++		/* no full name ? try aliases */
++		for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) {
++			for(c=0; c<MAXUNIALIAS; c++)
++				if( uni_lang[i].alias[c]!=0
++				&& !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) {
++					uni_lang_selected = &uni_lang[i];
++					goto got_a_language;
++				}
++		}
++	got_a_language:
++		if(uni_lang_selected!=0) {
++			WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name);
++			uni_sample = uni_lang[i].sample_upper;
++		}
++	}
++
++	/* try to guess the front-end parser by the file name suffix */
++	if(cursw==0) {
++		char *p = strrchr(argv[1], '.');
++		char *s;
++
++		if(p!=0 && (s = strdup(p+1))!=0) {
++			for(p=s; *p; p++)
++				*p = tolower(*p);
++			p = s;
++
++			for(i=0; frontswtab[i] != 0 && cursw == 0; i++) {
++				for(j=0; j<MAXSUFFIX; j++)
++					if(frontswtab[i]->suffix[j]
++					&& !strcmp(p, frontswtab[i]->suffix[j]) ) {
++						cursw = frontswtab[i];
++						WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n",
++							cursw->name);
++						WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
++						break;
++					}
++			}
++			free(s);
++		}
++
++		if(cursw==0) {
++			cursw = frontswtab[0];
++			WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", 
++				cursw->name);
++			WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n");
++		}
++	}
++
++	/* open the input file */
++	cursw->open(argv[1], front_arg);
++
++	/* Get base name of output file (if not specified)
++	 * by removing (known) suffixes
++	 */
++	if (argc == 2) {
++		char *p;
++		argv[2] = strdup (argv[1]);
++		p = strrchr(argv[2], '.');
++		if (p != NULL)
++			for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++)
++				if (!strcmp(p+1, cursw->suffix[j])) {
++					*p = '\0';
++					break;
++				}
++	}
++
++	if ((null_file = fopen(BITBUCKET, "w")) == NULL) {
++		fprintf(stderr, "**** Cannot open %s ****\n",
++			BITBUCKET);
++		exit(1);
++	}
++
++	if (argv[2][0] == '-' && argv[2][1] == 0) {
++#ifdef WINDOWS
++		if(encode) {
++			fprintf(stderr, "**** can't write encoded file to stdout ***\n");
++			exit(1);
++		}
++#endif /* WINDOWS */
++		pfa_file = afm_file = dvienc_file = null_file;
++
++		if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */
++			afm_file=stdout;
++		} else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */
++			dvienc_file=stdout;
++		} else {
++			pfa_file=stdout;
++		}
++	} else {
++#ifndef WINDOWS
++		snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" );
++#else /* WINDOWS */
++		snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
++#endif /* WINDOWS */
++		if(gen_pfa) {
++			if ((pfa_file = fopen(filename, "w+b")) == NULL) {
++				fprintf(stderr, "**** Cannot create %s ****\n", filename);
++				exit(1);
++			} else {
++				WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
++			}
++		} else
++			pfa_file = null_file;
++
++		if(gen_afm) {
++			snprintf(filename, sizeof filename, "%s.afm", argv[2]) ;
++			if ((afm_file = fopen(filename, "w+")) == NULL) {
++				fprintf(stderr, "**** Cannot create %s ****\n", filename);
++				exit(1);
++			}
++		} else
++			afm_file = null_file;
++
++		if(gen_dvienc) {
++			snprintf(filename, sizeof filename, "%s.enc", argv[2]) ;
++			if ((dvienc_file = fopen(filename, "w+")) == NULL) {
++				fprintf(stderr, "**** Cannot create %s ****\n", filename);
++				exit(1);
++			}
++		} else
++			dvienc_file = null_file;
++	}
++
++	/*
++	 * Now check whether we want a fully encoded .pfa file
++	 */
++#ifndef WINDOWS
++	if (encode && pfa_file != null_file) {
++		int             p[2];
++		extern FILE    *ifp, *ofp;	/* from t1asm.c */
++
++		ifp=stdin;
++		ofp=stdout;
++
++		if (pipe(p) < 0) {
++			perror("**** Cannot create pipe ****\n");
++			exit(1);
++		}
++		ofp = pfa_file;
++		ifp = fdopen(p[0], "r");
++		if (ifp == NULL) {
++			perror("**** Cannot use pipe for reading ****\n");
++			exit(1);
++		}
++		pfa_file = fdopen(p[1], "w");
++		if (pfa_file == NULL) {
++			perror("**** Cannot use pipe for writing ****\n");
++			exit(1);
++		}
++		switch (fork()) {
++		case -1:
++			perror("**** Cannot fork the assembler process ****\n");
++			exit(1);
++		case 0:	/* child */
++			fclose(pfa_file);
++			exit(runt1asm(pfbflag));
++		default: /* parent */
++			fclose(ifp); fclose(ofp);
++		}
++	}
++#endif /* WINDOWS */
++
++	numglyphs = cursw->nglyphs();
++
++	WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs);
++
++	glyph_list = (GLYPH *) calloc(numglyphs,  sizeof(GLYPH));
++
++	/* initialize non-0 fields */
++	for (i = 0; i < numglyphs; i++) {
++		GLYPH *g;
++
++		g = &glyph_list[i];
++		g->char_no = -1;
++		g->orig_code = -1;
++		g->name = "UNKNOWN";
++		g->flags = GF_FLOAT; /* we start with float representation */
++	}
++
++	handle_gnames();
++
++	cursw->glmetrics(glyph_list);
++	cursw->fnmetrics(&fontm);
++ 
++	original_scale_factor = 1000.0 / (double) fontm.units_per_em;
++
++	if(transform == 0)
++		scale_factor = 1.0; /* don't transform */
++	else
++		scale_factor = original_scale_factor;
++
++	if(correctvsize && uni_sample!=0) { /* only for known languages */
++		/* try to adjust the scale factor to make a typical
++		 * uppercase character of hight at least (correctvsize), this
++		 * may improve the appearance of the font but also
++		 * make it weird, use with caution
++		 */
++		int ysz;
++
++		ysz = iscale(glyph_list[encoding[uni_sample]].yMax);
++		if( ysz<correctvsize ) {
++			scale_factor *= (double)correctvsize / ysz;
++		}
++	}
++
++#ifdef XP_ONLY_BLOCKS
++    /* All glyphs from |xp_font_block_offset| to |xp_font_block_offset+255|*/
++    for( i = xp_font_block_offset ; i < (xp_font_block_offset+256) ; i++ ) {
++        unsigned long  ftindex;
++
++        /* Remap X11 font index to FreeType font index */
++        ftindex = FTRemap(xp_pstext_ft_face, &xp_xtf->mapping, i);
++
++        if( ftindex < numglyphs ) {
++          glyph_list[ftindex].flags |= GF_USED;
++        }
++    }
++    
++    /* also always include .notdef */
++    {
++        int notdef_found = FALSE;
++        
++        for (i = 0; i < numglyphs; i++) {
++            if(!strcmp(glyph_list[i].name, ".notdef")) {
++                glyph_list[i].flags |= GF_USED;
++                notdef_found = TRUE;
++                break;
++            }
++        }
++
++        if( !notdef_found )
++        {
++            /* No ".notdef" found ?
++             * Then copy outlines of char 0 to the first "free" slot and make
++             * it our ".notdef" char.
++             */
++            for (i = 0; i < numglyphs; i++) {
++                if((glyph_list[i].flags & GF_USED) == 0) {
++                    glyph_list[i] = glyph_list[0];
++                    glyph_list[i].flags |= GF_USED;
++                    glyph_list[i].name = ".notdef";
++                    notdef_found = TRUE;
++                    break;
++                }   
++            }    
++        }
++        
++        if( !notdef_found )
++        {
++          /* This shoudl never happen... */
++          fprintf(stderr, "ft2pt1: '.notdef' missing in generated font.\n");
++        }        
++    }
++#else
++	if(allglyphs) {
++		for (i = 0; i < numglyphs; i++) {
++			glyph_list[i].flags |= GF_USED;
++		}
++	} else {
++		for (i = 0; i < ENCTABSZ; i++) {
++			glyph_list[encoding[i]].flags |= GF_USED;
++		}
++
++		/* also always include .notdef */
++		for (i = 0; i < numglyphs; i++) 
++			if(!strcmp(glyph_list[i].name, ".notdef")) {
++				glyph_list[i].flags |= GF_USED;
++				break;
++			}
++	}
++#endif /* XP_ONLY_BLOCKS */
++
++	for (i = 0; i < numglyphs; i++) {
++		if (glyph_list[i].flags & GF_USED) {
++			DBG_TO_GLYPH(&glyph_list[i]);
++			convert_glyf(i);
++			DBG_FROM_GLYPH(&glyph_list[i]);
++		}
++	}
++
++	italic_angle = fontm.italic_angle;
++
++	if (italic_angle > 45.0 || italic_angle < -45.0)
++		italic_angle = 0.0;	/* consider buggy */
++
++	if (hints) {
++		findblues();
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].flags & GF_USED) {
++				DBG_TO_GLYPH(&glyph_list[i]);
++				buildstems(&glyph_list[i]);
++				assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
++				DBG_FROM_GLYPH(&glyph_list[i]);
++			}
++		}
++		stemstatistics();
++	} else {
++		for(i=0; i<4; i++)
++			bbox[i] = iscale(fontm.bbox[i]);
++	}
++	/* don't touch the width of fixed width fonts */
++	if( fontm.is_fixed_pitch )
++		correctwidth=0;
++	docorrectwidth(); /* checks correctwidth inside */
++	if (reverse)
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].flags & GF_USED) {
++				DBG_TO_GLYPH(&glyph_list[i]);
++				reversepaths(&glyph_list[i]);
++				assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name);
++				DBG_FROM_GLYPH(&glyph_list[i]);
++			}
++		}
++
++
++#if 0
++	/*
++	** It seems to bring troubles. The problem is that some
++	** styles of the font may be recognized as fixed-width
++	** while other styles of the same font as proportional.
++	** So it's better to be commented out yet.
++	*/
++	if (tryfixed) 
++		alignwidths();
++#endif
++
++	if(trybold) {
++		forcebold = fontm.force_bold;
++	}
++
++#ifdef XP_PSTEXT
++	fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s\n", fontm.name_ps);
++#else
++	fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright);
++	time(&now);
++	fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now));
++	fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name);
++	fprintf(pfa_file, "%% Args: %s\n", cmdline);
++	fprintf(pfa_file, "%%%%EndComments\n");
++#endif /* XP_PSTEXT */
++	fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n");
++
++	WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
++
++
++	fprintf(pfa_file, "  /version (%s) readonly def\n", fontm.name_version);
++
++	fprintf(pfa_file, "  /Notice (%s) readonly def\n", fontm.name_copyright);
++
++	fprintf(pfa_file, "  /FullName (%s) readonly def\n", fontm.name_full);
++	fprintf(pfa_file, "  /FamilyName (%s) readonly def\n", fontm.name_family);
++
++	if(wantuid) {
++		if(strUID)
++			fprintf(pfa_file, "  /UniqueID %s def\n", strUID);
++		else {
++			numUID=0;
++			for(i=0; fontm.name_full[i]!=0; i++) {
++				numUID *= 37; /* magic number, good for hash */
++				numUID += fontm.name_full[i]-' ';
++				/* if the name is long the first chars
++				 * may be lost forever, so re-insert
++				 * them thus making kind of CRC
++				 */
++				numUID += (numUID>>24) & 0xFF;
++			}
++			/* the range for private UIDs is 4 000 000 - 4 999 999 */
++			fprintf(pfa_file, "  /UniqueID %lu def\n", numUID%1000000+4000000);
++		}
++	}
++
++	fprintf(pfa_file, "  /Weight (%s) readonly def\n", fontm.name_style);
++
++	fprintf(pfa_file, "  /ItalicAngle %f def\n", italic_angle);
++	fprintf(pfa_file, "  /isFixedPitch %s def\n",
++		fontm.is_fixed_pitch ? "true" : "false");
++
++	/* we don't print out the unused glyphs */
++	nchars = 0;
++	for (i = 0; i < numglyphs; i++) {
++		if (glyph_list[i].flags & GF_USED) {
++			nchars++;
++		}
++	}
++
++    fprintf(afm_file, "StartFontMetrics 4.1\n");
++    fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix);
++    fprintf(afm_file, "FullName %s\n", fontm.name_full);
++    fprintf(afm_file, "Notice %s\n", fontm.name_copyright);
++    fprintf(afm_file, "EncodingScheme FontSpecific\n");
++    fprintf(afm_file, "FamilyName %s\n", fontm.name_family);
++    fprintf(afm_file, "Weight %s\n", fontm.name_style);
++    fprintf(afm_file, "Version %s\n", fontm.name_version);
++    fprintf(afm_file, "Characters %d\n", nchars);
++    fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle);
++
++    fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender));
++    fprintf(afm_file, "Descender %d\n", iscale(fontm.descender));
++
++	fprintf(pfa_file, "  /UnderlinePosition %d def\n",
++		iscale(fontm.underline_position));
++
++	fprintf(pfa_file, "  /UnderlineThickness %hd def\n",
++		iscale(fontm.underline_thickness));
++
++	fprintf(pfa_file, "end readonly def\n");
++
++	fprintf(afm_file, "UnderlineThickness %d\n",
++		iscale(fontm.underline_thickness));
++
++	fprintf(afm_file, "UnderlinePosition %d\n",
++		iscale(fontm.underline_position));
++
++    fprintf(afm_file, "IsFixedPitch %s\n",
++		fontm.is_fixed_pitch ? "true" : "false");
++    fprintf(afm_file, "FontBBox %d %d %d %d\n",
++		bbox[0], bbox[1], bbox[2], bbox[3]);
++
++	fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix);
++	fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n");
++	/* I'm not sure if these are fixed */
++	fprintf(pfa_file, "/FontType 1 def\n");
++
++	if (transform) {
++		fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n");
++	} else {
++		fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n",
++			original_scale_factor / 1000.0, original_scale_factor / 1000.0);
++	}
++
++	fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n",
++		bbox[0], bbox[1], bbox[2], bbox[3]);
++
++	fprintf(pfa_file, "/Encoding 256 array\n");
++	/* determine number of elements for metrics table */
++	nmetrics = 256;
++ 	for (i = 0; i < numglyphs; i++) {
++		if( glyph_list[i].flags & GF_USED 
++		&& glyph_list[i].char_no == -1 ) {
++			nmetrics++;
++		}
++	}
++	fprintf(afm_file, "StartCharMetrics %d\n", nmetrics);
++
++	fprintf(dvienc_file, "/%s%sEncoding [\n",
++		fontm.name_ps, uni_font_name_suffix);
++
++#ifdef XP_PSTEXT
++    {
++      int linewidth = 0;
++ 	  for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
++          linewidth += strlen(glyph_list[encoding[i]].name) + 14 + 8;
++		  fprintf(pfa_file, "dup %d /%s put%s",
++                  i,
++                  glyph_list[encoding[i]].name,
++                  (linewidth > 70 || i == 255)?(linewidth = 0, "\n"):("\t"));
++		  if( glyph_list[encoding[i]].flags & GF_USED )  {
++			  print_glyph_metrics(i, encoding[i]);
++		  }
++		  if (encoding[i])
++			  fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
++		  else
++			  fprintf (dvienc_file, "/.notdef\n");
++	  }
++    }
++#else
++ 	for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */
++		fprintf(pfa_file,
++			"dup %d /%s put\n", i, glyph_list[encoding[i]].name);
++		if( glyph_list[encoding[i]].flags & GF_USED )  {
++			print_glyph_metrics(i, encoding[i]);
++		}
++		if (encoding[i])
++			fprintf (dvienc_file, "/index0x%04X\n", encoding[i]);
++		else
++			fprintf (dvienc_file, "/.notdef\n");
++	}
++#endif /* XP_PSTEXT */
++	/* print the metrics for glyphs not in encoding table */
++	for(i=0; i<numglyphs; i++) {
++		if( (glyph_list[i].flags & GF_USED)
++		&& glyph_list[i].char_no == -1 ) {
++			print_glyph_metrics(-1, i);
++		}
++	}
++
++	fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n");
++	fprintf(pfa_file, "dup /Private 16 dict dup begin\n");
++
++	fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n");
++	fprintf(pfa_file, "/ND{noaccess def}executeonly def\n");
++	fprintf(pfa_file, "/NP{noaccess put}executeonly def\n");
++
++	/* UniqueID must be shown twice, in both font and Private dictionary */
++	if(wantuid) {
++		if(strUID)
++			fprintf(pfa_file, "/UniqueID %s def\n", strUID);
++		else
++			/* the range for private UIDs is 4 000 000 - 4 999 999 */
++			fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000);
++	}
++
++	if(forcebold==0)
++		fprintf(pfa_file, "/ForceBold false def\n");
++	else if(forcebold==1)
++		fprintf(pfa_file, "/ForceBold true def\n");
++
++	fprintf(pfa_file, "/BlueValues [ ");
++	for (i = 0; i < nblues; i++)
++		fprintf(pfa_file, "%d ", bluevalues[i]);
++	fprintf(pfa_file, "] def\n");
++
++	fprintf(pfa_file, "/OtherBlues [ ");
++	for (i = 0; i < notherb; i++)
++		fprintf(pfa_file, "%d ", otherblues[i]);
++	fprintf(pfa_file, "] def\n");
++
++	if (stdhw != 0)
++		fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw);
++	if (stdvw != 0)
++		fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw);
++	fprintf(pfa_file, "/StemSnapH [ ");
++	for (i = 0; i < 12 && stemsnaph[i] != 0; i++)
++		fprintf(pfa_file, "%d ", stemsnaph[i]);
++	fprintf(pfa_file, "] def\n");
++	fprintf(pfa_file, "/StemSnapV [ ");
++	for (i = 0; i < 12 && stemsnapv[i] != 0; i++)
++		fprintf(pfa_file, "%d ", stemsnapv[i]);
++	fprintf(pfa_file, "] def\n");
++
++	fprintf(pfa_file, "/MinFeature {16 16} def\n");
++	/* Are these fixed also ? */
++	fprintf(pfa_file, "/password 5839 def\n");
++
++	/* calculate the number of subroutines */
++
++	subid=5;
++	for (i = 0; i < numglyphs; i++) {
++		if (glyph_list[i].flags & GF_USED) {
++			subid+=glyph_list[i].nsg;
++		}
++	}
++
++	fprintf(pfa_file, "/Subrs %d array\n", subid);
++	/* standard subroutines */
++	fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n");
++	fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n");
++	fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n");
++	fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n");
++	/* our sub to make the hint substitution code shorter */
++	fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n");
++
++	if(pfa_file != null_file) { /* save time if the output would be wasted */
++		/* print the hinting subroutines */
++		subid=5;
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].flags & GF_USED) {
++				subid+=print_glyph_subs(i, subid);
++			}
++		}
++
++		fprintf(pfa_file, "ND\n");
++
++		fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars);
++
++		for (i = 0; i < numglyphs; i++) {
++			if (glyph_list[i].flags & GF_USED) {
++				print_glyph(i);
++			}
++		}
++	}
++
++
++	fprintf(pfa_file, "end\nend\nreadonly put\n");
++	fprintf(pfa_file, "noaccess put\n");
++	fprintf(pfa_file, "dup/FontName get exch definefont pop\n");
++	fprintf(pfa_file, "mark currentfile closefile\n");
++	fprintf(pfa_file, "cleartomark\n");
++	if(pfa_file != null_file)
++		fclose(pfa_file);
++
++    fprintf(afm_file, "EndCharMetrics\n");
++
++	if(afm_file != null_file) { /* save time if the output would be wasted */
++		/* print the kerning data if present */
++		cursw->kerning(glyph_list);
++		print_kerning(afm_file);
++	}
++
++    fprintf(afm_file, "EndFontMetrics\n");
++	if(afm_file != null_file)
++		fclose(afm_file);
++
++	fprintf(dvienc_file, "] def\n");
++	if(dvienc_file != null_file)
++		fclose(dvienc_file);
++
++	WARNING_1 fprintf(stderr, "Finished - font files created\n");
++
++	cursw->close();
++
++#ifndef WINDOWS
++	while (wait(&ws) > 0) {
++	}
++#else 
++	if (encode && pfa_file != null_file) {
++		extern FILE    *ifp, *ofp;	/* from t1asm.c */
++
++		snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" );
++
++		if ((ofp = fopen(filename, "w+b")) == NULL) {
++			fprintf(stderr, "**** Cannot create %s ****\n", filename);
++			exit(1);
++		} else {
++			WARNING_2 fprintf(stderr, "Creating file %s\n", filename);
++		}
++
++		snprintf(filename, sizeof filename, "%s.t1a", argv[2]);
++
++		if ((ifp = fopen(filename, "rb")) == NULL) {
++			fprintf(stderr, "**** Cannot read %s ****\n", filename);
++			exit(1);
++		} else {
++			WARNING_2 fprintf(stderr, "Converting file %s\n", filename);
++		}
++
++		runt1asm(pfbflag);
++
++		WARNING_2 fprintf(stderr, "Removing file %s\n", filename);
++		if(unlink(filename) < 0) 
++			WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename);
++	}
++#endif /* WINDOWS */
++
++	fclose(null_file);
++	return 0;
++}
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1_convert.1 xserver/hw/xprint/extras/ttf2pt1/ttf2pt1_convert.1
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1_convert.1	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf2pt1_convert.1	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,512 @@
++.rn '' }`
++''' $RCSfile$$Revision$$Date$
++'''
++''' $Log$
++''' Revision 1.1.4.1  2004/04/21 10:03:13  gisburn
++''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT
++'''
++''' Revision 1.1  2003/06/04 00:33:54  roland
++''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ...
++'''
++'''
++.de Sh
++.br
++.if t .Sp
++.ne 5
++.PP
++\fB\\$1\fR
++.PP
++..
++.de Sp
++.if t .sp .5v
++.if n .sp
++..
++.de Ip
++.br
++.ie \\n(.$>=3 .ne \\$3
++.el .ne 3
++.IP "\\$1" \\$2
++..
++.de Vb
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve
++.ft R
++
++.fi
++..
++'''
++'''
++'''     Set up \*(-- to give an unbreakable dash;
++'''     string Tr holds user defined translation string.
++'''     Bell System Logo is used as a dummy character.
++'''
++.tr \(*W-|\(bv\*(Tr
++.ie n \{\
++.ds -- \(*W-
++.ds PI pi
++.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
++.ds L" ""
++.ds R" ""
++'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
++'''   \*(L" and \*(R", except that they are used on ".xx" lines,
++'''   such as .IP and .SH, which do another additional levels of
++'''   double-quote interpretation
++.ds M" """
++.ds S" """
++.ds N" """""
++.ds T" """""
++.ds L' '
++.ds R' '
++.ds M' '
++.ds S' '
++.ds N' '
++.ds T' '
++'br\}
++.el\{\
++.ds -- \(em\|
++.tr \*(Tr
++.ds L" ``
++.ds R" ''
++.ds M" ``
++.ds S" ''
++.ds N" ``
++.ds T" ''
++.ds L' `
++.ds R' '
++.ds M' `
++.ds S' '
++.ds N' `
++.ds T' '
++.ds PI \(*p
++'br\}
++.\"	If the F register is turned on, we'll generate
++.\"	index entries out stderr for the following things:
++.\"		TH	Title 
++.\"		SH	Header
++.\"		Sh	Subsection 
++.\"		Ip	Item
++.\"		X<>	Xref  (embedded
++.\"	Of course, you have to process the output yourself
++.\"	in some meaninful fashion.
++.if \nF \{
++.de IX
++.tm Index:\\$1\t\\n%\t"\\$2"
++..
++.nr % 0
++.rr F
++.\}
++.TH TTF2PT1_CONVERT 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter"
++.UC
++.if n .hy 0
++.if n .na
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.de CQ          \" put $1 in typewriter font
++.ft CW
++'if n "\c
++'if t \\&\\$1\c
++'if n \\&\\$1\c
++'if n \&"
++\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
++'.ft R
++..
++.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
++.	\" AM - accent mark definitions
++.bd B 3
++.	\" fudge factors for nroff and troff
++.if n \{\
++.	ds #H 0
++.	ds #V .8m
++.	ds #F .3m
++.	ds #[ \f1
++.	ds #] \fP
++.\}
++.if t \{\
++.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++.	ds #V .6m
++.	ds #F 0
++.	ds #[ \&
++.	ds #] \&
++.\}
++.	\" simple accents for nroff and troff
++.if n \{\
++.	ds ' \&
++.	ds ` \&
++.	ds ^ \&
++.	ds , \&
++.	ds ~ ~
++.	ds ? ?
++.	ds ! !
++.	ds /
++.	ds q
++.\}
++.if t \{\
++.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
++.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
++.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
++.\}
++.	\" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
++.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
++.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
++.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++.ds oe o\h'-(\w'o'u*4/10)'e
++.ds Oe O\h'-(\w'O'u*4/10)'E
++.	\" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++.	\" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++.	ds : e
++.	ds 8 ss
++.	ds v \h'-1'\o'\(aa\(ga'
++.	ds _ \h'-1'^
++.	ds . \h'-1'.
++.	ds 3 3
++.	ds o a
++.	ds d- d\h'-1'\(ga
++.	ds D- D\h'-1'\(hy
++.	ds th \o'bp'
++.	ds Th \o'LP'
++.	ds ae ae
++.	ds Ae AE
++.	ds oe oe
++.	ds Oe OE
++.\}
++.rm #[ #] #H #V #F C
++.SH "NAME"
++\fBttf2pt1_convert\fR \- convenience font conversion script
++.SH "SYNOPSIS"
++ttf2pt1_convert \fB[config-file]\fR
++.SH "DESCRIPTION"
++`\fBConvert\fR\*(R' is the master conversion script provided with ttf2pt1. 
++When installed into a public directory it's named `\fBttf2pt1_convert\fR\*(R' 
++to avoid name collisions with the other programs.
++.PP
++If the configuration file is not specified as an argument then the file
++`\f(CWconvert.cfg\fR\*(R' in the current directory is used. This file contains
++a set of configuration variables. The distribution contains a sample file
++file `\f(CWconvert.cfg.sample\fR\*(R'. Please copy it to `\f(CWconvert.cfg\fR\*(R',
++look inside it and change the configuration variables. The more stable
++configuration variables, such as the path names of the scripts and
++encoding files are located in `\f(CWconvert\fR\*(R' itself, they are
++automatically updated when installing \fBttf2pt1\fR.
++.PP
++Put all the TTF fonts you want to convert into some directory (this
++may be just the directory that already contains all the Windows
++fonts on a mounted FAT filesystem). If you have fonts in different
++source encoding then put the fonts in each of the encodings
++into a separate directory. Up to 10 source directories are
++supported. If you (in a rather unlikely case) have more source
++directories then you can make two separate runs of the converter,
++converting up to 10 directories at a time.
++.PP
++The variables in the configuration file are:
++.Ip "\(bu" 2
++\fB\f(CWSRCDIRS\fR\fR \- the list of directories (with absolute paths) with 
++\s-1TTF\s0 fonts. Each line contains at least 3 fields: the name of the directory,
++the language of the fonts in it (if you have fonts for different 
++languages you have to put them into the separate directories) and the
++encoding of the fonts. Again, if you have some of the \s-1TTF\s0 typefaces in 
++one encoding, and some in another (say, \s-1CP\s0\-1251 and \s-1KOI\s0\-8), you have 
++to put them into the separate source directories. Some lines may contain
++4 fields. Then the fourth field is the name of the external map to
++convert the Unicode fonts into the desirable encoding. This map is
++used instead of the built-in map for the specified language.
++.Sp
++*8*
++An interesting thing is that some languages have more than one
++widely used character encodings. For example, the widely used
++encodings for Russian are \s-1IBM\s0 \s-1CP\s0\-866 (\s-1MS\s0\-\s-1DOS\s0 and Unix), \s-1KOI\s0\-8
++(Unix and \s-1VAX\s0, also the standard Internet encoding), \s-1IBM\s0 \s-1CP\s0\-1251 (\s-1MS\s0 Windows).
++That's why I have provided the means to generate the converted fonts
++in more than one encoding. See the file encodings/\s-1README\s0 for 
++details about the encoding tables. Actually, if you plan to use
++these fonts with Netscape Navigator better use the aliases
++cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251
++because that's what Netscape wants.
++.Ip "\(bu" 2
++\fB\f(CWDSTDIR\fR\fR \- directory for the resulting Type1 fonts. Be careful!
++This directory gets completely wiped out before conversion,
++so don't use any already existing directory for this purpose.
++.Ip "\(bu" 2
++\fB\f(CWDSTENC\fI{language}\fR\fR\fR \- the list of encodings in which the destination 
++fonts will be generated for each language. Each font of that 
++language will be generated in each of the specified
++encodings. If you don't want any translation, just specify both
++\f(CWSRCENC\fR and \f(CWDSTENC\fR as iso8859-1 (or if you want any other encoding
++specified in the fonts.dir, copy the description of 8859-1 with
++new name and use this new name for \f(CWSRCENC\fR and \f(CWDSTENC\fR).
++.Ip "\(bu" 2
++\fB\f(CWFOUNDRY\fR\fR \- the foundry name to be used in the fonts.dir file. I have
++set it to `fromttf\*(R' to avoid name conflicts with any existing font for
++sure. But this foundry name is not registered in X11 standards and
++if you want to get the full standard compliance or have a font server
++that enforces such a compliance, use `misc\*(R'.
++.PP
++The next few parameters control the general behavior of the converter.
++They default values are set to something reasonable.
++.Ip "\(bu" 2
++\fB\f(CWCORRECTWIDTH\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then use the 
++converter option \f(CW\fB-w\fR\fR, otherwise don't use it. See the description of 
++this option in the \s-1README\s0 file.
++.Ip "\(bu" 2
++\fB\f(CWREMOVET1A\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then after
++conversion remove the un-encoded \f(CW.t1a\fR font files and the 
++intermediate \f(CW.xpfa\fR font metric files.
++.Ip "\(bu" 2
++\fB\f(CWINSTALLFONTMAP\fR\fR \- a Ghostscript parameter, if the value is set to 
++\fB\f(CWYES\fR\fR then install the entries for the new fonts
++right into the main \f(CWFontmap\fR file. Otherwise just leave
++the file \f(CWFontmap.ttf\fR in the Ghostscript configuration
++directory.
++.Ip "\(bu" 2
++\fB\f(CWHINTSUBST\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR use the option
++\f(CW\fB-H\fR\fR, otherwise don't use it. This option enables the
++hint substitution technique. If you have not installed the X11 patch
++described above, use this option with great caution. See further 
++description of this option in the \s-1README\s0 file.
++.Ip "\(bu" 2
++\fB\f(CWENFORCEISO\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then
++disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically
++this was neccessary due to the way the installer scripts created the
++X11 font configuration files. It is not neccessary any more for this
++purpose. But if you plan to use these fonts with some other application
++that expects ISOLatin1 encoding then better enable this option.
++.Ip "\(bu" 2
++\fB\f(CWALLGLYPHS\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then
++include all the glyphs from the source fonts into the resulting fonts, even
++if these glyphs are inaccessible. If it's set to \fB\f(CWNO\fR\fR then
++include only the glyphs which have codes assigned to them. The glyphs
++without codes can not be used directly. But some clever programs,
++such as the Type 1 library from XFree86 3.9 and higher can change
++the encoding on the fly and use another set of glyphs. If you have not 
++installed the X11 patch described above, use this option with great 
++caution. See further description of the option option \f(CW\fB-a\fR\fR in the 
++\s-1README\s0 file.
++.Ip "\(bu" 2
++\fB\f(CWGENUID\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then use
++the option \f(CW\fB-uA\fR\fR of the converter to generate UniqueIDs for
++the converted fonts. The standard X11 Type 1 library does not use
++this \s-1ID\s0, so it may only be neccessary for the other applications.
++The script is clever enough to generate different UniqueID for the
++same font converted to multiple encodings. Also after conversion it
++checks all the fonts generacted during the session for duplicated
++UniqueID and shows those. Still, this does not quarantee that these
++UniqueIDs won't overlap with some other fonts. The UniqueIDs are
++generated as hash values from the font names, so it's guaranteed
++that if the `\f(CWconvert\fR\*(R' script runs multiple times it will
++generate the same UniqueIDs during each run. See further description 
++of this option in the \s-1README\s0 file.
++.Ip "\(bu" 2
++\fB\f(CWGENUID\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then create
++the \f(CW.pfb\fR files, otherwise the \f(CW.pfa\fR files. The \f(CW.pfb\fR
++files are more compact but contain binary data, so you may experience some
++troubles when transferring them through the network.
++.PP
++The following parameters are used to locate the other scripts and
++configuration files. By default the scripts do a bit of guessing for them:
++they search in the \fBttf2pt1\fR installation directory if \fBttf2pt1\fR
++was installed or otherwise suppose that you are running `\f(CWconvert\fR\*(R' with
++`\f(CWscripts\fR\*(R' subdirectory being the current directory.
++.Ip "\(bu" 2
++\fB\f(CWENCDIR\fR\fR \- directory containing the descriptions of encodings
++.Ip "\(bu" 2
++\fB\f(CWMAPDIR\fR\fR \- directory containing the external map files
++.PP
++Besides that a few parameters are built into the `\f(CWconvert\fR\*(R' script itself.
++You probably won't need to change them:
++.Ip "\(bu" 2
++\f(CW\fBT1ASM\fR\fR, \f(CW\fBTTF2PT1\fR\fR, \f(CW\fBTRANS\fR\fR, \f(CW\fBT1FDIR\fR\fR, \f(CW\fBFORCEISO\fR\fR \- paths to the other script
++.PP
++Also there are a few parameters controlling the installation of
++fonts for Ghostscript. Please look at their description in the 
++Ghostscript section of documentation or in the \fBttf2pt1_x2gs(1)\fR
++manual page before running `\f(CWconvert\fR\*(R'. If these parameters are
++set, `\f(CWconvert\fR\*(R' will call the `\f(CWx2gs\fR\*(R' script automatically
++to install the newly converted fonts in Ghostscript.
++.PP
++After creating the configuration file run the `\f(CWconvert\fR\*(R' script. Look at
++the result and the log file in \f(CWDSTDIR\fR.
++.PP
++Add the directory with newly converted fonts to the configuration
++of X server or font server. For most of the systems this step is
++very straightforward. For \s-1HP\s0\-\s-1UX\s0 it's rather tricky and poorly
++documented, so the file \s-1FONTS\s0.hpux gives a short description.
++.PP
++If you don't have the privileges of the root user, you still can
++configure your private font server. Just use some non-standard
++port number (see \s-1FONTS\s0.hpux for an example, exept that you won't
++need all the \s-1HP\s0\-related stuff on any other system).
++.SH "FILES"
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0scripts/convert.cfg.sample
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0scripts/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/README\s0
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/FONTS\s0
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR\s0/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_BINDIR/\s0ttf2pt1
++.SH "SEE ALSO"
++.Ip "\(bu" 4
++the \fIttf2pt1(1)\fR manpage
++.Ip "\(bu" 4
++the \fIttf2pt1_x2gs(1)\fR manpage
++.Ip "\(bu" 4
++the \fIt1asm(1)\fR manpage
++.SH "BUGS"
++.Sh "Known problems"
++.Ip "\(bu" 4
++One catch is that the X11 Type 1 font library has a rather low limit
++on the font size. Because of this the fonts with  more complicated
++outlines and the enabled hint substitution may not fit into
++this limit. The same applies to the fonts with very complicated
++outlines or with very many glyphs (especially the fonts with
++over 256 glyphs). So you will need to excercise caution with
++these options if you plan using these fonts with X11. Some vendors 
++such as \s-1HP\s0 provide the Type 1 implementation licensed from Adobe 
++which should have no such problem.
++.Sp
++But there is a solution even for the generic X11. A patch located
++in the subdirectory `\f(CWapp/X11\fR\*(R' fixes this problem as well
++as some other minor problems. Its description is provided in
++app/X11/\s-1README\s0.
++.Sp
++To fix the X11 font library, you have to get the X11 sources. I
++can recommend the ftp sites of the XFree86 project ftp://ftp.xfree86.org
++or of the Open Group ftp://ftp.x.org. This patch was made on the sources
++of XFree86 so you may have better success with applying it to the
++XFree86 distribution. After you have got the sources, make sure
++that you can compile them. Then apply the patch as described.
++Make sure that it was applied properly. Compile the sources again
++(actually, you need only the fonts library, the fonts server, and
++possibly the X server). It would be prudent now to save your old
++font library, font server and, possibly, X server. Then install
++the new recently compiled versions of these files. Of course,
++if you know someone who already has compiled these files for the
++same \s-1OS\s0 as yours, you can just copy the binary fles from him.
++.Sp
++Alas, building the X11 system from the source code is not the
++easiest thing in the world and if you have no experience it
++can be quite difficult. In this case just avoid the aforementioned
++features or check each converted font to make sure that it
++works properly.
++.Ip "\(bu" 4
++The Type1 font library from the standard X11 distribution
++does not work on \s-1HP\s0\-\s-1UX\s0 (at least, up to 10.01). The font server
++supplied with \s-1HP\s0\-\s-1UX\s0 up to 10.01 is also broken. Starting from 
++\s-1HP\s0\-\s-1UX\s0 10.20 (I don't know about 10.10) they supply a proprietary font 
++library and the converted fonts work fine with it, provided that
++they are configured properly (see the file \s-1FONTS\s0.hpux).
++.Ip "\(bu" 4
++The \f(CWfonts.scale\fR files created by the older versions of the
++\f(CWttf2pt1\fR installation program (up to release 3.1) have conflicted 
++with the language definitions of the \f(CWXfsft\fR font server and
++parts of it included into XFree86. To overcome this incompatibility
++the never versions creats the \f(CWfonts.scale\fR file describing all the
++fonts as belonging to the \f(CWadobe-fontspecific\fR encoding and
++the \f(CWfonts.alias\fR file with the proper names. The drawback of
++this solution is that \f(CWxlsfonts\fR gives the list of twice more
++fonts. But as a side effect the option \f(CW\fBENFORCEISO\fR\fR in
++`\f(CWconvert.cfg\fR\*(R' is not required for X11 any more.
++.Ip "\(bu" 4
++The conversion script has no support for Eastern multi-plane fonts.
++Contribution of such a support would be welcome.
++
++.rn }` ''
++.IX Title "TTF2PT1_CONVERT 1"
++.IX Name "B<ttf2pt1_convert> - convenience font conversion script"
++
++.IX Header "NAME"
++
++.IX Header "SYNOPSIS"
++
++.IX Header "DESCRIPTION"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "FILES"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "SEE ALSO"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "BUGS"
++
++.IX Subsection "Known problems"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1_x2gs.1 xserver/hw/xprint/extras/ttf2pt1/ttf2pt1_x2gs.1
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf2pt1_x2gs.1	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf2pt1_x2gs.1	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,319 @@
++.rn '' }`
++''' $RCSfile$$Revision$$Date$
++'''
++''' $Log$
++''' Revision 1.1.4.1  2004/04/21 10:03:13  gisburn
++''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT
++'''
++''' Revision 1.1  2003/06/04 00:33:54  roland
++''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ...
++'''
++'''
++.de Sh
++.br
++.if t .Sp
++.ne 5
++.PP
++\fB\\$1\fR
++.PP
++..
++.de Sp
++.if t .sp .5v
++.if n .sp
++..
++.de Ip
++.br
++.ie \\n(.$>=3 .ne \\$3
++.el .ne 3
++.IP "\\$1" \\$2
++..
++.de Vb
++.ft CW
++.nf
++.ne \\$1
++..
++.de Ve
++.ft R
++
++.fi
++..
++'''
++'''
++'''     Set up \*(-- to give an unbreakable dash;
++'''     string Tr holds user defined translation string.
++'''     Bell System Logo is used as a dummy character.
++'''
++.tr \(*W-|\(bv\*(Tr
++.ie n \{\
++.ds -- \(*W-
++.ds PI pi
++.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
++.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
++.ds L" ""
++.ds R" ""
++'''   \*(M", \*(S", \*(N" and \*(T" are the equivalent of
++'''   \*(L" and \*(R", except that they are used on ".xx" lines,
++'''   such as .IP and .SH, which do another additional levels of
++'''   double-quote interpretation
++.ds M" """
++.ds S" """
++.ds N" """""
++.ds T" """""
++.ds L' '
++.ds R' '
++.ds M' '
++.ds S' '
++.ds N' '
++.ds T' '
++'br\}
++.el\{\
++.ds -- \(em\|
++.tr \*(Tr
++.ds L" ``
++.ds R" ''
++.ds M" ``
++.ds S" ''
++.ds N" ``
++.ds T" ''
++.ds L' `
++.ds R' '
++.ds M' `
++.ds S' '
++.ds N' `
++.ds T' '
++.ds PI \(*p
++'br\}
++.\"	If the F register is turned on, we'll generate
++.\"	index entries out stderr for the following things:
++.\"		TH	Title 
++.\"		SH	Header
++.\"		Sh	Subsection 
++.\"		Ip	Item
++.\"		X<>	Xref  (embedded
++.\"	Of course, you have to process the output yourself
++.\"	in some meaninful fashion.
++.if \nF \{
++.de IX
++.tm Index:\\$1\t\\n%\t"\\$2"
++..
++.nr % 0
++.rr F
++.\}
++.TH TTF2PT1_X2GS 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter"
++.UC
++.if n .hy 0
++.if n .na
++.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
++.de CQ          \" put $1 in typewriter font
++.ft CW
++'if n "\c
++'if t \\&\\$1\c
++'if n \\&\\$1\c
++'if n \&"
++\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
++'.ft R
++..
++.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
++.	\" AM - accent mark definitions
++.bd B 3
++.	\" fudge factors for nroff and troff
++.if n \{\
++.	ds #H 0
++.	ds #V .8m
++.	ds #F .3m
++.	ds #[ \f1
++.	ds #] \fP
++.\}
++.if t \{\
++.	ds #H ((1u-(\\\\n(.fu%2u))*.13m)
++.	ds #V .6m
++.	ds #F 0
++.	ds #[ \&
++.	ds #] \&
++.\}
++.	\" simple accents for nroff and troff
++.if n \{\
++.	ds ' \&
++.	ds ` \&
++.	ds ^ \&
++.	ds , \&
++.	ds ~ ~
++.	ds ? ?
++.	ds ! !
++.	ds /
++.	ds q
++.\}
++.if t \{\
++.	ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
++.	ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
++.	ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
++.	ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
++.	ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
++.	ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
++.	ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
++.	ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
++.	ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
++.\}
++.	\" troff and (daisy-wheel) nroff accents
++.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
++.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
++.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
++.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
++.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
++.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
++.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
++.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
++.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
++.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
++.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
++.ds ae a\h'-(\w'a'u*4/10)'e
++.ds Ae A\h'-(\w'A'u*4/10)'E
++.ds oe o\h'-(\w'o'u*4/10)'e
++.ds Oe O\h'-(\w'O'u*4/10)'E
++.	\" corrections for vroff
++.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
++.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
++.	\" for low resolution devices (crt and lpr)
++.if \n(.H>23 .if \n(.V>19 \
++\{\
++.	ds : e
++.	ds 8 ss
++.	ds v \h'-1'\o'\(aa\(ga'
++.	ds _ \h'-1'^
++.	ds . \h'-1'.
++.	ds 3 3
++.	ds o a
++.	ds d- d\h'-1'\(ga
++.	ds D- D\h'-1'\(hy
++.	ds th \o'bp'
++.	ds Th \o'LP'
++.	ds ae ae
++.	ds Ae AE
++.	ds oe oe
++.	ds Oe OE
++.\}
++.rm #[ #] #H #V #F C
++.SH "NAME"
++\fBttf2pt1_x2gs\fR \- font installer for Ghostscript
++.SH "SYNOPSIS"
++ttf2pt1_x2gs \fB[config-file]\fR
++.SH "DESCRIPTION"
++The fonts generated with \fBttf2pt1\fR work fine with Ghostscript by
++themselves. The script `\fBx2gs\fR\*(R' (or `\fBttf2pt1_x2gs\fR\*(R' when installed
++into a public directory, to avoid name conflicts with other
++programs) links the font files from the X11 direcotry into the Ghostscript 
++directory and automatically creates the description file (\f(CWFontmap\fR) 
++in Ghostscript format.
++.PP
++If the configuration file is not specified as an argument then the file
++`\f(CWconvert.cfg\fR\*(R' in the current directory is used, just like the
++`\f(CWconvert\fR\*(R' script does. Indeed, this configuration file is used for 
++both scripts.
++.PP
++The Ghostscript-related parameters in the configuration file are:
++.PP
++\fB\f(CWDSTDIR\fR\fR \- the X11 font directory used by `\f(CWx2gs\fR\*(R' as the
++source of the fonts. This parameter is common with the X11 
++configuration.
++.PP
++\fB\f(CWGSDIR\fR\fR \- the base directory of Ghostsript. If this
++parameter is set to an empty string then `\f(CWconvert\fR\*(R' won't
++call `\f(CWx2gs\fR\*(R'. So if you want to get only the X11 fonts
++installed then set this parameter to an empty string. This 
++directory may vary on various system, so please check your 
++system and set this value accordingly before running the script.
++.PP
++\fB\f(CWGSFONTDIR\fR\fR \- the font directory of Ghostscript. In the standard
++Ghostscript installation it's a subdirectory of \f(CWGSDIR\fR 
++but some systems may use completely different directories.
++.PP
++\fB\f(CWGSCONFDIR\fR\fR \- the configuration subdirectory of Ghostscript
++that contains the \f(CWFontmap\fR file.
++.PP
++\fB\f(CWINSTALLFONTMAP\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then 
++install the entries for the new fonts right into the main 
++\f(CWFontmap\fR file. Otherwise just leave the file \f(CWFontmap.ttf\fR 
++in the Ghostscript configuration directory.
++.PP
++After preparing the configuration file run the script. It symbolicaly links 
++all the font files and creates the description file \f(CWFontmap.ttf\fR in 
++\f(CWGSCONDFIR\fR. After that there are two choices. 
++.PP
++If the option \f(CWINSTALLFONTMAP\fR was set to \f(CWYES\fR then 
++the font descriptions are also automatically installed into the
++master \f(CWFontmap\fR file. The script is clever enough to
++detect if it was run multiple times with the same directories
++and if so it replaces the old \f(CWFontmap\fR entries with
++the new ones instead of just accumulating all of them. You
++may also run it multiple times for multiple X11 directories
++and all the results will be properly collected in the \f(CWFontmap\fR.
++But it's your responsibility to watch that the names of the
++font files don't overlap. If the X11 font directory gets
++renamed then you have to remove its font entries from the
++\f(CWFontmap\fR and only after that re-run `\f(CWx2gs\fR\*(R'
++for the new directory. 
++.PP
++On the other hand if the option \f(CWINSTALLFONTMAP\fR was set to 
++\f(CWNO\fR then go to the \f(CWGSCONFDIR\fR directory and insert the 
++contents of \f(CWFontmap.ttf\fR into the \f(CWFontmap\fR file
++manually. This step may be left manual to make the installation
++a little bit more safe. 
++.PP
++After that you may also want to redefine some of the aliases in 
++\f(CWFontmap\fR to refer to the newly installed fonts.
++But the redefinition of the aliases may be dangerous if the width of
++characters in the new font will be different from the old font.
++Alas, there is no visible solution of this problem yet.
++.SH "FILES"
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0scripts/convert.cfg.sample
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/\s0scripts/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/README\s0
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR/FONTS\s0
++.Ip "\(bu" 2
++\s-1TTF2PT1_SHAREDIR\s0/*
++.Ip "\(bu" 2
++\s-1TTF2PT1_BINDIR/\s0ttf2pt1
++.SH "SEE ALSO"
++.Ip "\(bu" 4
++the \fIttf2pt1(1)\fR manpage
++.Ip "\(bu" 4
++the \fIttf2pt1_convert(1)\fR manpage
++.Ip "\(bu" 4
++the \fIt1asm(1)\fR manpage
++
++.rn }` ''
++.IX Title "TTF2PT1_X2GS 1"
++.IX Name "B<ttf2pt1_x2gs> - font installer for Ghostscript"
++
++.IX Header "NAME"
++
++.IX Header "SYNOPSIS"
++
++.IX Header "DESCRIPTION"
++
++.IX Header "FILES"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Header "SEE ALSO"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
++.IX Item "\(bu"
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf.c xserver/hw/xprint/extras/ttf2pt1/ttf.c
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf.c	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf.c	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,1480 @@
++/*
++ * True Type Font to Adobe Type 1 font converter 
++ * By Mark Heath <mheath@netspace.net.au> 
++ * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
++ * With help from Frank M. Siegert <fms@this.net> 
++ *
++ * see COPYRIGHT
++ *
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <time.h>
++#include <ctype.h>
++#include <math.h>
++
++#ifndef WINDOWS
++#	include <unistd.h>
++#	include <netinet/in.h>
++#else
++#	include "windows.h"
++#endif
++
++#include "ttf.h"
++#include "pt1.h"
++#include "global.h"
++
++/* prototypes of call entries */
++static void openfont(char *fname, char *arg);
++static void closefont( void);
++static int getnglyphs ( void);
++static int glnames( GLYPH *glyph_list);
++static void glmetrics( GLYPH *glyph_list);
++static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
++static void fnmetrics( struct font_metrics *fm);
++static void glpath( int glyphno, GLYPH *glyph_list);
++static void kerning( GLYPH *glyph_list);
++
++/* globals */
++
++/* front-end descriptor */
++struct frontsw ttf_sw = {
++	/*name*/       "ttf",
++	/*descr*/      "built-in TTF support",
++	/*suffix*/     { "ttf" },
++	/*open*/       openfont,
++	/*close*/      closefont,
++	/*nglyphs*/    getnglyphs,
++	/*glnames*/    glnames,
++	/*glmetrics*/  glmetrics,
++	/*glenc*/      glenc,
++	/*fnmetrics*/  fnmetrics,
++	/*glpath*/     glpath,
++	/*kerning*/    kerning,
++};
++
++/* statics */
++
++static FILE    *ttf_file;
++static int      ttf_nglyphs, long_offsets;
++
++static TTF_DIRECTORY *directory;
++static TTF_DIR_ENTRY *dir_entry;
++static char    *filebuffer;
++static char    *filebuffer_end;
++static TTF_NAME *name_table = NULL;
++static TTF_NAME_REC *name_record;
++static TTF_HEAD *head_table = NULL;
++static TTF_HHEA *hhea_table = NULL;
++static TTF_KERN *kern_table = NULL;
++static TTF_CMAP *cmap_table = NULL;
++static LONGHORMETRIC *hmtx_table = NULL;
++static TTF_GLYF *glyf_table;
++static BYTE    *glyf_start = NULL;
++static TTF_MAXP *maxp_table = NULL;
++static TTF_POST_HEAD *post_table = NULL;
++static union {
++	USHORT *sp;
++	ULONG  *lp;
++} loca_table;
++#define short_loca_table	loca_table.sp
++#define long_loca_table		loca_table.lp
++
++static short    cmap_n_segs;
++static USHORT  *cmap_seg_start, *cmap_seg_end;
++static short   *cmap_idDelta, *cmap_idRangeOffset;
++static TTF_CMAP_FMT0  *encoding0;
++static int             enc_type;
++
++static char     name_buffer[2000];
++static char    *name_fields[8];
++
++static int enc_found_ms, enc_found_mac;
++
++static char    *mac_glyph_names[258] = {
++	".notdef", ".null", "CR",
++	"space", "exclam", "quotedbl", "numbersign",
++	"dollar", "percent", "ampersand", "quotesingle",
++	"parenleft", "parenright", "asterisk", "plus",
++	"comma", "hyphen", "period", "slash",
++	"zero", "one", "two", "three",
++	"four", "five", "six", "seven",
++	"eight", "nine", "colon", "semicolon",
++	"less", "equal", "greater", "question",
++	"at", "A", "B", "C",
++	"D", "E", "F", "G",
++	"H", "I", "J", "K",
++	"L", "M", "N", "O",
++	"P", "Q", "R", "S",
++	"T", "U", "V", "W",
++	"X", "Y", "Z", "bracketleft",
++	"backslash", "bracketright", "asciicircum", "underscore",
++	"grave", "a", "b", "c",
++	"d", "e", "f", "g",
++	"h", "i", "j", "k",
++	"l", "m", "n", "o",
++	"p", "q", "r", "s",
++	"t", "u", "v", "w",
++	"x", "y", "z", "braceleft",
++	"bar", "braceright", "asciitilde", "Adieresis",
++	"Aring", "Ccedilla", "Eacute", "Ntilde",
++	"Odieresis", "Udieresis", "aacute", "agrave",
++	"acircumflex", "adieresis", "atilde", "aring",
++	"ccedilla", "eacute", "egrave", "ecircumflex",
++	"edieresis", "iacute", "igrave", "icircumflex",
++	"idieresis", "ntilde", "oacute", "ograve",
++	"ocircumflex", "odieresis", "otilde", "uacute",
++	"ugrave", "ucircumflex", "udieresis", "dagger",
++	"degree", "cent", "sterling", "section",
++	"bullet", "paragraph", "germandbls", "registered",
++	"copyright", "trademark", "acute", "dieresis",
++	"notequal", "AE", "Oslash", "infinity",
++	"plusminus", "lessequal", "greaterequal", "yen",
++	"mu", "partialdiff", "summation", "product",
++	"pi", "integral", "ordfeminine", "ordmasculine",
++	"Omega", "ae", "oslash", "questiondown",
++	"exclamdown", "logicalnot", "radical", "florin",
++	"approxequal", "increment", "guillemotleft", "guillemotright",
++	"ellipsis", "nbspace", "Agrave", "Atilde",
++	"Otilde", "OE", "oe", "endash",
++	"emdash", "quotedblleft", "quotedblright", "quoteleft",
++	"quoteright", "divide", "lozenge", "ydieresis",
++	"Ydieresis", "fraction", "currency", "guilsinglleft",
++	"guilsinglright", "fi", "fl", "daggerdbl",
++	"periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
++	"Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
++	"Egrave", "Iacute", "Icircumflex", "Idieresis",
++	"Igrave", "Oacute", "Ocircumflex", "applelogo",
++	"Ograve", "Uacute", "Ucircumflex", "Ugrave",
++	"dotlessi", "circumflex", "tilde", "macron",
++	"breve", "dotaccent", "ring", "cedilla",
++	"hungarumlaut", "ogonek", "caron", "Lslash",
++	"lslash", "Scaron", "scaron", "Zcaron",
++	"zcaron", "brokenbar", "Eth", "eth",
++	"Yacute", "yacute", "Thorn", "thorn",
++	"minus", "multiply", "onesuperior", "twosuperior",
++	"threesuperior", "onehalf", "onequarter", "threequarters",
++	"franc", "Gbreve", "gbreve", "Idot",
++	"Scedilla", "scedilla", "Cacute", "cacute",
++	"Ccaron", "ccaron", "dmacron"
++};
++
++/* other prototypes */
++static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
++	double *matrix, int level);
++static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
++	double *matrix);
++static double f2dot14( short x);
++
++/* get the TTF description table address and length for this index */
++
++static void
++get_glyf_table(
++	int glyphno,
++	TTF_GLYF **tab,
++	int *len
++)
++{
++	if(tab!=NULL) {
++		if (long_offsets) {
++			*tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
++		} else {
++			*tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
++		}
++	}
++	if(len!=NULL) {
++		if (long_offsets) {
++			*len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
++		} else {
++			*len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
++		}
++	}
++}
++
++static void
++handle_name(void)
++{
++	int             j, k, lang, len, platform;
++	char           *p, *string_area;
++	char           *nbp = name_buffer;
++	int             found3 = 0;
++
++	string_area = (char *) name_table + ntohs(name_table->offset);
++	name_record = &(name_table->nameRecords);
++
++	for (j = 0; j < 8; j++) {
++		name_fields[j] = ""; 
++	}
++
++	for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
++
++		platform = ntohs(name_record->platformID);
++
++		if (platform == 3) {
++
++			found3 = 1;
++			lang = ntohs(name_record->languageID) & 0xff;
++			len = ntohs(name_record->stringLength);
++			if (lang == 0 || lang == 9) {
++				k = ntohs(name_record->nameID);
++				if (k < 8) {
++					name_fields[k] = nbp;
++
++					p = string_area + ntohs(name_record->stringOffset);
++					for (k = 0; k < len; k++) {
++						if (p[k] != '\0') {
++							if (p[k] == '(') {
++								*nbp = '[';
++							} else if (p[k] == ')') {
++								*nbp = ']';
++							} else {
++								*nbp = p[k];
++							}
++							nbp++;
++						}
++					}
++					*nbp = '\0';
++					nbp++;
++				}
++			}
++		}
++		name_record++;
++	}
++
++	string_area = (char *) name_table + ntohs(name_table->offset);
++	name_record = &(name_table->nameRecords);
++
++	if (!found3) {
++		for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
++
++			platform = ntohs(name_record->platformID);
++
++			if (platform == 1) {
++
++				found3 = 1;
++				lang = ntohs(name_record->languageID) & 0xff;
++				len = ntohs(name_record->stringLength);
++				if (lang == 0 || lang == 9) {
++					k = ntohs(name_record->nameID);
++					if (k < 8) {
++						name_fields[k] = nbp;
++
++						p = string_area + ntohs(name_record->stringOffset);
++						for (k = 0; k < len; k++) {
++							if (p[k] != '\0') {
++								if (p[k] == '(') {
++									*nbp = '[';
++								} else if (p[k] == ')') {
++									*nbp = ']';
++								} else {
++									*nbp = p[k];
++								}
++								nbp++;
++							}
++						}
++						*nbp = '\0';
++						nbp++;
++					}
++				}
++			}
++			name_record++;
++		}
++	}
++	if (!found3) {
++		fprintf(stderr, "**** Cannot decode font name fields ****\n");
++		exit(1);
++	}
++	if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
++		name_fields[4] = name_fields[1];
++	}
++	if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */
++		name_fields[6] = name_fields[4];
++		if (name_fields[6][0] == 0) { /* oops, empty again */
++			WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n");
++			name_fields[6] = "Unknown";
++		}
++	}
++	p = name_fields[6];
++	/* must not start with a digit */
++	if(isdigit(*p))
++		*p+= 'A'-'0'; /* change to a letter */
++	while (*p != '\0') {
++		if (!isalnum(*p) || *p=='_') {
++			*p = '-';
++		}
++		p++;
++	}
++}
++
++static void
++handle_head(void)
++{
++	long_offsets = ntohs(head_table->indexToLocFormat);
++	if (long_offsets != 0 && long_offsets != 1) {
++		fprintf(stderr, "**** indexToLocFormat wrong ****\n");
++		exit(1);
++	}
++}
++
++/* limit the recursion level to avoid cycles */
++#define MAX_COMPOSITE_LEVEL 20
++
++static void
++draw_composite_glyf(
++	GLYPH *g,
++	GLYPH *glyph_list,
++	int glyphno,
++	double *orgmatrix,
++	int level
++)
++{
++	int len;
++	short           ncontours;
++	USHORT          flagbyte, glyphindex;
++	double          arg1, arg2;
++	BYTE           *ptr;
++	char           *bptr;
++	SHORT          *sptr;
++	double          matrix[6], newmatrix[6];
++
++	get_glyf_table(glyphno, &glyf_table, &len);
++
++	if(len<=0) /* nothing to do */
++		return;
++
++	ncontours = ntohs(glyf_table->numberOfContours);
++	if (ncontours >= 0) { /* simple case */
++		draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
++		return;
++	}
++
++	if(ISDBG(COMPOSITE) && level ==0)
++		fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name,
++			orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3],
++			orgmatrix[4], orgmatrix[5]);
++
++	/* complex case */
++	if(level >= MAX_COMPOSITE_LEVEL) {
++		WARNING_1 fprintf(stderr, 
++			"*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
++			g->name, level);
++		return;
++	}
++
++	ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
++	sptr = (SHORT *) ptr;
++	do {
++		flagbyte = ntohs(*sptr);
++		sptr++;
++		glyphindex = ntohs(*sptr);
++		sptr++;
++
++		if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
++			arg1 = (short)ntohs(*sptr);
++			sptr++;
++			arg2 = (short)ntohs(*sptr);
++			sptr++;
++		} else {
++			bptr = (char *) sptr;
++			arg1 = (signed char) bptr[0];
++			arg2 = (signed char) bptr[1];
++			sptr++;
++		}
++		matrix[1] = matrix[2] = 0.0;
++
++		if (flagbyte & WE_HAVE_A_SCALE) {
++			matrix[0] = matrix[3] = f2dot14(*sptr);
++			sptr++;
++		} else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
++			matrix[0] = f2dot14(*sptr);
++			sptr++;
++			matrix[3] = f2dot14(*sptr);
++			sptr++;
++		} else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
++			matrix[0] = f2dot14(*sptr);
++			sptr++;
++			matrix[2] = f2dot14(*sptr);
++			sptr++;
++			matrix[1] = f2dot14(*sptr);
++			sptr++;
++			matrix[3] = f2dot14(*sptr);
++			sptr++;
++		} else {
++			matrix[0] = matrix[3] = 1.0;
++		}
++
++		/*
++		 * See *
++		 * http://fonts.apple.com/TTRefMan/RM06/Chap6g
++		 * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
++		 */
++
++		if (fabs(matrix[0]) > fabs(matrix[1]))
++			matrix[4] = fabs(matrix[0]);
++		else
++			matrix[4] = fabs(matrix[1]);
++		if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
++			matrix[4] *= 2.0;
++
++		if (fabs(matrix[2]) > fabs(matrix[3]))
++			matrix[5] = fabs(matrix[2]);
++		else
++			matrix[5] = fabs(matrix[3]);
++		if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
++			matrix[5] *= 2.0;
++
++		/*
++		 * fprintf (stderr,"Matrix Opp %hd
++		 * %hd\n",arg1,arg2);
++		 */
++#if 0
++		fprintf(stderr, "Matrix: %f %f %f %f %f %f\n",
++		 matrix[0], matrix[1], matrix[2], matrix[3],
++			matrix[4], matrix[5]);
++		fprintf(stderr, "Offset: %f %f (%s)\n",
++			arg1, arg2,
++			((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
++#endif
++
++		if (flagbyte & ARGS_ARE_XY_VALUES) {
++			matrix[4] *= arg1;
++			matrix[5] *= arg2;
++		} else {
++			WARNING_1 fprintf(stderr, 
++				"*** Glyph %s: reusing scale from another glyph is unsupported\n",
++				g->name);
++			/*
++			 * must extract values from a glyph
++			 * but it seems to be too much pain
++			 * and it's not clear now that it
++			 * would be really used in any
++			 * interesting font
++			 */
++		}
++
++		/* at this point arg1,arg2 contain what logically should be matrix[4,5] */
++
++		/* combine matrices */
++
++		newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
++		newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
++
++		newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
++		newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
++
++		newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4];
++		newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5];
++
++		if(ISDBG(COMPOSITE)) {
++			fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
++				level+1, ' ', level, glyph_list[glyphindex].name,
++				matrix[0], matrix[1], matrix[2], matrix[3],
++				matrix[4], matrix[5]);
++			fprintf(stderr, "%*c        = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
++				level+1, ' ',
++				newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
++				newmatrix[4], newmatrix[5]);
++		}
++		draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
++
++	} while (flagbyte & MORE_COMPONENTS);
++}
++
++static void
++draw_simple_glyf(
++	GLYPH *g,
++	GLYPH *glyph_list,
++	int glyphno,
++	double *matrix
++)
++{
++	int             i, j, k, k1, len, first, cs, ce;
++	/* We assume that hsbw always sets to(0, 0) */
++	double          xlast = 0, ylast = 0;
++	int             finished, nguide, contour_start, contour_end;
++	short           ncontours, n_inst, last_point;
++	USHORT         *contour_end_pt;
++	BYTE           *ptr;
++#define GLYFSZ	2000
++	short           xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
++	double          xcoord[GLYFSZ], ycoord[GLYFSZ];
++	BYTE            flags[GLYFSZ];
++	double          tx, ty;
++	int             needreverse = 0;	/* transformation may require
++						 * that */
++	GENTRY         *lge;
++
++	lge = g->lastentry;
++
++	get_glyf_table(glyphno, &glyf_table, &len);
++
++	if (len <= 0) {
++		WARNING_1 fprintf(stderr,
++			"**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
++			g->name,
++			glyph_list[glyphno].name);
++		return;
++	}
++	ncontours = ntohs(glyf_table->numberOfContours);
++	if (ncontours < 0) {
++		WARNING_1 fprintf(stderr,
++			"**** Composite glyph %s refers to composite glyph %s, ignored\n",
++			g->name,
++			glyph_list[glyphno].name);
++		return;
++	}
++	contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
++
++	last_point = ntohs(contour_end_pt[ncontours - 1]);
++	n_inst = ntohs(contour_end_pt[ncontours]);
++
++	ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
++	j = k = 0;
++	while (k <= last_point) {
++		flags[k] = ptr[j];
++
++		if (ptr[j] & REPEAT) {
++			for (k1 = 0; k1 < ptr[j + 1]; k1++) {
++				k++;
++				flags[k] = ptr[j];
++			}
++			j++;
++		}
++		j++;
++		k++;
++	}
++
++	for (k = 0; k <= last_point; k++) {
++		if (flags[k] & XSHORT) {
++			if (flags[k] & XSAME) {
++				xrel[k] = ptr[j];
++			} else {
++				xrel[k] = -ptr[j];
++			}
++			j++;
++		} else if (flags[k] & XSAME) {
++			xrel[k] = 0.0;
++		} else {
++			xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
++			j += 2;
++		}
++		if (k == 0) {
++			xabs[k] = xrel[k];
++		} else {
++			xabs[k] = xrel[k] + xabs[k - 1];
++		}
++
++	}
++
++	for (k = 0; k <= last_point; k++) {
++		if (flags[k] & YSHORT) {
++			if (flags[k] & YSAME) {
++				yrel[k] = ptr[j];
++			} else {
++				yrel[k] = -ptr[j];
++			}
++			j++;
++		} else if (flags[k] & YSAME) {
++			yrel[k] = 0;
++		} else {
++			yrel[k] = ptr[j] * 256 + ptr[j + 1];
++			j += 2;
++		}
++		if (k == 0) {
++			yabs[k] = yrel[k];
++		} else {
++			yabs[k] = yrel[k] + yabs[k - 1];
++		}
++	}
++
++	if (matrix) {
++		for (i = 0; i <= last_point; i++) {
++			tx = xabs[i];
++			ty = yabs[i];
++			xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]);
++			ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]);
++		}
++	} else {
++		for (i = 0; i <= last_point; i++) {
++			xcoord[i] = fscale(xabs[i]);
++			ycoord[i] = fscale(yabs[i]);
++		}
++	}
++
++	i = j = 0;
++	first = 1;
++
++	while (i <= ntohs(contour_end_pt[ncontours - 1])) {
++		contour_end = ntohs(contour_end_pt[j]);
++
++		if (first) {
++			fg_rmoveto(g, xcoord[i], ycoord[i]);
++			xlast = xcoord[i];
++			ylast = ycoord[i];
++			contour_start = i;
++			first = 0;
++		} else if (flags[i] & ONOROFF) {
++			fg_rlineto(g, xcoord[i], ycoord[i]);
++			xlast = xcoord[i];
++			ylast = ycoord[i];
++		} else {
++			cs = i - 1;
++			finished = nguide = 0;
++			while (!finished) {
++				if (i == contour_end + 1) {
++					ce = contour_start;
++					finished = 1;
++				} else if (flags[i] & ONOROFF) {
++					ce = i;
++					finished = 1;
++				} else {
++					i++;
++					nguide++;
++				}
++			}
++
++			switch (nguide) {
++			case 0:
++				fg_rlineto(g, xcoord[ce], ycoord[ce]);
++				xlast = xcoord[ce];
++				ylast = ycoord[ce];
++				break;
++
++			case 1:
++				fg_rrcurveto(g,
++				      (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
++				      (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
++				      (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0,
++				      (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0,
++					    xcoord[ce],
++					    ycoord[ce]
++					);
++				xlast = xcoord[ce];
++				ylast = ycoord[ce];
++
++				break;
++
++			case 2:
++				fg_rrcurveto(g,
++				     (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0,
++				     (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0,
++				      (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0,
++				      (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0,
++					    xcoord[ce],
++					    ycoord[ce]
++					);
++				xlast = xcoord[ce];
++				ylast = ycoord[ce];
++				break;
++
++			case 3:
++				fg_rrcurveto(g,
++				      (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
++				      (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
++				  (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
++				  (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
++				      (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
++				      (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
++					);
++
++				fg_rrcurveto(g,
++				  (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0,
++				  (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0,
++				  (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0,
++				  (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0,
++				      (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0,
++				      (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0
++					);
++
++				fg_rrcurveto(g,
++				  (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0,
++				  (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0,
++				      (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0,
++				      (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0,
++					    xcoord[ce],
++					    ycoord[ce]
++					);
++				ylast = ycoord[ce];
++				xlast = xcoord[ce];
++
++				break;
++
++			default:
++				k1 = cs + nguide;
++				fg_rrcurveto(g,
++				      (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
++				      (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
++				  (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
++				  (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
++				      (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
++				      (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
++					);
++
++				for (k = cs + 2; k <= k1 - 1; k++) {
++					fg_rrcurveto(g,
++					(xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0,
++					(ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0,
++					(5.0 * xcoord[k] + xcoord[k + 1]) / 6.0,
++					(5.0 * ycoord[k] + ycoord[k + 1]) / 6.0,
++					    (xcoord[k] + xcoord[k + 1]) / 2.0,
++					     (ycoord[k] + ycoord[k + 1]) / 2.0
++						);
++
++				}
++
++				fg_rrcurveto(g,
++				      (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0,
++				      (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0,
++					  (2.0 * xcoord[k1] + xcoord[ce]) / 3.0,
++					  (2.0 * ycoord[k1] + ycoord[ce]) / 3.0,
++					    xcoord[ce],
++					    ycoord[ce]
++					);
++				xlast = xcoord[ce];
++				ylast = ycoord[ce];
++
++				break;
++			}
++		}
++		if (i >= contour_end) {
++			g_closepath(g);
++			first = 1;
++			i = contour_end + 1;
++			j++;
++		} else {
++			i++;
++		}
++	}
++
++	if (matrix) {
++		/* guess whether do we need to reverse the results */
++
++		double             x[3], y[3];
++		int                max = 0, from, to;
++
++		/* transform a triangle going in proper direction */
++		/*
++		 * the origin of triangle is in (0,0) so we know it in
++		 * advance
++		 */
++
++		x[0] = y[0] = 0;
++		x[1] = matrix[0] * 0 + matrix[2] * 300;
++		y[1] = matrix[1] * 0 + matrix[3] * 300;
++		x[2] = matrix[0] * 300 + matrix[2] * 0;
++		y[2] = matrix[1] * 300 + matrix[3] * 0;
++
++		/* then find the topmost point */
++		for (i = 0; i < 3; i++)
++			if (y[i] > y[max])
++				max = i;
++		from = (max + 3 - 1) % 3;
++		to = (max + 1) % 3;
++
++		needreverse = 0;
++
++		/* special cases for horizontal lines */
++		if (y[max] == y[from]) {
++			if (x[max] < y[from])
++				needreverse = 1;
++		} else if (y[to] == y[from]) {
++			if (x[to] < x[max])
++				needreverse = 1;
++		} else {	/* generic case */
++			if ((x[to] - x[max]) * (y[max] - y[from])
++			    > (x[max] - x[from]) * (y[to] - y[max]))
++				needreverse = 1;
++		}
++
++		if (needreverse) {
++			if (lge) {
++				assertpath(lge->next, __FILE__, __LINE__, g->name);
++				reversepathsfromto(lge->next, NULL);
++			} else {
++				assertpath(g->entries, __FILE__, __LINE__, g->name);
++				reversepaths(g);
++			}
++		}
++	}
++}
++
++static double
++f2dot14(
++	short x
++)
++{
++	short           y = ntohs(x);
++	return (y >> 14) + ((y & 0x3fff) / 16384.0);
++}
++
++
++/* check that the pointer points within the file */
++/* returns 0 if pointer is good, 1 if bad */
++static int
++badpointer(
++	void *ptr
++)
++{
++	return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
++}
++
++/*
++ * Externally accessible methods
++ */
++
++/*
++ * Open font and prepare to return information to the main driver.
++ * May print error and warning messages.
++ * Exit on error.
++ */
++
++static void
++openfont(
++	char *fname,
++	char *arg /* unused now */
++)
++{
++	int             i, j;
++	struct stat     statbuf;
++	static struct {
++		void **tbpp; /* pointer to pointer to the table */
++		char name[5]; /* table name */
++		char optional; /* flag: table may be missing */
++	} tables[] = {
++		{ (void **)&name_table, "name", 0 },
++		{ (void **)&head_table, "head", 0 },
++		{ (void **)&hhea_table, "hhea", 0 },
++		{ (void **)&post_table, "post", 0 },
++		{ (void **)&glyf_start, "glyf", 0 },
++		{ (void **)&cmap_table, "cmap", 0 },
++		{ (void **)&kern_table, "kern", 1 },
++		{ (void **)&maxp_table, "maxp", 0 },
++		{ (void **)&hmtx_table, "hmtx", 0 },
++		{ (void **)&long_loca_table, "loca", 0 },
++		{ NULL, "", 0 } /* end of table */
++	};
++
++	if (stat(fname, &statbuf) == -1) {
++		fprintf(stderr, "**** Cannot access %s ****\n", fname);
++		exit(1);
++	}
++	if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
++		fprintf(stderr, "**** Cannot malloc space for file ****\n");
++		exit(1);
++	}
++
++	filebuffer_end = filebuffer + statbuf.st_size;
++
++	if ((ttf_file = fopen(fname, "rb")) == NULL) {
++		fprintf(stderr, "**** Cannot open file '%s'\n", fname);
++		exit(1);
++	} else {
++		WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
++	}
++
++	if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
++		fprintf(stderr, "**** Could not read whole file \n");
++		exit(1);
++	}
++	fclose(ttf_file);
++
++	directory = (TTF_DIRECTORY *) filebuffer;
++
++	if (ntohl(directory->sfntVersion) != 0x00010000) {
++		fprintf(stderr,
++			"**** Unknown File Version number [%x], or not a TrueType file\n",
++			directory->sfntVersion);
++		exit(1);
++	}
++
++	/* clear the tables */
++	for(j=0; tables[j].tbpp != NULL; j++)
++		*(tables[j].tbpp) = NULL;
++
++	dir_entry = &(directory->list);
++
++	for (i = 0; i < ntohs(directory->numTables); i++) {
++
++		for(j=0; tables[j].tbpp != NULL; j++)
++			if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) {
++				*(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset));
++				break;
++			}
++
++		if (memcmp(dir_entry->tag, "EBDT", 4) == 0 ||
++			   memcmp(dir_entry->tag, "EBLC", 4) == 0 ||
++			   memcmp(dir_entry->tag, "EBSC", 4) == 0) {
++			WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
++		}
++		dir_entry++;
++	}
++
++	for(j=0; tables[j].tbpp != NULL; j++)
++		if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) {
++			fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name);
++			exit(1);
++		}
++
++	handle_name();
++
++	handle_head();
++
++	ttf_nglyphs = ntohs(maxp_table->numGlyphs);
++
++	enc_found_ms = enc_found_mac = 0;
++}
++
++/*
++ * Close font.
++ * Exit on error.
++ */
++
++static void
++closefont(
++	void
++)
++{
++	return; /* empty operation */
++}
++
++/*
++ * Get the number of glyphs in font.
++ */
++
++static int
++getnglyphs (
++	void
++)
++{
++	return ttf_nglyphs;
++}
++
++/*
++ * Get the names of the glyphs.
++ * Returns 0 if the names were assigned, non-zero if the font
++ * provides no glyph names.
++ */
++
++static int
++glnames(
++	GLYPH *glyph_list
++)
++{
++	int             i, len, n, npost;
++	unsigned int    format;
++	USHORT         *name_index;
++	char           *ptr, *p;
++	char          **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
++	int             n_ps_names;
++	int             ps_fmt_3 = 0;
++
++	format = ntohl(post_table->formatType);
++
++	if (format == 0x00010000) {
++		for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
++			glyph_list[i].name = mac_glyph_names[i];
++		}
++	} else if (format == 0x00020000) {
++                npost = ntohs(post_table->numGlyphs);
++                if (ttf_nglyphs != npost) {
++                        /* This is an error in the font, but we can now cope */
++                        WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n",
++                                npost, ttf_nglyphs);
++                }
++                n_ps_names = 0;
++                name_index = &(post_table->glyphNameIndex);
++
++                /* This checks the integrity of the post table */       
++                for (i=0; i<npost; i++) {
++                    n = ntohs(name_index[i]);
++                    if (n > n_ps_names + 257) {
++                        n_ps_names = n - 257;
++                    }
++                }
++
++                ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
++                i = 0;
++                while (*ptr > 0 && i < n_ps_names) {
++                        len = *ptr;
++                        /* previously the program wrote nulls into the table. If the table
++                           was corrupt, this could put zeroes anywhere, leading to obscure bugs,
++                           so now I malloc space for the names. Yes it is much less efficient */
++                           
++                        if ((p = malloc(len+1)) == NULL) {
++                            fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++                            exit(255);
++                        }
++                        
++                        ps_name_ptr[i] = p;
++                        strncpy(p, ptr+1, len);
++                        p[len] = '\0';
++                        i ++;
++                        ptr += len + 1;
++                }
++        
++                if (i != n_ps_names)
++                {
++                    WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
++                             i, n_ps_names);
++                    n_ps_names = i;
++                }
++
++                /*
++                 * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d,
++                 * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); }
++                 */
++
++                for (i = 0; i < npost; i++) {
++                        n = ntohs(name_index[i]);
++                        if (n < 258) {
++                                glyph_list[i].name = mac_glyph_names[n];
++                        } else if (n < 258 + n_ps_names) {
++                                glyph_list[i].name = ps_name_ptr[n - 258];
++                        } else {
++                                glyph_list[i].name = malloc(16);
++                                sprintf(glyph_list[i].name, "_g_%d", i);
++                                WARNING_2 fprintf(stderr,
++                                        "Glyph No. %d has no postscript name, becomes %s\n",
++                                        i, glyph_list[i].name);
++                        }
++                }
++                /* Now fake postscript names for all those beyond the end of the table */
++                if (npost < ttf_nglyphs) {
++                    for (i=npost; i<ttf_nglyphs; i++) {
++                        if ((glyph_list[i].name = malloc(16)) == NULL)
++                        {
++                            fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
++                            exit(255);
++                        }
++                        sprintf(glyph_list[i].name, "_g_%d", i);
++                        WARNING_2 fprintf(stderr,
++                                "Glyph No. %d has no postscript name, becomes %s\n",
++                                i, glyph_list[i].name);
++                    }
++                }
++	} else if (format == 0x00030000) {
++		WARNING_3 fputs("No postscript table, using default\n", stderr);
++		ps_fmt_3 = 1;
++	} else if (format == 0x00028000) {
++		ptr = (char *) &(post_table->numGlyphs);
++		for (i = 0; i < ttf_nglyphs; i++) {
++			glyph_list[i].name = mac_glyph_names[i + ptr[i]];
++		}
++	} else {
++		fprintf(stderr,
++			"**** Postscript table in wrong format %x ****\n",
++			format);
++		exit(1);
++	}
++
++	return ps_fmt_3;
++}
++
++/*
++ * Get the metrics of the glyphs.
++ */
++
++static void
++glmetrics(
++	GLYPH *glyph_list
++)
++{
++	int             i;
++	int             n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
++	GLYPH          *g;
++	LONGHORMETRIC  *hmtx_entry = hmtx_table;
++	FWORD          *lsblist;
++
++	for (i = 0; i < n_hmetrics; i++) {
++		g = &(glyph_list[i]);
++		g->width = ntohs(hmtx_entry->advanceWidth);
++		g->lsb = ntohs(hmtx_entry->lsb);
++		hmtx_entry++;
++	}
++
++	lsblist = (FWORD *) hmtx_entry;
++	hmtx_entry--;
++
++	for (i = n_hmetrics; i < ttf_nglyphs; i++) {
++		g = &(glyph_list[i]);
++		g->width = ntohs(hmtx_entry->advanceWidth);
++		g->lsb = ntohs(lsblist[i - n_hmetrics]);
++	}
++
++	for (i = 0; i < ttf_nglyphs; i++) {
++		g = &(glyph_list[i]);
++		get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
++
++		g->xMin = (short)ntohs(glyf_table->xMin);
++		g->xMax = (short)ntohs(glyf_table->xMax);
++		g->yMin = (short)ntohs(glyf_table->yMin);
++		g->yMax = (short)ntohs(glyf_table->yMax);
++	}
++
++}
++
++
++static void
++handle_ms_encoding(
++	GLYPH *glyph_list,
++	int *encoding,
++	int *unimap
++)
++{
++	int             j, k, kk, set_ok;
++	USHORT          start, end, ro;
++	short           delta, n;
++
++	for (j = 0; j < cmap_n_segs - 1; j++) {
++		start = ntohs(cmap_seg_start[j]);
++		end = ntohs(cmap_seg_end[j]);
++		delta = ntohs(cmap_idDelta[j]);
++		ro = ntohs(cmap_idRangeOffset[j]);
++
++		for (k = start; k <= end; k++) {
++			if (ro == 0) {
++				n = k + delta;
++			} else {
++				n = ntohs(*((ro >> 1) + (k - start) +
++				 &(cmap_idRangeOffset[j])));
++				if (delta != 0)
++				{
++					/*  Not exactly sure how to deal with this circumstance,
++						I suspect it never occurs */
++					n += delta;
++					fprintf (stderr,
++						 "rangeoffset and delta both non-zero - %d/%d",
++						 ro, delta);
++				}
++			}
++			if(n<0 || n>=ttf_nglyphs) {
++				WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
++				continue;
++			}
++			if (glyph_list[n].orig_code != -1) {
++#if 0
++				if (strcmp(glyph_list[n].name, ".notdef") != 0) {
++					WARNING_2 fprintf(stderr,
++						"Glyph %s has >= two encodings (A), %4.4x & %4.4x\n",
++					 glyph_list[n].name,
++						glyph_list[n].orig_code,
++						k);
++				}
++#endif
++				set_ok = 0;
++			} else {
++				set_ok = 1;
++			}
++			if (enc_type==1 || forcemap) {
++				kk = unicode_rev_lookup(k);
++				if(ISDBG(UNICODE))
++					fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
++				if (set_ok) {
++					glyph_list[n].orig_code = k;
++					/* glyph_list[n].char_no = kk; */
++				}
++				if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
++					encoding[kk] = n;
++			} else {
++				if ((k & 0xff00) == 0xf000) {
++					if( encoding[k & 0x00ff] == -1 ) {
++						encoding[k & 0x00ff] = n;
++						if (set_ok) {
++							/* glyph_list[n].char_no = k & 0x00ff; */
++							glyph_list[n].orig_code = k;
++						}
++					}
++				} else {
++					if (set_ok) {
++						/* glyph_list[n].char_no = k; */
++						glyph_list[n].orig_code = k;
++					}
++					WARNING_2 fprintf(stderr,
++						"Glyph %s has non-symbol encoding %4.4x\n",
++					 glyph_list[n].name,
++						k & 0xffff);
++					/*
++					 * just use the code
++					 * as it is
++					 */
++					if ((k & ~0xff) == 0 && encoding[k] == -1 )
++						encoding[k] = n;
++				}
++			}
++		}
++	}
++}
++
++static void
++handle_mac_encoding(
++	GLYPH *glyph_list,
++	int *encoding,
++	int *unimap
++)
++{
++	short           n;
++	int             j, size;
++
++	size = ntohs(encoding0->length) - 6;
++	for (j = 0; j < size; j++) {
++		n = encoding0->glyphIdArray[j];
++		if (glyph_list[n].char_no != -1) {
++			WARNING_2 fprintf(stderr,
++				"Glyph %s has >= two encodings (B), %4.4x & %4.4x\n",
++				glyph_list[n].name,
++				  glyph_list[n].char_no,
++				j);
++		} else {
++			if (j < ENCTABSZ) {
++				if(encoding[j] == -1) {
++					glyph_list[n].char_no = j;
++					encoding[j] = n;
++				}
++			}
++		}
++	}
++}
++
++/*
++ * Get the original encoding of the font. 
++ * Returns 1 for if the original encoding is Unicode, 2 if the
++ * original encoding is other 16-bit, 0 if 8-bit.
++ */
++
++static int
++glenc(
++	GLYPH *glyph_list,
++	int *encoding,
++	int *unimap
++)
++{
++	int             num_tables = ntohs(cmap_table->numberOfEncodingTables);
++	BYTE           *ptr;
++	int             i, format, offset, seg_c2, found;
++	int             platform, encoding_id;
++	TTF_CMAP_ENTRY *table_entry;
++	TTF_CMAP_FMT4  *encoding4;
++
++	if(enc_found_ms) {
++		handle_ms_encoding(glyph_list, encoding, unimap);
++		return enc_type;
++	} else if(enc_found_mac) {
++		handle_mac_encoding(glyph_list, encoding, unimap);
++		return 0;
++	}
++
++	if(force_pid != -1 && force_pid != 3) {
++		fputs("*** Only platform ID == 3 is supported\n", stderr);
++		exit(1);
++	}
++
++	enc_type = 0;
++	found = 0;
++
++	for (i = 0; i < num_tables && !found; i++) {
++		table_entry = &(cmap_table->encodingTable[i]);
++		offset = ntohl(table_entry->offset);
++		encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset);
++		format = ntohs(encoding4->format);
++		platform = ntohs(table_entry->platformID);
++		encoding_id = ntohs(table_entry->encodingID);
++
++		if (platform == 3 && format == 4) {
++			if(force_pid == 3) {
++				if(encoding_id != force_eid)
++					continue;
++				WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
++					force_pid, force_eid);
++				enc_type = 1;
++			} else {
++				switch (encoding_id) {
++				case 0:
++					WARNING_1 fputs("Found Symbol Encoding\n", stderr);
++					break;
++				case 1:
++					WARNING_1 fputs("Found Unicode Encoding\n", stderr);
++					enc_type = 1;
++					break;
++				default:
++					WARNING_1 {
++						fprintf(stderr,
++						"****MS Encoding ID %d not supported****\n",
++							encoding_id);
++						fputs("Treating it like Symbol encoding\n", stderr);
++					}
++					break;
++				}
++			}
++
++			found = 1;
++			seg_c2 = ntohs(encoding4->segCountX2);
++			cmap_n_segs = seg_c2 >> 1;
++			ptr = (BYTE *) encoding4 + 14;
++			cmap_seg_end = (USHORT *) ptr;
++			cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2);
++			cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2);
++			cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2);
++			enc_found_ms = 1;
++
++			handle_ms_encoding(glyph_list, encoding, unimap);
++		}
++	}
++
++	if (!found) {
++		if(force_pid != -1) {
++			fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
++				force_pid, force_eid);
++			exit(1);
++		}
++
++		WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr);
++		for (i = 0; i < num_tables && !found; i++) {
++			table_entry = &(cmap_table->encodingTable[i]);
++			offset = ntohl(table_entry->offset);
++			encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset);
++			format = ntohs(encoding0->format);
++			platform = ntohs(table_entry->platformID);
++			encoding_id = ntohs(table_entry->encodingID);
++
++			if (format == 0) {
++				found = 1;
++				enc_found_mac = 1;
++
++				handle_mac_encoding(glyph_list, encoding, unimap);
++			}
++		}
++	}
++	if (!found) {
++		fprintf(stderr, "**** No Recognised Encoding Table ****\n");
++		exit(1);
++	}
++
++	return enc_type;
++}
++
++/*
++ * Get the font metrics
++ */
++static void 
++fnmetrics(
++	struct font_metrics *fm
++)
++{
++	char *str;
++	static int fieldstocheck[]= {2,4,6};
++	int i, j, len;
++
++	fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) +
++		((short) ntohs(post_table->italicAngle.lower) / 65536.0);
++	fm->underline_position = (short) ntohs(post_table->underlinePosition);
++	fm->underline_thickness = (short) ntohs(post_table->underlineThickness);
++	fm->is_fixed_pitch = ntohl(post_table->isFixedPitch);
++
++	fm->ascender = (short)ntohs(hhea_table->ascender);
++	fm->descender = (short)ntohs(hhea_table->descender);
++
++	fm->units_per_em =  ntohs(head_table->unitsPerEm);
++
++	fm->bbox[0] = (short) ntohs(head_table->xMin);
++	fm->bbox[1] = (short) ntohs(head_table->yMin);
++	fm->bbox[2] = (short) ntohs(head_table->xMax);
++	fm->bbox[3] = (short) ntohs(head_table->yMax);
++
++	fm->name_copyright = name_fields[0];
++	fm->name_family = name_fields[1];
++	fm->name_style = name_fields[2];
++	fm->name_full = name_fields[4];
++	fm->name_version = name_fields[5];
++	fm->name_ps = name_fields[6];
++
++	/* guess the boldness from the font names */
++	fm->force_bold=0;
++
++	for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
++		str = name_fields[fieldstocheck[i]];
++		len = strlen(str);
++		for(j=0; j<len; j++) {
++			if( (str[j]=='B'
++				|| str[j]=='b' 
++					&& ( j==0 || !isalpha(str[j-1]) )
++				)
++			&& !strncmp("old",&str[j+1],3)
++			&& (j+4 >= len || !islower(str[j+4]))
++			) {
++				fm->force_bold=1;
++				break;
++			}
++		}
++	}
++}
++
++/*
++ * Get the path of contrours for a glyph.
++ */
++
++static void
++glpath(
++	int glyphno,
++	GLYPH *glyf_list
++)
++{
++	double          matrix[6];
++	GLYPH          *g;
++
++	g = &glyph_list[glyphno];
++
++	matrix[0] = matrix[3] = 1.0;
++	matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
++	draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
++}
++
++/*
++ * Get the kerning data.
++ */
++
++static void
++kerning(
++	GLYPH *glyph_list
++)
++{
++	TTF_KERN_SUB   *subtable;
++	TTF_KERN_ENTRY *kern_entry;
++	int             i, j;
++	int             ntables;
++	int             npairs;
++	char           *ptr;
++
++	if(kern_table == NULL) {
++        WARNING_1 fputs("No Kerning data\n", stderr);
++		return;
++	}
++	if(badpointer(kern_table)) {
++        fputs("**** Defective Kerning table, ignored\n", stderr);
++		return;
++	}
++
++	ntables = ntohs(kern_table->nTables);
++	ptr = (char *) kern_table + 4;
++
++	for (i = 0; i < ntables; i++) {
++		subtable = (TTF_KERN_SUB *) ptr;
++		if ((ntohs(subtable->coverage) & 0xff00) == 0) {
++			npairs = (short) ntohs(subtable->nPairs);
++			kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
++
++			kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
++			for (j = 0; j < npairs; j++) {
++				if( kern_entry->value != 0)
++					addkernpair(ntohs(kern_entry->left), 
++						ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
++				kern_entry++;
++			}
++		}
++		ptr += subtable->length;
++	}
++}
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ttf.h xserver/hw/xprint/extras/ttf2pt1/ttf.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/ttf.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/ttf.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,183 @@
++/*
++ * see COPYRIGHT
++ */
++
++/*	these definitions are mostly taken from Microsoft's True Type
++	documentation.
++*/
++
++#ifdef XP_PSTEXT
++typedef unsigned char BYTE;
++typedef signed char CHAR;
++typedef unsigned short USHORT;
++typedef signed short SHORT;
++typedef unsigned int ULONG;
++typedef signed int LONG;
++typedef SHORT FWORD;
++typedef USHORT UFWORD;
++#else
++#define BYTE unsigned char
++#define CHAR signed char
++#define USHORT unsigned short
++#define SHORT signed short
++#define ULONG unsigned int
++#define LONG signed int
++#define FWORD SHORT
++#define UFWORD USHORT
++#endif /* XP_PSTEXT */
++
++#define ONOROFF	0x01
++#define XSHORT	0x02
++#define YSHORT	0x04
++#define REPEAT	0x08
++#define XSAME	0x10
++#define YSAME	0x20
++
++#define ARG_1_AND_2_ARE_WORDS		0x0001
++#define ARGS_ARE_XY_VALUES 			0x0002
++#define XY_BOUND_TO_GRID			0x0004
++#define WE_HAVE_A_SCALE		 		0x0008
++#define MORE_COMPONENTS				0x0020
++#define WE_HAVE_AN_X_AND_Y_SCALE	0x0040
++#define WE_HAVE_A_TWO_BY_TWO		0x0080
++#define WE_HAVE_INSTRUCTIONS		0x0100
++#define USE_MY_METRICS				0x0200
++
++typedef struct short_2 {
++	SHORT	upper;
++	USHORT	lower;
++} FIXED ;
++
++typedef struct longhormetric {
++	UFWORD	advanceWidth;
++	FWORD	lsb;
++} LONGHORMETRIC;
++
++typedef struct ttf_hhea {
++	BYTE	version[4];
++	SHORT	ascender, descender, lineGap;
++	USHORT	advnaceWidthMax;
++	SHORT	minLSB, minRSB, xMaxExtent;
++	SHORT	caretSlopeRise, caretSlopeRun;
++	SHORT	reserved[5];
++	SHORT	metricDataFormat;
++	USHORT	numberOfHMetrics;
++} TTF_HHEA;
++
++typedef struct ttf_dir_entry {
++	char	tag[4];
++	ULONG	checksum;
++	ULONG	offset;
++	ULONG	length;
++} TTF_DIR_ENTRY ;
++
++typedef struct ttf_directory {
++	ULONG			sfntVersion;
++	USHORT			numTables;
++	USHORT			searchRange;
++	USHORT			entrySelector;
++	USHORT			rangeShift;
++	TTF_DIR_ENTRY	list;
++} TTF_DIRECTORY ;
++
++typedef struct ttf_name_rec {
++	USHORT	platformID;
++	USHORT	encodingID;
++	USHORT	languageID;
++	USHORT	nameID;
++	USHORT	stringLength;
++	USHORT	stringOffset;
++} TTF_NAME_REC;
++
++typedef struct ttf_name {
++	USHORT			format;
++	USHORT			numberOfNameRecords;
++	USHORT			offset;
++	TTF_NAME_REC	nameRecords;
++} TTF_NAME ;
++
++typedef struct ttf_head {
++	ULONG	version;
++	ULONG	fontRevision;
++	ULONG	checksumAdjust;
++	ULONG	magicNo;
++	USHORT	flags;
++	USHORT	unitsPerEm;
++	BYTE	created[8];
++	BYTE	modified[8];
++	FWORD	xMin, yMin, xMax, yMax;
++	USHORT	macStyle, lowestRecPPEM;
++	SHORT	fontDirection, indexToLocFormat, glyphDataFormat;
++} TTF_HEAD ;
++
++typedef struct ttf_kern {
++	USHORT	version, nTables;
++} TTF_KERN ;
++
++typedef struct ttf_kern_sub {
++	USHORT version, length, coverage;
++	USHORT nPairs, searchRange, entrySelector, rangeShift;
++} TTF_KERN_SUB;
++
++typedef struct ttf_kern_entry {
++	USHORT	left, right;
++	FWORD	value;
++} TTF_KERN_ENTRY;
++
++typedef struct ttf_cmap_fmt0 {
++	USHORT	format;
++	USHORT	length;
++	USHORT	version;
++	BYTE	glyphIdArray[256];
++} TTF_CMAP_FMT0;
++
++typedef struct ttf_cmap_fmt4 {
++	USHORT	format;
++	USHORT	length;
++	USHORT	version;
++	USHORT	segCountX2;
++	USHORT	searchRange;
++	USHORT	entrySelector;
++	USHORT	rangeShift;
++} TTF_CMAP_FMT4;
++
++typedef struct ttf_cmap_entry {
++	USHORT	platformID;
++	USHORT	encodingID;
++	ULONG	offset;
++} TTF_CMAP_ENTRY;
++
++typedef struct ttf_cmap {
++	USHORT			version;
++	USHORT			numberOfEncodingTables;
++	TTF_CMAP_ENTRY	encodingTable[1];
++} TTF_CMAP ;
++
++typedef struct ttf_glyf {
++	SHORT	numberOfContours;
++	FWORD	xMin, yMin, xMax, yMax;
++} TTF_GLYF ;
++
++typedef struct ttf_maxp {
++	ULONG	version;
++	USHORT	numGlyphs, maxPoints, maxContours;
++	USHORT	maxCompositePoints, maxCompositeContours;
++	USHORT	maxZones, maxTwilightPoints, maxStorage;
++	USHORT	maxFunctionDefs, maxInstructionsDefs;
++	USHORT	maxSizeOfInstructions, maxComponentElements;
++	USHORT	maxComponentDepth;
++} TTF_MAXP ;
++
++typedef struct ttf_post_head {
++	ULONG	formatType;
++	FIXED	italicAngle;
++	FWORD	underlinePosition;
++	FWORD	underlineThickness;
++	ULONG	isFixedPitch;
++	ULONG	minMemType42;
++	ULONG	maxMemType42;
++	ULONG	minMemType1;
++	ULONG	maxMemType1;
++	USHORT	numGlyphs;
++	USHORT	glyphNameIndex;
++} TTF_POST_HEAD ;
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/version.h xserver/hw/xprint/extras/ttf2pt1/version.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/version.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/version.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,7 @@
++/*
++ * see COPYRIGHT
++ */
++
++
++/* version number */
++#define TTF2PT1_VERSION "3.4.4-SNAP-030526"
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/winbuild.bat xserver/hw/xprint/extras/ttf2pt1/winbuild.bat
+--- xserver-old/hw/xprint/extras/ttf2pt1/winbuild.bat	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/winbuild.bat	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,11 @@
++rem file to build ttf2pt1 with Visual C++
++
++cl -DWINDOWS -c bdf.c
++cl -DWINDOWS -c ttf2pt1.c
++cl -DWINDOWS -c pt1.c
++cl -DWINDOWS -c ttf.c
++cl -DWINDOWS -c t1asm.c
++cl -DWINDOWS -c bitmap.c
++cl -o ttf2pt1 ttf2pt1.obj pt1.obj t1asm.obj ttf.obj bdf.obj bitmap.obj
++cl -o t1asm -DWINDOWS -DSTANDALONE t1asm.c
++
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/windows.h xserver/hw/xprint/extras/ttf2pt1/windows.h
+--- xserver-old/hw/xprint/extras/ttf2pt1/windows.h	1970-01-01 10:00:00.000000000 +1000
++++ xserver/hw/xprint/extras/ttf2pt1/windows.h	2006-06-27 13:10:26.000000000 +1000
+@@ -0,0 +1,93 @@
++/*
++ * Implementation of things missing in Windows
++ */
++
++#ifndef M_PI
++#define M_PI  3.14159265358979323846
++#endif
++
++#undef ntohs
++#undef ntohl
++#undef htonl
++
++#ifdef WINDOWS_FUNCTIONS
++/* byte order */
++
++static unsigned short StoM(unsigned short inv) {
++    union iconv {
++        unsigned short    ui;
++        unsigned char   uc[2];
++    } *inp, outv;
++
++    inp = (union iconv *)&inv;
++
++    outv.uc[0] = inp->uc[1];
++    outv.uc[1] = inp->uc[0];
++ 
++    return (outv.ui);
++}
++
++static unsigned int ItoM(unsigned int inv) {
++    union iconv {
++        unsigned int    ui;
++        unsigned char   uc[4];
++    } *inp, outv;
++
++    inp = (union iconv *)&inv;
++
++    outv.uc[0] = inp->uc[3];
++    outv.uc[1] = inp->uc[2];
++    outv.uc[2] = inp->uc[1];
++    outv.uc[3] = inp->uc[0];
++
++    return (outv.ui);
++}
++
++unsigned short ntohs(unsigned short inv) { return StoM(inv); }
++unsigned long ntohl(unsigned long inv) { return ItoM(inv); }
++unsigned long htonl(unsigned long inv) { return ItoM(inv); }
++
++char *optarg;
++int optind=1;
++
++char getopt(int argc, char **argv, char *args) {
++	int n,nlen=strlen(args),nLen=0;
++	char nCmd;
++	
++	if (argv[optind] && *argv[optind]=='-') {
++		nCmd=*((argv[optind]+1));
++
++		for (n=0;n<nlen;n++) {
++			if (args[n] == ':') continue;
++			if (args[n] == nCmd) {
++				if (args[n+1]==':') {
++					char retVal;
++					retVal=*(argv[optind]+1);
++					optarg=argv[optind+1];
++					if (!optarg) optarg="";
++					optind+=2;
++					return retVal;
++				} else {
++					char retVal;
++					retVal=*(argv[optind]+1);
++					optarg=NULL;
++					optind+=1;
++					return retVal;
++				}
++			}
++		}	
++	}
++	return -1;
++}
++
++#else
++
++unsigned short ntohs(unsigned short inv);
++unsigned long ntohl(unsigned long inv);
++unsigned long htonl(unsigned long inv);
++
++extern char *optarg;
++extern int optind;
++
++char getopt(int argc, char **argv, char *args);
++#endif
+diff -ruN xserver-old/hw/xprint/ps/Makefile.am xserver/hw/xprint/ps/Makefile.am
+--- xserver-old/hw/xprint/ps/Makefile.am	2006-06-27 12:50:14.000000000 +1000
++++ xserver/hw/xprint/ps/Makefile.am	2006-06-27 13:12:39.000000000 +1000
+@@ -30,13 +30,30 @@
+ 	PsText.c		\
+ 	PsWindow.c
+ 
+-EXTRA_DIST = 	PsFTFonts.c	\
++FREETYPE_SRCS = PsFTFonts.c	\
+ 	psout_ft.c		\
+ 	psout_ftpstype1.c	\
+-	psout_ftpstype3.c	\
+-	ttf2pt1wrap.c
++	psout_ftpstype3.c	
++
++EXTRA_DIST = ttf2pt1wrap.c
+ 
+ if XP_USE_FREETYPE
+-    AM_CFLAGS += -DXP_USE_FREETYPE
+-    libps_la_SOURCES += $(EXTRA_DIST)
++    TTF2PT1OURCEDIR = $(top_srcdir)/hw/xprint/extras/ttf2pt1
++    TTF2PT1SRCFILE = ttf2pt1.c
++    TTF2PT1OBJFILE = ttf2pt1.o
++    TTF2PT1SRCS_EXTRA = pt1.h t1asm.c ttf.h global.h version.h
++    TTF2PT1SRCS = ft.c pt1.c runt1asm.c $(TTF2PT1SRCFILE)
++    TTF2PT1OBJS = ft.o pt1.o runt1asm.o $(TTF2PT1OBJFILE)
++    
++    AM_CFLAGS += -DXP_USE_FREETYPE -DUSE_FREETYPE -DXP_ONLY_BLOCKS
++
++$(TTF2PT1SRCS_EXTRA):
++	-rm -f $@
++	$(LN_S) $(TTF2PT1OURCEDIR)/$@
++
++$(TTF2PT1SRCS):  $(TTF2PT1SRCS_EXTRA)
++	-rm -f $@
++	$(LN_S) $(TTF2PT1OURCEDIR)/$@
++
++    libps_la_SOURCES += $(FREETYPE_SRCS) $(TTF2PT1SRCS)
+ endif
--- xorg-server-1.4.2.orig/debian/patches/92_xprint-security-holes-fix.patch
+++ xorg-server-1.4.2/debian/patches/92_xprint-security-holes-fix.patch
@@ -0,0 +1,158 @@
+diff -ruN xorg-server-1.0.2-old/hw/xprint/config/C/print/attributes/printer xorg-server-1.0.2/hw/xprint/config/C/print/attributes/printer
+--- xorg-server-old/hw/xprint/config/C/print/attributes/printer	2004-04-24 04:46:58.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/attributes/printer	2006-04-14 21:38:06.000000000 +1000
+@@ -22,19 +22,18 @@
+ 
+ 
+ # Sample entry for the "PSspooldir" model
+-# Just add a printer called "xp_ps_spooldir_tmp_Xprintjobs" to "Xprinters"
++# Just add a printer called "xp_ps_spooldir_HOME_Xprintjobs" to "Xprinters"
+ # and you will get an extra printer which files the PostScript jobs
+-# in the "/tmp/Xprintjobs/" directory.
+-xp_ps_spooldir_tmp_Xprintjobs.xp-model-identifier: PSspooldir
++# in the "$HOME/Xprintjobs/" directory.
++xp_ps_spooldir_HOME_Xprintjobs.xp-model-identifier: PSspooldir
+ 
+ # Sample entry for the "PS2PDFspooldir-GS" model
+-# Just add a printer called "xp_pdf_spooldir_tmp_Xprintjobs" to "Xprinters"
++# Just add a printer called "xp_pdf_spooldir_HOME_Xprintjobs" to "Xprinters"
+ # and you will get an extra printer which convertes the PostScript jobs
+-# to PDF using "ps2pdf" and files them into the "/tmp/Xprintjobs/" directory.
++# to PDF using "ps2pdf" and files them into the "$HOME/Xprintjobs/" directory.
+ # NOTE: Future versions of Xprint will use the PDF DDX instead directly
+ # instead of relying on GhostScript/ps2pdf...
+-xp_pdf_spooldir_tmp_Xprintjobs.xp-model-identifier: PS2PDFspooldir-GS
+-
++xp_pdf_spooldir_HOME_Xprintjobs.xp-model-identifier: PS2PDFspooldir-GS
+ 
+ # IMPORTANT EXAMPLES
+ #
+diff -ruN xorg-server-old/hw/xprint/config/C/print/Makefile.am xorg-server/hw/xprint/config/C/print/Makefile.am
+--- xorg-server-old/hw/xprint/config/C/print/Makefile.am	2005-09-29 06:38:42.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/Makefile.am	2006-04-14 21:41:10.000000000 +1000
+@@ -4,7 +4,7 @@
+ 
+ 
+ Xprinters.ghostscript: $(srcdir)/Xprinters
+-	sed < $(srcdir)/Xprinters "s/#Printer xp_pdf_spooldir_tmp_Xprintjobs/Printer xp_pdf_spooldir_tmp_Xprintjobs/" > Xprinters.ghostscript
++	sed < $(srcdir)/Xprinters "s/#Printer xp_pdf_spooldir_HOME_Xprintjobs/Printer xp_pdf_spooldir_HOME_Xprintjobs/" > Xprinters.ghostscript
+ 
+ 
+ 
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/model-config xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/model-config
+--- xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/model-config	2004-04-24 04:52:27.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/model-config	2006-04-14 21:50:19.000000000 +1000
+@@ -20,7 +20,7 @@
+ #
+ # Attributes supported for this printer model
+ *content-orientations-supported: portrait landscape reverse-portrait reverse-landscape
+-*descriptor: PDF job spool dir /tmp/Xprintjobs
++*descriptor: PDF job spool dir $HOME/Xprintjobs
+ *document-formats-supported: {POSTSCRIPT 2}
+ *input-trays-supported:
+ *medium-source-sizes-supported: \
+@@ -45,7 +45,7 @@
+ }
+ 
+ *plexes-supported: simplex duplex tumble
+-*printer-model: "PDF job spool dir /tmp/Xprintjobs"
++*printer-model: "PDF job spool dir $HOME/Xprintjobs"
+ # 75, 100, 120, 150, 180, 200, 240, 300, 360, 400, 600, 720,
+ # 940, 1200 and 2440 are supported DPI values, we limit it here
+ # to some common values:
+@@ -60,7 +60,7 @@
+ # Note that "%xpconfigdir%" is currently only supported in Xprt servers build
+ # from xprint.mozdev.org sources, other platforms have replace it with the
+ # absolute path name to the script
+-*xp-spooler-command: %xpconfigdir%/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh -d /tmp/Xprintjobs -s .pdf -u 077 -p %printer-name% -c %copy-count% -t %job-name% -o "%options%"
++*xp-spooler-command: %xpconfigdir%/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh -s .pdf -u 077 -p %printer-name% -c %copy-count% -t %job-name% -o "%options%"
+ 
+ # NOTE: xp-psddx-* attributes are EXPERIMENTAL for now.
+ # xp-psddx-download-fonts defines which fonts should be downloaded as outlines
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh
+--- xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh	2004-04-24 04:52:27.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh	2006-04-14 21:53:19.000000000 +1000
+@@ -3,7 +3,7 @@
+ export PATH
+ 
+ verbose_msgs="false"
+-DEFAULT_SPOOLDIR=/tmp/Xprintjobs
++DEFAULT_SPOOLDIR=`perl -e '@x = getpwuid($>); print $x[7]'`/Xprintjobs
+ 
+ usage()
+ {
+@@ -74,7 +74,6 @@
+ 
+ if [ ! -d "${DEFAULT_SPOOLDIR}" ] ; then 
+   mkdir "${DEFAULT_SPOOLDIR}"
+-  chmod a+rwxt "${DEFAULT_SPOOLDIR}"
+ fi
+ 
+ if [ "${permmask}" != "" ] ; then
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/model-config xorg-server/hw/xprint/config/C/print/models/PSspooldir/model-config
+--- xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/model-config	2004-04-24 04:54:16.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PSspooldir/model-config	2006-04-14 21:57:02.000000000 +1000
+@@ -19,7 +19,7 @@
+ #
+ # Attributes supported for this printer model
+ *content-orientations-supported: portrait landscape reverse-portrait reverse-landscape
+-*descriptor: PostScript job spool dir /tmp/Xprintjobs
++*descriptor: PostScript job spool dir $HOME/Xprintjobs
+ *document-formats-supported: {POSTSCRIPT 2}
+ *input-trays-supported:
+ *medium-source-sizes-supported: \
+@@ -44,7 +44,7 @@
+ }
+ 
+ *plexes-supported: simplex duplex tumble
+-*printer-model: "PostScript job spool dir /tmp/Xprintjobs"
++*printer-model: "PostScript job spool dir $HOME/Xprintjobs"
+ # 75, 100, 120, 150, 180, 200, 240, 300, 360, 400, 600, 720,
+ # 940, 1200 and 2440 are supported DPI values, we limit it here
+ # to some common values:
+@@ -59,7 +59,7 @@
+ # Note that "%xpconfigdir%" is currently only supported in Xprt servers build
+ # from xprint.mozdev.org sources, other platforms have replace it with the
+ # absolute path name to the script
+-*xp-spooler-command: %xpconfigdir%/C/print/models/PSspooldir/spooltodir.sh -d /tmp/Xprintjobs -s .ps -u 077 -p %printer-name% -c %copy-count% -t %job-name% -o "%options%"
++*xp-spooler-command: %xpconfigdir%/C/print/models/PSspooldir/spooltodir.sh -s .ps -u 077 -p %printer-name% -c %copy-count% -t %job-name% -o "%options%"
+ 
+ # NOTE: xp-psddx-* attributes are EXPERIMENTAL for now.
+ # xp-psddx-download-fonts defines which fonts should be downloaded as outlines
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh xorg-server/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh
+--- xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh	2004-04-24 04:54:16.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh	2006-04-14 21:58:06.000000000 +1000
+@@ -3,7 +3,7 @@
+ export PATH
+ 
+ verbose_msgs="false"
+-DEFAULT_SPOOLDIR=/tmp/Xprintjobs
++DEFAULT_SPOOLDIR=`perl -e '@x = getpwuid($>); print $x[7]'`/Xprintjobs
+ 
+ usage()
+ {
+@@ -74,7 +74,6 @@
+ 
+ if [ ! -d "${DEFAULT_SPOOLDIR}" ] ; then 
+   mkdir "${DEFAULT_SPOOLDIR}"
+-  chmod a+rwxt "${DEFAULT_SPOOLDIR}"
+ fi
+ 
+ if [ "${permmask}" != "" ] ; then
+diff -ruN xorg-server-old/hw/xprint/config/C/print/Xprinters xorg-server/hw/xprint/config/C/print/Xprinters
+--- xorg-server-old/hw/xprint/config/C/print/Xprinters	2004-04-24 04:46:31.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/Xprinters	2006-04-14 22:04:56.000000000 +1000
+@@ -30,10 +30,10 @@
+ 
+ ########################################################################
+ # Preconfigured entry for the PSspooldir model
+-# (which sends jobs to /tmp/Xprintjobs instead to a physical printer)
++# (which sends jobs to $HOME/Xprintjobs instead to a physical printer)
+ ########################################################################
+-#Printer xp_pdf_spooldir_tmp_Xprintjobs
+-Printer xp_ps_spooldir_tmp_Xprintjobs
++#Printer xp_pdf_spooldir_HOME_Xprintjobs
++Printer xp_ps_spooldir_HOME_Xprintjobs
+ 
+ ########################################################################
+ # Add individual printers to the list of printers managed by the
--- xorg-server-1.4.2.orig/debian/patches/91_ttf2pt1_updates
+++ xorg-server-1.4.2/debian/patches/91_ttf2pt1_updates
@@ -0,0 +1,39 @@
+diff -ruN xserver-old/hw/xprint/extras/ttf2pt1/ft.c xorg-server/hw/xprint/extras/ttf2pt1/ft.c
+--- xorg-server-old/hw/xprint/extras/ttf2pt1/ft.c	2006-06-27 13:14:02.000000000 +1000
++++ xorg-server/hw/xprint/extras/ttf2pt1/ft.c	2006-06-27 13:18:56.000000000 +1000
+@@ -36,15 +36,15 @@
+ 
+ #ifdef XP_PSTEXT
+ #include "os.h"
+-#include "Xproto.h"
+-#include "font.h"
+-#include "fontstruct.h"
+-#include "fntfilst.h"
+-#include "fontutil.h"
+-#include "fontenc.h"
+-#include "ft.h"
++#include <X11/Xproto.h>
++#include <X11/fonts/font.h>
++#include <X11/fonts/fontstruct.h>
++#include <X11/fonts/fntfilst.h>
++#include <X11/fonts/fontutil.h>
++#include <X11/fonts/fontenc.h>
++#include <X11/fonts/ft.h>
+ #define NOT_IN_FTFUNCS
+-#include "ftfuncs.h"
++#include <X11/fonts/ftfuncs.h>
+ #endif /* XP_PSTEXT */
+ 
+ #include "pt1.h"
+diff -ruN xorg-server-old/hw/xprint/extras/ttf2pt1/ttf2pt1.c xorg-server/hw/xprint/extras/ttf2pt1/ttf2pt1.c
+--- xorg-server-old/hw/xprint/extras/ttf2pt1/ttf2pt1.c	2006-06-27 13:14:02.000000000 +1000
++++ xorg-server/hw/xprint/extras/ttf2pt1/ttf2pt1.c	2006-06-27 13:15:49.000000000 +1000
+@@ -1698,7 +1698,7 @@
+ 
+ #ifdef XP_PSTEXT
+ FT_Face         xp_pstext_ft_face     = NULL; /* used by ft.c */
+-FontPtr       xp_xtf                = NULL;
++FTFontPtr       xp_xtf                = NULL;
+ const char     *xp_psfontname         = NULL;
+ unsigned long   xp_font_block_offset  = 0UL;
+ 
--- xorg-server-1.4.2.orig/debian/patches/10_dont_look_in_home_for_config.diff
+++ xorg-server-1.4.2/debian/patches/10_dont_look_in_home_for_config.diff
@@ -0,0 +1,12 @@
+Index: a/hw/xfree86/common/xf86Config.c
+===================================================================
+--- a/hw/xfree86/common/xf86Config.c.orig	2007-08-16 22:47:18.000000000 -0400
++++ b/hw/xfree86/common/xf86Config.c	2007-08-16 22:47:21.000000000 -0400
+@@ -92,7 +92,6 @@
+ 			"/etc/X11/%R," "%P/etc/X11/%R," \
+ 			"%E," "%F," \
+ 			"/etc/X11/%F," "%P/etc/X11/%F," \
+-			"%D/%X," \
+ 			"/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
+ 			"%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
+ 			"%P/etc/X11/%X," \
--- xorg-server-1.4.2.orig/debian/patches/54_more-sanity-checks.diff
+++ xorg-server-1.4.2/debian/patches/54_more-sanity-checks.diff
@@ -0,0 +1,40 @@
+From 30c077f228f563e4e1f4115b345577d9fd393b68 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@redhat.com>
+Date: Fri, 24 Oct 2008 15:06:49 +1030
+Subject: [PATCH] dix: extra sanity-checks against potential NULL-dereferences. #434807
+
+Two minor code paths could potentially crash the server:
+- if scr is NULL, we shouldn't try to dereference it.
+- if GPE is called with buttons != 0 but the event is not a
+  ButtonPress or ButtonRelease, the button mapping may dereference a NULL
+  pointer.
+
+Admittedly the second should never happen, but better to guard against it.
+---
+ dix/getevents.c |    6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+Index: xorg-server/dix/getevents.c
+===================================================================
+--- xorg-server.orig/dix/getevents.c
++++ xorg-server/dix/getevents.c
+@@ -535,6 +535,9 @@
+     ScreenPtr scr = miPointerGetScreen(pDev);
+ 
+     /* Sanity checks. */
++    if (!scr)
++        return 0;
++
+     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
+         return 0;
+ 
+@@ -546,6 +549,9 @@
+     if (!pDev->valuator)
+         return 0;
+ 
++    if (buttons && !pDev->button)
++        return 0;
++
+     if (!coreOnly && pDev->coreEvents)
+         num_events = 2;
+     else
--- xorg-server-1.4.2.orig/debian/patches/07_autoconfig_screen_with_device_section.diff
+++ xorg-server-1.4.2/debian/patches/07_autoconfig_screen_with_device_section.diff
@@ -0,0 +1,27 @@
+Index: xorg-server/hw/xfree86/common/xf86Config.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86Config.c	2007-09-27 22:18:22.000000000 -0400
++++ xorg-server/hw/xfree86/common/xf86Config.c	2007-09-27 22:20:32.000000000 -0400
+@@ -1927,11 +1927,20 @@
+ 	if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor))
+ 	    return FALSE;
+     }
++    /* Configure the device. If there isn't one configured, attach to the
++     * first inactive one that we can configure. If there's none that work,
++     * set it to NULL so that the section can be autoconfigured later */
+     screenp->device     = xnfcalloc(1, sizeof(GDevRec));
+-    if (configDevice(screenp->device,conf_screen->scrn_device, TRUE))
++    if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) {
++        conf_screen->scrn_device = xf86configptr->conf_device_lst;
++	xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n"
++		"\tUsing the first device section listed.\n", screenp->id);
++    }
++    if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) {
+         screenp->device->myScreenSection = screenp;
+-    else
++    } else {
+         screenp->device = NULL;
++    }
+     screenp->options = conf_screen->scrn_option_lst;
+     
+     /*
--- xorg-server-1.4.2.orig/debian/patches/93_xprint_fonts_fix
+++ xorg-server-1.4.2/debian/patches/93_xprint_fonts_fix
@@ -0,0 +1,12 @@
+diff -ruN xorg-server-old/hw/xprint/ps/psout_ft.c xorg-server/hw/xprint/ps/psout_ft.c
+--- xorg-server-old/hw/xprint/ps/psout_ft.c	2006-04-02 10:09:43.000000000 +1000
++++ xorg-server/hw/xprint/ps/psout_ft.c	2006-04-14 22:22:42.000000000 +1000
+@@ -280,6 +280,8 @@
+       else
+       {
+         sprintf(buf, "%s", baseFontName);
++        xfree(self->FontName);
++        self->FontName = NULL;
+       }
+ 
+       if( self->FontSize == -1 )
--- xorg-server-1.4.2.orig/debian/patches/16_X86EMU-pass-the-correct-bus-dev-fn-tag-to-pci-emula.patch
+++ xorg-server-1.4.2/debian/patches/16_X86EMU-pass-the-correct-bus-dev-fn-tag-to-pci-emula.patch
@@ -0,0 +1,96 @@
+From 9c17439807c80876bf7027b17859714b31401ab9 Mon Sep 17 00:00:00 2001
+From: Bart Trojanowski <bart@jukie.net>
+Date: Fri, 11 Jan 2008 19:59:54 -0500
+Subject: [PATCH] X86EMU: pass the correct bus:dev:fn tag to pci emulation
+
+Signed-off-by: Bart Trojanowski <bart@jukie.net>
+
+Work funded by: Symbio Technologies
+
+There seems to be an inconsistency between what the x86emu gets from the
+PCI handling code and by accessing hardware directly.  x86emu relies on
+a set of functions to emulate PCI access.  When things goes wrong, the
+emulator is asked to execute an OUT instruction on port 0x20.
+
+I've put together a patch against xserver-xorg package that prevents
+accesses to BAD registers.  This turns a freeze into a segfault in X.
+
+http://www.jukie.net/~bart/patches/xorg-server/20080111/0001-X86EMU-added-blacklist-for-I-O-port-in-0-0xFF-range.patch
+
+It does not address the DDC not working, I hope that after fixing the
+bugs in x86emu, things may improve.
+
+Anyway, I am continuing to investigate the real cause of the PCI access
+issue.  To find out more read this thread:
+
+http://lists.freedesktop.org/archives/xorg/2008-January/031811.html
+
+-Bart
+
+diff -Nurp xorg-server-1.4.1~git20080118-patched/hw/xfree86/int10/helper_exec.c xorg-server-1.4.1~git20080118-working/hw/xfree86/int10/helper_exec.c
+--- xorg-server-1.4.1~git20080118-patched/hw/xfree86/int10/helper_exec.c	2008-01-22 10:22:26.000000000 -0800
++++ xorg-server-1.4.1~git20080118-working/hw/xfree86/int10/helper_exec.c	2008-01-22 11:00:52.000000000 -0800
+@@ -542,7 +542,8 @@ Mem_wl(CARD32 addr, CARD32 val)
+ 
+ static CARD32 PciCfg1Addr = 0;
+ 
+-#define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff)
++#define PCI_OFFSET(x) ((x) & 0x000000ff)
++#define PCI_TAG(x)    ((x) & 0x00ffff00)
+ 
+ static int
+ pciCfg1in(CARD16 addr, CARD32 *val)
+@@ -552,7 +553,7 @@ pciCfg1in(CARD16 addr, CARD32 *val)
+ 	return 1;
+     }
+     if (addr == 0xCFC) {
+-	*val = pciReadLong(Int10Current->Tag, OFFSET(PciCfg1Addr));
++	*val = pciReadLong(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr));
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_inl(%#x) = %8.8x\n", PciCfg1Addr, *val);
+ 	return 1;
+@@ -570,7 +571,7 @@ pciCfg1out(CARD16 addr, CARD32 val)
+     if (addr == 0xCFC) {
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_outl(%#x, %8.8x)\n", PciCfg1Addr, val);
+-	pciWriteLong(Int10Current->Tag, OFFSET(PciCfg1Addr), val);
++	pciWriteLong(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr), val);
+ 	return 1;
+     }
+     return 0;
+@@ -588,7 +589,7 @@ pciCfg1inw(CARD16 addr, CARD16 *val)
+     }
+     if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ 	offset = addr - 0xCFC;
+-	*val = pciReadWord(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset);
++	*val = pciReadWord(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr) + offset);
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_inw(%#x) = %4.4x\n", PciCfg1Addr + offset, *val);
+ 	return 1;
+@@ -611,7 +612,7 @@ pciCfg1outw(CARD16 addr, CARD16 val)
+ 	offset = addr - 0xCFC;
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_outw(%#x, %4.4x)\n", PciCfg1Addr + offset, val);
+-	pciWriteWord(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset, val);
++	pciWriteWord(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr) + offset, val);
+ 	return 1;
+     }
+     return 0;
+@@ -629,7 +630,7 @@ pciCfg1inb(CARD16 addr, CARD8 *val)
+     }
+     if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
+ 	offset = addr - 0xCFC;
+-	*val = pciReadByte(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset);
++	*val = pciReadByte(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr) + offset);
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_inb(%#x) = %2.2x\n", PciCfg1Addr + offset, *val);
+ 	return 1;
+@@ -652,7 +653,7 @@ pciCfg1outb(CARD16 addr, CARD8 val)
+ 	offset = addr - 0xCFC;
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" cfg_outb(%#x, %2.2x)\n", PciCfg1Addr + offset, val);
+-	pciWriteByte(Int10Current->Tag, OFFSET(PciCfg1Addr) + offset, val);
++	pciWriteByte(PCI_TAG(PciCfg1Addr), PCI_OFFSET(PciCfg1Addr) + offset, val);
+ 	return 1;
+     }
+     return 0;
--- xorg-server-1.4.2.orig/debian/patches/001_ubuntu_add_extra_modelines_from_xorg.patch
+++ xorg-server-1.4.2/debian/patches/001_ubuntu_add_extra_modelines_from_xorg.patch
@@ -0,0 +1,63 @@
+--- foo/hw/xfree86/common/extramodes.orig	2005-03-28 14:40:18.784980424 +1000
++++ bar/hw/xfree86/common/extramodes	2005-03-28 15:04:04.731203648 +1000
+@@ -7,27 +7,53 @@
+ # 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz
+ ModeLine "832x624" 57.284 832  864  928 1152  624  625  628  667 -Hsync -Vsync
+ 
++# 1280x768 @ 60Hz (LCD native res) hsync: 47.70kHz
++ModeLine "1280x768" 80.14 1280 1344 1480 1680  768 769 772 795
++
++# 1280x800 @ 60Hz (LCD native res) hsync: 49.68kHz
++ModeLine "1280x800" 83.46 1280 1344 1480 1680  800 801 804 828
++
+ # 1152x768 @ 54.8Hz (Titanium PowerBook) hsync: 44.2kHz
+-ModeLine "1152x768"   64.995 1152 1178 1314 1472  768  771  777  806 +hsync +vsync
++ModeLine "1152x768" 64.995 1152 1178 1314 1472  768  771  777  806 +hsync +vsync
++
++# 1152x864 @ 85Hz (Red Hat custom modeline)
++ModeLine "1152x864" 121.5 1152 1216 1344 1568    864  865  868  911 +hsync -vsync
+ 
+ # 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz
+ ModeLine "1400x1050" 122.0 1400 1488 1640 1880   1050 1052 1064 1082 +hsync +vsync
+ 
++# 1400x1050 @ 70Hz (Red Hat custom modeline) hsync: 76.8kHz
++ModeLine "1400x1050" 151.0 1400 1464 1656 1960   1050 1051 1054 1100 +hsync +vsync
++
+ # 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz
+ ModeLine "1400x1050" 155.8 1400 1464 1784 1912   1050 1052 1064 1090 +hsync +vsync
+ 
++# 1400x1050 @ 85Hz (Red Hat custom modeline) hsync: 93.2 kHz
++ModeLine "1400x1050" 184.0 1400 1464 1656 1960   1050 1051 1054 1100 +hsync +vsync
++
++# 1440x900 @ 100Hz (17" iMac LCD) hsync: 67 kHz
++ModeLine "1440x900" 108.84 1440 1472 1880 1912   900 918 927 946 +hsync +vsync
++
+ # 1600x1024 @ 60Hz (SGI 1600SW) hsync: 64.0kHz
+-Modeline "1600x1024" 106.910 1600 1620 1640 1670 1024 1027 1030 1067 -hsync -vsync
++ModeLine "1600x1024" 106.910 1600 1620 1640 1670 1024 1027 1030 1067 -hsync -vsync
++
++# 1680x1050 @ 60Hz (LCD native res) hsync: 64.22kHz
++ModeLine "1680x1050" 147.14 1680 1784 1968 2256  1050 1051 1054 1087
++
++# 1920x1200 @ 60Hz (LCD native res) hsync: 74.52kHz
++ModeLine "1920x1200" 193.16 1920 2048 2256 2592  1200 1201 1204 1242
++
++# 1920x1200 @ 70Hz (Red Hat custom modeline - bugzilla #53364) hsync: 87.50 KHz
++ModeLine "1920x1200" 230.0 1920 1936 2096 2528  1200 1201 1204 1250 -HSync -VSync
+ 
+ # 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz
+-Modeline "1920x1440" 341.35  1920 2072 2288 2656  1440 1441 1444 1512 -hsync +vsync
++ModeLine "1920x1440" 341.35  1920 2072 2288 2656  1440 1441 1444 1512 -hsync +vsync
+ 
+ # 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz
+-Modeline "2048x1536" 266.95  2048 2200 2424 2800  1536 1537 1540 1589 -hsync +vsync
++ModeLine "2048x1536" 266.95  2048 2200 2424 2800  1536 1537 1540 1589 -hsync +vsync
+ 
+ # 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz
+-Modeline "2048x1536" 340.48  2048 2216 2440 2832  1536 1537 1540 1603 -hsync +vsync
++ModeLine "2048x1536" 340.48  2048 2216 2440 2832  1536 1537 1540 1603 -hsync +vsync
+ 
+ # 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz
+-Modeline "2048x1536" 388.04  2048 2216 2440 2832  1536 1537 1540 1612 -hsync +vsync
+-
++ModeLine "2048x1536" 388.04  2048 2216 2440 2832  1536 1537 1540 1612 -hsync +vsync
--- xorg-server-1.4.2.orig/debian/patches/02_libvgahw_gcc4_volatile_fix.diff
+++ xorg-server-1.4.2/debian/patches/02_libvgahw_gcc4_volatile_fix.diff
@@ -0,0 +1,70 @@
+gcc4 has issues with libvgahw.a. This patch is a workaround stolen from
+https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=161242 (by Olivier
+Baudron). See also Debian #318218 and bugs merged to it
+
+Index: xorg-server/hw/xfree86/vgahw/vgaHW.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/vgahw/vgaHW.c	2006-11-26 01:24:48.000000000 +0100
++++ xorg-server/hw/xfree86/vgahw/vgaHW.c	2006-11-26 01:25:44.000000000 +0100
+@@ -434,12 +434,16 @@
+ static void
+ mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value)
+ {
++    volatile CARD8 tmp;
++
+     if (hwp->paletteEnabled)
+ 	index &= ~0x20;
+     else
+ 	index |= 0x20;
+ 
+-    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    /* gcc-4.0 -O2 is broken : needs a volatile assignment */ 
++    tmp = minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++
+     moutb(VGA_ATTR_INDEX, index);
+     moutb(VGA_ATTR_DATA_W, value);
+ }
+@@ -447,12 +451,16 @@
+ static CARD8
+ mmioReadAttr(vgaHWPtr hwp, CARD8 index)
+ {
++    volatile CARD8 tmp;
++  
+     if (hwp->paletteEnabled)
+ 	index &= ~0x20;
+     else
+ 	index |= 0x20;
+ 
+-    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    /* gcc-4.0 -O2 is broken : needs a volatile assignment */ 
++    tmp = minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++
+     moutb(VGA_ATTR_INDEX, index);
+     return minb(VGA_ATTR_DATA_R);
+ }
+@@ -472,7 +480,11 @@
+ static void
+ mmioEnablePalette(vgaHWPtr hwp)
+ {
+-    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    volatile CARD8 tmp;
++    
++    /* gcc-4.0 -O2 is broken : needs a volatile assignment */ 
++    tmp = minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    
+     moutb(VGA_ATTR_INDEX, 0x00);
+     hwp->paletteEnabled = TRUE;
+ }
+@@ -480,7 +492,11 @@
+ static void
+ mmioDisablePalette(vgaHWPtr hwp)
+ {
+-    (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    volatile CARD8 tmp;
++    
++    /* gcc-4.0 -O2 is broken : needs a volatile assignment */ 
++    tmp = minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET);
++    
+     moutb(VGA_ATTR_INDEX, 0x20);
+     hwp->paletteEnabled = FALSE;
+ }
--- xorg-server-1.4.2.orig/debian/patches/48_xaa_nooffscreenpixmaps.diff
+++ xorg-server-1.4.2/debian/patches/48_xaa_nooffscreenpixmaps.diff
@@ -0,0 +1,41 @@
+xaa: disable offscreen pixmaps by default
+
+Can be enabled with Option "XaaOffscreenPixmaps".
+
+Index: xorg-server/hw/xfree86/xaa/xaaInitAccel.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/xaa/xaaInitAccel.c
++++ xorg-server/hw/xfree86/xaa/xaaInitAccel.c
+@@ -87,7 +87,7 @@
+ 				OPTV_BOOLEAN,	{0}, FALSE },
+     {XAAOPT_PIXMAP_CACHE,		"XaaNoPixmapCache",
+ 				OPTV_BOOLEAN,	{0}, FALSE },
+-    {XAAOPT_OFFSCREEN_PIXMAPS,		"XaaNoOffscreenPixmaps",
++    {XAAOPT_OFFSCREEN_PIXMAPS,		"XaaOffscreenPixmaps",
+ 				OPTV_BOOLEAN,	{0}, FALSE },
+     { -1,				NULL,
+ 				OPTV_NONE,	{0}, FALSE }
+@@ -542,7 +542,7 @@
+ #define XAAMSG(s) do { if (serverGeneration == 1) xf86ErrorF(s); } while (0)
+ 
+     if((infoRec->Flags & OFFSCREEN_PIXMAPS) && HaveScreenToScreenCopy &&
+-		!xf86IsOptionSet(options, XAAOPT_OFFSCREEN_PIXMAPS)) {
++		xf86IsOptionSet(options, XAAOPT_OFFSCREEN_PIXMAPS)) {
+ 	XAAMSG("\tOffscreen Pixmaps\n");
+     } else {
+ 	infoRec->Flags &= ~OFFSCREEN_PIXMAPS;
+Index: xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre
+===================================================================
+--- xorg-server.orig/hw/xfree86/doc/man/xorg.conf.man.pre
++++ xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre
+@@ -1648,8 +1648,8 @@
+ Disables accelerated fills of a trapezoidal region with a monochrome
+ pattern.
+ .TP 7
+-.BI "Option \*qXaaNoOffscreenPixmaps\*q"
+-Disables accelerated draws into pixmaps stored in offscreen video memory.
++.BI "Option \*qXaaOffscreenPixmaps\*q"
++Enables accelerated draws into pixmaps stored in offscreen video memory.
+ .TP 7
+ .BI "Option \*qXaaNoPixmapCache\*q"
+ Disables caching of patterns in offscreen video memory.
--- xorg-server-1.4.2.orig/debian/patches/08_better_dpms_logging.diff
+++ xorg-server-1.4.2/debian/patches/08_better_dpms_logging.diff
@@ -0,0 +1,31 @@
+Index: xorg-server/hw/xfree86/common/xf86DPMS.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86DPMS.c	2008-01-07 20:19:47.000000000 -0500
++++ xorg-server/hw/xfree86/common/xf86DPMS.c	2008-01-07 20:28:11.000000000 -0500
+@@ -61,6 +61,7 @@
+     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+     DPMSPtr pDPMS;
+     pointer DPMSOpt;
++    MessageType enabled_from = X_INFO;
+ 
+     if (serverGeneration != DPMSGeneration) {
+ 	if ((DPMSIndex = AllocateScreenPrivateIndex()) < 0)
+@@ -82,8 +83,8 @@
+ 	    = xf86SetBoolOption(pScrn->options, "dpms", FALSE))
+ 	    && !DPMSDisabledSwitch)
+ 	    DPMSEnabled = TRUE;
++            enabled_from = X_CONFIG;
+ 	xf86MarkOptionUsed(DPMSOpt);
+-	xf86DrvMsg(pScreen->myNum, X_CONFIG, "DPMS enabled\n");
+     } else if (DPMSEnabledSwitch) {
+ 	if (!DPMSDisabledSwitch)
+ 	    DPMSEnabled = TRUE;
+@@ -92,6 +93,8 @@
+     else {
+ 	pDPMS->Enabled = defaultDPMSEnabled;
+     }
++    if (pDPMS->Enabled)
++	xf86DrvMsg(pScreen->myNum, enabled_from, "DPMS enabled\n");
+     pDPMS->CloseScreen = pScreen->CloseScreen;
+     pScreen->CloseScreen = DPMSClose;
+     DPMSCount++;
--- xorg-server-1.4.2.orig/debian/patches/53_Properly-initialize-io.pi_sel.pc_domain-on-kfreebsd.patch
+++ xorg-server-1.4.2/debian/patches/53_Properly-initialize-io.pi_sel.pc_domain-on-kfreebsd.patch
@@ -0,0 +1,32 @@
+From 43b9645e4f5343757613c422c9e1204ba826d1f7 Mon Sep 17 00:00:00 2001
+From: Petr Salinger <Petr.Salinger@seznam.cz>
+Date: Mon, 6 Oct 2008 18:33:31 +0200
+Subject: [PATCH] Properly initialize io.pi_sel.pc_domain on kfreebsd
+
+---
+ hw/xfree86/os-support/bus/freebsdPci.c |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/hw/xfree86/os-support/bus/freebsdPci.c b/hw/xfree86/os-support/bus/freebsdPci.c
+index 63c00b2..b1f3dbd 100644
+--- a/hw/xfree86/os-support/bus/freebsdPci.c
++++ b/hw/xfree86/os-support/bus/freebsdPci.c
+@@ -133,6 +133,7 @@ freebsdPciCfgRead(PCITAG tag, int off)
+ {
+ 	struct pci_io io;
+ 	int error;
++	io.pi_sel.pc_domain = PCI_DOM_FROM_TAG(tag);
+ 	io.pi_sel.pc_bus = BUS(tag);
+ 	io.pi_sel.pc_dev = DFN(tag) >> 3;
+ 	io.pi_sel.pc_func = DFN(tag) & 7;
+@@ -148,6 +149,7 @@ static void
+ freebsdPciCfgWrite(PCITAG tag, int off, CARD32 val)
+ {
+ 	struct pci_io io;
++	io.pi_sel.pc_domain = PCI_DOM_FROM_TAG(tag);
+ 	io.pi_sel.pc_bus = BUS(tag);
+ 	io.pi_sel.pc_dev = DFN(tag) >> 3;
+ 	io.pi_sel.pc_func = DFN(tag) & 7;
+-- 
+1.5.6.5
+
--- xorg-server-1.4.2.orig/debian/patches/13_debian_add_xkbpath_env_variable.diff
+++ xorg-server-1.4.2/debian/patches/13_debian_add_xkbpath_env_variable.diff
@@ -0,0 +1,27 @@
+--- xorg-server.orig/xkb/xkbInit.c
++++ xorg-server/xkb/xkbInit.c
+@@ -835,6 +835,14 @@
+ extern unsigned char	XkbDfltAccessXOptions;
+ 
+ int
++xkbInitGlobals()
++{
++    char * xkbpath= getenv("XKBPATH");
++    if (xkbpath!=NULL)
++	XkbBaseDirectory= xkbpath;
++}
++
++int
+ XkbProcessArguments(int argc,char *argv[],int i)
+ {
+     if (strcmp(argv[i],"-kb")==0) {
+--- xorg-server.orig/os/utils.c
++++ xorg-server/os/utils.c
+@@ -684,6 +684,7 @@
+  */
+ void InitGlobals(void)
+ {
++    xkbInitGlobals();
+     ddxInitGlobals();
+ }
+ 
--- xorg-server-1.4.2.orig/debian/patches/41_vbe_filter_less.diff
+++ xorg-server-1.4.2/debian/patches/41_vbe_filter_less.diff
@@ -0,0 +1,46 @@
+* Fri Sep 22 2006 Adam Jackson <ajackson@redhat.com> 1.1.1-41.fc6
+- xorg-x11-server-1.1.1-vbe-filter-less.patch: Be gentler about rejecting
+  VESA modes early, since xf86ValidateModes should handle them just fine.
+
+http://cvs.fedora.redhat.com/viewcvs/devel/xorg-x11-server/xorg-x11-server-1.1.1-vbe-filter-less.patch?rev=1.1&view=auto
+Debian bug #424684 (and maybe #428711)
+
+Index: xorg-server/hw/xfree86/vbe/vbeModes.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/vbe/vbeModes.c	2007-07-05 17:55:24.000000000 +0200
++++ xorg-server/hw/xfree86/vbe/vbeModes.c	2007-07-05 17:57:01.000000000 +0200
+@@ -152,34 +152,6 @@
+ 	xf86ErrorFVerb(DEBUG_VERB, "*");
+     }
+ 
+-    /*
+-     * Check if there's a valid monitor mode that this one can be matched
+-     * up with.  The actual matching is done later.
+-     */
+-    if (modeOK) {
+-	Bool sizeMatch = FALSE;
+-	modeOK = FALSE;
+-	for (p = pScrn->monitor->Modes; p != NULL; p = p->next) {
+-	    if ((p->HDisplay != mode->XResolution) ||
+-		(p->VDisplay != mode->YResolution) ||
+-		(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))
+-		continue;
+-	    sizeMatch = TRUE;
+-	    /* XXX could support the various V_ flags */
+-	    status = xf86CheckModeForMonitor(p, pScrn->monitor);
+-	    if (status == MODE_OK) {
+-		modeOK = TRUE;
+-		break;
+-	    }
+-	}
+-	if (sizeMatch && !modeOK) {
+-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+-		       "Not using built-in mode \"%dx%d\" (%s)\n",
+-		        mode->XResolution, mode->YResolution,
+-		        xf86ModeStatusToString(status));
+-	}
+-    }
+-
+     xf86ErrorFVerb(DEBUG_VERB,
+ 	    "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution);
+     xf86ErrorFVerb(DEBUG_VERB,
--- xorg-server-1.4.2.orig/debian/patches/46_reduce_wakeups_from_smart_scheduler.patch
+++ xorg-server-1.4.2/debian/patches/46_reduce_wakeups_from_smart_scheduler.patch
@@ -0,0 +1,157 @@
+commit 2338d5c9914e2a43c3a4f7ee0f4355ad0a1ad9e7
+Author: Arjan van de Ven <arjan@linux.intel.com>
+Date:   Sun Oct 28 09:37:52 2007 +0100
+
+    reduce wakeups from smart scheduler
+    
+    The smart scheduler itimer currently always fires after each request
+    (which in turn causes the CPU to wake out of idle, burning precious
+    power). Rather than doing this, just stop the timer before going into
+    the select() portion of the WaitFor loop. It's a cheap system call, and
+    it will only get called if there's no more commands batched up from the
+    active fd.
+    
+    This change also allows some of the functions to be simplified;
+    setitimer() will only fail if it's passed invalid data, and we don't do
+    that... so make it void and remove all the conditional code that deals
+    with failure.
+    
+    The change also allows us to remove a few variables that were used for
+    housekeeping between the signal handler and the main loop.
+    
+    Signed-off-by: Keith Packard <keithp@koto.keithp.com>
+
+commit 0e9ef65fa583bf2393dd0fda82df6f092387b425
+Author: Keith Packard <keithp@koto.keithp.com>
+Date:   Wed Nov 7 16:33:10 2007 -0800
+
+    Don't frob timers unless SmartSchedule is running
+
+--- xorg-server.orig/include/dixstruct.h
++++ xorg-server/include/dixstruct.h
+@@ -150,11 +150,9 @@
+ extern long SmartScheduleInterval;
+ extern long SmartScheduleSlice;
+ extern long SmartScheduleMaxSlice;
+-extern unsigned long SmartScheduleIdleCount;
+ extern Bool SmartScheduleDisable;
+-extern Bool SmartScheduleIdle;
+-extern Bool SmartScheduleTimerStopped;
+-extern Bool SmartScheduleStartTimer(void);
++extern void SmartScheduleStartTimer(void);
++extern void SmartScheduleStopTimer(void);
+ #define SMART_MAX_PRIORITY  (20)
+ #define SMART_MIN_PRIORITY  (-20)
+ 
+--- xorg-server.orig/os/WaitFor.c
++++ xorg-server/os/WaitFor.c
+@@ -217,7 +217,8 @@
+ 	XFD_COPYSET(&AllSockets, &LastSelectMask);
+ #ifdef SMART_SCHEDULE
+ 	}
+-	SmartScheduleIdle = TRUE;
++	SmartScheduleStopTimer ();
++
+ #endif
+ 	BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
+ 	if (NewOutputPending)
+@@ -237,13 +238,7 @@
+ 	selecterr = GetErrno();
+ 	WakeupHandler(i, (pointer)&LastSelectMask);
+ #ifdef SMART_SCHEDULE
+-	if (i >= 0)
+-	{
+-	    SmartScheduleIdle = FALSE;
+-	    SmartScheduleIdleCount = 0;
+-	    if (SmartScheduleTimerStopped)
+-		(void) SmartScheduleStartTimer ();
+-	}
++	SmartScheduleStartTimer ();
+ #endif
+ 	if (i <= 0) /* An error or timeout occurred */
+ 	{
+--- xorg-server.orig/os/utils.c
++++ xorg-server/os/utils.c
+@@ -1513,10 +1513,6 @@
+ 
+ #ifdef SMART_SCHEDULE
+ 
+-unsigned long	SmartScheduleIdleCount;
+-Bool		SmartScheduleIdle;
+-Bool		SmartScheduleTimerStopped;
+-
+ #ifdef SIGVTALRM
+ #define SMART_SCHEDULE_POSSIBLE
+ #endif
+@@ -1526,49 +1522,43 @@
+ #define SMART_SCHEDULE_TIMER		ITIMER_REAL
+ #endif
+ 
+-static void
++void
+ SmartScheduleStopTimer (void)
+ {
+ #ifdef SMART_SCHEDULE_POSSIBLE
+     struct itimerval	timer;
+     
++    if (SmartScheduleDisable)
++	return;
+     timer.it_interval.tv_sec = 0;
+     timer.it_interval.tv_usec = 0;
+     timer.it_value.tv_sec = 0;
+     timer.it_value.tv_usec = 0;
+     (void) setitimer (ITIMER_REAL, &timer, 0);
+-    SmartScheduleTimerStopped = TRUE;
+ #endif
+ }
+ 
+-Bool
++void
+ SmartScheduleStartTimer (void)
+ {
+ #ifdef SMART_SCHEDULE_POSSIBLE
+     struct itimerval	timer;
+     
+-    SmartScheduleTimerStopped = FALSE;
++    if (SmartScheduleDisable)
++	return;
+     timer.it_interval.tv_sec = 0;
+     timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
+     timer.it_value.tv_sec = 0;
+     timer.it_value.tv_usec = SmartScheduleInterval * 1000;
+-    return setitimer (ITIMER_REAL, &timer, 0) >= 0;
++    setitimer (ITIMER_REAL, &timer, 0);
+ #endif
+-    return FALSE;
+ }
+ 
+ #ifdef SMART_SCHEDULE_POSSIBLE
+ static void
+ SmartScheduleTimer (int sig)
+ {
+-    int olderrno = errno;
+-
+     SmartScheduleTime += SmartScheduleInterval;
+-    if (SmartScheduleIdle)
+-    {
+-	SmartScheduleStopTimer ();
+-    }
+-    errno = olderrno;
+ }
+ #endif
+ 
+@@ -1592,14 +1582,6 @@
+ 	perror ("sigaction for smart scheduler");
+ 	return FALSE;
+     }
+-    /* Set up the virtual timer */
+-    if (!SmartScheduleStartTimer ())
+-    {
+-	perror ("scheduling timer");
+-	return FALSE;
+-    }
+-    /* stop the timer and wait for WaitForSomething to start it */
+-    SmartScheduleStopTimer ();
+     return TRUE;
+ #else
+     return FALSE;
--- xorg-server-1.4.2.orig/debian/patches/series
+++ xorg-server-1.4.2/debian/patches/series
@@ -0,0 +1,39 @@
+001_ubuntu_add_extra_modelines_from_xorg.patch
+02_libvgahw_gcc4_volatile_fix.diff
+03_auto_load_driver.diff
+04_auto_load_driver_no_conf.diff
+05_kill_type1.diff
+06_use_proc_instead_of_sysfs_for_pci_domains.diff
+07_autoconfig_screen_with_device_section.diff
+08_better_dpms_logging.diff
+10_dont_look_in_home_for_config.diff
+11_dont_crash_on_bad_dri_mode.diff
+12_glx-don-t-crash-in-SwapBuffers-without-a-context.diff
+13_debian_add_xkbpath_env_variable.diff
+14_default_screen_section.diff
+15_X86EMU-added-blacklist-for-I-O-port-in-0-0xFF-range.patch
+16_X86EMU-pass-the-correct-bus-dev-fn-tag-to-pci-emula.patch
+17_x86emu_handle_cpuid.patch
+18_glx_initialize_getvisualconfigs_buf.diff
+21_glx_align_fixes.patch
+41_vbe_filter_less.diff
+43_allow_override_BIOS_EDID_preferred_mode.diff
+44_preferredmode_infinite_loop.diff
+45_only_XF86_APM_CAPABILITY_CHANGED_for_video_change_acpi_events.diff
+46_reduce_wakeups_from_smart_scheduler.patch
+47_fbdevhw_magic_numbers.diff
+48_xaa_nooffscreenpixmaps.diff
+49_x86emu_int1a_fix.diff
+50_Make-RandRQueryVersion-return-1.1-for-swapped-client.patch
+51_xevie-length.diff
+52_xevie-swap-replies.diff
+53_Properly-initialize-io.pi_sel.pc_domain-on-kfreebsd.patch
+54_more-sanity-checks.diff
+55_Fix-mod-macro-in-fb-and-mi.patch
+91_ttf2pt1
+91_ttf2pt1_updates
+92_xprint-security-holes-fix.patch
+93_spooltodir_check_file_exists
+93_xprint_fonts_fix
+94_xprint_XSERVER_LIBS
+95_xprint_disable_dbus
--- xorg-server-1.4.2.orig/debian/patches/49_x86emu_int1a_fix.diff
+++ xorg-server-1.4.2/debian/patches/49_x86emu_int1a_fix.diff
@@ -0,0 +1,70 @@
+commit 9e5b3deafb97ec1f83e6bfe067bc68df7385bc6a
+Author: Adam Jackson <ajax@redhat.com>
+Date:   Tue Jun 24 14:08:04 2008 -0400
+
+    Bug #11842: Fix emulation of int1A PCI BIOS services.
+    
+    Use only %di to name the PCI register to read/write, rather than %edi.
+    DOS is only expecting the base PCI config space anyway, and the BIOS
+    might be using the high bits of %edi.
+
+backported to pre-pciaccess, fixes #404885.
+
+Index: xorg-server/hw/xfree86/int10/xf86int10.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/int10/xf86int10.c	2008-06-24 20:31:06.000000000 +0200
++++ xorg-server/hw/xfree86/int10/xf86int10.c	2008-06-24 20:34:46.000000000 +0200
+@@ -667,7 +667,7 @@
+ 	return 1;
+     case 0xb108:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    X86_CL = pciReadByte(tag, X86_EDI);
++	    X86_CL = pciReadByte(tag, X86_DI);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
+@@ -680,7 +680,7 @@
+ 	return 1;
+     case 0xb109:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    X86_CX = pciReadWord(tag, X86_EDI);
++	    X86_CX = pciReadWord(tag, X86_DI);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
+@@ -693,7 +693,7 @@
+ 	return 1;
+     case 0xb10a:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    X86_ECX = pciReadLong(tag, X86_EDI);
++	    X86_ECX = pciReadLong(tag, X86_DI);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
+@@ -706,7 +706,7 @@
+ 	return 1;
+     case 0xb10b:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    pciWriteByte(tag, X86_EDI, X86_CL);
++	    pciWriteByte(tag, X86_DI, X86_CL);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
+@@ -719,7 +719,7 @@
+ 	return 1;
+     case 0xb10c:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    pciWriteWord(tag, X86_EDI, X86_CX);
++	    pciWriteWord(tag, X86_DI, X86_CX);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
+@@ -732,7 +732,7 @@
+ 	return 1;
+     case 0xb10d:
+ 	if ((tag = findPci(pInt, X86_EBX)) != PCI_NOT_FOUND) {
+-	    pciWriteLong(tag, X86_EDI, X86_ECX);
++	    pciWriteLong(tag, X86_DI, X86_ECX);
+ 	    X86_EAX = X86_AL | (SUCCESSFUL << 8);
+ 	    X86_EFLAGS &= ~((unsigned long)0x01); /* clear carry flag */
+ 	} else {
--- xorg-server-1.4.2.orig/debian/patches/09_debian_xserver_rtff.diff
+++ xorg-server-1.4.2/debian/patches/09_debian_xserver_rtff.diff
@@ -0,0 +1,52 @@
+$Id: 910_debian_Xserver_RTFF.diff 486 2005-08-03 04:51:11Z dnusinow $
+
+Give the user a far stronger clue as to what to do when their font configuration
+is horribly screwed up; this patch by Branden Robinson.
+
+Index: a/dix/main.c
+===================================================================
+--- a/dix/main.c.orig	2006-11-13 19:59:22.000000000 +0100
++++ b/dix/main.c	2006-11-26 01:55:13.000000000 +0100
+@@ -407,10 +407,42 @@
+ 			defaultFontPath);
+ 	}
+ 	if (!SetDefaultFont(defaultTextFont))
++#ifdef DEBIAN
++	    FatalError("could not open default font '%s';\n"
++"the X server's font paths might be misconfigured, remote font server(s)\n"
++"may be unreachable, and/or local fonts may not be installed or are not\n"
++"configured correctly.\n"
++"\n"
++"People inexperienced with the X Window System should have the\n"
++"\"xorg\" package installed.\n"
++"# apt-get install xorg\n"
++"\n"
++"Other useful commands to run include:\n"
++"$ dpkg --status x11-common\n"
++"$ dpkg --status xfonts-base\n"
++"$ zmore /usr/share/doc/x11-common/FAQ.gz", defaultTextFont);
++#else
+ 	    FatalError("could not open default font '%s'", defaultTextFont);
++#endif
+ 	if (!(rootCursor = CreateRootCursor(defaultCursorFont, 0)))
++#ifdef DEBIAN
++	    FatalError("could not open default cursor font '%s';\n"
++"the X server's font paths might be misconfigured, remote font server(s)\n"
++"may be unreachable, and/or local fonts may not be installed or are not\n"
++"configured correctly.\n"
++"\n"
++"People inexperienced with the X Window System should have the\n"
++"\"xorg\" package installed.\n"
++"# apt-get install xorg\n"
++"\n"
++"Other useful commands to run include:\n"
++"$ dpkg --status x11-common\n"
++"$ dpkg --status xfonts-base\n"
++"$ zmore /usr/share/doc/x11-common/FAQ.gz", defaultTextFont);
++#else
+ 	    FatalError("could not open default cursor font '%s'",
+ 		       defaultCursorFont);
++#endif
+ #ifdef DPMSExtension
+  	/* check all screens, looking for DPMS Capabilities */
+  	DPMSCapableFlag = DPMSSupported();
--- xorg-server-1.4.2.orig/debian/patches/95_xprint_disable_dbus
+++ xorg-server-1.4.2/debian/patches/95_xprint_disable_dbus
@@ -0,0 +1,30 @@
+From: Drew Parsons <dparsons@debian.org>
+Date: Fri, 9 May 2008 13:20:11 +0000 (+1000)
+Subject: Disable D-BUS from Xprint.
+X-Git-Url: http://gitweb.freedesktop.org/?p=xorg/xserver.git;a=commitdiff;h=2a3d1421e0cc18822ae8f478fcc272e16a9e9340
+
+Disable D-BUS from Xprint.
+
+Use dummy config functions to replace those from config/config.c, and
+therefore do not link Xprt with $CONFIG_LIB.
+
+Works around an endlessly spinning loop in dix/dispatch.c::Dispatch()
+(WaitForSomething() not waiting) when built with dbus, which was
+causing Xprt to use 95% cpu.
+---
+
+--- a/hw/xprint/ddxInit.c
++++ b/hw/xprint/ddxInit.c
+@@ -291,6 +291,12 @@ ddxProcessArgument (
+ #include "XIstubs.h"
+ #include "exglobals.h"
+ 
++/* Place dummy config functions here instead of config/config.c, 
++   since Xprint does not use D-BUS */
++void config_init() { }
++void config_fini() { }
++
++
+ int
+ ChangePointerDevice (
+     DeviceIntPtr       old_dev,
--- xorg-server-1.4.2.orig/debian/patches/21_glx_align_fixes.patch
+++ xorg-server-1.4.2/debian/patches/21_glx_align_fixes.patch
@@ -0,0 +1,57 @@
+--- xorg-server.orig/GL/glx/Makefile.am
++++ xorg-server/GL/glx/Makefile.am
+@@ -14,7 +14,8 @@
+ 	-I@MESA_SOURCE@/src/mesa/glapi \
+ 	-I@MESA_SOURCE@/src/mesa/main \
+ 	-DXFree86Server \
+-	@GLX_DEFINES@
++	@GLX_DEFINES@ \
++	@GLX_ARCH_DEFINES@
+ 
+ # none yet
+ #sdk_HEADERS =
+--- xorg-server.orig/configure.ac
++++ xorg-server/configure.ac
+@@ -287,6 +287,7 @@
+ 	case $host_os in
+ 		*netbsd*)	AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;;
+ 	esac
++	GLX_ARCH_DEFINES="-D__GLX_ALIGN64 -mieee"
+ 	;;
+   arm*)
+ 	ARM_VIDEO=yes
+@@ -317,6 +318,7 @@
+ 	xorg_loader_sparcmuldiv="yes"
+ 	SPARC64_VIDEO=yes
+ 	BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c"
++	GLX_ARCH_DEFINES="-D__GLX_ALIGN64"
+ 	;;
+   x86_64*|amd64*)
+   	use_x86_asm="yes"
+@@ -332,8 +334,16 @@
+ 				SYS_LIBS=-lamd64
+ 				;;
+ 	esac
++	GLX_ARCH_DEFINES="-D__GLX_ALIGN64"
++	;;
++  ia64*)
++  	GLX_ARCH_DEFINES="-D__GLX_ALIGN64"
++	;;
++  s390*)
++  	GLX_ARCH_DEFINES="-D__GLX_ALIGN64"
+ 	;;
+ esac
++AC_SUBST(GLX_ARCH_DEFINES)
+ 
+ dnl BSD *_video.c selection
+ AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes])
+--- xorg-server.orig/hw/dmx/glxProxy/Makefile.am
++++ xorg-server/hw/dmx/glxProxy/Makefile.am
+@@ -32,6 +32,7 @@
+                         unpack.h
+ 
+ AM_CFLAGS = \
++	    @GLX_ARCH_DEFINES@ \
+             $(DIX_CFLAGS) \
+             -I$(top_srcdir)/hw/dmx \
+             -I$(top_srcdir)/include \
--- xorg-server-1.4.2.orig/debian/patches/45_only_XF86_APM_CAPABILITY_CHANGED_for_video_change_acpi_events.diff
+++ xorg-server-1.4.2/debian/patches/45_only_XF86_APM_CAPABILITY_CHANGED_for_video_change_acpi_events.diff
@@ -0,0 +1,56 @@
+commit 74e84b8d891632141a60e2d29463ab46f622df3f
+Author: Matthias Hopf <mhopf@suse.de>
+Date:   Fri Oct 19 17:28:15 2007 +0200
+
+    Only issue XF86_APM_CAPABILITY_CHANGED for video change ACPI events (not e.g. brightness etc.).
+
+diff --git a/hw/xfree86/os-support/linux/lnx_acpi.c b/hw/xfree86/os-support/linux/lnx_acpi.c
+index 9808e37..bb975cc 100644
+--- a/hw/xfree86/os-support/linux/lnx_acpi.c
++++ b/hw/xfree86/os-support/linux/lnx_acpi.c
+@@ -69,9 +69,11 @@ lnxACPIGetEventFromOs(int fd, pmEvent *events, int num)
+ 	TimerSet(NULL, 0, ACPI_REOPEN_DELAY, lnxACPIReopen, NULL);
+ 	return 0;
+     }
++    /* FIXME: this only processes the first read ACPI event & might break
++     * with interrupted reads. */
+     
+     /* Check that we have a video event */
+-    if (strstr(ev, "video") == ev) {
++    if (!strncmp(ev, "video", 5)) {
+ 	char *video = NULL;
+ 	char *GFX = NULL;
+ 	char *notify = NULL;
+@@ -97,26 +99,19 @@ lnxACPIGetEventFromOs(int fd, pmEvent *events, int num)
+ 	ErrorF("data: 0x%lx\n",data_l);
+ #endif
+ 
+-	/* We currently don't differentiate between any event */
++	/* Differentiate between events */
+ 	switch (notify_l) {
+ 		case ACPI_VIDEO_NOTIFY_SWITCH:
+-			break;
+-		case ACPI_VIDEO_NOTIFY_PROBE:
+-			break;
+ 		case ACPI_VIDEO_NOTIFY_CYCLE:
+-			break;
+ 		case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
+-			break;
+ 		case ACPI_VIDEO_NOTIFY_PREV_OUTPUT:
+-			break;
++		    events[0] = XF86_APM_CAPABILITY_CHANGED;
++		    return 1;
++		case ACPI_VIDEO_NOTIFY_PROBE:
++		    return 0;
+ 		default:
+-			break;
++		    return 0;
+ 	}
+-
+-	/* Deal with all ACPI events as a capability change */
+-        events[0] = XF86_APM_CAPABILITY_CHANGED;
+-
+-	return 1;
+     }
+     
+     return 0;
--- xorg-server-1.4.2.orig/debian/patches/93_spooltodir_check_file_exists
+++ xorg-server-1.4.2/debian/patches/93_spooltodir_check_file_exists
@@ -0,0 +1,52 @@
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh
+--- xorg-server-old/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh	2006-04-14 22:14:47.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PS2PDFspooldir-GS/ps2pdf_spooltodir.sh	2006-04-14 22:17:05.000000000 +1000
+@@ -108,8 +108,21 @@
+ # which may screw-up further processing by other shell scripts ...
+ filename="`echo \"${filename}\" | tr '[:blank:]' '_' | tr -c -d '[:alnum:]_.-'`"
+ 
++# consider that the end name might be too long:
++# 1. Calculate the length of the suffix (I think we need to count in bytes)
++filename_length="`echo \"${filename_suffix}\" | wc -c`"
++# 2. remove this length from 256
++filename_length="`echo \"256-${filename_length}\" | bc`"
++# 3. and keep only the first 256 - suffix_length bytes from the name.
++filename="`echo \"${filename}\" | cut -b-${filename_length}`"
++
+ # ... add path and suffix ...
+-filename="${spooldir}/${filename}${filename_suffix}"
++# ... should be unique, but check anyway
++if [ -e "${spooldir}/${filename}" ]; then
++  filename="`tempfile -d "${spooldir}" -s "_${filename}${filename_suffix}"`"
++else
++  filename="${spooldir}/${filename}${filename_suffix}"
++fi
+ 
+ verbose "# File name is \"$filename\"."
+ 
+diff -ruN xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh xorg-server/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh
+--- xorg-server-old/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh	2006-04-14 22:14:47.000000000 +1000
++++ xorg-server/hw/xprint/config/C/print/models/PSspooldir/spooltodir.sh	2006-04-14 22:18:06.000000000 +1000
+@@ -108,8 +108,21 @@
+ # which may screw-up further processing by other shell scripts ...
+ filename="`echo \"${filename}\" | tr '[:blank:]' '_' | tr -c -d '[:alnum:]_.-'`"
+ 
++# consider that the end name might be too long:
++# 1. Calculate the length of the suffix (I think we need to count in bytes)
++filename_length="`echo \"${filename_suffix}\" | wc -c`"
++# 2. remove this length from 256
++filename_length="`echo \"256-${filename_length}\" | bc`"
++# 3. and keep only the first 256 - suffix_length bytes from the name.
++filename="`echo \"${filename}\" | cut -b-${filename_length}`"
++
+ # ... add path and suffix ...
+-filename="${spooldir}/${filename}${filename_suffix}"
++# ... should be unique, but check anyway
++if [ -e "${spooldir}/${filename}" ]; then
++  filename="`tempfile -d "${spooldir}" -s "_${filename}${filename_suffix}"`"
++else
++  filename="${spooldir}/${filename}${filename_suffix}"
++fi
+ 
+ verbose "# File name is \"$filename\"."
+ 
--- xorg-server-1.4.2.orig/debian/patches/55_Fix-mod-macro-in-fb-and-mi.patch
+++ xorg-server-1.4.2/debian/patches/55_Fix-mod-macro-in-fb-and-mi.patch
@@ -0,0 +1,44 @@
+From 8f536b80f153337f74f01be1a48f5067cefc47bc Mon Sep 17 00:00:00 2001
+From: Julien Cristau <jcristau@debian.org>
+Date: Mon, 29 Mar 2010 23:32:19 +0200
+Subject: [PATCH] Fix mod() macro in fb and mi
+
+Patch by Olivier Fourdan (Red Hat) via Ubuntu.
+
+References:
+https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/551193
+https://bugzilla.redhat.com/show_bug.cgi?id=570089
+---
+ fb/fbpict.c |    2 +-
+ mi/miarc.c  |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fb/fbpict.c b/fb/fbpict.c
+index 85b5171..ff29ff2 100644
+--- a/fb/fbpict.c
++++ b/fb/fbpict.c
+@@ -37,7 +37,7 @@
+ #include "mipict.h"
+ #include "fbpict.h"
+ 
+-#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
++#define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-(a)) % (b))
+ 
+ void
+ fbWalkCompositeRegion (CARD8 op,
+diff --git a/mi/miarc.c b/mi/miarc.c
+index 3b77ce7..34f4bb8 100644
+--- a/mi/miarc.c
++++ b/mi/miarc.c
+@@ -1528,7 +1528,7 @@ miRoundCap(
+ 
+ # define Dsin(d)	((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
+ # define Dcos(d)	((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
+-# define mod(a,b)	((a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
++# define mod(a,b)	((a) >= 0 ? (a) % (b) : (b) - (-(a)) % (b))
+ 
+ static double
+ miDcos (double a)
+-- 
+1.7.0.3
+
--- xorg-server-1.4.2.orig/debian/patches/51_xevie-length.diff
+++ xorg-server-1.4.2/debian/patches/51_xevie-length.diff
@@ -0,0 +1,42 @@
+From: Thorvald Natvig <thorvald@natvig.com>
+Subject: fix XEvIE
+
+For all the replys but ProcXevieQueryVersion, the rep.length field isn't
+set to zero, which makes the client misbehave when it gets the reply.
+
+Index: xorg-server/Xext/xevie.c
+===================================================================
+--- xorg-server.orig/Xext/xevie.c
++++ xorg-server/Xext/xevie.c
+@@ -213,6 +213,7 @@
+     
+     xevieModifiersOn = FALSE;
+ 
++    rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
+     WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep);
+@@ -232,6 +233,7 @@
+         XevieEnd(xevieClientIndex);
+     }
+ 
++    rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
+     WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep);
+@@ -250,6 +252,7 @@
+         return BadAccess;
+ 
+     xE = (xEvent *)&stuff->event;
++    rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
+     WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep);
+@@ -294,6 +297,7 @@
+         return BadAccess;
+ 
+     xevieMask = (long)stuff->event_mask;
++    rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
+     WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep);
--- xorg-server-1.4.2.orig/debian/patches/06_use_proc_instead_of_sysfs_for_pci_domains.diff
+++ xorg-server-1.4.2/debian/patches/06_use_proc_instead_of_sysfs_for_pci_domains.diff
@@ -0,0 +1,36 @@
+Upstream commit 56f21bda1ce95741c88c423b60bd709eef26eb12 was supposed to
+only avoid multiple scans of the PCI devices, but it actually also added
+an "optimization" based on using sysfs files instead of /proc. However,
+this code is broken, for instance because there are no ioctl handler on
+/sys/bus/pci/devices/*/config files while there some on /proc/bus/pci/*
+
+It breaks the Xserver on architectures that require such ioctls to scan
+the PCI devices and/or deal with PCI domains:
+#422077: xserver-xorg: Fatal server error on sparc: xf86MapPciMem failed
+#422095: xserver-xorg-core: fails to start on powerpc, no devices detected
+
+The following patch forces the server to behave as if we were running on
+a 2.4 kernel while scanning PCI devices, so that the sysfs code is disabled.
+
+Upstream doesn't apply this patch since they want to fix the sysfs-code.
+See https://bugs.freedesktop.org/show_bug.cgi?id=7248
+
+Thanks to Jim Watson for testing!
+
+---
+ hw/xfree86/os-support/bus/linuxPci.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: xorg-server-1.3.0.0.dfsg/hw/xfree86/os-support/bus/linuxPci.c
+===================================================================
+--- xorg-server-1.3.0.0.dfsg.orig/hw/xfree86/os-support/bus/linuxPci.c	2007-05-10 21:51:55.000000000 +0200
++++ xorg-server-1.3.0.0.dfsg/hw/xfree86/os-support/bus/linuxPci.c	2007-05-10 21:52:13.000000000 +0200
+@@ -148,7 +148,7 @@
+ 	int		domain, bus, dev, func;
+ 	char		file[64];
+ 	struct stat	ignored;
+-	static int is26 = -1;
++	static int is26 = 0;
+ 
+ 	domain = PCI_DOM_FROM_TAG(tag);
+ 	bus  = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag));
--- xorg-server-1.4.2.orig/debian/patches/44_preferredmode_infinite_loop.diff
+++ xorg-server-1.4.2/debian/patches/44_preferredmode_infinite_loop.diff
@@ -0,0 +1,28 @@
+From 29e0e180729a4f0cc020985a4de4c8bc4b9c7f5f Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@koto.keithp.com>
+Date: Mon, 22 Oct 2007 13:38:16 -0700
+Subject: [PATCH] Leave hardware-specified preferred modes alone when user preference exists.
+
+Instead of removing the preference bit marking the hardware declared mode
+preference, leave it in place and just move the user preferred mode to the
+front of the list while marking it with the USERPREF bit which will cause it
+to be selected by the initial mode selection code.
+---
+ hw/xfree86/modes/xf86Crtc.c |    3 +--
+ 1 files changed, 1 insertions(+), 2 deletions(-)
+
+Index: xorg-server/hw/xfree86/modes/xf86Crtc.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/modes/xf86Crtc.c
++++ xorg-server/hw/xfree86/modes/xf86Crtc.c
+@@ -1433,9 +1433,8 @@
+ 			output->probed_modes = mode;
+ 		    }
+ 		    mode->type |= (M_T_PREFERRED|M_T_USERPREF);
++		    break;
+ 		}
+-		else
+-		    mode->type &= ~M_T_PREFERRED;
+ 	    }
+ 	}
+ 	
--- xorg-server-1.4.2.orig/debian/patches/05_kill_type1.diff
+++ xorg-server-1.4.2/debian/patches/05_kill_type1.diff
@@ -0,0 +1,160 @@
+From 13949f997289068354e83bc83e50d97b8232efb1 Mon Sep 17 00:00:00 2001
+From: Julien Cristau <jcristau@debian.org>
+Date: Thu, 23 Aug 2007 11:27:33 +0200
+Subject: [PATCH] Get rid of the type1 font module.
+
+It is completely replaced by freetype these days.
+---
+ hw/xfree86/common/xf86AutoConfig.c   |    1 -
+ hw/xfree86/common/xf86Config.c       |    1 -
+ hw/xfree86/dixmods/Makefile.am       |    6 +--
+ hw/xfree86/dixmods/type1mod.c        |   75 ----------------------------------
+ hw/xfree86/doc/man/xorg.conf.man.pre |    4 +-
+ 5 files changed, 3 insertions(+), 84 deletions(-)
+ delete mode 100644 hw/xfree86/dixmods/type1mod.c
+
+Index: xorg-server/hw/xfree86/common/xf86AutoConfig.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86AutoConfig.c	2007-09-18 21:01:37.000000000 +0200
++++ xorg-server/hw/xfree86/common/xf86AutoConfig.c	2007-09-18 21:02:26.000000000 +0200
+@@ -49,7 +49,6 @@
+ 	"\tLoad\t\"dbe\"\n" \
+ 	"\tLoad\t\"glx\"\n" \
+ 	"\tLoad\t\"freetype\"\n" \
+-	"\tLoad\t\"type1\"\n" \
+ 	"\tLoad\t\"record\"\n" \
+ 	"\tLoad\t\"dri\"\n" \
+ 	"EndSection\n\n"
+Index: xorg-server/hw/xfree86/common/xf86Config.h
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86Config.h	2007-09-18 21:01:37.000000000 +0200
++++ xorg-server/hw/xfree86/common/xf86Config.h	2007-09-18 21:02:26.000000000 +0200
+@@ -61,7 +61,6 @@
+     {.name = "dbe",      .toLoad = TRUE,    .load_opt=NULL},
+     {.name = "glx",      .toLoad = TRUE,    .load_opt=NULL},
+     {.name = "freetype", .toLoad = TRUE,    .load_opt=NULL},
+-    {.name = "type1",    .toLoad = TRUE,    .load_opt=NULL},
+     {.name = "record",   .toLoad = TRUE,    .load_opt=NULL},
+     {.name = "dri",      .toLoad = TRUE,    .load_opt=NULL},
+     {.name = NULL,       .toLoad = FALSE,   .load_opt=NULL}
+Index: xorg-server/hw/xfree86/dixmods/Makefile.am
+===================================================================
+--- xorg-server.orig/hw/xfree86/dixmods/Makefile.am	2007-09-18 20:57:33.000000000 +0200
++++ xorg-server/hw/xfree86/dixmods/Makefile.am	2007-09-18 21:02:26.000000000 +0200
+@@ -40,8 +40,7 @@
+                          $(XTRAPMOD)
+ 
+ fontsmoduledir = $(moduledir)/fonts
+-fontsmodule_LTLIBRARIES = libfreetype.la \
+-                          libtype1.la
++fontsmodule_LTLIBRARIES = libfreetype.la
+ 
+ AM_CFLAGS = @XORG_CFLAGS@ @DIX_CFLAGS@
+ INCLUDES = @XORG_INCS@ \
+@@ -104,9 +103,6 @@
+ libfreetype_la_LDFLAGS = -avoid-version
+ libfreetype_la_SOURCES = ftmodule.c
+ 
+-libtype1_la_LDFLAGS = -avoid-version
+-libtype1_la_SOURCES = type1mod.c
+-
+ libdixmods_la_SOURCES = $(top_srcdir)/mi/miinitext.c
+ libdixmods_la_CFLAGS = -DXFree86LOADER $(AM_CFLAGS)
+ 
+Index: xorg-server/hw/xfree86/dixmods/type1mod.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/dixmods/type1mod.c	2007-09-10 14:32:05.000000000 +0200
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,75 +0,0 @@
+-/*
+- * Copyright (C) 1998 The XFree86 Project, Inc.  All Rights Reserved.
+- *
+- * Permission is hereby granted, free of charge, to any person obtaining a copy
+- * of this software and associated documentation files (the "Software"), to
+- * deal in the Software without restriction, including without limitation the
+- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+- * sell copies of the Software, and to permit persons to whom the Software is
+- * furnished to do so, subject to the following conditions:
+- *
+- * The above copyright notice and this permission notice shall be included in
+- * all copies or substantial portions of the Software.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+- * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+- *
+- * Except as contained in this notice, the name of the XFree86 Project shall
+- * not be used in advertising or otherwise to promote the sale, use or other
+- * dealings in this Software without prior written authorization from the
+- * XFree86 Project.
+- */
+-
+-#ifdef HAVE_XORG_CONFIG_H
+-#include <xorg-config.h>
+-#endif
+-
+-#include "misc.h"
+-
+-#include <X11/fonts/fontmod.h>
+-#include "xf86Module.h"
+-
+-static MODULESETUPPROTO(type1Setup);
+-
+-    /*
+-     * This is the module data function that is accessed when loading 
+-     * libtype1 as a module.
+-     */
+-
+-static XF86ModuleVersionInfo VersRec =
+-{
+-	"type1",
+-	MODULEVENDORSTRING,
+-	MODINFOSTRING1,
+-	MODINFOSTRING2,
+-	XORG_VERSION_CURRENT,
+-	1, 0, 2,
+-	ABI_CLASS_FONT,			/* Font module */
+-	ABI_FONT_VERSION,
+-	MOD_CLASS_FONT,
+-	{0,0,0,0}       /* signature, to be patched into the file by a tool */
+-};
+-
+-_X_EXPORT XF86ModuleData type1ModuleData = { &VersRec, type1Setup, NULL };
+-
+-extern void Type1RegisterFontFileFunctions(void);
+-
+-FontModule type1Module = {
+-    Type1RegisterFontFileFunctions,
+-    "Type1",
+-    NULL
+-};
+-
+-static pointer
+-type1Setup(pointer module, pointer opts, int *errmaj, int *errmin)
+-{
+-    type1Module.module = module;
+-    LoadFont(&type1Module);
+-
+-    /* Need a non-NULL return */
+-    return (pointer)1;
+-}
+Index: xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre
+===================================================================
+--- xorg-server.orig/hw/xfree86/doc/man/xorg.conf.man.pre	2007-09-18 20:51:46.000000000 +0200
++++ xorg-server/hw/xfree86/doc/man/xorg.conf.man.pre	2007-09-18 21:02:26.000000000 +0200
+@@ -700,10 +700,10 @@
+ prefix, or the \(lq.a\(rq, \(lq.o\(rq, or \(lq.so\(rq suffixes.
+ .PP
+ .RS 7
+-Example: the Type 1 font rasteriser can be loaded with the following entry:
++Example: the FreeType font rasteriser can be loaded with the following entry:
+ .PP
+ .RS 4
+-.B "Load \*qtype1\*q"
++.B "Load \*qfreetype\*q"
+ .RE
+ .RE
+ .TP 7
--- xorg-server-1.4.2.orig/debian/patches/12_glx-don-t-crash-in-SwapBuffers-without-a-context.diff
+++ xorg-server-1.4.2/debian/patches/12_glx-don-t-crash-in-SwapBuffers-without-a-context.diff
@@ -0,0 +1,33 @@
+From 48d47d3bdc951c11f442c7607b6e27bcd3627751 Mon Sep 17 00:00:00 2001
+From: Julien Cristau <jcristau@debian.org>
+Date: Wed, 10 Nov 2010 16:54:31 +0100
+Subject: [PATCH] glx: don't crash in SwapBuffers without a context
+
+Fixed upstream in d7ded953c4d263e3dd3374dc03eea19e80c05bc6 (Implment
+GLXPixmaps.)
+
+Signed-off-by: Julien Cristau <jcristau@debian.org>
+Tested-by: François Guerraz <kubrick@fgv6.net>
+---
+ GL/glx/glxcmds.c |    5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/GL/glx/glxcmds.c b/GL/glx/glxcmds.c
+index 900a347..7330ff6 100644
+--- a/GL/glx/glxcmds.c
++++ b/GL/glx/glxcmds.c
+@@ -472,8 +472,9 @@ static int GetDrawableOrPixmap( __GLXcontext *glxc, GLXDrawable drawId,
+ 	if (pDraw->type == DRAWABLE_WINDOW) {
+ 	    VisualID vid = wVisual((WindowPtr)pDraw);
+ 
+-	    modes = _gl_context_modes_find_visual(glxc->pGlxScreen->modes,
+-						  vid);
++	    if (glxc)
++		modes = _gl_context_modes_find_visual(glxc->pGlxScreen->modes,
++						      vid);
+ 	} else {
+ 	    /*
+ 	    ** An X Pixmap is not allowed as a parameter (a GLX Pixmap
+-- 
+1.7.2.3
+
--- xorg-server-1.4.2.orig/debian/patches/94_xprint_XSERVER_LIBS
+++ xorg-server-1.4.2/debian/patches/94_xprint_XSERVER_LIBS
@@ -0,0 +1,21 @@
+--- xorg-server.orig/hw/xprint/Makefile.am
++++ xorg-server/hw/xprint/Makefile.am
+@@ -18,6 +18,7 @@
+ 	$(top_builddir)/fb/libfb.la \
+ 	$(top_builddir)/render/librender.la \
+ 	$(XSERVER_LIBS) \
++	$(top_builddir)/mi/libmi.la \
+ 	$(top_builddir)/Xext/libXext.la \
+ 	$(top_builddir)/xkb/libxkb.la \
+ 	$(top_builddir)/xkb/libxkbstubs.la \
+--- xorg-server.orig/configure.ac
++++ xorg-server/configure.ac
+@@ -1635,7 +1635,7 @@
+ if test "x$XPRINT" = xyes; then
+ 	PKG_CHECK_MODULES([XPRINTMODULES], [printproto x11 xfont $XDMCP_MODULES xau])
+ 	XPRINT_CFLAGS="$XPRINTMODULES_CFLAGS"
+-	XPRINT_LIBS="$XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $RENDER_LIB $COMPOSITE_LIB $RANDR_LIB $XI_LIB $FIXES_LIB $DAMAGE_LIB $XI_LIB $GLX_LIBS $MIEXT_DAMAGE_LIB $CWRAP_LIBS $XKB_LIB $XKB_STUB_LIB"
++	XPRINT_LIBS="$XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $RENDER_LIB $COMPOSITE_LIB $RANDR_LIB $XI_LIB $FIXES_LIB $DAMAGE_LIB $XI_LIB $GLX_LIBS $MIEXT_DAMAGE_LIB $CWRAP_LIBS $XKB_LIB $XKB_STUB_LIB $DIX_LIB $MI_LIB $OS_LIB"
+ 	XPRINT_SYS_LIBS="$XPRINTMODULES_LIBS"
+ 
+ 	xpconfigdir=$libdir/X11/xserver
--- xorg-server-1.4.2.orig/debian/patches/17_x86emu_handle_cpuid.patch
+++ xorg-server-1.4.2/debian/patches/17_x86emu_handle_cpuid.patch
@@ -0,0 +1,230 @@
+From e76dd7d7991b32cfc0f64bddcdcee201f34a85c5 Mon Sep 17 00:00:00 2001
+From: Bart Trojanowski <bart@symbio-technologies.com>
+Date: Sat, 2 Feb 2008 12:21:57 -0500
+Subject: [PATCH] X86EMU: handle CPUID instruction
+
+This bug is tracked here:
+https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-amd/+bug/180742
+
+After trying to switch from X to VT (or just quit) the video-amd driver
+attempts to issue INT 10/0 to go to mode 3 (VGA).  The emulator, running
+the BIOS code, would then spit out:
+
+        c000:0282: A2 ILLEGAL EXTENDED X86 OPCODE!
+
+The opcode was 0F A2, or CPUID; it was not implemented in the emulator.
+This simple patch, against 1.3.0.0, handles the CPUID instruction in one of
+two ways:
+ 1) if ran on __i386__ or __x86_64__ then it calls the CPUID instruction
+     directly.
+ 2) if ran elsewhere it returns a canned 486dx4 set of values for
+     function 1.
+
+This fix allows the video-amd driver to switch back to console mode,
+with the GSW BIOS.
+
+Thanks to Symbio Technologies for funding my work, and ThinCan for
+providing hardware :)
+
+Signed-off-by: Bart Trojanowski <bart@jukie.net>
+---
+ hw/xfree86/x86emu/ops2.c                |   16 ++++++-
+ hw/xfree86/x86emu/prim_ops.c            |   44 +++++++++++++++++
+ hw/xfree86/x86emu/x86emu/prim_ops.h     |    1 +
+ hw/xfree86/x86emu/x86emu/prim_x86_gcc.h |   79 +++++++++++++++++++++++++++++++
+ 4 files changed, 139 insertions(+), 1 deletions(-)
+ create mode 100644 hw/xfree86/x86emu/x86emu/prim_x86_gcc.h
+
+diff --git a/hw/xfree86/x86emu/ops2.c b/hw/xfree86/x86emu/ops2.c
+index 8c6c535..324de8a 100644
+--- a/hw/xfree86/x86emu/ops2.c
++++ b/hw/xfree86/x86emu/ops2.c
+@@ -328,6 +328,20 @@ static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2))
+ }
+ 
+ /****************************************************************************
++REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
++Handles opcode 0x0f,0xa2
++****************************************************************************/
++static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2))
++{
++    START_OF_INSTR();
++    DECODE_PRINTF("CPUID\n");
++    TRACE_AND_STEP();
++    cpuid();
++    DECODE_CLEAR_SEGOVR();
++    END_OF_INSTR();
++}
++
++/****************************************************************************
+ REMARKS:
+ Handles opcode 0x0f,0xa3
+ ****************************************************************************/
+@@ -2734,7 +2748,7 @@ void (*x86emu_optab2[256])(u8) =
+ 
+ /*  0xa0 */ x86emuOp2_push_FS,
+ /*  0xa1 */ x86emuOp2_pop_FS,
+-/*  0xa2 */ x86emuOp2_illegal_op,
++/*  0xa2 */ x86emuOp2_cpuid,
+ /*  0xa3 */ x86emuOp2_bt_R,
+ /*  0xa4 */ x86emuOp2_shld_IMM,
+ /*  0xa5 */ x86emuOp2_shld_CL,
+diff --git a/hw/xfree86/x86emu/prim_ops.c b/hw/xfree86/x86emu/prim_ops.c
+index 461e09e..07ccfe5 100644
+--- a/hw/xfree86/x86emu/prim_ops.c
++++ b/hw/xfree86/x86emu/prim_ops.c
+@@ -102,6 +102,12 @@
+ #define	PRIM_OPS_NO_REDEFINE_ASM
+ #include "x86emu/x86emui.h"
+ 
++#if defined(__GNUC__)
++# if defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__)
++#  include "x86emu/prim_x86_gcc.h"
++# endif
++#endif
++
+ /*------------------------- Global Variables ------------------------------*/
+ 
+ static u32 x86emu_parity_tab[8] =
+@@ -2654,3 +2660,41 @@ DB(	if (CHECK_SP_ACCESS())
+     return res;
+ }
+ 
++/****************************************************************************
++REMARKS:
++CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
++****************************************************************************/
++void cpuid (void)
++{
++    u32 feature = M.x86.R_EAX;
++#ifdef X86EMU_HAS_HW_CPUID
++        hw_cpuid(&M.x86.R_EAX, &M.x86.R_EBX, &M.x86.R_ECX, &M.x86.R_EDX);
++#endif
++    switch (feature) {
++    case 0:
++        M.x86.R_EAX = 1;		// maximum function number we support
++#ifndef X86EMU_HAS_PRIM_CPUID
++        M.x86.R_EBX = 0x756e6547;
++        M.x86.R_ECX = 0x6c65746e;
++        M.x86.R_EDX = 0x49656e69;
++#endif
++        break;
++    case 1:
++#ifndef X86EMU_HAS_PRIM_CPUID
++        M.x86.R_EAX = 0x00000480;	// 486dx4
++        M.x86.R_EBX = 0x00000000;
++        M.x86.R_ECX = 0x00000000;
++        M.x86.R_EDX = 0x00000002;	// VME
++#else
++        M.x86.R_EDX &= 0x00000012;	// TSC and VME
++#endif
++        break;
++    default:
++        M.x86.R_EAX = 0;		// don't support extended features
++        M.x86.R_EBX = 0;
++        M.x86.R_ECX = 0;
++        M.x86.R_EDX = 0;
++        break;
++    }
++}
++
+diff --git a/hw/xfree86/x86emu/x86emu/prim_ops.h b/hw/xfree86/x86emu/x86emu/prim_ops.h
+index bea8357..6ac2a29 100644
+--- a/hw/xfree86/x86emu/x86emu/prim_ops.h
++++ b/hw/xfree86/x86emu/x86emu/prim_ops.h
+@@ -133,6 +133,7 @@ void    push_word (u16 w);
+ void    push_long (u32 w);
+ u16     pop_word (void);
+ u32		pop_long (void);
++void    cpuid (void);
+ 
+ #ifdef  __cplusplus
+ }                       			/* End of "C" linkage for C++   	*/
+diff --git a/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h b/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h
+new file mode 100644
+index 0000000..c085ddc
+--- /dev/null
++++ b/hw/xfree86/x86emu/x86emu/prim_x86_gcc.h
+@@ -0,0 +1,79 @@
++/****************************************************************************
++*
++* Inline helpers for x86emu
++*
++* Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC
++*
++*  ========================================================================
++*
++*  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 the authors not be used
++*  in advertising or publicity pertaining to distribution of the software
++*  without specific, written prior permission.  The authors makes no
++*  representations about the suitability of this software for any purpose.
++*  It is provided "as is" without express or implied warranty.
++*
++*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++*  EVENT SHALL THE AUTHORS 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.
++*
++*  ========================================================================
++*
++* Language:     GNU C
++* Environment:  GCC on i386 or x86-64
++* Developer:    Bart Trojanowski
++*
++* Description:  This file defines a few x86 macros that can be used by the
++*               emulator to execute native instructions.
++*
++*               For PIC vs non-PIC code refer to:
++*               http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
++*
++****************************************************************************/
++#ifndef __X86EMU_PRIM_X86_GCC_H
++#define __X86EMU_PRIM_X86_GCC_H
++
++#include "x86emu/types.h"
++
++#if !defined(__GNUC__) || !(defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__))
++#error This file is intended to be used by gcc on i386 or x86-64 system
++#endif
++
++#if defined(__PIC__) && defined(__i386__)
++
++#define X86EMU_HAS_HW_CPUID 1
++static inline void hw_cpuid (u32 *a, u32 *b, u32 *c, u32 *d)
++{
++    __asm__ __volatile__ ("pushl %%ebx      \n\t"
++                          "cpuid            \n\t"
++                          "movl %%ebx, %1   \n\t"
++                          "popl %%ebx       \n\t"
++                          : "=a" (*a), "=r" (*b),
++                            "=c" (*c), "=d" (*d)
++                          : "a" (*a), "c" (*c)
++                          : "cc");
++}
++
++#else // ! (__PIC__ && __i386__)
++
++#define X86EMU_HAS_HW_CPUID 1
++static inline void hw_cpuid (u32 *a, u32 *b, u32 *c, u32 *d)
++{
++    __asm__ __volatile__ ("cpuid"
++                          : "=a" (*a), "=b" (*b),
++                            "=c" (*c), "=d" (*d)
++                          : "a" (*a), "c" (*c)
++                          : "cc");
++}
++
++#endif // __PIC__ && __i386__
++
++
++#endif // __X86EMU_PRIM_X86_GCC_H
+-- 
+1.5.3.7.1150.g149d432
+
--- xorg-server-1.4.2.orig/debian/patches/03_auto_load_driver.diff
+++ xorg-server-1.4.2/debian/patches/03_auto_load_driver.diff
@@ -0,0 +1,335 @@
+Index: xorg-server/hw/xfree86/common/xf86AutoConfig.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86AutoConfig.c
++++ xorg-server/hw/xfree86/common/xf86AutoConfig.c
+@@ -39,6 +39,7 @@
+ #include "xf86Config.h"
+ #include "xf86Priv.h"
+ #include "xf86_OSlib.h"
++#include "dirent.h"
+ 
+ /* Sections for the default built-in configuration. */
+ 
+@@ -292,3 +293,207 @@
+ 
+     return (ret == CONFIG_OK);
+ }
++
++int 
++xchomp(char *line)
++{
++    size_t len = 0;
++
++    if (!line) {
++        return 1;
++    }
++
++    len = strlen(line);
++    if (line[len - 1] == '\n' && len > 0) {
++        line[len - 1] = '\0';
++        return 0;
++    }
++}
++
++GDevPtr
++autoConfigDevice(GDevPtr preconf_device)
++{
++    GDevPtr ptr = NULL;
++    confScreenPtr scrn = NULL;
++
++    if (!xf86configptr) {
++        return NULL;
++    }
++
++    /* If there's a configured section with no driver chosen, use it */
++    if (preconf_device) {
++        ptr = preconf_device;
++    } else {
++        ptr = (GDevPtr)xalloc(sizeof(GDevRec));
++        if (!ptr) {
++            return NULL;
++        }
++        memset((GDevPtr)ptr, 0, sizeof(GDevRec));
++        ptr->chipID = -1;
++        ptr->chipRev = -1;
++        ptr->irq = -1;
++
++        ptr->active = TRUE;
++        ptr->claimed = FALSE;
++        ptr->identifier = "Autoconfigured Video Device";
++        ptr->driver = NULL;
++    }
++    if (!ptr->driver) {
++        ptr->driver = chooseVideoDriver();
++    }
++
++    /* TODO Handle multiple screen sections */
++    if (xf86ConfigLayout.screens && !xf86ConfigLayout.screens->screen->device) {   
++        xf86ConfigLayout.screens->screen->device = ptr;
++        ptr->myScreenSection = xf86ConfigLayout.screens->screen;
++    }
++    xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n");
++
++    return ptr;
++}
++
++char*
++chooseVideoDriver(void)
++{
++    pciVideoPtr *pciptr, info = NULL;
++    DIR *idsdir;
++    FILE *fp;
++    struct dirent *direntry;
++    char *line = NULL;
++    char *chosen_driver = NULL;
++    size_t len;
++    ssize_t read;
++    char path_name[256], vendor_str[5], chip_str[5];
++    int vendor, chip;
++    int i, j;
++    char *matches[20]; /* If we have more than 20 drivers we're in trouble */
++    
++    for (i=0 ; i<20 ; i++)
++        matches[i] = NULL;
++
++    /* Find the primary device, and get some information about it. */
++    if (xf86PciVideoInfo) {
++	    for (pciptr = xf86PciVideoInfo; (info = *pciptr); pciptr++) {
++	        if (xf86IsPrimaryPci(info)) {
++	    	break;
++	        }
++	    }
++	    if (!info) {
++	        ErrorF("Primary device is not PCI\n");
++	    }
++    } else {
++        ErrorF("xf86PciVideoInfo is not set\n");
++    }
++
++    if (!info) {
++        ErrorF("Could not get primary PCI info\n");
++        goto end;
++    }
++
++    idsdir = opendir("/usr/share/xserver-xorg/pci");
++    if (idsdir) {
++        direntry = readdir(idsdir);
++        /* Read the directory */
++        while (direntry) {
++            if (direntry->d_name[0] == '.') {
++                direntry = readdir(idsdir);
++                continue;
++            }
++            len = strlen(direntry->d_name);
++            /* A tiny bit of sanity checking. We should probably do better */
++            if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) {
++                /* We need the full path name to open the file */
++                strncpy(path_name, "/usr/share/xserver-xorg/pci/", 256);
++                strncat(path_name, direntry->d_name, (256 - strlen(path_name)));
++                fp = fopen(path_name, "r");
++                if (fp == NULL) {
++                    xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name);
++                    goto end;
++                }
++                /* Read the file */
++                while ((read = getline(&line, &len, fp)) != -1) {
++                    xchomp(line);
++                    if (isdigit(line[0])) {
++                        strncpy(vendor_str, line, 4);
++                        vendor_str[4] = '\0';
++                        vendor = (int)strtol(vendor_str, NULL, 16);
++                        if ((strlen(&line[4])) == 0) {
++                                chip_str[0] = '\0';
++                                chip = -1;
++                        } else {
++                                /* Handle trailing whitespace */
++                                if (isspace(line[4])) {
++                                    chip_str[0] = '\0';
++                                    chip = -1;
++                                } else {
++                                /* Ok, it's a real ID */
++                                    strncpy(chip_str, &line[4], 4);
++                                    chip_str[4] = '\0';
++                                    chip = (int)strtol(chip_str, NULL, 16);
++                                }
++                        }
++                        if (vendor == info->vendor && 
++                               (chip == info->chipType || chip == -1)) {
++                            i = 0;
++                            while (matches[i]) {
++                                i++;
++                            }
++                            matches[i] = (char*)xalloc(sizeof(char) * strlen(direntry->d_name) -  3);
++                            if (!matches[i]) {
++                                xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n");
++                                goto end;
++                            }
++                            /* hack off the .ids suffix. This should guard
++                             * against other problems, but it will end up
++                             * taking off anything after the first '.' */
++                            for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) {
++                                if (direntry->d_name[j] == '.') {
++                                    matches[i][j] = '\0';
++                                    break;
++                                } else {
++                                    matches[i][j] = direntry->d_name[j];
++                                }
++                            }
++                            xf86Msg(X_INFO, "Matched %s from file name %s in autoconfig\n", matches[i], direntry->d_name);
++
++                        }
++                    } else {
++                        /* TODO Handle driver overrides here */
++                    }
++                }
++                fclose(fp);
++            }
++            direntry = readdir(idsdir);
++        }
++    }
++
++    /* TODO Handle multiple drivers claiming to support the same PCI ID */
++    if (matches[0]) {
++        chosen_driver = matches[0];
++    } else {
++        #if defined  __i386__ || defined __amd64__ || defined __hurd__
++        chosen_driver = "vesa";
++        #elif defined __alpha__
++        chosen_driver = "vga";
++        #elif defined __sparc__
++        chosen_driver = "sunffb";
++        #else 
++        chosen_driver = "fbdev";
++        #endif
++    }
++
++    xf86Msg(X_DEFAULT, "Matched %s for the autoconfigured driver\n", chosen_driver);
++
++    end:
++    i = 0;
++    while (matches[i]) {
++        if (matches[i] != chosen_driver) {
++            xfree(matches[i]);
++        }
++        i++;
++    }
++    xfree(line);
++    closedir(idsdir);
++
++    return chosen_driver;
++}
+Index: xorg-server/hw/xfree86/common/xf86Config.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86Config.c
++++ xorg-server/hw/xfree86/common/xf86Config.c
+@@ -1928,8 +1928,10 @@
+ 	    return FALSE;
+     }
+     screenp->device     = xnfcalloc(1, sizeof(GDevRec));
+-    configDevice(screenp->device,conf_screen->scrn_device, TRUE);
+-    screenp->device->myScreenSection = screenp;
++    if (configDevice(screenp->device,conf_screen->scrn_device, TRUE))
++        screenp->device->myScreenSection = screenp;
++    else
++        screenp->device = NULL;
+     screenp->options = conf_screen->scrn_option_lst;
+     
+     /*
+@@ -2218,13 +2220,17 @@
+ {
+     int i;
+ 
++    if (!conf_device) {
++        return FALSE;
++    }
++
+     if (active)
+ 	xf86Msg(X_CONFIG, "|   |-->Device \"%s\"\n",
+ 		conf_device->dev_identifier);
+     else
+ 	xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n",
+ 		conf_device->dev_identifier);
+-	
++
+     devicep->identifier = conf_device->dev_identifier;
+     devicep->vendor = conf_device->dev_vendor;
+     devicep->board = conf_device->dev_board;
+Index: xorg-server/hw/xfree86/common/xf86Config.h
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86Config.h
++++ xorg-server/hw/xfree86/common/xf86Config.h
+@@ -34,6 +34,8 @@
+ #define _xf86_config_h
+ 
+ #include "xf86Optrec.h"
++#include "xf86Parser.h"
++#include "xf86str.h"
+ 
+ #ifdef HAVE_PARSER_DECLS
+ /*
+@@ -76,5 +78,8 @@
+ ConfigStatus xf86HandleConfigFile(Bool);
+ 
+ Bool xf86AutoConfig(void);
++GDevPtr autoConfigDevice(GDevPtr preconf_device);
++char* chooseVideoDriver(void);
++int xchomp(char *line);
+ 
+ #endif /* _xf86_config_h */
+Index: xorg-server/hw/xfree86/common/xf86Init.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86Init.c
++++ xorg-server/hw/xfree86/common/xf86Init.c
+@@ -347,6 +347,16 @@
+     }
+ 
+     /* Load all driver modules specified in the config file */
++    /* If there aren't any specified in the config file, autoconfig them */
++    /* FIXME: Does not handle multiple active screen sections, but I'm not
++     * sure if we really want to handle that case*/
++    GDevPtr configured_device = xf86ConfigLayout.screens->screen->device;
++    if ((!configured_device) || (!configured_device->driver)) {
++        if (!autoConfigDevice(configured_device)) {
++            xf86Msg(X_ERROR, "Automatic driver configuration failed\n");
++            return ;
++        }
++    }
+     if ((modulelist = xf86DriverlistFromConfig())) {
+       xf86LoadModules(modulelist, NULL);
+       xfree(modulelist);
+Index: xorg-server/hw/xfree86/parser/Screen.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/parser/Screen.c
++++ xorg-server/hw/xfree86/parser/Screen.c
+@@ -526,15 +526,7 @@
+ 			}
+ 		}
+ 
+-		device = xf86findDevice (screen->scrn_device_str, p->conf_device_lst);
+-		if (!device)
+-		{
+-			xf86validationError (UNDEFINED_DEVICE_MSG,
+-						  screen->scrn_device_str, screen->scrn_identifier);
+-			return (FALSE);
+-		}
+-		else
+-			screen->scrn_device = device;
++		screen->scrn_device= xf86findDevice (screen->scrn_device_str, p->conf_device_lst);
+ 
+ 		adaptor = screen->scrn_adaptor_lst;
+ 		while (adaptor)
+Index: xorg-server/hw/xfree86/parser/read.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/parser/read.c
++++ xorg-server/hw/xfree86/parser/read.c
+@@ -80,8 +80,8 @@
+ static int
+ xf86validateConfig (XF86ConfigPtr p)
+ {
+-	if (!xf86validateDevice (p))
+-		return FALSE;
++	/*if (!xf86validateDevice (p))
++		return FALSE;*/
+ 	if (!xf86validateScreen (p))
+ 		return FALSE;
+ 	if (!xf86validateInput (p))
--- xorg-server-1.4.2.orig/debian/patches/43_allow_override_BIOS_EDID_preferred_mode.diff
+++ xorg-server-1.4.2/debian/patches/43_allow_override_BIOS_EDID_preferred_mode.diff
@@ -0,0 +1,131 @@
+https://bugs.freedesktop.org/show_bug.cgi?id=10625
+
+From Keith Packard.
+Prefers user-specified PreferredMode over EDID/BIOS specified preferred modes.
+It should cause the config file to override the EDID/BIOS detected preferred modes.
+
+#	modified:   hw/xfree86/common/xf86str.h
+#	modified:   hw/xfree86/modes/xf86Crtc.c
+#	modified:   hw/xfree86/modes/xf86Crtc.h
+#
+Index: xorg-server/hw/xfree86/common/xf86str.h
+===================================================================
+--- xorg-server.orig/hw/xfree86/common/xf86str.h
++++ xorg-server/hw/xfree86/common/xf86str.h
+@@ -132,6 +132,7 @@
+ # define M_T_DEFAULT 0x10	/* (VESA) default modes */
+ # define M_T_USERDEF 0x20	/* One of the modes from the config file */
+ # define M_T_DRIVER  0x40	/* Supplied by the driver (EDID, etc) */
++# define M_T_USERPREF 0x80	/* mode preferred by the user config */
+ 
+ /* Video mode */
+ typedef struct _DisplayModeRec {
+Index: xorg-server/hw/xfree86/modes/xf86Crtc.c
+===================================================================
+--- xorg-server.orig/hw/xfree86/modes/xf86Crtc.c
++++ xorg-server/hw/xfree86/modes/xf86Crtc.c
+@@ -711,7 +711,8 @@
+     for (mode = output->probed_modes; mode; mode = mode->next)
+     {
+ 	int	    dpi;
+-	int	    preferred = (mode->type & M_T_PREFERRED) != 0;
++	int	    preferred = (((mode->type & M_T_PREFERRED) != 0) +
++				 ((mode->type & M_T_USERPREF) != 0));
+ 	int	    diff;
+ 
+ 	if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+@@ -1431,7 +1432,7 @@
+ 			mode->prev = NULL;
+ 			output->probed_modes = mode;
+ 		    }
+-		    mode->type |= M_T_PREFERRED;
++		    mode->type |= (M_T_PREFERRED|M_T_USERPREF);
+ 		}
+ 		else
+ 		    mode->type &= ~M_T_PREFERRED;
+@@ -1548,6 +1549,7 @@
+     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			o, c;
+     DisplayModePtr	target_mode = NULL;
++    int			target_preferred = 0;
+     Rotation		target_rotation = RR_Rotate_0;
+     xf86CrtcPtr		*crtcs;
+     DisplayModePtr	*modes;
+@@ -1588,43 +1590,34 @@
+     }
+     
+     /*
+-     * Let outputs with preferred modes drive screen size
++     * User preferred > preferred > other modes
+      */
+     for (o = 0; o < config->num_output; o++)
+     {
+-	xf86OutputPtr output = config->output[o];
++	xf86OutputPtr	output = config->output[o];
++	DisplayModePtr	default_mode;
++	int		default_preferred;
+ 
+-	if (enabled[o] &&
+-	    xf86OutputHasPreferredMode (output, width, height))
++	if (!enabled[o])
++	    continue;
++	default_mode = xf86DefaultMode (output, width, height);
++	if (!default_mode)
++	    continue;
++	default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
++			     ((default_mode->type & M_T_USERPREF) != 0));
++	if (default_preferred > target_preferred || !target_mode)
+ 	{
+-	    target_mode = xf86DefaultMode (output, width, height);
++	    target_mode = default_mode;
++	    target_preferred = default_preferred;
+ 	    target_rotation = output->initial_rotation;
+-	    if (target_mode)
+-	    {
+-		modes[o] = target_mode;
+-		config->compat_output = o;
+-		break;
+-	    }
+-	}
+-    }
+-    if (!target_mode)
+-    {
+-	for (o = 0; o < config->num_output; o++)
+-	{
+-	    xf86OutputPtr output = config->output[o];
+-	    if (enabled[o])
+-	    {
+-		target_mode = xf86DefaultMode (output, width, height);
+-		target_rotation = output->initial_rotation;
+-		if (target_mode)
+-		{
+-		    modes[o] = target_mode;
+-		    config->compat_output = o;
+-		    break;
+-		}
+-	    }
++	    config->compat_output = o;
+ 	}
+     }
++    if (target_mode)
++	modes[config->compat_output] = target_mode;
++    /*
++     * Fill in other output modes
++     */
+     for (o = 0; o < config->num_output; o++)
+     {
+ 	xf86OutputPtr output = config->output[o];
+Index: xorg-server/hw/xfree86/modes/xf86Crtc.h
+===================================================================
+--- xorg-server.orig/hw/xfree86/modes/xf86Crtc.h
++++ xorg-server/hw/xfree86/modes/xf86Crtc.h
+@@ -39,6 +39,9 @@
+ #ifndef M_T_DRIVER
+ #define M_T_DRIVER	0x40
+ #endif
++#ifndef M_T_USERPREF
++#define M_T_USERPREF	0x80
++#endif
+ #ifndef HARDWARE_CURSOR_ARGB
+ #define HARDWARE_CURSOR_ARGB				0x00004000
+ #endif
--- xorg-server-1.4.2.orig/debian/patches/50_Make-RandRQueryVersion-return-1.1-for-swapped-client.patch
+++ xorg-server-1.4.2/debian/patches/50_Make-RandRQueryVersion-return-1.1-for-swapped-client.patch
@@ -0,0 +1,31 @@
+From 40090eca032d602c78223abaa13ca4702db86b74 Mon Sep 17 00:00:00 2001
+From: Julien Cristau <jcristau@debian.org>
+Date: Sun, 24 Aug 2008 17:44:10 +0200
+Subject: [PATCH] Make RandRQueryVersion return 1.1 for swapped clients
+
+Don't pretend we support randr 1.2 when queried by swapped clients.
+The dispatch code for RandR 1.2 requests would return BadImplementation
+anyway.
+---
+ randr/rrdispatch.c |    5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
+index 5525427..83deb6b 100644
+--- a/randr/rrdispatch.c
++++ b/randr/rrdispatch.c
+@@ -55,6 +55,11 @@ ProcRRQueryVersion (ClientPtr client)
+     rep.majorVersion = SERVER_RANDR_MAJOR;
+     rep.minorVersion = SERVER_RANDR_MINOR;
+     if (client->swapped) {
++	/*
++	 * We return BadImplementation for swapped clients on 1.2 requests,
++	 * let's not do that
++	 */
++	rep.minorVersion = 1;
+     	swaps(&rep.sequenceNumber, n);
+     	swapl(&rep.length, n);
+ 	swapl(&rep.majorVersion, n);
+-- 
+1.5.6.3
+
--- xorg-server-1.4.2.orig/debian/patches/15_X86EMU-added-blacklist-for-I-O-port-in-0-0xFF-range.patch
+++ xorg-server-1.4.2/debian/patches/15_X86EMU-added-blacklist-for-I-O-port-in-0-0xFF-range.patch
@@ -0,0 +1,190 @@
+From 6061612987ebba7ca65835e658b8d969be13a22d Mon Sep 17 00:00:00 2001
+From: Bart Trojanowski <bart@symbio-technologies.com>
+Date: Fri, 11 Jan 2008 11:52:59 -0500
+Subject: [PATCH] X86EMU: added blacklist for I/O port in 0-0xFF range
+
+Signed-off-by: Bart Trojanowski <bart@jukie.net>
+
+Work funded by: Symbio Technologies
+
+There seems to be an inconsistency between what the x86emu gets from the
+PCI handling code and by accessing hardware directly.  x86emu relies on
+a set of functions to emulate PCI access.  When things goes wrong, the
+emulator is asked to execute an OUT instruction on port 0x20.
+
+I've put together a patch against xserver-xorg package that prevents
+accesses to BAD registers.  This turns a freeze into a segfault in X.
+
+http://www.jukie.net/~bart/patches/xorg-server/20080111/0001-X86EMU-
+added-blacklist-for-I-O-port-in-0-0xFF-range.patch
+
+It does not address the DDC not working, I hope that after fixing the
+bugs in x86emu, things may improve.
+
+Anyway, I am continuing to investigate the real cause of the PCI access
+issue.  To find out more read this thread:
+
+http://lists.freedesktop.org/archives/xorg/2008-January/031811.html
+
+-Bart
+
+
+diff -Nurp xorg-server-1.4.1~git20080118/hw/xfree86/int10/helper_exec.c xorg-server-1.4.1~git20080118-working/hw/xfree86/int10/helper_exec.c
+--- xorg-server-1.4.1~git20080118/hw/xfree86/int10/helper_exec.c	2008-01-18 13:23:40.000000000 -0800
++++ xorg-server-1.4.1~git20080118-working/hw/xfree86/int10/helper_exec.c	2008-01-22 09:53:27.000000000 -0800
+@@ -21,6 +21,8 @@
+ #define PRINT_PORT 0
+ 
+ #include <unistd.h>
++#include <sys/types.h>
++#include <signal.h>
+ 
+ #include <X11/Xos.h>
+ #include "xf86.h"
+@@ -210,6 +212,72 @@ stack_trace(xf86Int10InfoPtr pInt)
+ 	xf86ErrorFVerb(3, "\n");
+ }
+ 
++enum port_action_e {
++	PORT_ACTION_PERMIT,
++	PORT_ACTION_WARN,
++	PORT_ACTION_BAIL,
++	PORT_ACTION_MAX
++};
++
++static const struct port_range {
++	CARD16 start, end;
++	enum port_action_e access;
++} port_range_table[] = {
++	// NOTE: port ranges are non overlapping and sorted
++	{ 0x00, 0x1f, PORT_ACTION_BAIL },	// DMA
++	{ 0x20, 0x21, PORT_ACTION_BAIL },	// PIC
++	{ 0x40, 0x47, PORT_ACTION_BAIL },	// PIT 1&2
++	{ 0x50, 0x53, PORT_ACTION_BAIL },
++	{ 0x70, 0x77, PORT_ACTION_BAIL },	// CMOS/RTC
++	{ 0x81, 0x8f, PORT_ACTION_BAIL },	// DIAG REGS
++	{ 0xa0, 0xa1, PORT_ACTION_BAIL },	// PIC2
++	{ 0xc0, 0xdf, PORT_ACTION_BAIL },	// DMA
++};
++#define ARRAY_SIZE(X) (sizeof((X)) / (sizeof(*(X))))
++#define ARRAY_END(X)  (&((X)[ARRAY_SIZE(X)]))
++
++static void assert_port_access_allowed (CARD16 port, CARD16 width)
++{
++	CARD16 access_start, access_end;
++	const struct port_range *pr, *pr_start, *pr_end;
++
++	access_start = port;
++	access_end = port + width - 1;
++
++	// TODO: if the list gets too long we should do a binary search
++	//        or convert the port list to a bitmap representation
++	pr_start = port_range_table;
++	pr_end   = ARRAY_END(port_range_table);
++
++	for (pr = pr_start; pr < pr_end; pr++) {
++		if (access_end < pr->start)
++			continue;
++		if (access_start > pr->end)
++			break;
++
++		// we are in the pr range now
++		switch (pr->access) {
++		default:
++			continue;
++		case PORT_ACTION_BAIL:
++		case PORT_ACTION_WARN:
++			break;
++		}
++
++		ErrorF("Emulator asked to make a suspect %saccess to "
++				"port %u (0x%04x)%s\n",
++				(width == 1) ? "byte " :
++				(width == 2) ? "word " :
++				(width == 4) ? "long " : "",
++				port, port,
++				(pr->access == PORT_ACTION_BAIL)
++				? "; terminating." : "ignoring.");
++
++		if (pr->access == PORT_ACTION_BAIL)
++			kill(getpid(), SIGSEGV);
++	}
++}
++
+ int
+ port_rep_inb(xf86Int10InfoPtr pInt,
+ 	     CARD16 port, CARD32 base, int d_f, CARD32 count)
+@@ -319,7 +387,7 @@ x_inb(CARD16 port)
+ 	    ErrorF(" inb(%#x) = %2.2x\n", port, val);
+ #ifdef __NOT_YET__
+     } else if (port < 0x0100) {		/* Don't interfere with mainboard */
+-	val = 0;
++        val = 0;
+ 	xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2,
+ 	    "inb 0x%4.4x\n", port);
+ 	if (xf86GetVerbosity() > 3) {
+@@ -327,10 +395,14 @@ x_inb(CARD16 port)
+ 	    stack_trace(Int10Current);
+ 	}
+ #endif /* __NOT_YET__ */
+-    } else if (!pciCfg1inb(port, &val)) {
+-	val = inb(Int10Current->ioBase + port);
+-	if (PRINT_PORT && DEBUG_IO_TRACE())
+-	    ErrorF(" inb(%#x) = %2.2x\n", port, val);
++    } else {
++	assert_port_access_allowed (port, sizeof(val));
++
++        if (!pciCfg1inb(port, &val)) {
++            val = inb(Int10Current->ioBase + port);
++            if (PRINT_PORT && DEBUG_IO_TRACE())
++                ErrorF(" inb(%#x) = %2.2x\n", port, val);
++        }
+     }
+     return val;
+ }
+@@ -349,10 +421,14 @@ x_inw(CARD16 port)
+ 	 */
+ 	X_GETTIMEOFDAY(&tv);
+ 	val = (CARD16)(tv.tv_usec / 3);
+-    } else if (!pciCfg1inw(port, &val)) {
+-	val = inw(Int10Current->ioBase + port);
+-	if (PRINT_PORT && DEBUG_IO_TRACE())
+-	    ErrorF(" inw(%#x) = %4.4x\n", port, val);
++    } else {
++	assert_port_access_allowed (port, sizeof(val));
++
++        if (!pciCfg1inw(port, &val)) {
++            val = inw(Int10Current->ioBase + port);
++            if (PRINT_PORT && DEBUG_IO_TRACE())
++                ErrorF(" inw(%#x) = %4.4x\n", port, val);
++        }
+     }
+     return val;
+ }
+@@ -384,6 +460,8 @@ x_outb(CARD16 port, CARD8 val)
+     } else if (!pciCfg1outb(port, val)) {
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" outb(%#x, %2.2x)\n", port, val);
++
++	assert_port_access_allowed (port, sizeof(val));
+ 	outb(Int10Current->ioBase + port, val);
+     }
+ }
+@@ -404,6 +482,8 @@ x_inl(CARD16 port)
+ {
+     CARD32 val;
+ 
++    assert_port_access_allowed (port, sizeof(val));
++
+     if (!pciCfg1in(port, &val)) {
+ 	val = inl(Int10Current->ioBase + port);
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+@@ -418,6 +498,8 @@ x_outl(CARD16 port, CARD32 val)
+     if (!pciCfg1out(port, val)) {
+ 	if (PRINT_PORT && DEBUG_IO_TRACE())
+ 	    ErrorF(" outl(%#x, %8.8x)\n", port, val);
++
++	assert_port_access_allowed (port, sizeof(val));
+ 	outl(Int10Current->ioBase + port, val);
+     }
+ }
--- xorg-server-1.4.2.orig/debian/patches/18_glx_initialize_getvisualconfigs_buf.diff
+++ xorg-server-1.4.2/debian/patches/18_glx_initialize_getvisualconfigs_buf.diff
@@ -0,0 +1,23 @@
+From: Guillaume Melquiond <guillaume.melquiond@gmail.com>
+Subject: GLX: initialize the buffer in GetVisualConfigs
+
+Backport from edad0a9dfebcce5c54b2f9c32bd9d45549e20c51.
+
+http://bugs.freedesktop.org/show_bug.cgi?id=13358
+http://bugs.freedesktop.org/show_bug.cgi?id=13863
+
+Index: xorg-server/GL/glx/glxcmds.c
+===================================================================
+--- xorg-server.orig/GL/glx/glxcmds.c
++++ xorg-server/GL/glx/glxcmds.c
+@@ -992,6 +992,10 @@
+ 	buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
+ 	buf[p++] = modes->transparentIndex;
+ 
++	while (p < __GLX_TOTAL_CONFIG) {
++		buf[p++] = 0;
++	}
++
+ 	if ( do_swap ) {
+ 	    __GLX_SWAP_INT_ARRAY(buf, __GLX_TOTAL_CONFIG);
+ 	}
--- xorg-server-1.4.2.orig/debian/patches/52_xevie-swap-replies.diff
+++ xorg-server-1.4.2/debian/patches/52_xevie-swap-replies.diff
@@ -0,0 +1,110 @@
+From b5cdcfa55c399e83d51242e93d4f25d8bc4fec1f Mon Sep 17 00:00:00 2001
+From: Julien Cristau <jcristau@debian.org>
+Date: Mon, 1 Sep 2008 19:45:30 +0200
+Subject: [PATCH] Xevie: swap replies as necessary
+
+---
+ Xext/xevie.c |   27 +++++++++++++++++++++++++++
+ 1 files changed, 27 insertions(+), 0 deletions(-)
+
+Index: xorg-server/Xext/xevie.c
+===================================================================
+--- xorg-server.orig/Xext/xevie.c
++++ xorg-server/Xext/xevie.c
+@@ -167,6 +167,7 @@
+ int ProcQueryVersion (register ClientPtr client)
+ {
+     xXevieQueryVersionReply rep;
++    int n;
+ 
+     REQUEST_SIZE_MATCH (xXevieQueryVersionReq);
+     rep.type = X_Reply;
+@@ -174,6 +175,12 @@
+     rep.sequence_number = client->sequence;
+     rep.server_major_version = XEVIE_MAJOR_VERSION;
+     rep.server_minor_version = XEVIE_MINOR_VERSION;
++    if (client->swapped) {
++	swaps(&rep.sequence_number, n);
++	swapl(&rep.length, n);
++	swaps(&rep.server_major_version, n);
++	swaps(&rep.server_minor_version, n);
++    }
+     WriteToClient (client, sizeof (xXevieQueryVersionReply), (char *)&rep);
+     return client->noClientException;
+ }
+@@ -182,6 +189,7 @@
+ int ProcStart (register ClientPtr client)
+ {
+     xXevieStartReply rep;
++    int n;
+ 
+     REQUEST_SIZE_MATCH (xXevieStartReq);
+     rep.pad1 = 0;
+@@ -216,6 +224,10 @@
+     rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
++    if (client->swapped) {
++	swaps(&rep.sequence_number, n);
++	swapl(&rep.length, n);
++    }
+     WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep);
+     return client->noClientException;
+ }
+@@ -224,6 +236,7 @@
+ int ProcEnd (register ClientPtr client)
+ {
+     xXevieEndReply rep;
++    int n;
+ 
+     if (xevieFlag) {
+         if (client->index != xevieClientIndex)
+@@ -236,6 +249,10 @@
+     rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
++    if (client->swapped) {
++	swaps(&rep.sequence_number, n);
++	swapl(&rep.length, n);
++    }
+     WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep);
+     return client->noClientException;
+ }
+@@ -247,6 +264,7 @@
+     xXevieSendReply rep;
+     xEvent *xE;
+     static unsigned char lastDetail = 0, lastType = 0;
++    int n;
+ 
+     if (client->index != xevieClientIndex)
+         return BadAccess;
+@@ -255,6 +273,10 @@
+     rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
++    if (client->swapped) {
++	swaps(&rep.sequence_number, n);
++	swapl(&rep.length, n);
++    }
+     WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep);
+ 
+     switch(xE->u.u.type) {
+@@ -292,6 +314,7 @@
+ {
+     REQUEST (xXevieSelectInputReq);
+     xXevieSelectInputReply rep;
++    int n;
+ 
+     if (client->index != xevieClientIndex)
+         return BadAccess;
+@@ -300,6 +323,10 @@
+     rep.length = 0;
+     rep.type = X_Reply;
+     rep.sequence_number = client->sequence;
++    if (client->swapped) {
++	swaps(&rep.sequence_number, n);
++	swapl(&rep.length, n);
++    }
+     WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep);
+     return client->noClientException;
+ }
--- xorg-server-1.4.2.orig/debian/local/xvfb-run
+++ xorg-server-1.4.2/debian/local/xvfb-run
@@ -0,0 +1,184 @@
+#!/bin/sh
+
+# $Id: xvfb-run 2027 2004-11-16 14:54:16Z branden $
+
+# This script starts an instance of Xvfb, the "fake" X server, runs a command
+# with that server available, and kills the X server when done.  The return
+# value of the command becomes the return value of this script.
+#
+# If anyone is using this to build a Debian package, make sure the package
+# Build-Depends on xvfb, xbase-clients, and xfonts-base.
+
+set -e
+
+PROGNAME=xvfb-run
+SERVERNUM=99
+AUTHFILE=
+ERRORFILE=/dev/null
+STARTWAIT=3
+XVFBARGS="-screen 0 640x480x8"
+LISTENTCP="-nolisten tcp"
+XAUTHPROTO=.
+
+# Query the terminal to establish a default number of columns to use for
+# displaying messages to the user.  This is used only as a fallback in the event
+# the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while the
+# script is running, and this cannot, only being calculated once.)
+DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true
+if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then
+    DEFCOLUMNS=80
+fi
+
+# Display a message, wrapping lines at the terminal width.
+message () {
+    echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS}
+}
+
+# Display an error message.
+error () {
+    message "error: $*" >&2
+}
+
+# Display a usage message.
+usage () {
+    if [ -n "$*" ]; then
+        message "usage error: $*"
+    fi
+    cat <<EOF
+Usage: $PROGNAME [OPTION ...] COMMAND
+Run COMMAND (usually an X client) in a virtual X server environment.
+Options:
+-a        --auto-servernum          try to get a free server number, starting at
+                                    --server-num
+-e FILE   --error-file=FILE         file used to store xauth errors and Xvfb
+                                    output (default: $ERRORFILE)
+-f FILE   --auth-file=FILE          file used to store auth cookie
+                                    (default: ./.Xauthority)
+-h        --help                    display this usage message and exit
+-n NUM    --server-num=NUM          server number to use (default: $SERVERNUM)
+-l        --listen-tcp              enable TCP port listening in the X server
+-p PROTO  --xauth-protocol=PROTO    X authority protocol name to use
+                                    (default: xauth command's default)
+-s ARGS   --server-args=ARGS        arguments (other than server number and
+                                    "-nolisten tcp") to pass to the Xvfb server
+                                    (default: "$XVFBARGS")
+-w DELAY  --wait=DELAY              delay in seconds to wait for Xvfb to start
+                                    before running COMMAND (default: $STARTWAIT)
+EOF
+}
+
+# Find a free server number by looking at .X*-lock files in /tmp.
+find_free_servernum() {
+    # Sadly, the "local" keyword is not POSIX.  Leave the next line commented in
+    # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
+    # anyway.
+    #local i
+
+    i=$SERVERNUM
+    while [ -f /tmp/.X$i-lock ]; do
+        i=$(($i + 1))
+    done
+    echo $i
+}
+
+# Clean up files
+clean_up() {
+    if [ -e "$AUTHFILE" ]; then
+        XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1
+    fi
+    if [ -n "$XVFB_RUN_TMPDIR" ]; then
+        if ! rm -r "$XVFB_RUN_TMPDIR"; then
+            error "problem while cleaning up temporary directory"
+            exit 5
+        fi
+    fi
+}
+
+# Parse the command line.
+ARGS=$(getopt --options +ae:f:hn:lp:s:w: \
+       --long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth-protocol:,server-args:,wait: \
+       --name "$PROGNAME" -- "$@")
+GETOPT_STATUS=$?
+
+if [ $GETOPT_STATUS -ne 0 ]; then
+    error "internal error; getopt exited with status $GETOPT_STATUS"
+    exit 6
+fi
+
+eval set -- "$ARGS"
+
+while :; do
+    case "$1" in
+        -a|--auto-servernum) SERVERNUM=$(find_free_servernum) ;;
+        -e|--error-file) ERRORFILE="$2"; shift ;;
+        -f|--auth-file) AUTHFILE="$2"; shift ;;
+        -h|--help) SHOWHELP="yes" ;;
+        -n|--server-num) SERVERNUM="$2"; shift ;;
+        -l|--listen-tcp) LISTENTCP="" ;;
+        -p|--xauth-protocol) XAUTHPROTO="$2"; shift ;;
+        -s|--server-args) XVFBARGS="$2"; shift ;;
+        -w|--wait) STARTWAIT="$2"; shift ;;
+        --) shift; break ;;
+        *) error "internal error; getopt permitted \"$1\" unexpectedly"
+           exit 6
+           ;;
+    esac
+    shift
+done
+
+if [ "$SHOWHELP" ]; then
+    usage
+    exit 0
+fi
+
+if [ -z "$*" ]; then
+    usage "need a command to run" >&2
+    exit 2
+fi
+
+if ! which xauth >/dev/null; then
+    error "xauth command not found"
+    exit 3
+fi
+
+# tidy up after ourselves
+trap clean_up EXIT
+
+# If the user did not specify an X authorization file to use, set up a temporary
+# directory to house one.
+if [ -z "$AUTHFILE" ]; then
+    XVFB_RUN_TMPDIR="${TMPDIR:-/tmp}/$PROGNAME.$$"
+    if ! mkdir -p -m 700 "$XVFB_RUN_TMPDIR"; then
+        error "temporary directory $XVFB_RUN_TMPDIR already exists"
+        exit 4
+    fi
+    AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority")
+fi
+
+# Start Xvfb.
+MCOOKIE=$(mcookie)
+XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1
+add :$SERVERNUM $XAUTHPROTO $MCOOKIE
+EOF
+XAUTHORITY=$AUTHFILE Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP >>"$ERRORFILE" \
+  2>&1 &
+XVFBPID=$!
+sleep "$STARTWAIT"
+if ! kill -0 $XVFBPID 2>/dev/null; then
+  echo "Xvfb failed to start" >&2
+  exit 1
+fi
+
+# Start the command and save its exit status.
+set +e
+DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@" 2>&1
+RETVAL=$?
+set -e
+
+# Kill Xvfb now that the command has exited.
+kill $XVFBPID
+
+# Return the executed command's exit status.
+exit $RETVAL
+
+# vim:set ai et sts=4 sw=4 tw=80:
--- xorg-server-1.4.2.orig/debian/local/xvfb-run.1
+++ xorg-server-1.4.2/debian/local/xvfb-run.1
@@ -0,0 +1,282 @@
+.\" $Id: xvfb-run.1 2138 2005-01-17 23:40:27Z branden $
+.\"
+.\" Copyright 1998-2004 Branden Robinson <branden@debian.org>.
+.\"
+.\" This is free software; you may redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2,
+.\" or (at your option) any later version.
+.\"
+.\" This is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License with
+.\" the Debian operating system, in /usr/share/common-licenses/GPL;  if
+.\" not, write to the Free Software Foundation, Inc., 59 Temple Place,
+.\" Suite 330, Boston, MA 02111-1307 USA
+.\"
+.\" We need the URL macro from groff's www macro package, but also want
+.\" things to work all right for people who don't have it.  So we define
+.\" our own URL macro and let the www macro package override it if it's
+.\" available.
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.TH xvfb\-run 1 "2004\-11\-12" "Debian Project"
+.SH NAME
+xvfb\-run \- run specified X client or command in a virtual X server environment
+.SH SYNOPSIS
+.B xvfb\-run
+[
+.I options
+]
+.I command
+.SH DESCRIPTION
+.B xvfb\-run
+is a wrapper for the
+.BR Xvfb (1x)
+command which simplifies the task of running commands (typically an X
+client, or a script containing a list of clients to be run) within a virtual
+X server environment.
+.PP
+.B xvfb\-run
+sets up an X authority file (or uses an existing user\-specified one),
+writes a cookie to it (see
+.BR xauth (1x))
+and then starts the
+.B Xvfb
+X server as a background process.
+The process ID of
+.B Xvfb
+is stored for later use.
+The specified
+.I command
+is then run using the X display corresponding to the
+.B Xvfb
+server
+just started and the X authority file created earlier.
+.PP
+When the
+.I command
+exits, its status is saved, the
+.B Xvfb
+server is killed (using the process ID stored earlier), the X authority
+cookie removed, and the authority file deleted (if the user did not specify
+one to use).
+.B xvfb\-run
+then exits with the exit status of
+.IR command .
+.PP
+.B xvfb\-run
+requires the
+.B xauth
+command to function.
+.SH OPTIONS
+.TP
+.B \-a\fR,\fB \-\-auto\-servernum
+Try to get a free server number, starting at 99, or the argument to
+.BR \-\-server\-num .
+.TP
+.BI \-e\  file \fR,\fB\ \-\-error\-file= file
+Store output from
+.B xauth
+and
+.B Xvfb
+in
+.IR file .
+The default is
+.IR /dev/null .
+.TP
+.BI \-f\  file \fR,\fB\ \-\-auth\-file= file
+Store X authentication data in
+.IR file .
+By default, a temporary directory called
+.IR xvfb\-run. PID
+(where PID is the process ID of
+.B xvfb\-run
+itself) is created in the directory specified by the environment variable
+.B TMPDIR
+(or
+.I /tmp
+if that variable is null or unset), and the
+.BR tempfile (1)
+command is used to create a file in that temporary directory called
+.IR Xauthority .
+.TP
+.B \-h\fR,\fB \-\-help
+Display a usage message and exit.
+.TP
+.BI \-n\  servernumber \fR,\fB\ \-\-server\-num= servernumber
+Use
+.I servernumber
+as the server number (but see the
+.B \-a\fR,\fB \-\-auto\-servernum
+option above).
+The default is 99.
+.TP
+.B \-l\fR,\fB \-\-listen\-tcp
+Enable TCP port listening in the X server.
+For security reasons (to avoid denial\-of\-service attacks or exploits),
+TCP port listening is disabled by default.
+.TP
+.BI \-p\  protocolname \fR,\fB\ \-\-xauth\-protocol= protocolname
+Use
+.I protocolname
+as the X authority protocol to use.
+The default is \(oq.\(cq, which
+.B xauth
+interprets as its own default protocol, which is MIT\-MAGIC\-COOKIE\-1.
+.TP
+.BI \-s\  arguments \fR,\fB\ \-\-server\-args= arguments
+Pass
+.I arguments
+to the
+.B Xvfb
+server.
+Be careful to quote any whitespace characters that may occur within
+.I arguments
+to prevent them from regarded as separators for
+.BR xvfb\-run 's
+own arguments.
+Also, note that specification of \(oq\-nolisten tcp\(cq in
+.I arguments
+may override the function of
+.BR xvfb\-run 's
+own
+.B \-l\fR,\fB \-\-listen\-tcp
+option, and that specification of the server number (e.g., \(oq:1\(cq) may
+be ignored because of the way the X server parses its argument list.
+Use the
+.B xvfb\-run
+option
+.BI \-n\  servernumber \fR,\fB\ \-\-server\-num= servernumber
+to achieve the latter function.
+The default is \(oq\-screen 0 640x480x8\(cq.
+.TP
+.BI \-w\  delay \fR,\fB\ \-\-wait= delay
+Wait
+.I delay
+seconds after launching
+.B Xvfb
+before attempting to start the specified command.
+The default is 3.
+.SH ENVIRONMENT
+.TP
+.B COLUMNS
+indicates the width of the terminal device in character cells.
+This value is used for formatting diagnostic messages.
+If not set, the terminal is queried using
+.BR stty (1)
+to determine its width.
+If that fails, a value of \(oq80\(cq is assumed.
+.TP
+.B TMPDIR
+specifies the directory in which to place
+.BR xvfb\-run 's
+temporary directory for storage of the X authority file; only used if the
+.B \-f
+or
+.B \-\-auth\-file
+options are not specified.
+.SH "OUTPUT FILES"
+.PP
+Unless the
+.B \-f
+or
+.B \-\-auth\-file
+options are specified, a temporary
+directory and file within it are created (and deleted) to store the X
+authority cookies used by the
+.B Xvfb
+server and client(s) run under it.
+See
+.BR tempfile (1).
+If \-f or \-\-auth\-file are used, then the specified X authority file is
+only written to, not created or deleted (though
+.B xauth
+creates an authority file itself if told to use use that does not already
+exist).
+.PP
+An error file with a user\-specified name is also created if the
+.B \-e
+or
+.B \-\-error\-file
+options are specifed; see above.
+.SH "EXIT STATUS"
+.B xvfb\-run
+uses its exit status as well as output to standard error to communicate
+diagnostics.
+The exit status of \(oq1\(cq is not used, and should be interpreted as failure
+of the specified command.
+.TP
+0
+.B xvfb\-run
+only uses this exit status if the
+.B \-h\fR,\fB \-\-help
+option is given.
+In all other situations, this may be interpreted as success of the specified
+command.
+.TP
+2
+No command to run was specified.
+.TP
+3
+The
+.B xauth
+command is not available.
+.TP
+4
+The temporary directory that was going to be used already exists; since
+.B xvfb\-run
+produces a uniquely named directory, this may indicate an attempt by another
+process on the system to exploit a temporary file race condition.
+.TP
+5
+A problem was encountered while cleaning up the temporary directory.
+.TP
+6
+A problem was encountered while using
+.BR getopt (1)
+to parse the command\-line arguments.
+.SH EXAMPLES
+.TP
+.B xvfb\-run \-\-auto\-servernum \-\-server\-num=1 xlogo
+runs the
+.BR xlogo (1x)
+demonstration client inside the
+.B Xvfb
+X server on the first available server number greater than or equal to 1.
+.TP
+.B xvfb\-run \-\-server\-args="\-screen 0 1024x768x24" ico \-faces
+runs the
+.BR ico (1x)
+demonstration client (and passes it the
+.B \-faces
+argument) inside the
+.B Xvfb
+X server, configured with a root window of 1024 by 768 pixels and a color
+depth of 24 bits.
+.PP
+Note that the demo X clients used in the above examples will not exit on
+their own, so they will have to be killed before
+.B xvfb\-run
+will exit.
+.SH BUGS
+See
+.URL "http://bugs.debian.org/xvfb" "the Debian Bug Tracking System" .
+If you wish to report a bug in
+.BR xvfb\-run ,
+please use the 
+.BR reportbug (1)
+command.
+.SH AUTHOR
+.B xfvb\-run
+was written by Branden Robinson and Jeff Licquia with sponsorship from
+Progeny Linux Systems.
+.SH "SEE ALSO"
+.BR Xvfb (1x),
+.BR xauth (1x)
+.\" vim:set et tw=80:
