#!/usr/bin/perl -w

## mgplatex - Compile latex code embedded in MagicPoint code

## See doc at end of file or run 'mgplatex -h'

## Todo : %latexline-%endlatexline :
##            Find a way of positionning the image correctly


				# Default values #####################
$verbose = 0;
$force = 0;
$outfile = "";
$directory = "";
$latexpreamble = "\\usepackage[latin1]{inputenc}\n";
$latexinit = "";
$skip = 0;
				# No arguments : show help ###########
unless (@ARGV) {
    print "\n       mgplatex : At least one argument is needed\n\n";
    exec "perldoc -t $0|cat";
}

while ($ARGV[0] =~ s/^-//) {	# Read options #######################
    map {			# Loop through each letter
      if    ($_ eq "v") { $verbose++ }
      elsif ($_ eq "s") { $skip = 1 }
      elsif ($_ eq "f") { $force = 1 }
      elsif ($_ eq "d") { $directory = shift @ARGV }
      elsif ($_ eq "o") { $outfile = shift @ARGV }
      elsif ($_ eq "h") { exec "perldoc -t $0|cat" }
      elsif ($_ eq "H") { exec "perldoc $0" }
      else              { die "Unknown option '$_'" }
   } split ("", shift @ARGV);
}

				# Preparation ########################

$infile = shift @ARGV;		# Name of input

unless ($outfile) {		# Name of output file
    $outfile = $infile;
    $outfile =~ s/\.mgplatex$//;
    $outfile .= ".mgp";
}
				# Directory for auxiliary files

$directory = "$infile.auxdir" unless $directory;

				# Open files

open FF, "<$infile" or die "Can't read file '$infile'";
open GG, ">$outfile" or die "Can't write file '$outfile'";

unless (-d $directory) {
    print "Creating '$directory'\n" if $verbose;
    mkdir $directory or die "Can't create directory '$directory'";
}

$counter = 0;			# Counter for latex expressions / files

				# CD to directory
chdir $directory or die "Can't cd to '$directory'";

while (! eof(FF)) {		# Read input #########################
    $_ = <FF>;

    my ($keep, $latex, $latexsize) = ("","","");

				# Reading LaTeX block ################

    if (/^\s*(?:\\|\%\s*)(beginlatex|latexline)\s*(.*)/) {

	print "Found beginning latex block\n" if $verbose > 1;

	$latexsize = $2;

	my $opening = $1;

	my ($isline,$lineoffset,$closing) = (0,10,"endlatex");
	if ($opening eq "latexline") {
	    $isline = 1;
	    $closing = "endlatexline";
	    if ($latexsize =~ s/^(\s*\d+\s+\d+\s+)(\d+)$/$1/) {
		$lineoffset = $2;
	    }
	}
	$latexsize = "0 $latexsize";
   

	my $basename = "latex-$counter";
	$counter++ ;

	while (1) {
	    $_ = <FF>;
	    last if  /^\s*(?:\\|\%\s*)$closing/;

				# Size of latex image

	    if (/^\%\s*latexsize\s*(.*)/) {
		chomp ($latexsize = $1);

	    } else {
				# Correct \input{} for changed directory
		s|\\input{(.*)}|"\\input{". &localize($1) ."}"|eg;

		/^\%\s*(center|leftfill|rightfill)/ ? $keep : $latex .= $_;
	    }
	    if (eof(FF)) {warn "Found $opening without $closing"; last}
	}
	## print "Keep  >>$keep<<\nLatex >>$latex<<\n" if $verbose;

	my $epsfile = "$basename.eps";

	my $mgpcode = qq(\%image "$directory/$epsfile" $latexsize\n);
	if ($isline) {
	    $mgpcode = "\%cont\n$mgpcode\%cont\n";
	}

	print GG $keep;		# Print kept code in mgp file
	print GG $mgpcode;	# Print image command in mgp file

				# Create latex code
	chomp ($latex);
	chomp ($latexinit);
	next if $skip;

	$alllatexcode = <<EOLATEX;
\\documentclass[12pt]{article}
$latexpreamble
\\begin{document}
\\thispagestyle{empty}
$latexinit
$latex
\\end{document}
EOLATEX

				# Check whether compilation is necessary

	$latexfile = "$basename.tex";

				# Load previous latex code, if it exists
	my $dont_compile = 0;
        if (! $force && -e $latexfile && -e $epsfile) {
	    open JJ, "<$latexfile"
		or die "Can't read original latex file '$latexfile'";
	    $origcode = join "", <JJ>;
	    close JJ;

	    $dont_compile = $alllatexcode eq $origcode;
	}

	if ($dont_compile) {	# Compilation not needed
	    
	    print "Skipping unchanged file '$latexfile'\n" if $verbose > 1;
	    next
	} else {		# Create the latex file and compile it

	    unlink $epsfile;
	    open II, ">$latexfile" or 
		die "Can't create file '$latexfile'";
	    print II $alllatexcode;
	    close II;

	    print "Compiling '$latexfile'\n" if $verbose;
	}

				# Where does output of latex and dvips go?
	$outpipe = ($verbose>1) ? "" : " &> /dev/null" ;

				# Compile latex file
	die "Can't run (in $directory) 'latex $latexfile' : \n" .
	    "There is probably a problem in the code --\n" .
	    $latex .
	    "\n------------------------------------------\n"  if
	    system "latex -interaction=nonstopmode $latexfile $outpipe";
	
	die "Can't run (in $directory) 'dvips -E $basename.dvi -o $epsfile'"
	    if system "dvips -E $basename.dvi -o $epsfile $outpipe";

				# Shift eps image so that it is aligned with
				# current line of text.
	# This does not work :-(
	# if ($isline) {
	#    system q|perl -i.bak -pe 's{^(%%BoundingBox:\s+\d+\s+\d+\s+\d+\s+)(\d+)}{"$1" . (| . $lineoffset . q|+ $2)}e' | . $basename . ".eps" ;
	# } 

				# Todo : remove temp files

				# End of reading LaTeX block ##########

				# Read LaTeX preamble or initialization
    } elsif (/^\s*(?:\\|\%\s*)(latexpreamble|latexinit)/) { 
	
	my $what = $1;
	
	$$what = "";

	while (1) {
	    $_ = <FF>;
	    last if  /^\s*(?:\\|\%\s*)end$what/;
	    $$what .= $_;
	    if (eof(FF)) {
		warn "$what without end$what";
		last;
	    }
	}
	print "Found $what\n" if $verbose;

	$$what =~ s|\\input{(.*)}|"\\input{". &localize($1) ."}"|eg;

				# End of reading LaTeX preamble ######

    } else {			# Pass mgp code through ##############
	print GG $_;
    }
}				# End of reading input ###############

close FF;
close GG;
exit 0;				# That's it ##########################

## Subs ##############################################################

				# change \input{x} to \input{../x}
sub localize {
    my $f = shift;
    $f =~ s{^}{../} unless $f =~ m{^/};
    $f;
}

## Doc ###############################################################

=head1 NAME mgplatex - Compile latex code embedded in MagicPoint code

Creates a MagicPoint F<file.mgp> from a F<file> containing MagicPoint
code with inlined LaTeX code.

=head1 SYNOPSIS mgplatex [options] F<file>

Reads F<file>, transforms LaTeX code enclosed in each
B<%beginlatex-%endlatex>, B<\beginlatex-\endlatex> or
B<%latexline-%endlatexline> block into equivalent mgp code and writes the
result in F<file.mgp>, which is readable by F<mgp>.

In the process, a directory is created (default : F<file.auxfiles>), in
which .tex files -one per block of latex code- are created and transformed
into encapsulated postscript (.eps) images by B<latex> and B<dvips>.

The arguments following %beginlatex are the width and height (in screen
percents) of the latex text and are passed to the mgp command %image that
is used to display the LaTeX output.

A %latexline block behave the same as %beginlatex block except that the
latex code is displayed on the same line as the preceding and following
magicpoint code. This is useful for embedding small amounts of latex code in
paragraphs.

If a B<%latexpreamble-%endlatexpreamble> block is present, it is inserted
before C<\begin{document}>. By default, C<\usepackage[latin1]{inputenc}> is
inserted. 

If a B<%latexinit-%endlatexinit> block is present, it is inserted
between C<\begin{document}> and the code defined by each
%beginlatex-%endlatex block. By default, nothing is instered.

=head1 EXAMPLE

The following block

  %beginlatex 60 30
  A little bit of \LaTeX : 
  \[ A(x) = \int_{0}^{\infty} e^-\frac{x}{2} dx \]
  %endlatex

is transformed by mgplatex into :

  %image "file.auxdir/latex-0.eps" 60 35

where F<file.auxdir/latex-0.eps> is the image resulting from running
B<latex> and B<dvips> on the latex code.

It is possible to I<use latex packages> by specifying them in preamble. The
following example uses the color and dsfont packages :

  %latexpreamble
  \usepackage[latin1]{inputenc}
  \usepackage{dsfont}
  \usepackage{color}
  %endlatexpreamble
  %beginlatex 30 5
    $$ \textcolor{red}{\mathbf{X}} \in \mathds{R}^3 $$
  %endlatex

=head1 OPTIONS

Options can be grouped together.

=over 4

=item -d F<dirname>

Put generated files in F<dirname>. By default, uses F<file.auxfiles>.


=item -o F<outfile>

Call F<outfile> the resulting .mgp file. By default, the name is obtained by
removing an eventual '.mgplatex' suffix of F<file> and appending '.mgp'.

=item -f

Force compilation of all latex files. By default, a latex file is compiled
only if it has been modified.

=item -v

Be verbose : say what's going on and show output of latex and dvips. More -v
options produce more verbose output.

=item -h

Show this help and exit.

=item -H

Display help with a pager and exit.

=back

=head1 SEE ALSO

B<mgp>, L<http://www.mew.org/mgp/>, B<latex> and B<dvips>.

Embedding latex in mgp is an old wheel that is often reinvented on
mgp-user@mew.org. Luigi Rizzo made a on-the-fly preprocessor [1] and so did
Stephan Buchert [3], who modified an the script B<tex2eps.sh> by Sylvain
Pion.  Anders Logg made an offline preprocessor B<mgptex> [2]. B<mgplatex>
should be able to read the embedded code of B<mgptex>.


 [1] http://www.mew.org/ml/mgp-users/msg00253.html
 [2] http://www.csl.sony.co.jp/person/nishida/mgp-users/msg00290.html
 [3] http://www.csl.sony.co.jp/person/nishida/mgp-users/msg00419.html

=head1 COPYRIGHT Etienne Grossmann E<lt>etienne@isr.ist.utl.ptE<gt>

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.

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.

=cut
