#!/usr/bin/perl -w 

# this program is copyright 2004 by Vincent Fourmond
# you can modify and redistribute it under the terms of the Gnu public licence

use Getopt::Long qw(:config  bundling);

my $help = 0;
my $packages = "";
my $packages_add = "";
my $gv = 1;
my $doc_class = "article";
my $doc_option = "a4paper";
my $pre_beg_commands = "";
my $post_beg_commands = "\\pagestyle{empty}%\n";
my $keep_ps = 0;

# wether the extension of the target file is ps or eps.
my $eps_output = 0;

my $inputfile = 0;

my $force_special = 0;

my $keep = 0;

my $bbox = "gs";

my $dvips_options = "";
my $dvips_tmp_options = "";

my $pdf = 0;

my $pre_add = "";

my $help_text = <<"FIN_AIDE";
Usage: 
fig2ps [-h|--help]\tPrints this help
fig2ps [options] file.fig  Converts file.fig into ps using LaTeX for texts.
    --[no]gv runs or not gv at the end;
    --packages=pack1,pack2,... packages to be used
    --add=pack1,pack2,... supplementary packages to be used
    -k|--keep  wether to keep or not the temporary files
    --bbox=dvips|gs|a,b,c,d method for the bounding box
    --input=file use file as a TeX template (\\input file)
    --dvips=s options to go to dvips
    --preamble=s add string to the preamble
    --[no]pdf wether fig2ps should produce ps or pdf output
    --eps wether the extension of the target file is eps or ps for postscript
    --keepps when producing pdf, tells to keep the intermediary ps file
    --[no]forcespecial forces every text object to be exported as special, that 
      is processed with LaTeX.

  See the man page for more details.
FIN_AIDE
    
 
###############################################################################
#############################  read config ####################################
###############################################################################


if ($0 =~ /pdf/ ){ $pdf = 1;}
if ($0 =~ /eps/ ){ $eps_output = 1;}


my $sysconfigfile = "/etc/fig2ps/fig2ps.rc";

my %conffilehash = ( 'PACKAGES' => \$packages, 'ADD' => \$packages_add,
		     'DOC_CLASS' => \$doc_class, 'DOC_OPTIONS' => \$doc_option,
		     'FORCE_SPECIAL' => \$force_special, 
		     'INPUT' => \$inputfile, 'GV' => \$gv,
		     'PREAMBLE' => \$pre_add,
		     'KEEP_PS' => \$keep_ps);

if(-f $sysconfigfile) {
    readconfig($sysconfigfile,%conffilehash); 
}
else {
    print "Warning : the system-wide configuration file is missing\n";
}

my $persoconfigfile = $ENV{"HOME"}."/.fig2ps.rc";

if(-f $persoconfigfile) {
    readconfig($persoconfigfile,%conffilehash); 
}


GetOptions('help|h' => \$help,
	   'packages=s' => \$packages,
	   'add=s' => \$packages_add,
	   'gv!' => \$gv,
	   'keep|k' => \$keep,
	   'keepps' => \$keep_ps,
	   'bbox|b=s' => \$bbox,
	   'input|i=s' => \$inputfile,
	   'dvips=s' =>  \$dvips_tmp_options,
	   'pdf!' => \$pdf,
	   'eps' => \$eps_output,
	   'preamble=s' => \$pre_add,
	   'forcespecial!' => \$force_special
	   );

if ($help) { print $help_text;exit;}
# added 23/04/04, Vincent Fourmond
$pre_beg_commands.= $pre_add;


my @Packages = (split (/,/,$packages));
my @Add =  (split (/,/,$packages_add));

my $header;

if($pdf)
{
    #for fonts !!
    push @Packages, "aeguill";
}

prepareTex();
 

# modified (Vincent Fourmond 20/10/2004), to account for several
# file conversions in the command line :

if(@ARGV <=0) 
{ 
    die "You need to specify at least one fig file to work on";
}

LOOP:
foreach my $file (@ARGV) 
{
    # (Vincent Fourmond 8/11/2004):
    # we first need to check wether the file does exists;
    # then, if it actually does, if it is a full (or relative) path
    # or if it's only a file without any directory spec:
    
    if (! (-r $file)) {
	warn "$file is not readable - switching to next\n";
	next LOOP;
    }
    
    my $saveDir;
    if($file =~ /^(.*)\/(.*?)$/ ) {
	chomp($saveDir = `pwd`);
	chdir $1;
	$file = $2;
    }
    
    
    ($pstmp = $file) =~ s/\.fig$/.fig2ps.tmp.ps/i;
    ($figtmp = $file) =~ s/\.fig$/.fig2ps.tmp.fig/i;
    ($pstmp2 = $file) =~ s/\.fig$/.fig2ps.tmp2.ps/i;
# we need to remove the spaces in the latex name, else it doesn' work at all
    ($textmp = $file) =~ s/\.fig$/.fig2ps.tmp.tex/i;
    ($logtmp = $file) =~ s/\.fig$/.fig2ps.tmp.log/i;
    ($auxtmp = $file) =~ s/\.fig$/.fig2ps.tmp.aux/i;
    ($dvitmp = $file) =~ s/\.fig$/.fig2ps.tmp.dvi/i;
    if($eps_output) {
	($psfile = $file) =~ s/\.fig$/.eps/i;
    }
    else {
	($psfile = $file) =~ s/\.fig$/.ps/i;
    }
    ($pdffile = $file) =~ s/\.fig$/.pdf/i;
    
# we need to remove the spaces in the latex name, else it doesn't work at all
# the same for dvi, log and  aux files...
    $textmp =~ s/ /_/g;
    $logtmp =~ s/ /_/g;
    $auxtmp =~ s/ /_/g;
    $dvitmp =~ s/ /_/g;
# we need it as well for pstmp, since it is included in the TeX file
    $pstmp =~ s/ /_/g;


    my $fig_file = $file;
    
    if($force_special)
    {
	$fig_file = $figtmp;
	make_special($file, $figtmp);
    }
    
# added quoting of filenames (Bug#242463)
    if(system "fig2dev -L pstex \"$fig_file\" > \"$pstmp\"")
    { 
	die "Problems with fig2dev pstex";
    }
    
# added quoting of filenames (Bug#242463)
    $commande = "fig2dev -L pstex_t -p \"$pstmp\" \"$fig_file\" |";
    
    open PSTEX, $commande;
# added quoting of filenames (Bug#242463)
    open TEX, "> $textmp";
    
    
    my $tail = "\\end{document}\n";
    
    print TEX $header;
    
    while(<PSTEX>)
    {
	print TEX;
    }
    print TEX $tail;
    close PSTEX;
    close TEX;
    
# added quoting of filenames (Bug#242463)
    if(system "latex \"$textmp\"")
    {
	die "Problems with LaTeX";
    }
    
    mkPS();
    
    if($pdf)
    {
	# added quoting of filenames (Bug#242463)
	system "epstopdf \"$psfile\" --outfile=\"$pdffile\"";
    }
    
    
    if(!$keep)
    {
	print "Deleting temporary files...\n";
	unlink $figtmp,$pstmp,$pstmp2,$textmp,$dvitmp,$logtmp,$auxtmp;
	if($pdf) { unlink $psfile unless $keep_ps;};
    }
    
    
    if($gv )
    {
	print "Starting gv\n";
	if($pdf) {
# added quoting of filenames (Bug#242463)
	    system "gv \"$pdffile\"";
	}
	else {
# added quoting of filenames (Bug#242463)
	    system "gv \"$psfile\"";
	}
    }
    # (Vincent Fourmond 8/11/2004) we go back to the old
    # directory...
    chdir $saveDir if($saveDir)
    }

###############################################################################
############################ make fig special #################################
###############################################################################

sub make_special {
    my $input = shift @_ or die "Not enough args";
    my $output = shift @_ or die "Not enough args";
    open IN, $input;
# added quoting of filenames (Bug#242463)
    open OUT, "> $output";
    while(<IN>)
    {
	if (/^4 /) # if this is a text
	{
	    my @data = split / +/;
	    if ($data[8] & 2) # already in special
	    {
		print OUT;
	    }
	    else {
		$data[8] ^= 2;
		print OUT  join ' ', @data;
	    }
	}
	else  	{
	    print OUT;
	}
    }

    close IN;
    close OUT;
}
 


###############################################################################
############################# prepare header ##################################
###############################################################################


sub prepareTex {

    if($inputfile) # use a common style
    {
	my $file = `kpsewhich $inputfile`;
	print $file;
	open FILE,$file;
	my @lines = <FILE>;
	close FILE;
	if(grep /\\documentclass/,@lines > 0) {
	    # we have already document class
	    $header = "\\input{$inputfile}\n";
	}
	else {
	    $header = "\\documentclass[".$doc_option.
		"]{".$doc_class."}\n";
	    $header.= "\\input{$inputfile}\n";
	}

	# adds the add packages, (Teteph...)
	foreach(@Add) {
	    if(/\[(\S+)\](\S+)/)
	    {
		$header .=  "\\usepackage[$1]{$2}\n";
	    }
	    else {
		my @_add = split ':';
		my $pack = pop @_add;
		if(@add> 0)
		{
		    $header.= "\\usepackage[".join(',',@add)."]{$pack}\n";
		}
		else 
		{
		    $header.= "\\usepackage{$_}\n";
		}
		
	    }
	}
	
	# for the use of colors...
	$header.= "\\usepackage{color}\n";
	if($pdf) {
	    $header.= "\\usepackage{aeguill}\n";
	}
	    
    }
    else # builds "by hand" the package list
    {
	$header = "\\documentclass[".$doc_option.
	    "]{".$doc_class."}\n";
	
	foreach(@Packages,@Add) {
	    if(/\[(\S+)\](\S+)/)
	    {
		$header .=  "\\usepackage[$1]{$2}\n";
	    }
	    else {
		my @add = split ':';
		my $pack = pop @add;
		if(@add> 0)
		{
		    $header.= "\\usepackage[".join(',',@add)."]{$pack}\n";
		}
		else 
		{
		    $header.= "\\usepackage{$_}\n";
		}
		
	    }
	}
	
    }
    $header.=  $pre_beg_commands."\n\\begin{document}".$post_beg_commands;
}
###############################################################################
############################# make PS #########################################
###############################################################################

 
sub mkPS {
    $dvips_options .= $dvips_tmp_options;
    if($pdf)
    {
	$dvips_options = "-Ppdf ".$dvips_options;
    }
    print "$bbox\n";
    if($bbox eq "dvips") # we are using the -E option of dvips 
	#to make a tight BB
    {
# added quoting of filenames (Bug#242463)
	if(system "dvips $dvips_options -E \"$dvitmp\" -o \"$psfile\"")
	{die "Problems with dvips" ;}
	print "Using divps for the bounding box\n";
    }
    else {
	my ($LLX, $LLY, $URX, $URY);
	if(system "dvips $dvips_options  \"$dvitmp\" -o \"$pstmp2\"")
	{die "Problems with dvips" ;}
	if($bbox eq "gs") { # we let gs compute the Bounding box
	    # we specify the paper size to be b0 so that there is no problems
	    # with outbound items
	    $commande = "gs -dNOPAUSE -q -sDEVICE=bbox -sPAPERSIZE=b0 ".
		"\"$pstmp2\" < /dev/null 2>& 1|";
	    open BBOX, $commande;
	    my $found = 0;
	    while(<BBOX>)
	    {
		if(/^\%+BoundingBox/)
		{
		   s/\%\%BoundingBox\: //;
		   ($LLX, $LLY, $URX, $URY) = split / /;
		   $found = 1;
	       }
	    }
	    close BBOX;
	    die "Problems with gs" unless ($found == 1);
	    # Ajout d'un pixel autour de la figure, pour le confort de la
	    # visualisation avec 'gv' (Alex).
	    --$LLX; --$LLY; ++$URX; ++$URY;
	}
	else {
	    ($LLX, $LLY, $URX, $URY) = split /,/,$bbox ;
	}
	open IN, $pstmp2;
	open OUT, ">" . $psfile;
	while (<IN>) {
	    if (/^\%+BoundingBox/) {
		print OUT "%%BoundingBox: $LLX $LLY $URX $URY\n";
	    }
	    else {print OUT}
	}
	close OUT;
	close IN;
	print "Using $LLX $LLY $URX $URY for the bounding box\n";
	# (Vincent Fourmond 4/10/2004) : print the actual size of the image
	print "Image is ". .1*int(10*(-$LLX + $URX)/(596. / 21.)). 
	    "cm wide and ".
	    .1*int(10*( - $LLY + $URY)/(596. / 21.)). "cm high\n";
    }
}



###############################################################################
############################ read config files ################################
###############################################################################


sub readconfig {
    my $file = shift @_;
    my %options = @_;

    open CONFIG, "$file";
    my $line = 0;
    while(<CONFIG>)
    {
	$line ++;
	while( /\\$/)
	{
	    chop;
	    chop;
	    $_.=<CONFIG>;
	}
	if ((!/^\#.*$/) && (!/^\s*$/) )
	{
	    (my $name, my $vals) = /(\S*)\s*=\s*(\S*)$/;
	    if((grep /$name/,keys(%options)) > 0)
	    {
		${$options{$name}} = $vals;
	    }
	    else {
		print "Warning : line ".$line." of file ".
		    $file." not understood\n";
	    }
	}
    }
    close CONFIG;
}






