package AutodocSupport::DumpDocs;

###############################################################################
###############################################################################
##
##    Written by Adam Swift (c) 1995 by Information Technology Solutions
##                           All rights reserved.
##
##	  This notice may not be removed from this source code.
##
##    This program is included in the MiscKit by permission from the author
##    and its use is governed by the MiscKit license, found in the file
##    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
##    for a list of all applicable permissions and restrictions.
##
##    Because the AutoDoc is licensed free of charge, there is no warranty 
##    for the program.  Copyright holder, Information Technology Solutions, 
##    is providing this program "as is" and this program is distributed in 
##    the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
##    even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
##    PARTICULAR PURPOSE.
##
###############################################################################
###############################################################################

require 5.000;
require Exporter;
require AutodocSupport::LogDebug;
require AutodocSupport::ReadSource;
require AutodocSupport::GenerateRTF;
require "flush.pl";

@ISA      = qw(Exporter);
@EXPORT   = qw(dump_documentation
	       set_copyrightowner
	       copyrightowner
	       set_usetimestamp
	       usetimestamp
	       dumpdocs_version);

use AutodocSupport::LogDebug;
use AutodocSupport::ReadSource;
use AutodocSupport::GenerateRTF;

############################################################################
#
# GLOBAL VARIABLES THAT AFFECT DOCUMENTATION DUMP
#
#  $format_boldwords    The array of words to boldify in &format_paragraph
#  $format_italicwords  The array of words to italicize in &format_paragraph
#

$module_version = '$Revision: 1.0 $';
$module_version =~ s!(\$\w+: | \$)!!g;
$module_id	= '$Id: DumpDocs.pm,v 1.0 1995/07/28 16:01:59 aswift Exp $';
$module_id      =~ s!(\$\w+: | \$)!!g;
$module_name	= $module_id;
$module_name	=~ s!^([^\,]+).*$!$1!;

#############################################################################
#
# NAME:       module_version
#
# ACTION:     returns the version number of this module
#
# RETURN:     the module version
#
#############################################################################
sub module_version
{
    return "$module_name (rev-$module_version)";
}

##
# Stupid hack!
##
sub dumpdocs_version
{
    return module_version();
}


sub set_copyrightowner
{
    $copyrightowner = $_[0];
}

sub copyrightowner
{
    return $copyrightowner if (defined($copyrightowner));
    return "";
}

sub set_usetimestamp
{
    $usetimestamp = $_[0];
}

sub usetimestamp
{
    return $usetimestamp if (defined($usetimestamp)); 
    return 0;
}


###############################################################################
#
# DOCUMENTATION DUMPING TO OBJECT RTF FILE
#
#    Use the information scanned into the global object variables to create
#  a Rich Text Formatted documentation file, in the directory specified by
#  $dest_dir.
#

#
# Locate and write the documentation file for the object passed as the one
# argument to this subroutine. 
#
sub dump_documentation
{
    local ($obj_root, $obj_r, $opt_silent) = @_;

    dblog (0, "Writing documentation for:\t$obj_root");
    dblog (1, "Writing documentation to file: $obj_r");
    
    # open the documentation file
    if (!open(DUMPFILE, ">$obj_r")) {
	warn ("Can't open $obj_r: $!\n");
	return 0;
    } else {
	if (!$opt_silent) {
	    print ("autodoc producing $obj_r ... ");
	    flush (STDOUT);
	}
    }
    
    @format_boldwords = ("self", "nil", "super", "id", "NULL");

    # Header	
    dump_rtfheader();
    
    # Body
    dump_copyrightinfo();
    dump_objectname();
    dump_inheritsfrom_declaredin();
    dump_classdescription()
	if (!object_noobjectdefined());
    dump_typedefs();
    dump_defines();
    dump_macros();
    dump_functions();
    dump_globals();
    dump_instancevariables();
    dump_methodtypes();

    dump_classmethods(object_classmethods())
	if (object_classmethods());
    dump_instancemethods(object_instmethods())
	if (object_instmethods());
    
    # Footer
    dump_rtffooter();	

    # close the docuentation file and message the user
    close (DUMPFILE);
    if (!$opt_silent) {
	print ("done\n");
    }
    return 1;
}				


#
# Dump the instance methods with full formatting, setup the format_italicwords
# so that the method documentaiton italicizes the arguments to the method.
#
sub dump_instancemethods
{
    local (@obj_instmethods) = @_;
    local ($index, $meth, $methname);

    dump_section_title("Instance Methods");
    &dump ('\b0 \fs36 \s21 \li2493 \fi-1132 \fi-376 \fs28 \fs16 ');

    @obj_instmethods = sort bymethodname @obj_instmethods;

    for ($index = 0; $index < @obj_instmethods; $index ++) {
	$meth = $obj_instmethods[$index];
	$methname = "-";
	$methname .= extract_methodname ($meth);
	&dump_method ($meth, $methname);

	if ($index < (@obj_instmethods - 1 )) {
	    &dump_line ("\\fs16 \\\n", '\fs28 \pard \s19 \li2493 \fi-376 ',
			'\ri1007 \ql \f0 \fs28 \fs16 \\');
	    &dump_line ("\\\n\\");
	}
    }
}


#
# Dump the class methods with full formatting, setup the format_italicwords
# so that the method documentaiton italicizes the arguments to the method.
#
sub dump_classmethods
{
    local (@obj_classmethods) = @_;
    local ($index, $meth, $methname);

    dump_section_title ("Class Methods");
    &dump ('\b0 \fs36 \s21 \li2493 \fi-1132 \fi-376 \fs28 \fs16 ');

    @obj_classmethods = sort bymethodname @obj_classmethods;

    for ($index = 0; $index < @obj_classmethods; $index ++) {
	$meth = $obj_classmethods[$index];
	$methname = "+";
	$methname .= extract_methodname ($meth);
	&dump_method ($meth, $methname);

	if ($index < (@obj_classmethods - 1 )) {
	    &dump_line ("\\fs16 \\\n", '\fs28 \pard \s19 \li2493 \fi-376 ',
			'\ri1007 \ql \f0 \fs28 \fs16 \\');
	    &dump_line ("\\\n\\");
	}
    }
}


#
# dump a formatted method with documentation
#
sub dump_method
{
    local ($meth, $methname, $methname_raw, $meth_form, $methtype, $methdocs);
    local (%obj_methoddocs);
    
    $meth = $_[0];		# the full method declaration 
    $methname = $_[1];		# the abbrv. unique name
    $methname =~ m/^([\+\-])/;
    $methname_raw = $';		# methname_raw is methname w/o + or -
    $methtype = $1;		# methtype is just the + or -
    $meth_form = "";		# meth_form is the rtf formatted version.

    &dump_line ("\\fs29 \\b $methname_raw\\");
    &dump ('\s20 \li3249 \fi-1132 \fi-756 \f1 \b0 \fs28 ');

    # boldify the method name AFTER the return value type casting (if any)
    if ($meth =~ /^\(/) {
	$meth =~ s/^\([^\)]+\)//;
	$meth_form = $&;
    }
    $meth_form .= "\\b ";
    $meth =~ s/^[^\:]*//;
    $meth_form .= $&;

    undef (@format_italicwords);
    # format the method arguments, their types, and titles
    while ($meth =~ /^:/) {

	# extract the colon
	$meth =~ s/://;	
	$meth_form .= ":\\b0 ";

	# extract the type casting (if any)
	if ($meth =~ /^\s*\(/) {
	    $meth =~ s/\s*(\([^\)]+\))\s*//;
	    $meth_form .= "$1";
	}

	# extract the argument and push it into the @format_italicwords array
	$meth =~ s/\s*//;
	$meth =~ s/\S*//;
	push (@format_italicwords, $&);
	$meth_form .= "\\i $&\\i0 \\b ";

	# check for a title for the next argument
	if ($meth =~ /:/) {
	    $meth =~ s/([^:]*)//;
	    $meth_form .= "$1";
	}		
    } 

    # dump the formatted method to the file
    $meth_form .= "\\b0 \\\n";
    if ($methtype eq "-") {
	&dump ("{\\f3 -} $meth_form");
    } else {
	&dump ("+ $meth_form");
    }
    
    # dump the method documentation
    &dump_line ('\pard \s0 \li2116 \fi0 \ri1007 \ql \tx2494 \tx2872 ',
		'\tx3250 \fs16 \\');
    %obj_methoddocs = object_methoddocs();
    if (defined($obj_methoddocs{$methname}) && ## bbum
	$obj_methoddocs{$methname} ne "") {

	$methdocs = &format_paragraph ($obj_methoddocs{$methname});
	&dump_line ("\\fs28 $methdocs \\");
    } else {
	&dump_line ('\fs28 No method description. \\');
    }
    undef (@format_italicwords);

    return;
}


#
# Dump the formatted method names with block names before the methods they
# were assigned to.
#
sub dump_methodtypes
{
    local ($p1, $p1end, $p2, $index);
    local ($methname, $methname_raw, $methtype, $diddumpblock, $block);
    local (@obj_methodnames, %obj_methodblocks);

    @obj_methodnames = object_methodnames();

    return 
	if (scalar(@obj_methodnames) == 0);
   
    %obj_methodblocks = object_methodblocks();

    # configure rtf paragraph style strings
    $p1 = '\pard \s35 \li6148 \fi-4031 \ri1007 ';
    $p1 .= '\ql \tx6148 \tx9676 \tx10180 \fs16';
    $p2 = '\pard \s34 \li6652 \fi-503 \ri1007 \ql \tx9676 \tx10180';

    dump_section_title ("Method Types");
    dump_line ("\\fs36 \\f1 \\b0 \\fs28 ");
    $diddumpblock = 1;
    $p1end = ' '; # this changes after the first block

    for ($index=0; $index < @obj_methodnames; $index++) {
	$methname = $obj_methodnames[$index];

	# If there is a method block assigned to this method
	if (($block = $obj_methodblocks{$methname})) {
	    &dump ("$p1 $p1end\\fs28 $block");

	    # long block names push methods to the next line
	    if (length($block) > 30) {
		&dump ("\\\n\\fi0 ");
	    } else {
		&dump (" \t");
	    }
	    $diddumpblock = 1;
	} else {
	    &dump ("$p2 ") if ($diddumpblock == 1);
	    $diddumpblock = 0;
	}

	$methname_raw = $methname;
	$methname_raw =~ s/^([\+\-])//;
	$methtype = $1;

	if ($methtype eq "-") {
	    &dump_line ("{\\f3 -} $methname_raw\\");
	} else {
	    &dump_line ("+ $methname_raw\\");
	}
	$p1end = "\\\n";
    }
}


sub dump_section_title
{
    local ($title) = $_[0];

    dump_spacer();
    dump_line("\\fs36 $title\\\n\\fs16 \\ \n\\");
}


sub dump_defines
{
    local ($title, @names, %docs, %values);

    $title = "Symbolic Constants";
    @names = object_defines();
    %docs = object_definedocs();
    %values = object_definevals();
    dump_synopsis_description_section(*title, 
				      *names, 
				      *docs, 
				      *values,
				      's!(.*)!\\\b $1\\\b0!');
}


sub dump_macros
{
    local ($title, @names, %docs, %values, $bold_expr);

    $title = "Macro Definitions";
    @names = object_macros();
    %docs = object_macrodocs();
    %values = {};
    $bold_expr = 's!(\\S+\\s*\\()([^\\(]*)\\)$!\\\b $1\\\b0$2\\\b \)\\\b0!';
    dump_synopsis_description_section(*title, 
				      *names, 
				      *docs, 
				      *values,
				      $bold_expr);
}


sub dump_functions
{
    local ($title, @names, %docs, %values, $bold_expr);

    $title = "Functions";
    @names = object_functions();
    %docs = object_functiondocs();
    %values = {};
    $bold_expr = 's!(\\S+\\s*\\()([^\\(]*)\\)$!\\\b $1\\\b0$2\\\b \)\\\b0!';
    dump_synopsis_description_section(*title, 
				      *names, 
				      *docs, 
				      *values,
				      $bold_expr);
}


sub dump_globals
{
    local ($title, @names, %docs, %values, $name);

    $title = "Global Variables";
    @names = object_globals();
    %docs = object_globaldocs();
    %values = {};
    dump_synopsis_description_section(*title, 
				      *names, 
				      *docs, 
				      *values,
				      's!(\\S+)\\;$!\\\b $1\\\b0\\;!');
}


sub dump_typedefs
{
    local ($title, @names, %docs, %values);

    $title = "Defined Types";
    @names = object_typedefs();
    %docs = object_typedefdocs();
    %values = object_typedefvals();
    dump_synopsis_description_section(*title, 
				      *names, 
				      *docs, 
				      *values,
				      's!(.*)!\\\b $1\\\b0!');
}


sub dump_synopsis_description_section
{
    local (*title, *names, *docs, *values) = @_;
    local ($define, $docs, $value, $show_sysnopsis, $name_expr);
    local ($i, $max, $name);
    
    return if (!scalar(@names));
    $name_expr = ""
	if ((scalar(@_) < 5) || (($name_expr = $_[4]) eq ""));

    dump_section_title($title);

    $show_synopsis = 1;
    $show_docs = 0;
    $max = scalar (@names);
    $docs = "";

    for ($i = 0; $i < $max; $i++) {
	$name = $names[$i];

	if (defined($values{$name})) {
	    local ($valline, @valarray, $indent);

	    $value = "\t$values{$name}";
	    $value =~ s!([\{\}])!\\$1!g;
	    $value =~ s!\n!\\\n\t\t!g;
	    $value = " $value ";
	    $value =~ s!(\W)$name(\W)!$1\\b $name\\b0$2!;
	    $value =~ s!^ | $!!g;

	    # do some fancy indentation on the value (if curlies are there)
	    if ($value =~ m!\{!) {
		$indent = "";
		@valarray = split(m!\n!, $value);
		foreach $valline (@valarray) {
		    $indent =~ s!\t!!
			if ($valline =~ m!\}!);
		    $valline = "$indent$valline"
			if ($indent =~ m!\t!);
		    
		    if ($valline =~ m!\{!) {
			$indent = "\t$indent";
			$valline =~ s!\{\s*(\S+)!\{$indent$1!;
		    }
		}
		$value = join("\n", @valarray)
	    }
	} else {
	    $value = "";
	}

	if ($show_synopsis) {
	    dump_line ('\pard\tx2116\tx6148\tx6794\tx7440\tx8086\tx9378',
		       '\fs20\li6148\fi-4421', "\\fc0\\cf0 SYNOPSIS \\");
	    $show_synopsis = 0;
	}
	if ($name_expr ne "") {
	    local ($fname) = $name;
	    # dblog(-5, "expr = $name_expr");
	    eval("\$fname =~ $name_expr");
	    warn ("Error formatting names: $@")
		if ($@ ne "");
	    dump_line ("\t\n\\f1\\b0\\fs28$fname$value\\");
	} else {
	    dump_line ("\t\n\\f1\\b0\\fs28$name$value\\");
	}
	
	$show_docs = 1
	    if (($i == ($max - 1)) || defined($docs{$names[$i+1]}));
	$docs = format_paragraph ($docs{$name})
	    if (defined($docs{$name}));

	if (($docs ne "") && ($show_docs == 1)) {
	    dump_line ('\pard \fs16 \li2116 \fi-389 \tx2116 \fc0 \cf0 \\');
	    dump_line ("\\f0 \\b \\fs20 DESCRIPTION\n\\");
	    dump_line ("\\f1 \\b0 \\fs28 \t", $docs, " \\\n");
	    &dump_line ('\pard\f0\b\fs16\li2100\fc0\cf0');
	    &dump_line ("\\fs16 \\\n\\") if ($i != ($max - 1));
	    $show_docs = 0;
	    $show_synopsis = 1;
	}
    }
}


#
# Dump the instance varaibles and their descriptions to the documentation file
# descriptions are formatted by format_words
#
sub dump_instancevariables
{
    local ($ivar, $lastivar, $docs);
    local (@obj_ivars, %obj_ivartypes, %obj_ivardocs);


    @obj_ivars = object_ivars();
    return 
	if (scalar(@obj_ivars) == 0);
    
    %obj_ivartypes = object_ivartypes();
    %obj_ivardocs = object_ivardocs();

    dump_section_title ("Instance Variables");
    &dump ('\fs36 \pard \s18 \li2116 \fi0 \ri1007 \ql \tx2872 \f1 \b0 \fs28 ');
    foreach $ivar (@obj_ivars) {
	dump_line ("$obj_ivartypes{$ivar}\\b $ivar\\b0 ;\\");
    }

    dump_line ('\pard \s11 \li6148 \fi-4031 \ri1007 \ql \tx6148 \tx9676 ',
		"\\tx10180 \\fs16 \\\n\\\n\\");

    $lastivar = $obj_ivars[$#obj_ivars];
    foreach $ivar (@obj_ivars) {
	$docs = &format_words ($obj_ivardocs{$ivar});
	dump_line ("\\fs28 $ivar \t$docs\\");
	dump_line ('\fs16 \\') 
	    if ($ivar ne $lastivar);
    }
}


#
# Dump the formatted class description to the docs.  Boldify any instance
# variables or methods that appear in the description
#
sub dump_classdescription
{
    local ($classdesc);

    # Problem here may be that both an obj and category are defined
    # in the same .m file.  Maybe figuring out how to dump two
    # seperate .rtf files would be optimal, but until then we should
    # allow for both to be included in the same .m and thus .rtf.
    dump_section_title ("Class Description") 
	if (object_inherits());
    dump_section_title ("Category Description") 
	if (object_category());
    &dump ('\fs36 \pard \s0 \li2116 \fi0 \ri1007 \ql \tx2494 ');
    &dump ('\tx2872 \tx3250 \f1 \b0 \fs28 \fs16 \fs28 ');

    $classdesc = &format_paragraph (object_classdocs());
    &dump_line ("$classdesc");

    &dump_line ("\\fs16 \\\n\\fs28");
}


#
# Reformat the text passed to this subroutine to turn the newline markers
# into real newlines, and generally make paragraphs look better.
#
sub format_paragraph
{    
    local ($paragraph, $word, $listRTF);
    
    $listRTF = '\pard \s11 \li7648 \fi-5131 \ri1007 \ql \tx7648 ';
    $listRTF .= "\\tx10180 \\fs16 \\\n \\fs28 ";
    $paragraph = $_[0];

    # Make all space-runs into single spaces
    $paragraph =~ s/ +/ /g;

    # make all spaces following a period (+ end paren) double spaces
    $paragraph =~ s/\.(\)?) /\.$1  /g;

    # Make newline markers into rtf compatible newlines
    $paragraph =~ s/\\n\s*/\\\n\\fs16 \\\n\\fs28 \\fs16 \\fs28 /g;

    # Boldify and Italicize the words, THIS REFORMATS '}' CURLY BRACES as '\}'
    $paragraph = &format_words ($paragraph); 

    # Find List encodings and format the lines THE CURLY IS REPLACED WITH ' '
    $paragraph =~ s/\_\{\s*([^\}\s]+)\s*([^\}]*)\}\s*/\{$listRTF $1\t$2 \}\n /g;

    return $paragraph;
}


#
# format special words as bold or italics
#
sub format_words
{
    local ($text) = " $_[0] ";		# Add spaces to help with matching 

    # boldify text of the form #{the text}
    $text =~ s/\#\{([^\}]+)\}/\\b $1\\b0 /g;

    # italicize text of the form %{the text}
    $text =~ s/\%\{([^\}]+)\}/\\i $1\\i0 /g;

    # boldify words which start with a "#" in front of them
    $text =~ s/([^\\])\#([\w\:]+)/$1\\b $2\\b0 /g
	while ($text =~ m/[^\\]\#[\w\:]+/);

    # italicize words which start with a "%" in front of them
    $text =~ s/([^\\])\%([\w]+)/$1\\i $2\\i0 /g
	while ($text =~ m/[^\\]\%[\w\:]+/);

    # italicize words in the $format_italicwords array
    foreach $word (@format_italicwords) {
	$text =~ s/(\W)$word(\W)/$1\\i $word\\i0 $2/g;
    }

    # boldify words in the $format_boldwords array
    foreach $word (@format_boldwords) {
	$text =~ s/(\W)$word(\W)/$1\\b $word\\b0 $2/g;
    }

    # Reformat curly braces so they don't prematurely end the doc.
    $text =~ s/\}/\\\}/g;

    # Reformat '\%' and '\#' to just '%' and '#'
    $text =~ s/\\([\#\%])/$1/g;

    # Remove the spaces we added before.
    $text =~ s/^\s+//;
    $text =~ s/\s+$//;
    return $text;
}


#
# return an ordered array of method names with no prepended + or -
#
sub format_methodnames
{
    local (@boldarray, $word);

    @boldarray = @_;

    foreach $word (@boldarray) {
	$word =~ s/^[\+\-]//;
    }
    # reverse sort the method names, so that longer names are matched before
    # shorter names with the same substring
    @boldarray = reverse (sort (@boldarray));

    return @boldarray;
}


#
# dump the formatting and text necessary to put the inheritance and
# declaration location in the docs
# This has been expanded to allow categories...
#
sub dump_inheritsfrom_declaredin
{
    local ($obj_inherits);

    if (object_noobjectdefined()) {
	&dump_line ('\fs56 \pard \s17 \li4888 \fi-2771 \ri1007 \ql ',
		    '\tx4888 \f1 \b0 \fs28 \fs16 \fs28 \f0 \b \fs28 ',
		    "Resource Collection \\");
    } else {
	$obj_inherits = object_inherits();
	if ($obj_inherits ne "") {
	    local ($obj_name) = object_name();

	    $obj_inherits = "none \\i ($obj_name is a root class)\\i0"
		if ($obj_inherits =~ m!^none$!);
	    &dump_line ('\fs56 \pard \s17 \li4888 \fi-2771 \ri1007 \ql ',
			'\tx4888 \f1 \b0 \fs28 \fs16 \fs28 \f0 \b \fs28 ',
			"Inherits From:\t\\b0 \\fs28 \\f1 $obj_inherits\\");
	} else {
	    if (object_category()) {
		&dump_line ('\fs56 \pard \s17 \li4888 \fi-2771 \ri1007 \ql ',
			    '\tx4888 \f1 \b0 \fs28 \fs16 \fs28 \f0 \b \fs28 ',
			    "Category Name:\t\\b0 \\fs28 \\f1 ",
			    object_category(), "\\");
	    }
	}
    }
    &dump_line ('\fs16 ');
    &dump_line ('\fs28 \s10 \fs16 \fs28 \f0 \b \fs28 ',
		"Declared In:\t\\b0 \\fs28 \\f1 ",
		object_declaredin(), "\\");
    &dump ("\\fs16 \\\n\\fs28 ");
}


#
# dump the formatting and text necessary to put the object name in the docs
#
sub dump_objectname
{
    &dump_line ('\pard \s0 \li2116 \fi0 \ri1007 \ql \tx2494 \tx2872 \tx3250 ',
		'\f1 \fs28 \fs16 \\', "\n\\fs28 \\\n\\fs16 \\");
    &dump_line ('\fs28 \pard \s5 \li2116 \fi0 \ri1007 \ql \f0 \b ',
		"\\fs56 ", object_name(), " \\");
    &dump_line ("\\fs16 \\\n\\\n\\\n\\\n\\\n\\");
}


#
# dump the formatting and text necessary to put the copyright info in the docs
#
sub dump_copyrightinfo
{
    local ($obj_copyowner);
    local ($version, $copyright);
    local (@ta, $timestamp);

    $obj_copyowner = copyrightowner();
    $timestamp = "";
    if (usetimestamp()) {
	@ta = localtime(time);
	$timestamp = "$ta[4]/$ta[3]/$ta[5] - $ta[2]";

	# do minutes so zeros show up nicely
	$timestamp = "$timestamp:$ta[1]" if ($ta[1] > 9);
	$timestamp = "$timestamp:0$ta[1]" if ($ta[1] < 10);
	$timestamp = "$timestamp0" if ($ta[1] == 0);

	# do seconds so zeros show up nicely
	$timestamp = "$timestamp:$ta[0]" if ($ta[0] > 9);
	$timestamp = "$timestamp:0$ta[0]" if ($ta[0] < 10);
	$timestamp = "$timestamp0" if ($ta[0] == 0);
	$timestamp = "$timestamp";
    }

    &dump_line ('\li0 \fi0 \ri0 \ql \sb0 \f1 \fs24 ');
    $version = object_version();
    $version .= " " if ($version ne "");
    $copyright = $obj_copyowner ? " by $obj_copyowner" : "";

    &dump_line ("${version}Copyright \\f3 \\'e3\\f1 ", object_year(), 
		"$copyright, All Rights Reserved.  $timestamp\\");
    
    &dump_line ("\\");
}


#
# Write out all the arguments to the DUMPFILE and finish it off with a newline
#
sub dump_line
{
    local ($buffer);
    foreach $buffer (@_) {
	print DUMPFILE ("$buffer");
    }
    print DUMPFILE ("\n");
}


#
# Write out all the arguments to the DUMPFILE 
#
sub dump
{
    local ($buffer);
    foreach $buffer (@_) {
	print DUMPFILE ("$buffer");
    }
}


#
# Dump the standard spacer to the docs
#
sub dump_spacer
{
    &dump_line ('\pard \s13 \li1360 \fi0 \ri1007 \ql \f0 \b \fs36 \fs16 \\');
    &dump_line ("\\\n\\\n\\\n\\");
}


#
# Write the Rich Text Format header, to start the documentation file.  This
# RTF header sets up several paragraph styles, but don't assume I know what
# is going on here.  I'll admit, this is VOODOO to me!
#
sub dump_rtfheader
{
    dump_line (rtf_fileheader());
    dump_line (rtf_fonttable());
    dump_line (rtf_stylesheet());
}


#
# Write the Rich Text Format footer, to complete the documentation file
#
sub dump_rtffooter
{
    &dump_line (rtf_filefooter());
}


#
# Compares the methods passed in $a and $b for alphabetical sorting, ignoring
# the typecasting
#
sub bymethodname
{
    local ($one, $two);
    if ($a =~/^\([^\)]+\)\s*/) {
	$one = $';
    } else {
	$one = $a;
    }
    if ($b =~/^\([^\)]+\)\s*/) {
	$two = $';
    } else {
	$two = $b;
    }
    return $one cmp $two;
}



1;
