#!/usr/bin/perl

# flpr -- FL's magic print script

# Copyright (C) 1996 Friedrich Leisch
#
# This program is free software; you can 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 program 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
# along with this file.  If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

# Send any bug reports to Friedrich.Leisch@ci.tuwien.ac.at

$VERSIONNR="2.1";

$HOME=$ENV{"HOME"};
$SITECONFIG="flpr.conf";
$USERCONFIG="$HOME/.flpr";

##################################
# Do not change anything below !!!
##################################

sub vsay
{
    print stderr $_[0] if ($opt_verbose || $opt_debug);    
}

sub say
{
    print stderr $_[0] unless $QUIET;
}

sub sys
{
    vsay("$_[0]\n");
    $e = system("$_[0]");
    say("<$_[0]> has exit code $e\n") if $opt_debug;
    die("Error while executing system command!\n") if $e;
}

sub version
{
    print "\n";
    print "flpr $VERSIONNR -- FL's magic print script\n";
    print "Copyright (C) 1996 Friedrich Leisch\n";
    print "\n";
}

sub usage
{    
    version();
    print "usage:\n";
    print "\n";
    print "flpr [-1] [-2] [-b/--blocks (1|2|4landscape|4portrait)]\n";
    print "     [-c/--copies num] [-d/--debug] [-f/--filter]\n";
    print "     [-H/--header string] [-h/--help] [-l/--load]\n";
    print "     [-m/--mail] [--no-guess-extension] [--no-init-file]\n";
    print "     [-n/--no-print] [--no-printer-file] [--no-select]\n";
    print "     [--no-site-file] [-p/--pages range] [-P/--printer string]\n";
    print "     [-q/--quiet] [-r/--(no)reverse] [--remove]\n";
    print "     [-s/--subject string] [-T/--type (magic|ps|dvi|text|image)]\n";
    print "     [-v/--(no)verbose] [-V/--version]\n";
    print "     file1 file2 file3 ...\n";
    print "\n";
    print "where valid file types are ascii text, postscript and DVI and\n";
    print "gzipped or compressed versions of the above.\n";
    print "\n";
}

sub magic
{
    if(!$opt_type || ($opt_type =~ /magic/i)){
	open(mag, "$MAGIC '$_[0]' |");
	read mag, $retval, 80;
	close mag;
	$retval =~ s/$_[0]: (.*)/$1/;
    }
    elsif($opt_type =~ /ps/i){
	$retval = "postscript";
    }
    elsif($opt_type =~ /dvi/i){
	$retval = "DVI";
    }
    elsif($opt_type =~ /text/i){
	$retval = "text";
    }
    elsif($opt_type =~ /image/i){
	$retval = "image";
    }
    else {
	die "Option type has to be one of magic, ps, dvi or text\n";
    }
    $retval;
}

sub guess_extension
{
    if(-r $_[0]) {
	$retval = $_[0];
    }
    elsif(!$opt_noguessextension) {
	vsay("Guessing extension of $_[0] => ");
	$x = $_[0];
	$x =~ s/\.$//;
	if(-r "$x.ps"){
	    $retval = "$x.ps";
	}
	elsif(-r "$x.dvi"){
	    $retval = "$x.dvi";
	}
	vsay("$retval\n");
    }
    $retval || die "Cannot open $_[0] for reading!\n";
}

sub psprint
{
    $pspipe ="";

    if(!$opt_noselect){
	$selectopt = "";
	$selectopt = "$selectopt -q" if $opt_quiet;
	$selectopt = "$selectopt -r" if $REVERSE;
	$selectopt = "$selectopt -p$opt_pages" if $opt_pages;
	$pspipe = " | psselect $selectopt ";
    }

    if($BLOCKS =~ /2/){
	say("printing 2 blocks per sheet\n");
	$pspipe = "$pspipe | $TWOPAGECMD";
    }
    elsif($BLOCKS =~ /4l/){
	say("printing 4 landscape blocks per sheet\n");
	$pspipe = "$pspipe | $LFOURPAGECMD";
    }
    elsif($BLOCKS =~ /4p/){
	say("printing 4 portrait blocks per sheet\n");
	$pspipe = "$pspipe | $PFOURPAGECMD";
    }
    
    $pstmpf="${TMPBASE}_ps";
    sys("$CAT '$_[0]' $pspipe > $pstmpf");

    if($MAIL || $SUBJECT){
	open(pstmpf, ">>$pstmpf");
	print pstmpf "% FLPR send mail\n" if $MAIL;
	print pstmpf "% FLPR accounting subject: $SUBJECT\n" if $SUBJECT;
	close pstmpf;
    }

    if(!$opt_noprint){
	if($opt_filter){
	    sys("cat $pstmpf");
	}
	else{
	    $lproptions = "";
	    $lproptions = "$lproptions -P$PRINTER" if $PRINTER;
	    $lproptions = "$lproptions -#$opt_copies" if $opt_copies;
	    sys("$LPR $lproptions $pstmpf");
	}
    }
}

sub dviprint
{
    $dvitmpf="${TMPBASE}_dvi.ps";
    sys("$DVIPS -q -f '$_[0]' > $dvitmpf");
    psprint($dvitmpf);
}

sub textprint
{
    $BLOCKS = $TEXT_BLOCKS unless ($opt_1 || $opt_2 || $opt_blocks);

    if($opt_header){
	$header=$opt_header;
    }
    else{
	$header=$fn;
    }
    $txttmpf="${TMPBASE}_txt.ps";
    sys("$A2PS -H'$header' '$_[0]' > $txttmpf");
    psprint($txttmpf);
}

sub imageprint
{
    $imgtmpf="${TMPBASE}_image.ps";
    sys("$IMGCONVERT '$_[0]' $imgtmpf");
    psprint($imgtmpf);
}


sub flpr
{
    $f=$_[0];

    $m = magic($f);

    if($f =~ /$TMPBASE/){
	$fn = "";
    }
    else{
	$fn = "$f ";
    }

    $DOPRINTTEXT = "not " if $opt_noprint;
    
    if($m =~ /compress.d/i){
	$tmpf="${TMPBASE}_unzipped";
	say "uncompressing ${fn}... ";
	sys("$ZCAT '$f' > $tmpf");
	flpr($tmpf);
    }
    elsif($m =~ /postscript/i){
	say $DOPRINTTEXT;
	say "printing ${fn}in postscript mode\n";
	psprint($f);
    }
    elsif($m =~ /DVI/){
	say $DOPRINTTEXT;
	say "printing ${fn}in dvi mode\n";
	dviprint($f);
    }
    elsif($m =~ /text|script/i){
	say $DOPRINTTEXT;
	say "printing ${fn}in text mode\n";
	textprint($f, $fn);
    }
    elsif($m =~ /image/i){
	say $DOPRINTTEXT;
	say "printing ${fn}in image mode\n";
	imageprint($f, $fn);
    }
    else{
	die "Cannot handle $m\n";
    }
}


# Parse all options case sensitive

use Getopt::Long;

$Getopt::Long::ignorecase=0;

@knownoptions = (
		 "1",
		 "2",
		 "blocks|b=s",
		 "copies|c=s",
		 "debug|d",
		 "filter|f",
		 "header|H:s",
		 "help|h",
		 "load|l=s",
		 "mail|m",
		 "noguessextension|no-guess-extension",
		 "noinitfile|no-init-file",
		 "noprint|no-print|n",
		 "noprinterfile|no-printer-file",
		 "noselect|no-select",
		 "nositefile|no-site-file",
		 "pages|p=s",
		 "printer|P=s",
		 "quiet|q!",
		 "reverse|r!",
		 "remove",
		 "subject|s=s",
		 "type|T=s",
		 "verbose|v!",
		 "version|V");

GetOptions (@knownoptions) || exit;


# If we only have to print version or help text, we donnot have much
# to do:

if($opt_version) {
    version();
    exit;
}

if($opt_help) {
    usage();
    exit;
}


say "---- flpr $VERSIONNR ----\n" unless $opt_quiet;


# Set some handy variables

$TMPDIR="/tmp";

$MAGIC="file";
$ZCAT="zcat";
$CAT="cat";
$LPR="lpr";
$DVIPS="dvips";
$A2PS="a2ps -1 -8 -p -nu -nL -ns -q -H$header";
$IMGCONVERT="convert -page A4";


$TWOPAGECMD="pstops -q \"2:0L@.7(21cm,0)+1L@.7(21cm,14.85cm)\"";
$PFOURPAGECMD="pstops -q \"4:0@.48(0cm,14.85cm)+1@.48(10.3cm,14.85cm)+2@.48(0,0.2cm)+3@.48(10.3cm,0.2cm)\"";
$LFOURPAGECMD="pstops -q \"4:0@.48(0,0.2cm)+1@.48(0cm,14.85cm)+2@.48(10.3cm,0.2cm)+3@.48(10.3cm,14.85cm)\"";

# Load the miscellaneous configuration files. 

if(!$opt_nositefile){
    if(-r "/usr/local/etc/$SITECONFIG"){
	$SITECONFIGDIR="/usr/local/etc";
    }
    else{
	$SITECONFIGDIR = "/etc";
    }
    if(-r "$SITECONFIGDIR/$SITECONFIG"){
	vsay "loading site configuration file $SITECONFIGDIR/$SITECONFIG\n";
	do "$SITECONFIGDIR/$SITECONFIG";
    }
}

if($opt_printer){
    $PRINTER = $opt_printer;
}
else{
    $PRINTER = $ENV{"PRINTER"};
}

if(-r "/usr/local/etc/flpr.$PRINTER"){
    $PRINTERCONFIG="/usr/local/etc/flpr.$PRINTER";
}
else{
    $PRINTERCONFIG="/etc/flpr.$PRINTER";
}

if(!$opt_noprinterfile && -r $PRINTERCONFIG){
    vsay "loading printer configuration file $PRINTERCONFIG\n";
    do $PRINTERCONFIG;
}

if(!$opt_noprinterfile && -r $USERCONFIG){
    vsay "loading user configuration file $USERCONFIG\n";
    do $USERCONFIG;
}

if(-r $opt_load){
    vsay "loading configuration file $opt_load\n";
    do $opt_load;
}
    
    

# Combine options and configuration files:

$TMPBASE="${TMPDIR}/flpr_$$";
$QUIET   = $opt_quiet   if $opt_quiet;
$MAIL    = $opt_mail    if $opt_mail;
$SUBJECT = $opt_subject if $opt_subject;
$REVERSE = $opt_reverse if $opt_reverse;

$BLOCKS  = "1" if $opt_1;
$BLOCKS  = "2" if $opt_2;
$BLOCKS  = $opt_blocks  if $opt_blocks;


# If we have no further arguments, we copy stdin to a tmpfile, else we
# try to print each file.

if($#ARGV==-1){
    $tmpf="${TMPBASE}_stdin";
    open(tmpf, ">$tmpf");
    while(<>){
	print tmpf $_;
    }
    close tmpf;
    flpr($tmpf);
}
else{
    for($k=0;$k<=$#ARGV;$k++){
	flpr(guess_extension($ARGV[$k]));
	if($opt_remove){
	    if(-w $ARGV[$k]){
		unlink $ARGV[$k];
	    }
	    else {
		say("Cannot remove file $ARGV[$k]: ");
		say("No such file or wrong permissions!\n");
	    }
	}
    }
}


# Finally clean up the temporary files except when in debiugging mode

if($opt_debug){
    say("Debug mode: Please remove files $TMPBASE* manually\n");
}
else {
    sys("/bin/rm -f ${TMPBASE}*");
}

