#!/usr/bin/perl
use strict;
my($app_svnid) = '$HeadURL$ $LastChangedRevision$';
#  Allow bare words, so &ade_err_error() calls look nicer.
no strict 'subs';
use lib substr `ade-config ade_include_prefix`,0,-1;

use ADE;
use Getopt::Long qw(:config no_ignore_case);

my(%ademan2html_defined_errors) = (
);

#  Variables for options
my($opt_fragment);

sub ademan2html
{
    my($errstack_ref) = @_;
    my($rc, $listpaths, $optval);
    my(@buffer, $count, $mode, $c);

    ###########################################################################
    #
    #  Set ADE options
    #
    ###########################################################################

    #  Register application-specific errors
    &ade_err_registerdefderrs(\%ademan2html_defined_errors);

    ##########################################################################
    #
    #  Process options
    #
    ##########################################################################

    #  Defaults for options
    $opt_fragment = undef;

    #  Register options
    &ade_err_debug($errstack_ref, 10, "ademan2html: registering ademan2html options ...");
    if (($rc=&ade_opt_register($errstack_ref, undef, "fragment", "main::ademan2html_opt_handler_%s")) != $ade_err_ok) {
        return($rc);
    }

    #  Register handler functions
    &ade_err_debug($errstack_ref, 10, "ademan2html: registering message handler functions ...");
    if (($rc=&ade_msg_register($errstack_ref, \&ademan2html_usage, \&ademan2html_version, \&ademan2html_listpaths)) != $ade_err_ok) {
        return($rc);
    } 

    #  Process options
    &ade_err_debug($errstack_ref, 10, "ademan2html: processing options ...");
    if (($rc=&ade_opt_process($errstack_ref)) != $ade_err_ok) {
        return($rc);
    }

    ##########################################################################
    #
    #  Process arguments
    #
    ##########################################################################

    &ade_err_debug($errstack_ref, 10, "ademan2html: processing arguments ...");
    &ade_msg_usage($errstack_ref) if (defined($ARGV[0]));

    ##########################################################################
    #
    #  Guts start here
    #
    ##########################################################################

    open(PIPE, "nroff -U -man|") || &ade_err_error($errstack_ref, "nroff: can't execute");
    if (!$opt_fragment) {
        print "<html>\n";
        print "<body>\n";
    }
    if (($rc=&ade_spc_autogendheader($errstack_ref, \*STDOUT, "<!--", "-->", undef)) != $ade_err_ok) {
        close(PIPE);
        return($rc);
    }

    print "<pre>\n";
    for ($count=0,$mode="normal";defined($c = $buffer[$count++] = getc PIPE);) {
    
        &ade_err_debug($errstack_ref, 10, "[READ:$c]");
    
        if ($count == 1) {
    
            if ($buffer[$count-1] eq " ") {
                &ade_err_debug($errstack_ref, 10, "[1SP]");
                &safeprint($errstack_ref, "$buffer[--$count]");
    
            } elsif ($buffer[$count-1] eq "\n") {
                &ade_err_debug($errstack_ref, 10, "[1NL]");
                #print "<br>";
                &safeprint($errstack_ref, "$buffer[--$count]");
    
            } elsif ($buffer[$count-1] eq "") {
                &ade_err_error($errstack_ref, "control sequence starts with ^H");
    
            } else {
                #  else must wait for more
                &ade_err_debug($errstack_ref, 10, "[1WAIT]");
    
            }
    
        } elsif ($count == 2) {
        
            if ($buffer[$count-1] eq " ") {
                &ade_err_debug($errstack_ref, 10, "[2SPNL]");
                &switchto($errstack_ref, "normal");
                &safeprint($errstack_ref, "$buffer[0]");
                &safeprint($errstack_ref, "$buffer[1]");
                $count = 0;
    
            } elsif ($buffer[$count-1] eq "\n") {
                &ade_err_debug($errstack_ref, 10, "[2SPNL]");
                &switchto($errstack_ref, "normal");
                &safeprint($errstack_ref, "$buffer[0]");
                #print "<br>";
                &safeprint($errstack_ref, "$buffer[1]");
                $count = 0;
    
            } elsif ($buffer[$count-1] eq "") {
    
                ; # must wait for end of X^H? sequence
                &ade_err_debug($errstack_ref, 10, "[2WAIT]");
    
            } else {
                &ade_err_debug($errstack_ref, 10, "[2NORMSHUF]");
                &switchto($errstack_ref, "normal");
                #  print oldest char and shuffle
                &safeprint($errstack_ref, "$buffer[0]");
                $buffer[0] = $buffer[1];
                $count--;
             
            }
    
        } elsif ($count == 3) {
    
            if ($buffer[$count-1] eq " " or $buffer[$count-1] eq "\n") {
                
                &ade_err_error($errstack_ref, "<char>^H{<space>|<newline>: invalid control sequence");
    
            } elsif ($buffer[0] eq "_") {
                &ade_err_debug($errstack_ref, 10, "[3ITALIC]");
                &switchto($errstack_ref, "italic");
                &safeprint($errstack_ref, "$buffer[2]");
                $count = 0;
    
            } elsif ($buffer[$count-1] eq $buffer[0]) {
                &ade_err_debug($errstack_ref, 10, "[3BOLD]");
                &switchto($errstack_ref, "bold");
                &safeprint($errstack_ref, "$buffer[0]");
                $count = 0;
    
            } elsif ($buffer[$count-1] eq "o" && $buffer[0] eq "+") {
                &ade_err_debug($errstack_ref, 10, "[BULLET]");
                &switchto($errstack_ref, "normal");
                &safeprint($errstack_ref, "o");
                $count = 0;
    
            } else {
                &ade_err_error($errstack_ref, "$buffer[0]^H$buffer[2]: invalid control sequence");
    
            }
    
        } else {
            &ade_err_error($errstack_ref, sprintf("%s: invalid control sequence", join("", @buffer)));
        }
    }
    
    if ($count == 0) {
    
        ; # nothing to do
        
    } elsif ($count == 1) {
    
        &switchto($errstack_ref, "normal");
        &safeprint($errstack_ref, "$buffer[--$count]");
        
    } elsif ($count == 2) {
    
        &ade_err_error($errstack_ref, "$buffer[0]^H: control sequence incomplete");
    
    }
    print "</pre>\n";
    if (!$opt_fragment) {
        print "</body>\n";
        print "</html>\n";
    }
    close(PIPE);

    return $ade_err_ok;
}

sub ademan2html_opt_handler_fragment
{
    my($errstack_ref) = @_;

    $opt_fragment = 1;

    return $ade_err_ok;
}

sub ademan2html_version
{
    my($errstack_ref, $version_text_ref) = @_;

    return(&ade_smf_extractversionfromsvnstring($errstack_ref, $app_svnid, $version_text_ref));
}

sub ademan2html_listpaths
{
    my($errstack_ref, $pathlist_text_ref) = @_;
    my($rc);

    ${$pathlist_text_ref} = undef;

    return($ade_err_ok);
}

sub ademan2html_usage
{
    my($errstack_ref, $usage_text_ref, $passno) = @_;

    if ($passno == 1) {
        ${$usage_text_ref} = "<srcdir>\n";
    } elsif ($passno == 2) {
        ${$usage_text_ref} = "                     --fragment              omit <html> and <body> enclosure\n";
    }

    return($ade_err_ok);
}

sub safeprint
{
    my($errstack_ref, $c) = @_;

    if ($c eq ">") {
        print "&gt;";

    } elsif ($c eq "<") {
        print "&lt;";

    } else {
        print $c;
    }

    return($ade_err_ok);
}

BEGIN {
    #  Function-static variables
    my($current_mode) = "normal";

    sub switchto
    {
        my($errstack_ref, $mode) = @_;
    
        if ($mode eq $current_mode) {
            return($ade_err_ok);
        }
    
        if ($current_mode eq "bold") {
            print "</b>";
            $current_mode = "normal";
        } elsif ($current_mode eq "italic") {
            print "</i>";
            $current_mode = "normal";
        }
    
        if ($mode eq "bold") {
            print "<b>";
            $current_mode = "bold";
        } elsif ($mode eq "italic") {
            print "<i>";
            $current_mode = "italic";
        }

        return($ade_err_ok);
    }
}

&ade_gep_main(\&ademan2html);
