#!/usr/bin/perl
# $Id: diff,v 1.2 1998/04/30 11:58:15 argggh Exp $

# diff --	Display diff output with markup.
#
#	Arne Georg Gleditsch <argggh@ifi.uio.no>
#	Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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 of the License, 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 program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

######################################################################

use lib 'lib/';
use SimpleParse;
use LXR::Common;
use LXR::Config;
use DB_File;


sub htmlsub {
    my ($s, $l) = @_;
    my @s = split(/(<[^>]*>|&[\#\w\d]+;?)/, $s);
    $s = '';
    
    while (@s) {
	my $f = substr(shift(@s), 0, $l);
	$l -= length($f);
	$s .= $f;
	$f = shift(@s);
	if ($f =~ /^&/) {
	    if ($l > 0) {
		$s .= $f;
		$l--;
	    }
	} else {
	    $s .= $f;
	}
    }
    $s .= ' ' x $l;
    return $s;
}


sub printdiff {

    unless ($diffvar) {
	foreach ($Conf->allvariables) {
	    push(@vars, $Conf->vardescription($_));
	}
	
	$vars[$#vars-1] .= " or ".pop(@vars) if $#vars > 0;
	
	print("<p align=center>\n",
	      "Please indicate the version of the file you wish to\n",
	      "compare to by clicking on the appropriate\n",
	      join(", ",@vars)," button.\n",
	      "</p>\n");
	return;
    }

    unless ($Path->{'file'}) {
	print("<h3 align=center>Diff not yet supported for directories.</h3>\n");
	return;
    }

    $origvirt = $Path->{'virt'}.$Path->{'file'};
    $origreal = $Path->{'real'}.$Path->{'file'};

    $origval = $Conf->variable($diffvar);
    $Conf->variable($diffvar,$diffval);
    $diffvirt = $Conf->mappath($Path->{'virt'}).$Path->{'file'};
    $diffreal = $Conf->sourceroot.$diffvirt;
    $Conf->variable($diffvar,$origval);

#    print("<h3>Diff of $origvirt -> $diffvirt</h3>\n");
#    print("<h3>($origreal -> $diffreal)</h3>\n");

    # FIXME: Check existence of $origreal & $diffreal.

    &fflush;
    unless (open(DIFF, "-|")){
	open(STDERR, ">&STDOUT");
	exec('diff', '-U0', $origreal, $diffreal);
	print "*** Diff subprocess died unexpextedly: $!\n";
	exit;
    }
    

    while (<DIFF>) {
	if (($os, $ol, $ns, $nl) = 
	    /@@ -(\d+)(?:,(\d+)|) \+(\d+)(?:,(\d+)|) @@/) {
	    $os++ if $ol eq '0';
	    $ns++ if $nl eq '0';
	    $ol = 1 unless defined($ol);
	    $nl = 1 unless defined($nl);

	    $bo = $os + $ofs;
	    if ($ol < $nl) {
		$ofs += $nl - $ol;

		$dir = '&gt;&gt;';
		$ms  = $nl - $ol;
		$ml  = $ol;
		$orig{$os+$ol} = $ms;
	    } else {
		$dir = '&lt;&lt;';
		$ms  = $ol - $nl;
		$ml  = $nl;
		$new{$ns+$nl} = $ms;
	    } 
	    foreach (0..$ml - 1) {
		$chg{$bo + $_} = '!!';
	    }
	    foreach (0..$ms - 1) {
		$chg{$bo + $ml + $_} = $dir;
	    }

	}
    }
    close(<DIFF>);


    print("<h1>Diff markup</h1>\n",
	  "<h3>Differences between ",

	  &fileref("$origvirt <i>(".$Conf->vardescription($diffvar).
		   " $origval)</i>", $origvirt, undef, "$diffvar=$origval"),
	  " and ",

	  &fileref("$diffvirt <i>(".$Conf->vardescription($diffvar).
		   " $diffval)</i>",$diffvirt, undef, "$diffvar=$diffval"),
	  "</h3><hr>\n");

#	  "<table width=\"100%\" border=0 cellpadding=0><tr><td>",
#
#	  &fileref("<b>$origvirt <i>(".$Conf->vardescription($diffvar).
#		   " $origval)</i></b>", $origvirt, undef, "$diffvar=$origval"),
#	  "<hr></td>\n<td></td>\n<td>",
#
#	  &fileref("<b>$diffvirt <i>(".$Conf->vardescription($diffvar).
#		   " $diffval)</i></b>",$diffvirt, undef, "$diffvar=$diffval"),
#	  "<hr></td>\n</tr></table>\n");


    open(FOO, $origreal);
    $orig = '';
    &markupfile(\*FOO, $Path->{'virt'}, $Path->{'file'}, 
		sub { $orig .= shift });
    $len = $.+$ofs;
    close(FOO);

    $Conf->variable($diffvar, $diffval);

    open(FOO, $diffreal);
    $new = '';
    &markupfile(\*FOO, $Conf->mappath($Path->{'virt'}), $Path->{'file'}, 
		sub { $new .= shift });
    close(FOO);

    $Conf->variable($diffvar, $origval);

    $i = 1; $orig =~ s/^/"\n" x ($orig{$i++})/mge;
    $i = 1; $new  =~ s/^/"\n" x ($new{$i++})/mge;

    @orig = split(/\n/, $orig);
    @new  = split(/\n/, $new);

    print("<pre>");
    foreach $i (0..$len) {
	$o = &htmlsub($orig[$i], 50);
#	$n = &htmlsub($new[$i], 999);
	$n = $new[$i];

#	print("<tr><td><code>$o</code></td>".
#	      "<td><font color=red> ", $chg{$i+1}, " </font></td>".
#	      "<td><code>$n</code></td></tr>\n");
	print("$o <font color=red>", ($chg{$i+1} || "  "), "</font> $n\n");
    }
    print("</pre>");

#    print("</td></tr></table>");
}


($Conf, $HTTP, $Path) = &init;
$diffvar = $HTTP->{'param'}->{'diffvar'};
$diffval = $HTTP->{'param'}->{'diffval'};

&makeheader('diff');
&printdiff;
&makefooter('diff');