# TagRoutines module
# =========== ======


# Exported Routines:
#	&TRInit		-- Initializes the module
#	&TRHandleTag	-- Implements the actions implied
#			   by an HTML tag.

# Module variables:
#	@tr_tagStack	-- a stack of the HTML tags for
#			   constructs that have been started
#			   but not yet completed.
#
#	@tr_itemStack	-- a stack of labels, one per nested
#			   <OL> construct that has been
#			   started but not yet completed.
#			   Each entry is a number, giving the next
#			   label to print with a <LI> tag.
#
#	$tr_preDepth	-- a counter to indicate the number of
#			   <PRE> constructs that have been started
#			   but not finished.  (Nesting of <PRE>
#			   constructs is probably illegal, but we
#			   will handle it sensibly.)

sub TRInit {
    @tr_tagStack = ();
    @tr_itemStack = ();
    $tr_preDepth = 0;
}


# TRHandleTag processes a HTML tag.
#
# Input:	The argument is a complete HTML tag with angle
#		brackets and optional modifiers such as
#		    "<p align=center>" or "</BLOCKQUOTE>"
#

sub TRHandleTag {
    local($tagText) = @_;
    local($tagName,$mode,$poppedTag);

    # remove opening angle bracket and any following white space
    $tagText =~ s/^<\s*//;
    # remove the closing angle bracket
    $tagText =~ s/>$//;

    if ($tagText =~ /^\//) {
	$mode = 'END';
	$tagText = substr($tagText,1,length($tagText)-1);
    } else {
	$mode = 'START';
    }

    
    # extract just the tag (omitting any modifiers)
    # and convert that tag to upper-case letters
    $tagName = $tagText;
    $tagName =~ tr/a-z/A-Z/;
    $tagName =~ s/\W.*//;

    if ($mode eq 'START') {
	push(@tr_tagStack, $tagName);
	&tr_TagDispatch($tagName, $mode, $tagText);
    } else {
	# pop tags from $tr_tagStack and terminate the constructs,
	# until we reach the tag we were given.
	for( ; ; ) {
	    $poppedTag = pop(@tr_tagStack);
	    last unless($poppedTag);	# quit if stack was empty
	    &tr_TagDispatch($poppedTag, 'END', '');
	    if ($poppedTag eq $tagName) {
	        last;	# quit if we handled the desired tag
	    }
	}
    }
}


# Input Arg 1:	a HTML tagname in uppercase (e.g. "OL")
# Input Arg 2:	either 'START' or 'END' indicating whether
#		the HTML construct is being started or ended
# Input Arg 3:	the full text of the HTML tag in the same case
#		as in the input but excluding angle brackets
#		(e.g. "P align=CENTER").
sub tr_TagDispatch {
    local($tag, $mode, $wholeText) = @_;
    if ($DEBUG & 2) {
	print "Dispatching tag: $tag($mode)\n";
    }
    if ($tag eq 'OL') {
	&tr_OL($mode);
    } elsif ($tag eq 'LI') {
	&tr_LI($mode);
    } elsif ($tag eq 'BLOCKQUOTE') {
	&tr_BLOCKQUOTE($mode);
    } elsif ($tag =~ /^H[1-6]/) {
	&tr_HEADING($mode, substr($tag,1,1)+0);
    } elsif ($tag eq 'TITLE') {
	&tr_HEADING($mode, 0);
    } elsif($tag eq 'P') {
	&tr_P($mode);
    } elsif ($tag eq 'PRE') {
	&tr_PRE($mode);
    } else {
	&tr_UnimplementedHTML($mode,$wholeText);
    }
}


# tr_HEADING implements the H1, H2 ... H6 tags
# Also handles TITLE (as equivalent to a H0 tag).
sub tr_HEADING {
    local($mode, $level) = @_;
    &OUFlushOutput();
    &OUFlushOutput();
}

# tr_P implements the P tag
sub tr_P {
    local($mode) = @_;
    &OUFlushOutput();
}

# tr_PRE implements the PRE tag
sub tr_PRE {
    local($mode) = @_;

    if ($mode eq 'START') {
	if ($tr_preDepth == 0) {
	    &OUStartPre();
	}
	$tr_preDepth++;
    } else {
	$tr_preDepth--;
	if ($tr_preDepth == 0) {
	    &OUEndPre();
	}
    }
    &OUFlushOutput();
}


# tr_OL implements the <OL> tag
sub tr_OL {
    local($mode) = @_;

    if ($mode eq 'START') {
	push(@tr_itemStack, 1);
	$OUIndentLevel++;
    } else {
	pop(@tr_itemStack);
	$OUIndentLevel--;
    }
    &OUFlushOutput();
}

# tr_LI implements the <LI> tag
sub tr_LI {
    local($mode) = @_;
    local($label,$nest,$x);

    $nest = @tr_itemStack;
    if ($mode eq 'START' && $nest > 0) {
	$OUIndentLevel--;
	&OUFlushOutput();
	$label = pop(@tr_itemStack);
	$x = $label . '. ';
	if (length($x) < $OUIndentIncrement) {
	    $x .= ' ' x ($OUIndentIncrement-length($x));
	}
	&OUAppendString($x);
	$label++;
	push(@tr_itemStack, $label);
	pop(@tr_tagStack);	# because there is no matching </LI>
	$OUIndentLevel++;
    }
}

# tr_BLOCKQUOTE implements the <BLOCKQUOTE> tag
sub tr_BLOCKQUOTE {
    local($mode) = @_;
    if ($mode eq 'START') {
	$OUIndentLevel++;
    } else {
	$OUIndentLevel--;
    }
    &OUFlushOutput();
}

# tr_UnimplementedHTML handles any unimplemented HTML tag
# We could print a warning message.
sub tr_UnimplementedHTML {
}

1;
