#!/usr/bin/perl -w

use strict;
use CGI;
use Getopt::Long;

my %esc_pat = (
    "0;30m"	=> "d",
    "0;31m"	=> "r",
    "0;32m"	=> "g",
    "0;33m"	=> "y",
    "0;34m"	=> "b",
    "0;35m"	=> "p",
    "0;36m"	=> "m",
    "0;37m"	=> "w",
    "1;30m"	=> "d",
    "1;31m"	=> "lr",
    "1;32m"	=> "lg",
    "1;33m"	=> "ly",
    "1;34m"	=> "lb",
    "1;35m"	=> "lp",
    "1;36m"	=> "lm",
    "1;37m"	=> "lw"
);

my %opts = (
    charset	=> 'windows-1251',
    title	=> 'Colorized log'
);
GetOptions (\%opts, "style|s=s",
		    "to|t=s",
		    "from|f=s",
		    "charset|c=s",
		    "title=s",
		    "optimise|o",
		    "help|h|?", \&help,
		    "help-style", \&help_style);

my $q = new CGI({});
my $last_pat='';
my $time1;
my ($style, $std_style);
my ($f_in, $f_out);

$std_style = <<END;
    body {background-color: #000000;	color: #ffffff;
	font-family: courier;}
    a	{color: #4040ff}	pre {font-size:14px}
    .d	{color:black}
    .r	{color:red}		.g	{color:#008800}
    .y	{color:brown}		.b	{color:blue}
    .m	{color:00a0a0}		.p	{color:magenta}
    .w	{color:lightgrey}	.lr	{color:#ff0000}
    .lg	{color:#00ff00}		.ly	{color:yellow}
    .lb	{color:#0000ff}		.lm	{color:cyan}
    .lp	{color:magenta}		.lw	{color:white}
END

$style = $std_style;
$opts{style} && -r $opts{style} && do {
        open STL, "<$opts{style}";
        $style = join "", <STL>;
	close STL;
    };

if ($opts{to}) {
	open(FOUT, ">$opts{to}");
	$f_out = *FOUT
} else {
        $f_out = *STDOUT
}

if ($opts{from} && -r $opts{from}) {
	open(FIN, "<$opts{from}");
	$f_in = *FIN
} else {
        $f_in = *STDIN
}

$time1 = time();
print	$f_out $q->start_html(-title=>"$opts{title}",
			-style=>{-code=>${style}},
			-head=>$q->meta({
			    -http_equiv	=> 'Content-Type',
			    -content	=> "text/html; charset=$opts{charset}"}),
			-meta=>{'generator'=>'log-colorizer by dikiy\@mud.ru'}
			    ),
	$q->comment("generated by log-colorizer"),
	$q->h1($opts{title}),
	"Generated with log-colorizer", $q->br,
	"Date : ". localtime(), $q->br,
	"(c) 2002 ",
	$q->a({href=>"mailto:dikiy\@mud.ru"}, "Andrew [dikiy] Baznikin"),
	$q->br,
	$q->hr,
	$q->start_pre;

#if ($opts{optimize} && $opts{from}) {}

my $was_w=1;
while (<$f_in>) {
    my $line = $_;
    $line =~ s/\x0d//g;
    $line =~ s/</&lt;/g;
    $line =~ s/>/&gt;/g;
    $line =~ s/\e\[(\d+);(\d+)m/{
		    if ("$1_$2" ne $last_pat) {
			$last_pat = "$1_$2";
			my $pat = $1 .";". $2 ."m";
			if (defined $esc_pat{$pat} ) {
			    if ($opts{optimise}) {
				if ($esc_pat{$pat} eq "w") {
				    $was_w = 1;
				    "<\/span>";
				} else {
				    if ($was_w) {
    					$was_w = 0;
					"<span class=$esc_pat{$pat}>";
				    } else {
    					$was_w = 0;
					"<\/span><span class=$esc_pat{$pat}>";
				    }
				}
			    } else {
        			"<\/span><span class=$esc_pat{$pat}>";
			    }
			} else {
			    print STDERR "Unknown ESC-sequence ESC[$1\;$2m\n"
			}
		    }
		}/ge;
    if ( $line =~ /\e\[((\d+;)?\d+\w)/ ) {
	print STDERR "Unknown ESC-sequence ESC[$1" }
    print $f_out $line;
}

print $f_out $q->end_pre, $q->hr,
	    "Converting time: ", time() - $time1, " seconds",
	    $q->end_html;

sub help
{
print <<END;
Log-Colorizer by Andrew [dikiy] Baznikin (dikiy\@mud.ru)
Convert ANSI log-files to HTML format

Usage:
    --help, -h, -?        - this help screen
    --help-style          - show used CSS class names (to write your own one)
    --from, -f  <file>    - input ANSI file  (default: STDIN)
    --to, -t  <file>      - output HTML file (default: STDOUT)
    --optimise, -o        - optimise HTML file
    --title <text>        - HTML page title  (default:"Colorized log")
    --codepage, -c <text> - set codepage for HTML file  (default: windows-1251)
    --style, -s <file>    - file to get CSS (Cascade Style Sheet) from
                                                        (default: built-in)
							
END
exit;
}

sub help_style
{
print <<END;
Log-Colorizer by Andrew [dikiy] Baznikin (dikiy\@scn.ru)
Convert ANSI log-files to HTML format

ESC-secuense to CSS class-name conversion:

END
foreach $_ (sort keys %esc_pat) { print "    <ESC>[$_ -> $esc_pat{$_}\n"};
exit;
}
