#!/usr/bin/perl -w

# last modified 12/16/02

# a minimalistic IDE for TeX

# This program will spawn an xdvi viewer creating the .dvi file if needed.
# it will then watch the .tex file and when it changes, regenerate the
# .dvi file and signal xdvi to redisplay it.

# .tex is assumed if the filename does not end in .tex

# automatically determined if the file is a laTeX or TeX file.

# now checks for changes to included files as well.

# append parameter landscape to get Xdvi landscape display

# assumes files that start with \documentclass[semhelv]{seminar} are landscape

# stops and continues Xdvi while TeXing to avoid Xdvi dieing.

my $filename;
my $interaction = "-interaction=nonstopmode";
my $texcmd = "tex";
my $texerrorcmd = "texerror.tcl";

my $landscape = 0; # set to display in Xdvi using -paper usr

my @included_files;

if($ARGV[0] ) 
{
	$filename = $ARGV[0];
}
else
{
	die "usage: $0 filename [landscape]\n";
}

if($ARGV[1] and $ARGV[1] =~ m/landscape/i)
{
	$landscape = 1;
}

if($filename !~ m/\.tex$/ )
{
	$filename .= '.tex';
	$filename =~ s/\.\.tex/.tex/;
}

if( ! -f $filename )
{
	die "$filename not found\n";
}

open(TEX,$filename) or die "cannot open $filename\n";

my $line = <TEX>;

while($line =~ m/^\%/ )
{
	$line = <TEX>;
}

if($line =~ m/^\\document/)
{
	$texcmd = "latex";
}
if($line =~ m/^\\documentclass\[semhelv\]\{seminar\}/)
{
	$landscape = 1;
}

while($line = <TEX> )
{
	my $ifile;
	if(($ifile) = $line =~ m/\\include\{(.+)\}/)
	{
		if($ifile !~ m/\.tex$/ )
		{
			$ifile .= '.tex';
		}
		push(@included_files,$ifile);
	}
}

close(TEX);

my $basename = $filename;

$basename =~ s/\.tex//;
	
my $dvi_pid=0;

if(! -f $basename.'.dvi')
{
	my @cmd = ($texcmd,$interaction,$filename);
	system(@cmd) == 0 or die "system @cmd failed: $?";
}

$dvi_pid = fork();
if($dvi_pid == 0)
{
	my @cmd;
	if($landscape)
	{
		@cmd = ('xdvi','-paper','usr',$basename.'.dvi');
	}
	else
	{
		@cmd = ('xdvi',$basename.'.dvi');
	}
	exec(@cmd) == 0 or die "system @cmd failed: $?";
}
			
my @stat = stat($filename);
unless(@stat)
{
	die "stat failed on $filename\n";
}

my $old_mod = $stat[9];

my @inc_mods;
for(my $i=0;$i <= $#included_files;$i++)		
{
	my $f = $included_files[$i];
	@stat = stat($f);
	unless(@stat)
	{
		die "stat failed on $f\n";
	}
	$inc_mods[$i] = $stat[9];
}			

while(1)
{
	$retex = 0;
	
	@stat = stat($filename);
	unless(@stat)
	{
		die "stat failed on $filename\n";
	}
	
	if($stat[9] != $old_mod)
	{
		$retex = 1;
		$old_mod = $stat[9];
	}
	
	for(my $i=0;$i <= $#included_files;$i++)		
	{
		my $f = $included_files[$i];
		@stat = stat($f);
		unless(@stat)
		{
			die "stat failed on $f\n";
		}
		
		if($stat[9] != $inc_mods[$i])
		{
			$retex = 1;
			$inc_mods[$i] = $stat[9];
		}
	}			

	if($retex)
	{
		if($dvi_pid)
		{
			kill('SIGSTOP',$dvi_pid);
		}
		my @cmd = ($texcmd,$interaction,$filename);
#		system(@cmd) == 0 or die "system @cmd failed: $?";
		if(system(@cmd) != 0)
		{
			@cmd=($texerrorcmd);
			system(@cmd);
		}
		
		if($dvi_pid)
		{
			kill('SIGCONT',$dvi_pid);
			kill('SIGUSR1',$dvi_pid);
		}
	}

	select(undef, undef, undef, 0.25);
}
