code:
# -*-perl-*-
#+##############################################################################
#
# roff.pm: convert to roff
#
# So much out of date that it may be considered unuseful.
#
#    Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
#
# 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 3 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.  If not, see <http://www.gnu.org/licenses/>.
#
# Originally written by Patrice Dumas.
#
#-##############################################################################

# FIXME obsolete
main::load_init_file('', 'noheaders.pm');

set_default('SPLIT', 0);
@EXPAND = ('info');
set_default('USE_ISO', 0);
$SMALL_RULE = '';
$DEFAULT_RULE = '';
$MIDDLE_RULE = '';
$BIG_RULE = '';
set_default('NODE_FILE_EXTENSION', 'roff');
set_default('EXTENSION', 'roff');
$MENU_SYMBOL = '*';
set_default('AVOID_MENU_REDUNDANCY', 0);

$print_Top           = \&T2H_ROFF_print_Top;
$print_misc		     = \&T2H_ROFF_print_misc;
$print_page_head     = \&T2H_ROFF_print_page_head;
$print_page_foot     = \&T2H_ROFF_print_page_foot;
$toc_body            = \&T2H_ROFF_toc_body;
$titlepage           = \&T2H_ROFF_titlepage;

sub T2H_ROFF_print_page_head
{
    my $fh = shift;
    print $fh <<EOT;
.nr _- 0
.tr \\(is'
.tr \\(if`
.tr \\(pd"

$AFTER_BODY_OPEN

EOT
    my $today = get_conf('today');
    print $fh $Texi2HTML::THISDOC{'copying_comment'} . "\n";
    print $fh "" . &$comment("Created by $Texi2HTML::THISDOC{'program_version'}, $Texi2HTML::THISDOC{'program_homepage'}\n");
    # FIXME this should instead be done in print_title
    print $fh ".ds St " . protect_spaces($Texi2HTML::THISDOC{'title'}) . "\n";
    print $fh '.oh \'\\\\*(St\'\'%\'' ."\n".'.eh \'%\'\'\\\\*(St\'' . "\n";
}

sub T2H_ROFF_print_page_foot
{
    my $fh = shift;
    my $program_string = program_string();
    print $fh <<EOT;
.br
.pp
$program_string
EOT
}

sub T2H_ROFF_print_Top($$)
{
    my $fh = shift;
    my $has_top_heading = shift;

    my $buttons = \@MISC_BUTTONS;
    &$print_head_navigation($fh, $buttons);
    # FIXME this is done in print_title now.
    # redo the titlepage with the actual state
    my ($titlepage_text, $titlepage_no_texi, $titlepage_simple_text) = main::do_special_region_lines('titlepage',$Texi2HTML::THISDOC{'state'});
    &$titlepage([],$titlepage_text, $titlepage_no_texi, $titlepage_simple_text);
    print $fh $Texi2HTML::TITLEPAGE;
    main::print_lines($fh, $Texi2HTML::THIS_SECTION);
}

# FIXME: use the vanilla print_misc instead, and add a
# $heading_text
sub T2H_ROFF_print_misc
{
    my $fh = shift;
    &$print_misc_header($fh);
    main::print_lines($fh);
    &$print_misc_footer($fh);
}

# FIXME obsolete, main one is right now, need to do a heading_text
sub T2H_ROFF_titlepage ($$$$)
{
    my $titlepage_lines = shift;
    my $titlepage_text = shift;
    my $titlepage_no_texi = shift;
    my $titlepage_simple_text = shift;

    my $result = '';
    if (@{$Texi2HTML::THISDOC{'titles'}}
        or @{$Texi2HTML::THISDOC{'subtitles'}}
        or @{$Texi2HTML::THISDOC{'authors'}})
    {
# FIXME obsolete, use $line_command instead
        foreach my $title (@{$Texi2HTML::THISDOC{'titles'}})
        {
            $result .= ".sz +10\n.ce\n" . protect_spaces($title) . "\n.sz -10\n";
        }
        foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}})
        {
            $result .= ".sz +4\n.ce\n" . protect_spaces($subtitle) . "\n.sz -4\n";
        }
        $result .= ".sp 4\n" if ($result ne '');
        foreach my $author (@{$Texi2HTML::THISDOC{'authors'}})
        {
            $result .= protect_spaces($author) . "\n.br\n";
        }
        $result .= ".sp 2\n" if (@{$Texi2HTML::THISDOC{'authors'}});
    }
    if (($result ne '') or ($Texi2HTML::TITLEPAGE ne ''))
    {
        $Texi2HTML::TITLEPAGE = ".tp\n" . $result . $titlepage_text . ".++ C\n";
    }
}

########################################################################
# Control of formatting:
# 1.) For some changes, it is often enough to change the value of
#     some global map. It might necessitate building a little
#     function along with the change in hash, if the change is the use
#     of another function (in style_map).
# 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines,
#     give them another name, and assign them to the respective
#     $<fnc> variable (below).

#
# This hash should have keys corresponding with the nonletter command accent
# whose following character is considered to be the argument
# This hash associates an accent macro to the ISO name for the accent if any.
# The customary use of this map is to find the ISO name appearing in html
# entity (like é) associated with a texinfo accent macro.
#
# The keys of the hash are
# ": umlaut
# ~: tilda accent
# ^: circumflex accent
# `: grave accent
# ': acute accent
# =: macron accent
%accent_map = (
          '"',  ':',
          '~',  '~',
          '^',  '^',
          '`',  '`',
          ',',  ',',
          "'", "'",
          '=', '',
         );

#
# texinfo "simple things" (@foo) to HTML ones
#
%simple_map = (
#           "*", "\n.br\n",
           ' ', '\ ',
           "\t", "\\\t",
           "\n", "\\\n",
     # "" or "" could also be possible for @-, but it seems
     # that some browser will consider this as an always visible hyphen mark
     # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html)
           '-', '',  # hyphenation hint
           '|', '',  # used in formatting commands @evenfooting and friends
           '/', '',
       # spacing commands
           ':', '',
           '!', '!',
           '?', '?',
           '.', '\&.',
           '@', '@',
           '}', '}',
           '{', '{',
          );

# this map is used in preformatted text
%simple_map_pre = %simple_map;

#
# texinfo "things" (@foo{}) to HTML ones
#
%things_map = (
               'TeX'          => 'TeX',
               'LaTeX'        => 'LaTeX',
               'bullet'       => '\(bu',
               'copyright'    => '\(co',
               'registeredsymbol' => '\(rg',
               'dots'         => '\&...',
               'enddots'      => '\&...',
               'equiv'        => '\(==',
# i18n
               'error'        => 'error->',
               'expansion'    => '\(->',
               'minus'        => '\-',
               'point'        => '*',
               'print'        => '-|',
               'result'       => '\(rh',
               # set in code using the language
               # 'today', &pretty_date,
               'aa'           => '\(oa',
               'AA'           => '\(oA',
               'ae'           => '\(ae',
               'oe'           => '\(oe',
               'AE'           => '\(AE',
               'OE'           => '\(OE',
               'o'            =>  '\(/o',
               'O'            =>  '\(/O',
               'ss'           => '\(ss',
               'l'            => '\(/l',
               'L'            => '\(/L',
               'exclamdown'   => '\(r!',
               'questiondown' => '\(r?',
               'pounds'       => '\(Po',
               'ordm'         => '\(Om',
               'ordf'         => '\(Of',
               'euro'         => '\(eu',
             );

# This map is used in preformatted environments
%pre_map = %things_map;

#%style_map = (
#      'acronym',    '',
#      'asis',       '',
#      'b',          ['\fB', '\fR'],
#      'cite',       ['\fI', '\fR'],
#      'code',       ['\fR\&\f(CW', '\fR'],
#      'command',    ['\fR\&\f(CW', '\fR'],
#      'ctrl',       ['\fR\&\f(CW', '\fR'],
#      'dfn',        ['\fI', '\fR'],
#      'dmn',        '',
#      'email',      ['\fB', '\fR'],
#      'emph',       ['\fI', '\fR'],
#      'env',        ['\fR\&\f(CW', '\fR'],
#      'file',       ['\fR\&\f(CW', '\fR', '"'],
#      'i',          ['\fI', '\fR'],
#      'kbd',        ['\fR\&\f(CW', '\fR'],
#      'key',        ['\fR\&\f(CW', '\fR'],
#      'math',       ['\fR\&\f(CW', '\fR'],
#      'option',     ['\fR\&\f(CW', '\fR', '"'],
#      'r',          ['\fR', ''],
#      'samp',       ['\fR\&\f(CW', '\fR', '"'],
#      'sc',         '&roff_sc',
#      'strong',     ['\fB', '\fR'],
#      't',          ['\fR\&\f(CW', '\fR'],
#      'uref',       '&default_uref',
#      'url',        '&default_url',
#      'var',        ['\fI', '\fR'],
#      'verb',       ['\fR\&\f(CW', '\fR'],
#      'titlefont',  ["\n.sz +10\n.ce\n", "\n.sz -10\n"],
#      'w',          '',
#      'H',          '&roff_accent',
#      'dotaccent',  '&roff_accent',
#      'ringaccent', '&roff_accent',
#      'tieaccent',  '&roff_accent',
#      'u',          '&roff_accent',
#      'ubaraccent', '&roff_accent',
#      'udotaccent', '&roff_accent',
#      'v',          '&roff_accent',
#      ',',          '&roff_accent',
#      'dotless',    ''
#     );

my @bold_commands = ('strong', 'b', 'email');
my @italic_commands = ('cite', 'dfn', 'emph', 'i', 'var', 'slanted');
my @fixed_command = ('code', 'command', 'ctrl', 'env', 'file', 'kbd', 'key',
   'math', 'option', 'samp', 't', 'verb');

foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents), keys(%accent_map))
{
     #$style_map{$accent_command} = { 'function' => \&t2h_roff_accent };
     $style_map{$accent_command} = '&roff_accent';
}
#foreach my $accent (keys(%accent_map))
#{
#    $style_map{$accent} = '&roff_accent';
#}

foreach my $command (keys(%style_map))
{
    delete $style_map{$command}->{'attribute'} if (exists($style_map{$command}->{'attribute'}));
    if (grep {$_ eq $command} @bold_commands)
    {
        delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
        $style_map{$command}->{'begin'} = '\fB';
        $style_map{$command}->{'end'} = '\fR';
        next;
    }
    elsif (grep {$_ eq $command} @italic_commands)
    {
        delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
        $style_map{$command}->{'begin'} = '\fI';
        $style_map{$command}->{'end'} = '\fR';
        next;
    }
    elsif (grep {$_ eq $command} @fixed_commands)
    {
        delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
        $style_map{$command}->{'begin'} = '\fR\&\f(CW';
        $style_map{$command}->{'end'} = '\fR';
        next;
    }
}

delete $style_map{'titlefont'}->{'function'} if (exists($style_map{'titlefont'}->{'function'}));
$style_map{'titlefont'}->{'begin'} = "\n.sz +10\n.ce\n";
$style_map{'titlefont'}->{'end'} = "\n.sz -10\n";

delete $style_map{'r'}->{'function'} if (exists($style_map{'r'}->{'function'}));
$style_map{'r'}->{'begin'} = '\r';
#$style_map{'r'}->{'end'} = '';

$style_map{'sc'} = '&roff_sc';

$style_map{'indicateurl'}->{'begin'} = '<';
$style_map{'indicateurl'}->{'end'} = '>';

foreach my $command (keys(%style_map))
{
    if (ref($style_map{$command}) ne 'HASH')
    {
         $style_map_pre{$command} = $style_map{$command};
         next;
    }
    $style_map_pre{$command} = {};
    foreach my $key (keys(%{$style_map{$command}}))
    {
        $style_map_pre{$command}->{$key} = $style_map{$command}->{$key};
    }
}

%special_accents = (
      'ringaccent' => 'aA',
      "'"          => 'aeiouyAEIOUY',
      ','          => 'cC',
      '^'          => 'aeiouAEIOU',
      '`'          => 'aeiouAEIOU',
      '~'          => 'nNaoAO',
      '"'          => 'aeiouyAEIOUY',
      'v'          => 'sSzZ',
);

sub roff_accent($$)
{
    my $text = shift;
    my $accent = shift;
    return $text if ($accent eq 'dotless');
    return "\\($accent_map{$accent}${text}" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
    return "\\(o${text}"  if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
    return "\\(v${text}" if (($accent eq 'v') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
#FIXME maybe we should protect the symbols such that they look like strings and
# not ponctuation marks ? Like it is done in texi2roff ?
    return $text . '\\&.' if ($accent eq 'dotaccent');
    return '\\&.' . $text  if ($accent eq 'udotaccent');
    return ascii_accents($text, $accent);
}

sub roff_sc($$)
{
    return "\n.sz -6\n" . uc($_[0]) . "\n.sz +6\n" ;
}

sub roff_ctrl($$)
{
   return "\\*^$_[0]";
}

$format = \&T2H_ROFF_format;

sub T2H_ROFF_format($$$)
{
    my $tag = shift;
    my $element = shift;
    my $text = shift;
    return '' if (!defined($element) or ($text !~ /\S/));
    return $element->[0] . $text . $element->[1];
}

%format_map = (
       'quotation'   =>  [ ".(q\n", ".)q\n" ],
       'smallquotation'   =>  [ ".(q\n", ".)q\n" ],
       # lists
       'itemize'     =>  [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
       'enumerate'   =>  [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
       'multitable'  =>  [ ".(l M\n.nh\n", ".hy\n.)l\n" ],
       'table'       =>  [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
       'vtable'      =>   [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
       'ftable'      =>   [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
       );

%special_list_commands = (
       'table'        =>  {},
       'vtable'       =>  {},
       'ftable'       =>  {},
       'itemize'      =>  {}
       );

$complex_format_map =
(
 'example' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => ".(l I\n\\&\\fR\\f(CW",
  'end_region' => "\\&\\fR\n.)l\n"
 },
 'smallexample' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => ".(l I\n.size -2\n\\&\\fR\\f(CW",
  'end_region' => "\\&\\fR\n.size +2\n.)l\n"
 },
 'display' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => ".(l I\n\\&\\fR\\f(CW",
  'end_region' => "\\&\\fR\n.)l\n"
 },
 'smalldisplay' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => ".(l I\n.size -2\n\\&\\fR\\f(CW",
  'end_region' => "\\&\\fR\n.size +2\n.)l\n"
 },
 'menu-comment' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => "",
  'end_region' => "\n"
 },
 'menu-preformatted' =>
 {
  'begin' => "",
  'end' => "",
  'begin_region' => "",
  'end_region' => "\n"
 }
);

# format shouldn't narrow the margins

$complex_format_map{'lisp'} =  $complex_format_map{'example'};
$complex_format_map{'smalllisp'} = $complex_format_map{'smallexample'};
$complex_format_map{'format'} = $complex_format_map{'display'};
$complex_format_map{'smallformat'} = $complex_format_map{'smalldisplay'};

sub protect_spaces($)
{
    my $text = shift;
    my $result = '';
    while($text)
    {
        if ($text =~ s/^([^\\]*)\\//o)
        {
            my $leading = $1;
            if (defined($leading))
            {
                 $leading =~ s/([\t ])/\\$1/go;
                 $result .= $leading . '\\';
            }
            if (($text =~ s/^(\s)//o) or ($text =~ s/^(.)//o))
            {
                 $result .= $1;
            }
        }
        else
        {
            $text =~ s/([\t ])/\\$1/go;
            $result .= $text;
            $text = '';
        }
    }
    return $result;
}

# formatting functions

$anchor            = \&t2h_roff_anchor;
$def_item          = \&t2h_roff_def_item;
$def               = \&t2h_roff_def;
$menu              = \&t2h_roff_menu;
$menu_link         = \&t2h_roff_menu_link;
$menu_comment      = \&t2h_roff_menu_comment;
$menu_description  = \&t2h_roff_menu_description;
$simple_menu_link  = \&t2h_roff_simple_menu_link;
$table_item        = \&t2h_roff_table_item;
$table_line        = \&t2h_roff_table_line;
$row               = \&t2h_roff_row;
$cell              = \&t2h_roff_cell;
$list_item         = \&t2h_roff_list_item;
$comment           = \&t2h_roff_comment;
$def_line	       = \&t2h_roff_def_line;
$raw               = \&t2h_roff_raw;
$heading           = \&t2h_roff_heading;
$paragraph         = \&t2h_roff_paragraph;
$preformatted      = \&t2h_roff_preformatted;
$foot_line_and_ref = \&t2h_roff_foot_line_and_ref;
$foot_section      = \&t2h_roff_foot_section;
$image             = \&t2h_roff_image;
$index_entry_label = \&t2h_roff_index_entry_label;
$index_summary     = \&t2h_roff_index_summary;
$print_index       = \&t2h_roff_print_index;
$protect_text      = \&t2h_roff_protect_text;
$cartouche         = \&t2h_roff_cartouche;
$sp                = \&t2h_roff_sp;
$normal_text       = \&t2h_roff_normal_text;
$empty_line        = \&t2h_roff_empty_line;
$unknown           = \&t2h_roff_unknown;
$float             = \&t2h_roff_float;
$listoffloats      = \&t2h_roff_listoffloats;
$listoffloats_entry = \&t2h_roff_listoffloats_entry;

# This function is used to protect characters which are special in html
# in inline text:  &, ", <, and >.
#
# argument:
# text to be protected
sub t2h_roff_protect_text($)
{
   my $text = shift;
   $text =~ s/\\/\\e/g;
#   $text =~ s/$;---$;/\\(em/g;
#   $text =~ s/$;--$;/-/g;
#   $text =~ s/$;-$;/\\-/g;
   $text =~ s/^\./\\&./;
   $text =~ s/([\s])\./$1\\&./g;
   return $text;
}

sub t2h_roff_normal_text($$$$$$$;$)
{
   my $text = shift;
   my $in_raw_text = shift;
   my $in_preformatted = shift;
   my $in_code =shift;
   my $in_math = shift;
   my $in_simple = shift;
   my $style_stack = shift;
   my $state = shift;

   $text = &$protect_text($text) unless($in_raw_text);
   if (! $in_code and !$in_preformatted and !$in_raw_text)
   {
       $text =~ s/---/\\(em/g;
       $text =~ s/--/\\(en/g;
       $text =~ s/-/\\-/g;
       $text =~ s/``/\\(lq/g;
       $text =~ s/''/\\(rq/g;
    }
    #$text =~ s/---/\\(em/g;
    #$text =~ s/(--?-?)/$;$1$;/go;
    return $text;
}

sub t2h_roff_unknown($$$)
{
    my $macro = shift;
    my $line = shift;
    my $pass = shift;

    if ($macro eq '*' and $pass == 2)
    {
        $line = '' if ($line =~ /^\s*$/);
        return ($line, 1, "\n.br\n", undef);
    }
    return ($line, 0, undef, undef);
}

# This function produces an anchor
#
# arguments:
# $name           :   anchor name
# $href           :   anchor href
# text            :   text displayed
# extra_attribs   :   added to anchor attributes list
sub t2h_roff_anchor($;$$$)
{
    my $name = shift;
    my $href = shift;
    my $text = shift;
    my $attributes = shift;
    $href = '' if (!defined($href) or ($href !~ /\S/));
    $text = '' if (!defined($text));
    return $text if ($text ne '');
    return "[$href]" if ($href ne '');
    return '';
}

# This function is used to format the text associated with a @deff/@end deff
#
# argument:
# text
sub t2h_roff_def_item($)
{
    my $text = shift;
    if ($text =~ /\S/)
    {
        {
            #return ".ba +5\n.(l L F\n" . $text . ".)l\n.ba -5\n";
            return ".(l L F\n.ba +5\n" . $text . ".ba -5\n.)l\n";
        }
    }
    return '';
}

# format the container for the @deffn line and text
#
# argument
# text of the whole @def, line and associated text.
sub t2h_roff_def($)
{
    my $text = shift;
    return $text;
}

# a whole menu
#
# argument:
# the whole menu text (entries and menu comments)
#
# argument:
# whole menu text.
sub t2h_roff_menu($)
{
    my $text = shift;
    chomp $text;
    return ".(l M\n\\&\\s8" . gdt('Menu:') . "\n" . $text . "\\&\\s0\n.)l\n";
}

# a simple menu entry ref in case we aren't in a standard menu context
sub t2h_roff_simple_menu_link($$$$$$$)
{
    my $entry = shift;
    my $preformatted = shift; # We assume this is true.
    my $href = shift;
    my $node = shift;
    my $title = shift;
    my $ending = shift;
    my $has_title = shift;
    $title = '' unless ($has_title);
    $title .= ':' if ($title ne '');
    return "$MENU_SYMBOL$title$node$ending";
}

# formats a menu entry link pointing to a node or section
#
# arguments:
# the entry text
# the state, a hash reference holding informations about the context, with a
#     usefull entry, 'preformatted', true if we are in a preformatted format
#     (a format keeping space between words). In that case a function
#     of the main program, main::do_preformatted($text, $state) might
#     be used to format the text with the current format style.
# href is optionnal. It is the reference to the section or the node anchor
#     which should be used to make the link (typically it is the argument
#     of a href= attribute in a <a> element).
sub t2h_roff_menu_link($$$$$$)
{
    my $entry = shift;
    my $state = shift;
    my $href = shift;
    my $node = shift;
    my $title = shift;
    my $ending = shift;
    my $has_title = shift;
    $title = '' unless ($has_title);
    $title .= ':' if ($title ne '');
    return "$MENU_SYMBOL$title$node$ending";
}

# formats a menu entry description, ie the text appearing after the node
# specification in a menu entry an spanning until there is another
# menu entry, an empty line or some text at the very beginning of the line
# (we consider that text at the beginning of the line begins a menu comment)
#
# arguments:
# the description text
# the state. See menu_entry.
sub t2h_roff_menu_description($$)
{
   my $text = shift;
   my $state = shift;
   return $text;
}

# a menu comment (between menu lines)
# formats the container of a menu comment. A menu comment is any text
# appearing between menu lines, either separated by an empty line from
# the preceding menu entry, or a text beginning at the first character
# of the line (text not at the very beginning of the line is considered to
# be the continuation of a menu entry description text).
#
# The text itself is considered to be in a preformatted environment
# with name 'menu-commment' and with style $MENU_PRE_STYLE.
#
# argument
# text contained in the menu comment.
sub t2h_roff_menu_comment($)
{
   my $text = shift;
   return $text;
}

# text after @item in table, vtable and ftable
sub t2h_roff_table_item($$$$$)
{
    my $text = shift;
    my $index_label = shift;
    my $format = shift;
    my $command = shift;
#    my $formatted_command = shift;
    my $style_stack = shift;
#    my $text_formatted = shift;
#    my $text_formatted_leading_spaces = shift;
#    my $text_formatted_trailing_spaces = shift;
    my $item_cmd = shift;

#    if (defined($text_formatted))
#    {
#        $text = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces;
#    }
#    $formatted_command = '' if (!defined($formatted_command) or
#          exists($special_list_commands{$format}->{$command}));
    $text = '.ip ' . $formatted_command . protect_spaces($text) . "\n";
    $text .= $index_label  if (defined($index_label));
    return $text;
}

# format text on the line following @item (in table, vtable and ftable)
sub t2h_roff_table_line($)
{
    my $text = shift;
    return $text;
}

# row in multitable
sub t2h_roff_row($)
{
    my $text = shift;

    if ($text =~ /\S/)
    {
         return $text ."\n" ;
    }
    return '';
}

# cell in multitable
sub t2h_roff_cell($)
{
    my $text = shift;
    chomp $text;
    return  protect_spaces($text) . "\\\t";
}

# format an item in a list
#
# argument:
# text of the item
sub t2h_roff_list_item($$$$$$$)
{
    my $text = shift;
    my $format = shift;
    my $command = shift;
    my $formatted_command = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    $formatted_command = '' if (!defined($formatted_command) or
          exists($special_list_commands{$format}->{$command}));
    if ($text =~ /\S/)
    {
        #return $formatted_command . $text;
        return $text . "\n";
    }
    return '';
}

# an comment
sub t2h_roff_comment($)
{
    my $text = shift;
    my $result = '';
    while ($text)
    {
        $text =~ s/$;---$;/--/g;
        $text =~ s/$;--$;/-/g;
        $text =~ s/$;-$;/-/g;
        $text =~ s/^(.*)//;
        $result .= ".\\\"$1";
        $result .= "\n" if ($text =~ s/^\n//);
    }
    return $result;
}

# a paragraph
sub t2h_roff_paragraph($$$$$$$$$$)
{
    my $text = shift;
    my $align = shift;
    my $indent = shift;
    my $paragraph_command = shift;
    my $paragraph_command_formatted = shift;
    my $paragraph_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    return '' if ($text =~ /^\s*$/);
    if (defined($paragraph_number) and defined($$paragraph_number))
    {
         $$paragraph_number++;
         $paragraph_command_formatted = undef if ($$paragraph_number > 1);
    }
#    $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or
#          exists($special_list_commands{$format}->{$paragraph_command}));
    #return $text if (defined($format) and $format eq 'multitable');
    return $text if (defined($format) and (($format eq 'multitable') or ($format eq 'quotation') or ($format eq 'smallquotation')));
    my $open = ".pp\n";
    if (defined($format) and (($format eq 'itemize') or ($format eq 'enumerate')) and
         defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1))
    {
         $open = ".lp\n";
    }
    my $close = '';
    if ($align)
    {
        if ($align eq 'flushleft')
        {
            $open .= ".ad l\n";
            $close .= ".ad b\n";
        }
        elsif ($align eq 'flushright')
        {
            $open .= ".ad r\n";
            $close .= ".ad b\n";
        }
        elsif ($align eq 'center')
        {
            $open .= ".ce\n";
        }
    }
    if (defined($format) and ($format eq 'enumerate') and
         defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1) and defined($number) and ($number ne ''))
    {
         $open .= "$number.";
    }
    chomp ($text);
    #return $open. $paragraph_command_formatted . $text . "\n" . $close;
    return $open. $text . "\n" . $close;
}

# a preformatted region
sub t2h_roff_preformatted($$$$$$$$$$)
{
    my $text = shift;
    my $pre_style = shift;
    my $class = shift;
    my $leading_command = shift;
    my $leading_command_formatted = shift;
    my $preformatted_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    $leading_command_formatted = '' if (!defined($leading_command_formatted) or
        exists($special_list_commands{$format}->{$leading_command}));

    if (defined($format) and $format eq 'multitable')
    {
        my $chomped = chomp($text);
        my $result  = '\&\fR\f(CW' . $text . '\&\fR';
        $result .= "\n" if ($chomped);
        return $result;
    }
    return '' if ($text eq '');
    if (defined($preformatted_number) and defined($$preformatted_number))
    {
         $$preformatted_number++;
         $leading_command_formatted = undef if ($$preformatted_number > 1);
    }
    $leading_command_formatted = '' if (!defined($leading_command_formatted));
    chomp $text;
    my $open = '';
    if (defined($format) and ($format eq 'enumerate') and
         defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1) and defined($number) and ($number ne ''))
    {
         $open = "$number. ";
    }
    return $complex_format_map{$class}->{'begin_region'} . $leading_command_formatted . $open . $text . $complex_format_map{$class}->{'end_region'};
}

# This function formats a heading for an element
#
# argument:
# an element. It is a hash reference for a node or a sectioning command.
# The interesting keys are:
# 'text': the heading text
# 'name': the heading text without section number
# 'node': true if it is a node
# 'level': level of the element. 0 for @top, 1 for chapter, heading,
#      appendix..., 2 for section and so on...
# 'tag_level': the sectioning element name, raisesections and lowersections
#      taken into account
sub t2h_roff_heading($$$$$;$$)
{
    my $element = shift;
    my $command = shift;
    my $texi_line = shift;
    my $line = shift;
    my $in_preformatted = shift;
    my $one_section = shift;
    my $element_heading = shift;

    my $name = $element->{'text'};
    if (!$element->{'node'})
    {
        $name = $element->{'name'};
    }
    return '' if ($element->{'name'} !~ /\S/);
    my $class = $element->{'tag_level'};
    $class = 'unnumbered' if ($class eq 'top');
    $level = $element->{'level'};
    $level = 3 if (!defined($level));
    $level = 1 if ($level == 0);
    my $heading = '';
    $heading = ".bp\n" if ($level == 1);
    $heading .= '.if !\n(_- \{\\' . "\n.nr _- 1\n.nr \$1 0 1\n" . '.af $1 A\}' . "\n"
        if ($class =~ /^appendix/);
    $name = protect_spaces($name);
    my $toc_entry = '\&';
    if ($class =~ /^unnumbered/ or ($class eq 'node'))
    {
        $heading .= ".uh $name\n";
        $toc_entry .= ' ';
    }
    elsif (($class =~ /section$/) or ($class eq 'chapter') or ($class =~ /^appendix/))
    {
        $heading .= ".sh $level $name\n";
        my $number = 1;
        while ($number < $level)
        {
            $toc_entry .= "\\n(\$$number.";
            $number++;
        }
        $toc_entry .= "\\n(\$$number ";
    }
    $toc_entry .= $name;
    return $heading . "\n" if ($class eq 'node');
    return $heading . ".(x\n" . $toc_entry . "\n.)x\n\\&\\fR\n";
}

sub T2H_ROFF_toc_body($$$)
{
    my $elements_list = shift;
    my $do_contents = shift;
    my $do_scontents = shift;
    if ($do_contents or $do_scontents)
    {
        my $lines = ".pp\n.nr % 0 1\n.af % i\n.bp \\n%+1\n.ce\n\\&\\fB" . gdt('Table of Contents') . "\\fR\n.sp 2\n.xp\n";
        if (!$do_contents)
        {
            push @{$Texi2HTML::OVERVIEW}, $lines;
        }
        else
        {
            push @{$Texi2HTML::TOC_LINES}, $lines;
        }
    }
}

# formatting of raw regions
# ih L2H is true another mechanism is used for tex
sub t2h_roff_raw($$)
{
    my $style = shift;
    my $text = shift;
    my $expanded = 1 if (grep {$style eq $_} @EXPAND);
    if ($style eq 'verbatim' or $style eq 'verbatiminclude' or ($expanded and ($style eq 'tex' or $style eq 'html')))
    {
        chomp ($text);
        return ".(l M\n\\fR\\&\\f(CW" . &$protect_text($text) . "\\fR\n.)l\n" ;
    }
    elsif ($expanded)
    {
        main::msg_debug ("(bug) unknown style $style");
        return &$protect_text($text);
    }
    return '';
}

# This function formats a footnote reference and the footnote text associated
# with a given footnote.
# The footnote reference is the text appearing in the main document pointing
# to the footnote text.
#
# arguments:
# absolute number of the footnote (in the document)
# relative number of the footnote (in the page)
# identifier for the footnote
# identifier for the footnote reference in the main document
# main document file
# footnote text file
# array with the footnote text lines
# the state. See menu entry.
#
# returns:
# reference on an array containing the footnote text lines which should
#     have been updated
# the text for the reference pointing on the footnote text
sub t2h_roff_foot_line_and_ref($$$$$$$)
{
    my $number_in_doc = shift;
    my $number_in_page = shift;
    my $footnote_id = shift;
    my $place_id = shift;
    my $document_file = shift;
    my $footnote_file = shift;
    my $lines = shift;
    my $state = shift;

    my $text = '';
    my $line;
    while (@$lines)
    {
         $line = shift @$lines;
         $text .= $line;
    }
    chomp $text;
    return ([], "\n.(f\n" . $text . "\n.)f\n" );
}

# formats a group of footnotes.
#
# argument:
# array reference on the footnotes texts lines
#
# returns an array reference on the group of footnotes lines
sub t2h_roff_foot_section($)
{
    my $lines = shift;
    @$lines = ();
}

# format an image
#
# arguments:
# image file name
# image basename
# a boolean true if we are in a preformatted format
sub t2h_roff_image($$$$)
{
   my $file = shift;
   my $base = shift;
   my $preformatted = shift;
   my $file_name = shift;
   return "[$base src=$file_name]" if ($base ne $file_name);
   return "[$base]";
}

# format a target in the main document for an index entry.
#
# arguments:
# target identifier
# boolean true if in preformatted format
sub t2h_roff_index_entry_label($$$$$$$$$)
{
    my $identifier = shift;
    my $preformatted = shift;
    my $entry = shift;
    my $index_name = shift;
    my $index_command = shift;
    my $texi_entry = shift;
    my $formatted_entry = shift;
    my $in_region_not_in_output = shift;
    my $index_entry_ref = shift;

    return ".(x $index_name\n" . protect_spaces($entry) . "\n.)x\n";
}

# process definition commands line @deffn for example
sub t2h_roff_def_line($$$$$)
{
   my $category = shift;
   my $name = shift;
   my $type = shift;
   my $arguments = shift;
   my $index_label = shift;
   $index_label = '' if (!defined($index_label));
   $name = '' if (!defined($name) or ($name =~ /^\s*$/));
   $type = '' if (!defined($type) or $type =~ /^\s*$/);
   if (!defined($arguments) or $arguments =~ /^\s*$/)
   {
       $arguments = '';
   }
   else
   {
       $arguments = '\fI' . protect_spaces($arguments) . '\fR';
   }
   my $type_name = ' ';
   $type_name = " $type" if ($type ne '');

   $type_name .= '\fB' . protect_spaces($name) . '\fR' if ($name ne '');
   $type_name .= $arguments . "\n";
   return '\fI' . protect_spaces($category) . ':\fR' . $type_name . $index_label;
}

# a cartouche
sub t2h_roff_cartouche($$)
{
    my $text = shift;
    return $text;
}

sub t2h_roff_sp($$)
{
   my $number = shift;
   my $preformatted = shift;
   return "\n.sp $number\n";
}

# format a whole index
#
# argument:
# index text
# index name
sub t2h_roff_print_index($$)
{
    my $text = shift;
    my $name = shift;
    return ".xp $name\n";
}

# format an index summary. This is a list of letters linking to the letter
# entries.
#
# arguments:
# array reference containing the formatted alphabetical letters
# array reference containing the formatted non lphabetical letters
sub t2h_roff_index_summary($$)
{
    my $alpha = shift;
    my $nonalpha = shift;
    my $join = '';
    my $nonalpha_text = '';
    my $alpha_text = '';
    return '';
}

# FIXME the following construct leads to something wrong ?
# something @c a comment
#
# other thing
sub t2h_roff_empty_line($)
{
    my $text = shift;
    return '';
}

sub t2h_roff_listoffloats_entry($$$$)
{
    my $style_texi = shift;
    my $float = shift;
    my $float_style = shift;
    my $caption = shift;
    my $href = shift;
	chomp ($caption);

    return '.ip ' . protect_spaces($float_style) . "\n" . $caption . "\n";
}

sub t2h_roff_listoffloats($$$)
{
    my $style_texi = shift;
    my $style = shift;
    my $float_entries = shift;

    my $result = ".(l L F\n.ba +5\n";
    foreach my $float_entry (@$float_entries)
    {
         $result .= $float_entry;
    }
    return $result . ".ba -5\n.)l\n";
}

sub t2h_roff_float($$$$$)
{
    my $text = shift;
    my $float = shift;
    my $caption = shift;
    my $shortcaption = shift;

    my $caption_text = '';

    if (defined($float->{'caption_texi'}))
    {
         $caption_text = $caption;
    }
    elsif (defined($float->{'shortcaption_texi'}))
    {
         $caption_text = $shortcaption;
    }
    elsif (defined($caption))
    {
         $caption_text = $caption;
    }
    chomp ($caption_text);
    return  ".(b L F\n" . $text . $caption_text . "\n.b)\n";
}

1;


code:
/*
 * Copyright 2009, Free Software Foundation, Inc.
 *
 * Copying and distribution of this file, with or without
 * modification, are permitted in any medium without royalty provided
 * the copyright notice and this notice are preserved.
 */

body {
    font: 1em/1.5em georgia,serif;
    max-width: 50em;
    margin: auto;
    padding: 0;
    padding: 30px 0 60px 0;
}

h1, h2, h3, h4, h5 {
    font-family: "Trebuchet MS", "Tahoma","Helvetica","Arial",sans-serif;
    letter-spacing: 0px;
    word-spacing: 0px;
    font-weight: normal;
}

h2.unnumbered {
    font-size: 34px;
    margin: 30px 0 60px 0;
    text-align: right;
}

/*
h2.unnumbered + p, h2.unnumbered + p + p {
    font-size: 14px;
}
*/

h2.chapter {
    font-size: 26px;
    margin: 30px 0;
    text-align: left;
}

h3 {
    font-size: 22px;
}

h4 {
    font-size: 18px;
}

a {
    color: midnightblue;
}

a:visited {
    color: indigo;
}

a:active, a:hover, a:visited:hover {
    color: crimson;
}

p, dd {
    text-align: justify;
}

dt {
    font-style: italic;
}

pre, tt, code, kbd, samp {
    font-size: 12px;
    line-height: 20px;
}

repo_name: mthl/texinfo

license: mit


code:
/* === === === === === === === === === === === === === === === === ===

   This file: texinfo-bright-colors.css
   Version:   1.01
   Date:      September 17, 2010
   Author:    Jaakko Hollmén, e-mail: Jaakko.Hollmen@tkk.fi

   The purpose of this cascading style sheet (CSS) style file named
   "texinfo-bright-colors.css" is to introduce several bright and
   contrasting colors for the structural elements of an HTML file.
   The primary focus of the CSS style is to observe the sturucture
   of HTML files created with Texinfo documentation system, more
   specifically texi2html.

   This is NOT a presentation style but a visualization of the
   structure of an HTML file through coloring of the elements. The
   style file may turn out to be useful for both developers of the
   HTML outputting tools and the Texinfo documentation writers who
   are interested in the outputted HTML structure.

   The coloring has been achieved by associating a background-color
   defined in the CSS file to important HTML elements. Minimal
   formatting has been done, except some expanded space has been
   introduced to horizontal rulers hr in order to make them more
   visible. There are margins around the document resembling a
   book-like presentation in the browser.

   This Cascading Style Sheet (CSS) file confroms to the CSS
   standard, level 2.1. You can validate the correctness of your
   own CSS style file or modification of the current CSS style file
   at the Web address: http://jigsaw.w3.org/css-validator/ by one
   the three input methods available.

   If you edit your already produced HTML file generated by hand,
   change the <style> .... </style> section in the header part of
   the HTML file with the following line:

   <link rel="stylesheet" href="texinfo-bright-colors.css">

   This line must be contained in the <header> ... </header>
   section of the HTML file. Alternatively, you can include the CSS
   style file when compiling as follows:

   texi2dvi --css-include=texinfo-bright-colors.css my-doc.texi

   Note: The output will be very colorful (!), you have been warned.

   --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

   (c) Copyright, Jaakko Hollmén, Finland, Jaakko.Hollmen@tkk.fi
       September, 2010

   The current file "texinfo-bright-colors.css" 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 3 of the License, or (at your option)
   any later version.

   The current file "texinfo-bright-colors.css" 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.

   === === === === === === === === === === === === === === === === */

body {
margin: 30px 10% 30px 10%;
background-color: white;
}

h1 {
  background-color: #FF0000;
}

h2 {
  background-color: #FF0066;
}

h3 {
  background-color: #FF00CC;
}

h4 {
  background-color: #FF33FF;
}

h5 {
  background-color: #FF99FF;
}

p {
  background-color: #B0B0B0;
}

blockquote {
  background-color: #FFCCFF;
}

div.shortcontents {
  background-color: #FF9900;
}

div.contents {
  background-color: #FF9900;
}

div.defun {
  background-color: #FF9900;
}

div.float {
  background-color: #FF9900;
}

div.footnote {
  background-color: #FF9900;
}

div.node {
  background-color: #FF9900;
}

ul {
  background-color: #FF9900;
}

ol {
  background-color: #CCFF33;
}

table {
  background-color: #FFFF00;
}

tr {
  background-color: #66FF00;
}

td {
  background-color: #66CC00;
}

dl {
  background-color: #00FF00;
}

dt {
  background-color: #66CC00;
}

dd {
  background-color: #00FFFF;
}

pre.display {
  background-color: #33CCFF;
}

pre.smalldisplay {
  background-color: #33CCFF;
}

pre.example {
  background-color: #33CCFF;
}

pre.smallexample {
  background-color: #33CCFF;
}

pre.format {
  background-color: #33CCFF;
}

pre.smallformat {
  background-color: #33CCFF;
}

pre.lisp {
  background-color: #33CCFF;
}

pre.smalllisp {
  background-color: #33CCFF;
}

pre.sp {
  background-color: #33CCFF;
}

pre.verbatim {
  background-color: #33CCFF;
}

code {
  background-color: #00FF00;
}

hr {
  background-color: #000000;
  padding-top: 0.2em;
  padding-bottom: 0.2em;
}


code:
# -*-perl-*-
#+##############################################################################
#
# utf8.pm: convert accented letters to utf8
#
# This style doesn't work when outputting info.
#
#    Copyright (C) 2004, 2006 Free Software Foundation, Inc.
#
# 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 3 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.  If not, see <http://www.gnu.org/licenses/>.
#
# Originally written by Patrice Dumas.
#
#-##############################################################################
set_default('USE_ISO', 0);
set_from_init_file('ENCODING_NAME', 'utf-8');

use Encode;
use Unicode::Normalize;

foreach my $key (keys(%unicode_accents), 'dotless')
{
    $style_map{$key}->{'function'} = \&t2h_utf8_accent;
    $style_map_texi{$key}->{'function'} = \&t2h_utf8_accent;
    $style_map_pre{$key}->{'function'} = \&t2h_utf8_accent;
}

foreach my $key (%things_map)
{
    if (exists($unicode_map{$key}) and ($unicode_map{$key} ne ''))
    {
        $things_map{$key} = chr(hex($unicode_map{$key}));
        $texi_map{$key} = chr(hex($unicode_map{$key}));
        $sorting_things_map{$key} = chr(hex($unicode_map{$key}));
        $pre_map{$key} = chr(hex($unicode_map{$key}));
    }
}

$normal_text       = \&t2h_utf8_normal_text;

1;


code:
# -*-perl-*-
#+##############################################################################
#
# xhtml.pm: convert to well-formed xhtml transitional
# !!!!!!! This is very out of date!!!!
#
#    Copyright (C) 2003 Free Software Foundation, Inc.
#
# 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 3 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.  If not, see <http://www.gnu.org/licenses/>.
#
# Originally written by Patrice Dumas.
#
#-##############################################################################

# FIXME this is out of date. There are still the T2H_ prefixes!

# APA: Add SystemLiteral to identify the canonical DTD.
# [Definition:] The SystemLiteral is called the entity's system
# identifier. It is a URI, which may be used to retrieve the entity.
# See http://www.xml.com/axml/target.html#NT-ExternalID
set_default('DOCTYPE', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/xhtml1-transitional.dtd">');

set_default('FRAMESET_DOCTYPE', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/xhtml1-frameset.dtd">');

# -iso
# if set, ISO8859 characters are used for special symbols (like copyright, etc)
# FIXME certainly obsoleted by t2h_default_set_iso_symbols which should
# certainly ba called indirectly through html_default_load
set_default('USE_ISO', 1);

# horizontal rules
$SMALL_RULE = '
';
$DEFAULT_RULE = '
';
$MIDDLE_RULE = '
';
$BIG_RULE = '
';

# this is added inside  after <title> and some <meta name>
# stuff, it can be used for eg.


code:
#+##############################################################################
#
# docbook.pm: convert to docbook
#
#    Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
#
# 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 3 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.  If not, see <http://www.gnu.org/licenses/>.
#
# Originally written by Patrice Dumas.
#
#-##############################################################################

# regarding sections and nodes, in docbook we don't care at all about the
# splitting done in the main program. When there is a node, it is recorded as
# being pending. When there is a section it is opened, and closed when
# there is the next section or end of file.

use strict;

my %docbook_complex_format;
my $kept_footnote_function;
my $docbook_in_footnote;
my %docbook_sections;
my %def_format_docbook;
my %def_argument_types_docbook;

my $docbook_pending_node_id;
my $docbook_current_section;
my @docbook_multitable_stack = ();
my @docbook_table_stack = ();
my @docbook_special_quotation;

sub docbook_default_load(;$)
{
my $from_command_line = shift;

t2h_default_set_variables_xml();
set_default('DOCTYPE', '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
  <!ENTITY tex "TeX">
  <!ENTITY latex "LaTeX">
]>');
@T2H_FORMAT_EXPAND = ('docbook');
@IMAGE_EXTENSIONS = ('eps', 'gif', 'jpg', 'jpeg', 'pdf', 'png', 'svg', 'txt');
set_default('INLINE_INSERTCOPYING', 1);
# this should lead to end_section being only called at the end of sectioning
set_default('USE_NODES', 0);
set_default('USE_SECTIONS', 1);

set_default('SHOW_MENU', 0);
set_default('SHOW_TITLE', 0);
set_default('HEADERS', 0);
set_default('SPLIT', '');
# certainly irrelevant
set_default('SIMPLE_MENU', 0);

t2h_default_push_handler(\&docbook_initialize_variables, \@command_handler_init);

%style_map = ();
t2h_default_copy_style_map (\%default_style_map, \%style_map);
foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
{
     $style_map{$accent_command} = { 'function' => \&xml_default_accent };
}

delete $style_map{'sc'}->{'inline_attribute'};
# FIXME there is a code element in v4.3
$style_map{'code'}->{'inline_attribute'} = 'literal';
$style_map{'strong'}->{'inline_attribute'} = 'emphasis role="bold"';
$style_map{'kbd'}->{'inline_attribute'} = 'userinput';
$style_map{'w'}->{'end'} = '<!-- /@w -->';
$style_map{'='}->{'function'} = \&docbook_macron;
$style_map{'b'}->{'inline_attribute'} = 'emphasis role="bold"';
$style_map{'cite'}->{'inline_attribute'} = 'citetitle';
$style_map{'command'}->{'inline_attribute'} = 'command';
$style_map{'dfn'}->{'inline_attribute'} = 'firstterm';
$style_map{'emph'}->{'inline_attribute'} = 'emphasis';
$style_map{'env'}->{'inline_attribute'} = 'envar';
$style_map{'file'}->{'inline_attribute'} = 'filename';
$style_map{'i'}->{'inline_attribute'} = 'wordasword';
$style_map{'key'}->{'inline_attribute'} = 'keycap';
delete $style_map{'key'}->{'begin'};
delete $style_map{'key'}->{'end'};
$style_map{'option'}->{'inline_attribute'} = 'option';
$style_map{'t'}->{'inline_attribute'} = 'literal';
delete $style_map{'sansserif'}->{'inline_attribute'};
delete $style_map{'r'}->{'inline_attribute'};
$style_map{'indicateurl'}->{'inline_attribute'} = 'wordasword';
delete $style_map{'indicateurl'}->{'begin'};
delete $style_map{'indicateurl'}->{'end'};
$style_map{'var'}->{'inline_attribute'} = 'replaceable';
delete $style_map{'verb'}->{'inline_attribute'};
$style_map{'email'}->{'function'} = \&docbook_email;
$style_map{'math'}->{'function'} = \&docbook_math;
$style_map{'uref'}->{'function'} = \&docbook_uref;
$style_map{'url'}->{'function'} = \&docbook_uref;
$style_map{'titlefont'}->{'function'} = \&docbook_titlefont;
#$style_map{'samp'}->{'function'} = \&docbook_samp;
#delete $style_map{'samp'}->{'inline_attribute'};
$style_map{'samp'}->{'inline_attribute'} = 'literal';
$style_map{'samp'}->{'begin'} = '‘';
$style_map{'samp'}->{'end'} = '’';

$kept_footnote_function = $style_map{'footnote'}->{'function'};
$style_map{'footnote'}->{'function'} = \&docbook_footnote;

foreach my $style (keys(%style_map))
{
   delete ($style_map{$style}->{'quote'});
}

#use Data::Dumper;
%style_map_pre = ();
t2h_default_copy_style_map (\%style_map, \%style_map_pre);

$style_map_pre{'r'}->{'inline_attribute'} = 'lineannotation';

$colon_command_punctuation_characters{'.'} = '.';
$colon_command_punctuation_characters{':'} = ':';
$colon_command_punctuation_characters{'?'} = '?';
$colon_command_punctuation_characters{'!'} = '!';

$stop_paragraph_command{'titlefont'} = 0;

# FIXME
#$no_paragraph_commands{'anchor'} = 0;

# FIXME
delete $special_accents{'ringaccent'};
$special_accents{'ogonek'} = 'aeiuAEIU';

%simple_map = %default_simple_map;
%simple_map_pre = %simple_map;

# FIXME right? ł Ł
$things_map{'l'} = '/l';
$things_map{'L'} = '/L';
$things_map{'TeX'} = '&tex;';
$things_map{'LaTeX'} = '&latex;';
$things_map{'enddots'} = '….';
$things_map{'minus'} = '−';
# FIXME ∗
$things_map{'point'} = '-!-';
# FIXME ≡
$things_map{'equiv'} = '==';
# FIXME no ‹ nor ›
$things_map{'guilsinglright'} = '>';
$things_map{'guilsinglleft'} = '<';
# The following is unneeded because normal_text is redefined.
# FIXME it should certainly be better to leave those substitutions,
# or even hardcodes them in normal_text.
# t2h_remove_text_substitutions("'", 1, 0, 0, 1);
# t2h_remove_text_substitutions('`', 1, 0, 0, 1);

$things_map{'quotedblbase'} = '„';
$things_map{'quotesinglbase'} = '‚';

%pre_map = %things_map;

#delete $inter_item_commands{'cindex'};

#$no_paragraph_commands{'cindex'} = 0;
$no_paragraph_commands{'float'} = 0;

%docbook_complex_format = (
   'example' => 'screen',
   'smallexample' => 'screen',
   'display' => 'literallayout',
   'smalldisplay' => 'literallayout',
   'lisp' => 'programlisting',
   'smalllisp' => 'programlisting',
   'format' => 'abstract',
   'smallformat' => 'screen'
);

%docbook_sections = (
  'top'  => 'chapter',
  'part' => 'part',
  'chapter'  => 'chapter',
  'unnumbered'  => 'chapter',
  'centerchap'  => 'chapter',
  'appendix' => 'appendix',
  'majorheading' => 'other',
  'chapheading' => 'other',
  'heading' => 'sect1',
  'subheading' => 'sect2',
  'subsubheading' => 'sect3',
  2 => 'sect1',
  3 => 'sect2',
  4 => 'sect3'
);

%def_format_docbook = (
  'deffn' => [ ['function', 'name'] ],
   'defvr' => [ ['varname', 'name'] ],
   'deftypefn' => [ [ 'returnvalue', 'type' ], ['function', 'name'] ],
   'deftypeop' => [ ['returnvalue', 'type'], ['methodname', 'name'] ],
   'deftypevr' => [ ['returnvalue', 'type'], ['varname', 'name'] ],
   'defcv' => [ ['classname', 'class'], ['property', 'name'] ],
   'deftypecv' => [ ['returnvalue', 'type'], ['property', 'name'] ],
   'defop' => [ ['classname', 'class'], ['methodname', 'name'] ],
   'deftp' => [ ['structname', 'name'] ]
);

%def_argument_types_docbook = (
  'param' => 'replaceable',
  'paramtype' => 'type',
  'delimiter' => ''
);

@docbook_special_quotation = ('note', 'caution', 'important', 'tip', 'warning');

$region_formats_kept{'copying'} = 1;

%format_map = (
       'group'       =>  '',
       'raggedright'       =>  '',
       'copying'     =>  'copying',
       );

$print_Top = \&docbook_print_Top;
$print_Top_footer = \&docbook_print_Top_footer;
$print_page_head = \&docbook_print_page_head;
$print_foot_navigation = \&docbook_noop;
$contents = \&docbook_noop;
$shortcontents = \&docbook_noop;
$about_body = \&docbook_noop;
$print_page_foot = \&docbook_print_page_foot;
$end_section = \&docbook_end_section;
$one_section = \&docbook_one_section;

$acronym_like          = \&docbook_acronym_like;
$anchor_label          = \&docbook_anchor_label;
$begin_format_texi     = \&docbook_begin_format_texi;
$cartouche             = \&docbook_cartouche;
$cell                  = \&docbook_cell;
$complex_format        = \&docbook_complex_format;
$def                   = \&docbook_def;
$def_line              = \&docbook_def_line;
$def_item              = \&docbook_def_item;
$element_label         = \&docbook_element_label;
$external_ref          = \&docbook_external_ref;
$float                 = \&docbook_float;
$foot_line_and_ref     = \&docbook_foot_line_and_ref;
$format                = \&docbook_format;
$format_list_item_texi = \&docbook_format_list_item_texi;
$heading               = \&docbook_heading;
$image                 = \&docbook_image;
$image_files           = \&docbook_image_files;
$index_entry_command   = \&docbook_index_entry_command;
$index_entry_label     = \&docbook_index_entry_label;
$index_summary         = \&docbook_index_summary;
$internal_ref          = \&docbook_internal_ref;
$insertcopying         = \&docbook_insertcopying;
$list_item             = \&docbook_list_item;
$misc_element_label    = \&docbook_noop;
$normal_text           = \&docbook_normal_text;
$paragraph             = \&docbook_paragraph;
$preformatted          = \&docbook_preformatted;
$printindex            = \&docbook_printindex;
$protect_text          = \&xml_default_protect_text;
$quotation              = \&docbook_quotation;
$quotation_prepend_text = \&docbook_quotation_prepend_text;
$listoffloats          = \&docbook_noop;
$raw                   = \&docbook_raw;
$row                   = \&docbook_row;
$sp                    = \&docbook_sp;
$style                 = \&docbook_style;
$table_item            = \&docbook_table_item;
$table_line            = \&docbook_table_line;
$table_list            = \&docbook_table_list;
$misc_command_line     = \&docbook_misc_commands;

}

sub docbook_footnote
{
    $docbook_in_footnote = 1;
    my $result = &$kept_footnote_function(@_);
    $docbook_in_footnote = 0;
    return $result;
}

sub docbook_macron($$)
{
    my $accent = shift;
    my $args = shift;
    return $args->[0] . "¯";
}

sub docbook_samp($$)
{
    shift;
    my $args = shift;
    return "‘<literal>$args->[0]</literal>’";
}

sub docbook_email($$)
{
    my $command = shift;
    my $args = shift;
    my $mail = shift @$args;
    my $text = shift @$args;
    $mail = main::normalise_space($mail);
    if (defined($text) and $text =~ /\S/)
    {
        # FIXME normalise_space would be more legible.
        #return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.main::normalise_space($text).'</ulink>';
        return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.$text.'</ulink>';
    }
    return docbook_add_id('email').">$mail</email>";
}

sub docbook_uref($$)
{
    shift;
    my $args = shift;
    my $url = shift @$args;
    my $text = shift @$args;
    my $replacement = shift @$args;
    $url = main::normalise_space($url);
    $text = '' if (!defined($text));
    $replacement = '' if (!defined($replacement));
    $replacement = $text if ($replacement eq '');
    $replacement = $url if ($replacement eq '');
    $replacement = main::normalise_space($replacement);

    return docbook_add_id('ulink')." url=\"$url\">$replacement</ulink>";
}

# FIXME
sub docbook_titlefont($$)
{
    shift;
    my $args = shift;
    return "$args->[0]";
}

# FIXME there ought to be something better... Like use tex4ht mathml
# output or something like that
sub docbook_math($$)
{
    shift;
    my $args = shift;
    my $text = shift @$args;
    return $text;
}

sub docbook_print_page_head($)
{
    my $fh = shift;
    my $language = get_conf('documentlanguage');
    my $doctype = get_conf('DOCTYPE');
    my $extension = get_conf('EXTENSION');
    print $fh <<EOT;
<?xml version="1.0"?>
$doctype
<book id="$Texi2HTML::THISDOC{'file_base_name'}.$extension" lang="$language">
EOT
}

sub docbook_print_page_foot($)
{
    my $fh = shift;
    print $fh "". docbook_close_section();
    print $fh <<EOT;
</book>
EOT
}

sub docbook_print_Top($$$)
{
    my $fh = shift;
    my $has_top_heading = shift;
    my $element = shift;
    main::print_lines($fh, $Texi2HTML::THIS_SECTION);
}

sub docbook_element_tag($)
{
   my $element = shift;
#print STDERR "$element->{'texi'}, $element->{'tag_level'}, $element->{'level'}\n";
   return $docbook_sections{$element->{'tag_level'}} if (exists($docbook_sections{$element->{'tag_level'}}));
   return $docbook_sections{$element->{'level'}} if (exists($docbook_sections{$element->{'level'}}));
}

sub docbook_node_id($)
{
   my $node_texi = shift;
   my $node = main::substitute_line($node_texi, 'docbook node id', {'code_style' => 1, 'remove_texi' => 1});
   $node =~ s/[\s\"]/-/g;
   return &$protect_text($node);
}

sub docbook_initialize_variables()
{
   $docbook_pending_node_id = undef;
   $docbook_current_section = undef;
   @docbook_multitable_stack = ();
   @docbook_table_stack = ();
}

sub docbook_add_id($)
{
    my $element = shift;
    my $result = "<$element";
    if (defined($docbook_pending_node_id) and (!$docbook_in_footnote or $element eq 'footnote'))
    {
        $result .= " id=\"$docbook_pending_node_id\"";
        $docbook_pending_node_id = undef;
    }
    return $result;
}

sub docbook_heading($$$$$)
{
    my $element = shift;
    my $command = shift;
    my $texi_line = shift;
    my $line = shift;
    my $in_preformatted = shift;

    if (defined($command) and $command =~ /heading/)
    {
        my $text = '';
        if (defined($line))
        {
            $text = $line;
            # this isn't done in main program in that case...
            chomp ($text);
            $text =~ s/^\s*//;
        }
        return docbook_add_id('bridgehead')." renderas=\"$docbook_sections{$command}\">$text</bridgehead>\n";
    }

    my $result = '';

# FIXME verify xreflabel
    if ($command ne 'node')
    {
        # close previous section
        $result .= docbook_close_section();
        my $title = $element->{'text_nonumber'};
        my $label = '';
        my $xreflabel = '';
        if ($element->{'number'})
        {
            my $label_nr = $element->{'number'};
            #$label_nr =~ s/\.$//;
            $label = $label_nr;
        }
        else
        {
            my $xreftitle = $title;
            $xreflabel = " xreflabel=\"$xreftitle\"";
        }
        $result .= docbook_add_id(docbook_element_tag($element) . " label=\"${label}\"${xreflabel}");
        $result .= ">\n<title>$title</title>\n";
        $docbook_current_section = $element;
    }
    return $result;
}

sub docbook_element_label($$$$)
{
    my $id = shift;
    my $element = shift;
    my $command = shift;
    my $line = shift;

    if ($command eq 'node')
    {
        $docbook_pending_node_id = docbook_node_id($element->{'texi'});
    }
    return '';
}

sub docbook_paragraph($$$$$$$$$$$$)
{
    my $text = shift;
    my $align = shift;
    my $indent = shift;
    my $paragraph_command = shift;
    my $paragraph_command_formatted = shift;
    my $paragraph_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $command_stack_at_end = shift;
    my $command_stack_at_begin = shift;

    if (defined($paragraph_number) and defined($$paragraph_number))
    {
       $$paragraph_number++;
    }

    # no para in multitables, caption and shortcaptions.
    my $top_stack = '';
    $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
    return $text if ($top_stack eq 'multitable' or $top_stack eq 'shortcaption' or $top_stack eq 'caption' or $top_stack eq 'documentdescription');

    if ($text =~ /\S/)
    {
       #return docbook_add_id('para').">$text</para>";
       return "<para>$text</para>";
    }
    return $text;
}

sub docbook_def_line($$$$$$$$$$$$$$$)
{
   my $category_prepared = shift;
   my $name = shift;
   my $type = shift;
   my $arguments = shift;
   my $index_label = shift;
   my $arguments_array = shift;
   my $arguments_type_array = shift;
   my $unformatted_arguments_array = shift;
   my $command = shift;
   my $class_name = shift;
   my $category = shift;
   my $class = shift;
   my $style = shift;
   my $original_command = shift;

   my %unformatted_arguments = ();

   my @unformatted_args = @$unformatted_arguments_array;
   foreach my $type (@$arguments_type_array)
   {
      my $unformatted_arg = shift @unformatted_args;
      $unformatted_arguments{$type} = $unformatted_arg;
   }
   # FIXME unformatted!
   my $result = "<synopsis role=\"$unformatted_arguments{'category'}\"><indexterm role=\""
    .$main::index_prefix_to_name{$style}."\"><primary>$class_name</primary></indexterm>";

   my %arguments = ( 'prepared_category' => $category_prepared,
         'category' => $category,
         'name' => $name,
         'type' => $type,
         'class' => $class
    );
   foreach my $type (keys(%arguments))
   {
      $arguments{$type} = '' if (!defined($arguments{$type}));
   }

   foreach my $mandatory_arg (@{$def_format_docbook{$command}})
   {
      my $elem = $mandatory_arg->[0];
      #if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /^\s*\@code\{/)
      if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /\@code\{/)
      {
      # FIXME unformatted
          my $arg_without_at_command = $unformatted_arguments{$mandatory_arg->[1]};
          #$arg_without_at_command =~ s/\s*\@code\{//;
          #$arg_without_at_command =~ s/\}\s*$//;
          while ($arg_without_at_command =~ /\@code\{([^\{\}]*)\}/)
          {
              $arg_without_at_command =~ s/\@code\{([^\{\}]*)\}/$1/;
          }
          $result .= "<$elem>$arg_without_at_command</$elem>";
      }
      else
      {
          $result .= "<$elem>$arguments{$mandatory_arg->[1]}</$elem>";
      }
   }

   my @types = @$arguments_type_array;
   @unformatted_args = @$unformatted_arguments_array;
   foreach my $arg (@$arguments_array)
   {
      my $type = shift @types;
      my $unformatted = shift @unformatted_args;
      if (exists ($def_argument_types_docbook{$type}))
      {
         if ($def_argument_types_docbook{$type} and
                ($type eq 'paramtype' or ($unformatted !~ /^\s*\@var\{/)))
         {
            $result .= "<$def_argument_types_docbook{$type}>$arg</$def_argument_types_docbook{$type}>";
         }
         else
         {
            $result .= $arg;
         }
      }
   }

   $result .= "</synopsis>\n";
   return $result;
}

# FIXME
# @deffn
# @c comment
# @end deffn
# leads to the creation of a <definitionitem> with a comment within,
# while there should be no definitionitem
sub docbook_def_item($)
{
    my $text = shift;
    my $only_inter_item_commands = shift;

    if ($text =~ /\S/)
    {
       return '<blockquote>' . $text . '</blockquote>' unless $only_inter_item_commands;
       return $text;
    }
    return '';
}

sub docbook_def($)
{
   my $text = shift;
   return docbook_add_id('informalfigure').'>'.$text.'</informalfigure>';
}

sub docbook_preformatted($$$$$$$$$$$$)
{
    my $text = shift;
    my $pre_style = shift;
    my $class = shift;
    my $leading_command = shift;
    my $leading_command_formatted = shift;
    my $preformatted_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $command_stack_at_end = shift;
    my $command_stack_at_begin = shift;

    return $text;
}

sub docbook_misc_commands($$$$$)
{
    my $macro = shift;
    my $line = shift;
    my $args = shift;
    my $stack = shift;
    my $state = shift;
#print STDERR "$macro $line";
#print STDERR "ARGS @$args\n" if defined ($args);
    #my $result_text = undef;
    my $result_text = undef;
    if ($macro eq 'c' or $macro eq 'comment' and scalar(@$args))
    {
       my $comment_line = $args->[0];
       chomp ($comment_line);
       # makeinfo remove all the leading spaces
       $comment_line =~ s/^\s//;
       $result_text = &$comment ($comment_line);
    }
    elsif ($macro eq 'settitle')
    {
     # FIXME to be formatted? Also maybe in line_command. And in html, it
     # is handled by heading _text
       my $arg = $args->[0];
       $arg =~ s/^\s*//;
       chomp($arg);
       $result_text = "<title>$arg</title>\n";
    }
    return ($macro, $line, $result_text);
}

sub docbook_foot_line_and_ref($$$$$$$)
{
    my $number_in_doc = shift;
    my $number_in_page = shift;
    my $footnote_id = shift;
    my $place_id = shift;
    my $document_file = shift;
    my $footnote_file = shift;
    my $lines = shift;
    my $state = shift;

    my $result = docbook_add_id('footnote').'>';
    foreach my $line (@$lines)
    {
       $result .= $line;
    }
    return ([], $result . '</footnote>');
}

sub docbook_any_ref($$$)
{
    my $type = shift;
    my $args = shift;
    my $unformatted_args = shift;

    # FIXME?
    if ($type eq 'inforef')
    {
        my $node_file = "($args->[2])$args->[0]";
        if ($args->[1] ne '')
        {
            return "*note $args->[1]: $node_file";
        }
        else
        {
            return "*note ${node_file}::";
        }
    }
    else
    {
        if (($args->[3] ne '') or ($args->[4] ne ''))
        {
            return '' if ($args->[4] eq '');
            my $section_name = $args->[2];
            $section_name = $args->[0] if ($section_name eq '');
            if ($type eq 'ref')
            {
                return gdt('section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1});
            }
            elsif ($type eq 'xref')
            {
                return gdt('See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1});
            }
            elsif ($type eq 'pxref')
            {
                return gdt('see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1});
            }
        }
        my $link = docbook_node_id($unformatted_args->[0]);
        my $title = $args->[2];
        $title = $args->[1] if ($title eq '');
        if ($title eq '')
        {
            if ($type eq 'ref')
            {
                return gdt('{ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"});
            }
            elsif ($type eq 'pxref')
            {
                return gdt('see {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"});
            }
            elsif ($type eq 'xref')
            {
                return gdt('See {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"});
            }
        }
        else
        {
            if ($type eq 'ref')
            {
                return gdt('{title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"});
            }
            elsif ($type eq 'pxref')
            {
                return gdt('see {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"},{'duplicate'=>1});
            }
            elsif ($type eq 'xref')
            {
                return gdt('See {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"},{'duplicate'=>1});
            }
        }
    }
}

sub docbook_external_ref($$$$$$$$$)
{
    my $type = shift;
    my $section = shift;
    my $book = shift;
    my $file = shift;
    my $href = shift;
    my $cross_ref = shift;
    my $args_texi = shift;
    my $formatted_args = shift;
    my $node = shift;

    return docbook_any_ref ($type, $formatted_args, $args_texi);
}

sub docbook_internal_ref($$$$$)
{
    my $type = shift;
    my $href = shift;
    my $short_name = shift;
    my $name = shift;
    my $is_section = shift;
    my $args_texi = shift;
    my $formatted_args = shift;

    return docbook_any_ref ($type, $formatted_args, $args_texi );
}

sub docbook_index_entry_command($$$$$)
{
   my $command = shift;
   my $index_name = shift;
   my $label = shift;
   my $entry_texi = shift;
   my $entry_formatted = shift;

   return $label if (defined($label) and $label ne '');
   return docbook_index_entry_label('','','',$main::index_prefix_to_name{$index_name}, '', '', $entry_formatted, {});
}

sub docbook_index_entry_label($$$$$$$$$)
{
    my $identifier = shift;
    my $preformatted = shift;
    my $entry = shift;
    my $index_name = shift;
    my $index_command = shift;
    my $texi_entry = shift;
    my $formatted_entry = shift;
    my $in_region_not_in_output = shift;
    my $index_entry = shift;

    return "<indexterm role=\"${index_name}\"><primary>${formatted_entry}</primary></indexterm>";
}

sub docbook_close_section()
{
    my $element = $docbook_current_section;

    if (!defined($element))
    {
        return '';
    }

    my $result = '';

    # there is a special case for a @chapter that is a child of @top
    # but should not be considered as is, since it is also toplevel.
    # @part, however may have other toplevel elements as children.
    return '' if ($element->{'child'} and (!$element->{'child'}->{'toplevel'} or $element->{'tag'} ne 'top'));
    $result .= '</'.docbook_element_tag($element).">\n";

    my $current = $element;
    # the second condition is such that top is closed only if it has
    # sub-elements below chapter.
    # the third condition is such that elements with a next element are
    # only closed for the last element, except when the next element is
    # toplevel and below top, such that @top is closed before the first
    # @chapter if there are @section or the like below @top
    while ($current->{'sectionup'} and !($current->{'sectionup'}->{'tag'} eq 'top' and $current->{'toplevel'}) and (!$current->{'childnext'} or ($current->{'childnext'}->{'toplevel'} and $current->{'sectionup'}->{'tag'} eq 'top')))
    {
        $current = $current->{'sectionup'};
        $result .= '</'.docbook_element_tag($current).">\n";
    }
    return $result;
}

sub docbook_end_section($$$)
{
    my $fh = shift;
    my $end_foot_navigation = shift;
    my $element = shift;
}

sub docbook_print_Top_footer($$)
{
    my $fh = shift;
    my $end_page = shift;
    my $element = shift;
}

sub docbook_one_section($$)
{
    my $fh = shift;
    my $element = shift;
    main::print_lines($fh);
    &$print_page_foot($fh);
}

sub docbook_insertcopying($)
{
    my $text = shift;
    my $comment = shift;
    my $simple_text = shift;

    return $text;
}

sub docbook_acronym_like($$$$$$)
{
    my $command = shift;
    my $acronym_texi = shift;
    my $acronym_text = shift;
    my $with_explanation = shift;
    my $explanation_lines = shift;
    my $explanation_text = shift;
    my $explanation_simply_formatted = shift;

    $command = 'abbrev' if ($command eq 'abbr');
    my $result = docbook_add_id($command).">$acronym_text</${command}>";
    if ($with_explanation)
    {
        $result .= " ($explanation_text)";
    }
    return $result;
}

sub docbook_image_files($$$$)
{
    my $base = shift;
    my $extension = shift;
    my $texi_base = shift;
    my $texi_extension = shift;
    my @files = ();
    return @files if (!defined($base) or ($base eq ''));
# FIXME should look at extension argument? makeinfo doesn't
#    push @files,"$base.$extension" if (defined($extension) and ($extension ne ''));
    foreach my $ext (@IMAGE_EXTENSIONS)
    {
        push @files, ["$base.$ext", "$texi_base.$ext"];
    }
    return @files;
}

sub docbook_image($$$$$$$$$$$$$$$$;$)
{
    my $file = shift;
    my $base = shift;
    my $preformatted = shift;
    my $file_name = shift;
    my $alt = shift;
    my $width = shift;
    my $height = shift;
    my $raw_alt = shift;
    my $extension = shift;
    my $working_dir = shift;
    my $file_path = shift;
    my $in_paragraph = shift;
    my $file_locations = shift;
    my $base_simple_format = shift;
    my $extension_simple_format = shift;
    my $file_name_simple_format = shift;
    my $line_nr = shift;

#    if (!defined($file_path) or $file_path eq '' or $file_path =~ /\.txt$/)
#    {
#        if (defined($extension) and $extension ne '')
#        {
#            $file = "$base.$extension";
#        }
#        else
#        {
#            $file = "$base.jpg";
#            $extension = 'jpg';
#        }
#        main::line_warn ("no image file for $base, (using $file)");
#    }
    my $txt_path;
    my @files = ();
    my @extensions = @IMAGE_EXTENSIONS;
    foreach my $file_location (@$file_locations)
    {
        my ($file_located, $path, $file_simple_format) = @$file_location;
        my $extension = shift @extensions;
        if (defined($path))
        {
           if ($extension eq 'txt' and !defined($txt_path))
           {
              $txt_path = $path;
           }
           else
           {
              push @files, [$file_located, uc($extension), $file_simple_format];
           }
        }
    }
    push @files, ["$base.jpg", 'JPG', "$base_simple_format.jpg" ] unless (@files);

    my $begin = docbook_add_id('inlinemediaobject').'>';
    my $end = '</inlinemediaobject>';
    if ($preformatted or !$in_paragraph)
    {
         $begin = docbook_add_id('informalfigure').'><mediaobject>';
         $end = '</mediaobject></informalfigure>';
    }
    my $result = $begin;
    foreach my $file_spec (@files)
    {
       $result .= "<imageobject><imagedata fileref=\"$file_spec->[2]\" format=\"$file_spec->[1]\"></imagedata></imageobject>";
    }
    if (defined($txt_path))
    {
       if (open(TXT, "<$txt_path"))
       {
          my $in_encoding = get_conf('IN_ENCODING');
          if (defined($in_encoding) and get_conf('USE_UNICODE'))
          {
              binmode(TXT, ":encoding($in_encoding)");
          }
          $result.="<textobject><literallayout>";
          while (my $img_txt = <TXT>)
          {
              $result .= $img_txt;
          }
          $result .= '</literallayout></textobject>';
          close(TXT);
       }
       else
       {
          main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr);
       }
    }
    else
    {
        main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr);
    }

    return "$result$end";
}

sub docbook_format_list_item_texi($$$$)
{
    my $format = shift;
    my $line = shift;
    my $prepended = shift;
    my $command = shift;

    my $result_line = undef;

    if (defined($command) and $command ne '' and !exists $special_list_commands{$format}->{$command} and $format ne 'itemize')
    {
        #@*table
        $line =~ s/^\s*//;
        $line =~ s/\s*$//;
        if (exists ($style_map{$command}))
        {
           $result_line = "\@$command\{$line\}\n";
        }
        elsif (exists ($things_map{$command}))
        {
           $result_line = "\@$command\{\} $line\n";
        }
        else
        {
           $result_line = "\@$command $line\n";
        }
    }

    return ($result_line, 0);
}

# row in multitable
sub docbook_row($$;$$)
{
    my $text = shift;
    my $macro = shift;
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $column_number = shift;

    my $result = '';
    if ($macro eq 'headitem')
    {
         if ($docbook_multitable_stack[-1] != 0)
         {
             $result .= "<thead>";
             $result = "</tbody>" . $result if ($docbook_multitable_stack[-1] == 1);
             $docbook_multitable_stack[-1] = 0;
         }
    }
    elsif ($docbook_multitable_stack[-1] != 1)
    {
         $result .= "<tbody>";
         $result = "</thead>" . $result if ($docbook_multitable_stack[-1] == 0);
         $docbook_multitable_stack[-1] = 1;
    }
    $result .= "<row>$text</row>";

    return $result;
}

# cell in multitable
sub docbook_cell($$;$$)
{
    my $text = shift;
    my $row_macro = shift;
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $column_number = shift;

    return "<entry>" . $text . '</entry>';
}

# if varlistentry_state is > 0 it means that a varlistentry is opened.
# if varlistentry_state is == 2 it means that we are in a succession
#          of term
# if varlistentry_state is == 1 it means that we are in the line
# Having a listitem in a varlistentry is a must, so an empty
# listitem is added if a varlistentry is closed and varlistentry_state == 2
#
# varlistentry acceps only term and listitem, so inter_item_commands
# are put in the next term, or, if at the end of the table in a last
# listitem
sub docbook_table_item($$$$$$)
{
    my $text = shift;
    my $index_label = shift;
    my $format = shift;
    my $command = shift;
#    my $formatted_command = shift;
    my $style_stack = shift;
#    my $text_formatted = shift;
#    my $text_formatted_leading_spaces = shift;
#    my $text_formatted_trailing_spaces = shift;
    my $item_cmd = shift;

#    $formatted_command = '' if (!defined($formatted_command));

#    if (defined($text_formatted))
#    {
#        $text_item = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces;
#    }
#    else
#    {
#        $text_item = $text;
#    }

    my $result = '';
    my $prepended = '';
    if (defined($docbook_table_stack[-1]->{'inter_item'}))
    {
        #$formatted_command = $docbook_table_stack[-1]->{'inter_item'} . $formatted_command;
        $prepended = $docbook_table_stack[-1]->{'inter_item'};
        delete $docbook_table_stack[-1]->{'inter_item'};
    }
    if ($item_cmd eq 'item')
    {
        if ($docbook_table_stack[-1]->{'varlistentry_state'} == 2)
        {
            $result .= "<listitem><para><!-- empty table line --></para></listitem>";
        }
        if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1)
        {
            $result .= '</varlistentry>';
        }
        $docbook_table_stack[-1]->{'varlistentry_state'} = 2;
        $result .= '<varlistentry>';
    }
    $result .= '<term>';
    $result .= $prepended . $text ."</term>\n";
    return $result;
}

sub docbook_table_line($$$)
{
    my $text = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

#print STDERR

    if ($text =~ /\S/)
    {
        if ($before_items)
        {
            return $text;
        }

        if ($only_inter_item_commands)
        {
            $docbook_table_stack[-1]->{'inter_item'} = $text;
            return '';
        }
        else
        {
            $docbook_table_stack[-1]->{'varlistentry_state'} = 1;
            return "<listitem>$text</listitem>";
        }
        #return $text;
    }
    else
    {
        return '';
    }
}

sub docbook_list_item($$$$$$$$$)
{
    my $text = shift;
    my $format = shift;
    my $command = shift;
    my $formatted_command = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $prepended = shift;
    my $prepended_formatted = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

#my $prep_t = 'UNDEF'; $prep_t = $prepended if (defined($prepended));
#$item_nr = 0 if (!defined($item_nr));
#print STDERR "  $item_nr --> $prep_t|${text}!!!!!\n";
    #return $text if ($only_inter_item_commands and $before_items);
    return  $text if ($before_items);
    return '<listitem>' . $text . "</listitem>\n";
}

sub docbook_table_list($$$$$$$$$)
{
    my $format_command = shift;
    my $text = shift;
    my $command = shift;
    my $formatted_command = shift;
# enumerate
    my $item_nr = shift;
    my $enumerate_style = shift;
# itemize
    my $prepended = shift;
    my $prepended_formatted = shift;
# multitable
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $number = shift;

    my $result = "<$format_command>";
    if ($format_command eq 'itemize')
    {
        my $itemfunction;
        #$prepended_formatted =~ s/^\s*// if (defined($prepended_formatted));
        $prepended =~ s/^\s*// if (defined($prepended));
        #if (defined($formatted_command) and $formatted_command ne '')
        if (defined($command) and $command ne '')
        {
            #$itemfunction = $formatted_command;
            $itemfunction = $command;
            #$itemfunction .= " $prepended_formatted" if (defined($prepended_formatted) and $prepended_formatted ne '');
            $itemfunction .= " $prepended" if (defined($prepended) and $prepended ne '');
        }
        #elsif (defined($prepended_formatted))
        elsif (defined($prepended))
        {
            #$itemfunction = $prepended_formatted;
            $itemfunction = $prepended;
        }
        my $mark = '';
       $mark = " mark=\"$itemfunction\"" if (defined($itemfunction) and $itemfunction ne '');
        return docbook_add_id('itemizedlist')."${mark}>$text</itemizedlist>";
    }
    elsif ($format_command eq 'enumerate')
    {
        my $numeration='arabic';
        if (defined($enumerate_style) and $enumerate_style ne '')
        {
           if ($enumerate_style =~ /^[A-Z]/)
           {
               $numeration = 'upperalpha';
           }
           elsif ($enumerate_style =~ /^[a-z]/)
           {
               $numeration = 'loweralpha';
           }
        }
        return docbook_add_id('orderedlist') ." numeration=\"$numeration\">$text</orderedlist>";
    }
    elsif ($format_command eq 'multitable')
    {
       my $result = docbook_add_id('informaltable').'><tgroup cols="'.$number.'">';
       my $fractions;
       my $multiply = 1;
       if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY')
           and scalar(@$columnfractions))
       {
           $fractions = [ @$columnfractions ];
           $multiply = 100;
       }
       elsif (defined($prototype_lengths) and (ref($prototype_lengths) eq 'ARRAY')
           and scalar(@$prototype_lengths))
       {
           $fractions = [ @$prototype_lengths ];
       }

       if (defined ($fractions))
       {
           foreach my $fraction (@$fractions)
           {
               $result .= '<colspec colwidth="'.($fraction*$multiply).'*"></colspec>';
           }
       }
       $text .= "</tbody>" if ($docbook_multitable_stack[-1] == 1);
       $text .= "</thead>" if ($docbook_multitable_stack[-1] == 0);
       pop @docbook_multitable_stack;
       return $result . "$text</tgroup></informaltable>";
    }
    elsif ($format_command =~ /^(v|f)?table$/)
    {
       $result = docbook_add_id('variablelist').'>';
       if (defined($docbook_table_stack[-1]->{'inter_item'}))
       { # there is a para in case there is only a comment, to avoid
         # an empty listitem
           $text .= "<listitem><para>$docbook_table_stack[-1]->{'inter_item'}</para></listitem>";
       }
       elsif ($docbook_table_stack[-1]->{'varlistentry_state'} == 2)
       {
           $text .= "<listitem><para><!-- empty table line --></para></listitem>";
       }
       $text .= '</varlistentry>' if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1);
       pop @docbook_table_stack;
       return $result . "$text</variablelist>\n";
    }
}

sub docbook_begin_format_texi($$$)
{
    my $command = shift;
    my $line = shift;
    my $state = shift;

    push (@docbook_multitable_stack, -1) if ($command eq 'multitable');
    push (@docbook_table_stack, {'varlistentry_state' => 0}) if ($command =~ /^(v|f)?table/);
    return $line;
}

# FIXME
sub docbook_sp($$)
{
   my $number = shift;
   my $preformatted = shift;
   return "";
}

sub docbook_index_summary($$)
{
    my $alpha = shift;
    my $nonalpha = shift;
    return '';
}

sub docbook_printindex($$)
{
    my $name = shift;
    my $printindex = shift;
    return docbook_add_id('index')."></index>\n";
}

sub docbook_complex_format($$)
{
    my $name = shift;
    my $text = shift;
    return '' if ($text eq '');
    my $result = docbook_add_id($docbook_complex_format{$name}).'>' .$text."</$docbook_complex_format{$name}>";
    return $result;
}

sub docbook_format($$)
{
    my $name = shift;
    my $element = shift;
    my $text = shift;
    return '' if ($text eq '');
    return $text if ($format_map{$name} eq '');
    if ($name eq 'copying')
    {
        # FIXME is info in docbook 5.0
        return "<bookinfo>\n<legalnotice>\n$text</legalnotice>\n</bookinfo>\n";
    }
    return docbook_add_id($format_map{$name}).'>' .$text."</$format_map{$name}>";
}

sub docbook_quotation_prepend_text($$)
{
    my $command = shift;
    my $argument_text = shift;

    return undef if (!defined($argument_text) or $argument_text =~ /^$/);

    chomp($argument_text);

    return undef if (grep {lc($argument_text) eq $_} @docbook_special_quotation);
    return gdt('@b{{quotation_arg}:} ', {'quotation_arg' => $argument_text}, {'keep_texi' => 1});
}

sub docbook_quotation($$$$$)
{
    my $command = shift;
    my $text = shift;
    my $argument_text = shift;
    my $argument_text_texi = shift;
    my $authors = shift;

    $argument_text_texi = '' if (!defined($argument_text_texi));
    chomp($argument_text_texi);
    my $docbook_command = 'blockquote';
    if (grep {lc($argument_text_texi) eq $_} @docbook_special_quotation)
    {
       $docbook_command = lc($argument_text_texi);
    }
    my $attribution = '';
    if ($authors)
    {
       foreach my $author (@$authors)
       {
           $attribution .= $author->{'author_text'};
       }
       $attribution = '<attribution>' .$attribution. '</attribution>' . "\n";
    }
    return  docbook_add_id($docbook_command).'>' .$attribution . $text . "</$docbook_command>\n";
}

sub docbook_style($$$$$$$$$)
{
    my $style = shift;
    my $command = shift;
    my $text = shift;
    my $args = shift;
    my $no_close =shift;
    my $no_open = shift;
    my $line_nr = shift;
    my $state = shift;
    my $command_stack = shift;
    my $kept_line_nrs = shift;

    my $result = $text;
    if (exists($style->{'function'}))
    {
        my $function = $style->{'function'};
        $result = &$function($command, $args, $command_stack, $state, $line_nr, $kept_line_nrs);
    }
    elsif (exists($style->{'inline_attribute'}))
    {
        my $element = $style->{'inline_attribute'};
        my $attribute_text = '';
        if ($element =~ /^(\w+)(\s+.*)/)
        {
            $element = $1;
            $attribute_text = $2;
        }

        if ($no_open)
        {
            $result = "<$element";
        }
        else
        {
            $result = docbook_add_id($element);
        }
        $result .= "$attribute_text>$text</$element>";
    }
    if (exists($style->{'begin'}) and !$no_open)
    {
        $result = $style->{'begin'} . $result;
    }
    if (exists($style->{'end'}) and !$no_close)
    {
        $result .= $style->{'end'};
    }
    return $result;
}

sub docbook_raw($$$)
{
    my $style = shift;
    my $text = shift;
    my $line_nr = shift;

    if ($style eq 'verbatim' or $style eq 'verbatiminclude')
    {
        return docbook_add_id('screen').'>' . &$protect_text($text) . '</screen>';
    }
    return '' unless (grep {$style eq $_} @EXPAND);
    if ($style eq 'docbook')
    {
        chomp ($text);
        return $text;
    }
    else
    {
        main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr);
        return &$protect_text($text);
    }
}

sub docbook_cartouche($$)
{
    my $text = shift;

    return $text;
}

sub docbook_anchor_label($$)
{
    my $id = shift;
    my $anchor_text = shift;
    # FIXME use docbook_node_id
    return '<anchor id="'. &$protect_text($anchor_text) . '"></anchor>';
}

sub docbook_float($$$$$)
{
    my $text = shift;
    my $float = shift;
    my $caption = shift;
    my $shortcaption = shift;

    my $label_texi = $float->{'texi'};
    return $text if (!defined($label_texi) or $label_texi eq '');

    return docbook_anchor_label('',$label_texi) . $text;
}

sub docbook_normal_text($$$$$$$;$)
{
   my $text = shift;
   my $in_raw_text = shift; # remove_texi
   my $in_preformatted = shift;
   my $in_code = shift;
   my $in_math = shift;
   my $in_simple = shift;
#print STDERR "Bug: in_raw_text in_simple $text\n" if ($in_raw_text and $in_simple);
   my $style_stack = shift;
   my $state = shift;

   #$text = uc($text) if (in_cmd($style_stack, 'sc'));
   $text = &$protect_text($text) unless($in_raw_text);
   if (! $in_code and !$in_preformatted)
   {
       if (!$in_raw_text)
       {
           $text =~ s/---/\&mdash\;/g;
           $text =~ s/--/\&ndash\;/g;
           $text =~ s/``/\&ldquo\;/g;
           $text =~ s/''/\&rdquo\;/g;
       }
       else
       {
           #FIXME really do that ? It is done by makeinfo in html
            $text =~ s/``/"/g;
            $text =~ s/''/"/g;
            # FIXME really do that in raw text?
            $text =~ s/---/\x{1F}/g;
            $text =~ s/--/-/g;
            $text =~ s/\x{1F}/--/g;
       }
   }
   return $text;
}

sub docbook_noop
{
    return '';
}

1;


code:
# -*-perl-*-
# vim: set filetype=perl:
######################################################################
# File: html.pm
# html output formatting
#
# A copy of this file is pasted into the beginning of texi2html by
# running './configure'.
#
# This file is in the public domain. Thus it may easily be used as an
# example for further customizations.
#
# Taken from texi2html.pm in 2009.
# Originally written by Olaf Bachmann.
#
# $Id$

use strict;

use vars qw(@html_default_multitable_stack);
# used in mediawiki.pm
#my  @html_default_multitable_stack;
# tracks menu entry index
my $html_menu_entry_index;
# the simple_formatted document title
my $html_default_title;

# initialise the html output
sub html_default_load(;$)
{
my $from_command_line = shift;

t2h_default_set_variables_xml();

###############################################################
# defaults

set_default('HEADERS', 1);

@T2H_FORMAT_EXPAND = ('html');

# The value is the 'SystemLiteral' which identifies the canonical DTD
# for the document.
# Definition: The SystemLiteral is called the entity's system
# identifier. It is a URI, which may be used to retrieve the entity.
# See http://www.xml.com/axml/target.html#NT-ExternalID
set_default('DOCTYPE', '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">');

# When frames are used, this SystemLiteral identifies the DTD used for
# the file containing the frame description.
set_default('FRAMESET_DOCTYPE', '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">');

# if the value is true the Texinfo menus are shown.
set_default('SHOW_MENU', 1);

set_default('SHOW_TITLE', 1);

# default is to use nodes only as elements.
set_default('USE_SECTIONS', undef);

set_default('TOP_FILE', 'index.html');

# file name used for Top node when NODE_FILES is true
set_default('TOP_NODE_FILE', 'index');

##############################################################################
#
# The following can only be set in the init file
#
##############################################################################

set_default('INLINE_INSERTCOPYING', 0);

# if this variable is true, numeric entities are used when there is no
# corresponding textual entity.
set_default('USE_NUMERIC_ENTITY', 1);

# if true, use the original command if the result is an entity
set_default('ENABLE_ENCODING_USE_ENTITY', 1);

# if set, do redirection files for renamed nodes
set_default('RENAMED_NODES_REDIRECTIONS', 1);

# used as identation for block enclosing command @example, etc
# If not empty, must be enclosed in
$EXAMPLE_INDENT_CELL = ' 	';

# same as above, only for @small
$SMALL_EXAMPLE_INDENT_CELL = ' 	';

# font size for @small
$SMALL_FONT_SIZE = '-1';

# horizontal rules
# Not used
$SMALL_RULE = '
';
$MIDDLE_RULE = '
';
# used almost everywhere
$DEFAULT_RULE = '
';
# used for top element and before misc elements
$BIG_RULE = '
';

# symbol put at the beginning of nodes entry in menu (and optionnaly of
# unnumbered in menus, see next variable)
$MENU_SYMBOL = '•';
#$MENU_SYMBOL = '*';

set_default('SIMPLE_MENU', 0);

# extension for nodes files when NODE_FILES is true
set_default('NODE_FILE_EXTENSION', 'html');

# extension
set_default('EXTENSION', 'html');

# default is to split the html output
set_default('SPLIT', 'node');

# this resets all the variables to the texi2html specific values if
# called as texi2html

t2h_default_set_variables_texi2html() if ($COMMAND_NAME eq 'texi2html');

# this controls the pre style for menus
$MENU_PRE_STYLE = 'font-family: serif';

# on bug-texinfo is has been said the the style is not code_style
# for menus (except for the node name).
# this controls the menu preformatted format
# FIXME this is not dynamic, so change in MENU_PRE_STYLE is not taken
# into account.
# This is used if the menu appears within a preformatted format (which
# is certainly an invalid construct), and SIMPLE_MENU is not set.
$MENU_PRE_COMPLEX_FORMAT = {
              'pre_style' => $MENU_PRE_STYLE,
              'class' => 'menu-preformatted',
#              'style' => 'code'
   };

# This controls the ul style for toc
$NO_BULLET_LIST_STYLE = 'list-style: none';
$NO_BULLET_LIST_CLASS = 'no-bullet';
$NO_BULLET_LIST_ATTRIBUTE = ' class="'.$NO_BULLET_LIST_CLASS.'"';

# These lines are inserted before and after the shortcontents
$BEFORE_OVERVIEW = "
\n";
$AFTER_OVERVIEW = "
\n";

# These lines are inserted before and after the contents
$BEFORE_TOC_LINES = "
\n";
$AFTER_TOC_LINES = "
\n";

# text inserted after
$AFTER_BODY_OPEN = '';

# text inserted before , this will be automatically inside

$PRE_BODY_CLOSE = '';

# this is added inside  after <title> and some <meta name>
# stuff, it can be used for eg.