#!/usr/local/bin/perl
#
# HISTORY
# Aug 1994  First version (Ver 1.00)
# Dec 1994  '-psc', '-txc' are supported 
#           rotated texts are kept as ps texts (version 1.10).
# Feb 1995  Some bugs in tgif2tex-sub are fixed .
#           all japanese stuff are removed in case of non-japanese ps
#           (version 1.20)
# Aug 1995  tig2tex, tgif2tps, tgif2tex-lib  are merged and many changes:
#           ignore japanese stuff, because tgif-2.16j do not have
#           eucfont if the picture has no japanese text
#           (version 1.30)
#           -epsfbox is supported. (Version 1.31)
# Nov 1995  -jis -euc -sjis are supported (Version 1.32)
# Nov 20, 1995  -merge -pagenum are supported (Version 1.33)

$latex_command='jlatex';	# latex command in your site.
$epsf='eclepsf';		# epsf style file in your site
$article='j-article';

@fontsize=('tiny','scriptsize','footnotesize','small','normalsize',
	   'large','Large','LARGE','huge','Huge');

$version='tgif2tex version 1.33';
$copyright='Copyright (C) 1994-1996 Koji Nakano (nakano@elcom.nitech.ac.jp)';

$usage =
"Usage: tgif2tex [-dvi] [-h] [-m mag ] [-merge texfile] [-p char] [-pagenum]
                 [-s] [-slide] [-t char] [-v] [-vv] filename ...
    -dvi    generate dvi file (only for slide mode)
    -epfsbox	for epsfbox
    -euc    output as euc
    -h      show this message
    -jis    output as jis (default: euc)
    -merge  merge slides into one
    -m	    magnification
    -p      escape char for ps text (default: .)
    -pagenum   print page number
    -s      silent
    -slide  slide mode
    -sjis    output as sjis (default: euc)
    -t      escape char for tex text (default: undefined)
    -v      verbose (default)
    -vv     very verbose
";

if($#ARGV<0 || ($ARGV[0] eq '-h')){
    print STDERR "$version\n$copyright\n$usage";
    exit;
}


print STDERR "$version\n";

$mag=1;				# manification
$adj=72*11;			# size of paper
$psc='\.';			# ESC for ps
$txc='';			# ESC for tex
$eucfont=0;			# 1 if has eucfont
$slide=0;			# 1 if slide
$dvi=0;				# 1 if generate dvi (slide mode only)
$verbose=1;			# 0=silent 1=verbose 2=very verbose
$debug=0;			# 1 if debug mode
$filename='';
$ext='';
$directory='.';
$nkf='';
$merge='';			#merge
$files=0;
$pagenum=0;
$pt=',11pt';
$size18=0;
$epsfile="\\epsfile{file=%s,scale=%d}";	# TeX commands for epsf

for(;$#ARGV>=0;shift){
    if($ARGV[0] eq '-p'){
	shift;
	$psc=$ARGV[0];
	$txc='';
    } elsif($ARGV[0] eq '-t'){
	shift;
	$txc=$ARGV[0];
	$psc='';
    } elsif($ARGV[0] eq '-s'){
	$verbose=0;
    } elsif($ARGV[0] eq '-v'){
	$verbose=1;
    } elsif($ARGV[0] eq '-vv'){
	$verbose=2;
    } elsif($ARGV[0] eq '-debug'){
	$debug=1;
    } elsif($ARGV[0] eq '-slide'){
	$slide=1;
    } elsif($ARGV[0] eq '-ohp'){
	$slide=1;
    } elsif($ARGV[0] eq '-dvi'){
	$dvi=1;
    } elsif($ARGV[0] eq '-jis'){
	$nkf='|nkf -j ';
    } elsif($ARGV[0] eq '-sjis'){
	$nkf='|nkf -s ';
    } elsif($ARGV[0] eq '-euc'){
	$nkf='| nkf -e ';
    } elsif($ARGV[0] eq '-m'){
	shift;
	$mag=$ARGV[0];
    } elsif($ARGV[0] eq '-12pt'){
	$pt=',12pt';
    } elsif($ARGV[0] eq '-11pt'){
	$pt=',11pt';
    } elsif($ARGV[0] eq '-10pt'){
	$pt='';
    } elsif($ARGV[0] eq '-large'){
	$size18=1;
    } elsif($ARGV[0] eq '-Large'){
	$size18=2;
    } elsif($ARGV[0] eq '-merge'){
	shift;
	if($merge eq ''){
	    $merge=$ARGV[0];
	    $merge="$merge.tex" unless $merge =~ /\.tex$/;
	    open(ALL,"> $merge");
	}
    } elsif($ARGV[0] eq '-epsfbox'){
	$epsf='epsf';
	$epsfile="\\epsfbox{%s}";
    } elsif($ARGV[0] eq '-pagenum'){
	$pagenum=1;
    } elsif($ARGV[0] =~ /^-/) {
	print STDERR "Do not know option $ARGV[0]\n";
    } else {
	&main;
    }
}
if($merge ne ''){
    print ALL "\\end{document}\n";
    close ALL;
    print "$merge generated\n";
    if($dvi==1){
	print STDERR "Execute $latex_command $merge.\n" if $verbose>0;
	system("$latex_command $merge");
    }
}
exit;

sub main{
    local($line);
    #determine $filename and $ext and open $filename.$ext
    if($ARGV[0]=~ /^(.+)\.ps$/){
	$filename=$1;
	$ext='ps';
    } elsif($ARGV[0]=~ /^(.+)\.eps$/){
	$filename=$1;
	$ext='eps';
	if($slide==1){
	    print STDERR "$filename.ps must be generated by tgif if slide mode.\n";
	    exit;
	}
    } else {
	$filename=$ARGV[0];
	$ext='eps' if -r "$filename.eps"; # assume $filename.eps exists
	$ext='ps' if -r "$filename.ps"; # assume $filename.ps exists
	if($ext eq ''){
	    print STDERR "Can open neither $filename.ps nor $filename.eps.\n";
	    exit;
	}
    }
    unless(open(PS,"< $filename.$ext")){
	print STDERR "Cannot open $filename.$ext.\n";
	exit;
    }
    if($filename=~ /^(.+)\/([\w\.\-]+)$/){
	$directory=$1;
	$fname=$2;
    } else {
	$directory='.';
	$fname=$filename;
	}
    &get_header;		# header is written to @header
    if($slide==1){
	    open(TEX,"> $filename.tex") || die "Cannot open $filename.tex";
	    ++$files;		# increment # of files.
	}
    while(&get_onepage){
	if($slide==1){
	    &slide_mode;
	}else{
	    &proc_page;
	}
    }
    if($slide==1){
	&slide_end;
    }
    print STDERR "No page found.\n" if $page==0;
}

sub proc_page{
    local($line);
    &find_title;
    if($title eq ''){
	unless($page==1){
	    print STDERR "Cannot find filename for page $page\n";
	    split(@onepage,0);
	    return;
	}
	$title=$fname
    }
    open(DPS,"> $directory/$title.dps") ||
	die "Cannot open $directory/$title.dps";
    open(TPS,"${nkf}> $directory/$title.tps") ||
	die "Cannot open $directory/$title.tps";
    print DPS "%%BoundingBox: $xhome $yhome $xend $yend\n";
    print DPS "%%Title: $filename\n";
    print DPS join('',@header);
    print TPS "%% Generated by $version\n";
    print TPS "%% Original: $filename.$ext page $page\n";
    print TPS "\\unitlength ${mag}pt\n";
    print TPS "\\begin{picture}($width,$height)\n";
    printf TPS "\\put(0,0){$epsfile}\n","$directory/$title.dps",$mag;
    while($line = shift(@onepage)){
	if($line =~ /^showpage/){last;}
	elsif($line =~ /^%%PageBoundingBox:/){
	    print DPS "%%PageBoundingBox: $xhome $yhome $xend $yend\n";
	} elsif($line =~ /^%\s+TEXT/){
	    &proc_text;
	} elsif($line =~ /^%\s+BOX/){
	    push(@box,$line);
	    while($line = shift(@onepage)){
		push(@box,$line);
		if($line =~ 
		   /^\s+(\d+) (\d+) moveto (\d+) \d+ lineto \d+ (\d+)/){
		    if(($lx=$1,$ly=$2,$rx=$3,$ry=$4)
		       ==($xmin,$ymin,$xmax,$ymax)){
			while($line = shift(@onepage)){
			    if($line =~ /^grestore$/){last;}
			    }
		    } else{
			print DPS join('',@box);
			while($line = shift(@onepage)){
			    print DPS $line;
			    if($line =~ /^grestore$/){last;}
			}
		    }
		}
		if($line =~ /^grestore$/){last;}
	    }
	    splice(@box,0);
	} else {print DPS $line;}
    }
    print DPS "%MatchingCreationDate: $create\n";
    print TPS "\\end{picture}\n";
    if($env ne ''){
	print TPS "\\end{center}\n";
	if($caption ne ''){
	    print TPS "\\caption{$caption}";
	    if($label ne ''){
		print TPS "\\label{$label}";
	    }
	    print TPS "\n";
	    print TPS "\\end{$env}\n";
	}
    }
    close DPS;
    close TPS;
    print STDERR "$title.dps and $title.tps generated.\n" if $verbose>0;
}

sub find_title{
    local($i,$line,$x,$y,$text,$offset,$length);
    $title='';
    for($i=0;$onepage[$i];){
	if($onepage[$i++] =~ /^%\s+TEXT/){
	    $offset=$i-1;
	    $length=1;
	    while($line = $onepage[$i++]){
		++$length;
		if($line =~/(\d+)\s+(\d+)\s+moveto\s+\((.+)\)\s+(.*)show\n$/){
		    $x=$1;
		    $y=$2;
		    $text = $3;
		    &modify_text(*text);
		    &trans(*x,*y);
		    if(($x<$xmin)||($y<$ymin)||($x>$xmax)||($y>$ymax)){
			($text =~/^\s*(\w+)\s*=\s*(.+)\s*$/) || last; 
			($left=$1) =~ tr/A-Z/a-z/;
			$right=$2;
			if($left eq 'file'){
			    $title=$right;
			}
			while($line = $onepage[$i++]){
			    ++$length;
			    if($line =~ /grestore/){
				last;
			    }
			}
			splice(@onepage,$offset,$length);
			$i=$offset;
		    }
		    last;
		}
	    }
	}
    }
}

sub slide_mode{
    $dpsname="$filename.$page.dps";
    $tpsname="$filename.$page.tps";
    open(DPS,"> $dpsname") || die "Cannot open $dpsname";
    open(TPS,"$nkf> $tpsname") || die "Cannot open $tpsname";
    print DPS "%%BoundingBox:  $xhome $yhome $xend $yend\n";
    print DPS "%%Title: $filename.$page\n";
    print TPS "%% Generated by $version\n";
    print TPS "%% Original: $filename.$ext page $page\n";
    print TPS "\\unitlength 1pt\n";
    print TPS "\\begin{picture}($width,$height)\n";
    printf TPS "\\put(0,0){$epsfile}\n",$dpsname,$mag;
    printf TPS "\\put(16,16){\\Large \\thepage}\n" if $pagenum==1;
    print DPS join('',@header);
    if($page==1){
	print TEX "\\documentstyle[$epsf$pt]{$article}\n";
	if($portrait==1){
	    printf TEX "\\setlength{\\textwidth}{%dpt}\n",$xend-$xhome+20;
	    printf TEX "\\setlength{\\textheight}{%dpt}\n",$yend-$yhome+20;
	    print TEX "\\setlength{\\oddsidemargin}{-0.7in}\n";
	    print TEX "\\setlength{\\evensidemargin}{-0.7in}\n";
	    print TEX "\\setlength{\\topmargin}{-0.5in}\n";
	} else {
	    printf TEX "\\setlength{\\textwidth}{%dpt}\n",$xend-$xhome+20;
	    printf TEX "\\setlength{\\textheight}{%dpt}\n",$yend-$yhome+20;
	    print TEX "\\setlength{\\oddsidemargin}{-0.5in}\n";
	    print TEX "\\setlength{\\evensidemargin}{-0.5in}\n";
	    print TEX "\\setlength{\\topmargin}{-0.9in}\n";
	}
	print TEX "\\pagestyle{empty}\n";
	print TEX "\\begin{document}\n";
	if($files==1){
	    print ALL "\\documentstyle[$epsf$pt]{$article}\n";
	    if($portrait==1){
		printf ALL "\\setlength{\\textwidth}{%dpt}\n",$xend-$xhome+20;
		printf ALL "\\setlength{\\textheight}{%dpt}\n",$yend-$yhome+20;
		print ALL "\\setlength{\\oddsidemargin}{-0.7in}\n";
		print ALL "\\setlength{\\evensidemargin}{-0.7in}\n";
		print ALL "\\setlength{\\topmargin}{-0.5in}\n";
	    } else {
		printf ALL "\\setlength{\\textwidth}{%dpt}\n",$xend-$xhome+20;
		printf ALL "\\setlength{\\textheight}{%dpt}\n",$yend-$yhome+20;
		print ALL "\\setlength{\\oddsidemargin}{-0.5in}\n";
		print ALL "\\setlength{\\evensidemargin}{-0.5in}\n";
		print ALL "\\setlength{\\topmargin}{-0.9in}\n";
	    }
	    print ALL "\\pagestyle{empty}\n";
	    print ALL "\\begin{document}\n";
	}
    } else{
	print TEX "\\newpage\n";
	print ALL "\\newpage\n";
    }
    print TEX "\n\\input{$tpsname}\n";
    print ALL "\n\\input{$tpsname}\n";
    while($line = shift(@onepage)){
	if($line =~ /^%%PageBoundingBox/){
	    print DPS "%%PageBoundingBox: $xhome $yhome $xend $yend\n";
	} elsif($line =~ /^%\sTEXT$/){
	    &proc_text;
	} else{
	    print DPS $line;
	}
    }
    print DPS "%MatchingCreationDate: $create\n";
    print TPS "\\end{picture}\n";
    close TPS;
    close DPS;
    print STDERR "$tpsname and $dpsname generated.\n";
}

sub slide_end{
    print TEX "\\end{document}\n";
    close TEX;
    print STDERR "$filename.tex generated.\n" if $verbose>0;
    if($dvi==1){
	print STDERR "Execute $latex_command $filename.tex.\n" if $verbose>0;
	system("$latex_command $filename.tex");
    }
}

sub get_header{
    # @header - header
    local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $week=(Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday];
    $month=(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon];
    $year+=1900;
    $create="$week $month $mday $hour:$min:$sec $year";
    while(<PS>){
	if(/^%%Title:/){
	    last;}
    }
    while(<PS>){
	if(/^%%CreationDate:/){
	    push(@header,"%%CreationDate: $create\n");
	} elsif(/^%%Creator:(.*)/){
	    push(@header,"%%Creator: $version (Original: $1)\n");
	} elsif(/^%%Pages:/){
	    push(@header,"%%Pages: 1\n");
	} else {
	    push(@header,$_);
	    if(/^%%EndProlog/){last;}
	    if(/^end/){last;}	# for .eps in tgif-2.16j
	}
    }
}

sub get_onepage{
    local($txmin,$tymin,$txmax,$tymax,$maxint);
    $portrait=1;		# assume portrait
    $page=1;			# assume page 1
    # $page, page number
    # @onepage, ps script of one page
    # $xend $yend $xhome $yhome $width $height -- picture size
    while(<PS>){		# try to find %%Page: ...
	if(/^%%Page:\s(\d+)\s(\d+)/){
	    $page=$1;
	} elsif(/^%%PageBoundingBox:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/){
	    $xhome=$1;
	    $yhome=$2;
	    $xend=$3;
	    $yend=$4;
	    push(@onepage,$_);
	    last;
	}
    }
    while(<PS>){
	if(/^90\s+rotate/){	# portrait if '90 rotate'
	    $portrait=0;
	    ($xhome,$yhome,$xend,$yend)=($yhome,-$xend,$yend,-$xhome);
	    next;
	}
	elsif(/^72\s0\smul\s(\d+)\s([\d\.]+)\smul\stranslate/){
	    $adj = $1 * $2;	# get page size
	    push(@onepage,$_);
	    last;
	}
	push(@onepage,$_);
    }
    $maxint=10000;
    $xmin=$maxint;
    $ymin=$maxint;
    $xmax=-$maxint;
    $ymax=-$maxint;
    while(<PS>){
	last if /^%%Trailer/;
	last if /^%Matching/;
	push(@onepage,$_);
	if(/^showpage/){last;}
	elsif(/^%\sBOX/){	# try to find the largest  box
	    while(<PS>){
		push(@onepage,$_);
		if(/^\s+(\d+) (\d+) moveto (\d+) \d+ lineto \d+ (\d+)/){
		    ($xmin,$ymin,$xmax,$ymax) =
			(&min($xmin,$1),&min($ymin,$2),&max($xmax,$3),&max($ymax,$4));
		}
		elsif(/^grestore/){last;}
	    }
	}
    }
    if($xmin!=$maxint){
	($txmin,$tymin,$txmax,$tymax)=($xmin,$ymin,$xmax,$ymax);
	$xhome=$yhome=0;
	&trans(*txmin,*tymin);
	&trans(*txmax,*tymax);
	($xhome,$yhome,$xend,$yend)
	    =(int($txmin),int($tymax),int($txmax),int($tymin));
    }
    if($slide==1){
	if($portrait==1){ # modify these values for adjustment
	    $xhome=30;
	    $yhome=150;
	    $xend=570;
	    $yend=830;
	    }else{
	    $xhome=30;
	    $yhome=-570;
	    $xend=800;
	    $yend=-30;
	}
    }
    $width=$xend-$xhome;
    $height=$yend-$yhome;
    if($_ eq ''){
	return 0;}	# cannot find page
    if($verbose>1){
	if($portrait==1){
	    print STDERR "Page $page is portrait.\n";
	} else {
	    print STDERR "Page $page is landscape.\n";
	}
	if($slide==0){
	    if($xmin==$maxint){
		print STDERR "Cannot find the largest box.\n";
		print STDERR "Assume picture size = $width X $height.\n";
	    } else {
		print STDERR "Picture size = ${width}pt X ${height}pt.\n";
	    }
	}
    }
    return 1;
}

sub trans{			# transform to pt
    local(*x,*y)=@_;
    $xmag=1.0015;		# values for adjustment
    $ymag=1.0018;
    $sc=0.5625;
    $yep=1;
    $x=($x*$sc-$xhome)*$xmag;
    if($portrait==1){$y=($adj-($y*$sc)-$yhome)*$ymag+$yep;}
    else{$y=(-$yhome-($y*$sc))*$ymag+$yep;}
}

sub max{
    local($a,$b)=@_;
    $a>$b ? $a :$b;
}

sub min{
    local($a,$b)=@_;
    $a<$b ? $a :$b;
}


sub proc_text{
    local($mode)=@_;
    local(@textbuf,$line,$pt,$size,$text,$eucfont);
    local($ps);
    $ps= ($psc eq '') ? 1:0;
    push(@textbuf,"% TEXT\n");
    while($line=shift(@onepage)){
	if($line =~ /rotate\s*$/){
	    $ps=1;
	} elsif($psc ne '' &&
		$line =~ /^(\s+\d+ \d+ moveto \()$psc(.*\)\s+.*show\n)/){
	    $line=$1.$2;
	    $ps=1;
	} elsif($txc ne '' &&
		$line =~ /^(\s+\d+ \d+ moveto \()$txc(.*\)\s+.*show\n)/){
	    $line=$1.$2;
	    $ps=0;
	} elsif($line =~ /eucfont\s*$/){
	    $eucfont=$line;
	}
	push(@textbuf,$line);
	if($line eq "\n"){
		last;
		}
	}
    if($ps==1){			# text should be kept in DPS
	print DPS join('',@textbuf);
	return;
    } elsif($eucfont ne ''){	# eucfont is necessary
	print DPS "% EUCFONTDEF\n$eucfont\n";
    }
    while($line = shift(@textbuf)){
	if($line =~ /^\/.+setfont\s*$/){
	    $line =~ /\[(\d+)/;
	    $pt=$1*$mag;
	    if($pt<=11){ $size="\\$fontsize[$size18]";}
	    elsif($pt<=12){ $size="\\$fontsize[$size18+1]";}
	    elsif($pt<=14){ $size="\\$fontsize[$size18+2]";}
	    elsif($pt<=17){ $size="\\$fontsize[$size18+3]";}
	    elsif($pt<=18){ $size="\\$fontsize[$size18+4]";}
	    elsif($pt<=20){ $size="\\$fontsize[$size18+5]";}
	    elsif($pt<=25){ $size="\\$fontsize[$size18+6]";}
	    else { $size="\\$fontsize[$size18+7]";}
	    $font='';
	    $jfont='';
	    $line =~ /-Roman-/ &&  ($font="\\rm");
	    $line =~ /-Bold-/ && ($font="\\bf");
	    $line =~ /-Oblique-/ && ($font="\\it");
	    $line =~ /-Italic-/ && ($font="\\it");
	    $line =~ /-BoldOblique-/ && ($font="\\sl");
	    $line =~ /-BoldItalic-/ && ($font="\\sl");
	    if($jap==1){
		$line =~ /-Ryumin-/ && ($jfont="\\dm");        
		$line =~ /-Gothic/ && ($jfont="\\dg");
	    }
	} elsif($line =~/(\d+) (\d+) moveto \((.+)\)\s+(.*)show\s*$/){
	    $x=$1;
	    $y=$2;
	    $text = $3;
	    $align = $4;
	    &modify_text(*text);
	    &trans(*x,*y);
	    $type = "lb";
	    $align =~/center/ && ($type = "b");
	    $align =~/right/ && ($type = "rb");
	    printf TPS "\\put(%0.1f,%0.1f){\\makebox(0,0)[$type]{\\mbox{$size$jfont$font $text}}}\n",$x,$y;
	} elsif($line =~ /grestore/){
	    last;
	} elsif($line =~ /^newpath/){
	    print DPS "\n\% BOX(TEXT)\n";
	    print DPS "gsave\n";
	    while($line = shift(@textbuf)){
		print DPS $line;
		if($line =~ /^closepath/){
		    print DPS "grestore\n";
		    last;
		}
	    }
	} elsif($line =~ /^gsave/){
	    print DPS "% TEXTBOX\n";
	    print DPS $line;
	    while($line = shift(@textbuf)){
		print DPS $line;
		if($line =~ /^grestore/){
		    last;
		}
	    }
	}
    }
}

sub modify_text{
    local(*text)=@_;
    $text =~ s/(\\\d\d\d)/sprintf("%c",oct(substr($&,1)))/eg;
    $text =~ s/\\\(/\(/g;
    $text =~ s/\\\)/\)/g;
    $text =~ s/\\\\/\\/g;
}
