# $File: //member/autrijus/Pod-HtmlHelp/HtmlHelp.pm $ $Author: autrijus $
# $Revision: #2 $ $Change: 672 $ $DateTime: 2002/08/16 18:51:54 $

=head1 NAME

Pod::HtmlHelp - Interface with Microsoft's HtmlHelp system

=head1 SYNOPSIS

    use Pod::HtmlHelp;
    pod2chm([options]);

=head1 DESCRIPTION

This module creates HtmlHelp from HTML or POD source (including the
Pod in PM library files) using Microsoft's HtmlHelp compiler. This
creates the intermediate project files and from those creates the
htmlhelp windows 32-bit help files.

=head1 FUNCTIONS

The individual functions that were designed with working with
html help files rather than the Perl htmlhelp documentation are
deprecated in favor of doing things with a single command. Some
of them need work in order to work again.

=over 4

=item MakeHelp

Turns a single html page into htmlhelp document.

=item MakeHelpFromDir

Turns a directory's worth of html pages into a single htmlhelp document.

=item MakeHelpFromTree

Turns a tree's worth of html pages into a single htmlhelp document.

=item MakeHelpFromHash

Creates an htmlhelp document where the labels on the folders are passed
into the program. Useful for labels like Tk::Whatsis::Gizmo to replace
the default ones looking like c:/perl/lib/site/Tk/Whatsis/Gizmo.

=item MakeHelpFromPod

Turns a single Pod or pm document into htmlhelp document.

=item MakeHelpFromPodDir

Turns a dir's worth of Pod or pm into a single htmlhelp document.

=item MakeHelpFromPodTree

Turns a tree's worth of Pod or pm into a single htmlhelp document.

=item MakeHelpFromPodHash

Like MaheHelpFromHash() but for Pod instead of html.

=item MakePerlHtmlIndex

Creates an HTML version of an index or TOC for perl help.

=item MakePerlHtml

Does everything for perl HTML works.

=back

=head1 CONFIG.PM

This library makes use of Config.pm to know where to get its stuff.

=head1 HHC.EXE

This library makes use of the HtmlHelp compiler by microsoft.

=head1 VARIABLES

=over 4

=item $HtmlHelp::CSS

Determines the stylesheet to be used for the htmlhelp files. Default
is the ActiveState common stylesheet. This variable can be set to
an empty string to allow for just plain old HTML with nothing fancy.

Default is perl.css.

=item $HtmlHelp::COMPILER

Complete path and file name of the HtmlHelp compiler from Microsoft.
This is REQUIRED for this library to run. It defaults to it's install
directory within <lib>/HtmlHelp. Feel free to move this in $COMPILER
if you have the HtmlHelp workshop from Microsoft and you want to
use the compiler from a different location.

=item $HtmlHelp::FULLTEXTSEARCH

Whether to create full text search. Defaults to true.

=item $HtmlHelp::CLEANUP

Whether to clean up temporary files (and html files if building
from raw Pod) after building the htmlhelp. This can be useful,
for example, when you need to keep the intermediate files created
by the process for inclusion into a collective help file.

=back

=head1 HISTORY

=over 4

=item 1.0.0 pete

First final release, went out with (ActiveState Perl) 502

=item 1.0.1 pete

Temporary, removed CSS insertion in favor of just adding a link to the
css, since it's being built on the user's machine now; and temporarily
added the hardcoded contents of the main toc to the built toc until I
have time to build it codewise.

=item 1.0.2 gsar

Fixed much brokenness.  Much ugliness remains.

=item 1.1 autrijus

Adapted for pod2chm use.

=back

=cut

#####################################################################

package Pod::HtmlHelp;
$Pod::HtmlHelp::VERSION = '1.1';

#####################################################################
use Config;
use File::Copy;
use File::Basename;
use File::Path;
use Pod::WinHtml;

#####################################################################
# Variables
my $CLEANUP = 1;
my $MAKE_HTML_FOR_HHELP = 0;
my $FULLTEXTSEARCH = 1;
my $LIB = $Config{'privlib'}; $LIB =~ s{\\}{/}g;
my $SITELIB = $Config{'sitelib'};
my $HTMLHELP = $LIB; $HTMLHELP =~ s{(\\|/)lib}{/HtmlHelp}i;
my $COMPILER = "$LIB/HtmlHelp/hhc.exe";
my $HTML = $LIB; $HTML =~ s{(\\|/)lib}{/Html}i;
my $TEMP = "$HTMLHELP/Temp";
my $MERGE_PACKAGES = 0;

#####################################################################
# Function PreDeclarations
use subs qw{
    RunCompiler MakeHelpFromPod MakeHelpFromPodDir MakeHelpFromDirMakePerlHtml
    MakePerlHtmlIndexCaller MakePerlHtmlIndex GetHtmlFilesFromTree MakePerlHelp
    MakePerlHelpMain MakeHelpFromPodTree MakeHtmlTree MakeHelpFromTree
    GetHtmlFileTreeList MakeHelpFromHash MakeModuleTreeHelp MakeHelp BackSlash
    ExtractFileName ExtractFilePath MakePackageMainFromSingleDir
    MakePackageMain MakePackages CopyDirStructure GetFileListForPackage
    CreateHHP CreateHHC CreateHHCFromHash
};

#####################################################################
# FUNCTION      RunCompiler
# RECEIVES      Project file to compile
# RETURNS       None
# SETS          None
# EXPECTS       $COMPILER, hhc and hhp files should be there
# PURPOSE       Runs the HtmlHelp compiler to create a chm file
sub RunCompiler {
    my $projfile = BackSlash(shift);
    my $compiler = BackSlash($COMPILER);

    print "Trying \"$compiler $projfile\"\n";
    qx($compiler $projfile);
}

#####################################################################
# FUNCTION      MakeHelpFromPod
# RECEIVES      Helpfile (no path), Working directory, Output
#               directory (path for chm file), Files to include
# RETURNS       Results from running MakeHelp
# SETS          None
# EXPECTS       None
# PURPOSE       Takes pod/pm files, turns them into html, and then
#               into Htmlhelp files.
sub MakeHelpFromPod {
    my ($helpfile, $workdir, $outdir, @podfiles) = @_;
    my $htmlfiles;
    my $htmlfile;
    my $podfile;

    foreach $podfile (@podfiles) {
	$podfile =~ s{\\}{/}g;
        $htmlfile = $podfile;
        $htmlfile =~ s{(^/]*)\....?$}{$1\.html};
        push(@htmlfiles, $htmlfile);
        pod2html("--infile=$podfile", "--outfile=$htmlfile");
    }

    @htmlfiles = grep{-e $_} @htmlfiles;

    unless(@htmlfiles) {
        $! = "No html files were created";
        return 0;
    }

    return MakeHelp($helpfile, $workdir, $outdir, @htmlfiles);
}

#####################################################################
# FUNCTION      MakeHelpFromPodDir
# RECEIVES      Helpfile (no extension), Working directory, Output
#               directory (for the Helpfile), Directory to translate
# RETURNS       1|0
# SETS          None
# EXPECTS       None
# PURPOSE       Takes a directory's worth of pod/pm files and turns
#               them into html and then a single chm file
sub MakeHelpFromPodDir {
    my ($helpfile, $workdir, $outdir, $fromdir) = @_;
    my @podfiles;
    my $htmlfile;
    my @htmlfiles;

    if(opendir(DIR,$fromdir)) {
        @podfiles = grep {/(\.pod)|(\.pm)/i} readdir(DIR);
        if(@podfiles) {
            foreach $podfile (@podfiles) {
                $htmlfile = $podfile;
                $htmlfile =~ s{(\.pm)|(\.pod)$}{\.html}i;
                $htmlfile =~ s|.*/||;
                $htmlfile = "$workdir/$htmlfile";
                push(@htmlfiles, $htmlfile);

                pod2html("--infile=$fromdir/$podfile", "--outfile=$htmlfile");
            }

            @htmlfiles = grep {-e $_} @htmlfiles;

            MakeHelp($helpfile, $workdir, $outdir, @htmlfiles);
        } else {
            $! = "No files to be made from $fromdir";
            return 0;
        }
    } else {
        $! = "Could not open directory $fromdir";
        return 0;
    }

    unlink @htmlfiles if $CLEANUP;

    1;
}

#####################################################################
# FUNCTION      MakeHelpFromDir
# RECEIVES      Helpfile (no extension), Working directory, Output
#               directory (for Helpfile), Dir of html files for input
# RETURNS       1|0
# SETS          None
# EXPECTS       None
# PURPOSE       Takes a directory's worth of html files and binds
#               them all into a chm file
sub MakeHelpFromDir {
    my ($helpfile, $workdir, $outdir, $fromdir) = @_;
    my @files;

    if(opendir(DIR,$fromdir)) {
        @files = map {"$fromdir/$_"} sort(grep {/\.html?/i} readdir(DIR));
        closedir(DIR);
        if(@files) {
            MakeHelp($helpfile, $workdir, $outdir, @files);
        } else {
            $! = "No files to be made from $fromdir";
            return 0;
        }
    } else {
        $! = "Could not open directory $fromdir";
        return 0;
    }

    1;
}

#####################################################################
# FUNCTION      MakePerlHtml
# RECEIVES      None
# RETURNS       None
# SETS          None
# EXPECTS       $HTML, $LIB, $SITELIB
# PURPOSE       Creates html files from pod for the entire perl
#               system, and creates the main toc file.
sub MakePerlHtml {
    MakeHtmlTree($LIB, "$HTML/lib", 1);
    MakeHtmlTree($SITELIB, "$HTML/lib/site", 2);
    MakePerlHtmlIndex("$HTML/lib", "$HTML/perltoc.html");
}

#####################################################################
# FUNCTION      MakePerlHtmlIndexCaller
# RECEIVES      None
# RETURNS       None
# SETS          None
# EXPECTS       $HTML
# PURPOSE       Caller for MakePerlHtmlIndex. Using this function
#               releases the caller from the responsibility of
#               feeding params to MakePerlHtmlIndex, which this
#               library gets automagically from Config.pm
sub MakePerlHtmlIndexCaller {
    #
    # Changed this to reflect the "single index file" idea
    #
    return MakePerlHtmlIndex("$HTML/lib", "$HTML/perltoc.html");
    #return MakePerlHtmlIndex("$HTML/lib", "$HTML/maintoc.html");
}

#####################################################################
# FUNCTION      MakePerlHtmlIndex
# RECEIVES      Base directory to look in, $index file to create
# RETURNS       1 | 0
# SETS          None
# EXPECTS       None
# PURPOSE       Creates the main html index for the perl system. This
#               is called by ppm after installing a package.
sub MakePerlHtmlIndex {
    my ($basedir, $indexfile) = @_;
    my %files;
    my $file;
    my $file_cmp;
    my $dir;
    my $dir_cmp;
    my $dir_to_print;
    my $dir_html_root;
    my $counter;
    my $file_to_print;
    my $sitedir;
    my $libdir;
    my $temp;


    # Get a list of all the files in the tree, list refs keyed by dir.
    # These files are under c:/perl/html/lib because they have
    # already been generated.

    # normalize to forward slashes (NEVER use backslashes in URLs!)
    $basedir =~ s{\\}{/}g;
    unless(%files = GetHtmlFilesFromTree($basedir)) {
        return 0;
    }

    # Start the html document
    unless(open(HTML, ">$indexfile")) {
        $! = "Couldn't write to $indexfile\n";
        return 0;
    }
    print HTML <<'EOT';
<HTML>
<HEAD>
<TITLE>Perl Help System Index</TITLE>
<BASE TARGET="PerlDoc">
</HEAD>
<LINK REL="STYLESHEET" HREF="ebx.css" TYPE="text/css">
<STYLE>
	BODY {font-size : 8.5pt;}
	P {font-size : 8.5pt;}
</STYLE>
<BODY>
EOT

    foreach $dir (keys %files) {
        foreach $file (@{$files{$dir}}) {
            $file_cmp = $file;
            $file_cmp =~ s/\.html?$//i;
            if(exists $files{"$dir/$file_cmp"}) {
                push(@{$files{"$dir/$file_cmp"}}, "$file_cmp/$file");
                @{$files{$dir}} = grep {$_ ne $file} @{$files{$dir}};
            }
        }
    }

    # Merge the different directories if duplicate directories
    # exist for lib and site. Effectively this removes lib/site
    # from existence, and prepends "site" onto the file name for
    # future reference. This way there is only one folder per
    # heading, but I can still tell when to use "site" in
    # making a html link.
    $libdir = "$HTML/lib";
    $sitedir = "$HTML/lib/site";
    push(@{$files{$libdir}}, map {"site/$_"} @{$files{$sitedir}});
    delete $files{$sitedir};
    foreach $dir (keys %files) {
        if($dir =~ m{/site/}i) {
            $dir_cmp = $dir;
            $dir_cmp =~ s{(/lib/)site/}{$1}i;
            push(@{$files{$dir_cmp}}, map {"site/$_"} @{$files{$dir}});
            delete $files{$dir};
        }
    }

    InsertMainToc_Temporary();

    print HTML <<EOT;
      <img id="Foldergif_63" src="folder.gif">&nbsp; 
      <b><a name="CorePerlFAQ">Core Perl FAQ</a><BR>
      </b> 
EOT

    foreach $file (@{$files{"$libdir/Pod"}}) {
	$file_to_print = $file;
	$file_to_print =~ s{\.html$}{}i;
	next unless $file_to_print =~ m{^(perlfaq\d*)$};
	print HTML <<EOT;
&nbsp;&nbsp;&nbsp;
<img id="Pagegif_63" src="page.gif">&nbsp;
<a href="./lib/Pod/$file_to_print.html">
$file_to_print
</a><BR>
EOT
    }

    print HTML <<EOT;
      <img id="Foldergif_63" src="folder.gif">&nbsp; 
      <b><a name="CorePerlDocs">Core Perl Docs</a><BR>
      </b> 
EOT

    foreach $file (@{$files{"$libdir/Pod"}}) {
	$file_to_print = $file;
	$file_to_print =~ s{\.html$}{}i;
	next unless $file_to_print =~ m{^(perl[a-z0-9]*)$};
	next if $file_to_print =~ /^perlfaq/;
	print HTML <<EOT;
&nbsp;&nbsp;&nbsp;
<img id="Pagegif_63" src="page.gif">&nbsp;
<a href="./lib/Pod/$file_to_print.html">
$file_to_print
</a><BR>
EOT
    }

    print HTML <<EOT;
    </p><hr>
    <h4><a name="ModuleDocs">Module Docs</a></h4>
    <p>
EOT

    foreach $dir (sort  { uc($a) cmp uc($b) } keys(%files)) {

        $counter++;
        $dir_to_print = $dir;

        # get just the directory starting with lib/
        $dir_to_print =~ s{.*/(lib/?.*$)}{$1}i;

        # change slashes to double colons
        $dir_to_print =~ s{/}{::}g;

        # kill extra stuff lib and site
        $dir_to_print =~ s{lib::}{}i;

        # Don't want to see lib:: and lib::site::
        $dir_to_print =~ s{(.*)(/|::)$}{$1};
        if($dir_to_print =~ m{^lib(/site)?$}i) {
            $dir_to_print = 'Root Libraries';
        }


        print HTML <<EOT;

<!-- -------------------------------------------- $dir -->
<SPAN 
  id="Dir_${counter}"
>
<b>
<img id="Foldergif_${counter}" src="folder.gif">&nbsp;
$dir_to_print<BR>
</b></SPAN>
<SPAN 
   id="Files_${counter}"
>
EOT
        if (@{$files{$dir}}) {
            foreach $file (sort { $c = $a;
                                  $d = $b;
                                  $c =~ s{^site/}{}i;
                                  $d =~ s{^site/}{}i;
                                  uc($c) cmp uc($d) } (@{$files{$dir}}))
	    {
                $file_to_print = $file;
                $file_to_print =~ s{\.html?}{}i;
		# skip perlfunc.pod etc.
		next if $file_to_print =~ m{^perl[a-z0-9]*$};
                $dir_html_root = $dir;
                if ($file_to_print =~ m{^site/[^/]*$}i) {
                    $dir_html_root =~ s{(lib/)}{$1site/}i;
                    $dir_html_root =~ s{/lib$}{/lib/site}i;
                    $file_to_print =~ s{^site/}{}i;
                    $file =~ s{^site/}{}i;
                }
		elsif ($file_to_print =~ m{^site/(.*)/}i) {
                    $temp = $1;

                    # Get rid of the site
                    $dir_html_root =~ s{(lib/)}{$1site/}i;
                    $dir_html_root =~ s{/lib$}{/lib/site}i;
                    $file_to_print =~ s{^site/}{}i;
                    $file =~ s{^site/}{}i;

                    # Get rid of the additional directory
                    $file_to_print =~ s{^[^/]*/}{}i;
                    $file =~ s{^[^/]*/}{}i;
                    $dir_html_root =~ s{/$temp/?}{}i;
                }
		elsif ($file_to_print =~ m{^(.*)/}) {
                    $temp = $1;
#                    $file_to_print =~ s{^[^/]/?}{}i;
#                    $file =~ s{^[^/]/?}{}i;
                    $file_to_print =~ s{^.*?/}{}i;
                    $file =~ s{^.*?/}{}i;
                    $dir_html_root =~ s{/$temp/?}{}i;
                }
                $dir_html_root =~ s{.*/lib$}{lib}i;
                $dir_html_root =~ s{.*/(lib/.*)}{$1}i;
                $dir_html_root =~ s{lib/\.\./html/}{}i;
                print HTML <<EOT;
&nbsp;&nbsp;&nbsp;
<img id="Pagegif_${counter}" src="page.gif">&nbsp;
<a href="$dir_html_root/$file">
$file_to_print
</a><BR>
EOT
            }
        }
	else {
            print HTML "&nbsp;&nbsp;&nbsp;\n";
            print HTML "No pod / html<BR>\n";
        }
        print HTML "</SPAN>\n";
    }
    print HTML "</p>\n";

    # Close the file
    print HTML "</BODY>\n";
    print HTML "</HTML>\n";
    close HTML;

    return 1;
}


#####################################################################
# FUNCTION      GetHtmlFilesFromTree (recursive)
# RECEIVES      Base directory to look in
# RETURNS       List of html files
# SETS          None
# EXPECTS       None
# PURPOSE       Searches an entire for html files, returns a list of
#               html files found including path information
sub GetHtmlFilesFromTree {
    my $basedir = shift;
    my @dirs;
    my @htmlfiles;
    my %ret;

    unless(opendir(DIR, $basedir)) {
        $! = "Can't read from directory $basedir\n";
        return 0;
    }
    @files = readdir(DIR);
    closedir(DIR);

    @dirs = grep {-d "$basedir/$_" and /[^.]$/} @files;
    @htmlfiles = grep {/\.html?$/i} @files;

    foreach $dir (@dirs) {
        unless(%ret = (%ret, GetHtmlFilesFromTree("$basedir/$dir"))) {
            return 0;
        }
    }

    %ret = (%ret, $basedir => \@htmlfiles);
}

#####################################################################
# FUNCTION      MakePerlHelp
# RECEIVES      None
# RETURNS       1 | 0
# SETS          None
# EXPECTS       None
# PURPOSE       Creates html help for the perl system. This is the
#               html help core build. If MAKE_HTML_FOR_HHELP is set
#               to a true vale, then it builds the help from POD,
#               otherwise it depends on the pod being there already.
sub MakePerlHelp {
    if($MAKE_HTML_FOR_HHELP) {
        unless(MakeHelpFromPodTree($HTMLHELP, $HTMLHELP, $LIB, "$HTML/lib")) {
            return 0;
        }
        unless(MakeHelpFromPodTree($HTMLHELP, $HTMLHELP, $SITELIB,
				   "$HTML/lib/site")) {
            return 0;
        }
    } else {
        unless(MakeHelpFromTree($HTMLHELP, $HTMLHELP, "$HTML/lib")) {
            return 0;
        }
    }

    unless(MakePerlHelpMain) {
        return 0;
    }

    # This handles MakePerlHtml too, since we've created all the html
    unless(MakePerlHtmlIndex("$HTML/lib", "$HTML/perltoc.html")) {
        return 0;
    }

    return 1;
}

#####################################################################
# FUNCTION      MakePerlHelpMain;
# RECEIVES      None
# RETURNS       None
# SETS          None
# EXPECTS       None
# PURPOSE       Creates the main perl helpfile from all the little
#               helpfiles already created.
sub MakePerlHelpMain {
    my @files;

    print "Generating main library helpfile\n";

    unless(opendir(DIR, $HTMLHELP)) {
        $! = "Directory $HTMLHELP could not be read\n";
        return 0;
    }

    unless(-e "$HTMLHELP/default.htm") {
        copy("$HTML/libmain.html", "$HTMLHELP/default.htm");
    }

    @files = grep {/\.hhc/i} readdir(DIR);
    closedir(DIR);

    $CLEANUP=0;
    $MERGE_PACKAGES = 1;

    MakeHelp("libmain.chm", $HTMLHELP, $HTMLHELP, @files);
    
    $CLEANUP = 1;
    $MERGE_PACKAGES = 0;

    return 1;
}

#####################################################################
# FUNCTION      MakeHelpFromPodTree
# RECEIVES      Working directory, Output directory, Source Diretory,
#               HtmlOutput Directory
# RETURNS       0 | 1
# SETS          None
# EXPECTS       None
# PURPOSE       Takes a tree's worth of pod and turns them first
#               into html and then into htmlhelp.
sub MakeHelpFromPodTree {
    my ($workdir, $outdir, $fromdir, $htmldir) = @_;

    unless(MakeHtmlTree($fromdir, $htmldir)) {
        return 0;
    }
    
    unless(MakeHelpFromTree($workdir, $outdir, $htmldir)) {
        return 0;
    }

#   if(opendir(DIR, $outdir)) {
#       unlink(map {"$outdir/$_"} grep {/\.hhp/i} readdir(DIR));
#       closedir(DIR);
#   } else {
#       warn "Could not clean up project files in $outdir\n";
#   }

    return 1;
}

#####################################################################
# FUNCTION      MakeHtmlTree
# RECEIVES      Source Directory, Html Output Directory
# RETURNS       0 | 1
# SETS          None
# EXPECTS       None
# PURPOSE       Makes a tree's worth of html from a tree's worth
#               of pod.
sub MakeHtmlTree {
    my ($fromdir, $htmldir, $depth) = @_;
    my @files;
    my @podfiles;
    my @dirs;
    my $podfile;
    my $htmlfile;
    my $dir;
    my $css = '../' x ($depth-1) . 'ebx.css';

    # Get list of files and directories to process
    $fromdir =~ s{\\}{/}g;
    if(!-d $fromdir) {
        $! = "Directory $fromdir does not exist\n";
        return 0;
    }
    unless(opendir(DIR, $fromdir)) {
        $! = "Directory $fromdir couldn't be read\n";
        return 0;
    }
    @files = readdir(DIR);
    closedir(DIR);

    @podfiles = map {"$fromdir/$_"} grep {/\.pod$|\.pm$/i} @files;
    @dirs = grep {-d "$fromdir/$_" and /[^.]$/} @files;

    if(@podfiles) {
        # Create the copy directory
        if(!-d $htmldir) {
            unless(mkpath($htmldir)) {
                $! = "Directory $htmldir could not be created\n";
                return 0;
            }
        }
        
        foreach $podfile (@podfiles) {
            $htmlfile = $podfile;
            $htmlfile =~ s{.*/(.*)}{$1};
            $htmlfile =~ s{\.pod|\.pm$}{.html}i;
            $htmlfile = "$htmldir/$htmlfile";
            unlink($htmlfile) if (-e $htmlfile);

            pod2html("--htmlroot=./".('../' x $depth), "--infile=$podfile", "--outfile=$htmlfile", "--css=$css");
        }
    }
   	++$depth;
	foreach $dir (@dirs) {
        MakeHtmlTree("$fromdir/$dir", "$htmldir/$dir", $depth);
    }

    return 1;
}

#####################################################################
# FUNCTION      MakeHelpFromTree
# RECEIVES      Working directory, Output directory, Source directory
# RETURNS       0 | 1
# SETS          None
# EXPECTS       None
# PURPOSE       Creates html help from a tree's worth of html
sub MakeHelpFromTree {
    my ($workdir, $outdir, $fromdir) = @_;
    my %files;
    my $file;
    my $key;
    my $file_root;

    $fromdir =~ s{\\}{/}g;
    unless(%files = GetHtmlFileTreeList($fromdir, $fromdir)) {
        return 0;
    }

    $file_root = $fromdir;
    $file_root =~ s{(.*)/$}{$1};

    foreach $key (sort(keys(%files))) {
    	print "$key...\n";
        $file = $key;
        $file = substr($key, length($file_root));
        $file =~ s{^/}{};
        $file =~ s{/}{-}g;
        $file =~ s{ }{}g;
        if($file eq "") {
            if($file_root =~ /lib$/i) {
                $file = "lib";
            } else {
                $file = "lib-site";
            }
        } elsif ($file_root =~ /lib$/i) {
            $file = "lib-" . $file;
        } elsif ($file_root =~ /site$/i) {
            $file = "lib-site-" . $file;
        }
        $file .= ".chm";

        unless(MakeHelp("$file", $workdir, $outdir, map {"$key/$_"} @{$files{$key}})) {
            return 0;
        }
    }

    return 1;
}

#####################################################################
# FUNCTION      GetHtmlFileTreeList (recursive)
# RECEIVES      Original root (from first call), Root (successive)
# RETURNS       Hash of files
# SETS          None
# EXPECTS       None
# PURPOSE       Get a list of html files throughout a tree
sub GetHtmlFileTreeList {
    my $origroot = shift;
    my $root = shift;
    my @files;
    my @htmlfiles;
    my @dirs;
    my $dir;
    my %ret;

    $origroot =~ s{\\}{/}g;
    $root =~ s{\\}{/}g;
    unless(opendir(DIR, $root)) {
        $! = "Can't open directory $root\n";
        return undef;
    }    
    @files = readdir(DIR);
    @dirs = grep {-d "$root/$_" and /[^.]$/} @files;
    @htmlfiles = grep {/\.html?/i} @files;
    closedir(DIR);

    %ret = ($root => \@htmlfiles) if @htmlfiles;

    foreach $dir (@dirs) {
        unless(%ret = (%ret, GetHtmlFileTreeList($origroot, "$root/$dir"))) {
            return undef;
        }
    }

    return %ret;
}

#####################################################################
# FUNCTION      MakeHelpFromHash
# RECEIVES      Helpfile name, working directory, output directory,
#               and a hash containing the html files to process and
#               their titles
# RETURNS       0 | 1
# SETS          None
# EXPECTS       None
# PURPOSE       Create a helpfile from a hash rather than from a
#               simple list of html files, to have better control
#               over the file titles. This function is unused and
#               may take some work to get it to work right.
sub MakeHelpFromHash {
    my ($helpfile, $workdir, $outdir, %htmlfiles) = @_;
    my $tocfile;
    my $projfile;

    die("MakeHelpFromHash() is not completely implemented\n");

    $tocfile = $helpfile;
    $tocfile =~ s/\.chm/.hhc/i;
    $tocfile = "$workdir/$tocfile";

    $projfile = $helpfile;
    $projfile =~ s/\.chm/.hhp/i;
    $projfile = "$workdir/$projfile";

    $helpfile = "$outdir/$helpfile";

    unless(CreateHHP($helpfile, $projfile, $tocfile, keys(%htmlfiles))) {
        return 0;
    }
    unless(CreateHHCFromHash($helpfile, $tocfile, %htmlfiles)) {
        return 0;
    }

    RunCompiler($helpfile);

    1;
}

#####################################################################
# FUNCTION      MakeModuleTreeHelp
# RECEIVES      Directory to start from, regex mask for that dir
# RETURNS       1 | 0
# SETS          None
# EXPECTS       The directories to be right
# PURPOSE       Create help from a tree of pod files for packages
sub MakeModuleTreeHelp {
    my ($fromdir, $mask) = @_;
    my @files;
    my @htmlfiles;
    my @podfiles;
    my @dirs;
    my $helpfile;
    my $podfile;
    my $htmlfile;
    my $dir;

    $fromdir =~ s{\\}{/}g;
    print "Creating help files for $fromdir\n";

    # Create the html for the directory
    unless(opendir(DIR, $fromdir)) {
        $! = "Can't read from directory $fromdir";
        return 0;
    }
    @files = readdir(DIR);
    closedir(DIR);
    @podfiles = map {"$fromdir/$_"} grep {/\.pm/i or /\.pod/i} @files;
    foreach $podfile (@podfiles) {
        $htmlfile = $podfile;
        $htmlfile =~ s/\.(pm|pod)$/.html/i;
        pod2html("--infile=$podfile", "--outfile=$htmlfile");
    }

    # Create the htmlhelp for the directory
    $CLEANUP = 0;
    @htmlfiles = map {"$fromdir/$_"} grep {/\.html?/i} @files;
    if(@htmlfiles) {
        $helpfile = $fromdir;
        $helpfile =~ s{$mask}{}i;
        $helpfile =~ s{/}{-}g;
        $helpfile .= ".chm";
        MakeHelp($helpfile, $fromdir, $fromdir, @htmlfiles);
    }

    # Recurse
    @dirs = map {"$fromdir/$_"} grep {-d and /[^.]$/} @files;
    foreach $dir (@dirs) {
        unless(CreateModuleTreeHelp("$fromdir/$dir")) {
            return 0;
        }
    }

    return 1;
}

#####################################################################
# FUNCTION      MakeHelp
# RECEIVES      Helpfile (without drive and path), Working Directory,
#               Output Directory, and a list of files to include
#               in the helpfile
# RETURNS       None
# SETS          None
# EXPECTS       None
# PURPOSE       Create help from a list of html files. Everything in
#               this library comes through here eventually.
sub MakeHelp {
    my ($helpfile, $workdir, $outdir, @htmlfiles) = @_;
    my $longtocfile;
    my $longprojfile;
    my $longhelpfile;
    my $longouthelpfile;
    my $longouttocfile;
    my $libdir;
    my $tocfile;
    my $projfile;

    print "makehelp: @_\n";
    $libdir = ExtractFilePath($htmlfiles[0]);

    $tocfile = $helpfile;
    $tocfile =~ s/\.chm/.hhc/i;
    if ($libdir ne "") {
        $longtocfile = "$libdir/$tocfile";
    }
    else {
        $longtocfile = "$outdir/$tocfile";
    }
    $longouttocfile = "$outdir/$tocfile";

    $projfile = $helpfile;
    $projfile =~ s/\.chm/.hhp/i;
    if ($libdir ne "") {
        $longprojfile = "$libdir/$projfile";
    }
    else {
        $longprojfile = "$outdir/$projfile";
    }

    if ($libdir ne "") {
        $longhelpfile = "$libdir/$helpfile";
    }
    else {
        $longhelpfile = "$outdir/$helpfile";
    }
    $longouthelpfile = "$outdir/$helpfile";

    print "----- CREATING HELP FILE $longouthelpfile -----\n";

    # put in the default document
    if ($libdir eq "") {
        unshift(@htmlfiles, "$HTMLHELP/default.htm");
    }

    unless(CreateHHP($longhelpfile, $longprojfile, $longtocfile, @htmlfiles)) {
        return 0;
    }
    unless(CreateHHC($longhelpfile, $longtocfile, @htmlfiles)) {
        return 0;
    }
    
    print "checking for $COMPILER\n";

    return 0 if (!-x $COMPILER);
    RunCompiler($longhelpfile);

    if($libdir ne "") {
        if($longhelpfile ne $longouthelpfile) {
            copy($longhelpfile, $longouthelpfile);
            copy($longtocfile, $longouttocfile);
        }
    }

    # temporary for when i want to see what it's doing
#   $CLEANUP = 0;

    if($CLEANUP) {
        unlink $longhelpfile, $longtocfile, $longprojfile;
    }

    1;
}

#####################################################################
# FUNCTION      BackSlash
# RECEIVES      string containing a path to convert
# RETURNS       converted string
# SETS          none
# EXPECTS       none
# PURPOSE       Internally, perl works better if we're using a
#               front slash in paths, so I don't care what I'm
#               using. But externally we need to keep everything as
#               backslashes. This function does that conversion.
sub BackSlash {
    my $in = shift;
    $in =~ s{/}{\\}g;
    return $in;
}

#####################################################################
# FUNCTION      ExtractFileName
# RECEIVES      FileName with (drive and) path
# RETURNS       FileName portion of the file name
# SETS          None
# EXPECTS       None
# PURPOSE       Gives the file name (anything after the last slash)
#               from a given file and path
sub ExtractFileName {
    my $in = shift;
    $in =~ s/.*(\\|\/)(.*)/$2/;
    $in;
}

#####################################################################
# FUNCTION      ExtractFilePath
# RECEIVES      Full file and path name
# RETURNS       Path without the file name (no trailing slash)
# SETS          None
# EXPECTS       None
# PURPOSE       Returns the path portion of a path/file combination,
#               not including the last slash.
sub ExtractFilePath {
    my $in = shift;
    if($in =~ /\\|\//) {
        $in =~ s/(.*)(\\|\/)(.*)/$1/;
    } else {
        $in = "";
    }
    $in;
}

#####################################################################
# FUNCTION      MakePackageMainFromSingleDir
# RECEIVES      Package helpfile directory, helpfile to create
# RETURNS       1 | 0
# SETS          None
# EXPECTS       None
# PURPOSE       Creates the package helpfile from the directory of
#               package helpfiles. Creates the master.
sub MakePackageMainFromSingleDir {
    my $package_helpfile_dir = shift;
    my $helpfile = shift;
    my $helpfile_dir;
    my @hhcfiles;

    $helpfile_dir = ExtractFilePath($helpfile);
    $helpfile = ExtractFileName($helpfile);

    unless(opendir(DIR, $package_helpfile_dir)) {
        $! = "Couldn't read from package directory $package_helpfile_dir";
        return 0;
    }
    @hhcfiles = grep {/\.hhc$/i} readdir(DIR);
    closedir(DIR);

    $CLEANUP = 0;
    unless(MakeHelp($helpfile, $helpfile_dir, $helpfile_dir, @hhcfiles)) {
        return 0;
    }

    1;
}

#####################################################################
# FUNCTION      MakePackageMain
# RECEIVES      Packages directory (contains packages which contain
#               blib directories), helpfile name to create (include
#               drive and path information)
# RETURNS       1 | 0
# SETS          None
# EXPECTS       None
# PURPOSE       For the packages build of HtmlHelp, this function
#               combines all the little packages into one chm
#               file linked to all the little ones per module.
sub MakePackageMain {
    my $package_root_dir = shift;
    my $helpfile = shift;
    my $helpfile_dir;
    my @files;
    my @dirs;
    my @dir;
    my @hhcfiles;

    $helpfile_dir = ExtractFilePath($helpfile);
    $helpfile = ExtractFileName($helpfile);

    unless(opendir(DIR, $package_root_dir)) {
        $! = "Couldn't read from package directory $package_root_dir";
        return 0;
    }
    @files = readdir(DIR);
    closedir(DIR);

    @dirs = map {"$package_root_dir/$_"} grep {-d "$package_root_dir/$_" and /[^.]/} @files;

    foreach $dir (@dirs) {
        if(opendir(DIR, "$dir/blib/HtmlHelp")) {
            @files = readdir(DIR);
            closedir(DIR);
            @hhcfiles = (@hhcfiles, grep {/\.hhc$/i} @files);
        } else {
            warn "Couldn't read / didn't add $dir/blib/HtmlHelp";
        }
    }

    $CLEANUP = 0;
    unless(MakeHelp($helpfile, $helpfile_dir, $helpfile_dir, @hhcfiles)) {
        return 0;
    }

    1;
}

#####################################################################
# FUNCTION      MakePackages
# RECEIVES      Name of directory containing the package dirs, which
#               package directories in turn contain blib dirs.
# RETURNS       None
# SETS          Creates Html and HtmlHelp within the package dirs
# EXPECTS       None, but there should be some pm files in blib, but
#               it ignores it if there isn't
# PURPOSE       Creates Html and HtmlHelp within the package dirs. We
#               decided that we don't want to build the packages at
#               the same time as the main htmlhelp, so this was
#               needed to build them (Murray) at a different time and
#               merge them in.
sub MakePackages {
    my $package_root_dir = shift;
    my (@files) = @_;
    my $package_root_dir_mask;
    my @package_dirs;
    my $package_dir;
    my @file;
    my @dirs;
    my $package_file;
    my $podfile;
    my $htmlfile;
    my @package_file_list;
    my @helphtmlfiles;
    my $htmlfilecopy;
    my $helpfile;

    $CLEANUP = 0;

    $package_root_dir =~ s{\\}{/}g;
    $package_root_dir_mask = $package_root_dir;

    if (!@files) {
        unless(opendir(DIR, $package_root_dir)) {
            $! = "Directory could not be opened $package_root_dir";
            return 0;
        }
        @files = readdir(DIR);
        closedir(DIR);
    }

    @dirs = grep {-d "$package_root_dir/$_" and /[^.]$/} @files;
    @package_dirs = map {"$package_root_dir/$_"} @dirs;

    foreach $package_dir (@package_dirs) {
        @helphtmlfiles = ();

        next if (!-d "$package_dir/blib");

        print "Making help for $package_dir\n";

        # Make room for the stuff
        unless(-d "$package_dir/blib/HtmlHelp") {
            unless(mkpath("$package_dir/blib/HtmlHelp")) {
                $! = "Directory could not be created $package_dir/blib/HtmlHelp";
                return 0;
            }
        }
        unless(-d "$package_dir/blib/Html") {
            unless(mkpath("$package_dir/blib/Html")) {
                $! = "Directory could not be created $package_dir/blib/Html";
                return 0;
            }
        }
        unless(-d "$package_dir/blib/Html/lib") {
            unless(mkpath("$package_dir/blib/Html/lib")) {
                $! = "Directory could not be created $package_dir/blib/Html/lib";
                return 0;
            }
        }
        unless(-d "$package_dir/blib/Html/lib/site") {
            unless(mkpath("$package_dir/blib/Html/lib/site")) {
                $! = "Directory could not be created $package_dir/blib/Html/lib/site";
                return 0;
            }
        }

        # Make the structure under the html
        unless(CopyDirStructure("$package_dir/blib/lib", "$package_dir/blib/Html/lib/site")) {
            return 0;
        }

        # Get a list of all the files to be worked with
        @package_file_list = GetFileListForPackage("$package_dir/blib/lib");

        foreach $file (@package_file_list) {
            print "   ... found $file\n";
        }

        unless(@package_file_list) {
            print "   Nothing to do for this package\n";
            next;
        }

        # Make the html
        foreach $package_file (@package_file_list) {
            unless(-d "$package_dir/blib/temp") {
                unless(mkpath("$package_dir/blib/temp")) {
                    $! = "Directory could not be created $package_dir/blib/temp";
                    return 0;
                }
            }
            $htmlfile = $package_file;
            $htmlfile =~ s/\.(pm|pod)$/.html/i;
            $htmlfile =~ s{/blib/lib/}{/blib/Html/lib/site/}i;
            pod2html("--infile=$package_file", "--outfile=$htmlfile");
            if (-e $htmlfile) {
                unless(-d "$package_dir/blib/temp") {
                    unless(mkpath("$package_dir/blib/temp")) {
                        $! = "Directory could not be created $package_dir/blib/temp";
                        return 0;
                    }
                }
                
                $htmlfilecopy = $htmlfile;
                $htmlfilecopy =~ s{.*/blib/html/}{}i;
                $htmlfilecopy =~ s{/}{-}g;

                copy($htmlfile, "$package_dir/blib/temp/$htmlfilecopy");
                push(@helphtmlfiles, "$package_dir/blib/temp/$htmlfilecopy");
            }
        }

        # Make the htmlhelp
        $helpfile = basename($package_dir);
#       $helpfile =~ s{$package_root_dir_mask/?}{};
        $helpfile .= ".chm";
        $helpfile = "pkg-" . $helpfile;
        unless(MakeHelp($helpfile, "$package_dir/blib/temp",
			"$package_dir/blib/temp", @helphtmlfiles))
	{
            return 0;
        }
        if (-e "$package_dir/blib/temp/$helpfile") {
            copy("$package_dir/blib/temp/$helpfile",
		 "$package_dir/blib/HtmlHelp/$helpfile");

            $hhcfile = $helpfile;
            $hhcfile =~ s/\.chm$/.hhc/i;
            if (-e "$package_dir/blib/temp/$hhcfile") {
                copy("$package_dir/blib/temp/$hhcfile",
		     "$package_dir/blib/HtmlHelp/$hhcfile");
            }
	    else {
                warn("$package_dir/blib/temp/$hhcfile not found, "
		     ."file will not be included");
            }
        }
	else {
            warn("No help file was generated for "
		 ."$package_dir/blib/temp/$helpfile");
        }

        # Clean up the mess from making helpfiles, temp stuff and that
        if (-d "$package_dir/blib/temp") {
            if (opendir(DIR, "$package_dir/blib/temp")) {
                unlink(map {"$package_dir/blib/temp/$_"}
		       grep {-f "$package_dir/blib/temp/$_"} readdir(DIR));
                closedir(DIR);
                unless (rmdir("$package_dir/blib/temp")) {
                    warn "Couldn't rmdir temp dir $package_dir/blib/temp\n";
                }
            }
	    else {
                warn "Couldn't read/remove temp dir $package_dir/blib/temp\n";
            }
        }
    }

    1;
}

#####################################################################
# FUNCTION      CopyDirStructure
# RECEIVES      From Directory, To Directory
# RETURNS       1 | 0
# SETS          None
# EXPECTS       None
# PURPOSE       Copies the structure of the dir tree at and below
#               the Source Directory (fromdir) to the Target
#               Directory (todir). This does not copy files, just
#               the directory structure.
sub CopyDirStructure {
    my ($fromdir, $todir) = @_;
    my @files;
    my @dirs;
    my $dir;

    unless(opendir(DIR, $fromdir)) {
        $! = "Couldn't read from directory $fromdir";
        return 0;
    }
    @files = readdir(DIR);
    @dirs = grep {
        -d "$fromdir/$_" and /[^.]$/ and $_ !~ /auto$/i
    } @files;
    closedir(DIR);

    foreach $dir (@dirs) {

        #
        # I could make it so that it only creates the directory if
        # it has pod in it, but what about directories below THAT
        # if it DOES have pod in it. That would be skipped. May want
        # to do some kind of lookahead. Cutting out the auto more
        # or less cuts out the problem though, right?
        #

        unless(-e "$todir/$dir") {
            unless(mkpath("$todir/$dir")) {
                $! = "Directory could not be created $todir/$dir";
                return 0;
            }
        }
        unless(CopyDirStructure("$fromdir/$dir", "$todir/$dir")) {
            return 0;
        }
    }

    1;
}

#####################################################################
# FUNCTION      GetFileListForPackage (recursive)
# RECEIVES      Root directory
# RETURNS       List of pod files contained in directories under root
# SETS          None
# EXPECTS       None
# PURPOSE       For the packages build, this function searches a
#               directory for pod files, and all directories through
#               the tree beneath it. It returns the complete path
#               and file name for all the pm or pod files it finds.
sub GetFileListForPackage {
    my ($root) = @_;
    my @podfiles;
    my @dirs;
    my $dir;

    unless(opendir(DIR, $root)) {
        $! = "Can't read from directory $root";
        return undef;
    }
    @files = readdir(DIR);
    closedir(DIR);

    @podfiles = map {
        "$root/$_"
    } grep {
        /\.pm/i or /\.pod/i
    } @files;
    
    @dirs = map {
        "$root/$_"
    } grep {
        -d "$root/$_" and /[^.]$/ and $_ !~ /auto$/i
    } @files;
    
    foreach $dir (@dirs) {
        @podfiles = (@podfiles, GetFileListForPackage("$dir"))
    }

    @podfiles;
}

#####################################################################
# FUNCTION      CreateHHP
# RECEIVES      help file name, project file name, toc file name,
#               and a list of files to include
# RETURNS       1|0 for success
# SETS          none
# EXPECTS       none
# PURPOSE       Creates the project file for the html help project.
sub CreateHHP {
    my ($helpfile, $projfile, $tocfile, @files) = @_;
    my $file;
    my $chmfile;
    my $first_html_file;
    my ($shorthelpfile, $shortprojfile, $shorttocfile);
    my ($shortfirstfile, $shortfile);

    my @htmlfiles = grep {/\.html?$/i} @files;
    my @hhcfiles  = grep {/\.hhc$/i}   @files;

    $shorthelpfile = ExtractFileName($helpfile);
    $shortprojfile = ExtractFileName($projfile);
    $shorttocfile =  ExtractFileName($tocfile);

    $first_html_file = $htmlfiles[0];
    unless(defined $first_html_file) {
        warn "No default html file for $backhelp\n";
    }
    $shortfirstfile = ExtractFileName($first_html_file);

    print "Creating $shortprojfile\n";

    unless(open(HHP, ">$projfile")) {
        $! = "Could not write project file";
        return 0;
    }
    print HHP <<EOT;
[OPTIONS]
Compatibility=1.1
Compiled file=$shorthelpfile
Contents file=$shorttocfile
Display compile progress=Yes
EOT
    if ($FULLTEXTSEARCH) {
        print HHP "Full-text search=Yes\n";
    }
    print HHP <<EOT;
Language=0x409 English (United States)
Default topic=$shortfirstfile


[FILES]
EOT
    foreach $file (@htmlfiles) {
        $shortfile = ExtractFileName($file);
        print HHP "$shortfile\n";
        print "   added $shortfile\n";
    }

    if(@hhcfiles) {
        print HHP "\n";
        print HHP "[MERGE FILES]\n";
        foreach $file (@hhcfiles) {
            $chmfile = $file;
            $chmfile =~ s/\.hhc$/.chm/i;
            $shortfile = ExtractFileName($chmfile);
            print HHP "$shortfile\n";
            print "   added $shortfile\n";
        }
        if($MERGE_PACKAGES) {
            print HHP "packages.chm\n";
            print "   ---> MERGED PACKAGES.CHM\n";
        }
    }

    close(HHP);

    return 1;
}

#####################################################################
# FUNCTION      CreateHHC
# RECEIVES      Helpfile name, TOC file name (HHC), list of files
# RETURNS       0 | 1
# SETS          None
# EXPECTS       None
# PURPOSE       Creates the HHC (Table of Contents) file for the
#               htmlhelp file to be created.
# NOTE          This function is used (and abused) for every piece
#               of the htmlhelp puzzle, so any change for one thing
#               can break something totally unrelated. Be careful.
#               This was the result of rapidly changing spex. In
#               general, it's used for:
#                   @ Creating helpfiles from pod/pm
#                   @ Creating helpfiles from html
#                   @ Creating helpfiles from chm's and hhc's
#                   @ Creating child helpfiles from modules
#                   @ Creating main helpfiles
#                   @ Creating helpfile for core build
#                   @ Creating main for core build
#                   @ Creating package helpfiles for packages build
#                   @ Creating package main for package build
#                   @ General Htmlhelp file building other than AS
sub CreateHHC {
    my ($helpfile, $tocfile, @files) = @_;
    my $file;
    my $title;
    my $shorttoc;
    my $shorthelp;
    my $shortfile;
    my $backfile;
    my @libhhcs;
    my @sitehhcs;
    my @otherhhcs;

    $helpfile =~ s{\\}{/}g;
    $tocfile =~ s{\\}{/}g;
    $shorttoc = ExtractFileName($tocfile);
    $shorthelp = ExtractFileName($helpfile);

    print "Creating $shorttoc\n";
    
    unless(open(HHC, ">$tocfile")) {
        $! = "Could not write contents file";
        return 0;
    }
    print HHC <<'EOT';
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<!-- Sitemap 1.0 -->
</HEAD>
<BODY>
<OBJECT type="text/site properties">
	<param name="ImageType" value="Folder">
</OBJECT>
<UL>
EOT

    foreach $file (grep {/\.html?$/i} @files) {
        # don't want default.htm in the toc file
        next if $file =~ /default\.html?$/i;

	$file =~ s{\\}{/}g;
        $title = $file;
        $title =~ s{\.html$}{}i;
        $title =~ s{.*/(.*)}{$1};

        # Section added for packages build
        # Note: this is an abuse of regexes but needed for all cases
        $title =~ s/^pkg-//i;
#       $title =~ s{(.*lib)$}{$1/}i;
        $title =~ s{^lib-site-}{lib/site/}i;
        $title =~ s{^lib-}{lib/}i;
        $title =~ s{^site}{site/}i;
        $title =~ s{^site-}{site/}i;
#       $title =~ s{([^2])-([^x])}{${1}::${2}}ig;
        $title =~ s{Win32-(?!x86)}{Win32::}ig;

#$backfile = BackSlash($file);
        $shortfile = ExtractFileName($backfile);

        print "   adding ${shorthelp}::/${shortfile}\n";


        print HHC <<EOT;
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		<param name="Local" value="${shorthelp}::/${shortfile}">
		</OBJECT>
EOT
    }

    foreach $file (sort(grep {/\.hhc$/i} @files)) {
        if($file =~ /^lib-site-/i) {
            push(@sitehhcs, $file);
        } elsif($file =~ /lib-site\.hhc/i) {
            unshift(@sitehhcs, $file);
        } elsif($file =~ /^lib-/i) {
            push(@libhhcs, $file);
        } elsif($file =~ /lib\.hhc/i) {
            unshift(@libhhcs, $file);
        } else {
            push(@otherhhcs, $file);
        }
    }

    #
    # The Lib merge files
    #
    if(@libhhcs) {
        print HHC <<EOT;
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Core Libraries">
</OBJECT>
<UL>
EOT
        foreach $file (@libhhcs) {
	    $file =~ s{\\}{/}g;
            next if uc($shorttoc) eq uc($file);
    
            # Note: this is an abuse of regexes but needed for all cases
            $title = $file;                         
            $title =~ s{^pkg-}{}i;
            $title =~ s{\.hhc$}{}i;
            $title =~ s{(.*lib)$}{$1/}i;
            $title =~ s{^lib-site-}{lib/site/}i;
            $title =~ s{^lib-}{lib/}i;
            $title =~ s{^site}{site/}i;
            $title =~ s{^site-}{site/}i;
#           $title =~ s{([^2])-([^x])}{${1}::${2}}ig;
            $title =~ s{Win32-(?!x86)}{Win32::}ig;

            if ($title =~ m{^lib/$}i) { $title = "Main Libraries" }
            $title =~ s{^lib/}{}i;

#            $backfile = BackSlash($file);
            $shortfile = ExtractFileName($backfile);

            print "   merging ${shortfile}\n";

            print HHC <<EOT;
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		</OBJECT>
	<OBJECT type="text/sitemap">
		<param name="Merge" value="${shortfile}">
		</OBJECT>
EOT
        }
        print HHC "</UL>\n";
    }

    #
    # The site merge files
    #
    if(@sitehhcs) {
        print HHC <<'EOT';
<!--Beginning of site libraries-->
<LI> <OBJECT type="text/sitemap">
<param name="Name" value="Site Libraries">
</OBJECT>
<UL>
EOT

        foreach $file (@sitehhcs) {
	    $file =~ s{\\}{/}g;
            next if uc($shorttoc) eq uc($file);

            # Note: this is an abuse of regexes but needed for all cases
            $title = $file;                         
            $title =~ s{^pkg-}{}i;
            $title =~ s{\.hhc$}{}i;
            $title =~ s{(.*lib)$}{$1/}i;
            $title =~ s{^lib-site-}{lib/site/}i;
            $title =~ s{^lib-}{lib/}i;
            $title =~ s{^site}{site/}i;
            $title =~ s{^site-}{site/}i;
#           $title =~ s{([^2])-([^x])}{${1}::${2}}ig;
            $title =~ s{Win32-(?!x86)}{Win32::}ig;

            if ($title =~ m{^lib/site$}i) { $title = "Main Libraries" }
            $title =~ s{^lib/site/}{}i;

#            $backfile = BackSlash($file);
            $shortfile = ExtractFileName($backfile);

            print "   merging ${shortfile}\n";

            print HHC <<EOT
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		</OBJECT>
	<OBJECT type="text/sitemap">
		<param name="Merge" value="${shortfile}">
		</OBJECT>
EOT
        }
        print HHC "</UL>\n";

        #
        # quick fix: plop in the packages file
        #
        if($MERGE_PACKAGES) {
            print HHC <<EOT;
<OBJECT type="text/sitemap">
<param name="Merge" value="packages.hhc">
</OBJECT>
EOT
        }

        print HHC "<!--End of site libraries-->\n";
    }

    #
    # All the rest of the merge files
    #
    if(@otherhhcs) {
        foreach $file (@otherhhcs) {
	    $file =~ s{\\}{/}g;
            next if uc($shorttoc) eq uc($file);
    
            # Note: this is an abuse of regexes but needed for all cases
            $title = $file;                         
            $title =~ s{^pkg-}{}i;
            $title =~ s{\.hhc$}{}i;
            $title =~ s{(.*lib)$}{$1/}i;
            $title =~ s{^lib-site-}{lib/site/}i;
            $title =~ s{^lib-}{lib/}i;
            $title =~ s{^site}{site/}i;
            $title =~ s{^site-}{site/}i;
#           $title =~ s{([^2])-([^x])}{${1}::${2}}ig;
            $title =~ s{Win32-(?!x86)}{Win32::}ig;

#            $backfile = BackSlash($file);
            $shortfile = ExtractFileName($backfile);

            print "   merging ${shortfile}\n";

            print HHC <<EOT;
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		</OBJECT>
	<OBJECT type="text/sitemap">
		<param name="Merge" value="${shortfile}">
		</OBJECT>
EOT
        }
    }


    # Close up shop and go home
    print HHC "</UL>\n";
    print HHC "</BODY></HTML>\n";
    close(HHC);

    1;
}

#####################################################################
# FUNCTION      CreateHHCFromHash
# RECEIVES      Helpfile, HHC filename, and assoc array of files
#               where keys are files and values are file titles
# RETURNS       1|0
# SETS          None
# EXPECTS       None
# PURPOSE       Same as CreateHHC but allows for direct control over
#               the file titles
sub CreateHHCFromHash {
    my ($helpfile, $tocfile, %files) = @_;
    my $file;
    my $title;
    my $shorttoc;
    my $shorthelp;
    my $backfile;

    $shorttoc = $tocfile;
    $shorttoc =~ s{.*/(.*)}{$1};

    $shorthelp = $helpfile;
    $shorthelp =~ s{.*/(.*)}{$1};

    print "Creating $shorttoc\n";

    unless(open(HHC, ">$tocfile")) {
        $! = "Could not write contents file";
        return 0;
    }
    print HHC <<'EOT';
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<!-- Sitemap 1.0 -->
</HEAD>
<BODY>
<OBJECT type="text/site properties">
	<param name="ImageType" value="Folder">
</OBJECT>
<UL>
EOT
    while (($file,$title) = each %files) {
        next unless $file =~ /\.html?/i;
#        $backfile = BackSlash($file);
        print HHC <<EOT;
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		<param name="Local" value="$backfile">
		</OBJECT>
EOT
    }
    while (($file,$title) = each %files) {
        next if uc($shorttoc) eq uc($file);
        next unless $file =~ /\.hhc/i;
#        $backfile = BackSlash($file);
        print HHC <<EOT;
	<LI> <OBJECT type="text/sitemap">
		<param name="Name" value="$title">
		</OBJECT>
	<OBJECT type="text/sitemap">
		<param name="Merge" value="$backfile">
		</OBJECT>
EOT
    }
    print HHC "</UL>\n";
    print HHC "</BODY></HTML>\n";
    close(HHC);

    1;
}

#####################################################################
# DO NOT REMOVE THE FOLLOWING LINE, IT IS NEEDED TO LOAD THIS LIBRARY
1;

__END__

=head1 SEE ALSO

L<Pod::WinHtml>

=head1 AUTHORS

=over 4

=item *

David (pete) Grove E<lt>david@grove.netE<gt>

=item *

Gurusamy Sarathy E<lt>gsar@activestate.comE<gt>

=item *

Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>

=back

=head1 COPYRIGHT

Copyright 2000 by ActiveState Tools Corp (L<http://www.activestate.com/>).

Copyright 2001, 2002 by Autrijus Tang E<lt>autrijus@autrijus.orgE<gt>.

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>

=cut