#!/usr/bin/perl -w

#  gdkxft - Provide Xft font support in gdk
#  Copyright (C) 2001 Josh Parsons
#  
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Library General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#  
#  This library 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
#  Library General Public License for more details.
#  
#  You should have received a copy of the GNU Library General Public
#  License along with this library; if not, write to the
#  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#  Boston, MA 02111-1307, USA.


# PROBLEMS
#
#   - No "rollback" done if an error occurs part-way through something.
#
#   - The places searched for XF86Config-4 does not match the places searched
#     by XFree86.  (See XF86Config(5).)
#
#   - Uses a fixed search path for xftcache, and ignores $PATH.
#
#   - No testing for strange characters in filenames, which means it may
#     write malformed files: e.g. fsconfig font paths containing `"' or
#     other [^a-zA-Z0-9_.+-] characters that may be treated strangely
#     by whatever programs read the files we write.
#
#   - The XftConfig file written should use information in the existing
#     XftConfig file (perhaps even simply adding an `include' or `includif'
#     directive) rather than simply supplying a replacement that discards user
#     changes in existing XftConfig file or may in some other way be
#     inappropriate to the site.
#
#     There are benefits in using `include'/`includeif' even when initially
#     using the whole-replacement method: if the user re-runs
#     gdkxfg_sysinstall -f (or whatever flag) to update for changes in font
#     paths (i.e. the information gdkxft_sysinstall needs to create its
#     XftConfig stuff), then we could rewrite just the sourced file and leave
#     the existing XftConfig file intact (including leaving any subsequent
#     hand edits).
#
#   - I (pjm) am inclined to think that (un)install_theme and
#     (un)install_xinitrc should be handled by the standard (un)install
#     targets in the makefile.
#
#     Advantages:
#
#       + Package managers will know about the files.
#
#       + Simplify this script.  Running random perl scripts as root makes
#         people nervous; they may wish to read the script.
#
#       + Easier for users to get the right thing happening if they have unusual
#         setups.
#
#       + Easier to edit the files that are to be installed.
#
#     Disadvantages:
#
#       + Development work (changing Makefile.am's, probably changing configure.in
#         to work out the right directories).
#
#       (No other disadvantages that I can think of.)

# Given that this script is to be run by the root user, and writes over config
# files, it's important to be safety conscious and use `-w' and `use strict'.
use strict;

# Select what messages are written.  Currently only tested for >= 0, to
# specify whether "normal operation" messages are shown.
# Perhaps should search for `#print', enabling them for $verbosity >= 1,
# and adding a `--verbose' option.
my $verbosity = 0;

# Unordered set of fonts.  Only the keys are meaningful; we use a hash only to
# remove duplicates.
my %fontdirs;

# Absolute file name of the XF86Config[-4] file being used.
my $xf86config;

# Mapping from filename to ftfamily as specified by Xftcache file.
# Filled in readxftcache, used in readfontdir.
# (Should probably be returned by readxftcache and passed to readfontdir
# rather than being a global var.)
my %file2ftfamily;

# Mapping from X family to ftfamily.
my %x2ft;

sub addfontdir ($) {
    my $dir = shift ||return;
    return unless(-r "$dir/fonts.dir");

    #print "[$dir]\n";
    $fontdirs{$dir}=1;
}

# parse the fonts out of XF86Config
sub read_xf86config ($) {
    my $filename = shift ||die;
    open(IN,$filename) ||return 0;

    print STDERR "Reading $filename\n" if($verbosity >= 0);
    $xf86config=$filename;

    # This parsing is somewhat brittle, but unfortunately the XF86Config man
    # page is somewhat vague (e.g. not even mentioning comments, and not
    # really specifying whitespace requirements).  We currently leave $/ as
    # its default newline, meaning that we assume that no fontpath directive
    # is split over more than one line, and that no line contains more than
    # one fontpath directive.
    #
    # Another potential problem is that we accept fontpath directives anywhere
    # in XF86Config, not just ones appearing in the Files section.
    while(<IN>) {
	chomp;
	s/#.*$//;
	if(/^\s*_*F_*o_*n_*t_*P_*a_*t_*h_*\s+\"([^\"]*)\"/i) {
	    my @fdirs = split(/,/, $1, );
	    foreach my $i (@fdirs) {
		addfontdir($i);
	    }
	}
    }

    close(IN);
    return 1;
}

# parse the fonts out of xfs's config
sub read_fsconfig ($) {
    my $filename = shift ||die;
    open(IN,$filename) ||return 0;

    print STDERR "Reading $filename\n" if($verbosity >= 0);
    #$fsconfig=$filename;

    while(<IN>) {
	my $comma;
	chomp;
	if(s/\s*catalogue\s*=//i) {
	    do {
		chomp;
		addfontdir($1) if(/\s*([^,\s]+)\s*([,]?)/);
		$comma=$2;
	    } while($comma && ($_ = <IN>));
	}
    }

    close(IN);
    return 1;
}

# case-insensitive eq operator
sub caseeq ($$) {
    my ($s1,$s2) = @_;
    return $s1 =~ /^\Q$s2\E$/i;
}

# read the fonts.dir file from a font directory
sub readfontdir ($) {
    my $dir = shift ||die;
    open(FDIR,"$dir/fonts.dir") || die "Couldn't open $dir/fonts.dir: $!; stopped";
 
   while(<FDIR>) {
	chomp;
	my ($file,$xname) = split(/[ \t]+/,$_,2);
	next unless ($xname);
	my ($dummy,$vendor,$family,$rest) = split(/-/,$xname,4);
	next unless ($family && $file);

	my $ftfamily = $file2ftfamily{$file};
	next unless $ftfamily;
	next if caseeq($ftfamily,$family);

	#print "[$family] -> [$file] -> [$ftfamily]\n";
	$x2ft{$family}=$ftfamily;
	
    };

    close(FDIR);
    return 1;
}

# read xftcache-generated XftCache file from a font directory
sub readxftcache ($) {
    my $dir = shift ||die;
    open(XFTC,"$dir/XftCache") ||die "Couldn't open $dir/XftCache: $!; stopped";

    while(<XFTC>) {
	chomp;
	my ($file,$dummy,$info) = split(/[ \t]+/,$_,3);
	$file =~ s/\"//g;
	$info =~ s/\"//g;
	my ($family,$rest) = split(/:/,$info,2);
	next unless ($family && $file);

#	print "[$file] [$family]\n";
	$file2ftfamily{$file} = $family;
    };

    close(XFTC);
    return 1;
}

sub read_xconfigs () {
    # look for XF86Config
    read_xf86config("/etc/X11/XF86Config-4") || 
	read_xf86config("/etc/XF86Config-4") ||
	    read_xf86config("/usr/local/X11R6/lib/X11/XF86Config-4") ||
		read_xf86config("/usr/local/lib/X11/XF86Config-4") ||
		    read_xf86config("/usr/X11R6/lib/X11/XF86Config-4") ||
			read_xf86config("/usr/lib/X11/XF86Config-4") ||
    read_xf86config("/etc/X11/XF86Config") || 
	read_xf86config("/etc/XF86Config") ||
	    read_xf86config("/usr/local/X11R6/lib/X11/XF86Config") ||
		read_xf86config("/usr/local/lib/X11/XF86Config") ||
		    read_xf86config("/usr/X11R6/lib/X11/XF86Config") ||
			read_xf86config("/usr/lib/X11/XF86Config");

    # look for xfs config
    read_fsconfig("/etc/X11/fs/config") ||
	read_fsconfig("/usr/local/X11R6/lib/X11/fs/config") ||
	    read_fsconfig("/usr/local/lib/X11/fs/config") ||
		read_fsconfig("/usr/X11R6/lib/X11/fs/config") ||
		    read_fsconfig("/usr/lib/X11/fs/config");
}

# look for xftcache
sub find_xftcache ($) {
    my $xftcachefilename="xftcache";
    my $dir = shift ||die;
    #print STDERR "find_xftcache('$dir')\n";
    return "$dir/$xftcachefilename" if (-x "$dir/$xftcachefilename");
    return undef;
}

# stupidly install an xftconfig if we can't be smart about it
sub install_xftconfig_dumb ($) {
    my $outfile=shift ||die;

    # save old XftConfig
    my $save="$outfile.gdkxftsaved";
    rename($outfile, $save) if(-r $outfile && ! -r $save);

    # produce output
    print STDERR "Building $outfile (stupidly)\n" if($verbosity >= 0);
    open(OUT,">$outfile") || die "Cannot write to $outfile: $!; stopped";

    print OUT <<XFTCONFIG;
# This file was automatically generated by gdkxft.
# For some reason, I was unable to generate a customised XftConfig
# for your system, so I have used a copy of my XftConfig.  This might
# not work for you: edit it.

includeif	"~/.xftconfig"

match any family == "fixed"		edit family =+ "LuciduxMono";
match any family == "serif"		edit family += "LuciduxSerif";
match any family == "sans"		edit family += "LuciduxSans";
match any family == "mono"		edit family += "LuciduxMono";

dir "/usr/lib/X11/fonts/Type1"

dir "/usr/share/fonts/default/TrueType"
dir "/usr/X11R6/lib/X11/fonts/Speedo"
dir "/usr/share/AbiSuite/fonts"
dir "/usr/share/fonts/ja/TrueType"
dir "/usr/X11R6/lib/X11/fonts/misc"
dir "/usr/X11R6/lib/X11/fonts/75dpi"
dir "/usr/X11R6/lib/X11/fonts/100dpi"
dir "/usr/share/fonts/default/Type1"
dir "/usr/share/abisource/fonts"

match any family == "Standard Symbols" edit family += "Standard Symbols L";
match any family == "Standard Symbols L" edit family =+ "Standard Symbols";
match any family == "Century Schoolbook" edit family += "Century Schoolbook L";
match any family == "Century Schoolbook L" edit family =+ "Century Schoolbook";
match any family == "charter" edit family += "Bitstream Charter";
match any family == "Bitstream Charter" edit family =+ "charter";
match any family == "Palatino" edit family += "URW Palladio L";
match any family == "URW Palladio L" edit family =+ "Palatino";
match any family == "Zapf Chancery" edit family += "URW Chancery L";
match any family == "URW Chancery L" edit family =+ "Zapf Chancery";
match any family == "Goth" edit family += "URW Gothic L";
match any family == "URW Gothic L" edit family =+ "Goth";
match any family == "Arial" edit family += "Nimbus Sans L";
match any family == "Nimbus Sans L" edit family =+ "Arial";
match any family == "Symbol" edit family += "Standard Symbols L";
match any family == "Standard Symbols L" edit family =+ "Symbol";
match any family == "Courier New" edit family += "Nimbus Mono L";
match any family == "Nimbus Mono L" edit family =+ "Courier New";
match any family == "Bookman L" edit family += "URW Bookman L";
match any family == "URW Bookman L" edit family =+ "Bookman L";
match any family == "Nimbus Mono" edit family += "Nimbus Mono L";
match any family == "Nimbus Mono L" edit family =+ "Nimbus Mono";
match any family == "Zapf Dingbats" edit family += "Dingbats";
match any family == "Dingbats" edit family =+ "Zapf Dingbats";
match any family == "Bookman" edit family += "URW Bookman L";
match any family == "URW Bookman L" edit family =+ "Bookman";
match any family == "Courier" edit family += "Nimbus Mono L";
match any family == "Nimbus Mono L" edit family =+ "Courier";
match any family == "lucidux sans" edit family += "LuciduxSans";
match any family == "LuciduxSans" edit family =+ "lucidux sans";
match any family == "courier" edit family += "Courier 10 Pitch";
match any family == "Courier 10 Pitch" edit family =+ "courier";
match any family == "Helvetica" edit family += "Nimbus Sans L";
match any family == "Nimbus Sans L" edit family =+ "Helvetica";
match any family == "Gothic L" edit family += "URW Gothic L";
match any family == "URW Gothic L" edit family =+ "Gothic L";
match any family == "Palladio L" edit family += "URW Palladio L";
match any family == "URW Palladio L" edit family =+ "Palladio L";
match any family == "lucidux serif" edit family += "LuciduxSerif";
match any family == "LuciduxSerif" edit family =+ "lucidux serif";
match any family == "Palladio" edit family += "URW Palladio L";
match any family == "URW Palladio L" edit family =+ "Palladio";
match any family == "New Century Schoolbook" edit family += "Century Schoolbook L";
match any family == "Century Schoolbook L" edit family =+ "New Century Schoolbook";
match any family == "Chancery L" edit family += "URW Chancery L";
match any family == "URW Chancery L" edit family =+ "Chancery L";
match any family == "Helvetic" edit family += "Nimbus Sans L";
match any family == "Nimbus Sans L" edit family =+ "Helvetic";
match any family == "Avantgarde" edit family += "URW Gothic L";
match any family == "URW Gothic L" edit family =+ "Avantgarde";
match any family == "lucidux mono" edit family += "LuciduxMono";
match any family == "LuciduxMono" edit family =+ "lucidux mono";
match any family == "Times" edit family += "Nimbus Roman No9 L";
match any family == "Nimbus Roman No9 L" edit family =+ "Times";
match any family == "Nimbus Roman" edit family += "Nimbus Roman No9 L";
match any family == "Nimbus Roman No9 L" edit family =+ "Nimbus Roman";
match any family == "Nimbus Sans Condensed" edit family += "Nimbus Sans L";
match any family == "Nimbus Sans L" edit family =+ "Nimbus Sans Condensed";
match any family == "Nimbus Sans" edit family += "Nimbus Sans L";
match any family == "Nimbus Sans L" edit family =+ "Nimbus Sans";
match any family == "Times New Roman" edit family += "Nimbus Roman No9 L";
match any family == "Nimbus Roman No9 L" edit family =+ "Times New Roman";
XFTCONFIG

    close(OUT);
}

# fiddle with /etc/X11/XftConfig
sub install_xftconfig () {
    read_xconfigs;

    # look for where to put XftConfig
    my $outfile = $xf86config;
    $outfile =~ s/XF86Config(?:-4)?/XftConfig/;

    # check that existing XftConfig is vanilla
    my $xfttop = "";
    if(open(XFT,"<$outfile")) {
	$xfttop=<XFT>;
	close(XFT);
    };
    # XXX Would be more reliable to add a `include gdkxft_XftConfig'
    # directive, and check for that line here.  (Just because a file no longer
    # has $XFree86...$ doesn't mean that it does have gdkxft stuff.)
    if($xfttop !~ /\$XFree86.*\$/) {
	print STDERR "Your $outfile is already configured.\n";
	return;
    }

    # find xftcache binary
    my $xftcache = 
	find_xftcache("/usr/local/bin") ||
	    find_xftcache("/usr/local/bin/X11") ||
		find_xftcache("/usr/local/X11R6/bin") ||
		    find_xftcache("/usr/bin") ||
			find_xftcache("/usr/bin/X11") ||
			    find_xftcache("/usr/X11R6/bin");

    unless($xftcache) {
	print STDERR "I couldn't find an xftcache binary.  This means that I can't automatically\nconfigure your XftConfig.  You may need to edit $outfile.\n";
	install_xftconfig_dumb $outfile;
	return;
    }

    # run xftcache on each dir and look for matching filenames
    print STDERR "Scanning font directories...\n" if($verbosity >= 0);
    foreach my $fontdir (keys %fontdirs) {
	next unless(-d $fontdir);
	
	#print STDERR "Inspecting $fontdir\n";
	system($xftcache,$fontdir) && die "'$xftcache $fontdir' failed: $?";

	# build a list of matching names
	%file2ftfamily=();
	readxftcache($fontdir) && readfontdir($fontdir);
    }


    # save old XftConfig
    my $save="$outfile.gdkxftsaved";
    rename($outfile, $save) if(-r $outfile && ! -r $save);

    # produce output
    print STDERR "Building $outfile\n" if($verbosity >= 0);
    open(OUT,">$outfile") || die "Cannot write to $outfile: $!; stopped";
    select(OUT);

    print <<HEADER;
# This file was automatically generated by gdkxft.
# It should contain a reasonable Xft configuration given your
# X server and fontserver setup.

includeif	"~/.xftconfig"

match any family == "fixed"		edit family =+ "LuciduxMono";
match any family == "serif"		edit family += "LuciduxSerif";
match any family == "sans"		edit family += "LuciduxSans";
match any family == "mono"		edit family += "LuciduxMono";

HEADER

    # look here first
    print "dir \"/usr/lib/X11/fonts/Type1\"\n\n" 
	if(-r "/usr/lib/X11/fonts/Type1");

    # other dirs
    foreach my $fontdir (keys %fontdirs) {
	print "dir \"$fontdir\"\n";
    };

    # matches
    print "\n";
    foreach my $xfamily (keys %x2ft) {
	my $ftfamily = $x2ft{$xfamily};
	print "match any family == \"$xfamily\" edit family += \"$ftfamily\";\n";
	print "match any family == \"$ftfamily\" edit family =+ \"$xfamily\";\n";
    };
    
    # finished
    select(STDOUT);
    close(OUT);
}

# reverse earlier changes to XFtConfig
sub uninstall_xftconfig () {
    read_xconfigs;

    my $outfile=$xf86config;
    $outfile =~ s/XF86Config(?:-4)?/XftConfig/;
    my $save="$outfile.gdkxftsaved";
    if(-r $save) {
	print STDERR "Moving $save to $outfile\n" if($verbosity >= 0);
	rename($save, $outfile) || die "Move failed: $!; stopped";
    }
}

# put an LD_PRELOAD into scripts that will always be sourced
# by xinit / xdm / gdm
# not very portable, but neither is LD_PRELOAD
sub install_xinitrc_file ($) {
    my $x = shift || die;
    my $file;
    if(-d "$x/Xsession.d") {
	$file = "$x/Xsession.d/90gdkxft";
    } elsif(-d "$x/xinit/xinitrc.d") {
	$file = "$x/xinit/xinitrc.d/gdkxft";
    } else {
	return 0;
    }

    print STDERR "Creating $file\n" if($verbosity >= 0);
    open(OUT,">$file") ||die "Cannot write to $file: $!; stopped";

    # impl: Autoconf value of libdir usually contains `$',
    # e.g. `${exec_prefix}/lib'.  We have a choice of either inserting
    # `prefix="/usr/X11R6"' etc. into a ''-style (i.e. uninterpolated)
    # here-document, or else getting perl to interpret the variable
    # substitutions (i.e. setting prefix,exec_prefix,libdir as `my' vars in the
    # perl code).  The disadvantage of inserting `prefix=' etc. into the shell
    # script is that these settings may interfere with other shell scripts
    # sourced by xinit/xdm/....  (Remember that the scripts need to be sourced
    # rather than exec'd, since in some cases they need their variable
    # settings to be visible to other scripts, or (as in our case) to export
    # things into the environment.)

    my $prefix = "/usr/X11R6";
    my $exec_prefix = "/usr/X11R6";
    my $libdir = "/usr/X11R6/lib";
    print OUT <<XINITRC;
# This file created by gdkxft_sysinstall.

LIBGDKXFT_SO="${libdir}/libgdkxft.so.0"

if ! [ -r "\$LIBGDKXFT_SO" ]
then
	echo "\$LIBGDKXFT_SO is not readable!"
elif expr "\$LD_PRELOAD" : ".*libgdkxft.so.*" >/dev/null
then
	echo "libgdkxft.so is already preloaded."
else
	echo "Preloading \$LIBGDKXFT_SO"
	LD_PRELOAD="\$LD_PRELOAD \$LIBGDKXFT_SO"
	export LD_PRELOAD
fi

XINITRC

    close(OUT);
    
    chmod 0755, $file;
    # Ignore chmod errors: execute permission shouldn't be necessary anyway
    # given that the file is source'd, and arguably umask should have been
    # respected anyway.

    return 1;
}

sub uninstall_xinitrc_file ($) {
    my $x = shift || die;
    my $file;
    foreach my $i ("$x/Xsession.d/90gdkxft", "$x/xinit/xinitrc.d/gdkxft") {
	# Here we have a choice of `-d $i' or `-e "$i/gdkxft"'.  The former
	# does the wrong thing if a directory earlier in the search list is
	# created after initial gdkxft xinitrc creation.  Whereas the latter is
	# arguably wrong (yet arguably right) if the gdkxft was installed in
	# two different directories and the user calls gdkxfg_sysinstall -u(x)
	# twice.
	if(-e $i) {
	    $file = $i;
	    last;
	}
    }
    return 0 if(!defined($file));

    return 1 unless(-e $file);
    print STDERR "Removing $file\n" if($verbosity >= 0);
    unlink($file) || die "Unlinking of $file failed: $!; stopped";

    return 1;
}

sub install_xinitrc () {
    install_xinitrc_file("/etc/X11") ||
	install_xinitrc_file("/usr/local/X11R6/lib/X11") ||
	    install_xinitrc_file("/usr/local/lib/X11") ||
		install_xinitrc_file("/usr/X11R6/lib/X11") ||
		    install_xinitrc_file("/usr/lib/X11") ||
			print STDERR "Couldn't find an xinitrc.d/Xsession.d directory\n";
}
sub uninstall_xinitrc () {
    uninstall_xinitrc_file("/etc/X11") ||
	uninstall_xinitrc_file("/usr/local/X11R6/lib/X11") ||
	    uninstall_xinitrc_file("/usr/local/lib/X11") ||
		uninstall_xinitrc_file("/usr/X11R6/lib/X11") ||
		    uninstall_xinitrc_file("/usr/lib/X11") ||
			print STDERR "Couldn't find an xinitrc.d/Xsession.d directory\n";
}

# create a theme to show off anti-aliased fonts
sub install_theme () {
    my $themedir="/usr/X11R6";
    chomp $themedir;
    $themedir.="/share/themes";

    unless(-d $themedir) {
	print STDERR "No theme directory at $themedir";
	return 0;
    };

    mkdir("$themedir/Gdkxft", 0755);
    mkdir("$themedir/Gdkxft/gtk", 0755);
    my $file = "$themedir/Gdkxft/gtk/gtkrc";

    print STDERR "Creating $file\n" if($verbosity >= 0);
    open(OUT,">$file") ||die "Cannot write to $file: $!; stopped";

    print OUT <<GTKRC;
# This file created by gdkxft_sysinstall.
# A simple theme that uses anti-aliased fonts with many gtk widgets.

style "lil-tt" 
{
  font="-b&h-lucidux mono-medium-r-normal-*-12-*-*-*-m-*-iso8859-1"
}

style "lil-noaa" 
{
  font="-adobe-times-medium-r-normal-*-14-*-*-*-p-*-iso8859-1"
}

style "lil-serif" 
{
  font="-urw-times-medium-r-normal-*-14-*-*-*-p-*-iso8859-1"
}

style "lil-sans" 
{
  font="-urw-helvetica-medium-r-normal-*-13-*-*-*-p-*-iso8859-1"
}

style "big-sans" 
{
  font="-urw-helvetica-medium-r-normal-*-15-*-*-*-p-*-iso8859-1"
}

style "llil-sans" 
{
  font="-urw-helvetica-medium-r-normal-*-10-*-*-*-p-*-iso8859-1"
}

widget_class "*" style "lil-noaa"
widget_class "*Entry*" style "lil-serif"
widget_class "*Label*" style "lil-sans"
widget_class "*Button*" style "lil-sans"
widget_class "*Menu*" style "lil-sans"
widget_class "*MenuBar*" style "big-sans"
widget_class "*Toolbar*" style "lil-sans"
widget_class "*Frame" style "llil-sans"
GTKRC

    close(OUT);
    return 1;
}
sub uninstall_theme () {
    my $themedir="/usr/X11R6";
    chomp $themedir;
    $themedir.="/share/themes";

    unless(-d $themedir) {
	print STDERR "No theme directory at $themedir";
	return 0;
    };

    my $file = "$themedir/Gdkxft/gtk/gtkrc";
    return 1 unless(-e $file);
    print STDERR "Removing $file\n" if($verbosity >= 0);
    unlink($file);
    die "Unlinking of $file failed: $!; stopped" if(-e $file);

    rmdir "$themedir/Gdkxft/gtk";
    rmdir "$themedir/Gdkxft";
}

# do a complete install
sub do_install () {
    print STDERR "I am about to modify your X configuration: if you haven't already done so, \nplease read the README file distributed with gdkxft.\n" if($verbosity >= 0);

    install_xftconfig;
    install_xinitrc;
    install_theme;
}

# do a complete uninstall
sub do_uninstall () {
    uninstall_xftconfig;
    uninstall_xinitrc;
    uninstall_theme;
}

# Used by both usage and help.
my $usage_string = <<USAGE;
Usage: gdkxft_sysinstall [--quiet] [-u|-f|-x|-t|-uf|-ux|-ut]

To configure other parts of your system to use gdkxft, run this
script as root.  To reverse the changes made by a previous run of
gdkxft_sysinstall, use the -u option.  For more information, see
the README file that comes with gdkxft.
USAGE

sub usage () {
    print STDERR $usage_string;
    exit(1);
}

sub help () {
    print $usage_string, <<HELP;

Options:
  (none)     Install xftconfig, xinitrc, and theme.
  -{f|x|t}   Install xftconfig, xinitrc, or theme, respectively.
  -u         Uninstall xftconfig, xinitrc, and theme.
  -u{f|x|t}  Uninstall xftconfig, xinitrc, or theme, respectively.
  --help     Display this message on stdout, and immediately exit.
  --quiet    Suppress the short "normal operation" messages.  (Experts only.)
  --version  Display version number on stdout, and immediately exit.
HELP
    exit(0);
}


# Parse command-line arguments.

if(($#ARGV >= 0) && ($ARGV[0] eq '--quiet')) {
    # (Having a --quiet option is questionable, but it's better than having a
    # script writer directing all stderr to /dev/null.  We mark it `Experts
    # only' in the documentation is to discourage at least normal users from
    # using it.  If we left it completely undocumented then we'd be back to
    # the situation without a --quiet option.)

    $verbosity = -1;
    shift;
}
if ($#ARGV > 0) {
    usage();
} elsif ($#ARGV < 0) {
    do_install;
} else {
    my $param = shift;

    if ($param eq '--help') {
	help;
    } elsif ($param eq '--version') {
	print 'gdkxft 1.5', "\n";
	exit(0);
    } elsif ($param eq "-u") {
	do_uninstall;
    } elsif ($param eq "-f") {
	install_xftconfig;
    } elsif ($param eq "-uf") {
	uninstall_xftconfig;
    } elsif ($param eq "-x") {
	install_xinitrc;
    } elsif ($param eq "-ux") {
	uninstall_xinitrc;
    } elsif ($param eq "-t") {
	install_theme;
    } elsif ($param eq "-ut") {
	uninstall_theme;
    } else {
	usage;
    }
}
