#!/perl

use strict;
use warnings;
my $WHITE_PATTERN2 = "^[ \t\n\r]*\$"; # spacey if ($var =~ /$WHITE_PATTERN2/o ) { ...}
my $tab_stg = '&nbsp;&nbsp;&nbsp;'; # replace tabs, with 3 spaces
my $verb2 = 0;
my $perlstx = 'C:/Program Files/EditPlus 2/perl.stx';
my $DELIMITER = ',(){}[]-+*/=~!&|<>?:;.';
my @stx = ();
my @stxc;

my $logfil = 'templog.txt';

my $infile = shift || '.';
my $outfil = shift || 'tempout.htm';
my ($OF, $IF, $LF, $STX);
my $name;
###               l.blue brown  l.br  s.gr pink   mauve  b.gr   l.br  blue wh    l.gr
my @TTColors = qw(match orange regex green color1 color2 color3 peach blue white grey);
for $name (@TTColors) {
	no strict 'refs';       # allow symbol table manipulation
    *$name = *{uc $name} = sub { "<TT class='$name'>@_</TT>" };
	### *$name = *{uc $name} = sub { "<TT class='$name'>\n@_\n</TT>" };
}
###my @colors = qw(red blue green yellow orange purple violet);
my @colors = qw(red yellow purple violet);
for $name (@colors) {
	no strict 'refs';       # allow symbol table manipulation
    *$name = *{uc $name} = sub { "<FONT COLOR='$name'>@_</FONT>" };
}

my $msg = '';
my ($line, $txt);
my $i = 0;
my ($cnt1, $cnt2);

if ($infile eq '.') {
	die "No input file given ...\n";
}
open $LF, ">$logfil" or die "Can NOT open LOG file $logfil!\n";

tolog ("$0 Started " . localtime(time()) . " ...\n");
if (! -f $infile) {
	die "Input file [$infile] NOT FOUND! ...\n";
}

tolog ("Opening $infile ...\n");
open $IF, "<$infile" or die "Can not OPEN $infile!\n";
tolog ("Loading $infile ...\n");
my @lines = <$IF>; # slurp whole file, to an array of lines
close($IF);

open $STX, "<$perlstx" or die "Can NOT locate $perlstx file...\n";
@stx = <$STX>;
close($STX);

open $OF, ">$outfil" or die "Can not create $outfil!\n";

###### pre-process perl.stx file ######################################
$i = @stx;
tolog ("List of $i STX file lines...\n");
my %stxh;
my @ResWds = ();
my @BFuncs = ();
my %HResWds;
my %HBFuncs;
my $sw = 0; # no switch on
foreach $line (@stx) {
	chomp $line;
	my $ll = length($line); # get LENGTH of file line
	my @a;
	my $k;
	my $v;
	my $c = substr ($line, 0, 1);
	$msg = '';
	if ($c eq ';') { # comment
		$msg = 'comment only';
	} elsif ($c eq '#') { # hash item=value
		$msg = ' hash';
		@a = split('=', $line); # get key/value
		($k, $v) = @a;
		$k = substr($k, 1);
		###$stxh{$a[0]} = $a[1];
		if ( exists $stxh{$k} ) {
			if ($stxh{$k} eq $v) {
				$msg .= ' same ';
			} else {
				$msg .= ' new ';
			}
			$stxh{$k} .= '|' . $v;
			###$v = $stxh{$k};
		} else {
			$stxh{$k} = $v;
		}
		### $msg .= ' k=' . $a[0] . ' v=' . $a[1] . '-'; 
		###$msg .= ' k=' . $k . ' v=' . $v . ' - '; 
		$msg .= ' k=' . $k . ' v=' . $stxh{$k} . ' - '; 
		#KEYWORD=Reserved words
		#KEYWORD=Built-in functions
#		if ($a[0] eq '#KEYWORD') {
#			if ($a[1] eq 'Reserved words') {
#				$sw = 1;
#				$msg .= '(ResWds)';
#			} elsif ($a[1] eq 'Built-in functions') {
#				$sw = 2;
#				$msg .= '(BFuncs)';
#			} else {
#				$sw = 0;
#			}
#		}
		if ($k eq 'KEYWORD') {
			if ($v eq 'Reserved words') {
				$sw = 1;
				$msg .= '(ResWds)';
			} elsif ($v eq 'Built-in functions') {
				$sw = 2;
				$msg .= '(BFuncs)';
			} else {
				$sw = 0;
			}
		}
	}

	if ($ll > 1) {
		if ($sw == 1) {
			push(@ResWds, $line);
			if ( exists $HResWds{$line} ) {
				die "Duplicate RESERVE WORD [$line]\n"
			}
			$HResWds{$line} = $line;
			$msg .= " - rw+";
		} elsif ($sw == 2) {
			push(@BFuncs, $line);
			if ( exists $HBFuncs{$line} ) {
				die "Duplicate BUILT-IN FUNCTION [$line]\n"
			}
			$HBFuncs{$line} = $line;
			$msg .= " - bf+";
		}
	}
	tolog ($line . $msg . "\n") if $verb2;
}

$line = 'new';
if ( ! exists $HBFuncs{$line} ) {
	$msg = ' ++Added';
	push(@BFuncs, $line);
	$HBFuncs{$line} = $line;
	tolog ($line . $msg . "\n");
}

$cnt1 = @ResWds;
$cnt2 = @BFuncs;
tolog ("END List of $i STX file lines...rw=$cnt1 bf=$cnt2 \n");
###### end-process perl.stx file ######################################


add_html_head( $OF, $infile );
### add_html_tail($OF);

my $lncnt = @lines; # get count
tolog ("Processing $infile ... $lncnt lines\n");
my $lc = 0;
my $dnpara = 1;
my @lnbits;
my $chk;
my $istxt = 1;
## my $func;
prt ("<p>\n");
foreach $line (@lines) {
	$txt = $line;
	chomp $txt;
	@lnbits = split(' ',$txt);
	$lc++;
	$istxt = 1; # assume text
	if ($txt =~ /$WHITE_PATTERN2/o ) {
		$txt = "</p>\n<p>\n"; # CLOSE paragraph, and open
		$istxt = 0; # NOT text
	} else {
		$txt = white(htmlise($txt));
		$txt .= "<br>\n";
	}

	prt ($txt); # just for COMPARISON

	if ($istxt) {
		###do_line_parse ($line);
		do_line_parse ($line);
	}
}

tolog ("Processed $lc lines of $infile ... written to $outfil ...\n");
prt ("</p>\n");
add_html_tail($OF);
close($OF);
 system $outfil;
# system $logfil;

sub prt {
	tolog (@_);
	print $OF @_;
}

sub addTTitem {
	my ($fh, $nm, $bd, $bg) = @_;
	print $fh <<"EOF3";
.$nm { BACKGROUND-COLOR: $bg }
EOF3

}

sub addTTitem_full {
	my ($fh, $nm, $bd, $bg) = @_;
	print $fh <<"EOF3";
.$nm
{
    BORDER-TOP: $bd 1px solid;
    BORDER-LEFT-WIDTH: 1px;
    BORDER-LEFT-COLOR: $bd;
    PADDING-BOTTOM: 1px;
    PADDING-TOP: 1px;
    BORDER-BOTTOM: $bd 1px solid;
    WHITE-SPACE: nowrap;
    BACKGROUND-COLOR: $bg;
    BORDER-RIGHT-WIDTH: 1px;
    BORDER-RIGHT-COLOR: $bd
}
EOF3

}

sub add_html_style {
	my ($fh) = @_;
	print $fh <<"EOF1";
<style><!--
TT
{
    FONT-FAMILY: 'Andale Mono', 'Lucida Console', monospace
}
EOF1

#################################
###my @TTset = qw( match #0066ff #e8f4ff string #0000ff #ccccff );
 my @TTset = (
	 "match", "#0066ff", "#e8f4ff",
	 "string", "#0000ff", "#ccccff",
	 "orange", "#ff6600", "#ffcc99",
	 "regex",  "#ff6600", "#fff4e8",
	 "green",  "#006400", "#ccffcc",
	 "color1", "#ff6600", "#ff99cc",
	 "color2", "#0066ff", "#cc99ff",
	 "color3", "#00a000", "#ccff99",
	 "peach",  "#0066ff", "peachpuff",
	 "blue",   "blue",    "powderblue",
	 "white",  "#909090", "#ffffff",
	 "grey",   "#909090", "#dddddd" );

 my $nm;
 my $bd;
 my $bg;
 my $mx = @TTset;
 tolog ("Processing $mx / 3 styles ...\n");
 tolog ( @TTset . "\n" );
 my $i;
 ## ??while (($nm, $bd, $bg) = @TTset) {
 for ($i = 0; $i < ($mx / 3); $i++) {
	 $nm = $TTset[($i*3)+0];
	 $bd = $TTset[($i*3)+1];
	 $bg = $TTset[($i*3)+2]; 
	 addTTitem ($fh, $nm, $bd, $bg);
 }
###################################

	print $fh <<"EOF2";
--></style>
EOF2

}

sub add_html_head {
	my ($fh, $hdr) = @_;
	print $fh <<"EOF";
<html>
<head>
<title>$hdr</title>
</head>
EOF
	add_html_style($fh);

	print $fh <<"EOF";
<body>
<h1 align="center">$hdr</h1>
EOF

}

sub add_html_tail {
	my ($fh) = @_;
	add_color_samp($fh);
	print $fh <<"EOF";
</body>
</html>
EOF

}

sub add_color_samp {
	my ($fh) = @_;
### my @TTColors = qw(match orange regex green color1 color2 color3 peach blue white grey);
	print $fh "<p> Colours ";
	foreach $name (@TTColors) {
		###no strict 'refs'; # allow symbol table manipulation
		my $func = \&$name; ## get the function - the auto-generated sub
		###$txt = \&$name($name);
		$txt = $func->($name); # suround/encase the text
		print $fh "[";
		###print $fh match($name);
		print $fh $txt;
		print $fh "]";
	}
	print $fh "</p>\n";
}

sub tolog {
	print @_;
	print $LF @_;
}

### NOT passed an ALL-SPACEY line
sub do_line_parse {
	my ($tx) = @_;
	chomp $tx;
	my $tx2;
	my $tx3;
	my $tx4 = htmlise($tx); ## the HTML'ISED string
	my $tx5;
	my $txsp = ''; # frontend SPACEY stuff
	my $c1 = substr ($tx, 0, 1); # get and keep first char
	@lnbits = split (' ', $tx); # initial split spaces
	my $c2 = substr ($lnbits[0], 0, 1); # get POTENTIAL new first char
	my $pos1 = index ($tx, $c2); # get pos of first array char, in string
	if ($pos1 > 0) {
		$txsp = substr($tx, 0, ($pos1 + 1)); # get SPACEY at FRONT
	}
	my $cnt = @lnbits; # count of componets, so far
	my $cntorg = $cnt; # keep original SIZE, $cnt is 'adjusted' during ...
	my $i = 0;
	my @sp11;
	if ($lnbits[0] =~ m/^\#/) {
		# is comment
		tolog ("Is comment - try ...\n");
		$tx3 = green($tx4);
		$tx3 .= "<br>\n";
		prt ($tx3);
	} else {
		## does not START with a # comment char
		my $i2 = 0;
		my $i3 = 0;
		tolog ("{ comps $cntorg\n"); # log COUNT at start
		### first run - to re-combine quoted text within LINE ARRAY
		foreach $tx2 (@lnbits) {
			$i2++; # PRE-BUMP THE COUNT
			$msg = $tx2;
			my $ln = length($tx2);
			my $ch = substr ($tx2, 0, 1);
			$i = 0;
			### special +?.*^$()[]{}|\
			if ($tx2 =~ /^['"]/ ) { ## "' # does it start with quotes d or s
			#### if (($ch eq '"')||($ch eq "'")) {
				### $msg .= " begin quote";
				$i = 1;
				if ($ln > 1) {
					$tx3 = substr ($tx2, 1, $ln - 1); # get past quote 
					if ( $tx3 =~ /$ch/) {
						$pos1 = index ($tx3, $ch); # get position of next quote
						if ($pos1 > 0) {
							$tx5 = substr ($tx2, 0, ($pos1 + 1 + 1)); # get QUOTE
							$tx3 = substr ($tx3, $pos1); # get ending text
							$msg .= ' SPLIT ';
							$msg .= '[';
							$msg .= $tx5;
							$msg .= ']';
							$msg .= '[';
							$msg .= $tx3;
							$msg .= ']????';
						}
						$msg .= " begin and end same quotes";
						$tx3 = substr($tx2,1);
						###$c = gotdelim($tx3);
						###if ($c) {
						###	$pos1 = index ($tx3,$c);
						$i = 0;
					}
				}
				if ($i) {
					# should JOIN until the END
					$i3 = 0;
					for ($i = $i2; $i < $cnt; $i++) {
						$tx3 = $lnbits[$i]; # get next
						$tx2 .= ' '; # add back space
						$tx2 .= $tx3; ### $lnbits[$i];
						$i3++;
						if ($tx3 =~ /$ch/) {
							last; # exit when terminator found
						}
					}
					$lnbits[$i2 - 1] = $tx2; # put back single quoted message
					###splice (@lnbits, $i2, $cnt - $i2); # collapse following items
					splice (@lnbits, $i2, $i3); # collapse following items
					$msg = $tx2;
					$msg .= ", now joined, to its end";
					$cnt = @lnbits; ### UPDATE THE COUNT
				}
				$i3++;
			} elsif ($ch eq '#') { # if starts with a comment
				## should join to end of line
				$i3 = 0;
				for ($i = $i2; $i < $cnt; $i++) {
					$tx3 = $lnbits[$i];
					$tx2 .= ' ';
					$tx2 .= $tx3; ### $lnbits[$i];
					$i3++;
				}
				$msg .= ' joined ';
				$msg .= $lnbits[$i2 - 1];
				$msg .= ' to ';
				$msg .= $tx2;
				$lnbits[$i2 - 1] = $tx2; # put back single quoted message
				###splice (@lnbits, $i2, $cnt - $i2); # collapse following items
				$msg .= ' sp ' . $i2 . ' ' . $i3 . '[';
				splice (@lnbits, $i2, $i3); # collapse following items
				### $msg = $tx2;
				$msg .= "], line comment";
				$cnt = @lnbits;
				$i3++;
			} else {
				## not begin quote, nor begin # ...
				my $c = 0;
				if ($ch eq '$') {
					# start of a scalor ... any other 'deliminter', in this line component?
					$tx3 = substr($tx2,1);
					$c = gotdelim($tx3);
					if ($c) {
						$pos1 = index ($tx3,$c);
						if ( $pos1 > 0 ) { # if NOT the first char, first
							### we have $var=, or a million other variations
							my $ts = '\\';
							$ts .= $c;
							@sp11 = split ($ts, $tx3);
							if ((($pos1 + 1 + 1) == $ln) && ($c ne ',')){
								### DELIMITER is LAST CHARACTER, not comma
								$tx5 = substr( $tx2, 0, ($ln - 1) ); # get all but last
								@sp11 = ($tx5, $c); # set insert array
								splice (@lnbits, ($i2 - 1), 1, @sp11); # INSERT into array at this pos
								$msg .= ' DONE SPLIT ';
								foreach $tx5 (@sp11) {
									$msg .= '[';
									$msg .= $tx5;
									$msg .= ']';
								}
								$msg .= 'ok, but adds a SPACE?!';
								$cnt = @lnbits; ### ADJUST COUNT ITERATOR
							} else {
								$msg .= ' POSSIBLE SPLIT TO [';
								foreach $tx5 (@sp11) {
									$msg .= $tx5;
								}
								$msg .= '] maybe??!!';
							}
						}
					}
				} else {
					$c = gotdelim($tx2);
				}

				if ($c) {
					$msg .= ' *D ';
					$msg .= $c;
					$msg .= '* ';
				}

				if ( exists $HResWds{$tx2} ) {
					$msg .= ' *B*'; ### blue('R');
					$i3++;
				}
				if ( exists $HBFuncs{$tx2} ) {
					$msg .= ' *P*';
					$i3++;
				}
				$i3++;
			}
			tolog ($msg . "\n");
		} # for array list of line components

		my $nct = @lnbits;
		if ($cnt != $nct) {
			die "***FIX a COUNT UPDATE $cnt $nct $cntorg ????\n";
		}
		if ($cntorg == $nct) {
			tolog ("} end comps $cntorg\n");
		} else {
			tolog ("} end comps $cntorg, adj. $nct " . ($cntorg - $nct) . "\n");
		}

		tolog ("{{ $nct");
		$tx3 = ''; # clear output
		if ($c1 eq ' ') {
			## $tx3 = '&nbsp; ';
			$tx3 = htmlise($txsp); # space to HTML
			$msg = 'Space=[';
			$msg .= $txsp;
			$msg .= '][';
			$msg .= $tx3;
			$msg .= ']';
			tolog ($msg . "\n");
		}

		#############################################
		$i3 = 0; # init COUNTER
		foreach $tx2 (@lnbits) { # process for OUTPUT
			my $c = substr ($tx2, 0, 1); # get FIRST CHAR
			if ($i3) { # was (length($tx3)) {
				$tx3 .= white(' '); # add back 'space'
			}
			$msg = $tx2;
			if ($c eq '#') { # comment component - should be to end-of-line, or more ...
				$msg = orange($tx2);
				$tx3 .= $msg;
			} elsif ($tx2 =~ /^['"]/ ) { ## "' # does it start with quotes DOUBLE or SINGLE
				if ($c eq "'") {
					$tx3 .= green($tx2);
				} elsif ($c eq '"') {
					$tx3 .= color3($tx2);
				} else {
					die "*** MATCH GATE FAILED!!! ***\n";
				}
			} elsif ($c eq '$') {
				# start of scalar
				$msg = color1($tx2);
				$tx3 .= $msg;
			} elsif ($c eq '@') {
				# start of array
				$msg = match($tx2);
				$tx3 .= $msg;
			} elsif ($c eq '%') {
				# start of hash
				$msg = peach($tx2);
				$tx3 .= $msg;
			} elsif ( exists $HResWds{$tx2} ) {
				$msg = blue($tx2);
				$tx3 .= $msg;
			} elsif ( exists $HBFuncs{$tx2} ) {
				$msg = color2($tx2); ## purple($tx2);
				$tx3 .= $msg; ## purple($tx2);
			} else {
				$tx3 .= white($tx2);
			}
			tolog (' [' . $msg . ']');
			$i3++; ## count a line item
		}
		tolog ("}}\n");
		$tx3 .= "<br>\n";
		tolog ($tx3);
		prt ($tx3);
	}
}


sub htmlise {
	my ($txt) = @_;
	# convert to HTML
	$txt =~ s/\t/$tab_stg /g; # substitute TAB characters
	$txt =~ s/"/&quot;/g; # sub double quotes
	$txt =~ s/\</&lt;/g; # sub less than tag beginning
	$txt =~ s/\>/&gt;/g; # and html/xml tag ending
	my $ln = length($txt); # get the final length
	if (substr ($txt, 0, 1) eq ' ') { # if starts with a space
		my $htmsps = 0;
		my $htmnbs = '&nbsp;';
		for ($htmsps = 1; $htmsps < $ln; $htmsps++) {
			if (substr ($txt, $htmsps, 1) ne ' ') {
				last;
			}
			$htmnbs .= '&nbsp;' if $htmsps > 1;
		}
		$htmsps-- if $htmsps > 1; # back off last space, if more than 1
		tolog ("Replacing $htmsps with [$htmnbs] ...\n") if $verb2;
		$txt =~ s/ {$htmsps}/$htmnbs/; # replace (N) spaces with '&nbsp; x N
		if ($verb2) {
			my (@vals) = split;
			while (@vals) {
				my ($vc) = shift (@vals);
				tolog ("[$vc] ");
			}
			tolog ("\n");
		}
	} # if it was space beginning

	#if ($func) {
	#	$txt = $func->($txt);
	#}
	#$txt .= "<br>\n";
	return $txt;
}

sub gotdelim {
	my ($tx) = @_;
	my $c;
	my $mx = length($DELIMITER); ### = ',(){}[]-+*/=~!&|<>?:;.';
	my @ar = split (//, $DELIMITER);
	my $i = 0;
	foreach $c (@ar) {
		my $ts = '\\';
		$ts .= $c;
		if ($tx =~ /$ts/) {
			# return 1;
			return $c;
		}
		$i++;
	}
	return 0;
}

### EOF
