#!/usr/bin/perl
# vim:ft=perl:cindent:ts=4:sts=4:sw=4:et:fdm=marker:cms=\ #\ %s
#
# dwww-build -- build HTML pages for dwww
#
# Part of the dwww package.  Written by Lars Wirzenius.
# Rewritten in perl by Robert Luberda <robert@debian.org> on Sep, 2003.
#
# kv5r css update: Added: copy the css file at 110; #'d html formatting at 535
#
# "@(#)dwww:$Id: dwww-build 528 2009-02-02 08:06:39Z robert $"

use strict;
use warnings;

use File::Glob ':glob';
use File::Path qw/rmtree mkpath/;
use File::Temp qw/tempfile tempdir/;
use File::NCopy qw/copy/;
use Cwd qw/realpath/;
use IO::Handle;
use Debian::Dwww::Utils;
use Debian::Dwww::Initialize;
use Debian::Dwww::Common;

my $dwwwconf = &DwwwInitialize("/etc/dwww/dwww.conf");

my $dwww_title_encoded  = &HTMLEncode($dwwwconf->{'DWWW_TITLE'});
my $dwww_lib_dir        = "/usr/share/dwww/";
my $dwww_templ_dir      = "$dwww_lib_dir/templates";
my $template_mbs_start  = "$dwww_templ_dir/man-in-section.start";
my $template_mbs_end    = "$dwww_templ_dir/man-in-section.end";
my $template_mbn_start  = "$dwww_templ_dir/man-begins-with.start";
my $template_mbn_end    = "$dwww_templ_dir/man-begins-with.end";
my $template_midx_start = "$dwww_templ_dir/man-index.start";
my $template_midx_end   = "$dwww_templ_dir/man-index.end";
my $template_index_main = "$dwww_templ_dir/dwww.template";


my $verbose = "no";
if ($#ARGV >= 0 and  $ARGV[0] eq "--verbose" ) {
    $verbose="yes";
    shift @ARGV;
}
my ($tgt, $tgttmp) = undef;

if (($#ARGV < 0) or  ($ARGV[0] eq "--default" )) {
    $tgt=$dwwwconf->{'DWWW_DOCROOTDIR'} . "/dwww";
} else {
    $tgt="$ARGV[0]";
}
my $tgtupdir = $dwwwconf->{'DWWW_TMPDIR'};

umask 077;
$tgttmp  = tempdir('dwww-build.XXXXXX', DIR => "$tgtupdir", CLEANUP => 1);

my $manlist_fh = tempfile('manlist.XXXXX', DIR => "$tgttmp", UNLINK => 0);
undef $tgtupdir;

my $sepr = " // "; #  manlist file output separator


umask 022;

my @manpages = ();
my $sections = {};
my $letters  = {};

$tgttmp = "$tgttmp/data/";
&mkpath("$tgttmp") or die "Can't create temporary directory: $tgttmp";
&mkpath("$tgttmp/man") or die "Can't create temporary directory: $tgttmp";
&mkpath("$tgttmp/menu") or die "Can't create temporary directory: $tgttmp";

#########################################
#
# MAIN PROGRAM
#
#########################################

STDOUT->autoflush(1);

print "Building dwww pages (a-g):\n";

print "  a) list of manual pages... ";
&find_man();
print "done\n";

print "  b) list of sections and names... ";
&find_sections_and_letters();
print "done\n";

print "  c) manual pages by name... ";
&man_by_name();
print "done\n";

print "  d) manual pages by section... ";
&man_by_section();
print "done\n";

print "  e) manual pages index... ";
&man_index();
print "done\n";

print "  f) front page... ";
&make_front_page();
print "done\n";

print "  g) copying files... ";

&copy("$dwww_lib_dir/*.png", $tgttmp);

# kv5r mod: copy the css file:
&copy("$dwww_lib_dir/dwww.css", $tgttmp);
&append_user_css("/etc/dwww/dwww-user.css", "$tgttmp/dwww.css");


# copying menu directory;
( -d "$tgt/menu" ) && &copy(\1, "$tgt/menu", $tgttmp);

# rename dirs
&RenameDir($tgttmp, $tgt);
print "done\n";
#
# For wn, special handling is required:
if ( -x "/usr/bin/wndex" ) {
    &make_wnindex("$tgt");
    &make_wnindex("$tgt/man");
    &make_wnindex("$tgt/menu");
}

print "The dwww pages have been re-built.\n";

exit (0);


sub debug() { # {{{
    local $_ = shift;
    print STDERR "$_\n";
} # }}}

sub GetBTSDocUrl() { # {{{
        my $btsdoclocal  = "/usr/share/doc/debian/bug-reporting.txt.gz";
        my $btsdocexturi = "https://www.debian.org/Bugs/Reporting";
        return (-r $btsdoclocal ) ? &GetURL('file', $btsdoclocal) : $btsdocexturi;
} # }}}

sub GetSectionDescription() { # {{{
    my $section = shift;
    my $desc="";

    if ($section eq "1")                { $desc="User commands"; }
    elsif ($section eq "1a")            { $desc="User commands"; }               # rss2email
    elsif ($section eq "1bind")         { $desc="DNS tools"; }
    elsif ($section eq "1db")           { $desc="Berkeley database routines"; }
    elsif ($section eq "1emacs21")      { $desc="Emacs 21"; }
    elsif ($section eq "1fun")          { $desc="Funny man pages"; }
    elsif ($section eq "1gmt")          { $desc="Generic Mapping Tools"; }           # gmt-manpages
    elsif ($section eq "1l")            { $desc="User commands"; }
    elsif ($section eq "1m")            { $desc="Ncurses - terminfo utilities"; }
    elsif ($section eq "1mh")           { $desc="Mh (a mail user agent)"; }
    elsif ($section eq "1n")            { $desc="Drawmap"; }                 # drawmap
    elsif ($section eq "1nas")          { $desc="Network Audio System programs"; }
    elsif ($section eq "1netpbm")       { $desc="Netpbm (graphics tools)"; }
    elsif ($section eq "1osd_clock")    { $desc="Clock using the XOSD library"; }      # osdclock
    elsif ($section eq "1p")            { $desc="Perl"; }
    elsif ($section eq "1pccts")        { $desc="The Purdue Compiler Construction Tool Set"; }   # pccts
    elsif ($section eq "1pvm")          { $desc="Parallel Virtual Machine"; }
    elsif ($section eq "1olvwm")        { $desc="OpenLook virtual window manager"; }     # olvwm
    elsif ($section eq "1sr")           { $desc="Surfraw"; }                 # surfraw
    elsif ($section eq "1ssl")          { $desc="SSL programs"; }
    elsif ($section eq "1vga")          { $desc="Svgalib programs"; }
    elsif ($section eq "1wn")           { $desc="WordNet lexical database"; }
    elsif ($section eq "1x")            { $desc="X Window System programs"; }
    elsif ($section eq "2")             { $desc="System calls"; }
    elsif ($section eq "2fun")          { $desc="Funny man pages"; }
    elsif ($section eq "3")             { $desc="Library functions"; }
    elsif ($section eq "3abz")          { $desc="Abz library"; }                 # libabz0-dev
    elsif ($section eq "3alleg")        { $desc="Allegro library"; }             # liballegro-doc
    elsif ($section eq "3ber")          { $desc="Basic Encoding Rules library"; }
    elsif ($section eq "3bind")         { $desc="Internet name resolution (DNS) routines"; }
    elsif ($section eq "3blt")          { $desc="BLT Library"; }
    elsif ($section eq "3caca")         { $desc="Colour AsCii Art library"; }            # libcaca-dev
    elsif ($section eq "3cc")           { $desc="CommonC++ / Bayonne"; }             # libcommoncpp2-dev, bayonne-doc
    elsif ($section eq "3curses")       { $desc="Ncurses - curses routines"; }
    elsif ($section eq "3debug")        { $desc="Debug library"; }               # libdebug0-dev
    elsif ($section eq "3diet")         { $desc="Reimplementation of Daniel Bernstein's interfaces"; }   # libowfat-dev
    elsif ($section eq "3db")           { $desc="Berkeley db database routines"; }
    elsif ($section eq "3el")           { $desc="BSD editline and history libraries"; }      # libedit-dev
    elsif ($section eq "3erl")          { $desc="Erlang programming language"; }         # erlang-manpages
    elsif ($section eq "3form")         { $desc="SVR4 compatible screen forms - ncurses"; }
    elsif ($section eq "3fun")          { $desc="Funny man pages"; }
    elsif ($section eq "3gii")          { $desc="General Input Interface library"; }
    elsif ($section eq "3ggi")          { $desc="General Graphics Interface library"; }
    elsif ($section eq "3gdbm")         { $desc="GNU dbm database routines"; }
    elsif ($section eq "3gle")          { $desc="OpenGL tubing and extrusion library"; }     # libgle3-dev
    elsif ($section eq "3itcl")         { $desc="OOP extension for Tcl"; }           # itk3.1-doc
    elsif ($section eq "3itk")          { $desc="OOP extension for Tcl"; }           # itk3.1-doc
    elsif ($section eq "3iv")           { $desc="Open Inventor toolkit"; }           # inventor-doc
    elsif ($section eq "3iwidgets")     { $desc="OOP extension for Tcl [incr Widgets]"; }   # iwidgets3.1-doc
    elsif ($section eq "3l")            { $desc="Langband"; }                   # langband-engine
    elsif ($section eq "3m17n")         { $desc="Multilingual text processing library"; }   # m17n-docs
    elsif ($section eq "3menu")         { $desc="Ncurses - SVR4 compatible screen menus"; }
    elsif ($section eq "3mm")           { $desc="Msql database routines"; }
    elsif ($section eq "3nas")          { $desc="Network Audio System library"; }
    elsif ($section eq "3ncurses")      { $desc="Ncurses (terminal screen painting)"; }
    elsif ($section eq "3ncp")          { $desc="NetWare Core Protocol librabary"; }     # libncp-dev
    elsif ($section eq "3netpbm")       { $desc="Netpbm graphics library"; }
    elsif ($section eq "3o")            { $desc="Objective Caml library"; }          # ocaml-nox, liblablgtk2-ocaml-doc
    elsif ($section eq "3ossp")         { $desc="OSSP uuid ISO-C"; }             # libossp-uuid-dev
    elsif ($section eq "3paper")        { $desc="Paper handling library"; }
    elsif ($section eq "3pm")           { $desc="Perl modules"; }
    elsif ($section eq "3perl")         { $desc="Perl modules"; }
    elsif ($section eq "3plplot")       { $desc="PLplot, a plotting library"; }          # plplot-doc
    elsif ($section eq "3pub")          { $desc="Lars Wirzenius' publib routines"; }
    elsif ($section eq "3pvm")          { $desc="Parallel Virtual Machine"; }            # pvm-dev
    elsif ($section eq "3qt")           { $desc="Trolltech's QT library "; }
    elsif ($section eq "3readline")     { $desc="GNU readline prompt routine"; }
    elsif ($section eq "3ruby")         { $desc="Ruby Class to use HTML Templates"; }       # libhtml-template-ruby
    elsif ($section eq "3snmp")         { $desc="Simple Network Management Protocol"; }      # libsnmp5-dev
    elsif ($section eq "3ssl")          { $desc="SSL library"; }
    elsif ($section eq "3tiff")         { $desc="Libtiff graphics library"; }
    elsif ($section eq "3tcl")          { $desc="Tcl (Tool Command Language) library"; }
    elsif ($section eq "3tclrl")        { $desc="GNU readline for Tcl library"; }
    elsif ($section eq "3tclx")         { $desc="TclX (Extended Tcl) library"; }
    elsif ($section eq "3tcsh")         { $desc="TENEX C Shell (tcsh)"; }
    elsif ($section eq "3thr")          { $desc="Pthreads library"; }
    elsif ($section eq "3tix")          { $desc="Tix widget library for Tk"; }
    elsif ($section eq "3tk")           { $desc="Tk widget library"; }
    elsif ($section eq "3tnm")          { $desc="Tcl shell including the Tnm extensions"; }
    elsif ($section eq "3vga")          { $desc="Svgalib library"; }
    elsif ($section eq "3x")            { $desc="X Window System library"; }
    elsif ($section eq "3xp")           { $desc="X Print Client library"; }
    elsif ($section eq "4")             { $desc="Device files"; }
    elsif ($section eq "4b")            { $desc="Device files"; }                # emwin
    elsif ($section eq "4x")            { $desc="X Window System"; }
    elsif ($section eq "5")             { $desc="File formats"; }
    elsif ($section eq "5bind")         { $desc="DNS"; }
    elsif ($section eq "5el")           { $desc="BSD editline and history libraries"; }      # libedit-dev
    elsif ($section eq "5fun")          { $desc="Funny man pages"; }
    elsif ($section eq "5g")            { $desc="File formats"; }                # sam
    elsif ($section eq "5heimdal")      { $desc="Heimdal Kerberos"; }                # heimdal-docs
    elsif ($section eq "5l")            { $desc="File formats"; }
    elsif ($section eq "5rad")          { $desc="Radius server"; }               # radiusd-cistron
    elsif ($section eq "5mh")           { $desc="Mh (mail user agent)"; }
    elsif ($section eq "5mm")           { $desc="Msql database"; }
    elsif ($section eq "5nas")          { $desc="Network Audio System"; }
    elsif ($section eq "5snmp")         { $desc="Net-SNMP library"; }
    elsif ($section eq "5ssl")          { $desc="SSL library"; }
    elsif ($section eq "5vga")          { $desc="Svgalib library"; }
    elsif ($section eq "5x")            { $desc="X Window System file formats"; }
    elsif ($section eq "6")             { $desc="Games"; }
    elsif ($section eq "6fun")          { $desc="Funny man pages"; }
    elsif ($section eq "6vga")          { $desc="Svgalib games"; }
    elsif ($section eq "6x")            { $desc="X Window System games"; }
    elsif ($section eq "7")             { $desc="Miscellaneous"; }
    elsif ($section eq "7bind")         { $desc="DNS terms"; }
    elsif ($section eq "7ctrlproxy")    { $desc="IRC proxy with multiserver support"; } # ctrlproxy
    elsif ($section eq "7g")            { $desc="Miscellaneous"; }               # sam
    elsif ($section eq "7gcc")          { $desc="GNU C compiler library"; }
    elsif ($section eq "7gii")          { $desc="General Input Interface library"; }
    elsif ($section eq "7ggi")          { $desc="General Graphics Interface library"; }
    elsif ($section eq "7ssl")          { $desc="SSL library"; }
    elsif ($section eq "7vga")          { $desc="Svgalib library"; }
    elsif ($section eq "7x")            { $desc="X Window System"; }
    elsif ($section eq "8")             { $desc="System administration commands"; }
    elsif ($section eq "8bind")         { $desc="DNS commands"; }
    elsif ($section eq "8fun")          { $desc="Funny man pages"; }
    elsif ($section eq "8c")            { $desc="System administration commands"; }     # ipopd, nntp
    elsif ($section eq "8l")            { $desc="System administration commands"; }     # tua
    elsif ($section eq "8lvm-10")       { $desc="Logical Volume Manager"; }          # lvm10
    elsif ($section eq "8mailutils")    { $desc="Mailutils"; }
    elsif ($section eq "8mh")           { $desc="Mh (mail user agent)"; }
    elsif ($section eq "8p")            { $desc="Perl scripts"; }
    elsif ($section eq "8postfix")      { $desc="Postfix mail transport agent"; }
    elsif ($section eq "8rad")          { $desc="Radius server"; }               # radiusd-cistron
    elsif ($section eq "8x")            { $desc="X Window System programs"; }           # powertweak-gtk, chos
    elsif ($section eq "8vga")          { $desc="Svgalib library"; }
    elsif ($section eq "9")             { $desc="Linux kernel functions"; }
    elsif ($section eq "9gii")          { $desc="General Input Interface library"; }
    elsif ($section eq "l")             { $desc="Local man pages"; }
    elsif ($section =~ /^[0-9]posix$/)  { $desc="Posix man pages" ; }
    elsif ($section =~ /^[157]wn$/)     { $desc="WordNet lexical database" ; }
    elsif ($section =~ /^[1-4]rtl$/)    { $desc="Real-Timer-Linux" ; }
    elsif ($section =~ /^[158]cn$/)     { $desc="C News server" ; }

    return $desc;
} # }}}

sub GetSectionDescriptionInBraces() { # {{{
    my $section = shift;
    my $desc=&GetSectionDescription($section);

    $desc = "($desc)" unless $desc eq "";
    return $desc;
} # }}}


# Encodes given $name to be used as a file name or a href name
sub FileEncode() { # {{{
    my ($type, $name) = @_;
    $name = &URLEncode($name);
    $name =~ s/_/%5f/g;
    $name =~ s/%/_/g;

    return $type . $name;
} # }}}

sub GetIndex() { # {{{
    my ($type, $vars) = @_;
    my $ret = '';
    my @list = ();
    my $l = 0;
    my $max_l = 120;

    foreach my $i ( sort keys %$vars ) {
        $l += length($i) + 3;
        if ($l > $max_l) {
            $ret .= join (' | ', @list) . "<br>\n";
            @list   = ();
            $l  = length($i) + 3;
        }
        push(@list, '<a href="#' . &FileEncode($type, $i) . '">' . &HTMLEncode($i) . '</a>');
    }
    $ret .= join (' | ', @list) . "\n" unless $#list < 0;
    return $ret;
} # }}}



#
# Find all manual page files.
#
sub find_man() { # {{{
    my @manpath = ();
    my @manpages = ();
    my @mantmp  = ();

    @manpath = split (/:/ , `manpath -q`);

    foreach my $i (@manpath) {
        chomp $i;
        next if ( "$i" eq "" );
        next unless ( -d "$i" );
        $i = &realpath($i);
        next if ( "$i" eq "");
        push(@mantmp, &bsd_glob("$i/man*/*", GLOB_MARK|GLOB_NOSORT));
    }

    foreach my $index (0 .. $#mantmp) {
        $_ = $mantmp[$index];
        next unless (-f $_);
        s/\.(gz|Z|bz2)$//;
        next unless (m;^.*man([1-9nl])/([^/])([^/]*)\.(\1[^./]*)$;);
        push(@manpages, join( $sepr,  lc($4), uc($2), "$2$3",   &URLEncode($mantmp[$index])));

    };
    @mantmp   = undef;
    @manpages = sort { uc($a) cmp uc($b) } @manpages;
    seek ($manlist_fh, 0, 0);
    foreach (@manpages) {
        print $manlist_fh $_ . "\n";
    }
    $manlist_fh -> flush();
} # }}}


#
# Output a list of sections.
#
sub find_sections_and_letters() { # {{{

    seek ($manlist_fh, 0, 0);
    while (<$manlist_fh>){
        chomp;
        my ($section, $letter,  undef,  $path) = split ($sepr, $_, 4);
        $sections->{$section}->{$letter} = 1;
        $letters->{$letter}->{$section} = 1;
    }
} # }}}

#
# Build lists of manual pages according to first letter.
###
sub man_by_name() { # {{{
    my $type = 'n';

    foreach my $letter ( keys( %$letters ) ) {
        open M, ">$tgttmp/man/" . &FileEncode($type, $letter) . ".html";
        print M &TemplateFile($template_mbn_start,
                    { 'TITLE' => $dwww_title_encoded,
                      'LETTER' => &HTMLEncode($letter),
                      'HREFLETTER' => &FileEncode($type, $letter),
                      'SECTIONS' => &GetIndex('s', $letters->{$letter})
                    });
        close M;
    }

    my %lastsections = ();
    my %tables   = ();
    my $lastletter   = '';

    seek ($manlist_fh, 0, 0);
    while (<$manlist_fh>) {
        chomp();
        my ($section, $letter, $name, $file) = split ($sepr, $_, 4);
        if ($lastletter ne $letter) {
            if ($lastletter ne '') {
                &EndTable(\*M, $tables{$lastletter});
                close M;
            }
            open M, ">>$tgttmp/man/" . &FileEncode($type, $letter) . ".html";
            $lastletter = $letter;
        }
        if ((not exists $lastsections{$letter}) or
            ($lastsections{$letter} ne $section)) {
            my $capt='<a class="nohref" name="' . &FileEncode('s', $section) . '">' .
                 "- in section " . &HTMLEncode($section) . "</a>";
            my $desc = &GetSectionDescriptionInBraces($section);
            $capt .= ":" if $desc eq '';
            $desc = " ${desc}:" if $desc ne '';

            $tables{$letter} = &BeginTable(\*M, $capt, 4, $desc);
            $lastsections{$letter} = $section;
        }
        &AddToTable(\*M, $tables{$letter}, "<a href=\"" . &GetURL('man', $file, $TRUE) . "\">" . &HTMLEncode($name) . "</a>");
    }

    if ($lastletter ne '') {
        &EndTable(\*M, $tables{$lastletter});
        close M;
    }

    foreach my $letter ( keys( %$letters ) ) {
        open M, ">>$tgttmp/man/" . &FileEncode($type, $letter) . ".html";
        print M &TemplateFile($template_mbn_end,
                    { 'TITLE' => $dwww_title_encoded,
                      'SECTIONS' => &GetIndex('s', $letters->{$letter})
                    });
        close M;
    }
} # }}}

#
# Build lists of manual pages according to section
###
sub man_by_section() { # {{{
    my $type    = 's';
    my $section = undef;

    # Start a file for each section
    foreach $section ( keys( %$sections ) ) {
        open M, ">$tgttmp/man/" . &FileEncode($type, $section) . ".html";
        print M &TemplateFile($template_mbs_start,
                    { 'TITLE' => $dwww_title_encoded,
                      'SECTION' => &HTMLEncode($section),
                      'SECTIONDESC' => &GetSectionDescriptionInBraces($section),
                      'HREFSECTION' => &FileEncode($type, $section),
                      'LETTERS' => &GetIndex('n', $sections->{$section})
                    });
        close M;
    }

    my $table    = undef;
    my $lastsection  = '';
    my $lastletter   = '';
    seek ($manlist_fh, 0, 0);

    while (<$manlist_fh>) {
        chomp();
        my ($section, $letter, $name, $file) = split ($sepr, $_, 4);
        # Note that records are sorted by section
        # and for each section - by the letter
        if ($lastsection ne $section) {
            if (defined $table) {
                &EndTable(\*M, $table);
                close M;
            }
            open M, ">>$tgttmp/man/" . &FileEncode($type, $section) . ".html";
            $lastsection = $section;
            $lastletter  = '';
            $table       = undef;
        }
        if ($lastletter ne $letter) {
            my $capt='<a class="nohref" name="' . &FileEncode('n', $letter) . '">' .
                 "- starting with " . &HTMLEncode($letter) . ":</a>";

            if (defined $table) {
                &EndTable(\*M, $table);
            }

            $table      = &BeginTable(\*M, $capt, 4);
            $lastletter = $letter;
        }

        die ('Internal error: $table should be defined! ($file=' . $file .')')
             unless (defined $table);

        &AddToTable(\*M, $table, "<a href=\"" . &GetURL('man', $file, $TRUE) . "\">" . &HTMLEncode($name) . "</a>");
    }

    if ($lastsection ne '') {
        if (defined $table) {
            &EndTable(\*M, $table);
        }
        close M;
    }

    foreach $section ( keys( %$sections ) ) {
        open M, ">>$tgttmp/man/" . &FileEncode($type, $section) . ".html";
        print M &TemplateFile($template_mbs_end,
                    { 'TITLE' => $dwww_title_encoded,
                      'LETTERS' => &GetIndex('n', $sections->{$section})
                    });
        close M;
    }


} # }}}


sub man_index() { # {{{


    open M, ">>$tgttmp/man/index.html";
    print M &TemplateFile($template_midx_start,
                { 'TITLE' => $dwww_title_encoded,
                });

        # made browsers to calculate widths by themselves
    my $table = &BeginTable(\*M, '<a class="nohref" name="n">Man pages by first letter:</a>', 14, '', []);

    foreach my $letter ( sort keys( %$letters ) ) {
        my $fname =  &FileEncode('n', $letter);
        &AddToTable(\*M, $table, "<a name=\"$fname\" href=\"$fname.html\">"
                    . &HTMLEncode($letter) . "</a>");
    }

    &EndTable(\*M, $table);

# html not necessary here: css handles it. (kv5r)
#         print M "<BR><HR><BR>\n";
        print M "\n";

    $table = &BeginTable(\*M, '<a class="nohref" name="s">Man pages by section:</a>', 3, '', [4, 10, '*']);

    my $lastsectionbase = "";
    my $sectionbase = "";
    foreach my $section ( sort keys( %$sections ) ) {
        $sectionbase = substr($section, 0, 1);
        if ($sectionbase ne $lastsectionbase)
        {
            if ($lastsectionbase ne "") {
                # empty row separating sections
                &AddToTable(\*M, $table, '&nbsp;');
                &AddToTable(\*M, $table, '');
                &AddToTable(\*M, $table, '');
            }
            if ($sectionbase ne $section) {
                &AddToTable(\*M, $table, '<strong>' . &HTMLEncode($sectionbase) . '</strong>');
                &AddToTable(\*M, $table, '');
                &AddToTable(\*M, $table, '<strong>' . &GetSectionDescription($sectionbase.'</strong>'));
            }

            $lastsectionbase = $sectionbase;
        }

        my $desc      = &GetSectionDescription($section);
        my ($bs, $be) = undef;
        if ($sectionbase eq $section) {
            $bs = '<strong>';
            $be = '</strong>';
        } else {
            $bs = '';
            $be = '';
            $desc = '&nbsp;&nbsp;' . $desc unless $desc eq '';
            &AddToTable(\*M, $table, '');
        }

        my $fname = &FileEncode('s', $section);
        &AddToTable(\*M, $table, "<a name=\"$fname\" href=\"$fname.html\">"
                    . $bs . &HTMLEncode($section) . $be . "</a>");

        &AddToTable(\*M, $table, '') if  ($sectionbase eq $section);

        &AddToTable(\*M, $table, $bs . $desc . $be);
    }
    &EndTable(\*M, $table);


    print M &TemplateFile($template_midx_end,
                { 'BTSDOCURL' => &GetBTSDocUrl()
                            });
} # }}}

#
# Create the front page.
#
sub make_front_page() { # {{{
    open M, ">$tgttmp/index.html" or die "Cannot open file $tgttmp/index.html: $!";
    print M &TemplateFile($template_index_main,
                { 'TITLE' => $dwww_title_encoded,
                  'BTSDOCURL' => &GetBTSDocUrl()
                });
    close M;
} # }}}


# This is a special routine for the wn webserver
#
sub make_wnindex # {{{
{
    my $dir = shift;

    chdir("$dir");
        if ( ! -e "index" ) {
        open I, ">index";
                print I "Attribute=serveall\n";
        close I;
    }

        &system("/usr/bin/wndex >/dev/null");
} # }}}


sub append_user_css($$) # {{{
{
    my ($src, $dst) = @_;

    return unless -r $src;
    open SRC, "<$src"    or die "Can't open $src for reading: $!";
    open DST, ">>$dst"   or die "Can't open $dst for writing: $!";
    while (<SRC>)
    {
        print DST $_;
    }
} # }}}

