#
# functions for pretty printing of htp code.
#
# options: 
#  $optn include line numbers
#  $opts include EBNF like syntax

$tagstart      = qq(<span class="htp-tag">);
$macrorefstart = qq(<span class="htp-macro">);
$attribstart   = qq(<span class="htp-attrib">);
$valuestart    = qq(<span class="htp-value">);
$stringstart   = qq(<span class="htp-string">);
$synstart      = qq(<span class="ebnf">);
$commentstart  = qq(<span class="comment">);
$manlink       = qq(<manlink href=\"TAG.html\">TEXT</manlink>);
$includelink   = "";
$endtag        = qq(</span>);

$syntax="[](|)[]";

$replacetags = "alttext|block|blockdef|def|file|if|inc|img|imageurl|opt|output|quote|set|undef|unset|use|while";

my $incomment = 0;
my $infiletag = 0;
my $ininclude = 0;
my $intag = 0;
my $inhtptag = 0;
my $instring = 0;

$optn = 0;
$opts = 0;

sub colormacro($) {
    $_ = $_[0];
    
    s!(^|[^\$])(\$([A-Za-z0-9_-]+|[^\$\{A-Za-z0-9_-]|\{[^\}]*\}))
	!$1$macrorefstart$2$endtag!xg;

    if ($opts) {
	s/[](|)[]/$synstart$&$endtag/g;
    }

    return $_;
}

sub parsehtml($) {
    my ($in) = @_;
    my $out = "";
    $in =~ s/&/&amp;/g;
    while ($in) {
	if ($instring) {

	    $in =~ s/^((\\.|[^\\\"])*)//s;
	    $file = $1;
	    if ($ininclude && $includelink && $file !~ /\$/
		&& $in =~ /^\"/) {
		$include = $includelink;
		$include =~ s/FILE/$file/g;
		$out .= $valuestart . $include . $endtag;
	    } else {
		$out .= colormacro($file);
	    }
	    if ($in =~ s/^(\")//) {
		$out .= $1;
		$instring = 0;
		$out .= $endtag;
	    }

	} elsif ($incomment) {

	    $in =~ s/^(([^-]|-*[^>-])*)//s;
	    $out .= $1;
	    if ($in =~ s/^(--+)>//) {
		$out .= $1."&gt;";
		$incomment = 0;
		$out .= $endtag;
	    }

	} elsif ($intag) {

	    # colorize attrib value pairs
	    $in =~ s/^(\s*)//s;
	    $out .= $1;
	    if ($opts) {
		if ($in =~ s/^($syntax)//s) {
		    $out .= $synstart.$1.$endtag;
		}
	    }
	    if ($in =~ s/^>//s) {
		$intag = $inhtptag = 0;
		$out .= "&gt;$endtag";
	    } else {
		$ininclude = 0;
		$excl = $opts ? '](|)[>\s=' : '>\s=';
		if ($in =~ s/^([^$excl]+)//s) {
		    $attrib = $1;
		    $out .= $attribstart . colormacro($attrib) . $endtag;
		    $ininclude = ($attrib =~ /(include|template)/i);
		}
		if ($opts) {
		    if ($in =~ s/^($syntax)//s) {
			$out .= $synstart.$1.$endtag;
		    }
		}
		if ($in =~ s/^(=)//s) {
		    $out .= "=";
		    if ($opts) {
			if ($in =~ s/^($syntax)//s) {
			    $out .= $synstart.$1.$endtag;
			}
		    }
		    if ($in =~ s/^\"//s) {
			$out .= $stringstart.'"';
			$instring = 1;
		    } elsif ($in =~ s/^([^\s>]*)//s) {
			$file = $1;
			if ($ininclude && $includelink && $file !~ /\$/) {
			    $include = $includelink;
			    $include =~ s/FILE/$file/g;
			    $out .= $valuestart . $include . $endtag;
			} else {
			    $out .= $valuestart . colormacro($file) . $endtag;
			}
		    }
		}
	    }
	} else {

	    $in =~ s/^([^<]*)//s;
	    $_ = $1;

	    # replace some spaces with nbsp
	    s/^ /&nbsp;/g;
	    s/\t/&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;/g;
	    s/(\s) /$1&nbsp;/g;
	    $out .= $_;

	    if ($in =~ s/^<(\/?)($replacetags)\b//si) {
		$tag = "\L$2\E";
		$text = "$1$2";
		$ml = $manlink;
		$ml =~ s/TAG/$tag/;
		$ml =~ s/TEXT/$text/;
		$out .= "$tagstart\&lt;$ml";
                $infiletag = 1 if $tag =~ /file/i;
		$intag = $inhtptag = 1;
	    } elsif ($in =~ s/^<(!--)//s) {
		$out .= $commentstart . "&lt;" . $1;
		$incomment = 1;
	    } elsif ($in =~ s/^<([^\s>]*)//s) {
		$out .= $tagstart . "&lt;" . colormacro($1);
		$intag = 1;
	    }
	}
    }
    return $out;
}

sub highlight_htp {
    my ($FILE) = @_;
    my $linenr = 0;
    print "<p><code>\n";
    while (<$FILE>) {    
	$_ = parsehtml($_);
	
	if ($optn) {
	    # add line header
	    $head = sprintf '<font size="-2">%2d. </font>', ++$linenr;
	    $head =~ s/> />&nbsp;/g;
	    $_ = "$head$_";
	}
	
	chomp $_;
	print "$_<br>\n";
    }
    print "</code></p>\n";
}

1;
