<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Copyright (C) 1998-09  Stephane Galland &lt;galland@arakhne.org&gt;
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

=pod

=head1 NAME

Bib2HTML::Generator::Theme - A theme for the HTML generator

=head1 SYNOPSYS

use Bib2HTML::Generator::Theme ;

my $gen = Bib2HTML::Generator::Theme-&gt;new( generator,
                                           bib2html,
                                           target,
                                           title,
                                           lang ) ;

=head1 DESCRIPTION

Bib2HTML::Generator::Theme is a Perl module, which proposes
a documentation theme for the HTML generator of bib2html.

=head1 GETTING STARTED

=head2 Initialization

To start a generator script, say something like this:

    use Bib2HTML::Generator::Theme;

    my $gen = Bib2HTML::Generator::Theme-&gt;new( $generator,
					       { 'VERSION' =&gt; '0.11' },
						'./bib_output',
						'Title',
					        $lang ) ;

...or something similar. Acceptable parameters to the constructor are:

=over

=item * parent (object ref)

is a reference to the current HTML generator.

=item * bib2html (hash)

contains some data about bib2html.

=item * target (string)

The directory in which the documentation must be put.

=item * title (string)

is the title of the documentation.

=item * lang (object ref)

is a reference to the language object.

=back

=head1 METHOD DESCRIPTIONS

This section contains only the methods in Theme.pm itself.

=over

=cut

package Bib2HTML::Generator::Theme;

@ISA = ('Exporter');
@EXPORT = qw();
@EXPORT_OK = qw();

use strict;
use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
use Exporter;

use Carp ;
use File::Spec ;

use Bib2HTML::General::Verbose ;
use Bib2HTML::General::Error ;
use Bib2HTML::General::HTML ;
use Bib2HTML::General::Misc ;
use Bib2HTML::Generator::FileWriter ;
use Bib2HTML::Generator::StdOutWriter ;

#------------------------------------------------------
#
# Global vars
#
#------------------------------------------------------

# Version number of theme
my $VERSION = "2.0" ;

#------------------------------------------------------
#
# Constructor
#
#------------------------------------------------------

sub new($$$$$) : method {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self = { 'PARENT' =&gt; $_[0] || confess( 'you must supply the parent object' ),
	       'BIB2HTML' =&gt; $_[1] || '',
	       'TARGET_DIR' =&gt; $_[2] || confess( 'you must supply the target directory' ),
	       'TITLE' =&gt; $_[3] || '',
	       'LANG' =&gt; $_[4] || confess( 'you must supply the language object' ),
	     } ;

  my $simpleclass = $class;
  if ($class =~ /^.*::(.+?)$/) {
    $simpleclass = "$1";
  }

  # Register lang files
  if ($self-&gt;{'LANG'}) {
    $self-&gt;{'LANG'}-&gt;registerLang("Theme.$simpleclass");
  }

  bless( $self, $class );
  return $self;
}

=pod

=item * copy_files()

Copies some files from the bib2html distribution directly inside the
HTML documentation tree.

=cut
sub copy_files() : method {
  my $self = shift ;
}

=pod

=item * get_stream_writer()

Replies the instance of the output stream writer.

=cut
sub get_stream_writer() : method {
  my $self = shift ;
  if (!$self-&gt;{'STREAM_WRITER'}) {
    $self-&gt;{'STREAM_WRITER'} = new Bib2HTML::Generator::FileWriter-&gt;new();
  }
  return $self-&gt;{'STREAM_WRITER'};
}

=pod

=item * set_stream_writer($)

Set the instance of the output stream writer.
Replies the old writer.
Takes 1 arg:

=over

=item * writer (ref to Bib2HTML::Generator::Writer)

is the instance of the writer.

=back

=cut
sub set_stream_writer($) : method {
  my $self = shift ;
  my $writer = shift;
  my $old_writer = $self-&gt;{'STREAM_WRITER'};
  $self-&gt;{'STREAM_WRITER'} = $writer;
  return $old_writer;
}

#------------------------------------------------------
#
# Filename API
#
#------------------------------------------------------

=pod

=item * ext_href()

Replies a hyperlink according to the parameters
Takes 3 args:

=over

=item * section (string)

is the id of the section.

=item * label (string)

is the label of the hyperlink

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub ext_href($$$) : method {
  my $self = shift ;
  my $section = shift || confess( 'you must supply the section id' ) ;
  my $label = shift || '' ;
  my $rootdir = shift || confess( 'you must supply the root directory' ) ;
  return $self-&gt;href( htmlcatfile($rootdir,$self-&gt;filename($section,@_)),
                      $label,
                      $self-&gt;browserframe($section) ) ;
}

=pod

=item * ext_wt_href()

Replies a hyperlink according to the parameters (without target)
Takes 3 args:

=over

=item * section (string)

is the id of the section.

=item * label (string)

is the label of the hyperlink

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub ext_wt_href($$$) : method {
  my $self = shift ;
  my $section = shift || confess( 'you must supply the section id' ) ;
  my $label = shift || '' ;
  my $rootdir = shift || confess( 'you must supply the root directory' ) ;
  return $self-&gt;href( htmlcatfile($rootdir,$self-&gt;filename($section,@_)),
                      $label ) ;
}

=pod

=item * filename()

Replies the filename of the specified section.
Takes 1 arg:

=over

=item * section (string)

is the name of the section.

=back

=cut
sub filename : method {
  my $self = shift ;
  return $self-&gt;{'PARENT'}-&gt;filename(@_) ;
}

=pod

=item * browserframe()

Replies the frame used for the specified section.
Takes 1 arg:

=over

=item * section (string)

is the name of the section.

=back

=cut
sub browserframe : method {
  my $self = shift ;
  return $self-&gt;{'PARENT'}-&gt;browserframe(@_) ;
}

#------------------------------------------------------
#
# Page API
#
#------------------------------------------------------

=pod

=item * get_copyright()

Replies a string that represents the copyright of this translator.

=over

=item * rootdir (string)

is the path to the root directory

=back

=cut
sub get_copyright($) : method {
  my $self = shift ;
  my $rootdir = $_[0] ;
  return join( '',
	       $self-&gt;par( $self-&gt;small( $self-&gt;href( $self-&gt;{'BIB2HTML'}{'BUG_URL'},
						      $self-&gt;{'LANG'}-&gt;get( 'I18N_LANG_SUBMIT_BUG'), "_top" ) ) ),
	       $self-&gt;par( $self-&gt;small( $self-&gt;{'LANG'}-&gt;get( 'I18N_LANG_BIB2HTML_COPYRIGHT',
							       $self-&gt;href( $self-&gt;{'BIB2HTML'}{'URL'},
									    "bib2html ".$self-&gt;{'BIB2HTML'}{'VERSION'},
									    "_top" ),
							       $self-&gt;href( "mailto:".$self-&gt;{'BIB2HTML'}{'AUTHOR_EMAIL'},
									    $self-&gt;{'BIB2HTML'}{'AUTHOR'} ),
							       $self-&gt;href( "http://www.gnu.org/copyleft/gpl.html",
									    "GNU General Public License",
									    "_top" ) ) ) )
	     ) ;
}

=pod

=item * get_html_index()

Replies the content of the main index.html
Takes 1 arg:

=over

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub get_html_index($) {
  my $self = shift ;
  my $rootdir = $_[0] || confess( 'you must supply the root directory' ) ;
  return join( '',
	       "&lt;FRAMESET cols=\"20%,80%\"&gt;\n",
	       "&lt;FRAMESET rows=\"30%,70%\"&gt;\n",
	       "&lt;FRAME src=\"",
	       htmlcatfile($rootdir,$self-&gt;filename('overview-frame')),
	       "\" name=\"",
	       $self-&gt;browserframe('overview-frame'),
	       "\"&gt;\n&lt;FRAME src=\"",
	       htmlcatfile($rootdir,$self-&gt;filename('allelements')),
	       "\" name=\"",
	       $self-&gt;browserframe('allelements'),
	       "\"&gt;\n&lt;/FRAMESET&gt;\n&lt;FRAME src=\"",
	       htmlcatfile($rootdir,$self-&gt;filename('overview-summary')),
	       "\" name=\"",
	       $self-&gt;browserframe('overview-summary'),
	       "\"&gt;\n&lt;NOFRAMES&gt;\n",
	       $self-&gt;{'LANG'}-&gt;get('I18N_LANG_NO_FRAME_ALERT',
				    $self-&gt;filename('overview-summary'),
				    ''),
	       "&lt;/NOFRAMES&gt;\n",
	       "&lt;/FRAMESET&gt;\n" ) ;
}

=pod

=item * create_html_page()

Creates an HTML page without a &lt;BODY&gt;.
Takes 3 args:

=over

=item * filename (string)

is the name of the file in which the page
must be created.

=item * content (string)

is the content of the page.

=item * title (string)

is the title of the page.

=item * rootdir (string)

is the path to the root directory.

=item * frameset (boolean)

must be true if the generated page must respect the w3c frameset definition,
otherwhise it will respect the w3c transitional definition

=back

=cut
sub create_html_page($$$$$) : method {
  my $self = shift ;
  my $rootdir = $_[3] || confess( 'you must supply the root directory' ) ;
  confess( 'you must supply the filename' ) unless $_[0] ;
  my $filename = File::Spec-&gt;catfile( $self-&gt;{'TARGET_DIR'}, htmlpath($_[0]) ) ;
  Bib2HTML::General::Verbose::two( "Writing $filename..." ) ;

  my $writer = $self-&gt;get_stream_writer();

  $writer-&gt;openstream("$filename")
    or Bib2HTML::General::Error::syserr( "$filename: $!\n" );

  my $header ;
  if ( $_[4] ) {
    $header = "&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/REC-html40/frameset.dtd\"&gt;" ;
  }
  else {
    $header = "&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\"&gt;" ;
  }

  $writer-&gt;out(join( '',
  		   	 $header,
			 "\n\n&lt;!-- Generated by bib2html ".$self-&gt;{'BIB2HTML'}{'VERSION'},
			 " on ",
			 "".localtime(),
			 " --&gt;\n\n",
  		  	 "&lt;HTML&gt;\n&lt;HEAD&gt;\n&lt;TITLE&gt;",
			 $_[2] || '',
			 "&lt;/TITLE&gt;\n",
			 "&lt;META http-equiv=\"Content-Type\" ",
			 "content=\"text/html; charset=",
			 $self-&gt;get_html_encoding(),#ISO-8859-1
			 "\"&gt;\n",
			 $self-&gt;get_html_header($rootdir),
			 "&lt;/HEAD&gt;\n",
			 $_[1] || '',
			 "&lt;/HTML&gt;" ) ) ;

  $writer-&gt;closestream() ;
}

=pod

=item * get_html_encoding()

Replies the HTML encoding of each page
(by default ISO-8859-1).

=cut
sub get_html_encoding() : method {
  my $self = shift ;
  return $self-&gt;{'html_encoding'} || "ISO-8859-1" ;
}

=pod

=item * set_html_encoding($)

Set the HTML encoding of each page
Takes 1 arg:

=over

=item * encoding (string)

is the new encoding

=back

=cut
sub set_html_encoding($) : method {
  my $self = shift ;
  my $encoding = shift;
  $self-&gt;{'html_encoding'} = $encoding if ($encoding) ;
}

=pod

=item * get_html_header()

Replies the HTML header of each page.
Takes 1 arg:

=over

=item * rootdir (string)

is the path to the root directory

=back

=cut
sub get_html_header($) : method {
  my $self = shift ;
  return '' ;
}

=pod

=item * create_html_body_page()

Creates an HTML page with a &lt;BODY&gt;.
Takes 3 args:

=over

=item * filename (string)

is the name of the file in which the page
must be created.

=item * content (string)

is the content of the page.

=item * title (string)

is the title of the page.

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub create_html_body_page($$$$@) : method {
  my $self = shift ;
  my $filename = shift ;
  my $content = shift ;
  my $title = shift ;
  my $rootdir = shift || confess( "the rootdir must be supplied" ) ;
  $content = join( '',
		   "&lt;BODY",
		   ( $self-&gt;{'BACKGROUND_COLOR'} ?
		     " BGCOLOR=\"" .
		     $self-&gt;{'BACKGROUND_COLOR'} .
		     "\"" : '' ),
		   "&gt;\n",
		   $content ) ;
  my $small ;
  if ((@_)&amp;&amp;("$_[0]" eq 'small')) {
    shift @_ ;
    $small = 1 ;
  }
  $self-&gt;mergeValidHTMLIcons($content,$rootdir,$small,@_) ;
  $content .= "\n&lt;/BODY&gt;\n",
  $self-&gt;create_html_page( "$filename",
			   "$content",
			   "$title",
			   "$rootdir",
			   0 ) ;
}

=pod

=item * getMyValidHTML()

Replies the list of W3C protocols for which this theme
was validated. You must override this method.

=cut
sub getMyValidHTML() {
  my $self = shift ;
  return () ;
}

sub mergeValidHTMLIcons($$$@) {
  my $self = shift ;
  if (int(@_)&gt;3) {

    #
    # A protocol is displayed as supported only if
    # the generator AND the theme support it, or
    # if the protocol was CSS and was supported
    # by the theme only (We assume that the generators
    # does not use any CSS syntax)
    #
    my @themevalid = $self-&gt;getMyValidHTML() ;
    my @valid = () ;
    for(my $i=3; $i&lt;int(@_); $i++) {
      if (strinarray("$_[$i]",\@themevalid)) {
	push @valid, "$_[$i]" ;
      }
    }
    if (strinarray('css',\@themevalid)) {
      push @valid, 'css' ;
    }

    if ($_[2]) {
      setAsValidHTML_small($_[0],$_[1],@valid) ;
    }
    else {
      setAsValidHTML($_[0],$_[1],@valid) ;
    }
  }
}

#------------------------------------------------------
#
# Paragraph API
#
#------------------------------------------------------

=pod

=item * frame_subpart()

Replies a subpart of a frame
Takes 3 args:

=over

=item * title (string)

is the title of the part.

=item * text (array)

is the content of the frame.

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub frame_subpart($$$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * frame_window()

Replies a frame
Takes 3 args:

=over

=item * title (string)

is the title of the frame.

=item * text (string)

is the content of the frame.

=item * prefix (optional string)

is a string which is put before the title

=back

=cut
sub frame_window($$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * partseparator()

Replies a part separator.

=cut
sub partseparator($) {
  my $self = shift ;
  return "&lt;HR&gt;\n" ;
}

=pod

=item * title()

Formats a page title
Takes 2 args:

=over

=item * text (string)

=item * text_before (optional boolean)

indicates if some text are before this title

=back

=cut
sub title($) {
  my $self = shift ;
  my $text = $_[0] || confess( 'you must specify the text' ) ;
  return
    ($_[1] ? $self-&gt;partseparator() : '') .
      "&lt;center&gt;&lt;h2&gt;$text&lt;/h2&gt;&lt;/center&gt;\n\n" ;
}

=pod

=item * subtitle()

Formats a page subtitle
Takes 1 arg:

=over

=item * text (string)

=item * text_before (optional boolean)

indicates if some text are before this title

=back

=cut
sub subtitle($) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  if ( ! $text ) {
    Bib2HTML::General::Error::syswarm( 'a title was expected' ) ;
  }
  return
    ($_[1] ? "&lt;hr&gt;\n" : '').
      "&lt;h2&gt;$text&lt;/h2&gt;\n" ;
}

=pod

=item * strong()

Formats a keyword
Takes 2 args:

=over

=item * text (string)

=back

=cut
sub strong($) {
  my $self = shift ;
  my $text = $_[0] || confess( 'you must specify the text' ) ;
  return "&lt;b&gt;$text&lt;/b&gt;" ;
}

=pod

=item * entry_title()

Formats the title of an BibTeX entry.
Takes 1 arg:

=over

=item * text (string)

=back

=cut
sub entry_title($) {
  my $self = shift ;
  my $title = $_[0] || '' ;
  if ( ! $title ) {
    Bib2HTML::General::Error::syswarm( 'a title was expected' ) ;
  }
  return join( '',
	       "&amp;quot;&lt;i&gt;&lt;b&gt;",
	       $title,
	       "&lt;/b&gt;&lt;/i&gt;&amp;quot;" ) ;
}

=pod

=item * format_date()

Formats a date.
Takes 2 args:

=over

=item * month (string)

=item * year (string)

=back

=cut
sub format_date($$) {
  my $self = shift ;
  my $month = $_[0] || '' ;
  my $year = $_[1] || confess( 'you must supply the year' ) ;
  return ($month?"$month&amp;nbsp;":"")."$year" ;
}

=pod

=item * href()

Replies a hyperlink.
Takes 3 args:

=over

=item * url (string)

is the URL to link to

=item * label (string)

is the label of the hyperlink

=item * target (optional string)

is the frame target.

=back

=cut
sub href($$) {
  my $self = shift ;
  my $url = $_[0] || confess( 'you must specify the URL' ) ;
  my $label = $_[1] ;
  return '' unless ($label) ;
  return join( '',
	       "&lt;A HREF=\"",
	       $url,
	       "\"",
	       ( $_[2] ? " target=\"$_[2]\"" : "" ),
	       "&gt;",
	       $label,
	       "&lt;/A&gt;" ) ;
}

=pod

=item * small()

Replies a text with a small size.
Takes 1 arg:

=over

=item * text (string)

=back

=cut
sub small($) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  return join( '',
	       "&lt;FONT SIZE=\"-1\"&gt;",
	       $text,
	       "&lt;/FONT&gt;\n" ) ;
}

=pod

=item * tiny()

Replies a text with a tiny size.
Takes 1 arg:

=over

=item * text (string)

=back

=cut
sub tiny($) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  return join( '',
	       "&lt;FONT SIZE=\"-2\"&gt;",
	       $text,
	       "&lt;/FONT&gt;\n" ) ;
}

=pod

=item * par()

Replies a paragraph.
Takes 1 arg:

=over

=item * text (string)

=back

=cut
sub par($) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  return join( '',
	       "&lt;P&gt;",
	       $text,
	       "&lt;/P&gt;\n" ) ;
}

=pod

=item * get_tree_node()

Replues the HTML string for the specified tree.
a list.
Takes 2 args:

=over

=item * node (string)

is the string that is the root of the tree.

=item * subs (string)

is an HTML string that describes the children.

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub get_tree_node($$$) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  my $sub = $_[1] || '' ;
  $sub = "&lt;ul&gt;$sub&lt;/ul&gt;" ;
  if ( $text ) {
    return "&lt;li type=\"circle\"&gt;".$text.$sub."&lt;/li&gt;\n" ;
  }
  else {
    return "$sub\n" ;
  }
}

=pod

=item * get_tree_leaf()

Replies a line of a tree which will be displayed inside
a list.
Takes 1 args:

=over

=item * node (string)

is the string that is the root of the tree.

=item * rootdir (string)

is the path to the root directory.

=back

=cut
sub get_tree_leaf($$) {
  my $self = shift ;
  my $text = $_[0] || '' ;
  return join( '',
               "&lt;li type=\"circle\"&gt;",
               $text,
               "&lt;/li&gt;\n" ) ;
}

=pod

=item * get_tree()

Creates a tree.
Takes 2 or 3 args:

=over

=item * tree (hash)

is the tree

=item * rootdir (string)

is the path to the root directory

=item * root label (optional string)

is the label of the root node

=back

=cut
sub get_tree($$;$) : method {
  my $self = shift ;
  my $tree = $_[0] || confess( "you must supply the tree" ) ;
  my $rootdir = $_[1] || confess( 'you must supply the root directory' ) ;
  my $content = $self-&gt;__get_default_tree__($tree,$rootdir) ;
  if ( $content ) {
    return "&lt;ul&gt;$content&lt;/ul&gt;\n" ;
  }
  else {
    return "$content" ;
  }
}

sub __get_default_tree__($$) {
  my $self = shift ;
  my $tree = $_[0] || confess( "you must supply the tree" ) ;
  my $rootdir = $_[1] || confess( 'you must supply the root directory' ) ;
  my $content = '' ;

  my @c = keys %{$tree};
  @c = sortbyletters(@c);
  foreach my $children (@c) {

    if ( isemptyhash($tree-&gt;{"$children"}) ) {
      # leaf
      $content .= $self-&gt;get_tree_leaf("$children",$rootdir) ;
    }
    else {
      # node
      my $sub = $self-&gt;__get_default_tree__($tree-&gt;{"$children"},$rootdir) ;
      $content .= $self-&gt;get_tree_node("$children",$sub,$rootdir) ;
    }

  }

  return $content ;
}

=pod

=item * get_navigation_bar()

Replies the navigation bar.
Takes 3 args:

=over

=item * url (string)

is the url of the generated page.

=item * params (hash ref)

is a set of parameters used to generate the bar.

=item * root (string)

is the root directory for the generated documentation.

=back

=cut
sub get_navigation_bar($$$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * section()

Replies a section
Takes 3 args:

=over

=item * title (string)

is the title of the new section.

=item * content (string)

is the content of the new section

=item * root (string)

is the root directory for the generated documentation.

=back

=cut
sub section($$$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

#------------------------------------------------------
#
# Array API
#
#------------------------------------------------------

=pod

=item * build_onecolumn_array()

Replies an one-column array.
Takes 2 args:

=over

=item * title (string)

is the title of the array

=item * cells (array ref)

is the content of the returned cells.

=back

=cut
sub build_onecolumn_array($$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * build_twocolumn_array()

Replies an two-column array.
Takes 2 args:

=over

=item * title (string)

is the title of the array

=item * cells (array ref)

is the content of the returned cells.

=back

=cut
sub build_twocolumn_array($$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * build_small_array()

Replies an small one-column array.
Takes 2 args:

=over

=item * title (string)

is the title of the array

=item * cells (array ref)

is the content of the returned cells.

=back

=cut
sub build_small_array($$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * build_tiny_array()

Replies a tiny one-column array.
Takes 2 args:

=over

=item * title (string)

is the title of the array

=item * cells (array ref)

is the content of the returned cells.

=back

=cut
sub build_tiny_array($$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

=pod

=item * build_threecolumn_array()

Replies an two-column array.
Takes 3 args:

=over

=item * title (string)

is the title of the array

=item * cells (array ref)

is the content of the returned cells.

=item * anchor (string)

is the name of the anchor.

=back

=cut
sub build_threecolumn_array($$$) : method {
  my $self = shift ;
  confess( 'you must overwrite this method' ) ;
}

#------------------------------------------------------
#
# Index API
#
#------------------------------------------------------

=pod

=item * format_index_page()

Replies a formatted page for the index.
Takes 3 args:

=over

=item * letterlist (string)

is the list of letters of the index.

=item * letter (string)

is the current letter.

=item * content (array ref)

is the content of the page.

=back

=cut
sub format_index_page($$$) : method {
  my $self = shift ;
  my $letterlist = $_[0] || '' ;
  my $letter = notempty( $_[1], 'you must supply the index letter for this page' ) ;

  my $content = join( '',
		      ( $letterlist ?
			$letterlist.$self-&gt;partseparator() : '' ),
		      "&lt;H2&gt;",
		      uc($letter),
		      "&lt;/H2&gt;\n",
		      "&lt;DL&gt;" ) ;

  my $previouslabel = '' ;
  my @currententry = () ;

  foreach my $entry (@{$_[2]}) {
    if ( "$previouslabel" eq $entry-&gt;{'label'} ) {
      # Caching this entry for futher display
      push @currententry, $entry ;
    }
    else {
      # Generate the page content
      $self-&gt;__generate_index_entry(\@currententry,$content,$entry);
    }

    $previouslabel = $entry-&gt;{'label'} ;
  }

  if ( @currententry ) {
    $self-&gt;__generate_index_entry(\@currententry,$content);
  }

  $content .= join( '',
		    "&lt;/DL&gt;",
		    ( $letterlist ?
		      $self-&gt;partseparator().$letterlist : '' ) ) ;

  return $content ;
}

sub __generate_index_entry($$;$) {
  my $self = shift ;

  # Generates the previous entries
  if ( @{$_[0]} == 1 ) {
    $_[1] .= join( '',
		   "&lt;DT&gt;",
		   $self-&gt;href( $_[0]-&gt;[0]{'url'},
				$_[0]-&gt;[0]{'label'} ),
		   ( $_[0]-&gt;[0]{'short_comment'} ?
		     " - ".$_[0]-&gt;[0]{'short_comment'} :
		     '' ),
		   "&lt;/DT&gt;&lt;DD&gt;",
		   $_[0]-&gt;[0]{'comment'},
		   "&amp;nbsp;&lt;/DD&gt;\n" ) ;
  }
  elsif ( @{$_[0]} &gt; 1 ) {
    $_[1] .= join( '',
		   "&lt;DT&gt;",
		   $_[0]-&gt;[0]{'label'},
		   "&lt;/DT&gt;&lt;DD&gt;&lt;UL&gt;" ) ;
    foreach my $entry_to_display (@{$_[0]}) {
      $_[1] .= join( '',
		     "&lt;LI&gt;",
		     $entry_to_display-&gt;{'comment'},
		     $self-&gt;href( $entry_to_display-&gt;{'url'},
				  "&lt;IMG src=\"./loupe.gif\" alt=\"\" ".
				  "border=\"0\" align=\"center\"&gt;" ),
		     "&lt;/LI&gt;\n"
		   ) ;
    }
    $_[1] .= "&lt;/UL&gt;&lt;/DD&gt;\n" ;
  }
  # Prepare the caching for this entry
  if ( $_[2] ) {
    @{$_[0]} = ( $_[2] ) ;
  }
}

#------------------------------------------------------
#
# Filename API
#
#------------------------------------------------------

=pod

=item * get_math_start_tag()

Replies the HTML balise which starts the math mode.

=cut
sub get_math_start_tag() : method {
  my $self = shift ;
  return "&lt;math&gt;" ;
}

=pod

=item * get_math_stop_tag()

Replies the HTML balise which stops the math mode.

=cut
sub get_math_stop_tag() : method {
  my $self = shift ;
  return "&lt;/math&gt;" ;
}

1;
__END__

=back

=head1 COPYRIGHT

(c) Copyright 1998-09 Stéphane Galland &lt;galland@arakhne.org&gt;, under GPL.

=head1 AUTHORS

=over

=item *

Conceived and initially developed by Stéphane Galland E&lt;lt&gt;galland@arakhne.orgE&lt;gt&gt;.

=back

=head1 SEE ALSO

bib2html.pl
</pre></body></html>