1#!/usr/bin/perl --
2# perl
3'di ';
4'ig 00 ';
5#+##############################################################################
6#
7# *** THIS PROGRAM WAS MODIFIED FOR PROCESSING THE GAMBIT MANUAL ***
8#
9# The original file can be found here
10#
11#   http://nongnu.askapache.com/texi2html/texi2html-1.82.tar.gz
12#
13# The lines that were modified contain the comment "###GAMBIT###".
14#
15#-##############################################################################
16#+##############################################################################
17#
18# texi2html: Program to transform Texinfo documents to HTML
19#
20#    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
21#                             Derek Price <derek@ximbiot.com>,
22#                             Adrian Aichner <adrian@xemacs.org>,
23#                           & others.
24#
25#    This program is free software; you can redistribute it and/or modify
26#    it under the terms of the GNU General Public License as published by
27#    the Free Software Foundation; either version 2 of the License, or
28#    (at your option) any later version.
29#
30#    This program is distributed in the hope that it will be useful,
31#    but WITHOUT ANY WARRANTY; without even the implied warranty of
32#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33#    GNU General Public License for more details.
34#
35#    You should have received a copy of the GNU General Public License
36#    along with this program; if not, write to the Free Software
37#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
38#    02110-1301  USA
39#
40#-##############################################################################
41# The man page for this program is included at the end of this file and can be
42# viewed using the command 'nroff -man texi2html'.
43
44# for POSIX::setlocale and File::Spec
45require 5.00405;
46# Perl pragma to restrict unsafe constructs
47use strict;
48# used in case of tests, to revert to "C" locale.
49use POSIX qw(setlocale LC_ALL LC_CTYPE);
50# used to obtain the name of the current working directory
51use Cwd;
52# Used to find the parent directory of this script.
53use File::Basename;
54# used to find a relative path back to the current working directory
55use File::Spec;
56
57#
58# According to
59# larry.jones@sdrc.com (Larry Jones)
60# this pragma is not present in perl5.004_02:
61#
62# Perl pragma to control optional warnings
63# use warnings;
64
65#++##########################################################################
66#
67# NOTE FOR DEBUGGING THIS SCRIPT:
68# You can run 'perl texi2html.pl' directly, provided you have the script
69# in the same directory with, or the environment variable T2H_HOME set to
70# the directory containing, the texi2html.init, T2h_i18n.pm, translations.pl,
71# l2h.init, & T2h_l2h.pm files
72#
73#--##########################################################################
74my $T2H_HOME = defined $ENV{T2H_HOME} ? $ENV{T2H_HOME} : dirname $0;
75if ($0 =~ /\.pl$/)
76{
77    # Issue a warning in debugging mode if $T2H_HOME is set but isn't
78    # accessible.
79    if (!-e $T2H_HOME)
80    { warn "T2H_HOME ($T2H_HOME) does not exist."; }
81    elsif (!-d $T2H_HOME)
82    { warn "T2H_HOME ($T2H_HOME) is not a directory."; }
83    elsif (!-x $T2H_HOME)
84    { warn "T2H_HOME ($T2H_HOME) is not accessible."; }
85}
86
87# CVS version:
88# $Id: texi2html.pl,v 1.255 2009/01/05 11:44:48 pertusus Exp $
89
90# Homepage:
91my $T2H_HOMEPAGE = "http://www.nongnu.org/texi2html/";
92
93# Authors (appears in comments):
94my $T2H_AUTHORS = <<EOT;
95texi2html was written by:
96            Lionel Cons <Lionel.Cons\@cern.ch> (original author)
97            Karl Berry  <karl\@freefriends.org>
98            Olaf Bachmann <obachman\@mathematik.uni-kl.de>
99            and many others.
100Maintained by: Many creative people.
101Send bugs and suggestions to <texi2html-bug\@nongnu.org>
102EOT
103
104# Version: set in configure.in
105my $THISVERSION = '1.82';
106my $THISPROG = "texi2html $THISVERSION"; # program name and version
107
108#+++########################################################################
109#                                                                          #
110# Paths and file names                                                     #
111#                                                                          #
112#---########################################################################
113
114# set by configure, prefix for the sysconfdir and so on
115my $prefix = '/usr/local';
116my $datarootdir = '${prefix}/share';
117my $sysconfdir;
118my $pkgdatadir;
119my $datadir;
120
121# We need to eval as $prefix has to be expanded. However when we haven't
122# run configure @sysconfdir will be expanded as an array, thus we verify
123# whether configure was run or not
124if ('${prefix}/etc' ne '@' . 'sysconfdir@')
125{
126    $sysconfdir = eval '"${prefix}/etc"';
127}
128else
129{
130    $sysconfdir = "/usr/local/etc";
131}
132
133if ('${datarootdir}' ne '@' . 'datadir@')
134{
135    $pkgdatadir = eval '"${datarootdir}/texi2html"';
136    $datadir = eval '"${datarootdir}"';
137}
138else
139{
140    $pkgdatadir = "/usr/local/share/texi2html";
141    $datadir = "/usr/local/share";
142}
143
144my $i18n_dir = 'i18n'; # name of the directory containing the per language files
145my $conf_file_name = 'Config' ;
146my $texinfo_htmlxref = 'htmlxref.cnf';
147
148my $target_prefix = "t_h";
149
150# directories for texi2html init files
151my @texi2html_config_dirs = ('./');
152push @texi2html_config_dirs, "$ENV{'HOME'}/.texi2html/" if (defined($ENV{'HOME'}));
153push @texi2html_config_dirs, "$sysconfdir/texi2html/" if (defined($sysconfdir));
154push @texi2html_config_dirs, "$pkgdatadir" if (defined($pkgdatadir));
155
156# directories for texinfo configuration files
157my @texinfo_config_dirs = ('./.texinfo/');
158push @texinfo_config_dirs, "$ENV{'HOME'}/.texinfo/" if (defined($ENV{'HOME'}));
159push @texinfo_config_dirs, "$sysconfdir/texinfo/" if (defined($sysconfdir));
160push @texinfo_config_dirs, "$datadir/texinfo/" if (defined($datadir));
161
162
163#+++########################################################################
164#                                                                          #
165# Constants                                                                #
166#                                                                          #
167#---########################################################################
168
169my $DEBUG_MENU   =  1;
170my $DEBUG_INDEX =  2;
171my $DEBUG_TEXI  =  4;
172my $DEBUG_MACROS =  8;
173my $DEBUG_FORMATS   = 16;
174my $DEBUG_ELEMENTS  = 32;
175my $DEBUG_USER  = 64;
176my $DEBUG_L2H   = 128;
177
178my $ERROR = "***";                 # prefix for errors
179my $WARN  = "**";                  # prefix for warnings
180
181my $VARRE = '[\w\-]+';          # RE for a variable name
182my $NODERE = '[^:]+';             # RE for node names
183
184my $MAX_LEVEL = 4;
185my $MIN_LEVEL = 1;
186
187#+++###########################################################################
188#                                                                             #
189# Initialization                                                              #
190# Some declarations, some functions that are GPL and therefore cannot be in   #
191# texi2html.init, some functions that are not to be customized.               #
192# Pasted content of File $(srcdir)/texi2html.init: Default initializations    #
193#                                                                             #
194#---###########################################################################
195
196{
197package Texi2HTML::Config;
198
199
200sub load($)
201{
202    my $file = shift;
203    eval { require($file) ;};
204    if ($@ ne '')
205    {
206        print STDERR "error loading $file: $@\n";
207        return 0;
208    }
209    return 1;
210}
211
212# customization options variables
213
214use vars qw(
215$DEBUG
216$PREFIX
217$VERBOSE
218$SUBDIR
219$IDX_SUMMARY
220$SPLIT
221$SHORT_REF
222@EXPAND
223$EXPAND
224$TOP
225$DOCTYPE
226$FRAMESET_DOCTYPE
227$ERROR_LIMIT
228$CHECK
229$TEST
230$DUMP_TEXI
231$MACRO_EXPAND
232$USE_GLOSSARY
233$INVISIBLE_MARK
234$USE_ISO
235$TOP_FILE
236$TOC_FILE
237$FRAMES
238$SHOW_MENU
239$NUMBER_SECTIONS
240$USE_NODES
241$USE_SECTIONS
242$USE_NODE_TARGET
243$USE_UNICODE
244$USE_UNIDECODE
245$TRANSLITERATE_NODE
246$NODE_FILES
247$NODE_NAME_IN_MENU
248$AVOID_MENU_REDUNDANCY
249$SECTION_NAVIGATION
250$MONOLITHIC
251$SHORTEXTN
252$EXTENSION
253$OUT
254$NOVALIDATE
255$DEF_TABLE
256$LANG
257$DO_CONTENTS
258$DO_SCONTENTS
259$SEPARATED_FOOTNOTES
260$TOC_LINKS
261$L2H
262$L2H_L2H
263$L2H_SKIP
264$L2H_TMP
265$L2H_CLEAN
266$L2H_FILE
267$L2H_HTML_VERSION
268$EXTERNAL_DIR
269@INCLUDE_DIRS
270@PREPEND_DIRS
271@CONF_DIRS
272$IGNORE_PREAMBLE_TEXT
273@CSS_FILES
274@CSS_REFS
275$INLINE_CONTENTS
276$INLINE_INSERTCOPYING
277);
278
279# customization variables
280# ENCODING is deprecated
281use vars qw(
282$ENCODING
283
284$ENCODING_NAME
285$DOCUMENT_ENCODING
286$OUT_ENCODING
287$IN_ENCODING
288$DEFAULT_ENCODING
289$MENU_PRE_STYLE
290$MENU_PRE_COMPLEX_FORMAT
291$CENTER_IMAGE
292$EXAMPLE_INDENT_CELL
293$SMALL_EXAMPLE_INDENT_CELL
294$SMALL_FONT_SIZE
295$SMALL_RULE
296$DEFAULT_RULE
297$MIDDLE_RULE
298$BIG_RULE
299$TOP_HEADING
300$INDEX_CHAPTER
301$SPLIT_INDEX
302$HREF_DIR_INSTEAD_FILE
303$USE_MENU_DIRECTIONS
304$USE_UP_FOR_ADJACENT_NODES
305$AFTER_BODY_OPEN
306$PRE_BODY_CLOSE
307$EXTRA_HEAD
308$VERTICAL_HEAD_NAVIGATION
309$WORDS_IN_PAGE
310$ICONS
311$UNNUMBERED_SYMBOL_IN_MENU
312$SIMPLE_MENU
313$MENU_SYMBOL
314$USE_ACCESSKEY
315$USE_REL_REV
316$USE_LINKS
317$OPEN_QUOTE_SYMBOL
318$CLOSE_QUOTE_SYMBOL
319$NO_BULLET_LIST_STYLE
320$NO_BULLET_LIST_ATTRIBUTE
321$TOP_NODE_FILE
322$TOP_NODE_UP
323$NODE_FILE_EXTENSION
324$BEFORE_OVERVIEW
325$AFTER_OVERVIEW
326$BEFORE_TOC_LINES
327$AFTER_TOC_LINES
328$NEW_CROSSREF_STYLE
329$TOP_HEADING_AT_BEGINNING
330$USER
331$USE_NUMERIC_ENTITY
332$USE_SETFILENAME
333$SEPARATE_DESCRIPTION
334$IGNORE_BEFORE_SETFILENAME
335$OVERVIEW_LINK_TO_TOC
336$COMPLETE_IMAGE_PATHS
337$DATE
338%ACTIVE_ICONS
339%NAVIGATION_TEXT
340%PASSIVE_ICONS
341%BUTTONS_NAME
342%BUTTONS_GOTO
343%BUTTONS_EXAMPLE
344%BUTTONS_ACCESSKEY
345%BUTTONS_REL
346@CHAPTER_BUTTONS
347@MISC_BUTTONS
348@SECTION_BUTTONS
349@SECTION_FOOTER_BUTTONS
350@NODE_FOOTER_BUTTONS
351@LINKS_BUTTONS
352@IMAGE_EXTENSIONS
353);
354
355# customization variables which may be guessed in the script
356#our $ADDRESS;
357use vars qw(
358$BODYTEXT
359$CSS_LINES
360$DOCUMENT_DESCRIPTION
361$EXTERNAL_CROSSREF_SPLIT
362);
363
364# I18n
365use vars qw(
366$I
367$LANGUAGES
368);
369
370# customizable subroutines references
371use vars qw(
372$print_section
373$one_section
374$end_section
375$print_Top_header
376$print_Top_footer
377$print_Top
378$print_Toc
379$print_Overview
380$print_Footnotes
381$print_About
382$print_misc_header
383$print_misc_footer
384$print_misc
385$print_section_header
386$print_section_footer
387$print_chapter_header
388$print_chapter_footer
389$print_element_header
390$print_page_head
391$print_page_foot
392$print_head_navigation
393$print_foot_navigation
394$button_icon_img
395$print_navigation
396$about_body
397$print_frame
398$print_toc_frame
399$toc_body
400$titlepage
401$insertcopying
402$css_lines
403$print_redirection_page
404$translate_names
405$init_out
406$finish_out
407$node_file_name
408$element_file_name
409$node_target_name
410$element_target_name
411$placed_target_file_name
412$inline_contents
413$program_string
414
415$preserve_misc_command
416$protect_text
417$anchor
418$anchor_label
419$element_label
420$misc_element_label
421$def_item
422$def
423$menu
424$menu_command
425$menu_link
426$menu_description
427$menu_comment
428$simple_menu_link
429$ref_beginning
430$info_ref
431$book_ref
432$external_href
433$external_ref
434$internal_ref
435$table_item
436$table_line
437$row
438$cell
439$list_item
440$comment
441$def_line
442$def_line_no_texi
443$heading_no_texi
444$raw
445$raw_no_texi
446$heading
447$element_heading
448$paragraph
449$preformatted
450$foot_line_and_ref
451$foot_section
452$address
453$image
454$image_files
455$index_entry_label
456$index_entry
457$index_entry_command
458$index_letter
459$print_index
460$printindex
461$index_summary
462$summary_letter
463$complex_format
464$cartouche
465$sp
466$definition_category
467$definition_index_entry
468$table_list
469$copying_comment
470$documentdescription
471$index_summary_file_entry
472$index_summary_file_end
473$index_summary_file_begin
474$style
475$format
476$normal_text
477$empty_line
478$unknown
479$unknown_style
480$float
481$caption_shortcaption
482$caption_shortcaption_command
483$listoffloats
484$listoffloats_entry
485$listoffloats_caption
486$listoffloats_float_style
487$listoffloats_style
488$acronym_like
489$quotation
490$quotation_prepend_text
491$paragraph_style_command
492$heading_texi
493$index_element_heading_texi
494$format_list_item_texi
495$begin_format_texi
496$begin_style_texi
497$begin_paragraph_texi
498$tab_item_texi
499$colon_command
500$simple_command
501$thing_command
502$begin_special_region
503$end_special_region
504
505$PRE_ABOUT
506$AFTER_ABOUT
507);
508
509# hash which entries might be redefined by the user
510use vars qw(
511$complex_format_map
512%accent_map
513%def_map
514%format_map
515%simple_map
516%simple_map_pre
517%simple_map_texi
518%simple_map_math
519%simple_map_pre_math
520%simple_map_texi_math
521%style_map
522%style_map_pre
523%style_map_texi
524%simple_format_simple_map_texi
525%simple_format_style_map_texi
526%simple_format_texi_map
527%command_type
528%paragraph_style
529%stop_paragraph_command
530%format_code_style
531%region_formats_kept
532%texi_formats_map
533%things_map
534%pre_map
535%texi_map
536%unicode_map
537%unicode_diacritical
538%transliterate_map
539%transliterate_accent_map
540%no_transliterate_map
541%ascii_character_map
542%ascii_simple_map
543%ascii_things_map
544%numeric_entity_map
545%perl_charset_to_html
546%misc_pages_targets
547%iso_symbols
548%misc_command
549%no_paragraph_commands
550%css_map
551%format_in_paragraph
552%special_list_commands
553%accent_letters
554%unicode_accents
555%special_accents
556%inter_item_commands
557$def_always_delimiters
558$def_in_type_delimiters
559$def_argument_separator_delimiters
560%colon_command_punctuation_characters
561@command_handler_init
562@command_handler_process
563@command_handler_finish
564%command_handler
565%special_style
566);
567
568# subject to change
569use vars qw(
570%makeinfo_encoding_to_map
571%makeinfo_unicode_to_eight_bit
572%eight_bit_to_unicode
573%t2h_encoding_aliases
574);
575
576# needed in this namespace for translations
577$I = \&Texi2HTML::I18n::get_string;
578
579#
580# Function refs covered by the GPL as part of the texi2html.pl original
581# code. As such they cannot appear in texi2html.init which is public
582# domain (at least the things coded by me, and, if I'm not wrong also the
583# things coded by Olaf -- Pat).
584#
585
586$toc_body                 = \&T2H_GPL_toc_body;
587$style                    = \&T2H_GPL_style;
588$format                   = \&T2H_GPL_format;
589$printindex               = \&t2h_GPL_default_printindex;
590$summary_letter           = \&t2h_default_summary_letter;
591
592sub T2H_GPL_toc_body($)
593{
594    my $elements_list = shift;
595    return unless ($Texi2HTML::THISDOC{'DO_CONTENTS'} or
596      $Texi2HTML::THISDOC{'DO_SCONTENTS'} or $FRAMES);
597    my $current_level = 0;
598    my $ul_style = $NUMBER_SECTIONS ? $NO_BULLET_LIST_ATTRIBUTE : '';
599    foreach my $element (@$elements_list)
600    {
601        next if ($element->{'top'});
602        my $ind = '  ' x $current_level;
603        my $level = $element->{'toc_level'};
604        print STDERR "Bug no toc_level for ($element) $element->{'texi'}\n" if (!defined ($level));
605        if ($level > $current_level)
606        {
607            while ($level > $current_level)
608            {
609                $current_level++;
610                my $ln = "\n$ind<ul${ul_style}>\n";
611                $ind = '  ' x $current_level;
612                push(@{$Texi2HTML::TOC_LINES}, $ln);
613            }
614        }
615        elsif ($level < $current_level)
616        {
617            while ($level < $current_level)
618            {
619                $current_level--;
620                $ind = '  ' x $current_level;
621                my $line = "</li>\n$ind</ul>";
622                $line .=  "</li>" if ($level == $current_level);
623                push(@{$Texi2HTML::TOC_LINES}, "$line\n");
624
625            }
626        }
627        else
628        {
629            push(@{$Texi2HTML::TOC_LINES}, "</li>\n");
630        }
631        # if there is more than one toc, in different files, the toc in
632        # the file different from $Texi2HTML::THISDOC{'toc_file'} may have
633        # wrong links, that is links that point to the same file and are
634        # therefore empty, although the section isn't in the current file,
635        # since it is in $Texi2HTML::THISDOC{'toc_file'}.
636        my $dest_for_toc = $element->{'file'};
637        my $dest_for_stoc = $element->{'file'};
638        my $dest_target_for_stoc = $element->{'target'};
639        if ($Texi2HTML::Config::OVERVIEW_LINK_TO_TOC)
640        {
641            $dest_for_stoc = $Texi2HTML::THISDOC{'toc_file'};
642            $dest_target_for_stoc = $element->{'tocid'};
643        }
644        $dest_for_toc = '' if ($dest_for_toc eq $Texi2HTML::THISDOC{'toc_file'});
645        $dest_for_stoc = '' if ($dest_for_stoc eq $Texi2HTML::THISDOC{'stoc_file'});
646        my $text = $element->{'text'};
647        #$text = $element->{'name'} unless ($NUMBER_SECTIONS);
648        my $toc_entry = "<li>" . &$anchor ($element->{'tocid'}, "$dest_for_toc#$element->{'target'}",$text);
649        my $stoc_entry = "<li>" . &$anchor ($element->{'stocid'}, "$dest_for_stoc#$dest_target_for_stoc",$text);
650        push (@{$Texi2HTML::TOC_LINES}, $ind . $toc_entry);
651        push(@{$Texi2HTML::OVERVIEW}, $stoc_entry. "</li>\n") if ($level == 1);
652    }
653    while (0 < $current_level)
654    {
655        $current_level--;
656        my $ind = '  ' x $current_level;
657        push(@{$Texi2HTML::TOC_LINES}, "</li>\n$ind</ul>\n");
658    }
659    @{$Texi2HTML::TOC_LINES} = () unless ($Texi2HTML::THISDOC{'DO_CONTENTS'});
660    if (@{$Texi2HTML::TOC_LINES})
661    {
662        unshift @{$Texi2HTML::TOC_LINES}, $BEFORE_TOC_LINES;
663        push @{$Texi2HTML::TOC_LINES}, $AFTER_TOC_LINES;
664    }
665    @{$Texi2HTML::OVERVIEW} = () unless ($Texi2HTML::THISDOC{'DO_SCONTENTS'} or $FRAMES);
666    if (@{$Texi2HTML::OVERVIEW})
667    {
668        unshift @{$Texi2HTML::OVERVIEW}, "<ul${ul_style}>\n";
669        push @{$Texi2HTML::OVERVIEW}, "</ul>\n";
670        unshift @{$Texi2HTML::OVERVIEW}, $BEFORE_OVERVIEW;
671        push @{$Texi2HTML::OVERVIEW}, $AFTER_OVERVIEW;
672    }
673}
674
675sub T2H_GPL_style($$$$$$$$$)
676{                           # known style
677    my $style = shift;
678    my $command = shift;
679    my $text = shift;
680    my $args = shift;
681    my $no_close = shift;
682    my $no_open = shift;
683    my $line_nr = shift;
684    my $state = shift;
685    my $style_stack = shift;
686
687    my $do_quotes = 0;
688    my $use_attribute = 0;
689    my $use_begin_end = 0;
690    if (ref($style) eq 'HASH')
691    {
692        #print STDERR "GPL_STYLE $command ($style)\n";
693        #print STDERR " @$args\n";
694        if (ref($style->{'args'}) ne 'ARRAY')
695        {
696            print STDERR "BUG: args not an array for command `$command'\n";
697        }
698        $do_quotes = $style->{'quote'};
699        if ((@{$style->{'args'}} == 1) and defined($style->{'attribute'}))
700        {
701            $style = $style->{'attribute'};
702            $use_attribute = 1;
703            $text = $args->[0];
704        }
705        elsif (defined($style->{'function'}))
706        {
707            $text = &{$style->{'function'}}($command, $args, $style_stack, $state, $line_nr);
708        }
709    }
710    else
711    {
712        if ($style =~ s/^\"//)
713        {                       # add quotes
714            $do_quotes = 1;
715        }
716        if ($style =~ s/^\&//)
717        {                       # custom
718            $style = 'Texi2HTML::Config::' . $style;
719            eval "\$text = &$style(\$text, \$command, \$style_stack)";
720        }
721        elsif ($style ne '')
722        {
723            $use_attribute = 1;
724        }
725        else
726        {                       # no style
727        }
728    }
729    if ($use_attribute)
730    {                       # good style
731        my $attribute_text = '';
732        if ($style =~ /^(\w+)(\s+.*)/)
733        {
734            $style = $1;
735            $attribute_text = $2;
736        }
737#        $text = "<${style}$attribute_text>$text</$style>" ;
738        $text = "<${style}$attribute_text>" . "$text" if (!$no_open);
739        $text .= "</$style>" if (!$no_close);
740        if ($do_quotes)
741        {
742             $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
743             $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
744        }
745    }
746    if (ref($style) eq 'HASH')
747    {
748        if (defined($style->{'begin'}) and !$no_open)
749        {
750             $text = $style->{'begin'} . $text;
751        }
752        if (defined($style->{'end'}) and !$no_close)
753        {
754            $text = $text . $style->{'end'};
755        }
756    }
757    if ($do_quotes and !$use_attribute)
758    {
759        $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
760        $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
761    }
762    return $text;
763}
764
765sub T2H_GPL_format($$$)
766{
767    my $tag = shift;
768    my $element = shift;
769    my $text = shift;
770    return '' if (!defined($element) or ($text !~ /\S/));
771    return $text if ($element eq '');
772    my $attribute_text = '';
773    if ($element =~ /^(\w+)(\s+.*)/)
774    {
775        $element = $1;
776        $attribute_text = $2;
777    }
778    return "<${element}$attribute_text>\n" . $text. "</$element>\n";
779}
780
781my $t2h_default_file_number;
782my $t2h_default_index_page_nr;
783#my %t2h_default_element_indices;
784my %t2h_default_index_letters_hash;
785my %t2h_default_index_letters_array;
786my %t2h_default_seen_files;
787my $t2h_default_element_split_printindices;
788my %t2h_default_split_files;
789
790# FIXME call it where indices are split in main program
791sub t2h_default_init_split_indices ()
792{
793    #print STDERR "Do splitting of index letters, once.\n";
794
795    push @command_handler_process, \&t2h_default_index_rearrange_directions;
796    %t2h_default_index_letters_hash = ();
797    %t2h_default_index_letters_array = ();
798    %t2h_default_seen_files = ();
799    %t2h_default_split_files = ();
800    $t2h_default_element_split_printindices = undef;
801    $t2h_default_index_page_nr = 0;
802    $t2h_default_file_number = 0;
803
804    foreach my $index_name (keys %{$Texi2HTML::THISDOC{'indices'}})
805    {
806      #print STDERR "Gathering and sorting $index_name letters\n";
807      foreach my $key (keys %{$Texi2HTML::THISDOC{'indices'}->{$index_name}->[0]->{'entries'}})
808      {
809        my $letter = uc(substr($key, 0, 1));
810        $t2h_default_index_letters_hash{$index_name}->{$letter}->{$key} = $Texi2HTML::THISDOC{'indices'}->{$index_name}->[0]->{'entries'}->{$key};
811      }
812
813      my $entries_count = 0;
814      my @letters = ();
815      # use cmp if only letters or only symbols, otherwise symbols before
816      # letters
817      foreach my $letter (sort {
818         ((($a =~ /^[[:alpha:]]/ and $b =~ /^[[:alpha:]]/) or
819          ($a !~ /^[[:alpha:]]/ and $b !~ /^[[:alpha:]]/)) && $a cmp $b)
820             || ($a =~ /^[[:alpha:]]/ && 1) || -1 } (keys(%{$t2h_default_index_letters_hash{$index_name}})))
821      {
822        my $letter_entry = {'letter' => $letter };
823        foreach my $key (sort {uc($a) cmp uc($b)} (keys(%{$t2h_default_index_letters_hash{$index_name}->{$letter}})))
824        {
825          push @{$letter_entry->{'entries'}}, $t2h_default_index_letters_hash{$index_name}->{$letter}->{$key};
826        }
827        push @letters, $letter_entry;
828        $entries_count += scalar(@{$letter_entry->{'entries'}});
829        #if ($SPLIT and $SPLIT_INDEX and $entries_count >= $SPLIT_INDEX)
830        # FIXME this is not right, above is right
831        # Don't split if document is not split
832        if ($SPLIT and $SPLIT_INDEX and $entries_count > $SPLIT_INDEX)
833        {
834          push @{$t2h_default_index_letters_array{$index_name}}, [ @letters ];
835          @letters = ();
836          $entries_count = 0;
837        }
838      }
839      push @{$t2h_default_index_letters_array{$index_name}}, [ @letters ] if (scalar(@letters));
840    }
841}
842
843sub t2h_default_associate_index_element($$$$)
844{
845  my $element = shift;
846  my $is_top = shift;
847  my $docu_name = shift;
848  my $use_node_file = shift;
849
850  my ($file, $default_element_file);
851
852  if ($SPLIT)
853  {
854    # respect the default splitting
855    $default_element_file = $element->{'file'};
856    if ($t2h_default_seen_files{$default_element_file})
857    {
858      $file = $t2h_default_seen_files{$default_element_file};
859    }
860    else
861    {
862      if ($is_top eq 'top')
863      {
864        $file = $default_element_file;
865      }
866      else
867      {
868        $file = "${docu_name}_$t2h_default_file_number";
869        $file .= '.' . $Texi2HTML::THISDOC{'extension'} if
870           (defined($Texi2HTML::THISDOC{'extension'}));
871      }
872      $t2h_default_file_number++;
873      $t2h_default_seen_files{$default_element_file} = $file;
874    }
875  }
876  my $modify_file = ($SPLIT and (!$use_node_file or $t2h_default_split_files{$default_element_file}));
877  $element->{'file'} = $file if ($modify_file);
878
879  my $current_element = $element;
880  #print STDERR "Doing printindices for $element $element->{'texi'}, file $file (@{$element->{'place'}})\n";
881
882  my @places = @{$element->{'place'}};
883  @{$element->{'place'}} = ();
884
885  foreach my $place (@places)
886  {
887    unless ($place->{'command'} and $place->{'command'} eq 'printindex')
888    {
889#print STDERR "HHHHHHHHH ($element->{'texi'}) place: $place->{'texi'}, current: $current_element->{'texi'}, $current_element->{'file'}\n";
890       push @{$current_element->{'place'}}, $place;
891       $place->{'file'} = $current_element->{'file'};
892       $place->{'element_ref'} = $current_element if ($place->{'element_ref'} and $current_element ne $element);
893       next;
894    }
895    my $printindex = $place;
896    my $index_name = $printindex->{'name'};
897    #print STDERR "Associate letters in $element->{'texi'} for $index_name\n";
898    my @letter_groups = ();
899    # empty index
900    next if (!exists($t2h_default_index_letters_array{$index_name}));
901    my @letters_split = @{$t2h_default_index_letters_array{$index_name}};
902
903    # index is not split
904    if (scalar(@letters_split) eq 1)
905    {
906      push @{$letter_groups[0]->{'letters'}}, @{$letters_split[0]};
907    }
908    # the element is at the level of splitting, then we split according to
909    # INDEX_SPLIT
910    elsif (!$element->{'top'} and $SPLIT and (($SPLIT eq 'node') or (defined($element->{'level'}) and $element->{'level'} <= $Texi2HTML::THISDOC{'split_level'})))
911    {
912      $t2h_default_split_files{$default_element_file} = 1;
913      foreach my $letters_split (@letters_split)
914      {
915        push @letter_groups, {'letters' => [@$letters_split]};
916      }
917    }
918    else
919    { # we 'unsplit' index split if not located where document is indeed split
920      #print STDERR "UNSPLIT $element->{'texi'}, $index_name\n";
921      foreach my $letters_split (@letters_split)
922      {
923        push @{$letter_groups[0]->{'letters'}}, @$letters_split;
924      }
925    }
926    $letter_groups[0]->{'element'} = $current_element;
927    # may only happen if SPLIT
928    if (scalar(@letter_groups) > 1)
929    { # this weird construct is there because the element use as a key is
930      # converted to a string by perl, losing its meaning as a reference,
931      # the reference must be recorded explicitly
932      $t2h_default_element_split_printindices->{$element}->{'element'} = $element;
933      push @{$t2h_default_element_split_printindices->{$element}->{'printindices'}}, $printindex;
934      #print STDERR "Pushing $element, $element->{'texi'}, $printindex\n";
935      foreach my $split_group (@letter_groups)
936      {
937        my $first_letter = $split_group->{'letters'}->[0]->{'letter'};
938        my $last_letter = $split_group->{'letters'}->[-1]->{'letter'};
939        if (!$split_group->{'element'})
940        {
941          #construct new element name
942          my $letters_heading;
943          if ($last_letter ne $first_letter)
944          {
945            $letters_heading = &$normal_text("$first_letter -- $last_letter");
946          }
947          else
948          {
949            $letters_heading = &$normal_text("$first_letter");
950          }
951          my ($name, $simple);
952          my $texi = "ADDED ELEMENT $element->{'texi'}: $letters_heading";
953          if (!defined($element->{'text'}))
954          {
955            my $element_heading_texi = &$heading_texi($element->{'tag'}, $element->{'texi'}, $element->{'number'});
956
957            my $heading_texi = &$index_element_heading_texi(
958                 $element_heading_texi,
959                 $element->{'tag'},
960                 $element->{'texi'},
961                 $element->{'number'},
962                 $first_letter, $last_letter);
963            $name = main::substitute_line($heading_texi);
964            $simple = main::simple_format(undef,undef,$heading_texi);
965          }
966          else
967          { # should never happen
968            $name = "$element->{'text'}: $letters_heading";
969            $simple = "$element->{'simple_format'}: $letters_heading";
970          }
971
972          #file and id
973          my $relative_file = $Texi2HTML::THISDOC{'file_base_name'} . '_' . $t2h_default_file_number;
974          $t2h_default_file_number++;
975          $relative_file .= '.' . $Texi2HTML::THISDOC{'extension'} if
976             (defined($Texi2HTML::THISDOC{'extension'}));
977          my $id = "index_split-$t2h_default_index_page_nr";
978          $t2h_default_index_page_nr++;
979
980          my $new_element = { 'file' => $relative_file, 'id' => $id, 'target' => $id, 'text' => $name, 'texi' => $texi, 'seen' => 1, 'simple_format' => $simple };
981
982          $split_group->{'element'} = $new_element;
983          $current_element = $new_element;
984          #print STDERR "Added $new_element->{'file'} for $new_element->{'texi'} ($first_letter:$last_letter)\n";
985        }
986        else
987        { # this is the first index split, it is still associated with the element
988          #print STDERR "No file added for ($first_letter:$last_letter)\n";
989        }
990      }
991      $t2h_default_seen_files{$default_element_file} = $current_element->{'file'};
992    }
993    else
994    {
995       push @{$current_element->{'place'}}, $place;
996    }
997    $printindex->{'split_groups'} = \@letter_groups;
998    #print STDERR "$index_name processed for $element, $element->{'texi'} (@{$printindex->{'split_groups'}})\n";
999  }
1000
1001  return $file if ($modify_file);
1002  return undef;
1003}
1004
1005sub t2h_default_index_rearrange_directions()
1006{
1007  return if (!defined($t2h_default_element_split_printindices));
1008  foreach my $element_string (keys(%$t2h_default_element_split_printindices))
1009  {
1010    my $element = $t2h_default_element_split_printindices->{$element_string}->{'element'};
1011    my $current_element = $element;
1012    #print STDERR " E Processing $element_string,$current_element $current_element->{'texi'}\n";
1013    foreach my $printindex (@{$t2h_default_element_split_printindices->{$element_string}->{'printindices'}})
1014    {
1015      #print STDERR "  I Processing $printindex $printindex->{'name'} (@{$printindex->{'split_groups'}})\n";
1016      foreach my $split_group (@{$printindex->{'split_groups'}})
1017      {
1018        my $first_letter = $split_group->{'letters'}->[0]->{'letter'};
1019        my $last_letter = $split_group->{'letters'}->[-1]->{'letter'};
1020
1021        my $new_element = $split_group->{'element'};
1022        next if ($current_element eq $new_element);
1023        #print STDERR "   G Processing ($first_letter:$last_letter) in $element->{'texi'}, index $printindex->{'name'}: $new_element->{'texi'}\n";
1024        $new_element->{'This'} = $new_element;
1025        if ($current_element->{'Forward'})
1026        {
1027          $current_element->{'Forward'}->{'Back'} = $new_element;
1028          $new_element->{'Forward'} = $current_element->{'Forward'};
1029        }
1030        $current_element->{'Forward'} = $new_element;
1031        $new_element->{'Back'} = $current_element;
1032        if ($current_element->{'Following'})
1033        {
1034#print STDERR "F: C($current_element): $current_element->{'texi'}, N($new_element): $new_element->{'texi'} -- C->F: $current_element->{'Following'}->{'texi'}\n";
1035          $new_element->{'Following'} = $current_element->{'Following'};
1036          $current_element->{'Following'} = $new_element;
1037        }
1038        foreach my $key ('FastForward', 'FastBack', 'Up', 'tag_level', 'tag',
1039            'level', 'node')
1040        {
1041          $new_element->{$key} = $element->{$key} if (defined($element->{$key}));
1042        }
1043        $current_element = $new_element;
1044      }
1045    }
1046  }
1047}
1048
1049# not needed to initialize it for a document, since it is reset
1050# in index_summary
1051my $t2h_symbol_indices = 0;
1052
1053# format a letter appearing in a summary for an index. The letter links to
1054# the place where the index elements beginning with this letter are (called
1055# a letter entry).
1056#
1057# arguments:
1058# letter
1059# file where the target letter entry is
1060# identifier for the target letter entry
1061
1062# This should better be in texi2html.init, but $t2h_symbol_indices
1063# has to be in the same file scope than printindeex.
1064sub t2h_default_summary_letter($$$$$$$)
1065{
1066   my $letter = shift;
1067   my $file = shift;
1068   my $default_identifier = shift;
1069   my $index_element_id = shift;
1070   my $number = shift;
1071   my $index_element = shift;
1072   my $index_name = shift;
1073
1074   my $is_symbol = $letter !~ /^[A-Za-z]/;
1075   my $identifier = $default_identifier;
1076
1077   if ($NEW_CROSSREF_STYLE)
1078   {
1079      if ($is_symbol)
1080      {
1081         $t2h_symbol_indices++;
1082         $identifier = $index_element_id . "_${index_name}_symbol-$t2h_symbol_indices";
1083      }
1084      else
1085      {
1086         $identifier = $index_element_id . "_${index_name}_letter-${letter}";
1087      }
1088   }
1089   my $result = &$anchor('', $file . '#' . $identifier, '<b>' . &$protect_text($letter) . '</b>', 'class="summary-letter"');
1090   return $result unless ($NEW_CROSSREF_STYLE);
1091   return ($result, $identifier, $is_symbol);
1092}
1093
1094# this replaces do_index_page
1095# args should be:
1096# index_name
1097sub t2h_GPL_default_printindex($)
1098{
1099  my $index_name = shift;
1100
1101  my %letter_entries;
1102  my $identifier_index_nr = 0;
1103  # could be cross verified with argument
1104  my $printindex = shift @{$Texi2HTML::THISDOC{'printindices'}};
1105  if ($printindex->{'name'} ne $index_name)
1106  {
1107    print STDERR "BUG: THISDOC{'printindices'} $printindex->{'name'} ne $index_name\n";
1108  }
1109#print STDERR "Doing printindex $index_name\n";
1110  return '' if (! defined($printindex->{'split_groups'}));
1111  my @split_letters = @{$printindex->{'split_groups'}};
1112
1113  return '' if (!scalar(@split_letters));
1114
1115  foreach my $split_group (@split_letters)
1116  {
1117    #do summmary
1118    my @non_alpha = ();
1119    my @alpha = ();
1120    my $file = $split_group->{'element'}->{'file'};
1121    # letter_id could be done once for all instead of for each split_group
1122    # and outside of t2h_default_summary_letter (or t2h_default_summary_letter
1123    # could be simplified and inlined
1124    my %letter_id;
1125    foreach my $summary_split_group (@split_letters)
1126    {
1127      foreach my $letter_entry (@{$summary_split_group->{'letters'}})
1128      {
1129        my $letter = $letter_entry->{'letter'};
1130        #my $letter = $letter_entry;
1131        my $dest_file = '';
1132        $dest_file = $summary_split_group->{'element'}->{'file'}
1133           if ($summary_split_group ne $split_group);
1134        my $index_element_id = $summary_split_group->{'element'}->{'id'};
1135        my $default_identifier = $index_element_id . "_$identifier_index_nr";
1136        $identifier_index_nr++;
1137        my ($result, $identifier, $is_symbol) =
1138          &$summary_letter($letter, $dest_file, $default_identifier, $index_element_id, '', '', $index_name);
1139        $identifier = $default_identifier if (!defined($identifier));
1140        $letter_id{$letter} = $identifier;
1141        $is_symbol = $letter !~ /^[A-Za-z]/ if (!defined($is_symbol));
1142
1143        if ($is_symbol)
1144        {
1145          push @non_alpha, $result;
1146        }
1147        else
1148        {
1149          push @alpha, $result;
1150        }
1151      }
1152    }
1153    my $summary = &$index_summary(\@alpha, \@non_alpha);
1154
1155    # reset symbols numbering
1156    $t2h_symbol_indices = 0;
1157
1158    my $letters_text = '';
1159    foreach my $letter_entry (@{$split_group->{'letters'}})
1160    {
1161      my $letter = $letter_entry->{'letter'};
1162      my $entries_text = '';
1163      #foreach my $entry (@{$letter_entries{$letter}->{'entries'}})
1164      foreach my $index_entry_ref (@{$letter_entry->{'entries'}})
1165      {
1166        #my $entry_infos = main::get_index_entry_infos($index_entry, $split_group->{'element'});
1167        #my ($text_href, $entry, $element_href, $element_text, $entry_file, $element_file, $entry_target, $entry_element_target) = @$entry_infos;
1168        my ($text_href, $entry_file, $element_file, $entry_target,
1169          $entry_element_target, $formatted_entry, $element_href, $entry_element_text)
1170          =  main::get_index_entry_infos($index_entry_ref, $split_group->{'element'});
1171        $entries_text .= &$index_entry ($text_href, $formatted_entry, $element_href, $entry_element_text, $entry_file, $element_file, $entry_target, $entry_element_target);
1172      }
1173      $letters_text .= &$index_letter ($letter, $letter_id{$letter}, $entries_text)
1174    }
1175    my $index_text = &$print_index($letters_text, $index_name);
1176    $split_group->{'text'} = $summary . $index_text . $summary;
1177#    print STDERR "    ---> $index_name @{$split_group->{'letters'}}
1178#     * elt:   $split_group->{'element'}->{'id'}, $split_group->{'element'}->{'file'}, $split_group->{'element'}->{'name'}
1179#     * directions: B: $split_group->{'element'}->{'Back'}->{'name'}, F: $split_group->{'element'}->{'Forward'}->{'name'}, FB: $split_group->{'element'}->{'FastBack'}->{'name'}, FF: $split_group->{'element'}->{'FastForward'}->{'name'}
1180#     * text
1181#
1182#$split_group->{'text'}
1183#
1184#";
1185  }
1186  my $current_page = shift @split_letters;
1187  if (!scalar(@split_letters))
1188  {
1189    return $current_page->{'text'};
1190  }
1191
1192  while (1)
1193  {
1194    # print the index letters
1195    push @{$Texi2HTML::THIS_SECTION}, $current_page->{'text'};
1196
1197    $current_page = shift @split_letters;
1198    last if (!defined($current_page));
1199
1200    # end the previous element
1201    main::finish_element ($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, $Texi2HTML::THIS_ELEMENT->{'Forward'}, 0);
1202
1203    # do the new element beginning
1204    $Texi2HTML::THIS_ELEMENT = $current_page->{'element'};
1205    main::do_element_directions($Texi2HTML::THIS_ELEMENT);
1206    main::open_out_file($current_page->{'element'}->{'file'});
1207    &$print_page_head($Texi2HTML::THISDOC{'FH'});
1208    &$print_chapter_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if $Texi2HTML::Config::SPLIT eq 'chapter';
1209    &$print_section_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if $Texi2HTML::Config::SPLIT eq 'section';
1210
1211    @{$Texi2HTML::THIS_SECTION} =  &$element_label($Texi2HTML::THIS_ELEMENT->{'id'}, $Texi2HTML::THIS_ELEMENT, undef, undef);
1212    push @{$Texi2HTML::THIS_SECTION}, &$print_element_header(1, 0);
1213    push @{$Texi2HTML::THIS_SECTION}, &$heading($Texi2HTML::THIS_ELEMENT);
1214  }
1215  return '';
1216}
1217# leave this within comments, and keep the require statement
1218# This way, you can directly run texi2html.pl, if
1219# $T2H_HOME/texi2html.init exists.
1220
1221# @INIT@
1222# -*-perl-*-
1223######################################################################
1224# File: texi2html.init
1225#
1226# Default values for command-line arguments and for various customizable
1227# procedures are set in this file.
1228#
1229# A copy of this file is pasted into the beginning of texi2html by
1230# running './configure'.
1231#
1232# Copy this file, rename it and make changes to it, if you like.
1233# Afterwards, load the file with command-line
1234# option -init-file <your_init_file>
1235#
1236# $Id: texi2html.init,v 1.173 2009/01/01 22:35:10 pertusus Exp $
1237
1238######################################################################
1239# The following variables can also be set by command-line options
1240#
1241#
1242# The default values are set in this file, texi2html.init and the content
1243# of this file is included at the beginning of the texi2html script file.
1244# Those values may be overrided by values set in $sysconfdir/texi2htmlrc
1245# and then by values set in $HOME/texi2htmlrc.
1246#
1247# command line switches may override these values, and values set in files
1248# specified by -init-file are also taken into account.
1249# values set in these files overwrite values set by the command-line
1250# options appearing before -init-file and might still be overwritten by
1251# command-line arguments following the -init-file option.
1252
1253# -debug
1254# The integer value specifies what kind of debugging output is generated.
1255$DEBUG = 0;
1256
1257# -doctype
1258# The value is the 'SystemLiteral' which identifies the canonical DTD
1259# for the document.
1260# Definition: The SystemLiteral is called the entity's system
1261# identifier. It is a URI, which may be used to retrieve the entity.
1262# See http://www.xml.com/axml/target.html#NT-ExternalID
1263$DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd">';
1264
1265# -frameset-doctype
1266# When frames are used, this SystemLiteral identifies the DTD used for
1267# the file containing the frame description.
1268$FRAMESET_DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html401/frameset.dtd">';
1269
1270# -test
1271# If this value is true, some variables which should be dynamically generated
1272# (the date, the user running texi2html, the version of texi2html) are set to
1273# fix and given values. This is usefull in case the resulting manual is
1274# compared with a reference. For example this is used in the tests of test.sh.
1275$TEST = 0;
1276
1277# -dump-texi
1278# This value is usefull for debugging purposes. The result of the first pass is
1279# put in <document name>.passtexi, the result of the second pass is put in
1280# <document name>.passfirst.
1281$DUMP_TEXI = 0;
1282
1283# -expand
1284# the @EXPAND array contains the expanded section names.
1285@EXPAND = ('html');
1286
1287# -invisible
1288# This seems obsolete and is not used anywhere.
1289# This was a workaround for a known bug of many WWW browsers, including
1290# netscape. This was used to create invisible destination in anchors.
1291$INVISIBLE_MARK = '';
1292# $INVISIBLE_MARK = '&#160;';
1293
1294# -iso
1295# if this value is true, ISO8859 characters are used for special symbols
1296# (like copyright, etc).
1297$USE_ISO = 1;
1298
1299# -I
1300# add a directory to the list of directories where @include files are
1301# searched for (besides the directory of the file). additional '-I'
1302# args are appended to this list.
1303# (APA: Don't implicitely search ., to conform with the docs!)
1304# my @INCLUDE_DIRS = (".");
1305@INCLUDE_DIRS = ();
1306
1307# -P
1308# prepend a directory to the list of directories where @include files are
1309# searched for before the directory of the file. additional '-P'
1310# args are prepended to this list.
1311@PREPEND_DIRS = ();
1312
1313# --conf-dir
1314# append to the files searched for init files.
1315@CONF_DIRS = ();
1316
1317# -top-file
1318# This file name is used for the top-level file.
1319# The extension is set appropriately, if necessary.
1320# If empty, <basename of document>.html is used.
1321# Typically, you would set this to "index.html".
1322$TOP_FILE = '';
1323
1324# -toc-file
1325# This file name is used for the table of contents.  The
1326# extension is set appropriately, if necessary.
1327# If empty, <basename of document>_toc.html is used.
1328$TOC_FILE = '';
1329
1330# -frames
1331# if the value is true, HTML 4.0 "frames" are used.
1332# A file describing the frame layout is generated, together with a file
1333# with the short table of contents.
1334$FRAMES = 0;
1335
1336# -menu | -nomenu
1337# if the value is true the Texinfo menus are shown.
1338$SHOW_MENU = 1;
1339
1340# -number | -nonumber
1341# if this is set the sections are numbered, and section names and numbers
1342# are used in references and menus (instead of node names).
1343$NUMBER_SECTIONS = 1;
1344
1345# -use-nodes
1346# if this is set the nodes are used as sectionning elements.
1347# Otherwise the nodes are incorporated in sections.
1348#$USE_NODES = 0;
1349$USE_NODES = undef;
1350
1351$USE_SECTIONS = 1;
1352
1353# -node-files
1354# if this is set one file per node is generated, which can be a target for
1355# cross manual references.
1356$NODE_FILES = 0;
1357
1358# -split section|chapter|node|none
1359# if $SPLIT is set to 'section' (resp. 'chapter') one html file per section
1360# (resp. chapter) is generated. If $SPLIT is set to 'node' one html file per
1361# node or sectionning element is generated. In all these cases separate pages
1362# for Top, Table of content (Toc), Overview and About are generated.
1363# Otherwise a monolithic html file that contains the whole document is
1364# created.
1365#$SPLIT = 'section';
1366$SPLIT = '';
1367
1368# -sec-nav|-nosec-nav
1369# if this is set then navigation panels are printed at the beginning of each
1370# section.
1371# If the document is split at nodes then navigation panels are
1372# printed at the end if there were more than $WORDS_IN_PAGE words on page.
1373#
1374# Navigation panels are always printed at the beginning of output files.
1375#
1376# This is most useful if you do not want to have section navigation
1377# with -split chapter. There will be chapter navigation panel at the
1378# beginning and at the end of chapters anyway.
1379$SECTION_NAVIGATION = 1;
1380
1381# -separated-footnotes
1382# if this is set footnotes are on a separated page. Otherwise they are at
1383# the end of each file (if the document is split).
1384$SEPARATED_FOOTNOTES = 1;
1385
1386# -toc-links
1387# if this is set, links from headings to toc entries are created.
1388$TOC_LINKS = 0;
1389
1390# -subdir
1391# If this is set, then put result files into the specified directory.
1392# If not set, then result files are put into the current directory.
1393#$SUBDIR = 'html';
1394$SUBDIR = '';
1395
1396# -short-extn
1397# If this is set, then all HTML files will have extension ".htm" instead of
1398# ".html". This is helpful when shipping the document to DOS-based systems.
1399$SHORTEXTN = 0;
1400
1401# -prefix
1402# This set the output file prefix, prepended to all .html, .gif and .pl files.
1403# By default, this is the basename of the document.
1404$PREFIX = '';
1405
1406# -o filename
1407# If this is set a monolithic document is outputted into $filename.
1408$OUT = '';
1409
1410# -no-validate
1411# suppress node cross-reference validation
1412$NOVALIDATE = 0;
1413
1414# -short-ref
1415# if this is set cross-references are given without section numbers.
1416$SHORT_REF = '';
1417
1418# -idx-sum
1419# if value is set, then for each @printindex <index name>
1420# <document name>_<index name>.idx is created which contains lines of the form
1421# key ref sorted alphabetically (case matters).
1422$IDX_SUMMARY = 0;
1423
1424# -def-table
1425# If this is set a table construction for @def.... instead of definition
1426# lists.
1427# (New Option: 27.07.2000 Karl Heinz Marbaise)
1428$DEF_TABLE = 0;
1429
1430# -verbose
1431# if this is set chatter about what we are doing.
1432$VERBOSE = '';
1433
1434# -lang
1435# use &$I('my string') if you want to have translations of 'my string'
1436# and provide the translations in $LANGUAGES->{$LANG} with 'my string'
1437# as key.
1438# To add a new language use ISO 639 language codes (see e.g. perl module
1439# Locale-Codes-1.02 for  definitions). Supply translations in the
1440# $LANGUAGES hash and put it in a file with $LANG as name in an i18n
1441# directory.
1442# This is used for the initial language, it is overriden during
1443# document processing if there is a @documentlanguage.
1444# It is ignored if the language is passed on the command line.
1445$LANG = 'en';
1446
1447# -ignore-preamble-text
1448# If this is set the text before @node and sectionning commands is ignored.
1449$IGNORE_PREAMBLE_TEXT = 0;
1450
1451# -html-xref-prefix
1452# base directory for external manuals.
1453#$EXTERNAL_DIR = '../';
1454$EXTERNAL_DIR = undef;
1455
1456# -l2h
1457# if this is set, latex2html is used for generation of math content.
1458$L2H = '';
1459
1460# -transliterate-file-names
1461# transliterate node names for external refs (and internal if NODE_FILES)
1462$TRANSLITERATE_NODE = 1;
1463
1464# --error-limit
1465# quit after NUM errors (default 1000).
1466$ERROR_LIMIT = 1000;
1467
1468# -monolithic
1469# output only one file including ToC. It only makes sense when not split
1470$MONOLITHIC = 1;
1471
1472# -css-include
1473# All the specified css files are used. More precisely the @import sections
1474# are added to the beginning of the CSS_LINES the remaining is added at
1475# the end of the CSS_LINES (after the css rules generated by texi2html).
1476# cf texinfo manual for more info.
1477# - means STDIN
1478@CSS_FILES = ();
1479
1480# -css-ref
1481# the specified url are used as stylesheet links
1482@CSS_REFS = ();
1483
1484######################
1485# The following options are only relevant if $L2H is set
1486#
1487# -l2h-l2h
1488# name/location of latex2html program
1489$L2H_L2H = "latex2html";
1490
1491# -l2h-skip
1492# If this is set the actual call to latex2html is skipped. The previously
1493# generated content is reused, instead.
1494$L2H_SKIP = '';
1495
1496# -l2h-tmp
1497# If this is set l2h uses the specified directory for temporary files. The path
1498# leading to this directory may not contain a dot (i.e., a ".");
1499# otherwise, l2h will fail.
1500$L2H_TMP = '';
1501
1502# -l2h-file
1503# If set, l2h uses the file as latex2html init file
1504$L2H_FILE = 'l2h.init';
1505
1506# -l2h-clean
1507# if this is set the intermediate files generated by texi2html in relation with
1508# latex2html are cleaned (they all have the prefix <document name>_l2h_).
1509$L2H_CLEAN = 1;
1510
1511##############################################################################
1512#
1513# The following can only be set in the init file
1514#
1515##############################################################################
1516
1517# If true do table of contents even if there is no @content
1518$DO_CONTENTS = undef;
1519
1520# If true do short table of contents even if there is no @shortcontent
1521$DO_SCONTENTS = undef;
1522
1523# if set, output the contents where the command is located
1524$INLINE_CONTENTS = 0;
1525
1526# if this variable is true, numeric entities are used when there is no
1527# corresponding textual entity.
1528$USE_NUMERIC_ENTITY = 1;
1529
1530# if set, the image files are completed to be relative from the
1531# document directory, to the source manual directory and then to
1532# the image
1533$COMPLETE_IMAGE_PATHS = 0;
1534
1535# if this variable is true, @setfilename is used if found to determine the
1536# out file name
1537$USE_SETFILENAME = 0;
1538
1539# if true, begin outputting at @setfilename, if this command is present.
1540$IGNORE_BEFORE_SETFILENAME = 1;
1541
1542# if true the link in Overview link to the corresponding Toc entry.
1543$OVERVIEW_LINK_TO_TOC = 0;
1544
1545# if set always separate description and menu link, even in
1546# preformatted environment
1547$SEPARATE_DESCRIPTION = 0;
1548
1549# if set, then use node names in menu entries, instead of section names
1550$NODE_NAME_IN_MENU = 0;
1551
1552# if set, use node anchors for sections targets
1553$USE_NODE_TARGET = 1;
1554
1555# new style for crossrefs
1556$NEW_CROSSREF_STYLE = 1;
1557
1558# top heading is always at the beginning of the element.
1559$TOP_HEADING_AT_BEGINNING = 1;
1560
1561# if set and menu entry equals menu description, then do not print
1562# menu description.
1563# Likewise, if node name equals entry name, do not print entry name.
1564$AVOID_MENU_REDUNDANCY = 1;
1565
1566# if set, center @image by default
1567# otherwise, do not center by default
1568# Deprecated and not used anymore
1569$CENTER_IMAGE = 1;
1570
1571# used as identation for block enclosing command @example, etc
1572# If not empty, must be enclosed in <td></td>
1573$EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
1574
1575# same as above, only for @small
1576$SMALL_EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
1577
1578# font size for @small
1579$SMALL_FONT_SIZE = '-1';
1580
1581# horizontal rules
1582$SMALL_RULE = '<hr size="1">';
1583$DEFAULT_RULE = '<hr>';
1584$MIDDLE_RULE = '<hr size="2">';
1585$BIG_RULE = '<hr size="6">';
1586
1587# if non-empty, and no @..heading appeared in Top node, then
1588# use this as header for top node/section, otherwise use value of
1589# @settitle or @shorttitle (in that order)
1590$TOP_HEADING = '';
1591
1592# if set, use this chapter for 'Index' button, else
1593# use first chapter with @printindex
1594$INDEX_CHAPTER = '';
1595
1596# if set and $SPLIT is set, then split index pages at the next letter
1597# after they have more than that many entries
1598$SPLIT_INDEX = 100;
1599
1600# symbol put at the beginning of nodes entry in menu (and optionnaly of
1601# unnumbered in menus, see next variable)
1602$MENU_SYMBOL = '&bull;';
1603#$MENU_SYMBOL = '*';
1604
1605$SIMPLE_MENU = 0;
1606
1607$OPEN_QUOTE_SYMBOL = "\`";
1608$CLOSE_QUOTE_SYMBOL = "'";
1609
1610# if true put a $MENU_SYMBOL before unnumbered in menus
1611$UNNUMBERED_SYMBOL_IN_MENU = 0;
1612
1613# extension for nodes files when NODE_FILES is true
1614$NODE_FILE_EXTENSION = 'html';
1615
1616# extension
1617$EXTENSION = 'html';
1618
1619# file name used for Top node when NODE_FILES is true
1620$TOP_NODE_FILE = 'index';
1621
1622# node name used for Top node when automatic node directions are used
1623$TOP_NODE_UP = '(dir)';
1624
1625# this controls the pre style for menus
1626$MENU_PRE_STYLE = 'font-family: serif';
1627
1628# on bug-texinfo is has been said the the style is not code_style
1629# for menus (except for the node name).
1630# this controls the menu preformatted format
1631# FIXME this is not dynamic, so change in MENU_PRE_STYLE is not taken
1632# into account.
1633$MENU_PRE_COMPLEX_FORMAT = {
1634              'pre_style' => $MENU_PRE_STYLE,
1635              'class' => 'menu-preformatted',
1636#              'style' => 'code'
1637   };
1638
1639# This controls the ul style for toc
1640$NO_BULLET_LIST_STYLE = 'list-style: none';
1641$NO_BULLET_LIST_ATTRIBUTE = ' class="toc"';
1642
1643# These lines are inserted before and after the shortcontents
1644$BEFORE_OVERVIEW = "<div class=\"shortcontents\">\n";
1645$AFTER_OVERVIEW = "</div>\n";
1646
1647# These lines are inserted before and after the contents
1648$BEFORE_TOC_LINES = "<div class=\"contents\">\n";
1649$AFTER_TOC_LINES = "</div>\n";
1650
1651# if set (e.g., to index.html) replace hrefs to this file
1652# (i.e., to index.html) by ./
1653# Obsolete. Worked around a bug that is fixed now.
1654$HREF_DIR_INSTEAD_FILE = '';
1655
1656# text inserted after <body ...>
1657$AFTER_BODY_OPEN = '';
1658
1659# text inserted before </body>, this will be automatically inside <p></p>
1660$PRE_BODY_CLOSE = '';
1661
1662# this is added inside <head></head> after <title> and some <meta name>
1663# stuff, it can be used for eg. <style>, <script>, <meta> etc. tags.
1664$EXTRA_HEAD = '';
1665
1666# Specifies the minimum page length required before a navigation panel
1667# is placed at the bottom of a page
1668# FIXME this is not true:
1669# THIS_WORDS_IN_PAGE holds number of words of current page
1670$WORDS_IN_PAGE = 300;
1671
1672# if this is set a vertical navigation panel is used.
1673$VERTICAL_HEAD_NAVIGATION = 0;
1674
1675# html version for latex2html
1676$L2H_HTML_VERSION = "4.0";
1677
1678# use the information given by menus to complete the node directions
1679$USE_MENU_DIRECTIONS = 1;
1680
1681# try up sections to complete the node directions
1682$USE_UP_FOR_ADJACENT_NODES = 1;
1683
1684# use accesskey in hrefs
1685$USE_ACCESSKEY = 0;
1686
1687# use rel= and rev= in hrefs. Currently only rel is used
1688$USE_REL_REV = 0;
1689
1690# generate <link> elements in head
1691$USE_LINKS = 0;
1692
1693# specify in this array which "buttons" should appear in which order
1694# in the navigation panel for sections; use ' ' for empty buttons (space)
1695@SECTION_BUTTONS =
1696    (
1697     'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1698     ' ', ' ', ' ', ' ',
1699     'Top', 'Contents', 'Index', 'About',
1700    );
1701
1702# buttons for misc stuff
1703@MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About');
1704
1705# buttons for chapter file footers
1706# (and headers but only if SECTION_NAVIGATION is false)
1707@CHAPTER_BUTTONS =
1708    (
1709     'FastBack', 'FastForward', ' ',
1710     ' ', ' ', ' ', ' ',
1711     'Top', 'Contents', 'Index', 'About',
1712    );
1713
1714# buttons for section file footers
1715@SECTION_FOOTER_BUTTONS =
1716    (
1717     'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1718    );
1719
1720@NODE_FOOTER_BUTTONS =
1721    (
1722     'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1723     ' ', ' ', ' ', ' ',
1724     'Top', 'Contents', 'Index', 'About',
1725#     'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1726    );
1727
1728@LINKS_BUTTONS =
1729    (
1730      'Top', 'Index', 'Contents', 'About', 'Up', 'NextFile', 'PrevFile'
1731    );
1732
1733$ICONS = 0;
1734
1735# insert here name of icon images for buttons
1736# Icons are used, if $ICONS and resp. value are set
1737%ACTIVE_ICONS =
1738    (
1739     'Top',         '',
1740     'Contents',    '',
1741     'Overview',    '',
1742     'Index',       '',
1743     'This',        '',
1744     'Back',        '',
1745     'FastBack',    '',
1746     'Prev',        '',
1747     'Up',          '',
1748     'Next',        '',
1749     'NodeUp',      '',
1750     'NodeNext',    '',
1751     'NodePrev',    '',
1752     'Following',   '',
1753     'Forward',     '',
1754     'FastForward', '',
1755     'About' ,      '',
1756     'First',       '',
1757     'Last',        '',
1758     'NextFile',    '',
1759     'PrevFile',    '',
1760     ' ',           '',
1761    );
1762
1763# insert here name of icon images for these, if button is inactive
1764%PASSIVE_ICONS =
1765    (
1766     'Top',         '',
1767     'Contents',    '',
1768     'Overview',    '',
1769     'Index',       '',
1770     'This',        '',
1771     'Back',        '',
1772     'FastBack',    '',
1773     'Prev',        '',
1774     'Up',          '',
1775     'Next',        '',
1776     'NodeUp',      '',
1777     'NodeNext',    '',
1778     'NodePrev',    '',
1779     'Following',   '',
1780     'Forward',     '',
1781     'FastForward', '',
1782     'About',       '',
1783     'First',       '',
1784     'Last',        '',
1785     'NextFile',    '',
1786     'PrevFile',    '',
1787    );
1788
1789@IMAGE_EXTENSIONS = ('png','jpg','jpeg','gif');
1790#, 'txt');
1791
1792
1793%misc_pages_targets = (
1794   'Overview' => 'SEC_Overview',
1795   'Contents' => 'SEC_Contents',
1796   'Footnotes' => 'SEC_Foot',
1797   'About' => 'SEC_About'
1798);
1799
1800$init_out    = \&t2h_default_init_out;
1801$finish_out    = \&t2h_default_finish_out;
1802
1803$translate_names = \&t2h_default_translate_names;
1804
1805sub t2h_default_translate_names()
1806{
1807# Names of text as alternative for icons
1808# FIXME maybe get those in simple_format?
1809    %NAVIGATION_TEXT =
1810    (
1811     'Top',         &$I('Top'),
1812     'Contents',    &$I('Contents'),
1813     'Overview',    &$I('Overview'),
1814     'Index',       &$I('Index'),
1815     ' ',           ' &nbsp; ',
1816     'This',        &$I('current'),
1817     'Back',        ' &lt; ',
1818     'FastBack',    ' &lt;&lt; ',
1819     'Prev',        &$I('Prev'),
1820     'Up',          &$I(' Up '),
1821     'Next',        &$I('Next'),
1822     'NodeUp',      &$I('Node up'),
1823     'NodeNext',    &$I('Next node'),
1824     'NodePrev',    &$I('Previous node'),
1825     'Following',   &$I('Following node'),
1826     'Forward',     ' &gt; ',
1827     'FastForward', ' &gt;&gt; ',
1828     'About',       ' ? ',
1829     'First',       ' |&lt; ',
1830     'Last',        ' &gt;| ',
1831     'NextFile',    &$I('Next file'),
1832     'PrevFile',    &$I('Previous file'),
1833    );
1834
1835    %BUTTONS_GOTO =
1836    (
1837     'Top',         &$I('Cover (top) of document'),
1838     'Contents',    &$I('Table of contents'),
1839     'Overview',    &$I('Short table of contents'),
1840     'Index',       &$I('Index'),
1841     'This',        &$I('Current section'),
1842     'Back',        &$I('Previous section in reading order'),
1843     'FastBack',    &$I('Beginning of this chapter or previous chapter'),
1844     'Prev',        &$I('Previous section on same level'),
1845     'Up',          &$I('Up section'),
1846     'Next',        &$I('Next section on same level'),
1847     'NodeUp',      &$I('Up node'),
1848     'NodeNext',    &$I('Next node'),
1849     'NodePrev',    &$I('Previous node'),
1850     'Following',   &$I('Node following in node reading order'),
1851     'Forward',     &$I('Next section in reading order'),
1852     'FastForward', &$I('Next chapter'),
1853     'About' ,      &$I('About (help)'),
1854     'First',       &$I('First section in reading order'),
1855     'Last',        &$I('Last section in reading order'),
1856     'NextFile',    &$I('Forward section in next file'),
1857     'PrevFile',    &$I('Back section in previous file'),
1858    );
1859
1860    %BUTTONS_NAME =
1861    (
1862     'Top',         &$I('Top'),
1863     'Contents',    &$I('Contents'),
1864     'Overview',    &$I('Overview'),
1865     'Index',       &$I('Index'),
1866     ' ',           ' ',
1867     'This',        &$I('This'),
1868     'Back',        &$I('Back'),
1869     'FastBack',    &$I('FastBack'),
1870     'Prev',        &$I('Prev'),
1871     'Up',          &$I('Up'),
1872     'Next',        &$I('Next'),
1873     'NodeUp',      &$I('NodeUp'),
1874     'NodeNext',    &$I('NodeNext'),
1875     'NodePrev',    &$I('NodePrev'),
1876     'Following',   &$I('Following'),
1877     'Forward',     &$I('Forward'),
1878     'FastForward', &$I('FastForward'),
1879     'About',       &$I('About'),
1880     'First',       &$I('First'),
1881     'Last',        &$I('Last'),
1882     'NextFile',    &$I('NextFile'),
1883     'PrevFile',    &$I('PrevFile'),
1884    );
1885
1886    %BUTTONS_ACCESSKEY =
1887    (
1888     'Top',         '',
1889     'Contents',    '',
1890     'Overview',    '',
1891     'Index',       '',
1892     'This',        '',
1893     'Back',        'p',
1894     'FastBack',    '',
1895     'Prev',        'p',
1896     'Up',          'u',
1897     'Next',        'n',
1898     'NodeUp',      'u',
1899     'NodeNext',    'n',
1900     'NodePrev',    'p',
1901     'Following',   '',
1902     'Forward',     'n',
1903     'FastForward', '',
1904     'About' ,      '',
1905     'First',       '',
1906     'Last',        '',
1907     'NextFile',    '',
1908     'PrevFile',    '',
1909    );
1910
1911# see http://www.w3.org/TR/REC-html40/types.html#type-links
1912    %BUTTONS_REL =
1913    (
1914     'Top',         'start',
1915     'Contents',    'contents',
1916     'Overview',    '',
1917     'Index',       'index',
1918     'This',        '',
1919     'Back',        'previous',
1920     'FastBack',    '',
1921     'Prev',        'previous',
1922     'Up',          'up',
1923     'Next',        'next',
1924     'NodeUp',      'up',
1925     'NodeNext',    'next',
1926     'NodePrev',    'previous',
1927     'Following',   '',
1928     'Forward',     'next',
1929     'FastForward', '',
1930     'About' ,      'help',
1931     'First',       '',
1932     'Last',        '',
1933     'NextFile',    'next',
1934     'PrevFile',    'previous',
1935    );
1936
1937}
1938
1939# is used in main program for dumping texi too.
1940sub t2h_default_set_out_encoding()
1941{
1942    # these variables are used for the corresponding
1943    # $Texi2HTML::THISDOC{'*_ENCODING'} to keep code shorter
1944    my ($out_encoding, $encoding_name, $document_encoding);
1945
1946    if (defined($DOCUMENT_ENCODING))
1947    {
1948        $document_encoding = $DOCUMENT_ENCODING;
1949    }
1950    elsif (defined($Texi2HTML::THISDOC{'documentencoding'}))
1951    {
1952        $document_encoding = $Texi2HTML::THISDOC{'documentencoding'};
1953    }
1954
1955    if (defined($OUT_ENCODING))
1956    {
1957        $out_encoding = $OUT_ENCODING;
1958    }
1959
1960    if (defined($ENCODING_NAME))
1961    {
1962        $encoding_name = $ENCODING_NAME;
1963    }
1964
1965    if (!defined($out_encoding) and (defined($encoding_name)))
1966    {
1967        $out_encoding = main::encoding_alias ($encoding_name);
1968        $out_encoding = $encoding_name if (!defined($out_encoding));
1969    }
1970    if (!defined($out_encoding) and (defined($Texi2HTML::THISDOC{'IN_ENCODING'})))
1971    {
1972        $out_encoding = $Texi2HTML::THISDOC{'IN_ENCODING'};
1973    }
1974    if (!defined($out_encoding) and (defined($document_encoding)))
1975    {
1976        $out_encoding = main::encoding_alias ($document_encoding);
1977        $out_encoding = $document_encoding if (!defined($out_encoding));
1978    }
1979
1980    if (!defined($encoding_name))
1981    {
1982         if (defined($out_encoding) and defined($perl_charset_to_html{$out_encoding}))
1983         {
1984             $encoding_name = $perl_charset_to_html{$out_encoding};
1985         }
1986         elsif (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and defined($perl_charset_to_html{$Texi2HTML::THISDOC{'IN_ENCODING'}}))
1987         {
1988             $encoding_name = $perl_charset_to_html{$Texi2HTML::THISDOC{'IN_ENCODING'}};
1989         }
1990         elsif (defined($document_encoding) and defined($perl_charset_to_html{$document_encoding}))
1991         {
1992             $encoding_name = $perl_charset_to_html{$document_encoding};
1993         }
1994         elsif (defined($out_encoding))
1995         {
1996             $encoding_name = $out_encoding;
1997         }
1998         elsif (defined($Texi2HTML::THISDOC{'IN_ENCODING'}))
1999         {
2000             $encoding_name = $Texi2HTML::THISDOC{'IN_ENCODING'};
2001         }
2002         elsif (defined($document_encoding))
2003         {
2004             $encoding_name = $document_encoding;
2005         }
2006         elsif (defined($perl_charset_to_html{$DEFAULT_ENCODING}))
2007         {
2008             $encoding_name = $perl_charset_to_html{$DEFAULT_ENCODING};
2009         }
2010         else
2011         {
2012             $encoding_name = 'us-ascii';
2013         }
2014    }
2015
2016    $Texi2HTML::THISDOC{'OUT_ENCODING'} = $out_encoding;
2017    $Texi2HTML::THISDOC{'ENCODING_NAME'} = $encoding_name;
2018    $Texi2HTML::THISDOC{'DOCUMENT_ENCODING'} = $document_encoding;
2019
2020    $out_encoding = 'UNDEF' if (!defined($out_encoding));
2021    my $in_encoding = $Texi2HTML::THISDOC{'IN_ENCODING'};
2022    $in_encoding = 'UNDEF' if (!defined($in_encoding));
2023    $document_encoding = 'UNDEF' if (!defined($document_encoding));
2024    print STDERR "# Encodings: doc $document_encoding, in $in_encoding out $out_encoding, name $encoding_name\n" if ($VERBOSE);
2025}
2026
2027my  @t2h_default_multitable_stack;
2028# We have to do this dynamically because of internationalization and because
2029# in body $LANG could be used.
2030sub t2h_default_init_out()
2031{
2032    @t2h_default_multitable_stack = ();
2033    &$translate_names;
2034    # Set the default body text, inserted between <body ... >
2035    if (defined($BODYTEXT))
2036    {
2037        $Texi2HTML::THISDOC{'BODYTEXT'} = $BODYTEXT;
2038    }
2039    else
2040    {
2041        $Texi2HTML::THISDOC{'BODYTEXT'} = 'lang="' . $Texi2HTML::THISDOC{'current_lang'} . '" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"';
2042    }
2043    if (!defined($EXTERNAL_CROSSREF_SPLIT))
2044    {
2045        if ($SPLIT)
2046        {
2047            $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = 1;
2048        }
2049        else
2050        {
2051            $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = 0;
2052        }
2053    }
2054    else
2055    {
2056        $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = $EXTERNAL_CROSSREF_SPLIT;
2057    }
2058
2059    t2h_default_set_out_encoding();
2060
2061    # not in code_style, according to post on bug-texinfo
2062    if ($SIMPLE_MENU)
2063    {
2064        foreach my $format ('menu', 'detailmenu')
2065        {
2066            if (!defined($complex_format_map->{$format}))
2067            {
2068                $complex_format_map->{$format} = { 'begin' => q{''} , 'end' => q{''},
2069                 'pre_style' => "$MENU_PRE_STYLE", 'class' => 'menu-preformatted',
2070#                 'style' => 'code'
2071                };
2072            }
2073        }
2074        #$SEPARATE_DESCRIPTION = 1;
2075        #$format_map{'menu_comment'} = '' if (!defined($format_map{'menu_comment'}));
2076    }
2077    elsif (!defined($format_map{'menu_comment'}) and !defined($complex_format_map->{'menu_comment'}))
2078    {
2079        $complex_format_map->{'menu_comment'} =
2080        {
2081           'begin' => q{"<tr><th colspan=\"3\" align=\"left\" valign=\"top\">"},
2082           'end' => q{"</th></tr>"}, 'pre_style' => "$MENU_PRE_STYLE", 'class' => 'menu-comment',
2083#            'style' => 'code'
2084        }
2085    }
2086    # obsolete
2087    #return $OUT_ENCODING;
2088};
2089
2090sub t2h_default_finish_out()
2091{
2092}
2093
2094#######################################################################
2095#
2096# Values guessed if not set here. The value used is in
2097# $Texi2HTML::THISDOC{'VARNAME'}
2098#
2099#######################################################################
2100
2101$BODYTEXT = undef;
2102
2103# default used in init_out for the setting of the ENCODING_NAME variable
2104$DEFAULT_ENCODING = 'utf8';
2105
2106# In file encoding. The @documentencoding allows autodetection of
2107# that variable.
2108$DOCUMENT_ENCODING = undef;
2109
2110# In file encoding, understandable by perl. Set according to DOCUMENT_ENCODING
2111$IN_ENCODING = undef;
2112
2113# Formatted document encoding name. If undef, set in init_out based on
2114# $OUT_ENCODING or $DOCUMENT_ENCODING if they are defined
2115$ENCODING_NAME = undef;
2116
2117# Out files encoding, understandable by perl. If undef, set in init_out
2118# using $ENCODING_NAME or $IN_ENCODING if they are defined
2119$OUT_ENCODING = undef;
2120
2121# Used to set $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'}.
2122# if undef set to @documentdescription. If there is no @documentdescription,
2123# set in page_head.
2124$DOCUMENT_DESCRIPTION = undef;
2125
2126# if undef $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} set 1 if SPLIT,
2127# to 0 otherwise
2128$EXTERNAL_CROSSREF_SPLIT = undef;
2129
2130$USER = undef;
2131$DATE = undef;
2132
2133
2134########################################################################
2135# Control of Page layout:
2136# You can make changes of the Page layout at two levels:
2137# 1.) For small changes, it is often enough to change the value of
2138#     some global string/hash/array variables
2139# 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines,
2140#     give them another name, and assign them to the respective
2141#     $<fnc> variable.
2142
2143# As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, Texi2HTML::SIMPLE_TEXT hold
2144# href, html-name, node-name, name after removal of texi commands of
2145# This     -- current section (resp. html page)
2146# Top      -- top element
2147# Contents -- Table of contents element
2148# Overview -- Short table of contents element
2149# Index    -- Index page element
2150# About    -- page which explain "navigation buttons" element
2151# First    -- first node element
2152# Last     -- last node element
2153#
2154# Whether or not the following hash values are set, depends on the context
2155# (all values are w.r.t. 'This' section)
2156# Next        -- next element of texinfo
2157# Prev        -- previous element of texinfo
2158# NodeUp      -- up node of texinfo
2159# Following   -- following node in node reading order, taking menu into account
2160# Forward     -- next node in reading order
2161# Back        -- previous node in reading order
2162# Up          -- parent given by sectionning commands
2163# FastForward -- if leave node, up and next, else next node
2164# FastBackward-- if leave node, up and prev, else prev node
2165#
2166# Furthermore, the following global variabels are set:
2167# $Texi2HTML::THISDOC{title}          -- title as set by @title...
2168# $Texi2HTML::THISDOC{title_no_texi}  -- title without texi (without html elements)
2169# $Texi2HTML::THISDOC{title_texi}     -- title with texinfo @-commands
2170# $Texi2HTML::THISDOC{fulltitle}      -- full title as set by @title...
2171# $Texi2HTML::THISDOC{subtitle}       -- subtitle as set by @subtitle
2172# $Texi2HTML::THISDOC{author}         -- author as set by @author
2173# $Texi2HTML::THISDOC{copying_comment}  -- text of @copying and @end copying in comment
2174#
2175# $Texi2HTML::THISDOC{program}          -- name and version of texi2html
2176# $Texi2HTML::THISDOC{program_homepage} -- homepage for texi2html
2177# $Texi2HTML::THISDOC{program_authors}  -- authors of texi2html
2178# $Texi2HTML::THISDOC{today}            -- date formatted with pretty_date
2179# $Texi2HTML::THISDOC{toc_file}         -- table of contents file
2180# $Texi2HTML::THISDOC{file_base_name}   -- base name of the texinfo manual file
2181# $Texi2HTML::THISDOC{input_file_name}  -- name of the texinfo manual file
2182# $Texi2HTML::THISDOC{destination_directory}
2183                                 #      -- directory for the resulting files
2184# $Texi2HTML::THISDOC{user}             -- user running the script
2185# $Texi2HTML::THISDOC{css_import_lines} -- ref on @import lines in css files
2186# $Texi2HTML::THISDOC{css_lines}        -- ref on css rules lines
2187# other $Texi2HTML::THISDOC keys corresponds with texinfo commands, the value
2188# being the command arg, for the following commands:
2189# kbdinputstyle, paragraphindent, setchapternewpage, headings, footnotestyle,
2190# exampleindent, firstparagraphindent, everyheading, everyfooting,
2191# evenheading, evenfooting, oddheading, oddfooting
2192#
2193# and pointer to arrays of lines which need to be printed by main::print_lines
2194# $Texi2HTML::THIS_SECTION  -- lines of 'This' section
2195# $Texi2HTML::OVERVIEW      -- lines of short table of contents
2196# $Texi2HTML::TOC_LINES     -- lines of table of contents
2197# $Texi2HTML::TITLEPAGE     -- lines of title page
2198#
2199# $Texi2HTML::THIS_ELEMENT  holds the element reference.
2200
2201#
2202# There are the following subs which control the layout:
2203#
2204$print_section            = \&T2H_DEFAULT_print_section;
2205$end_section              = \&T2H_DEFAULT_end_section;
2206$one_section              = \&T2H_DEFAULT_one_section;
2207$print_Top_header         = \&T2H_DEFAULT_print_Top_header;
2208$print_Top_footer	      = \&T2H_DEFAULT_print_Top_footer;
2209$print_Top		      = \&T2H_DEFAULT_print_Top;
2210$print_Toc		      = \&T2H_DEFAULT_print_Toc;
2211$print_Overview	      = \&T2H_DEFAULT_print_Overview;
2212$print_Footnotes	      = \&T2H_DEFAULT_print_Footnotes;
2213$print_About	      = \&T2H_DEFAULT_print_About;
2214$print_misc_header	      = \&T2H_DEFAULT_print_misc_header;
2215$print_misc_footer	      = \&T2H_DEFAULT_print_misc_footer;
2216$print_misc		      = \&T2H_DEFAULT_print_misc;
2217$print_section_footer     = \&T2H_DEFAULT_print_section_footer;
2218$print_chapter_header     = \&T2H_DEFAULT_print_chapter_header;
2219$print_section_header     = \&T2H_DEFAULT_print_section_header;
2220$print_element_header     = \&T2H_DEFAULT_print_element_header;
2221$print_chapter_footer     = \&T2H_DEFAULT_print_chapter_footer;
2222$print_page_head	      = \&T2H_DEFAULT_print_page_head;
2223$print_page_foot	      = \&T2H_DEFAULT_print_page_foot;
2224$print_head_navigation    = \&T2H_DEFAULT_print_head_navigation;
2225$print_foot_navigation    = \&T2H_DEFAULT_print_foot_navigation;
2226$button_icon_img	      = \&T2H_DEFAULT_button_icon_img;
2227$print_navigation	      = \&T2H_DEFAULT_print_navigation;
2228$about_body		      = \&T2H_DEFAULT_about_body;
2229$print_frame              = \&T2H_DEFAULT_print_frame;
2230$print_toc_frame          = \&T2H_DEFAULT_print_toc_frame;
2231#$toc_body                 = \&T2H_DEFAULT_toc_body;
2232$titlepage                 = \&T2H_DEFAULT_titlepage;
2233$css_lines                 = \&T2H_DEFAULT_css_lines;
2234$print_redirection_page    = \&T2H_DEFAULT_print_redirection_page;
2235$node_file_name            = \&T2H_DEFAULT_node_file_name;
2236$inline_contents           = \&T2H_DEFAULT_inline_contents;
2237$program_string            = \&T2H_DEFAULT_program_string;
2238
2239########################################################################
2240# Layout for html for every sections
2241#
2242
2243sub T2H_DEFAULT_print_element_header
2244{
2245    my $first_in_page = shift;
2246    my $previous_is_top = shift;
2247    my $buttons = \@SECTION_BUTTONS;
2248
2249    if (($first_in_page or $previous_is_top) and $SECTION_NAVIGATION)
2250    {
2251        return &$print_head_navigation(undef, $buttons);
2252    }
2253    else
2254    { # got to do this here, as it isn't done in print_head_navigation
2255        return &$print_navigation($buttons) if ($SECTION_NAVIGATION or $SPLIT eq 'node');
2256    }
2257}
2258
2259sub T2H_DEFAULT_print_section
2260{
2261    my $fh = shift;
2262    my $first_in_page = shift;
2263    my $previous_is_top = shift;
2264    my $element = shift;
2265    my $buttons = \@SECTION_BUTTONS;
2266
2267    my $nw = main::print_lines($fh);
2268    if (defined $SPLIT
2269        and (($SPLIT eq 'node') && $SECTION_NAVIGATION))
2270    {
2271        my $buttons = \@NODE_FOOTER_BUTTONS;
2272        &$print_foot_navigation($fh, $buttons, $SMALL_RULE,
2273          (!defined($WORDS_IN_PAGE) or (defined ($nw) and $nw >= $WORDS_IN_PAGE)),
2274          $element);
2275#        print $fh "$SMALL_RULE\n";
2276#        &$print_navigation($buttons) if (!defined($WORDS_IN_PAGE) or (defined ($nw)
2277#                                    and $nw >= $WORDS_IN_PAGE));
2278    }
2279}
2280
2281sub T2H_DEFAULT_one_section($$)
2282{
2283    my $fh = shift;
2284    my $element = shift;
2285    main::print_lines($fh);
2286    print $fh "$SMALL_RULE\n";
2287    &$print_page_foot($fh);
2288}
2289
2290###################################################################
2291# Layout of top-page I recommend that you use @ifnothtml, @ifhtml,
2292# @html within the Top texinfo node to specify content of top-level
2293# page.
2294#
2295# If you enclose everything in @ifnothtml, then title, subtitle,
2296# author and overview is printed
2297# Texi2HTML::HREF of Next, Prev, Up, Forward, Back are not defined
2298# if $T2H_SPLIT then Top page is in its own html file
2299sub T2H_DEFAULT_print_Top_header($$)
2300{
2301    my $fh = shift;
2302    my $do_page_head = shift;
2303    &$print_page_head($fh) if ($do_page_head);
2304}
2305sub T2H_DEFAULT_print_Top_footer($$$)
2306{
2307    my $fh = shift;
2308    my $end_page = shift;
2309    my $element = shift;
2310    my $buttons = \@MISC_BUTTONS;
2311    &$print_foot_navigation($fh, $buttons, $SMALL_RULE,
2312       ($end_page and ($SECTION_NAVIGATION or ($SPLIT and $SPLIT ne 'node'))), $element);
2313#    &$print_foot_navigation($fh);
2314#    print $fh "$SMALL_RULE\n";
2315    if ($end_page)
2316    {
2317#        &$print_navigation($fh, $buttons);
2318        &$print_page_foot($fh);
2319    }
2320}
2321
2322sub T2H_DEFAULT_print_Top($$$)
2323{
2324    my $fh = shift;
2325    my $has_top_heading = shift;
2326    my $element = shift;
2327
2328    # for redefining navigation buttons use:
2329    # my $buttons = [...];
2330    # as it is, 'Top', 'Contents', 'Index', 'About' are printed
2331    my $buttons = \@MISC_BUTTONS;
2332
2333    my $nw;
2334    # a dirty hack. A section is considered to be empty if there are 2
2335    # lines or less in it. Indeed, this catches the sectionning command like
2336    # @top and the @node.
2337    if (scalar(@$Texi2HTML::THIS_SECTION) > 2)
2338    {
2339        # if top-level node has content
2340        $nw = main::print_lines($fh, $Texi2HTML::THIS_SECTION);
2341    }
2342    else
2343    {
2344        # top-level node is fully enclosed in @ifnothtml
2345        # print fulltitle, subtitle, author, Overview or table of contents
2346        # redo the titlepage with the actual state
2347        my ($titlepage_text, $titlepage_no_texi, $titlepage_simple_format) = main::do_special_region_lines('titlepage',$Texi2HTML::THISDOC{'state'});
2348
2349        &$titlepage([],$titlepage_text, $titlepage_no_texi, $titlepage_simple_format);
2350        # only print the header and node label
2351        print $fh $Texi2HTML::THIS_SECTION->[0];
2352        print $fh $Texi2HTML::TITLEPAGE;
2353        if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'})
2354        {
2355             print $fh '<h2> ' . $Texi2HTML::NAME{'Overview'} . "</h2>\n" . "<blockquote\n";
2356             my $nw = main::print_lines($fh, $Texi2HTML::OVERVIEW);
2357             print $fh "</blockquote>\n";
2358        }
2359        elsif (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::THISDOC{'setcontentsaftertitlepage'})
2360        {
2361             print $fh '<h1> ' . $Texi2HTML::NAME{'Contents'}  . "</h1>\n";
2362             my $nw = main::print_lines($fh, $Texi2HTML::TOC_LINES);
2363        }
2364    }
2365}
2366
2367###################################################################
2368# Layout of Toc, Overview, and Footnotes pages
2369# By default, we use "normal" layout
2370# Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined
2371# use: my $buttons = [...] to redefine navigation buttons
2372sub T2H_DEFAULT_print_Toc
2373{
2374    return &$print_misc(@_);
2375}
2376sub T2H_DEFAULT_print_Overview
2377{
2378    return &$print_misc(@_);
2379}
2380sub T2H_DEFAULT_print_Footnotes
2381{
2382    return &$print_misc(@_);
2383}
2384sub T2H_DEFAULT_print_About
2385{
2386    # if there is no section navigation and it is not split, the
2387    # navigation information is useless
2388    return &$print_misc(@_) if ($SPLIT or $SECTION_NAVIGATION);
2389}
2390
2391sub T2H_DEFAULT_print_misc_header
2392{
2393    my $fh = shift;
2394    my $buttons = shift;
2395    my $new_file = shift;
2396    my $misc_page = shift;
2397    &$print_page_head($fh) if ($new_file);
2398    print $fh "".&$misc_element_label($misc_pages_targets{$misc_page}, $misc_page);
2399    &$print_head_navigation($fh, $buttons) if ($new_file or $SECTION_NAVIGATION);
2400}
2401
2402sub T2H_DEFAULT_print_misc_footer
2403{
2404    my $fh = shift;
2405    my $buttons = shift;
2406    my $new_file = shift;
2407    &$print_foot_navigation($fh, $buttons, $SMALL_RULE,
2408        ($new_file and ($SECTION_NAVIGATION or ($SPLIT and $SPLIT ne 'node'))), undef);
2409#    print $fh "$SMALL_RULE\n";
2410    if ($new_file)
2411    {
2412#        &$print_navigation($fh, $buttons);# if ($SPLIT ne 'node');
2413        &$print_page_foot($fh);
2414    }
2415}
2416
2417sub T2H_DEFAULT_print_misc
2418{
2419    my $fh = shift;
2420    my $new_file = shift;
2421    my $misc_page = shift;
2422    my $buttons = \@MISC_BUTTONS;
2423    &$print_misc_header($fh, $buttons, $new_file, $misc_page);
2424    print $fh "<h1>$Texi2HTML::NAME{This}</h1>\n";
2425    main::print_lines($fh);
2426    &$print_misc_footer($fh, $buttons, $new_file);
2427}
2428##################################################################
2429# section_footer is only called if SPLIT eq 'section'
2430# section_footer: after print_section of last section, before print_page_foot
2431#
2432
2433sub T2H_DEFAULT_print_section_footer
2434{
2435    my $fh = shift;
2436    my $element = shift;
2437    my $buttons = \@SECTION_FOOTER_BUTTONS;
2438    &$print_foot_navigation($fh, $buttons, $BIG_RULE, 1, $element);
2439#    &$end_section ($fh, 1, $element);
2440#    &$print_navigation($fh, $buttons);
2441}
2442
2443###################################################################
2444# chapter_header and chapter_footer are only called if
2445# SPLIT eq 'chapter'
2446# chapter_header: after print_page_head, before print_section
2447# chapter_footer: after print_section of last section, before print_page_foot
2448#
2449# If you want to get rid of navigation stuff after each section,
2450# redefine print_section such that it does not call print_navigation,
2451# and put print_navigation into print_chapter_header
2452sub T2H_DEFAULT_print_chapter_header
2453{
2454    my $fh = shift;
2455    my $element = shift;
2456    # nothing to do there, by default, the navigation panel
2457    # is the section navigation panel
2458    if (! $SECTION_NAVIGATION)
2459    { # in this case print_navigation is called here.
2460        my $buttons = \@CHAPTER_BUTTONS;
2461        &$print_head_navigation($fh, $buttons);
2462        print $fh "\n$MIDDLE_RULE\n" unless ($VERTICAL_HEAD_NAVIGATION);
2463    }
2464}
2465
2466sub T2H_DEFAULT_print_chapter_footer
2467{
2468    my $fh = shift;
2469    my $element = shift;
2470    my $buttons = \@CHAPTER_BUTTONS;
2471    &$print_foot_navigation($fh, $buttons, $BIG_RULE, 1, $element);
2472#    print $fh "$BIG_RULE\n";
2473#    &$print_navigation($fh, $buttons);
2474}
2475
2476sub T2H_DEFAULT_print_section_header
2477{
2478    # nothing to do there, by default
2479    if (! $SECTION_NAVIGATION)
2480    { # in this case print_navigation is called here.
2481        my $fh = shift;
2482        my $buttons = \@SECTION_BUTTONS;
2483        &$print_head_navigation($fh, $buttons);
2484    }
2485}
2486
2487
2488###################################################################
2489# Layout of standard header and footer
2490#
2491
2492sub T2H_DEFAULT_print_page_head($)
2493{
2494    my $fh = shift;
2495    my $longtitle = "$Texi2HTML::THISDOC{'fulltitle_simple_format'}";
2496    $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if (defined ($Texi2HTML::SIMPLE_TEXT{'This'}) and ($Texi2HTML::SIMPLE_TEXT{'This'} !~ /^\s*$/) and $SPLIT);
2497    my $description = $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'};
2498    $description = $longtitle if (!defined($description));
2499    $description = "<meta name=\"description\" content=\"$description\">" if
2500         ($description ne '');
2501    my $encoding = '';
2502    $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$Texi2HTML::THISDOC{'ENCODING_NAME'}\">" if (defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and ($Texi2HTML::THISDOC{'ENCODING_NAME'} ne ''));
2503    my $links = '';
2504    if ($USE_LINKS)
2505    {
2506        foreach my $link (@LINKS_BUTTONS)
2507        {
2508#print STDERR "$link!!$Texi2HTML::HREF{$link}\n";
2509            if (defined($Texi2HTML::HREF{$link}) and $Texi2HTML::HREF{$link} ne '')
2510            {
2511                my $title = '';
2512                $title = " title=\"$Texi2HTML::SIMPLE_TEXT{$link}\"" if (defined($Texi2HTML::SIMPLE_TEXT{$link}));
2513                my $rel = '';
2514                $rel = " rel=\"$BUTTONS_REL{$link}\"" if (defined($BUTTONS_REL{$link}));
2515                $links .= "<link href=\"$Texi2HTML::HREF{$link}\"${rel}${title}>\n";
2516            }
2517        }
2518    }
2519
2520    print $fh <<EOT;
2521$DOCTYPE
2522<html>
2523$Texi2HTML::THISDOC{'copying_comment'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program}
2524$Texi2HTML::THISDOC{program_authors}-->
2525<head>
2526<title>$longtitle</title>
2527
2528$description
2529<meta name="keywords" content="$longtitle">
2530<meta name="resource-type" content="document">
2531<meta name="distribution" content="global">
2532<meta name="Generator" content="$Texi2HTML::THISDOC{program}">
2533$encoding
2534${links}$Texi2HTML::THISDOC{'CSS_LINES'}
2535$EXTRA_HEAD
2536</head>
2537
2538<body $Texi2HTML::THISDOC{'BODYTEXT'}>
2539$AFTER_BODY_OPEN
2540EOT
2541}
2542
2543sub T2H_DEFAULT_program_string()
2544{
2545    my $user = $Texi2HTML::THISDOC{'user'};
2546    my $date = $Texi2HTML::THISDOC{'today'};
2547    $user = '' if (!defined($user));
2548    $date = '' if (!defined($date));
2549    if (($user ne '') and ($date ne ''))
2550    {
2551        return  &$I('This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.', {
2552           'user' => $user, 'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} }, {'duplicate'=>1});
2553    }
2554    elsif ($user ne '')
2555    {
2556        return  &$I('This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.', {
2557           'user' => $user, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} }, {'duplicate'=>1});
2558    }
2559    elsif ($date ne '')
2560    {
2561        return  &$I('This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.', {
2562           'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} },{'duplicate'=>1});
2563    }
2564    return &$I('This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.', {
2565       'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program'
2566=> $Texi2HTML::THISDOC{'program'} },{'duplicate'=>1});
2567}
2568
2569sub T2H_DEFAULT_end_section($$$)
2570{
2571    my $fh = shift;
2572    my $misc_and_section_separation = shift;
2573    my $element = shift;
2574    #&$print_foot_navigation($fh) if ($end_foot_navigation);
2575    #print $fh "$BIG_RULE\n";
2576    if ($misc_and_section_separation)
2577    {
2578        &$print_foot_navigation($fh, undef, $BIG_RULE, 0, $element);
2579    }
2580    else
2581    {
2582        print $fh "$BIG_RULE\n";
2583    }
2584}
2585
2586sub T2H_DEFAULT_print_page_foot($)
2587{
2588    my $fh = shift;
2589    my $program_string = &$program_string();
2590    print $fh <<EOT;
2591<p>
2592 <font size="-1">
2593  $program_string
2594 </font>
2595 <br>
2596$PRE_BODY_CLOSE
2597</p>
2598</body>
2599</html>
2600EOT
2601}
2602
2603###################################################################
2604# Layout of navigation panel
2605
2606sub T2H_DEFAULT_print_head_navigation($$)
2607{
2608    my $fh = shift;
2609    my $buttons = shift;
2610
2611    my $result = '';
2612    if ($VERTICAL_HEAD_NAVIGATION)
2613    {
2614        $result .= <<EOT;
2615<table border="0" cellpadding="0" cellspacing="0">
2616<tr valign="top">
2617<td align="left">
2618EOT
2619    }
2620    $result .= &$print_navigation($buttons, $VERTICAL_HEAD_NAVIGATION);
2621    if ($VERTICAL_HEAD_NAVIGATION)
2622    {
2623        $result .= <<EOT;
2624</td>
2625<td align="left">
2626EOT
2627    }
2628    elsif (defined $SPLIT
2629           and ($SPLIT eq 'node'))
2630    {
2631        $result .= "$SMALL_RULE\n";
2632    }
2633
2634    print $fh $result if (defined($fh));
2635    return $result;
2636}
2637
2638sub T2H_DEFAULT_print_foot_navigation
2639{
2640    my $fh = shift;
2641    my $buttons = shift;
2642    my $rule = shift;
2643    my $print_navigation_panel = shift;
2644    my $element = shift;
2645
2646    $rule = '' if (!defined($rule));
2647    $print_navigation_panel = 1 if (!defined($print_navigation_panel)
2648             and defined($buttons));
2649
2650    if ($VERTICAL_HEAD_NAVIGATION)
2651    {
2652        print $fh <<EOT;
2653</td>
2654</tr>
2655</table>
2656EOT
2657    }
2658    print $fh "$rule\n" if ($rule ne '');
2659    print $fh "".&$print_navigation($buttons) if ($print_navigation_panel);
2660}
2661
2662######################################################################
2663# navigation panel
2664#
2665# how to create IMG tag
2666sub T2H_DEFAULT_button_icon_img
2667{
2668    my $button = shift;
2669    my $icon = shift;
2670    my $name = shift;
2671    return '' if (!defined($icon));
2672    $button = "" if (!defined ($button));
2673    $name = '' if (!defined($name));
2674    my $alt = '';
2675    if ($name ne '')
2676    {
2677        if ($button ne '')
2678        {
2679            $alt = "$button: $name";
2680        }
2681        else
2682        {
2683            $alt = $name;
2684        }
2685    }
2686    else
2687    {
2688        $alt = $button;
2689    }
2690    return qq{<img src="$icon" border="0" alt="$alt" align="middle">};
2691}
2692
2693sub T2H_DEFAULT_print_navigation
2694{
2695    my $buttons = shift;
2696    my $vertical = shift;
2697
2698    my $result = '';
2699    $result .= '<table cellpadding="1" cellspacing="1" border="0">'."\n";
2700    $result .= "<tr>" unless $vertical;
2701    for my $button (@$buttons)
2702    {
2703        $result .= qq{<tr valign="top" align="left">\n} if $vertical;
2704        $result .=  qq{<td valign="middle" align="left">};
2705
2706        if (ref($button) eq 'CODE')
2707        {
2708            $result .= &$button($vertical);
2709        }
2710        elsif (ref($button) eq 'SCALAR')
2711        {
2712            $result .= "$$button" if defined($$button);
2713        }
2714        elsif (ref($button) eq 'ARRAY')
2715        {
2716            my $text = $button->[1];
2717            my $button_href = $button->[0];
2718            # verify that $button_href is simple text and text is a reference
2719            if (defined($button_href) and !ref($button_href)
2720               and defined($text) and (ref($text) eq 'SCALAR') and defined($$text))
2721            {             # use given text
2722                if ($Texi2HTML::HREF{$button_href})
2723                {
2724                  my $anchor_attributes = '';
2725                  if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button_href})) and ($BUTTONS_ACCESSKEY{$button_href} ne ''))
2726                  {
2727                      $anchor_attributes = "accesskey=\"$BUTTONS_ACCESSKEY{$button_href}\"";
2728                  }
2729                  if ($USE_REL_REV and (defined($BUTTONS_REL{$button_href})) and ($BUTTONS_REL{$button_href} ne ''))
2730                  {
2731                      $anchor_attributes .= " rel=\"$BUTTONS_REL{$button_href}\"";
2732                  }
2733                  $result .=  "" .
2734                        &$anchor('',
2735                                    $Texi2HTML::HREF{$button_href},
2736                                    $$text,
2737                                    $anchor_attributes
2738                                   )
2739                                    ;
2740                }
2741                else
2742                {
2743                  $result .=  $$text;
2744                }
2745            }
2746        }
2747        elsif ($button eq ' ')
2748        {                       # handle space button
2749            $result .=
2750                ($ICONS && $ACTIVE_ICONS{' '}) ?
2751                    &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) :
2752                        $NAVIGATION_TEXT{' '};
2753            #next;
2754        }
2755        elsif ($Texi2HTML::HREF{$button})
2756        {                       # button is active
2757            my $btitle = $BUTTONS_GOTO{$button} ?
2758                'title="' . $BUTTONS_GOTO{$button} . '"' : '';
2759            if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button})) and ($BUTTONS_ACCESSKEY{$button} ne ''))
2760            {
2761                $btitle .= " accesskey=\"$BUTTONS_ACCESSKEY{$button}\"";
2762            }
2763            if ($USE_REL_REV and (defined($BUTTONS_REL{$button})) and ($BUTTONS_REL{$button} ne ''))
2764            {
2765                $btitle .= " rel=\"$BUTTONS_REL{$button}\"";
2766            }
2767            if ($ICONS && $ACTIVE_ICONS{$button})
2768            {                   # use icon
2769                $result .= '' .
2770                    &$anchor('',
2771                        $Texi2HTML::HREF{$button},
2772                        &$button_icon_img($BUTTONS_NAME{$button},
2773                                   $ACTIVE_ICONS{$button},
2774                                   $Texi2HTML::SIMPLE_TEXT{$button}),
2775                        $btitle
2776                      );
2777            }
2778            else
2779            {                   # use text
2780                $result .=
2781                    '[' .
2782                        &$anchor('',
2783                                    $Texi2HTML::HREF{$button},
2784                                    $NAVIGATION_TEXT{$button},
2785                                    $btitle
2786                                   ) .
2787                                       ']';
2788            }
2789        }
2790        else
2791        {                       # button is passive
2792            $result .=
2793                $ICONS && $PASSIVE_ICONS{$button} ?
2794                    &$button_icon_img($BUTTONS_NAME{$button},
2795                                          $PASSIVE_ICONS{$button},
2796                                          $Texi2HTML::SIMPLE_TEXT{$button}) :
2797
2798                                              "[" . $NAVIGATION_TEXT{$button} . "]";
2799        }
2800        $result .= "</td>\n";
2801        $result .= "</tr>\n" if $vertical;
2802    }
2803    $result .= "</tr>" unless $vertical;
2804    $result .= "</table>\n";
2805    return $result;
2806}
2807
2808######################################################################
2809# Frames: this is from "Richard Y. Kim" <ryk@coho.net>
2810# Should be improved to be more conforming to other _print* functions
2811# toc_file and main_file passed as args are relative to the texinfo manual
2812# location, and therefore are not used.
2813
2814sub T2H_DEFAULT_print_frame
2815{
2816    my $fh = shift;
2817    my $toc_file = shift;
2818    my $main_file = shift;
2819    $main_file = $Texi2HTML::THISDOC{'filename'}->{'top'};
2820    $toc_file = $Texi2HTML::THISDOC{'filename'}->{'toc_frame'};
2821    print $fh <<EOT;
2822$FRAMESET_DOCTYPE
2823<html>
2824<head><title>$Texi2HTML::THISDOC{'fulltitle'}</title></head>
2825<frameset cols="140,*">
2826  <frame name="toc" src="$toc_file">
2827  <frame name="main" src="$main_file">
2828</frameset>
2829</html>
2830EOT
2831}
2832
2833sub T2H_DEFAULT_print_toc_frame
2834{
2835    my $fh = shift;
2836    my $stoc_lines = shift;
2837    &$print_page_head($fh);
2838    print $fh <<EOT;
2839<h2>Content</h2>
2840EOT
2841    print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines;
2842    print $fh "</body></html>\n";
2843}
2844
2845# This subroutine is intended to fill @Texi2HTML::TOC_LINES and
2846# @Texi2HTML::OVERVIEW with the table of contents and short table of
2847# contents.
2848#
2849# arguments:
2850# ref on an array containing all the elements
2851
2852# each element is a reference on a hash. The following keys might be of
2853# use:
2854# 'top': true if this is the top element
2855# 'toc_level': level of the element in the table of content. Highest level
2856#              is 1 for the @top element and for chapters, appendix and so on,
2857#              2 for section, unnumberedsec and so on...
2858# 'tocid': label used for reference linking to the element in table of
2859#          contents
2860# 'file': the file containing the element, usefull to do href to that file
2861#         in case the document is split.
2862# 'text': text of the element, with section number
2863# 'text_nonumber': text of the element, without section number
2864
2865# Relevant configuration variables are:
2866# $NUMBER_SECTIONS
2867# $NO_BULLET_LIST_ATTRIBUTE: usefull in case a list is used
2868# $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames.
2869# $BEFORE_OVERVIEW
2870# $AFTER_OVERVIEW
2871# $BEFORE_TOC_LINES
2872# $AFTER_TOC_LINES
2873# $DO_CONTENTS
2874# $DO_SCONTENTS
2875
2876sub T2H_DEFAULT_toc_body($)
2877{
2878}
2879
2880sub T2H_DEFAULT_inline_contents($$$)
2881{
2882    my $fh = shift;
2883    my $command = shift;
2884    my $element = shift;
2885    my $name;
2886    my $lines;
2887
2888    my $result = undef;
2889
2890    if ($command eq 'contents')
2891    {
2892        $name = $Texi2HTML::NAME{'Contents'};
2893        $lines = $Texi2HTML::TOC_LINES;
2894    }
2895    else
2896    {
2897        $name = $Texi2HTML::NAME{'Overview'};
2898        $lines = $Texi2HTML::OVERVIEW;
2899    }
2900    if (@{$lines})
2901    {
2902         $result = [ "".&$anchor($element->{'id'})."\n",
2903            "<h1>$name</h1>\n" ];
2904         push @$result, @$lines;
2905    }
2906
2907    return $result;
2908}
2909
2910sub T2H_DEFAULT_css_lines ($$)
2911{
2912    my $import_lines = shift;
2913    my $rule_lines = shift;
2914#    return if (defined($CSS_LINES) or (!@$rule_lines and !@$import_lines and (! keys(%css_map))));
2915    if (defined($CSS_LINES))
2916    { # if predefined, use CSS_LINES.
2917       $Texi2HTML::THISDOC{'CSS_LINES'} = $CSS_LINES;
2918       return;
2919    }
2920    return if (!@$rule_lines and !@$import_lines and (! keys(%css_map)));
2921    my $css_lines = "<style type=\"text/css\">\n<!--\n";
2922    $css_lines .= join('',@$import_lines) . "\n" if (@$import_lines);
2923    foreach my $css_rule (sort(keys(%css_map)))
2924    {
2925        next unless ($css_map{$css_rule});
2926        $css_lines .= "$css_rule {$css_map{$css_rule}}\n";
2927    }
2928    $css_lines .= join('',@$rule_lines) . "\n" if (@$rule_lines);
2929    $css_lines .= "-->\n</style>\n";
2930    foreach my $ref (@CSS_REFS)
2931    {
2932        $css_lines .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$ref\">\n";
2933    }
2934    $Texi2HTML::THISDOC{'CSS_LINES'} = $css_lines;
2935}
2936
2937######################################################################
2938# About page
2939#
2940
2941# PRE_ABOUT can be a function reference or a scalar.
2942# Note that if it is a scalar, T2H_InitGlobals has not been called,
2943# and all global variables like $ADDRESS are not available.
2944$PRE_ABOUT = sub
2945{
2946    return '  ' . &$program_string() .  "\n";
2947};
2948
2949# If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>.
2950$AFTER_ABOUT = '';
2951
2952%BUTTONS_EXAMPLE =
2953    (
2954     'Top',         ' &nbsp; ',
2955     'Contents',    ' &nbsp; ',
2956     'Overview',    ' &nbsp; ',
2957     'Index',       ' &nbsp; ',
2958     'This',        '1.2.3',
2959     'Back',        '1.2.2',
2960     'FastBack',    '1',
2961     'Prev',        '1.2.2',
2962     'Up',          '1.2',
2963     'Next',        '1.2.4',
2964     'NodeUp',      '1.2',
2965     'NodeNext',    '1.2.4',
2966     'NodePrev',    '1.2.2',
2967     'Following',   '1.2.4',
2968     'Forward',     '1.2.4',
2969     'FastForward', '2',
2970     'About',       ' &nbsp; ',
2971     'First',       '1.',
2972     'Last',        '1.2.4',
2973     'NextFile',    ' &nbsp; ',
2974     'PrevFile',    ' &nbsp; ',
2975    );
2976
2977sub T2H_DEFAULT_about_body
2978{
2979    my $about = "<p>\n";
2980    if (ref($PRE_ABOUT) eq 'CODE')
2981    {
2982        $about .= &$PRE_ABOUT();
2983    }
2984    else
2985    {
2986        $about .= $PRE_ABOUT;
2987    }
2988    $about .= <<EOT;
2989</p>
2990<p>
2991EOT
2992    $about .= &$I('  The buttons in the navigation panels have the following meaning:') . "\n";
2993    $about .= <<EOT;
2994</p>
2995<table border="1">
2996  <tr>
2997EOT
2998    $about .= '    <th> ' . &$I('Button') . " </th>\n" .
2999'    <th> ' . &$I('Name') . " </th>\n" .
3000'    <th> ' . &$I('Go to') . " </th>\n" .
3001'    <th> ' . &$I('From 1.2.3 go to') . "</th>\n" . "  </tr>\n";
3002
3003    for my $button (@SECTION_BUTTONS)
3004    {
3005        next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY';
3006        $about .= "  <tr>\n    <td align=\"center\">";
3007        $about .=
3008            ($ICONS && $ACTIVE_ICONS{$button} ?
3009             &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) :
3010             ' [' . $NAVIGATION_TEXT{$button} . '] ');
3011        $about .= "</td>\n";
3012        $about .= <<EOT;
3013    <td align="center">$BUTTONS_NAME{$button}</td>
3014    <td>$BUTTONS_GOTO{$button}</td>
3015    <td>$BUTTONS_EXAMPLE{$button}</td>
3016  </tr>
3017EOT
3018    }
3019
3020    $about .= <<EOT;
3021</table>
3022
3023<p>
3024EOT
3025    $about .= &$I('  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:') . "\n";
3026
3027#  where the <strong> Example </strong> assumes that the current position
3028#  is at <strong> Subsubsection One-Two-Three </strong> of a document of
3029#  the following structure:
3030    $about .= <<EOT;
3031</p>
3032
3033<ul>
3034EOT
3035    $about .= '  <li> 1. ' . &$I('Section One') . "\n" .
3036"    <ul>\n" .
3037'      <li>1.1 ' . &$I('Subsection One-One') . "\n";
3038    $about .= <<EOT;
3039        <ul>
3040          <li>...</li>
3041        </ul>
3042      </li>
3043EOT
3044    $about .= '      <li>1.2 ' . &$I('Subsection One-Two') . "\n" .
3045"        <ul>\n" .
3046'          <li>1.2.1 ' . &$I('Subsubsection One-Two-One') . "</li>\n" .
3047'          <li>1.2.2 ' . &$I('Subsubsection One-Two-Two') . "</li>\n" .
3048'          <li>1.2.3 ' . &$I('Subsubsection One-Two-Three') . " &nbsp; &nbsp;\n"
3049.
3050'            <strong>&lt;== ' . &$I('Current Position') . " </strong></li>\n" .
3051'          <li>1.2.4 ' . &$I('Subsubsection One-Two-Four') . "</li>\n" .
3052"        </ul>\n" .
3053"      </li>\n" .
3054'      <li>1.3 ' . &$I('Subsection One-Three') . "\n";
3055    $about .= <<EOT;
3056        <ul>
3057          <li>...</li>
3058        </ul>
3059      </li>
3060EOT
3061    $about .= '      <li>1.4 ' . &$I('Subsection One-Four') . "</li>\n";
3062    $about .= <<EOT;
3063    </ul>
3064  </li>
3065</ul>
3066$AFTER_ABOUT
3067EOT
3068    return $about;
3069}
3070
3071# return value is currently ignored
3072sub T2H_DEFAULT_titlepage($$$$)
3073{
3074    my $titlepage_lines = shift;
3075    my $titlepage_text = shift;
3076    my $titlepage_no_texi = shift;
3077    my $titlepage_simple_format = shift;
3078
3079    my $result = '';
3080    my $title = '';
3081    $title = $Texi2HTML::THISDOC{'title'} if (defined($Texi2HTML::THISDOC{'title'}) and $Texi2HTML::THISDOC{'title'} !~ /^\s*$/);
3082    if ($title ne ''
3083        or @{$Texi2HTML::THISDOC{'subtitles'}}
3084        or @{$Texi2HTML::THISDOC{'authors'}})
3085    {
3086        $result = "<div align=\"center\">\n";
3087        if ($title ne '')
3088        {
3089            $result .= '<h1>' . $title . "</h1>\n";
3090        }
3091        foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}})
3092        {
3093            $result .= '<h2>' . $subtitle . "</h2>\n";
3094        }
3095        foreach my $author (@{$Texi2HTML::THISDOC{'authors'}})
3096        {
3097            $result .= '<strong> ' . $author . " </strong><br>\n";
3098        }
3099        $result .= "</div>\n$DEFAULT_RULE\n";
3100    }
3101
3102    $Texi2HTML::TITLEPAGE = $titlepage_text;
3103
3104    $Texi2HTML::TITLEPAGE = $result . $Texi2HTML::TITLEPAGE;
3105
3106    if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'} and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'contents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
3107    {
3108        foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
3109        {
3110            $Texi2HTML::TITLEPAGE .= $line;
3111        }
3112        $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
3113    }
3114    if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'} and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
3115    {
3116        foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
3117        {
3118            $Texi2HTML::TITLEPAGE .= $line;
3119        }
3120        $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
3121    }
3122    return $Texi2HTML::TITLEPAGE;
3123}
3124
3125# FIXME Honor DOCUMENT_DESCRIPTION?
3126sub T2H_DEFAULT_print_redirection_page($)
3127{
3128    my $fh = shift;
3129    my $longtitle = "$Texi2HTML::THISDOC{'fulltitle_simple_format'}";
3130    $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if exists $Texi2HTML::SIMPLE_TEXT{'This'};
3131    my $description = $longtitle;
3132    my $encoding = '';
3133    $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$Texi2HTML::THISDOC{'ENCODING_NAME'}\">" if (defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and ($Texi2HTML::THISDOC{'ENCODING_NAME'} ne ''));
3134    my $href = &$anchor('', $Texi2HTML::HREF{'This'}, $Texi2HTML::NAME{'This'});
3135    my $string = &$I('The node you are looking for is at %{href}.',
3136       { 'href' => $href });
3137    print $fh <<EOT;
3138$DOCTYPE
3139<html>
3140<!-- Created on $Texi2HTML::THISDOC{'today'} by $Texi2HTML::THISDOC{'program'} -->
3141<!--
3142$Texi2HTML::THISDOC{'program_authors'}
3143-->
3144<head>
3145<title>$longtitle</title>
3146
3147<meta name="description" content="$description">
3148<meta name="keywords" content="$longtitle">
3149<meta name="resource-type" content="document">
3150<meta name="distribution" content="global">
3151<meta name="Generator" content="$Texi2HTML::THISDOC{program}">
3152$encoding
3153$Texi2HTML::THISDOC{'CSS_LINES'}
3154<meta http-equiv="Refresh" content="2; url=$Texi2HTML::HREF{'This'}">
3155$EXTRA_HEAD
3156</head>
3157
3158<body $Texi2HTML::THISDOC{'BODYTEXT'}>
3159$AFTER_BODY_OPEN
3160<p>$string</p>
3161</body>
3162EOT
3163}
3164
3165sub T2H_DEFAULT_node_file_name($$)
3166{
3167    my $node = shift;
3168    my $type = shift;
3169    return undef if ($node->{'external_node'}
3170       or ($type eq 'top' and !$NEW_CROSSREF_STYLE));
3171    my $node_file_base;
3172    if ($type eq 'top' and defined($TOP_NODE_FILE))
3173    {
3174        $node_file_base = $TOP_NODE_FILE;
3175    }
3176    elsif ($NEW_CROSSREF_STYLE)
3177    {
3178        if ($TRANSLITERATE_NODE)
3179        {
3180            $node_file_base = $node->{'cross_manual_file'};
3181        }
3182        else
3183        {
3184            $node_file_base = $node->{'cross_manual_target'};
3185        }
3186    }
3187    else
3188    {
3189         $node_file_base = main::remove_texi($node->{'texi'});
3190         $node_file_base =~ s/[^\w\.\-]/-/g;
3191    }
3192    if (defined($NODE_FILE_EXTENSION) and $NODE_FILE_EXTENSION ne '')
3193    {
3194        return ($node_file_base . ".$NODE_FILE_EXTENSION");
3195    }
3196    return $node_file_base;
3197}
3198
3199########################################################################
3200# Control of formatting:
3201# 1.) For some changes, it is often enough to change the value of
3202#     some global map. It might necessitate building a little
3203#     function along with the change in hash, if the change is the use
3204#     of another function (in style_map).
3205# 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines,
3206#     give them another name, and assign them to the respective
3207#     $<fnc> variable (below).
3208
3209
3210#
3211# This hash should have keys corresponding with the nonletter command accent
3212# whose following character is considered to be the argument
3213# This hash associates an accent macro to the ISO name for the accent if any.
3214# The customary use of this map is to find the ISO name appearing in html
3215# entity (like &eacute;) associated with a texinfo accent macro.
3216#
3217# The keys of the hash are
3218# ": umlaut
3219# ~: tilda accent
3220# ^: circumflex accent
3221# `: grave accent
3222# ': acute accent
3223# =: macron accent
3224%accent_map = (
3225          '"',  'uml',
3226          '~',  'tilde',
3227          '^',  'circ',
3228          '`',  'grave',
3229          "'", 'acute',
3230          ",", 'cedil',
3231          '=', '',
3232          'ringaccent', 'ring',
3233          'H', '',
3234          'dotaccent', '',
3235          'u', '',
3236          'ubaraccent', '',
3237          'udotaccent', '',
3238          'v', '',
3239          'ogonek', 'ogon',
3240         );
3241
3242#
3243# texinfo "simple things" (@foo) to HTML ones
3244#
3245%simple_map = (
3246           '*', "<br>",     # HTML+
3247           ' ', '&nbsp;',
3248           "\t", '&nbsp;',
3249           "\n", '&nbsp;',
3250     # "&#173;" or "&shy;" could also be possible for @-, but it seems
3251     # that some browser will consider this as an always visible hyphen mark
3252     # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html)
3253           '-', '',  # hyphenation hint
3254           '|', '',  # used in formatting commands @evenfooting and friends
3255           '/', '',
3256       # spacing commands
3257           ':', '',
3258           '!', '!',
3259           '?', '?',
3260           '.', '.',
3261           '@', '@',
3262           '}', '}',
3263           '{', '{',
3264          );
3265
3266# this map is used in preformatted text
3267%simple_map_pre = %simple_map;
3268$simple_map_pre{'*'} = "\n";
3269
3270# maps for the math specific commands
3271%simple_map_math = (
3272           '\\', '\\'
3273           );
3274
3275%simple_map_pre_math = %simple_map_math;
3276%simple_map_texi_math = %simple_map_math;
3277
3278%colon_command_punctuation_characters = (
3279   '.' => '.',
3280   ':' => ':',
3281   '?' => '?',
3282   '!' => '!'
3283);
3284
3285#
3286# texinfo "things" (@foo{}) to HTML ones
3287#
3288%things_map = (
3289               'TeX'          => 'TeX',
3290               'LaTeX'          => 'LaTeX',
3291# pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing)
3292#               'br', '<br>',     # paragraph break
3293               'bullet'       => '*',
3294#               #'copyright' => '(C)',
3295               'copyright'    => '&copy;',
3296               'registeredsymbol'   => '&reg;',
3297               'dots'         => '<small class="dots">...</small>',
3298               'enddots'      => '<small class="enddots">...</small>',
3299               'equiv'        => '==',
3300# FIXME i18n
3301               'error'        => 'error--&gt;',
3302               'expansion'    => '==&gt;',
3303               'arrow'        => '->',
3304               'minus'        => '-',
3305               'point'        => '-!-',
3306               'print'        => '-|',
3307               'result'       => '=&gt;',
3308               # set in code using the language
3309               # 'today', &pretty_date,
3310               'today'        => '',
3311               'aa'           => '&aring;',
3312               'AA'           => '&Aring;',
3313               'ae'           => '&aelig;',
3314               'oe'           => '&oelig;', #pertusus: also &#156;. &oelig; not in html 3.2
3315               'AE'           => '&AElig;',
3316               'OE'           => '&OElig;', #pertusus: also &#140;. &OElig; not in html 3.2
3317               'o'            =>  '&oslash;',
3318               'O'            =>  '&Oslash;',
3319               'ss'           => '&szlig;',
3320               'l'            => '&#322;',
3321               'L'            => '&#321;',
3322               'exclamdown'   => '&iexcl;',
3323               'questiondown' => '&iquest;',
3324               'pounds'       => '&pound;',
3325               'ordf'         => '&ordf;',
3326               'ordm'         => '&ordm;',
3327               'comma'        => ',',
3328               'euro'         => '&euro;',
3329               'geq'          => '&ge;',
3330               'leq'          => '&le;',
3331               'tie'          => '&nbsp;',
3332               'textdegree'          => '&deg;',
3333               'quotedblleft'          => '&ldquo;',
3334               'quotedblright'          => '&rdquo;',
3335               'quoteleft'          => '&lsquo;',
3336               'quoteright'          => '&rsquo;',
3337               'quotedblbase'          => '&bdquo;',
3338               'quotesinglbase'          => '&sbquo;',
3339               'guillemetleft'          => '&laquo;',
3340               'guillemetright'          => '&raquo;',
3341               'guillemotleft'          => '&laquo;',
3342               'guillemotright'          => '&raquo;',
3343               'guilsinglleft'          => '&lsaquo;',
3344               'guilsinglright'          => '&rsaquo;',
3345             );
3346
3347# This map is used in preformatted environments
3348%pre_map = %things_map;
3349$pre_map{'dots'} = '...';
3350$pre_map{'enddots'} = '...';
3351#$pre_map{'br'} = "\n";
3352
3353%ascii_things_map = (
3354               'TeX'          => 'TeX',
3355               'LaTeX'          => 'LaTeX',
3356               'bullet'       => '*',
3357               'copyright' => '(C)',
3358               'registeredsymbol'   => '(R)',
3359               'dots'         => '...',
3360               'enddots'      => '...',
3361               'equiv'        => '==',
3362# FIXME i18n
3363               'error'        => 'error-->',
3364               'expansion'    => '==>',
3365               'arrow'        => '->',
3366               'minus'        => '-',
3367               'point'        => '-!-',
3368               'print'        => '-|',
3369               'result'       => '=>',
3370               'today'        => '',
3371               'aa'           => 'aa',
3372               'AA'           => 'AA',
3373               'ae'           => 'ae',
3374               'oe'           => 'oe',
3375               'AE'           => 'AE',
3376               'OE'           => 'OE',
3377               'o'            => '/o',
3378               'O'            => '/O',
3379               'ss'           => 'ss',
3380               'l'            => '/l',
3381               'L'            => '/L',
3382               'exclamdown'   => '?',
3383               'questiondown' => '!',
3384               'pounds'       => '#',
3385               'ordf'         => 'a',
3386               'ordm'         => 'o',
3387               'comma'        => ',',
3388               'euro'         => 'Euro',
3389               'geq'          => '>=',
3390               'leq'          => '<=',
3391               'tie'          => ' ',
3392               'textdegree'          => 'o',
3393               'quotedblleft'          => '``',
3394               'quotedblright'          => "''",
3395               'quoteleft'          => '`',
3396               'quoteright'          => "'",
3397               'quotedblbase'          => ',,',
3398               'quotesinglbase'          => ',',
3399               'guillemetleft'          => '<<',
3400               'guillemetright'          => '>>',
3401               'guillemotleft'          => '<<',
3402               'guillemotright'          => '>>',
3403               'guilsinglleft'          => '<',
3404               'guilsinglright'          => '>',
3405);
3406
3407# ascii representation of @-commands
3408%ascii_simple_map = (
3409           '*', "\n",
3410           ' ', ' ',
3411           "\t", ' ',
3412           "\n", ' ',
3413           '-', '',  # hyphenation hint
3414           '|', '',  # used in formatting commands @evenfooting and friends
3415           '/', '',
3416           ':', '',
3417           '!', '!',
3418           '?', '?',
3419           '.', '.',
3420           '@', '@',
3421           '}', '}',
3422           '{', '{',
3423);
3424
3425#
3426# This map is used when texi elements are removed and replaced
3427# by simple text
3428#
3429%simple_map_texi = %ascii_simple_map;
3430
3431
3432# text replacing macros when texi commands are removed and plain text is
3433# produced
3434%texi_map = (
3435               'TeX', 'TeX',
3436               'LaTeX', 'LaTeX',
3437               'bullet', '*',
3438               'copyright', 'C',
3439               'registeredsymbol', 'R',
3440               'dots', '...',
3441               'enddots', '...',
3442               'equiv', '==',
3443               'error', 'error-->',
3444               'expansion', '==>',
3445               'arrow',  '->',
3446               'minus', '-',
3447               'point', '-!-',
3448               'print', '-|',
3449               'result', '=>',
3450               'today'        => '',
3451               'aa', 'aa',
3452               'AA', 'AA',
3453               'ae', 'ae',
3454               'oe', 'oe',
3455               'AE', 'AE',
3456               'OE', 'OE',
3457               'o',  'o',
3458               'O',  'O',
3459               'ss', 'ss',
3460               'l', 'l',
3461               'L', 'L',
3462               'exclamdown', '! upside-down',
3463               #'exclamdown', '&iexcl;',
3464               'questiondown', '? upside-down',
3465               #'questiondown', '&iquest;',
3466               'pounds', 'pound sterling',
3467               #'pounds', '&pound;'
3468               'ordf'         => 'a',
3469               'ordm'         => 'o',
3470               'comma'        => ',',
3471               'euro'         => 'Euro',
3472               'geq'          => '>=',
3473               'leq'          => '<=',
3474               'tie'          => ' ',
3475               'textdegree'          => 'o',
3476               'quotedblleft'          => '``',
3477               'quotedblright'          => "''",
3478               'quoteleft'          => '`',
3479               'quoteright'          => "'",
3480               'quotedblbase'          => ',,',
3481               'quotesinglbase'          => ',',
3482               'guillemetleft'          => '<<',
3483               'guillemetright'          => '>>',
3484               'guillemotleft'          => '<<',
3485               'guillemotright'          => '>>',
3486               'guilsinglleft'          => '<',
3487               'guilsinglright'          => '>',
3488            );
3489
3490# taken from
3491#Latin extended additionnal
3492#http://www.alanwood.net/unicode/latin_extended_additional.html
3493#C1 Controls and Latin-1 Supplement
3494#http://www.alanwood.net/unicode/latin_1_supplement.html
3495#Latin Extended-A
3496#http://www.alanwood.net/unicode/latin_extended_a.html
3497#Latin Extended-B
3498#http://www.alanwood.net/unicode/latin_extended_b.html
3499#dotless i: 0131
3500
3501#http://www.alanwood.net/unicode/arrows.html 21**
3502#http://www.alanwood.net/unicode/general_punctuation.html 20**
3503#http://www.alanwood.net/unicode/mathematical_operators.html 22**
3504
3505%unicode_map = (
3506               'bullet'       => '2022',
3507               'copyright'    => '00A9',
3508               'registeredsymbol'   => '00AE',
3509               'dots'         => '2026',
3510               'enddots'      => '',
3511               'equiv'        => '2261',
3512               'error'        => '',
3513               'expansion'    => '2192',
3514               'arrow'        => '2192',
3515               'minus'        => '2212', # in mathematical operators
3516#               'minus'        => '002D', # in latin1
3517               'point'        => '2605',
3518               'print'        => '22A3',
3519               'result'       => '21D2',
3520               'today'        => '',
3521               'aa'           => '00E5',
3522               'AA'           => '00C5',
3523               'ae'           => '00E6',
3524               'oe'           => '0153',
3525               'AE'           => '00C6',
3526               'OE'           => '0152',
3527               'o'            => '00F8',
3528               'O'            => '00D8',
3529               'ss'           => '00DF',
3530               'l'            => '0142',
3531               'L'            => '0141',
3532               'exclamdown'   => '00A1',
3533               'questiondown' => '00BF',
3534               'pounds'       => '00A3',
3535               'ordf'         => '00AA',
3536               'ordm'         => '00BA',
3537               'comma'        => '002C',
3538               'euro'         => '20AC',
3539               'geq'          => '2265',
3540               'leq'          => '2264',
3541               'tie'          => '',
3542#               'tie'          => '0020',
3543               'textdegree'          => '00B0',
3544               'quotedblleft'          => '201C',
3545               'quotedblright'          => '201D',
3546               'quoteleft'          => '2018',
3547               'quoteright'          => '2019',
3548               'quotedblbase'          => '201E',
3549               'quotesinglbase'          => '201A',
3550               'guillemetleft'          => '00AB',
3551               'guillemetright'          => '00BB',
3552               'guillemotleft'          => '00AB',
3553               'guillemotright'          => '00BB',
3554               'guilsinglleft'          => '2039',
3555               'guilsinglright'          => '203A',
3556             );
3557
3558%makeinfo_encoding_to_map = (
3559  "iso-8859-1",  'iso8859_1',
3560  "iso-8859-2",  'iso8859_2',
3561  "iso-8859-15", 'iso8859_15',
3562  "koi8-r",      'koi8',
3563  "koi8-u",      'koi8',
3564);
3565
3566foreach my $encoding (keys(%makeinfo_encoding_to_map))
3567{
3568   $t2h_encoding_aliases{$encoding} = $encoding;
3569   $t2h_encoding_aliases{$makeinfo_encoding_to_map{$encoding}} = $encoding;
3570}
3571
3572# cut and pasted from eigth_bit_makeinfo_maps.pl, in turn generated with
3573# ./parse_8bit_makeinfo_maps.pl
3574
3575%makeinfo_unicode_to_eight_bit = (
3576   'iso8859_1' => {
3577      '00A0' => 'A0',
3578      '00A1' => 'A1',
3579      '00A2' => 'A2',
3580      '00A3' => 'A3',
3581      '00A4' => 'A4',
3582      '00A5' => 'A5',
3583      '00A6' => 'A6',
3584      '00A7' => 'A7',
3585      '00A8' => 'A8',
3586      '00A9' => 'A9',
3587      '00AA' => 'AA',
3588      '00AB' => 'AB',
3589      '00AC' => 'AC',
3590      '00AD' => 'AD',
3591      '00AE' => 'AE',
3592      '00AF' => 'AF',
3593      '00B0' => 'B0',
3594      '00B1' => 'B1',
3595      '00B2' => 'B2',
3596      '00B3' => 'B3',
3597      '00B4' => 'B4',
3598      '00B5' => 'B5',
3599      '00B6' => 'B6',
3600      '00B7' => 'B7',
3601      '00B8' => 'B8',
3602      '00B9' => 'B9',
3603      '00BA' => 'BA',
3604      '00BB' => 'BB',
3605      '00BC' => 'BC',
3606      '00BD' => 'BD',
3607      '00BE' => 'BE',
3608      '00BF' => 'BF',
3609      '00C0' => 'C0',
3610      '00C1' => 'C1',
3611      '00C2' => 'C2',
3612      '00C3' => 'C3',
3613      '00C4' => 'C4',
3614      '00C5' => 'C5',
3615      '00C6' => 'C6',
3616      '00C7' => 'C7',
3617      '00C7' => 'C7',
3618      '00C8' => 'C8',
3619      '00C9' => 'C9',
3620      '00CA' => 'CA',
3621      '00CB' => 'CB',
3622      '00CC' => 'CC',
3623      '00CD' => 'CD',
3624      '00CE' => 'CE',
3625      '00CF' => 'CF',
3626      '00D0' => 'D0',
3627      '00D1' => 'D1',
3628      '00D2' => 'D2',
3629      '00D3' => 'D3',
3630      '00D4' => 'D4',
3631      '00D5' => 'D5',
3632      '00D6' => 'D6',
3633      '00D7' => 'D7',
3634      '00D8' => 'D8',
3635      '00D9' => 'D9',
3636      '00DA' => 'DA',
3637      '00DB' => 'DB',
3638      '00DC' => 'DC',
3639      '00DD' => 'DD',
3640      '00DE' => 'DE',
3641      '00DF' => 'DF',
3642      '00E0' => 'E0',
3643      '00E1' => 'E1',
3644      '00E2' => 'E2',
3645      '00E3' => 'E3',
3646      '00E4' => 'E4',
3647      '00E5' => 'E5',
3648      '00E6' => 'E6',
3649      '00E7' => 'E7',
3650      '00E8' => 'E8',
3651      '00E9' => 'E9',
3652      '00EA' => 'EA',
3653      '00EB' => 'EB',
3654      '00EC' => 'EC',
3655      '00ED' => 'ED',
3656      '00EE' => 'EE',
3657      '00EF' => 'EF',
3658      '00F0' => 'F0',
3659      '00F1' => 'F1',
3660      '00F2' => 'F2',
3661      '00F3' => 'F3',
3662      '00F4' => 'F4',
3663      '00F5' => 'F5',
3664      '00F6' => 'F6',
3665      '00F7' => 'F7',
3666      '00F8' => 'F8',
3667      '00F9' => 'F9',
3668      '00FA' => 'FA',
3669      '00FB' => 'FB',
3670      '00FC' => 'FC',
3671      '00FD' => 'FD',
3672      '00FE' => 'FE',
3673      '00FF' => 'FF',
3674   },
3675   'iso8859_15' => {
3676      '00A0' => 'A0',
3677      '00A1' => 'A1',
3678      '00A2' => 'A2',
3679      '00A3' => 'A3',
3680      '20AC' => 'A4',
3681      '00A5' => 'A5',
3682      '0160' => 'A6',
3683      '00A7' => 'A7',
3684      '0161' => 'A8',
3685      '00A9' => 'A9',
3686      '00AA' => 'AA',
3687      '00AB' => 'AB',
3688      '00AC' => 'AC',
3689      '00AD' => 'AD',
3690      '00AE' => 'AE',
3691      '00AF' => 'AF',
3692      '00B0' => 'B0',
3693      '00B1' => 'B1',
3694      '00B2' => 'B2',
3695      '00B3' => 'B3',
3696      '017D' => 'B4',
3697      '00B5' => 'B5',
3698      '00B6' => 'B6',
3699      '00B7' => 'B7',
3700      '017E' => 'B8',
3701      '00B9' => 'B9',
3702      '00BA' => 'BA',
3703      '00BB' => 'BB',
3704      '0152' => 'BC',
3705      '0153' => 'BD',
3706      '0178' => 'BE',
3707      '00BF' => 'BF',
3708      '00C0' => 'C0',
3709      '00C1' => 'C1',
3710      '00C2' => 'C2',
3711      '00C3' => 'C3',
3712      '00C4' => 'C4',
3713      '00C5' => 'C5',
3714      '00C6' => 'C6',
3715      '00C7' => 'C7',
3716      '00C8' => 'C8',
3717      '00C9' => 'C9',
3718      '00CA' => 'CA',
3719      '00CB' => 'CB',
3720      '00CC' => 'CC',
3721      '00CD' => 'CD',
3722      '00CE' => 'CE',
3723      '00CF' => 'CF',
3724      '00D0' => 'D0',
3725      '00D1' => 'D1',
3726      '00D2' => 'D2',
3727      '00D3' => 'D3',
3728      '00D4' => 'D4',
3729      '00D5' => 'D5',
3730      '00D6' => 'D6',
3731      '00D7' => 'D7',
3732      '00D8' => 'D8',
3733      '00D9' => 'D9',
3734      '00DA' => 'DA',
3735      '00DB' => 'DB',
3736      '00DC' => 'DC',
3737      '00DD' => 'DD',
3738      '00DE' => 'DE',
3739      '00DF' => 'DF',
3740      '00E0' => 'E0',
3741      '00E1' => 'E1',
3742      '00E2' => 'E2',
3743      '00E3' => 'E3',
3744      '00E4' => 'E4',
3745      '00E5' => 'E5',
3746      '00E6' => 'E6',
3747      '00E7' => 'E7',
3748      '00E8' => 'E8',
3749      '00E9' => 'E9',
3750      '00EA' => 'EA',
3751      '00EB' => 'EB',
3752      '00EC' => 'EC',
3753      '00ED' => 'ED',
3754      '00EE' => 'EE',
3755      '00EF' => 'EF',
3756      '00F0' => 'F0',
3757      '00F1' => 'F1',
3758      '00F2' => 'F2',
3759      '00F3' => 'F3',
3760      '00F4' => 'F4',
3761      '00F5' => 'F5',
3762      '00F6' => 'F6',
3763      '00F7' => 'F7',
3764      '00F8' => 'F8',
3765      '00F9' => 'F9',
3766      '00FA' => 'FA',
3767      '00FB' => 'FB',
3768      '00FC' => 'FC',
3769      '00FD' => 'FD',
3770      '00FE' => 'FE',
3771      '00FF' => 'FF',
3772   },
3773   'iso8859_2' => {
3774      '00A0' => 'A0',
3775      '0104' => 'A1',
3776      '02D8' => 'A2',
3777      '0141' => 'A3',
3778      '00A4' => 'A4',
3779      '013D' => 'A5',
3780      '015A' => 'A6',
3781      '00A7' => 'A7',
3782      '00A8' => 'A8',
3783      '015E' => 'AA',
3784      '0164' => 'AB',
3785      '0179' => 'AC',
3786      '00AD' => 'AD',
3787      '017D' => 'AE',
3788      '017B' => 'AF',
3789      '00B0' => 'B0',
3790      '0105' => 'B1',
3791      '02DB' => 'B2',
3792      '0142' => 'B3',
3793      '00B4' => 'B4',
3794      '013E' => 'B5',
3795      '015B' => 'B6',
3796      '02C7' => 'B7',
3797      '00B8' => 'B8',
3798      '0161' => 'B9',
3799      '015F' => 'BA',
3800      '0165' => 'BB',
3801      '017A' => 'BC',
3802      '02DD' => 'BD',
3803      '017E' => 'BE',
3804      '017C' => 'BF',
3805      '0154' => 'C0',
3806      '00C1' => 'C1',
3807      '00C2' => 'C2',
3808      '0102' => 'C3',
3809      '00C4' => 'C4',
3810      '0139' => 'C5',
3811      '0106' => 'C6',
3812      '00C7' => 'C7',
3813      '010C' => 'C8',
3814      '00C9' => 'C9',
3815      '0118' => 'CA',
3816      '00CB' => 'CB',
3817      '011A' => 'CC',
3818      '00CD' => 'CD',
3819      '00CE' => 'CE',
3820      '010E' => 'CF',
3821      '0110' => 'D0',
3822      '0143' => 'D1',
3823      '0147' => 'D2',
3824      '00D3' => 'D3',
3825      '00D4' => 'D4',
3826      '0150' => 'D5',
3827      '00D6' => 'D6',
3828      '00D7' => 'D7',
3829      '0158' => 'D8',
3830      '016E' => 'D9',
3831      '00DA' => 'DA',
3832      '0170' => 'DB',
3833      '00DC' => 'DC',
3834      '00DD' => 'DD',
3835      '0162' => 'DE',
3836      '00DF' => 'DF',
3837      '0155' => 'E0',
3838      '00E1' => 'E1',
3839      '00E2' => 'E2',
3840      '0103' => 'E3',
3841      '00E4' => 'E4',
3842      '013A' => 'E5',
3843      '0107' => 'E6',
3844      '00E7' => 'E7',
3845      '010D' => 'E8',
3846      '00E9' => 'E9',
3847      '0119' => 'EA',
3848      '00EB' => 'EB',
3849      '011B' => 'EC',
3850      '00ED' => 'ED',
3851      '00EE' => 'EE',
3852      '010F' => 'EF',
3853      '0111' => 'F0',
3854      '0144' => 'F1',
3855      '0148' => 'F2',
3856      '00F3' => 'F3',
3857      '00F4' => 'F4',
3858      '0151' => 'F5',
3859      '00F6' => 'F6',
3860      '00F7' => 'F7',
3861      '0159' => 'F8',
3862      '016F' => 'F9',
3863      '00FA' => 'FA',
3864      '0171' => 'FB',
3865      '00FC' => 'FC',
3866      '00FD' => 'FD',
3867      '0163' => 'FE',
3868      '02D9' => 'FF',
3869   },
3870   'koi8' => {
3871      '0415' => 'A3',
3872      '0454' => 'A4',
3873      '0456' => 'A6',
3874      '0457' => 'A7',
3875      '04D7' => 'B3',
3876      '0404' => 'B4',
3877      '0406' => 'B6',
3878      '0407' => 'B7',
3879      '042E' => 'C0',
3880      '0430' => 'C1',
3881      '0431' => 'C2',
3882      '0446' => 'C3',
3883      '0434' => 'C4',
3884      '0435' => 'C5',
3885      '0444' => 'C6',
3886      '0433' => 'C7',
3887      '0445' => 'C8',
3888      '0438' => 'C9',
3889      '0439' => 'CA',
3890      '043A' => 'CB',
3891      '043B' => 'CC',
3892      '043C' => 'CD',
3893      '043D' => 'CE',
3894      '043E' => 'CF',
3895      '043F' => 'D0',
3896      '044F' => 'D1',
3897      '0440' => 'D2',
3898      '0441' => 'D3',
3899      '0442' => 'D4',
3900      '0443' => 'D5',
3901      '0436' => 'D6',
3902      '0432' => 'D7',
3903      '044C' => 'D8',
3904      '044B' => 'D9',
3905      '0437' => 'DA',
3906      '0448' => 'DB',
3907      '044D' => 'DC',
3908      '0449' => 'DD',
3909      '0447' => 'DE',
3910      '044A' => 'DF',
3911      '042D' => 'E0',
3912      '0410' => 'E1',
3913      '0411' => 'E2',
3914      '0426' => 'E3',
3915      '0414' => 'E4',
3916      '0415' => 'E5',
3917      '0424' => 'E6',
3918      '0413' => 'E7',
3919      '0425' => 'E8',
3920      '0418' => 'E9',
3921      '0419' => 'EA',
3922      '041A' => 'EB',
3923      '041B' => 'EC',
3924      '041C' => 'ED',
3925      '041D' => 'EE',
3926      '041E' => 'EF',
3927      '041F' => 'F0',
3928      '042F' => 'F1',
3929      '0420' => 'F2',
3930      '0421' => 'F3',
3931      '0422' => 'F4',
3932      '0423' => 'F5',
3933      '0416' => 'F6',
3934      '0412' => 'F7',
3935      '042C' => 'F8',
3936      '042B' => 'F9',
3937      '0417' => 'FA',
3938      '0428' => 'FB',
3939      '042D' => 'FC',
3940      '0429' => 'FD',
3941      '0427' => 'FE',
3942      '042A' => 'FF',
3943   },
3944);
3945
3946%eight_bit_to_unicode = ();
3947foreach my $encoding (keys(%makeinfo_encoding_to_map))
3948{
3949   my $unicode_to_eight = $makeinfo_unicode_to_eight_bit{$makeinfo_encoding_to_map{$encoding}};
3950#print STDERR "$encoding, $makeinfo_encoding_to_map{$encoding}, $unicode_to_eight\n";
3951   foreach my $utf8_key (keys(%{$unicode_to_eight}))
3952   {
3953      $eight_bit_to_unicode{$encoding}->{$unicode_to_eight->{$utf8_key}} =
3954         $utf8_key;
3955   }
3956}
3957
3958my %makeinfo_transliterate_map = (
3959  '0416' => 'ZH',
3960  '0447' => 'ch',
3961  '00EB' => 'e',
3962  '0414' => 'D',
3963  '0159' => 'r',
3964  '00E6' => 'ae',
3965  '042B' => 'Y',
3966  '00FA' => 'u',
3967  '043B' => 'l',
3968  '00DE' => 'TH',
3969  '00D9' => 'U',
3970  '00C4' => 'A',
3971  '0148' => 'n',
3972  '00F6' => 'o',
3973  '0434' => 'd',
3974  '041E' => 'O',
3975  '041B' => 'L',
3976  '044B' => 'y',
3977  '0107' => 'c',
3978  '0415' => 'E',
3979  '00C1' => 'A',
3980  '00D3' => 'O',
3981  '00DB' => 'U',
3982  '016E' => 'U',
3983  '013A' => 'l',
3984  '017B' => 'Z',
3985  '00F1' => 'n',
3986  '0428' => 'SH',
3987  '0153' => 'oe',
3988  '00F4' => 'o',
3989  '0144' => 'n',
3990  '0404' => 'IE',
3991  '0427' => 'CH',
3992  '0162' => 'T',
3993  '017A' => 'z',
3994  '0448' => 'sh',
3995  '0436' => 'zh',
3996  '00F9' => 'u',
3997  '0406' => 'I',
3998  '0103' => 'a',
3999  '0422' => 'T',
4000  '0160' => 'S',
4001  '0165' => 't',
4002  '017E' => 'z',
4003  '00F0' => 'd',
4004  '043E' => 'o',
4005  '043D' => 'n',
4006  '013E' => 'l',
4007  '0412' => 'V',
4008  '0111' => 'd',
4009  '0155' => 's',
4010  '017C' => 'z',
4011  '00CE' => 'I',
4012  '042D' => 'E',
4013  '00C8' => 'E',
4014  '00F8' => 'oe',
4015  '00F2' => 'o',
4016  '00FF' => 'y',
4017  '0420' => 'R',
4018  '0119' => 'e',
4019  '00D2' => 'O',
4020  '043C' => 'm',
4021  '00D0' => 'DH',
4022  '0179' => 'Z',
4023  '0110' => 'D',
4024  '043F' => 'p',
4025  '0170' => 'U',
4026  '011A' => 'E',
4027  '010C' => 'C',
4028  '015A' => 'S',
4029  '0433' => 'g',
4030  '00E1' => 'a',
4031  '010D' => 'c',
4032  '00CC' => 'I',
4033  '016F' => 'u',
4034  '0457' => 'yi',
4035  '00C2' => 'A',
4036  '0438' => 'i',
4037  '00E3' => 'a',
4038  '0435' => 'e',
4039  '0440' => 'r',
4040  '042A' => 'W',
4041  '0431' => 'b',
4042  '00EE' => 'i',
4043  '0150' => 'O',
4044  '00E8' => 'e',
4045  '0418' => 'I',
4046  '00CF' => 'I',
4047  '015F' => 's',
4048  '0142' => 'l',
4049  '0147' => 'N',
4050  '00DF' => 'ss',
4051  '00E5' => 'aa',
4052  '00C3' => 'A',
4053  '0106' => 'C',
4054  '0141' => 'L',
4055  '0164' => 'T',
4056  '017D' => 'Z',
4057  '00EC' => 'i',
4058  '041C' => 'M',
4059  '00C9' => 'E',
4060  '00E0' => 'a',
4061  '043A' => 'k',
4062  '00F5' => 'o',
4063  '042C' => 'X',
4064  '0449' => 'shch',
4065  '0444' => 'f',
4066  '0139' => 'L',
4067  '0158' => 'R',
4068  '00F3' => 'o',
4069  '00FB' => 'u',
4070  '0424' => 'F',
4071  '0446' => 'c',
4072  '0423' => 'U',
4073  '0442' => 't',
4074  '00FD' => 'y',
4075  '0102' => 'A',
4076  '0104' => 'A',
4077  '00CB' => 'E',
4078  '0426' => 'C',
4079  '00CD' => 'I',
4080  '0437' => 'z',
4081  '0178' => 'y',
4082  '00D4' => 'O',
4083  '044D' => 'e',
4084  '0432' => 'v',
4085  '013D' => 'L',
4086  '0163' => 't',
4087  '0456' => 'i',
4088  '011B' => 'e',
4089  '044F' => 'ya',
4090  '0429' => 'SHCH',
4091  '0411' => 'B',
4092  '044A' => 'w',
4093  '00C6' => 'AE',
4094  '041D' => 'N',
4095  '00DA' => 'U',
4096  '00C0' => 'A',
4097  '0152' => 'OE',
4098  '00DD' => 'Y',
4099  '0154' => 'R',
4100  '00E9' => 'e',
4101  '00D5' => 'O',
4102  '041F' => 'P',
4103  '0161' => 's',
4104  '0430' => 'a',
4105  '0445' => 'h',
4106  '00E2' => 'a',
4107  '00D6' => 'O',
4108  '0407' => 'YI',
4109  '00CA' => 'E',
4110  '0439' => 'i',
4111  '0171' => 'u',
4112  '00DC' => 'U',
4113  '042F' => 'YA',
4114  '0425' => 'H',
4115  '00FE' => 'th',
4116  '00D1' => 'N',
4117  '044C' => 'x',
4118  '010F' => 'd',
4119  '0410' => 'A',
4120  '0443' => 'u',
4121  '00EF' => 'i',
4122  '0105' => 'a',
4123  '00EA' => 'e',
4124  '00E4' => 'a',
4125  '015E' => 'S',
4126  '0417' => 'Z',
4127  '00ED' => 'i',
4128  '00FC' => 'u',
4129  '04D7' => 'IO',
4130  '00D8' => 'OE',
4131  '0419' => 'I',
4132  '0421' => 'S',
4133  '0143' => 'N',
4134  '010E' => 'D',
4135  '0413' => 'G',
4136  '015B' => 's',
4137  '0151' => 'o',
4138  '00E7' => 'c',
4139  '00C5' => 'AA',
4140  '0441' => 's',
4141  '0118' => 'E',
4142  '00C7' => 'C',
4143  '041A' => 'K',
4144  '0454' => 'ie',
4145  '042E' => 'yu',
4146);
4147
4148
4149%transliterate_map = (
4150               '00C5'  => 'AA',
4151               '00E5'  => 'aa',
4152               '00D8'  => 'OE',
4153               '00F8'  => 'oe',
4154               '00E6' => 'ae',
4155               '0153' => 'oe',
4156               '00C6' => 'AE',
4157               '0152' => 'OE',
4158               '00DF' => 'ss',
4159               '0141' => 'L',
4160               '0142' => 'l',
4161               '00D0'  => 'DH',
4162               '0415'  => 'E',
4163               '0435'  => 'e',
4164               '0426'  => 'C',
4165               '042A'  => 'W',
4166               '044A'  => 'w',
4167               '042C'  => 'X',
4168               '044C'  => 'x',
4169               '042E'  => 'yu',
4170               '042F'  => 'YA',
4171               '044F'  => 'ya',
4172               '0433'  => 'g',
4173               '0446'  => 'c',
4174               '04D7'  => 'IO',
4175               '00DD'  => 'Y', # unidecode gets this wrong ?
4176          );
4177
4178foreach my $symbol(keys(%unicode_map))
4179{
4180    if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol}))
4181    {
4182         $no_transliterate_map{$unicode_map{$symbol}} = 1;
4183    }
4184}
4185
4186%ascii_character_map = (
4187            ' ' => '0020',
4188            '!' => '0021',
4189            '"' => '0022',
4190            '#' => '0023',
4191            '$' => '0024',
4192            '%' => '0025',
4193            '&' => '0026',
4194            "'" => '0027',
4195            '(' => '0028',
4196            ')' => '0029',
4197            '*' => '002A',
4198            '+' => '002B',
4199            ',' => '002C',
4200            '-' => '002D',
4201            '.' => '002E',
4202            '/' => '002F',
4203            ':' => '003A',
4204            ';' => '003B',
4205            '<' => '003C',
4206            '=' => '003D',
4207            '>' => '003E',
4208            '?' => '003F',
4209            '@' => '0040',
4210            '[' => '005B',
4211            '\\' => '005C',
4212            ']' => '005D',
4213            '^' => '005E',
4214            '_' => '005F',
4215            '`' => '0060',
4216            '{' => '007B',
4217            '|' => '007C',
4218            '}' => '007D',
4219            '~' => '007E',
4220);
4221
4222%perl_charset_to_html = (
4223              'utf8'       => 'utf-8',
4224              'utf-8-strict'       => 'utf-8',
4225              'ascii'      => 'us-ascii',
4226);
4227
4228%t2h_encoding_aliases = (
4229              'latin1' => 'iso-8859-1',
4230);
4231
4232foreach my $perl_charset (keys(%perl_charset_to_html))
4233{
4234   $t2h_encoding_aliases{$perl_charset} = $perl_charset_to_html{$perl_charset};
4235   $t2h_encoding_aliases{$perl_charset_to_html{$perl_charset}} = $perl_charset_to_html{$perl_charset};
4236}
4237
4238# symbols used for the commands if $USE_ISO is true.
4239%iso_symbols = (
4240         'equiv'     => '&equiv;',
4241         'dots'      => '&hellip;',
4242         'bullet'    => '&bull;',
4243         'result'    => '&rArr;',
4244         'expansion' => '&rarr;',
4245         'arrow'     => '&rarr;',
4246         'point'     => '&lowast;',
4247         "'"         => '&rsquo;',
4248         '`'         => '&lsquo;',
4249        );
4250
4251%stop_paragraph_command = (
4252 'titlefont' => 1,
4253 'insertcopying' => 1
4254);
4255
4256# on bug-texinfo verified that code_style shouldn't be used for anything
4257# else than node.
4258# anyway it doesn't make sense since the section name normally formatted
4259# is used
4260#%format_code_style = (
4261#  'menu_name' => 1,
4262#  'menu_description' => 1
4263#);
4264
4265# not used currently for html, but used in chm.init
4266%numeric_entity_map = ();
4267
4268foreach my $symbol (keys(%unicode_map))
4269{
4270    if ($symbol ne '')
4271    {
4272        $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';';
4273    }
4274}
4275
4276# When the value begins with & the function with that name is used to do the
4277# html. The first argument is the text enclosed within {}, the second is the
4278# style name (which is also the key of the hash)
4279#
4280# Otherwithe the value is the html element used to enclose the text, and if
4281# there is a " the resulting text is also enclosed within `'
4282my %old_style_map = (
4283      'acronym',    '',
4284      'asis',       '',
4285      'b',          'b',
4286      'cite',       'cite',
4287      'clicksequence', '',
4288      'code',       'code',
4289      'command',    'code',
4290      'ctrl',       '&default_ctrl',
4291      'dfn',        'em',
4292      'dmn',        '',
4293      'email',      '&default_email',
4294      'emph',       'em',
4295      'env',        'code',
4296      'file',       '"tt',
4297      'i',          'i',
4298      'kbd',        'kbd',
4299      'key',        'kbd',
4300      'math',       'em',
4301      'option',     '"samp',
4302      'r',          '',
4303      'samp',       '"samp',
4304      'sc',         '&default_sc',
4305      'strong',     'strong',
4306      't',          'tt',
4307      'uref',       '&default_uref',
4308      'url',        '&default_url',
4309      'var',        'var',
4310      'verb',       'tt',
4311      'titlefont',  '&default_titlefont',
4312      'w',          '',
4313     );
4314
4315# default is {'args' => ['normal'], 'attribute' => ''},
4316%style_map = (
4317      'asis',       {},
4318      'b',          {'attribute' => 'b'},
4319      'cite',       {'attribute' => 'cite'},
4320      'clicksequence', {},
4321      'click',      {'function' => \&t2h_default_click_normal},
4322      'code',       {'args' => ['code'], 'attribute' => 'code'},
4323      'command',    {'args' => ['code'], 'attribute' => 'code'},
4324      'ctrl',       {'function' => \&t2h_default_ctrl,'type' => 'simple_style'},
4325      'dfn',        {'attribute' => 'em'},
4326      'dmn',        {},
4327      'email',      {'args' => ['code', 'normal'],
4328                       'function' => \&t2h_default_email,
4329                       'type' => 'simple_style'},
4330      #'email',      {'args' => ['normal', 'normal'],
4331      #                 'function' => \&t2h_default_email},
4332      'emph',       {'attribute' => 'em'},
4333      'env',        {'args' => ['code'], 'attribute' => 'code'},
4334      'file',       {'args' => ['code'], 'attribute' => 'tt', 'quote' => '"'},
4335      'i',          {'attribute' => 'i'},
4336      'slanted',    {'attribute' => 'i'},
4337      'sansserif',  {'attribute' => 'span class="sansserif"'},
4338      'kbd',        {'args' => ['code'], 'attribute' => 'kbd'},
4339      'key',        {'args' => ['code'], 'begin' => '&lt;', 'end' => '&gt;'},
4340      'math',       {'function' => \&t2h_default_math, 'args' => ['math'] },
4341      'option',     {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'},
4342      'r',          {'attribute' => 'span class="roman"'},
4343      'samp',       {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'},
4344#      'sc',         {'function' => \&t2h_default_sc},
4345      'sc',         {'attribute' => 'small'},
4346      'strong',     {'attribute' => 'strong'},
4347      't',          {'attribute' => 'tt'},
4348      'uref',       {'function' => \&t2h_default_uref,
4349                      'args' => ['code', 'normal', 'normal'],
4350                      'type' => 'simple_style' },
4351      #'uref',       {'function' => \&t2h_default_uref,
4352      #                'args' => ['normal', 'normal', 'normal']},
4353      'url',        {'function' => \&t2h_default_uref,
4354                      'args' => ['code', 'normal', 'normal'],
4355                      'type' => 'simple_style'},
4356      'indicateurl', {'args' => ['code'], 'begin' => '&lt;<code>', 'end' => '</code>&gt;','type' => 'simple_style'},
4357      'var',        {'attribute' => 'var'},
4358      'verb',       {'args' => ['code'], 'attribute' => 'tt'},
4359      'titlefont',  {'function' => \&t2h_default_titlefont,
4360            'type' => 'simple_style'},
4361      'w',          {'type' => 'simple_style'},
4362      'hyphenation', {'function' => \&t2h_default_hyphenation, 'args' => ['keep']},
4363     );
4364
4365%command_type = ();
4366
4367foreach my $style (keys(%style_map))
4368{
4369   if (exists($style_map{$style}->{'type'}))
4370   {
4371       $command_type{$style} = $style_map{$style}->{'type'};
4372   }
4373   else
4374   {
4375       $command_type{$style} = 'style';
4376   }
4377}
4378
4379%unicode_diacritical = (
4380       'H'          => '030B',
4381       'ringaccent' => '030A',
4382       "'"          => '0301',
4383       'v'          => '030C',
4384       ','          => '0327',
4385       '^'          => '0302',
4386       'dotaccent'  => '0307',
4387       '`'          => '0300',
4388       '='          => '0304',
4389       '~'          => '0303',
4390       '"'          => '0308',
4391       'udotaccent' => '0323',
4392       'ubaraccent' => '0332',
4393       'u'          => '0306',
4394       'tieaccent'  => '0361',
4395       'ogonek'     => '0328'
4396);
4397
4398%unicode_accents = (
4399    'dotaccent' => { # dot above
4400        'A' => '0226', #C moz-1.2
4401        'a' => '0227', #c moz-1.2
4402        'B' => '1E02',
4403        'b' => '1E03',
4404        'C' => '010A',
4405        'c' => '010B',
4406        'D' => '1E0A',
4407        'd' => '1E0B',
4408        'E' => '0116',
4409        'e' => '0117',
4410        'F' => '1E1E',
4411        'f' => '1E1F',
4412        'G' => '0120',
4413        'g' => '0121',
4414        'H' => '1E22',
4415        'h' => '1E23',
4416        'i' => '0069',
4417        'I' => '0130',
4418        'N' => '1E44',
4419        'n' => '1E45',
4420        'O' => '022E', #Y moz-1.2
4421        'o' => '022F', #v moz-1.2
4422        'P' => '1E56',
4423        'p' => '1E57',
4424        'R' => '1E58',
4425        'r' => '1E59',
4426        'S' => '1E60',
4427        's' => '1E61',
4428        'T' => '1E6A',
4429        't' => '1E6B',
4430        'W' => '1E86',
4431        'w' => '1E87',
4432        'X' => '1E8A',
4433        'x' => '1E8B',
4434        'Y' => '1E8E',
4435        'y' => '1E8F',
4436        'Z' => '017B',
4437        'z' => '017C',
4438    },
4439    'udotaccent' => { # dot below
4440        'A' => '1EA0',
4441        'a' => '1EA1',
4442        'B' => '1E04',
4443        'b' => '1E05',
4444        'D' => '1E0C',
4445        'd' => '1E0D',
4446        'E' => '1EB8',
4447        'e' => '1EB9',
4448        'H' => '1E24',
4449        'h' => '1E25',
4450        'I' => '1ECA',
4451        'i' => '1ECB',
4452        'K' => '1E32',
4453        'k' => '1E33',
4454        'L' => '1E36',
4455        'l' => '1E37',
4456        'M' => '1E42',
4457        'm' => '1E43',
4458        'N' => '1E46',
4459        'n' => '1E47',
4460        'O' => '1ECC',
4461        'o' => '1ECD',
4462        'R' => '1E5A',
4463        'r' => '1E5B',
4464        'S' => '1E62',
4465        's' => '1E63',
4466        'T' => '1E6C',
4467        't' => '1E6D',
4468        'U' => '1EE4',
4469        'u' => '1EE5',
4470        'V' => '1E7E',
4471        'v' => '1E7F',
4472        'W' => '1E88',
4473        'w' => '1E89',
4474        'Y' => '1EF4',
4475        'y' => '1EF5',
4476        'Z' => '1E92',
4477        'z' => '1E93',
4478    },
4479    'ubaraccent' => { # line below
4480        'B' => '1E06',
4481        'b' => '1E07',
4482        'D' => '1E0E',
4483        'd' => '1E0F',
4484        'h' => '1E96',
4485        'K' => '1E34',
4486        'k' => '1E35',
4487        'L' => '1E3A',
4488        'l' => '1E3B',
4489        'N' => '1E48',
4490        'n' => '1E49',
4491        'R' => '1E5E',
4492        'r' => '1E5F',
4493        'T' => '1E6E',
4494        't' => '1E6F',
4495        'Z' => '1E94',
4496        'z' => '1E95',
4497    },
4498    ',' => { # cedilla
4499        'C' => '00C7',
4500        'c' => '00E7',
4501        'D' => '1E10',
4502        'd' => '1E11',
4503        'E' => '0228', #C moz-1.2
4504        'e' => '0229', #c moz-1.2
4505        'G' => '0122',
4506        'g' => '0123',
4507        'H' => '1E28',
4508        'h' => '1E29',
4509        'K' => '0136',
4510        'k' => '0137',
4511        'L' => '013B',
4512        'l' => '013C',
4513        'N' => '0145',
4514        'n' => '0146',
4515        'R' => '0156',
4516        'r' => '0157',
4517        'S' => '015E',
4518        's' => '015F',
4519        'T' => '0162',
4520        't' => '0163',
4521    },
4522    '=' => { # macron
4523        'A' => '0100',
4524        'a' => '0101',
4525        'E' => '0112',
4526        'e' => '0113',
4527        'I' => '012A',
4528        'i' => '012B',
4529        'G' => '1E20',
4530        'g' => '1E21',
4531        'O' => '014C',
4532        'o' => '014D',
4533        'U' => '016A',
4534        'u' => '016B',
4535        'Y' => '0232', #? moz-1.2
4536        'y' => '0233', #? moz-1.2
4537    },
4538    '"' => { # diaeresis
4539        'A' => '00C4',
4540        'a' => '00E4',
4541        'E' => '00CB',
4542        'e' => '00EB',
4543        'H' => '1E26',
4544        'h' => '1E27',
4545        'I' => '00CF',
4546        'i' => '00EF',
4547        'O' => '00D6',
4548        'o' => '00F6',
4549        't' => '1E97',
4550        'U' => '00DC',
4551        'u' => '00FC',
4552        'W' => '1E84',
4553        'w' => '1E85',
4554        'X' => '1E8C',
4555        'x' => '1E8D',
4556        'y' => '00FF',
4557        'Y' => '0178',
4558    },
4559    'u' => { # breve
4560        'A' => '0102',
4561        'a' => '0103',
4562        'E' => '0114',
4563        'e' => '0115',
4564        'G' => '011E',
4565        'g' => '011F',
4566        'I' => '012C',
4567        'i' => '012D',
4568        'O' => '014E',
4569        'o' => '014F',
4570        'U' => '016C',
4571        'u' => '016D',
4572    },
4573    "'" => { # acute
4574        'A' => '00C1',
4575        'a' => '00E1',
4576        'C' => '0106',
4577        'c' => '0107',
4578        'E' => '00C9',
4579        'e' => '00E9',
4580        'G' => '01F4',
4581        'g' => '01F5',
4582        'I' => '00CD',
4583        'i' => '00ED',
4584        'K' => '1E30',
4585        'k' => '1E31',
4586        'L' => '0139',
4587        'l' => '013A',
4588        'M' => '1E3E',
4589        'm' => '1E3F',
4590        'N' => '0143',
4591        'n' => '0144',
4592        'O' => '00D3',
4593        'o' => '00F3',
4594        'P' => '1E54',
4595        'p' => '1E55',
4596        'R' => '0154',
4597        'r' => '0155',
4598        'S' => '015A',
4599        's' => '015B',
4600        'U' => '00DA',
4601        'u' => '00FA',
4602        'W' => '1E82',
4603        'w' => '1E83',
4604        'Y' => '00DD',
4605        'y' => '00FD',
4606        'Z' => '0179',
4607        'z' => '018A',
4608    },
4609    '~' => { # tilde
4610        'A' => '00C3',
4611        'a' => '00E3',
4612        'E' => '1EBC',
4613        'e' => '1EBD',
4614        'I' => '0128',
4615        'i' => '0129',
4616        'N' => '00D1',
4617        'n' => '00F1',
4618        'O' => '00D5',
4619        'o' => '00F5',
4620        'U' => '0168',
4621        'u' => '0169',
4622        'V' => '1E7C',
4623        'v' => '1E7D',
4624        'Y' => '1EF8',
4625        'y' => '1EF9',
4626    },
4627    '`' => { # grave
4628        'A' => '00C0',
4629        'a' => '00E0',
4630        'E' => '00C8',
4631        'e' => '00E8',
4632        'I' => '00CC',
4633        'i' => '00EC',
4634        'N' => '01F8',
4635        'n' => '01F9',
4636        'O' => '00D2',
4637        'o' => '00F2',
4638        'U' => '00D9',
4639        'u' => '00F9',
4640        'W' => '1E80',
4641        'w' => '1E81',
4642        'Y' => '1EF2',
4643        'y' => '1EF3',
4644    },
4645    '^' => { # circumflex
4646        'A' => '00C2',
4647        'a' => '00E2',
4648        'C' => '0108',
4649        'c' => '0109',
4650        'E' => '00CA',
4651        'e' => '00EA',
4652        'G' => '011C',
4653        'g' => '011D',
4654        'H' => '0124',
4655        'h' => '0125',
4656        'I' => '00CE',
4657        'i' => '00EE',
4658        'J' => '0134',
4659        'j' => '0135',
4660        'O' => '00D4',
4661        'o' => '00F4',
4662        'S' => '015C',
4663        's' => '015D',
4664        'U' => '00DB',
4665        'u' => '00FB',
4666        'W' => '0174',
4667        'w' => '0175',
4668        'Y' => '0176',
4669        'y' => '0177',
4670        'Z' => '1E90',
4671        'z' => '1E91',
4672    },
4673    'ringaccent' => { # ring
4674        'A' => '00C5',
4675        'a' => '00E5',
4676        'U' => '016E',
4677        'u' => '016F',
4678        'w' => '1E98',
4679        'y' => '1E99',
4680    },
4681    'v' => { # caron
4682        'A' => '01CD',
4683        'a' => '01CE',
4684        'C' => '010C',
4685        'c' => '010D',
4686        'D' => '010E',
4687        'd' => '010F',
4688        'E' => '011A',
4689        'e' => '011B',
4690        'G' => '01E6',
4691        'g' => '01E7',
4692        'H' => '021E', #K with moz-1.2
4693        'h' => '021F', #k with moz-1.2
4694        'I' => '01CF',
4695        'i' => '01D0',
4696        'K' => '01E8',
4697        'k' => '01E9',
4698        'L' => '013D', #L' with moz-1.2
4699        'l' => '013E', #l' with moz-1.2
4700        'N' => '0147',
4701        'n' => '0148',
4702        'O' => '01D1',
4703        'o' => '01D2',
4704        'R' => '0158',
4705        'r' => '0159',
4706        'S' => '0160',
4707        's' => '0161',
4708        'T' => '0164',
4709        't' => '0165',
4710        'U' => '01D3',
4711        'u' => '01D4',
4712        'Z' => '017D',
4713        'z' => '017E',
4714    },
4715    'H' => { # double acute
4716        'O' => '0150',
4717        'o' => '0151',
4718        'U' => '0170',
4719        'u' => '0171',
4720    },
4721    'ogonek' => {
4722        'A' => '0104',
4723        'a' => '0105',
4724        'E' => '0118',
4725        'e' => '0119',
4726        'I' => '012E',
4727        'i' => '012F',
4728        'U' => '0172',
4729        'u' => '0173',
4730        'O' => '01EA',
4731        'o' => '01EB',
4732    },
4733);
4734
4735%transliterate_accent_map = ();
4736foreach my $command (keys(%unicode_accents))
4737{
4738    foreach my $letter(keys (%{$unicode_accents{$command}}))
4739    {
4740        $transliterate_accent_map{$unicode_accents{$command}->{$letter}}
4741            = $letter
4742          unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}}));
4743    }
4744}
4745
4746%special_accents = (
4747      'ringaccent' => 'aA',
4748      "'"          => 'aeiouyAEIOUY',
4749      ','          => 'cC',
4750      '^'          => 'aeiouAEIOU',
4751      '`'          => 'aeiouAEIOU',
4752      '~'          => 'nNaoAO',
4753      '"'          => 'aeiouyAEIOU',
4754# according to http://www2.lib.virginia.edu/small/vhp/download/ISO.txt
4755# however this doesn't seems to work in firefox
4756#      'ogonek'     => 'aeiuAEIU',
4757);
4758
4759foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
4760{
4761     $style_map{$accent_command} = { 'function' => \&t2h_default_accent };
4762     $old_style_map{$accent_command} = '&default_accent';
4763     $style_map_texi{$accent_command} = { 'function' => \&t2h_default_ascii_accent };
4764}
4765
4766sub default_accent($$)
4767{
4768    my $text = shift;
4769    my $accent = shift;
4770    return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
4771    return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
4772    return $text . '&lt;' if ($accent eq 'v');
4773    return ascii_accents($text, $accent);
4774}
4775
4776sub t2h_default_accent($$)
4777{
4778    my $accent = shift;
4779    my $args = shift;
4780
4781    my $text = $args->[0];
4782
4783    return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
4784    return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
4785    return $text . '&lt;' if ($accent eq 'v');
4786# FIXME here there could be a conversion to the character in the right
4787# encoding, like
4788#    if ($USE_UNICODE and defined($OUT_ENCODING) and $OUT_ENCODING ne ''
4789#        and exists($unicode_accents{$accent}) and  exists($unicode_accents{$accent}->{$text}))
4790#    {
4791#          my $encoded_char =  Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET);
4792#          return $encoded_char if ($encoded_char ne '');
4793#    }
4794    if ($USE_NUMERIC_ENTITY)
4795    {
4796        if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text}))
4797        {
4798             return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';');
4799        }
4800    }
4801    return ascii_accents($text, $accent);
4802}
4803
4804sub ascii_accents($$)
4805{
4806    my $text = shift;
4807    my $accent = shift;
4808    return $text if ($accent eq 'dotless');
4809    return $text . "''" if ($accent eq 'H');
4810    return $text . '.' if ($accent eq 'dotaccent');
4811    return $text . '*' if ($accent eq 'ringaccent');
4812    return $text . '[' if ($accent eq 'tieaccent');
4813    return $text . '(' if ($accent eq 'u');
4814    return $text . '_' if ($accent eq 'ubaraccent');
4815    return '.' . $text  if ($accent eq 'udotaccent');
4816    return $text . '<' if ($accent eq 'v');
4817    return $text . ';' if ($accent eq 'ogonek');
4818    return $text . $accent if (defined($accent_map{$accent}));
4819}
4820
4821sub default_sc($$)
4822{
4823    return '<small>' . uc($_[0]) . '</small>';
4824}
4825
4826# now unused, upcasing is done in normal_text
4827sub t2h_default_sc($$$)
4828{
4829    shift;
4830    my $args = shift;
4831    return '<small>' . uc($args->[0]) . '</small>';
4832}
4833
4834sub default_ctrl($$)
4835{
4836   return "^$_[0]";
4837}
4838
4839# obsolete, no warning, but noop
4840sub t2h_default_ctrl($$$)
4841{
4842    shift;
4843    my $args = shift;
4844    #return "^$args->[0]";
4845    return "$args->[0]";
4846}
4847
4848sub default_sc_pre($$)
4849{
4850    return uc($_[0]);
4851}
4852
4853# now unused, upcasing is done in normal_text
4854sub t2h_default_sc_pre($$$)
4855{
4856    shift;
4857    my $args = shift;
4858    return uc($args->[0]);
4859}
4860
4861sub default_titlefont($$)
4862{
4863    return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/);
4864    return '';
4865}
4866
4867# Avoid adding h1 if the text is empty
4868sub t2h_default_titlefont($$$)
4869{
4870    shift;
4871    my $args = shift;
4872    return "<h1 class=\"titlefont\">$args->[0]</h1>" if ($args->[0] =~ /\S/);
4873    return '';
4874}
4875
4876# At some point in time (before 4.7?) according to the texinfo
4877# manual, url shouldn't lead to a link but rather be formatted
4878# like text. It is now what indicateurl do, url is the same that
4879# uref with one arg. If we did like makeinfo did it would have been
4880#sub url($$)
4881#{
4882#    return '&lt;<code>' . $_[0] . '</code>&gt;';
4883#}
4884#
4885# This is unused, t2h_default_uref is used instead
4886sub t2h_default_url ($$)
4887{
4888    shift;
4889    my $args = shift;
4890    my $url = shift @$args;
4891    #$url =~ s/\s*$//;
4892    #$url =~ s/^\s*//;
4893    $url = main::normalise_space($url);
4894    return '' unless ($url =~ /\S/);
4895    return &$anchor('', $url, $url);
4896}
4897
4898sub default_url ($$)
4899{
4900    my $url = shift;
4901    my $command = shift;
4902    $url =~ s/\s*$//;
4903    $url =~ s/^\s*//;
4904    return '' unless ($url =~ /\S/);
4905    return &$anchor('', $url, $url);
4906}
4907
4908sub default_uref($$)
4909{
4910    my $arg = shift;
4911    my $command = shift;
4912    my ($url, $text, $replacement);
4913    ($url, $text, $replacement) = split /,\s*/, $arg;
4914    $url =~ s/\s*$//;
4915    $url =~ s/^\s*//;
4916    $text = $replacement if (defined($replacement));
4917    $text = $url unless ($text);
4918    return $text if ($url eq '');
4919    return &$anchor('', $url, $text);
4920}
4921
4922sub t2h_default_uref($$)
4923{
4924    shift;
4925    my $args = shift;
4926    my $url = shift @$args;
4927    my $text = shift @$args;
4928    my $replacement = shift @$args;
4929    #$url =~ s/\s*$//;
4930    #$url =~ s/^\s*//;
4931    $url = main::normalise_space($url);
4932    $replacement = '' if (!defined($replacement));
4933    $replacement = main::normalise_space($replacement);
4934    $text = '' if (!defined($text));
4935    $text = main::normalise_space($text);
4936    $text = $replacement if ($replacement ne '');
4937    $text = $url unless ($text ne '');
4938    return $text if ($url eq '');
4939    return &$anchor('', $url, $text);
4940}
4941
4942sub t2h_default_math($$)
4943{
4944    shift;
4945    my $args = shift;
4946    my $text = shift @$args;
4947#print STDERR "t2h_default_math $text\n";
4948    $text =~ s/[{}]//g;
4949#    $text =~ s/\@\\/\\/g;
4950    return "<em>$text</em>";
4951}
4952
4953sub default_email($$)
4954{
4955    my $arg = shift;
4956    my $command = shift;
4957    my ($mail, $text);
4958    ($mail, $text) = split /,\s*/, $arg;
4959    $mail =~ s/\s*$//;
4960    $mail =~ s/^\s*//;
4961    $text = $mail unless ($text);
4962    return $text if ($mail eq '');
4963    return &$anchor('', "mailto:$mail", $text);
4964}
4965
4966sub t2h_default_email($$)
4967{
4968    my $command = shift;
4969    my $args = shift;
4970    my $mail = shift @$args;
4971    my $text = shift @$args;
4972    $mail = main::normalise_space($mail);
4973    #$mail =~ s/\s*$//;
4974    #$mail =~ s/^\s*//;
4975    $text = $mail unless (defined($text) and ($text ne ''));
4976    $text = main::normalise_space($text);
4977    return $text if ($mail eq '');
4978    return &$anchor('', "mailto:$mail", $text);
4979}
4980
4981sub t2h_default_click_normal($$$)
4982{
4983    return t2h_default_click('normal', @_);
4984}
4985
4986sub t2h_default_click_pre($$$)
4987{
4988    return t2h_default_click('pre', @_);
4989}
4990
4991sub t2h_default_click_texi($$$)
4992{
4993    return t2h_default_click('texi', @_);
4994}
4995
4996sub t2h_default_click($$$$$)
4997{
4998    my $context = shift;
4999    my $command = shift;
5000    my $args = shift;
5001    my $arg = shift @$args;
5002    my $cmd = $Texi2HTML::THISDOC{'clickstyle'};
5003    $cmd = 'arrow' if (!defined($cmd) or ($cmd eq ''));
5004
5005    my $hash = \%things_map;
5006    if ($context eq 'pre')
5007    {
5008        $hash = \%pre_map;
5009    }
5010    elsif ($context eq 'texi')
5011    {
5012        $hash = \%texi_map;
5013    }
5014    return $hash->{$cmd} . $arg if (exists($hash->{$cmd}));
5015    return $arg;
5016}
5017
5018sub t2h_default_hyphenation($$)
5019{
5020    my $command = shift;
5021    my $args = shift;
5022    my $text = shift @$args;
5023    $text =~ s/^\s*//;
5024    $text =~ s/\s*$//;
5025    my @list = split /\s+/, $text;
5026    foreach my $entry (@list)
5027    {
5028         my $word = $entry;
5029         $word =~ s/-//g;
5030         $Texi2HTML::THISDOC{'hyphenation'}->{$word} = $entry;
5031    }
5032}
5033
5034sub t2h_default_ascii_accent($$$$)
5035{
5036    my $accent = shift;
5037    my $args = shift;
5038
5039    my $text = $args->[0];
5040    return ascii_accents($text, $accent);
5041}
5042
5043sub t2h_default_no_texi_email
5044{
5045    my $command = shift;
5046    my $args = shift;
5047    my $mail = shift @$args;
5048    my $text = shift @$args;
5049    $mail = main::normalise_space($mail);
5050    #$mail =~ s/\s*$//;
5051    #$mail =~ s/^\s*//;
5052    return $text if (defined($text) and ($text ne ''));
5053    return $mail;
5054}
5055
5056sub t2h_default_no_texi_image($$$$)
5057{
5058    my $command = shift;
5059    my $args = shift;
5060    #my $text = $args->[0];
5061    #$text = main::normalise_space($text);
5062    #my @args = split (/\s*,\s*/, $text);
5063    my $file = $args->[0];
5064    $file =~ s/^\s*//;
5065    $file =~ s/\s*$//;
5066    return main::substitute_line($file, {'remove_texi' => 1, 'code_style' => 1});
5067}
5068
5069sub t2h_default_no_texi_acronym_like($$)
5070{
5071    my $command = shift;
5072    my $args = shift;
5073    my $acronym_texi = $args->[0];
5074    return (main::remove_texi($acronym_texi));
5075}
5076
5077sub t2h_remove_command($$$$)
5078{
5079    return '';
5080}
5081
5082# This is used for style in preformatted sections
5083my %old_style_map_pre = %old_style_map;
5084$old_style_map_pre{'sc'} = '&default_sc_pre';
5085$old_style_map_pre{'titlefont'} = '';
5086
5087foreach my $command (keys(%style_map))
5088{
5089    $style_map_pre{$command} = {};
5090    $style_map_texi{$command} = {} if (!exists($style_map_texi{$command}));
5091    $style_map_texi{$command}->{'args'} = $style_map{$command}->{'args'}
5092        if (exists($style_map{$command}->{'args'}));
5093 #print STDERR "COMMAND $command";
5094
5095    foreach my $key (keys(%{$style_map{$command}}))
5096    {
5097        $style_map_pre{$command}->{$key} = $style_map{$command}->{$key};
5098    }
5099}
5100
5101#$style_map_pre{'sc'}->{'function'} = \&t2h_default_sc_pre;
5102$style_map_pre{'sc'} = {};
5103$style_map_pre{'titlefont'} = {};
5104$style_map_pre{'click'}->{'function'} = \&t2h_default_click_pre;
5105
5106#$style_map_texi{'sc'}->{'function'} = \&t2h_default_sc_pre;
5107$style_map_texi{'sc'} = {};
5108$style_map_texi{'email'}->{'function'} = \&t2h_default_no_texi_email;
5109$style_map_texi{'click'}->{'function'} = \&t2h_default_click_texi;
5110
5111####### special styles. You shouldn't need to change them
5112%special_style = (
5113           #'xref'      => ['keep','normal','normal','keep','normal'],
5114           'xref'         => { 'args' => ['keep','keep','keep','keep','keep'],
5115               'function' => \&main::do_xref },
5116           'ref'         => { 'args' => ['keep','keep','keep','keep','keep'],
5117               'function' => \&main::do_xref },
5118           'pxref'         => { 'args' => ['keep','keep','keep','keep','keep'],
5119               'function' => \&main::do_xref },
5120           'inforef'      => { 'args' => ['keep','keep','keep'],
5121               'function' => \&main::do_xref },
5122           'image'        => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_image },
5123           'anchor'       => { 'args' => ['keep'], 'function' => \&main::do_anchor_label },
5124           'footnote'     => { 'args' => ['keep'], 'function' => \&main::do_footnote },
5125           'shortcaption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
5126           'caption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
5127           'acronym',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
5128           'abbr',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
5129);
5130
5131# @image is replaced by the first arg in strings
5132$style_map_texi{'image'} = { 'args' => ['keep','keep','keep','keep','keep'],
5133       'function' => \&t2h_default_no_texi_image };
5134
5135$style_map_texi{'acronym'} = { 'args' => ['keep','keep'],
5136       'function' => \&t2h_default_no_texi_acronym_like };
5137$style_map_texi{'abbr'} = { 'args' => ['keep','keep'],
5138       'function' => \&t2h_default_no_texi_acronym_like };
5139
5140foreach my $special (keys(%special_style))
5141{
5142    $style_map{$special} = $special_style{$special}
5143          unless (defined($style_map{$special}));
5144    $style_map_pre{$special} = $special_style{$special}
5145          unless (defined($style_map_pre{$special}));
5146    $style_map_texi{$special} = { 'args' => ['keep'],
5147        'function' => \&t2h_remove_command }
5148          unless (defined($style_map_texi{$special}));
5149}
5150####### end special styles.
5151
5152
5153#foreach my $command (keys(%style_map))
5154#{
5155#    print STDERR "STYLE_MAP_TEXI $command($style_map_texi{$command}) ";
5156#    print STDERR "ARGS $style_map_texi{$command}->{'args'} " if (defined($style_map_texi{$command}->{'args'}));
5157#    print STDERR "FUN $style_map_texi{$command}->{'function'} " if (defined($style_map_texi{$command}->{'function'}));
5158#    print STDERR "\n";
5159#}
5160
5161# uncomment to use the old interface
5162#%style_map = %old_style_map;
5163#%style_map_pre = %old_style_map_pre;
5164
5165%simple_format_simple_map_texi = %simple_map_pre;
5166%simple_format_texi_map = %pre_map;
5167%simple_format_style_map_texi = ();
5168
5169foreach my $command (keys(%style_map_texi))
5170{
5171    #$simple_format_style_map_texi{$command} = {};
5172    foreach my $key (keys (%{$style_map_texi{$command}}))
5173    {
5174    #print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n";
5175        $simple_format_style_map_texi{$command}->{$key} =
5176             $style_map_texi{$command}->{$key};
5177    }
5178    $simple_format_style_map_texi{$command} = {} if (!defined($simple_format_style_map_texi{$command}));
5179}
5180
5181foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
5182{
5183#    $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal'];
5184    $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent;
5185}
5186
5187# regions expanded or not depending on the value of this hash.
5188# @EXPAND sets entries in this hash, and you should better use
5189# @EXPAND unless you know what you are doing.
5190%texi_formats_map = (
5191     'iftex' => 0,
5192     'ignore' => 0,
5193     'menu' => 0,
5194     'ifplaintext' => 0,
5195     'ifinfo' => 0,
5196     'ifxml' => 0,
5197     'ifhtml' => 0,
5198     'ifdocbook' => 0,
5199     'html' => 0,
5200     'tex' => 0,
5201     'xml' => 0,
5202     'docbook' => 0,
5203     'titlepage' => 1,
5204     'documentdescription' => 1,
5205     'copying' => 1,
5206     'ifnothtml' => 1,
5207     'ifnottex' => 1,
5208     'ifnotplaintext' => 1,
5209     'ifnotinfo' => 1,
5210     'ifnotxml' => 1,
5211     'ifnotdocbook' => 1,
5212     'direntry' => 0,
5213     'verbatim' => 'raw',
5214     'ifclear' => 'value',
5215     'ifset' => 'value' ,
5216     );
5217
5218%format_map = (
5219#       'quotation'   =>  'blockquote',
5220       # lists
5221#       'itemize'     =>  'ul',
5222       'enumerate'   =>  'ol',
5223#       'multitable'  =>  'table',
5224       'table'       =>  'dl compact="compact"',
5225       'vtable'      =>  'dl compact="compact"',
5226       'ftable'      =>  'dl compact="compact"',
5227       'group'       =>  '',
5228#       'detailmenu'  =>  '',
5229       );
5230
5231%special_list_commands = (
5232       'table'        =>  {},
5233       'vtable'       =>  {},
5234       'ftable'       =>  {},
5235       'itemize'      =>  { 'bullet'  => '' }
5236       );
5237
5238%inter_item_commands = (
5239  'c' => 1,
5240  'comment' => 1,
5241  'cindex' => 1
5242);
5243#
5244# texinfo format to align attribute of paragraphs
5245#
5246
5247%paragraph_style = (
5248      'center'     => 'center',
5249      'flushleft'  => 'left',
5250      'flushright' => 'right',
5251      );
5252
5253# an eval of these $complex_format_map->{what}->{'begin'} yields beginning
5254# an eval of these $complex_format_map->{what}->{'end'} yields end
5255# $EXAMPLE_INDENT_CELL and SMALL_EXAMPLE_INDENT_CELL can be usefull here
5256$complex_format_map =
5257{
5258 'example' =>
5259 {
5260  'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
5261  'end' => q{"</td></tr></table>\n"},
5262  'style' => 'code',
5263 },
5264 'smallexample' =>
5265 {
5266  'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
5267  'end' => q{"</td></tr></table>\n"},
5268  'style' => 'code',
5269 },
5270 'display' =>
5271 {
5272  'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
5273  'end' => q{"</td></tr></table>\n"},
5274 },
5275 'smalldisplay' =>
5276 {
5277  'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
5278  'end' => q{"</td></tr></table>\n"},
5279 }
5280};
5281
5282# format shouldn't narrow the margins
5283
5284$complex_format_map->{'lisp'} =  $complex_format_map->{'example'};
5285$complex_format_map->{'smalllisp'} = $complex_format_map->{'smallexample'};
5286$complex_format_map->{'format'} = $complex_format_map->{'display'};
5287$complex_format_map->{'smallformat'} = $complex_format_map->{'smalldisplay'};
5288
5289%def_map = (
5290    # basic commands
5291    'deffn', [ 'f', 'category', 'name', 'arg' ],
5292    'defvr', [ 'v', 'category', 'name' ],
5293    'deftypefn', [ 'f', 'category', 'type', 'name', 'argtype' ],
5294    'deftypeop', [ 'f', 'category', 'class' , 'type', 'name', 'argtype' ],
5295    'deftypevr', [ 'v', 'category', 'type', 'name' ],
5296    'defcv', [ 'v', 'category', 'class' , 'name' ],
5297    'deftypecv', [ 'v', 'category', 'class' , 'type', 'name' ],
5298    'defop', [ 'f', 'category', 'class' , 'name', 'arg' ],
5299    'deftp', [ 't', 'category', 'name', 'argtype' ],
5300    # shortcuts
5301    # FIXME i18n
5302    'defun', 'deffn Function',
5303    'defmac', 'deffn Macro',
5304    'defspec', 'deffn {Special Form}',
5305    'defvar', 'defvr Variable',
5306    'defopt', 'defvr {User Option}',
5307    'deftypefun', 'deftypefn {Function}',
5308    'deftypevar', 'deftypevr Variable',
5309    'defivar', 'defcv {Instance Variable}',
5310    'deftypeivar', 'deftypecv {Instance Variable}',
5311    'defmethod', 'defop Method',
5312    'deftypemethod', 'deftypeop Method',
5313         );
5314
5315$def_always_delimiters = "()[]";
5316$def_in_type_delimiters = ",;";
5317$def_argument_separator_delimiters = "()[],";
5318
5319# basic x commands
5320foreach my $key (keys(%def_map))
5321{
5322    $def_map{$key . 'x'} = $def_map{$key};
5323}
5324
5325#
5326# miscalleneous commands
5327#
5328# Depending on the value, the command arg or spaces following the command
5329#     are handled differently:
5330#
5331# the value is a reference on a hash.
5332# the hash keys are
5333#    'arg'  if the value is 'line' then the remaining of the line is the arg
5334#           if it is a number it is the number of args (separated by spaces)
5335#    'skip' if the value is 'line' then the remaining of the line is skipped
5336#           if the value is 'space' space but no newline is skipped
5337#           if the value is 'whitespace' space is skipped
5338#           if the value is 'linewhitespace' space is skipped if there are
5339#                 only spaces remaining on the line
5340#           if the value is 'linespace' space but no newline is skipped if
5341#                 there are only spaces remaining on the line
5342#    'keep' if true the args and the macro are kept, otherwise the macro
5343#          args and skipped stuffs are removed
5344%misc_command = (
5345        'bye' => {'skip' => 'line'}, # no arg
5346        # set, clear
5347        'set' => {'skip' => 'line'}, # special arg
5348        'clear' => {'skip' => 'line'}, # special arg
5349        # comments
5350        'comment' => {'arg' => 'line'},
5351        'c' => {'arg' => 'line'},
5352
5353        # not needed for formatting
5354        'raisesections' => {'skip' => 'line'},  # no arg
5355        'lowersections' => {'skip' => 'line'}, # no arg
5356        'contents' => {}, # no arg
5357        'shortcontents' => {}, # no arg
5358        'summarycontents'=> {}, # no arg
5359        'setcontentsaftertitlepage' => {}, # no arg
5360        'setshortcontentsaftertitlepage' => {}, # no arg
5361#        'detailmenu' => {'skip' => 'whitespace'}, # no arg
5362#        'end detailmenu' => {'skip' => 'whitespace'}, # no arg
5363        'clickstyle' => {'skip' => 'line'}, # arg should be an @-command
5364        # in preamble
5365        'novalidate' => {}, # no arg
5366        'dircategory'=> {'arg' => 'line'}, # line. Position with regard
5367                         # with direntry is significant
5368        'pagesizes' => {'skip' => 'line', 'arg' => 'line'}, # can have 2 args
5369                                 # or one? 200mm,150mm 11.5in
5370        'finalout' => {}, # no arg
5371        'paragraphindent' => {'skip' => 'line', 'arg' => 1}, # arg none asis
5372                             # or a number and forbids anything else on the line
5373        'firstparagraphindent' => {'skip' => 'line', 'arg' => 1}, # none insert
5374        'frenchspacing' => {'arg' => 1}, # on off
5375        'fonttextsize' => {'arg' => 1}, # 10 11
5376        'allowcodebreaks' => {'arg' => 1}, # false or true
5377        'exampleindent' => {'skip' => 'line', 'arg' => 1}, # asis or a number
5378        'footnotestyle'=> {'skip' => 'line', 'arg' => 1}, # end and separate
5379                                 # and nothing else on the line
5380        'afourpaper' => {'skip' => 'line'}, # no arg
5381        'afivepaper' => {'skip' => 'line'}, # no arg
5382        'afourlatex' => {'skip' => 'line'}, # no arg
5383        'afourwide' => {'skip' => 'line'}, # no arg
5384        'headings'=> {'skip' => 'line', 'arg' => 1},
5385                    #off on single double singleafter doubleafter
5386                    # interacts with setchapternewpage
5387        'setchapternewpage' => {'skip' => 'line', 'arg' => 1}, # off on odd
5388        'everyheading' => {'arg' => 'line'},
5389        'everyfooting' => {'arg' => 'line'},
5390        'evenheading' => {'arg' => 'line'},
5391        'evenfooting' => {'arg' => 'line'},
5392        'oddheading' => {'arg' => 'line'},
5393        'oddfooting' => {'arg' => 'line'},
5394        'smallbook' => {'skip' => 'line'}, # no arg
5395        'setfilename' => {'arg' => 'line'},
5396        #'shorttitle' => {'arg' => 'line', 'texi' => 1},
5397        #'shorttitlepage' => {'arg' => 'line', 'texi' => 1},
5398        #'settitle' => {'arg' => 'line', 'texi' => 1},
5399        #'author' => {'arg' => 'line', 'texi' => 1},
5400        #'subtitle' => {'arg' => 'line', 'texi' => 1},
5401        #'title' => {'arg' => 'line', 'texi' => 1},
5402        'shorttitle' => {'arg' => 'line'},
5403        'shorttitlepage' => {'arg' => 'line'},
5404        'settitle' => {'arg' => 'line'},
5405        'author' => {'arg' => 'line'},
5406        'subtitle' => {'arg' => 'line'},
5407        'title' => {'arg' => 'line'},
5408        'syncodeindex' => {'skip' => 'linespace', 'arg' => 2},
5409                          # args are index identifiers
5410        'synindex' => {'skip' => 'linespace', 'arg' => 2},
5411        'defindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
5412        'defcodeindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
5413        'documentlanguage' => {'skip' => 'whitespace', 'arg' => 1},
5414                                                       # language code arg
5415        'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code
5416                                                        #example distinct
5417        'everyheadingmarks' => {'skip' => 'whitespace', 'arg' => 1}, # top bottom
5418                                                        #makeinfo ignore line
5419        'everyfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
5420        'evenheadingmarks' => {'skip' => 'whitespace', 'arg' => 1},
5421        'oddheadingmarks' => {'skip' => 'whitespace', 'arg' => 1},
5422        'evenfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
5423        'oddfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
5424        'sp' => {'skip' => 'whitespace', 'arg' => 1}, # no arg
5425                                    # at the end of line or a numerical arg
5426        # formatting
5427        'page' => {}, # no arg (pagebreak)
5428        'refill' => {}, # no arg (obsolete, to be ignored)
5429        'noindent' => {'skip' => 'whitespace'}, # no arg
5430        'indent' => {'skip' => 'whitespace'},
5431        'need' => {'skip' => 'line', 'arg' => 1}, # one numerical/real arg
5432        'exdent' => {'skip' => 'space'},
5433        # not valid for info (should be in @iftex)
5434        'vskip' => {'arg' => 'line'}, # arg line in TeX
5435        'cropmarks' => {}, # no arg
5436        # miscalleneous
5437        'verbatiminclude'=> {'skip' => 'line'},
5438        'documentencoding' => {'arg' => 1}, # makeinfo ignore the whole line
5439        # ???
5440        'filbreak' => {},
5441        # obsolete @-commands
5442        'quote-arg' => {},
5443        'allow-recursion' => {},
5444     );
5445my %misc_command_old = (
5446        # not needed for formatting
5447        'raisesections', 'line',  # no arg
5448        'lowersections', 'line', # no arg
5449        'contents', 1, # no arg
5450        'shortcontents', 1, # no arg
5451        'summarycontents', 1, # no arg
5452        'detailmenu', 'whitespace', # no arg
5453        'end detailmenu', 'whitespace', # no arg
5454        #'end detailmenu', 1, # no arg
5455        'novalidate', 1, # no arg
5456        'bye', 'line', # no arg
5457        # comments
5458        'comment', 'line',
5459        'c', 'line',
5460        # in preamble
5461        'dircategory', 'line', # line. Position with regard with direntry is
5462                               # significant
5463        'pagesizes', 'line arg2', # can have 2 args
5464        'finalout', 1, # no arg
5465        'paragraphindent', 'line arg1', # in fact accepts only none asis
5466                             # or a number and forbids anything else on the line
5467        'firstparagraphindent', 'line arg1', # in fact accepts only none insert
5468        'exampleindent', 'line arg1', # in fact accepts only asis or a number
5469        'footnotestyle', 'line arg1', # in fact accepts only end and separate
5470                                 # and nothing else on the line
5471        'afourpaper', 'line', # no arg
5472        'afourlatex', 'line', # no arg
5473        'afourwide', 'line',  # no arg
5474        'headings', 'line', # one arg, possibilities are
5475                    #off on single double singleafter doubleafter
5476                    # interacts with setchapternewpage
5477        'setchapternewpage', 'line', # no arg
5478        'everyheading', 'line',
5479        'everyfooting', 'line',
5480        'evenheading', 'line',
5481        'evenfooting', 'line',
5482        'oddheading', 'line',
5483        'oddfooting', 'line',
5484        'smallbook', 'line', # no arg
5485        'setfilename', 'line',
5486        'shorttitle', 'linetexi',
5487        'shorttitlepage', 'linetexi',
5488        'settitle', 'linetexi',
5489        'author', 'linetexi',
5490        'subtitle', 'linetexi',
5491        'title','linetexi',
5492        'syncodeindex','linespace arg2', # args are
5493        'synindex','linespace arg2',
5494        'defindex', 'line arg1', # one identifier arg
5495        'defcodeindex', 'line arg1', # one identifier arg
5496        'documentlanguage', 'whitespace arg1', # one language code arg
5497        'kbdinputstyle', 'whitespace arg1', # one arg within
5498                                 #code example distnct
5499        'sp', 'whitespace arg1', # no arg at the en of line or a numerical arg
5500        # formatting
5501        'page', 1, # no arg (pagebreak)
5502        'refill', 1, # no arg (obsolete, to be ignored))
5503        'noindent', 'space', # no arg
5504        'need', 'line arg1', # one numerical/real arg
5505        'exdent', 'space',
5506        # not valid for info (should be in @iftex)
5507        'vskip', 'line', # arg line in TeX
5508        'cropmarks', 1, # no arg
5509        # miscalleneous
5510        'verbatiminclude', 'line',
5511        'documentencoding', 'arg1',
5512        # ???
5513        'filbreak', 1,
5514     );
5515
5516%format_in_paragraph = (
5517        'html'  => 1,
5518);
5519# map mapping css specification to style
5520
5521%css_map =
5522     (
5523         'ul.toc'                 => "$NO_BULLET_LIST_STYLE",
5524         'pre.menu-comment'       => "$MENU_PRE_STYLE",
5525         'pre.menu-preformatted'  => "$MENU_PRE_STYLE",
5526         'a.summary-letter'       => 'text-decoration: none',
5527         'a:link'                 => 'color: #0000e0', ###GAMBIT### added
5528         'a:visited'              => 'color: #0000e0', ###GAMBIT### added
5529         'blockquote.smallquotation' => 'font-size: smaller',
5530#         'pre.display'            => 'font-family: inherit',
5531#         'pre.smalldisplay'       => 'font-family: inherit; font-size: smaller',
5532         'pre.display'            => 'font-family: serif',
5533         'pre.smalldisplay'       => 'font-family: serif; font-size: smaller',
5534         'pre.smallexample'       => 'font-size: smaller',
5535         'span.sansserif'         => 'font-family:sans-serif; font-weight:normal;',
5536         'span.roman'         => 'font-family:serif; font-weight:normal;'
5537     );
5538
5539$css_map{'pre.format'} = $css_map{'pre.display'};
5540$css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'};
5541$css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'};
5542
5543# The command_handler arrays are for commands formatted externally.
5544# The function references in @command_handler_init are called
5545# before the second pass, before the @-commands text collection.
5546# Those in @command_handler_process are called between the second pass
5547# and the third pass, after collection of @-commands text and before their
5548# expansion.
5549# Those in @command_handler_process are called after the third pass,
5550# after the document generation.
5551@command_handler_init = ();
5552@command_handler_process = ();
5553@command_handler_finish = ();
5554
5555# the keys of %command_handler are @-command names and the value
5556# is a hash reference with the following keys:
5557# 'init'          function reference used to collect the @-command text
5558# 'expand'        function reference used when expanding the @-command text
5559%command_handler = ();
5560
5561
5562# formatting functions
5563
5564$anchor            = \&t2h_default_anchor;
5565$def_item          = \&t2h_default_def_item;
5566$def               = \&t2h_default_def;
5567$menu_command      = \&t2h_default_menu_command;
5568$menu_link         = \&t2h_default_menu_link;
5569#$menu_comment      = \&t2h_default_menu_comment;
5570$menu_description  = \&t2h_default_menu_description;
5571#$simple_menu_link  = \&t2h_default_simple_menu_link;
5572$external_ref      = \&t2h_default_external_ref;
5573$external_href     = \&t2h_default_external_href;
5574$internal_ref      = \&t2h_default_internal_ref;
5575$table_item        = \&t2h_default_table_item;
5576$table_line        = \&t2h_default_table_line;
5577$table_list        = \&t2h_default_table_list;
5578$row               = \&t2h_default_row;
5579$cell              = \&t2h_default_cell;
5580$list_item         = \&t2h_default_list_item;
5581$comment           = \&t2h_default_comment;
5582$def_line          = \&t2h_default_def_line;
5583$def_line_no_texi  = \&t2h_default_def_line_no_texi;
5584$raw               = \&t2h_default_raw;
5585$raw_no_texi       = \&t2h_default_raw_no_texi;
5586$heading           = \&t2h_default_heading;
5587$element_heading   = \&t2h_default_element_heading;
5588$heading_no_texi   = \&t2h_default_heading_no_texi;
5589$paragraph         = \&t2h_default_paragraph;
5590$preformatted      = \&t2h_default_preformatted;
5591$foot_line_and_ref = \&t2h_default_foot_line_and_ref;
5592$foot_section      = \&t2h_default_foot_section;
5593$image_files       = \&t2h_default_image_files;
5594$image             = \&t2h_default_image;
5595$address           = \&t2h_default_address;
5596$index_entry_label = \&t2h_default_index_entry_label;
5597$index_summary     = \&t2h_default_index_summary;
5598#$summary_letter    = \&t2h_default_summary_letter;
5599$index_entry       = \&t2h_default_index_entry;
5600$index_entry_command = \&t2h_default_index_entry_command;
5601$index_letter      = \&t2h_default_index_letter;
5602#$printindex       = \&t2h_default_printindex;
5603$print_index       = \&t2h_default_print_index;
5604$protect_text      = \&t2h_default_protect_text;
5605$normal_text       = \&t2h_default_normal_text;
5606$complex_format    = \&t2h_default_complex_format;
5607$cartouche         = \&t2h_default_cartouche;
5608$sp                = \&t2h_default_sp;
5609$definition_category      = \&t2h_default_definition_category;
5610$definition_index_entry   = \&t2h_default_definition_index_entry;
5611$copying_comment          = \&t2h_default_copying_comment;
5612$documentdescription      = \&t2h_default_documentdescription;
5613$index_summary_file_entry = \&t2h_default_index_summary_file_entry;
5614$index_summary_file_end   = \&t2h_default_index_summary_file_end;
5615$index_summary_file_begin = \&t2h_default_index_summary_file_begin;
5616$empty_line               = \&t2h_default_empty_line;
5617$unknown                  = \&t2h_default_unknown;
5618$unknown_style            = \&t2h_default_unknown_style;
5619$caption_shortcaption     = \&t2h_default_caption_shortcaption;
5620$caption_shortcaption_command  = \&t2h_default_caption_shortcaption_command;
5621$float                     = \&t2h_default_float;
5622$listoffloats             = \&t2h_default_listoffloats;
5623$listoffloats_entry       = \&t2h_default_listoffloats_entry;
5624$listoffloats_caption     = \&t2h_default_listoffloats_caption;
5625$listoffloats_float_style = \&t2h_default_listoffloats_float_style;
5626$listoffloats_style       = \&t2h_default_listoffloats_style;
5627$acronym_like             = \&t2h_default_acronym_like;
5628$quotation                = \&t2h_default_quotation;
5629$quotation_prepend_text   = \&t2h_default_quotation_prepend_text;
5630$paragraph_style_command  = \&t2h_default_paragraph_style_command;
5631$heading_texi             = \&t2h_default_heading_texi;
5632$index_element_heading_texi = \&t2h_default_index_element_heading_texi;
5633$element_label              = \&t2h_default_element_label;
5634$misc_element_label         = \&t2h_default_misc_element_label;
5635$anchor_label               = \&t2h_default_anchor_label;
5636$preserve_misc_command      = \&t2h_default_preserve_misc_command;
5637$format_list_item_texi      = \&t2h_default_format_list_item_texi;
5638$begin_format_texi          = \&t2h_default_begin_format_texi;
5639$tab_item_texi              = \&t2h_default_tab_item_texi;
5640$insertcopying              = \&t2h_default_insertcopying;
5641$colon_command              = \&t2h_default_colon_command;
5642$simple_command             = \&t2h_default_simple_command;
5643$thing_command              = \&t2h_default_thing_command;
5644
5645# return the line after preserving things according to misc_command map.
5646# You should not change it. It is here, nevertheless, to be used
5647# in other function references if needed.
5648sub t2h_default_preserve_misc_command($$)
5649{
5650    my $line = shift;
5651    my $macro = shift;
5652    my $text = '';
5653    my $args = [];
5654    my $skip_spec = '';
5655    my $arg_spec = '';
5656
5657#print STDERR "HHHHHHHHH $line $macro\n";
5658    $skip_spec = $misc_command{$macro}->{'skip'}
5659        if (defined($misc_command{$macro}->{'skip'}));
5660    $arg_spec = $misc_command{$macro}->{'arg'}
5661        if (defined($misc_command{$macro}->{'arg'}));
5662
5663    if ($arg_spec eq 'line')
5664    {
5665        $text .= $line;
5666        $args = [ $line ];
5667        $line = '';
5668    }
5669    elsif ($arg_spec)
5670    {
5671        my $arg_nr = $misc_command{$macro}->{'arg'};
5672        while ($arg_nr)
5673        {
5674            $line =~ s/(\s+\S*)//o;
5675            my $argument = $1;
5676            if (defined($argument))
5677            {
5678                $text .= $argument;
5679                push @$args, $argument;
5680            }
5681            $arg_nr--;
5682        }
5683    }
5684
5685    if ($macro eq 'bye')
5686    {
5687        $line = '';
5688        $text = "\n";
5689    }
5690    elsif ($skip_spec eq 'linespace')
5691    {
5692        if ($line =~ /^\s*$/o)
5693        {
5694            $line =~ s/([ \t]*)//o;
5695            $text .= $1;
5696        }
5697    }
5698    elsif ($skip_spec eq 'linewhitespace')
5699    {
5700        if ($line =~ /^\s*$/o)
5701        {
5702            $text .= $line;
5703            $line = '';
5704        }
5705    }
5706    elsif ($skip_spec eq 'line')
5707    {
5708        $text .= $line;
5709        $line = '';
5710    }
5711    elsif ($skip_spec eq 'whitespace')
5712    {
5713        $line =~ s/(\s*)//o;
5714        $text .=  $1;
5715    }
5716    elsif ($skip_spec eq 'space')
5717    {
5718        $line =~ s/([ \t]*)//o;
5719        $text .= $1;
5720    }
5721    $line = '' if (!defined($line));
5722    return ($line, $text, $args);
5723}
5724
5725sub t2h_default_simple_command($$$$)
5726{
5727    my $command = shift;
5728    my $in_preformatted = shift;
5729    my $line_nr = shift;
5730    my $state = shift;
5731
5732    if ($in_preformatted)
5733    {
5734        return $simple_map_pre{$command};
5735    }
5736    else
5737    {
5738        return $simple_map{$command};
5739    }
5740}
5741
5742sub t2h_default_thing_command($$$$$)
5743{
5744    my $command = shift;
5745    my $text = shift;
5746    my $in_preformatted = shift;
5747    my $line_nr = shift;
5748    my $state = shift;
5749
5750    my $result;
5751    if ($in_preformatted)
5752    {
5753        $result = $pre_map{$command};
5754    }
5755    else
5756    {
5757        $result = $things_map{$command};
5758    }
5759    return $result . $text;
5760}
5761
5762# this is called each time a format begins. Here it is used to keep a
5763# record of the multitables to have a faithful count of the cell nr.
5764sub t2h_default_begin_format_texi($$$)
5765{
5766    my $command = shift;
5767    my $line = shift;
5768    my $state = shift;
5769
5770    # first array element is the number of cell in a row
5771    # second is the number of paragraphs in a cell
5772    push (@t2h_default_multitable_stack, [-1,-1]) if ($command eq 'multitable');
5773
5774    return $line;
5775}
5776
5777# This function is called whenever a complex format is processed
5778#
5779# arguments:
5780# name of the format
5781# text appearing inside the format
5782#
5783# an eval of $complex_format->{format name}->{'begin'} should lead to the
5784# beginning of the complex format, an eval of
5785# $complex_format->{format name}->{'end'}  should lead to the end of the
5786# complex format.
5787sub t2h_default_complex_format($$)
5788{
5789    my $name = shift;
5790    my $text = shift;
5791    return '' if ($text eq '');
5792    my $beginning = eval "$complex_format_map->{$name}->{'begin'}";
5793    if ($@ ne '')
5794    {
5795        print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'begin'}: $@";
5796        $beginning = '';
5797
5798    }
5799    my $end = eval "$complex_format_map->{$name}->{'end'}";
5800    if ($@ ne '')
5801    {
5802        print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'end'}: $@";
5803        $end = '';
5804
5805    }
5806    return $beginning . $text . $end;
5807}
5808
5809sub t2h_default_empty_line($$)
5810{
5811    my $text = shift;
5812    my $state = shift;
5813    #ignore the line if it just follows a deff
5814    return '' if ($state->{'deff_line'});
5815    return $text;
5816}
5817
5818sub t2h_default_unknown($$$$$)
5819{
5820    my $macro = shift;
5821    my $line = shift;
5822    my $pass = shift;
5823    my $stack = shift;
5824    my $state = shift;
5825
5826    my ($result_line, $result, $result_text, $message);
5827    return ($line, 0, undef, undef);
5828}
5829
5830sub t2h_default_unknown_style($$$$)
5831{
5832    my $command = shift;
5833    my $text = shift;
5834    my $state = shift;
5835
5836    my ($result, $result_text, $message);
5837    return (0, undef, undef);
5838}
5839
5840sub t2h_default_caption_shortcaption($)
5841{
5842    my $float = shift;
5843    my $caption_lines;
5844    my $shortcaption_lines;
5845    my $style = $float->{'style_texi'};
5846    if (defined($float->{'nr'}))
5847    {
5848        my $nr = $float->{'nr'};
5849        if ($style ne '')
5850        {
5851            $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
5852        }
5853        else
5854        {
5855            $style = $nr;
5856        }
5857    }
5858
5859    if (defined($float->{'caption_texi'}))
5860    {
5861        @$caption_lines = @{$float->{'caption_texi'}};
5862        if (defined($style))
5863        {
5864            $caption_lines->[0] = '@strong{' . &$I('%{style}: %{caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] });
5865        }
5866        else
5867        {
5868            $caption_lines->[0] = '@strong{' .  $caption_lines->[0];
5869        }
5870        push @$caption_lines, "}\n";
5871    }
5872    elsif (defined($style))
5873    {
5874        $caption_lines->[0] = '@strong{' . $style . '}' . "\n";
5875    }
5876    if (defined($float->{'shortcaption_texi'}))
5877    {
5878         @$shortcaption_lines = @{$float->{'shortcaption_texi'}};
5879         if (defined($style))
5880         {
5881              $shortcaption_lines->[0] = '@strong{' . &$I('%{style}: %{shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] });
5882         }
5883         else
5884         {
5885              $shortcaption_lines->[0] = '@strong{' .  $shortcaption_lines->[0];
5886         }
5887         push @$shortcaption_lines, "}\n";
5888    }
5889    elsif (defined($style))
5890    {
5891         $shortcaption_lines->[0] = '@strong{' . $style . '}' . "\n";
5892    }
5893    return ($caption_lines, $shortcaption_lines);
5894}
5895
5896# everything is done in &$float
5897sub t2h_default_caption_shortcaption_command($$$$)
5898{
5899   my $command = shift;
5900   my $text = shift;
5901   my $texi_lines = shift;
5902   my $float_element = shift;
5903   return '';
5904}
5905
5906sub t2h_default_float($$$$$)
5907{
5908    my $text = shift;
5909    my $float = shift;
5910    my $caption = shift;
5911    my $shortcaption = shift;
5912
5913    my $label = '';
5914    if (exists($float->{'id'}))
5915    {
5916        $label = &$anchor($float->{'id'});
5917    }
5918    my $caption_text = '';
5919
5920    if (defined($float->{'caption_texi'}))
5921    {
5922        $caption_text = $caption;
5923    }
5924    elsif (defined($float->{'shortcaption_texi'}))
5925    {
5926        $caption_text = $shortcaption;
5927    }
5928    elsif (defined($caption))
5929    {
5930        $caption_text = $caption;
5931    }
5932
5933    return '<div class="float">' . "$label\n" . $text . '</div>' . $caption_text;
5934}
5935
5936sub t2h_default_listoffloats_style($)
5937{
5938    my $style_texi = shift;
5939    return ($style_texi);
5940}
5941
5942sub t2h_default_listoffloats_float_style($$)
5943{
5944    my $style_texi = shift;
5945    my $float = shift;
5946
5947    my $style = $float->{'style_texi'};
5948    if (defined($float->{'nr'}))
5949    {
5950         my $nr = $float->{'nr'};
5951         if ($style ne '')
5952         {
5953              $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
5954         }
5955         else
5956         {
5957              $style = $nr;
5958         }
5959    }
5960    return $style;
5961}
5962
5963sub t2h_default_listoffloats_caption($)
5964{
5965    my $float = shift;
5966    if (defined($float->{'shortcaption_texi'}))
5967    {
5968         return [ @{$float->{'shortcaption_texi'}} ];
5969    }
5970    elsif (defined($float->{'caption_texi'}))
5971    {
5972         return [ @{$float->{'caption_texi'}} ];
5973    }
5974    return [ ];
5975}
5976
5977sub t2h_default_listoffloats_entry($$$$)
5978{
5979    my $style_texi = shift;
5980    my $float = shift;
5981    my $float_style = shift;
5982    my $caption = shift;
5983    my $href = shift;
5984
5985    return '<dt>' . &$anchor('', $href, $float_style) . '</dt><dd>' . $caption
5986. '</dd>' . "\n";
5987}
5988
5989sub t2h_default_listoffloats($$$)
5990{
5991    my $style_texi = shift;
5992    my $style = shift;
5993    my $float_entries = shift;
5994
5995    my $result = "<dl class=\"listoffloats\">\n" ;
5996    foreach my $float_entry (@$float_entries)
5997    {
5998         $result .= $float_entry;
5999    }
6000    return $result . "</dl>\n";
6001}
6002
6003sub t2h_default_insertcopying($$$)
6004{
6005    my $text = shift;
6006    my $comment = shift;
6007    my $simple_text = shift;
6008    return $text;
6009}
6010
6011# This function is used to protect characters which are special in html
6012# in inline text:  &, ", <, and >.
6013#
6014# argument:
6015# text to be protected
6016sub t2h_default_protect_text($)
6017{
6018   my $text = shift;
6019   $text =~ s/&/&amp;/g;
6020   $text =~ s/</&lt;/g;
6021   $text =~ s/>/&gt;/g;
6022   $text =~ s/\"/&quot;/g;
6023   return $text;
6024}
6025
6026sub in_cmd($$)
6027{
6028   my $style_stack = shift;
6029   my $command = shift;
6030   my $result = 0;
6031   if ($style_stack and scalar(@{$style_stack}))
6032   {
6033       my $level = $#$style_stack;
6034       #print STDERR ":::$level ::@{$style_stack}\n";
6035       while ($level >= 0)
6036       {
6037           if ($style_stack->[$level] eq $command)
6038           {
6039               $result = 1;
6040               last;
6041           }
6042           $level--;
6043       }
6044   }
6045   return $result;
6046}
6047#
6048#
6049
6050sub in_small_caps($)
6051{
6052   my $style_stack = shift;
6053   my $in_sc = 0;
6054   if ($style_stack and scalar(@{$style_stack}))
6055   {
6056       my $level = $#$style_stack;
6057       #print STDERR ":::$level ::@{$style_stack}\n";
6058       while ($level >= 0)
6059       {
6060           if ($style_stack->[$level] eq 'sc')
6061           {
6062               $in_sc = 1;
6063               last;
6064           }
6065           $level--;
6066       }
6067   }
6068   return $in_sc;
6069}
6070#
6071#
6072sub t2h_default_normal_text($$$$$$;$)
6073{
6074   my $text = shift;
6075   my $in_raw_text = shift; # remove_texi
6076   my $in_preformatted = shift;
6077   my $in_code = shift;
6078   my $in_simple = shift;
6079   my $style_stack = shift;
6080   my $state = shift;
6081   $text = uc($text) if (in_cmd($style_stack, 'sc'));
6082   $text = &$protect_text($text) unless($in_raw_text);
6083   if (! $in_code and !$in_preformatted)
6084   {
6085       if ($USE_ISO and !$in_raw_text)
6086       {
6087           $text =~ s/---/\&mdash\;/g;
6088           $text =~ s/--/\&ndash\;/g;
6089           $text =~ s/``/\&ldquo\;/g;
6090           $text =~ s/''/\&rdquo\;/g;
6091           if (! $in_simple)
6092           { # lquot and rquot don't seem to be accepted in title.
6093               $text =~ s/'/$iso_symbols{"'"}/g if (defined ($iso_symbols{"'"}));
6094               $text =~ s/`/$iso_symbols{'`'}/g if (defined ($iso_symbols{'`'}));
6095           }
6096       }
6097       else
6098       {
6099            if ($in_raw_text) #FIXME really do that ? It is done by makeinfo
6100            {
6101                 $text =~ s/``/"/g;
6102                 $text =~ s/''/"/g;
6103            }
6104            else
6105            {
6106                $text =~ s/``/&quot;/g;
6107                $text =~ s/''/&quot;/g;
6108                # to be like texinfo
6109                #$text =~ s/'/\&rsquo\;/g;
6110                #$text =~ s/`/\&lsquo\;/g;
6111            }
6112            # temporary reuse '' to store --- !....
6113            # FIXME won't '---' be handled wrongly?
6114            # FIXME really do that in raw text?
6115            $text =~ s/---/''/g;
6116            $text =~ s/--/-/g;
6117            $text =~ s/''/--/g;
6118       }
6119   }
6120   else
6121   {
6122       # to be like texinfo
6123#       my $special_code = 0;
6124#       $special_code = 1 if (in_cmd($style_stack, 'code') or
6125#           in_cmd($style_stack, 'example') or in_cmd($style_stack, 'verbatim'));
6126#       $text =~ s/'/\&rsquo\;/g unless ($special_code and exists($main::value{'txicodequoteundirected'}));
6127#       $text =~ s/`/\&lsquo\;/g unless ($special_code and exists($main::value{'txicodequotebacktick'}));
6128   }
6129   return $text;
6130}
6131
6132# This function produces an anchor
6133#
6134# arguments:
6135# $name           :   anchor name
6136# $href           :   anchor href
6137# text            :   text displayed
6138# extra_attribs   :   added to anchor attributes list
6139sub t2h_default_anchor($;$$$)
6140{
6141    my $name = shift;
6142    my $href = shift;
6143    my $text = shift;
6144    my $attributes = shift;
6145#print STDERR "!$name!$href!$text!$attributes!\n";
6146    if (!defined($attributes) or ($attributes !~ /\S/))
6147    {
6148        $attributes = '';
6149    }
6150    else
6151    {
6152        $attributes = ' ' . $attributes;
6153    }
6154    $name = '' if (!defined($name) or ($name !~ /\S/));
6155    $href = '' if (!defined($href) or ($href !~ /\S/));
6156    $text = '' if (!defined($text));
6157    return $text if (($name eq '') and ($href eq ''));
6158    $name = "name=\"$name\"" if ($name ne '');
6159    $href = "href=\"$href\"" if ($href ne '');
6160    $href = ' ' . $href if (($name ne '') and ($href ne ''));
6161#print STDERR "!!!$name!$href!$text!$attributes!\n";
6162    return "<a ${name}${href}${attributes}>$text</a>";
6163}
6164
6165# This function is used to format the text associated with a @deff/@end deff
6166#
6167# argument:
6168# text
6169#
6170# $DEF_TABLE should be used to distinguish between @def formatted as table
6171# and as definition lists.
6172sub t2h_default_def_item($$)
6173{
6174    my $text = shift;
6175    my $only_inter_item_commands = shift;
6176    if ($text =~ /\S/)
6177    {
6178        if (! $DEF_TABLE)
6179        {
6180            return '<dd>' . $text . '</dd>';# unless $only_inter_item_commands;
6181            #return $text; # invalid without dd in ul
6182        }
6183        else
6184        {
6185#            return '<tr><td colspan="2">' . $text . '</td></tr>'; ###GAMBIT###
6186            return $text;
6187        }
6188    }
6189    return '';
6190}
6191
6192sub t2h_default_definition_category($$$$)
6193{
6194    my $name = shift;
6195    my $class = shift;
6196    my $style = shift;
6197    my $command = shift;
6198    return ($name) if (!defined($class) or $class =~ /^\s*$/);
6199    if ($style eq 'f')
6200    {
6201        return &$I('%{name} on %{class}', { 'name' => $name, 'class' => $class });
6202    }
6203    elsif ($style eq 'v')
6204    {
6205        return &$I('%{name} of %{class}', { 'name' => $name, 'class' => $class });
6206    }
6207    else
6208    {
6209        return $name;
6210    }
6211}
6212
6213sub t2h_default_definition_index_entry($$$$)
6214{
6215    my $name = shift;
6216    my $class = shift;
6217    my $style = shift;
6218    my $command = shift;
6219    return ($name) if (!defined($class) or $class =~ /^\s*$/);
6220    if ($style eq 'f')
6221    {
6222        return &$I('%{name} on %{class}', { 'name' => $name, 'class' => $class });
6223    }
6224    elsif ($style eq 'v' and $command ne 'defcv')
6225    {
6226        return &$I('%{name} of %{class}', { 'name' => $name, 'class' => $class });
6227    }
6228    else
6229    {
6230        return $name;
6231    }
6232}
6233
6234# format the container for the @deffn line and text
6235#
6236# argument
6237# text of the whole @def, line and associated text.
6238#
6239# $DEF_TABLE should be used.
6240sub t2h_default_def($)
6241{
6242    my $text = shift;
6243    if ($text =~ /\S/)
6244    {
6245        if (! $DEF_TABLE)
6246        {
6247            return "<dl>\n" . $text . "</dl>\n";
6248        }
6249        else
6250        {
6251#            return "<table width=\"100%\">\n" . $text . "</table>\n"; ###GAMBIT### move table to each definition
6252            return $text . "\n";
6253        }
6254    }
6255    return '';
6256
6257}
6258
6259# tracks menu entry index
6260my $menu_entry_index;
6261
6262# a whole menu
6263#
6264# argument:
6265# the whole menu text (entries and menu comments)
6266#
6267# argument:
6268# whole menu text.
6269sub t2h_default_menu_command($$$)
6270{
6271    my $format = shift;
6272    my $text = shift;
6273    my $in_preformatted = shift;
6274
6275    $menu_entry_index=0;
6276
6277    my $begin_row = '';
6278    my $end_row = '';
6279    if ($in_preformatted)
6280    {
6281        $begin_row = '<tr><td>';
6282        $end_row = '</td></tr>';
6283    }
6284    if ($text =~ /\S/)
6285    {
6286        return $text if ($format eq 'detailmenu');
6287        return "<table class=\"menu\" border=\"0\" cellspacing=\"0\">${begin_row}\n"
6288        . $text . "${end_row}</table>\n";
6289    }
6290}
6291
6292# obsolete
6293# a simple menu entry ref in case we aren't in a standard menu context
6294#sub t2h_default_simple_menu_link($$$$$$$)
6295#{
6296#    my $entry = shift;
6297#    my $preformatted = shift;
6298#    my $href = shift;
6299#    my $node = shift;
6300#    my $title = shift;
6301#    my $ending = shift;
6302#    my $has_title = shift;
6303#    $title = '' unless($has_title);
6304#    $ending = '' if (!defined($ending));
6305#    if (($entry eq '') or $NODE_NAME_IN_MENU or $preformatted)
6306#    {
6307#        $title .= ':' if ($title ne '');
6308#        $entry = "$MENU_SYMBOL$title$node";
6309#    }
6310#    $menu_entry_index++;
6311#    my $accesskey;
6312#    $accesskey = "accesskey=\"$menu_entry_index\"" if ($USE_ACCESSKEY and ($menu_entry_index < 10));
6313#    $entry = &$anchor('', $href, $entry, $accesskey) if ($href);
6314#    $entry .= $ending if ($preformatted);
6315#    $entry .= '&nbsp;' unless $preformatted;
6316#    return $entry;
6317#}
6318
6319# formats a menu entry link pointing to a node or section
6320#
6321# arguments:
6322# the entry text
6323# the state, a hash reference holding informations about the context, with a
6324#     usefull entry, 'preformatted', true if we are in a preformatted format
6325#     (a format keeping space between words). In that case a function
6326#     of the main program, main::do_preformatted($text, $state) might
6327#     be used to format the text with the current format style.
6328# href is optionnal. It is the reference to the section or the node anchor
6329#     which should be used to make the link (typically it is the argument
6330#     of a href= attribute in a <a> element).
6331sub t2h_default_menu_link($$$$$$$$)
6332{
6333    my $entry = shift;
6334    my $state = shift;
6335    my $href = shift;
6336    my $node = shift;
6337    my $title = shift;
6338    my $ending = shift;
6339    my $has_title = shift;
6340    my $command_stack = shift;
6341    my $preformatted = shift;
6342
6343    my $in_commands = 0;
6344    $in_commands = 1 if ($command_stack->[-1] and $command_stack->[-1] ne 'menu' and $command_stack->[-1] ne 'detailmenu');
6345
6346    $title = '' unless ($has_title);
6347#print STDERR  "MENU_LINK($in_commands)($state->{'preformatted'})\n";
6348    if (($entry eq '') or $NODE_NAME_IN_MENU or $preformatted)
6349    {
6350        $title .= ':' if ($title ne '');
6351        $entry = "$MENU_SYMBOL$title$node";
6352    }
6353    $menu_entry_index++;
6354    my $accesskey;
6355    $accesskey = "accesskey=\"$menu_entry_index\"" if ($USE_ACCESSKEY and ($menu_entry_index < 10));
6356    $entry = &$anchor ('', $href, $entry, $accesskey) if (defined($href));
6357
6358    return $entry.$ending if ($preformatted);
6359    return $entry .'&nbsp;' if ($in_commands);
6360    return "<tr><td align=\"left\" valign=\"top\">$entry</td><td>&nbsp;&nbsp;</td>";
6361}
6362
6363sub simplify_text($)
6364{
6365    my $text = shift;
6366    $text =~ s/[^\w]//og;
6367    return $text;
6368}
6369
6370# formats a menu entry description, ie the text appearing after the node
6371# specification in a menu entry an spanning until there is another
6372# menu entry, an empty line or some text at the very beginning of the line
6373# (we consider that text at the beginning of the line begins a menu comment)
6374#
6375# arguments:
6376# the description text
6377# the state. See menu_entry.
6378# the heading of the element associated with the node.
6379sub t2h_default_menu_description($$$$)
6380{
6381    my $text = shift;
6382    my $state = shift;
6383    my $element_text = shift;
6384    my $command_stack = shift;
6385    my $preformatted = shift;
6386
6387    my $in_commands = 0;
6388    $in_commands = 1 if ($command_stack->[-1] and $command_stack->[-1] ne 'menu' and $command_stack->[-1] ne 'detailmenu');
6389    return $text if ($preformatted or $in_commands);
6390    # FIXME: the following is better-looking.
6391    #return $text."<br>" if ($in_commands and !$state->{'preformatted'});
6392    if ($AVOID_MENU_REDUNDANCY)
6393    {
6394        $text = '' if (simplify_text($element_text) eq simplify_text($text));
6395    }
6396    return "<td align=\"left\" valign=\"top\">$text</td></tr>\n";
6397}
6398
6399# a menu comment (between menu lines, obsolete)
6400# formats the container of a menu comment. A menu comment is any text
6401# appearing between menu lines, either separated by an empty line from
6402# the preceding menu entry, or a text beginning at the first character
6403# of the line (text not at the very beginning of the line is considered to
6404# be the continuation of a menu entry description text).
6405#
6406# The text itself is considered to be in a preformatted environment
6407# with name 'menu-commment' and with style $MENU_PRE_STYLE.
6408#
6409# argument
6410# text contained in the menu comment.
6411#sub t2h_default_menu_comment($)
6412#{
6413#   my $text = shift;
6414#   return $text if ($SIMPLE_MENU);
6415#   if ($text =~ /\S/)
6416#   {
6417#       return "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">$text</th></tr>";
6418#   }
6419#   return '';
6420#}
6421
6422# Construct a href to an external source of information.
6423# node is the node with texinfo @-commands
6424# node_id is the node transliterated and transformed as explained in the
6425#         texinfo manual
6426# node_xhtml_id is the node transformed such that it is unique and can
6427#     be used to make an html cross ref as explained in the texinfo manual
6428# file is the file in '(file)node'
6429sub t2h_default_external_href($$$)
6430{
6431    my $node = shift;
6432    my $node_id = shift;
6433    my $node_xhtml_id = shift;
6434    my $file = shift;
6435    $file = '' if (!defined($file));
6436    my $default_target_split = $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'};
6437    my $target_split;
6438    my $target_mono;
6439    my $href_split;
6440    my $href_mono;
6441    if ($file ne '')
6442    {
6443         if ($NEW_CROSSREF_STYLE)
6444         {
6445             $file =~ s/\.[^\.]*$//;
6446             $file =~ s/^.*\///;
6447             my $href;
6448             if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}))
6449             {
6450                  if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}))
6451                  {
6452                       $target_split = 1;
6453                       $href_split =  $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}->{'href'};
6454                  }
6455                  if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}))
6456                  {
6457                       $target_mono = 1;
6458                       $href_mono =  $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}->{'href'};
6459                  }
6460             }
6461
6462             if ((not $target_mono) and (not $target_split))
6463             { # nothing specified for that manual, use default
6464                  $target_split = $default_target_split;
6465             }
6466             elsif ($target_split and $target_mono)
6467             { # depends on the splitting of the manual
6468                  $target_split = $SPLIT;
6469             }
6470             elsif ($target_mono)
6471             { # only mono specified
6472                  $target_split = 0;
6473             }
6474
6475             if ($target_split)
6476             {
6477                  if (defined($href_split))
6478                  {
6479                       $file = "$href_split";
6480                  }
6481                  elsif (defined($EXTERNAL_DIR))
6482                  {
6483                       $file = "$EXTERNAL_DIR/$file";
6484                  }
6485                  elsif ($SPLIT)
6486                  {
6487                       $file = "../$file";
6488                  }
6489                  $file .= "/";
6490             }
6491             else
6492             {# target not split
6493                  if (defined($href_mono))
6494                  {
6495                       $file = "$href_mono";
6496                  }
6497                  else
6498                  {
6499                       if (defined($EXTERNAL_DIR))
6500                       {
6501                            $file = "$EXTERNAL_DIR/$file";
6502                       }
6503                       elsif ($SPLIT)
6504                       {
6505                           $file = "../$file";
6506                       }
6507                       $file .= "." . $NODE_FILE_EXTENSION;
6508                  }
6509             }
6510         }
6511         else
6512         {
6513             $file .= "/";
6514             if (defined($EXTERNAL_DIR))
6515             {
6516                 $file = $EXTERNAL_DIR . $file;
6517             }
6518             else
6519             {
6520                 $file = '../' . $file;
6521             }
6522         }
6523    }
6524    else
6525    {
6526        $target_split = $default_target_split;
6527    }
6528    if ($node eq '')
6529    {
6530         if ($NEW_CROSSREF_STYLE)
6531         {
6532             if ($target_split)
6533             {
6534                 return $file . $TOP_NODE_FILE . '.' . $NODE_FILE_EXTENSION . '#Top';
6535                 # or ?
6536                 #return $file . '#Top';
6537             }
6538             else
6539             {
6540                  return $file . '#Top';
6541             }
6542         }
6543         else
6544         {
6545             return $file;
6546         }
6547    }
6548    my $target;
6549    if ($NEW_CROSSREF_STYLE)
6550    {
6551         $node = $node_id;
6552         $target = $node_xhtml_id;
6553    }
6554    else
6555    {
6556         $node = main::remove_texi($node);
6557         $node =~ s/[^\w\.\-]/-/g;
6558    }
6559    my $file_basename = $node;
6560    $file_basename = $TOP_NODE_FILE if ($node =~ /^top$/i);
6561    if ($NEW_CROSSREF_STYLE)
6562    {
6563        if ($target_split)
6564        {
6565            return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target;
6566        }
6567        else
6568        {
6569            return $file . '#' . $target;
6570        }
6571    }
6572    else
6573    {
6574        return $file . $file_basename . ".$NODE_FILE_EXTENSION";
6575    }
6576}
6577
6578# format a reference external to the generated manual. This produces a full
6579# reference with introductive words and the reference itself.
6580#
6581# arguments:
6582# type of the reference: xref (reference at the beginning of a sentence),
6583#     pxref (reference in a parenthesis),
6584# section in the book. This might be undef.
6585# book name.
6586# node and file name formatted according to the convention used in info
6587#     '(file)node' and no node means the Top node.
6588# href linking to the html page containing the referenced node. A typical
6589#     use for this href is a href attribute in an <a> element
6590# an optionnal cross reference name
6591sub t2h_default_external_ref($$$$$$$$)
6592{
6593    my $type = shift;
6594    my $section = shift;
6595    my $book = shift;
6596    my $file_node = shift;
6597    my $href = shift;
6598    my $cross_ref = shift;
6599    my $args_texi = shift;
6600    my $formatted_args = shift;
6601
6602    $file_node = "$cross_ref: $file_node" if (($file_node ne '') and ($cross_ref ne ''));
6603    $file_node = &$anchor('', $href, $file_node) if ($file_node ne '');
6604
6605    # Yes, this is ugly, but this helps internationalization
6606    if ($type eq 'pxref')
6607    {
6608         if (($book ne '') and ($file_node ne ''))
6609         {
6610              return &$I('see %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6611              return &$I('see %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book },{'duplicate'=>1});
6612         }
6613         elsif ($book ne '')
6614         {
6615              return &$I('see section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6616              return &$I('see @cite{%{book}}', { 'book' => $book },{'duplicate'=>1});
6617         }
6618         elsif ($file_node ne '')
6619         {
6620              return &$I('see %{node_file_href}', { 'node_file_href' => $file_node },{'duplicate'=>1});
6621         }
6622    }
6623    if ($type eq 'xref' or $type eq 'inforef')
6624    {
6625         if (($book ne '') and ($file_node ne ''))
6626         {
6627              return &$I('See %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6628              return &$I('See %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book },{'duplicate'=>1});
6629         }
6630         elsif ($book ne '')
6631         {
6632              return &$I('See section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6633              return &$I('See @cite{%{book}}', { 'book' => $book },{'duplicate'=>1});
6634         }
6635         elsif ($file_node ne '')
6636         {
6637              return &$I('See %{node_file_href}', { 'node_file_href' => $file_node },{'duplicate'=>1});
6638         }
6639    }
6640    if ($type eq 'ref')
6641    {
6642         if (($book ne '') and ($file_node ne ''))
6643         {
6644              return &$I('%{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6645              return &$I('%{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book },{'duplicate'=>1});
6646         }
6647         elsif ($book ne '')
6648         {
6649              return &$I('section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section },{'duplicate'=>1}) if ($section ne '');
6650              return &$I('@cite{%{book}}', { 'book' => $book },{'duplicate'=>1});
6651         }
6652         elsif ($file_node ne '')
6653         {
6654              return &$I('%{node_file_href}', { 'node_file_href' => $file_node },{'duplicate'=>1});
6655         }
6656    }
6657    return '';
6658}
6659
6660# format a reference to a node or a section in the generated manual. This
6661# produces a full reference with introductive words and the reference itself.
6662#
6663# arguments:
6664# type of the reference: xref (reference at the beginning of a sentence),
6665#     pxref (reference in a parenthesis),
6666# href linking to the html page containing the node or the section. A typical
6667#     use for this href is a href attribute in an <a> element
6668# short name for this reference
6669# name for this reference
6670# boolean true if the reference is a reference to a section
6671#
6672# $SHORT_REF should be used.
6673sub t2h_default_internal_ref($$$$$$$)
6674{
6675    my $type = shift;
6676    my $href = shift;
6677    my $short_name = shift;
6678    my $name = shift;
6679    my $is_section = shift;
6680    my $args_texi = shift;
6681    my $formatted_args = shift;
6682
6683    if (! $SHORT_REF)
6684    {
6685        $name = &$anchor('', $href, $name);
6686        if ($type eq 'pxref')
6687        {
6688            return &$I('see section %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section);
6689            return &$I('see %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6690        }
6691        elsif ($type eq 'xref' or $type eq 'inforef')
6692        {
6693            return &$I('See section %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section);
6694            return &$I('See %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6695        }
6696        elsif ($type eq 'ref')
6697        {
6698            return &$I('%{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6699        }
6700    }
6701    else
6702    {
6703        $name = &$anchor('', $href, $short_name);
6704        if ($type eq 'pxref')
6705        {
6706            return &$I('see %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6707        }
6708        elsif ($type eq 'xref' or $type eq 'inforef')
6709        {
6710            return &$I('See %{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6711        }
6712        elsif ($type eq 'ref')
6713        {
6714            return &$I('%{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
6715        }
6716    }
6717    return '';
6718}
6719
6720sub teletyped_in_stack($)
6721{
6722    my $stack = shift;
6723    foreach my $element(reverse(@$stack))
6724    {
6725        return 1 if ($complex_format_map->{$element} and
6726            $complex_format_map->{$element}->{'style'} and
6727            $complex_format_map->{$element}->{'style'} eq 'code');
6728    }
6729    return 0;
6730}
6731
6732# text after @item in table, vtable and ftable
6733sub t2h_default_table_item($$$$$$$$$)
6734{
6735    my $text = shift;
6736    my $index_label = shift;
6737    my $format = shift;
6738    my $command = shift;
6739    my $formatted_command = shift;
6740    my $style_stack = shift;
6741    my $text_formatted = shift;
6742    my $text_formatted_leading_spaces = shift;
6743    my $text_formatted_trailing_spaces = shift;
6744    my $item_cmd = shift;
6745
6746    #print STDERR "-> $format (@$style_stack)\n";
6747    if (defined($text_formatted) and !exists $special_list_commands{$format}->{$command})
6748    {
6749        $text = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces;
6750    }
6751    $formatted_command = '' if (!defined($formatted_command) or
6752          exists($special_list_commands{$format}->{$command}));
6753    if (teletyped_in_stack($style_stack))
6754    {
6755       $text .= '</tt>';
6756       $formatted_command = '<tt>' . $formatted_command;
6757    }
6758    $text .= "\n" . $index_label  if (defined($index_label));
6759    return '<dt>' . $formatted_command . $text . '</dt>' . "\n";
6760}
6761
6762# format text on the line following the @item line (in table, vtable and ftable)
6763sub t2h_default_table_line($$$)
6764{
6765    my $text = shift;
6766    my $only_inter_item_commands = shift;
6767    my $before_items = shift;
6768
6769    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));
6770
6771    if ($text =~ /\S/)
6772    {
6773        return '<dd>' . $text . '</dd>' . "\n";# unless ($only_inter_item_commands);
6774        #return $text; # invalid without dd in ul
6775    }
6776    return '';
6777}
6778
6779#my $cell_nr = -1;
6780
6781# row in multitable
6782sub t2h_default_row($$$$$$$$)
6783{
6784    my $text = shift;
6785    my $macro = shift;
6786    my $columnfractions = shift;
6787    my $prototype_row = shift;
6788    my $prototype_lengths = shift;
6789    my $column_number = shift;
6790    my $only_inter_item_commands = shift;
6791    my $before_items = shift;
6792
6793    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));
6794
6795    # this is used to keep the cell number
6796    $t2h_default_multitable_stack[-1]->[0] = -1;
6797
6798    if ($text =~ /\S/)
6799    {
6800         if ($macro eq 'headitem')
6801         {
6802              return '<thead><tr>' . $text . '</tr></thead>' . "\n";
6803         }
6804         return '<tr>' . $text . '</tr>' . "\n";
6805    }
6806    return '';
6807}
6808
6809# cell in multitable
6810sub t2h_default_cell($$$$$$$$)
6811{
6812    my $text = shift;
6813    my $row_macro = shift;
6814    my $columnfractions = shift;
6815    my $prototype_row = shift;
6816    my $prototype_lengths = shift;
6817    my $column_number = shift;
6818    my $only_inter_item_commands = shift;
6819    my $before_items = shift;
6820
6821    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));
6822
6823    $t2h_default_multitable_stack[-1]->[0]++;
6824    my $cell_nr = $t2h_default_multitable_stack[-1]->[0];
6825    my $fractions = '';
6826
6827    if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY')
6828         and exists($columnfractions->[$cell_nr]))
6829    {
6830        my $fraction = sprintf('%d', 100*$columnfractions->[$cell_nr]);
6831        $fractions = " width=\"$fraction%\"";
6832    }
6833
6834    # in constructs like
6835    # @strong{
6836    # @multitable ....
6837    # }
6838    # the space won't be removed since the <strong> is put before the space.
6839    $text =~ s/^\s*//;
6840    $text =~ s/\s*$//;
6841
6842    if ($row_macro eq 'headitem')
6843    {
6844        return "<th${fractions}>" . $text . '</th>';
6845    }
6846    return "<td${fractions}>" . $text . '</td>';
6847}
6848
6849sub t2h_default_format_list_item_texi($$$$)
6850{
6851    my $format = shift;
6852    my $line = shift;
6853    my $prepended = shift;
6854    my $command = shift;
6855
6856    my $result_line;
6857    my $open_command = 0;
6858
6859    if (defined($prepended) and $prepended ne '')
6860    {
6861         $result_line = $prepended . ' ' . $line;
6862    }
6863    $open_command = 1 if (defined($command));
6864    return ($result_line, $open_command);
6865}
6866
6867
6868# format an item in a list
6869#
6870# argument:
6871# text of the item
6872# format of the list (itemize or enumerate)
6873# command passed as argument to the format
6874# formatted_command leading command formatted, if it is a thing command
6875sub t2h_default_list_item($$$$$$$$$$$)
6876{
6877    my $text = shift;
6878    my $format = shift;
6879    my $command = shift;
6880    my $formatted_command = shift;
6881    my $item_nr = shift;
6882    my $enumerate_style = shift;
6883    my $number = shift;
6884    my $prepended = shift;
6885    my $prepended_formatted = shift;
6886    my $only_inter_item_commands = shift;
6887    my $before_items = shift;
6888
6889    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));
6890
6891    $formatted_command = '' if (!defined($formatted_command) or
6892          exists($special_list_commands{$format}->{$command}));
6893    my $prepend = '';
6894#    if (defined($prepended) and $prepended ne '')
6895#    {
6896#        $prepend = $prepended;
6897#    }
6898#    elsif ($formatted_command ne '')
6899    if ($formatted_command ne '')
6900    {
6901        $prepend = $formatted_command;
6902    }
6903    if ($text =~ /\S/)
6904    {
6905        return '<li>' . $prepend . $text . '</li>';
6906    }
6907    return '';
6908}
6909
6910sub t2h_default_table_list($$$$$$$$$)
6911{
6912    my $format_command = shift;
6913    my $text = shift;
6914    my $command = shift;
6915    my $formatted_command = shift;
6916# enumerate
6917    my $item_nr = shift;
6918    my $enumerate_style = shift;
6919# itemize
6920    my $prepended = shift;
6921    my $prepended_formatted = shift;
6922# multitable
6923    my $columnfractions = shift;
6924    my $prototype_row = shift;
6925    my $prototype_lengths = shift;
6926    my $column_number = shift;
6927#    my $number = shift;
6928    $formatted_command = '' if (!defined($formatted_command) or
6929          exists($special_list_commands{$format}->{$command}));
6930    if ($format_command eq 'itemize')
6931    {
6932        return "<ul>\n" . $text . "</ul>\n" if (($command eq 'bullet') or (($command eq '') and ($prepended eq '')));
6933        return "<ul$NO_BULLET_LIST_ATTRIBUTE>\n" . $text . "</ul>\n";
6934    }
6935    elsif ($format_command eq 'multitable')
6936    {
6937        pop @t2h_default_multitable_stack;
6938        return &$format('multitable', 'table', $text);
6939    }
6940}
6941
6942# an html comment
6943sub t2h_default_comment($)
6944{
6945    my $text = shift;
6946    $text =~ s/--+/-/go;
6947    return '<!-- ' . $text . ' -->' . "\n";
6948}
6949
6950sub t2h_collect_styles($)
6951{
6952    my $cmd_stack = shift;
6953    my @result = ();
6954    foreach my $style (reverse(@$cmd_stack))
6955    {
6956#        last unless (defined($command_type{$style}) and $command_type{$style} eq 'style');
6957        push @result, $style if (defined($command_type{$style}) and $command_type{$style} eq 'style');
6958    }
6959    return @result;
6960}
6961
6962sub t2h_get_attribute($;$)
6963{
6964    my $command = shift;
6965    my $map_ref = shift;
6966    $map_ref = \%style_map if (!defined($map_ref));
6967    return '' unless (defined($map_ref->{$command}));
6968    if ((ref($map_ref->{$command}) eq 'HASH')
6969       and exists($map_ref->{$command}->{'attribute'}))
6970    {
6971        return $map_ref->{$command}->{'attribute'};
6972    }
6973    elsif ($map_ref->{$command} !~ /^&/)
6974    {
6975        my $attribute = $map_ref->{$command};
6976        $attribute =~ s/^\"//;
6977        return $attribute;
6978    }
6979    return '';
6980}
6981
6982sub t2h_begin_style($$;$)
6983{
6984    my $command = shift;
6985    my $text = shift;
6986    my $map_ref = shift;
6987    my $attribute = t2h_get_attribute($command,$map_ref);
6988    $attribute = "<$attribute>" if ($attribute ne '');
6989    return $attribute.$text;
6990}
6991
6992sub t2h_end_style($$;$)
6993{
6994    my $command = shift;
6995    my $text = shift;
6996    my $map_ref = shift;
6997    my $attribute = t2h_get_attribute($command,$map_ref);
6998    if ($attribute =~ /^(\w+)/)
6999    {
7000        $attribute = $1;
7001    }
7002    $attribute = "</$attribute>" if ($attribute ne '');
7003    return $text.$attribute;
7004}
7005
7006# a paragraph
7007# arguments:
7008# $text of the paragraph
7009# $align for the alignement
7010# $indent for the indent style (indent or noindent)
7011# The following is usefull if the paragraph is in an itemize.
7012# $paragraph_command is the leading formatting command (like @minus)
7013# $paragraph_command_formatted is the leading formatting command formatted
7014# $paragraph_number is a reference on the number of paragraphs appearing
7015#    in the format. The value should be increased if a paragraph is done
7016# $format is the format name (@itemize)
7017sub t2h_default_paragraph($$$$$$$$$$$$)
7018{
7019    my $text = shift;
7020    my $align = shift;
7021    my $indent = shift;
7022    my $paragraph_command = shift;
7023    my $paragraph_command_formatted = shift;
7024    my $paragraph_number = shift;
7025    my $format = shift;
7026    my $item_nr = shift;
7027    my $enumerate_style = shift;
7028    my $number = shift;
7029    my $command_stack_at_end = shift;
7030    my $command_stack_at_begin = shift;
7031#print STDERR "format: $format\n" if (defined($format));
7032#print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n";
7033    $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or
7034          exists($special_list_commands{$format}->{$paragraph_command}));
7035    return '' if ($text =~ /^\s*$/);
7036
7037    foreach my $style(t2h_collect_styles($command_stack_at_begin))
7038    {
7039       $text = t2h_begin_style($style, $text);
7040    }
7041    foreach my $style(t2h_collect_styles($command_stack_at_end))
7042    {
7043       $text = t2h_end_style($style, $text);
7044    }
7045
7046    if (defined($paragraph_number) and defined($$paragraph_number))
7047    {
7048         $$paragraph_number++;
7049         return $text  if (($format eq 'itemize' or $format eq 'enumerate') and
7050            ($$paragraph_number == 1));
7051    }
7052
7053    my $top_stack = '';
7054    $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
7055    if ($top_stack eq 'multitable')
7056    {
7057       $t2h_default_multitable_stack[-1]->[1]++;
7058       if ($t2h_default_multitable_stack[-1]->[1] == 0)
7059       {
7060           return $text;
7061       }
7062    }
7063
7064    my $open = '<p>';
7065    if ($align)
7066    {
7067        $open = "<p align=\"$paragraph_style{$align}\">";
7068    }
7069    return $open.$text.'</p>';
7070}
7071
7072# a preformatted region
7073# arguments:
7074# $text of the preformatted region
7075# $pre_style css style
7076# $class identifier for the preformatted region (example, menu-comment)
7077# The following is usefull if the preformatted is in an itemize.
7078# $leading_command is the leading formatting command (like @minus)
7079# $leading_command_formatted is the leading formatting command formatted
7080# $preformatted_number is a reference on the number of preformatteds appearing
7081#    in the format. The value should be increased if a preformatted is done
7082sub t2h_default_preformatted($$$$$$$$$$$$)
7083{
7084    my $text = shift;
7085    my $pre_style = shift;
7086    my $class = shift;
7087    my $leading_command = shift;
7088    my $leading_command_formatted = shift;
7089    my $preformatted_number = shift;
7090    my $format = shift;
7091    my $item_nr = shift;
7092    my $enumerate_style = shift;
7093    my $number = shift;
7094    my $command_stack_at_end = shift;
7095    my $command_stack_at_begin = shift;
7096
7097#print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n";
7098    return '' if ($text eq '');
7099    $leading_command_formatted = '' if (!defined($leading_command_formatted) or
7100          exists($special_list_commands{$format}->{$leading_command}));
7101    if (defined($preformatted_number) and defined($$preformatted_number))
7102    {
7103        $$preformatted_number++;
7104    }
7105    my $top_stack = '';
7106    $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
7107    if ($top_stack eq 'multitable')
7108    {
7109       $text =~ s/^\s*//;
7110       $text =~ s/\s*$//;
7111    }
7112
7113    foreach my $style(t2h_collect_styles($command_stack_at_begin))
7114    {
7115       $text = t2h_begin_style($style, $text, \%style_map_pre);
7116    }
7117    foreach my $style(t2h_collect_styles($command_stack_at_end))
7118    {
7119       $text = t2h_end_style($style, $text, \%style_map_pre);
7120    }
7121    return "<pre class=\"$class\">".$text."</pre>";
7122}
7123
7124# This function formats a heading for an element
7125#
7126# argument:
7127# an element. It is a hash reference for a node or a sectionning command.
7128#             it may be the wrong one in case of headings.
7129# The interesting keys are:
7130# 'text': the heading text
7131# 'text_nonumber': the heading text without section number
7132# 'node': true if it is a node
7133# 'level': level of the element. 0 for @top, 1 for chapter, heading,
7134#      appendix..., 2 for section and so on...
7135# 'tag_level': the sectionning element name, raisesections and lowersections
7136#      taken into account
7137sub t2h_default_element_heading($$$$$$$$$$$$)
7138{
7139    my $element = shift;
7140    my $command = shift;
7141    my $texi_line = shift;
7142    my $line = shift;
7143    my $in_preformatted = shift;
7144    my $one_section = shift;
7145    my $element_heading = shift;
7146    my $first_in_page = shift;
7147    my $is_top = shift;
7148    my $previous_is_top = shift;
7149    my $command_line = shift;
7150    my $element_id = shift;
7151    my $new_element = shift;
7152#print STDERR ":::::::: $element $command i_p $in_preformatted o_s $one_section e_h $element_heading f_p $first_in_page i_t $is_top p_i_t $previous_is_top id $element_id new $new_element\n";
7153
7154    my $result = &$element_label($element_id, $element, $command, $command_line);
7155    if ($new_element and !$one_section)
7156    {
7157       if (!$element->{'element_ref'}->{'top'})
7158       {
7159    #return $result if (defined($command) and $command eq 'node' and !$element_heading);
7160           $result .= &$print_element_header($first_in_page, $previous_is_top);
7161       }
7162       else
7163       {
7164           $result .= &$print_head_navigation(undef, \@MISC_BUTTONS) if ($SPLIT or $SECTION_NAVIGATION);
7165       }
7166    }
7167
7168    return $result if (!$element_heading);
7169    return $result. &$heading($element, $command, $texi_line, $line, $in_preformatted, $one_section, $element_heading);
7170}
7171
7172sub t2h_default_heading($$$$$;$$)
7173{
7174    my $element = shift;
7175    my $command = shift;
7176    my $texi_line = shift;
7177    my $line = shift;
7178    my $in_preformatted = shift;
7179    my $one_section = shift;
7180    my $element_heading = shift;
7181
7182    my $level = 3;
7183    if (!$element->{'node'})
7184    {
7185        $level = $element->{'level'};
7186    }
7187    my $text = $element->{'text'};
7188    my $class = $element->{'tag_level'};
7189    $class = 'unnumbered' if ($class eq 'top');
7190    my $align = '';
7191    $align = ' align="center"' if ($element->{'tag'} eq 'centerchap');
7192    if ($element->{'top'})
7193    {
7194       return '' if ($element->{'titlefont'});
7195       $level = 1;
7196       $text = $Texi2HTML::NAME{'Top'};
7197       $class = 'settitle' unless ($one_section);
7198    }
7199    # when it is a heading, the element is irrelevant, so the command and the
7200    # line are used...
7201    if (defined($command) and $command =~ /heading/)
7202    {
7203        $level = $main::sec2level{$command} if (defined($main::sec2level{$command}));
7204        if (defined($line))
7205        {
7206            $text = $line;
7207            # this isn't done in main program in that case...
7208            chomp ($text);
7209            $text =~ s/^\s*//;
7210        }
7211        $class = $command;
7212    }
7213    elsif (defined($element->{'tocid'}) and $TOC_LINKS)
7214    {
7215         $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text);
7216    }
7217    $level = 1 if ($level == 0);
7218    return '' if ($text !~ /\S/);
7219    if (!$in_preformatted)
7220    {
7221       return "<h$level class=\"$class\"$align>$text</h$level>\n";
7222    }
7223    else
7224    {
7225       return "<strong>$text</strong>\n";
7226    }
7227}
7228
7229sub t2h_default_heading_no_texi($$$)
7230{
7231    my $element = shift;
7232    my $command = shift;
7233    my $line = shift;
7234    return main::remove_texi($line);
7235}
7236
7237# formatting of raw regions
7238# if L2H is true another mechanism is used for tex
7239sub t2h_default_raw($$)
7240{
7241    my $style = shift;
7242    my $text = shift;
7243    if ($style eq 'verbatim' or $style eq 'tex')
7244    {
7245        return "<pre class=\"$style\">" . &$protect_text($text) . '</pre>';
7246    }
7247    elsif ($style eq 'html')
7248    {
7249        chomp ($text);
7250        return $text;
7251    }
7252    else
7253    {
7254        main::echo_warn ("Raw style $style not handled");
7255        return &$protect_text($text);
7256    }
7257}
7258
7259# raw environment when removing texi (in comments)
7260sub t2h_default_raw_no_texi($$)
7261{
7262    my $style = shift;
7263    my $text = shift;
7264    return $text;
7265}
7266
7267# This function formats a footnote reference and the footnote text associated
7268# with a given footnote.
7269# The footnote reference is the text appearing in the main document pointing
7270# to the footnote text.
7271#
7272# arguments:
7273# absolute number of the footnote (in the document)
7274# relative number of the footnote (in the page)
7275# identifier for the footnote
7276# identifier for the footnote reference in the main document
7277# main document file
7278# footnote text file
7279# array with the footnote text lines
7280# the state. See menu entry.
7281#
7282# returns:
7283# reference on an array containing the footnote text lines which should
7284#     have been updated
7285# the text for the reference pointing on the footnote text
7286sub t2h_default_foot_line_and_ref($$$$$$$$$)
7287{
7288    my $number_in_doc = shift;
7289    my $number_in_page = shift;
7290    my $footnote_id = shift;
7291    my $place_id = shift;
7292    my $document_file = shift;
7293    my $footnote_file = shift;
7294    my $lines = shift;
7295    my $document_state = shift;
7296
7297    if ($document_file eq $footnote_file)
7298    {
7299        $document_file = $footnote_file = '';
7300    }
7301    unshift (@$lines, '<h3>' .
7302          &$anchor($footnote_id, $document_file . "#$place_id",
7303                   "($number_in_doc)")
7304          . "</h3>\n");
7305    # this is a bit obscure, this allows to add an anchor only if formatted
7306    # as part of the document.
7307    $place_id = '' if ($document_state->{'outside_document'} or $document_state->{'multiple_pass'});
7308    return ($lines, &$anchor($place_id,  $footnote_file . "#$footnote_id",
7309           "($number_in_doc)"));
7310}
7311
7312# formats a group of footnotes.
7313#
7314# argument:
7315# array reference on the footnotes texts lines
7316#
7317# returns an array reference on the group of footnotes lines
7318sub t2h_default_foot_section($)
7319{
7320    my $lines = shift;
7321    unshift (@$lines, "<div class=\"footnote\">\n" ,"$DEFAULT_RULE\n", "<h3>" . &$I('Footnotes') . "</h3>\n");
7322    push (@$lines, "</div>\n");
7323    return $lines;
7324}
7325
7326sub t2h_default_image_files($$$$)
7327{
7328    my $base = shift;
7329    my $extension = shift;
7330    my $texi_base = shift;
7331    my $texi_extension = shift;
7332    my @files = ();
7333    return @files if (!defined($base) or ($base eq ''));
7334    if (defined($extension) and ($extension ne ''))
7335    {
7336       push @files,["$base.$extension", "$texi_base.$texi_extension"];
7337    }
7338    foreach my $ext (@IMAGE_EXTENSIONS)
7339    {
7340        push @files,["$base.$ext", "$texi_base.$ext"];
7341    }
7342    return @files;
7343}
7344
7345# format an image
7346#
7347# arguments:
7348# image file name with path
7349# image basename
7350# a boolean true if we are in a preformatted format
7351# image file name without path
7352# alt text
7353# width
7354# height
7355# raw alt
7356# extension
7357# path to working dir
7358# path to file relative from working dir
7359sub t2h_default_image($$$$$$$$$$$$$$$$)
7360{
7361    my $file = shift;
7362    my $base = shift;
7363    my $preformatted = shift;
7364    my $file_name = shift;
7365    my $alt = shift;
7366    my $width = shift;
7367    my $height = shift;
7368    my $raw_alt = shift;
7369    my $extension = shift;
7370    my $working_dir = shift;
7371    my $file_path = shift;
7372    my $in_paragraph = shift;
7373    my $file_locations = shift;
7374    my $base_simple_format = shift;
7375    my $extension_simple_format = shift;
7376    my $file_name_simple_format = shift;
7377
7378    if (!defined($file_path) or $file_path eq '')
7379    {
7380        if (defined($extension) and $extension ne '')
7381        {
7382            $file = "$base.$extension";
7383        }
7384        else
7385        {
7386            $file = "$base.jpg";
7387        }
7388        main::echo_warn ("no image file for $base, (using $file)");
7389    }
7390    elsif (! $COMPLETE_IMAGE_PATHS)
7391    {
7392        $file = $file_name;
7393    }
7394    $alt = &$protect_text($base) if (!defined($alt) or ($alt eq ''));
7395    return "[ $alt ]" if ($preformatted);
7396    # it is possible that $file_name is more correct as it allows the user
7397    # to chose the relative path.
7398    $file = &$protect_text($file);
7399    return "<img src=\"$file\" alt=\"$alt\">";
7400}
7401
7402# address put in footer describing when was generated and who did the manual
7403sub t2h_default_address($$)
7404{
7405    my $user = shift;
7406    my $date = shift;
7407    $user = '' if (!defined($user));
7408    $date = '' if (!defined($date));
7409    if (($user ne '') and ($date ne ''))
7410    {
7411        return &$I('by @emph{%{user}} on @emph{%{date}}', { 'user' => $user,
7412            'date' => $date });
7413    }
7414    elsif ($user ne '')
7415    {
7416        return &$I('by @emph{%{user}}', { 'user' => $user });
7417    }
7418    elsif ($date ne '')
7419    {
7420        return &$I('on @emph{%{date}}', { 'date' => $date });
7421    }
7422    return '';
7423}
7424
7425# format a target in the main document for an index entry.
7426#
7427# arguments:
7428# target identifier
7429# boolean true if in preformatted format
7430# FIXME document the remaining
7431sub t2h_default_index_entry_label($$$$$)
7432{
7433    my $identifier = shift;
7434    my $preformatted = shift;
7435    my $entry = shift;
7436    my $index_name = shift;
7437    my $index_command = shift;
7438    my $texi_entry = shift;
7439    my $formatted_entry = shift;
7440
7441    return '' if (!defined($identifier) or ($identifier !~ /\S/));
7442    my $label = &$anchor($identifier);
7443    return $label . "\n" if (!$preformatted);
7444    return $label;
7445}
7446
7447sub t2h_default_index_entry_command($$$$$)
7448{
7449   my $command = shift;
7450   my $index_name = shift;
7451   my $label = shift;
7452   my $entry_texi = shift;
7453   my $entry_formatted = shift;
7454
7455   return $label;
7456}
7457
7458###GAMBIT### added this function
7459sub escape_spaces($)
7460{
7461    my $text = shift;
7462    my $result = '';
7463    while ($text ne '')
7464    {
7465        if ($text =~ s/^(.)//o)
7466        {
7467             my $char = $1;
7468             if ($char eq ' ')
7469             {
7470                 $result .= "_";
7471             }
7472             else
7473             {
7474                 $result .= "$char";
7475             }
7476        }
7477    }
7478    return $result;
7479}
7480
7481###GAMBIT### added this function
7482sub escape_url($)
7483{
7484    my $text = shift;
7485    my $result = '';
7486    while ($text ne '')
7487    {
7488        if ($text =~ s/^(.)//o)
7489        {
7490             my $char = $1;
7491             if ($char eq '#')
7492             {
7493                 $result .= "%E2%99%AF";
7494             }
7495             elsif ($char eq '%')
7496             {
7497                 $result .= "%25";
7498             }
7499             elsif ($char eq '*')
7500             {
7501                 $result .= "%2A";
7502             }
7503             elsif ($char eq '+')
7504             {
7505                 $result .= "%2B";
7506             }
7507             elsif ($char eq '<')
7508             {
7509                 $result .= "%3C";
7510             }
7511             elsif ($char eq '>')
7512             {
7513                 $result .= "%3E";
7514             }
7515             else
7516             {
7517                 $result .= "$char";
7518             }
7519        }
7520    }
7521    return $result;
7522}
7523
7524# process definition commands line @deffn for example
7525sub t2h_default_def_line($$$$$$$$$$$$$$$$)
7526{
7527   my $category_prepared = shift;
7528   my $name = shift;
7529   my $type = shift;
7530   my $arguments = shift;
7531   my $index_label = shift;
7532   my $arguments_array = shift;
7533   my $arguments_type_array = shift;
7534   my $unformatted_arguments_array = shift;
7535   my $command = shift;
7536   my $class_name = shift;
7537   my $category = shift;
7538   my $class = shift;
7539   my $style = shift;
7540   my $original_command = shift;
7541
7542   $index_label = '' if (!defined($index_label));
7543   chomp($index_label);
7544   $category_prepared = '' if (!defined($category_prepared) or ($category_prepared =~ /^\s*$/));
7545   $name = '' if (!defined($name) or ($name =~ /^\s*$/));
7546   $type = '' if (!defined($type) or $type =~ /^\s*$/);
7547   if (!defined($arguments) or $arguments =~ /^\s*$/)
7548   {
7549       $arguments = '';
7550   }
7551   else
7552   {
7553       chomp ($arguments);
7554       $arguments = '<i>' . $arguments . '</i>';
7555   }
7556   my $type_name = '';
7557   $type_name = " $type" if ($type ne '');
7558   $type_name .= " <code>(</code>"; ###GAMBIT### added
7559#   $type_name .= ' <b>' . $name . '</b>' if ($name ne ''); ###GAMBIT### removed
7560
7561   ###GAMBIT### added the following code to assign an anchor to each definition
7562   my $name2 = $name;
7563   $name2 =~ s/&lt;/</g;
7564   $name2 =~ s/&gt;/>/g;
7565   my $anchor1_name = escape_url(escape_spaces('Definition of ' . $name2));
7566   my $anchor2_name = escape_url(escape_spaces(ucfirst($category) . ' ' . $name2));
7567   my $anchor1 = '<a name="' . $anchor1_name . '"></a>';
7568   my $anchor2 = '<a name="' . $anchor2_name . '"></a>';
7569   my $labels = '';
7570
7571   ###GAMBIT### added the following if to have manual refer to the wiki and the wiki refer to the manual
7572   if ($Texi2HTML::THISDOC{'title_texi'} eq 'wiki documentation')
7573   {
7574     #print STDERR "wiki\n";
7575     $type_name .= '<code><b><a href="http://www.iro.umontreal.ca/~gambit/doc/gambit-c.html#' . $anchor1_name . '">' . $name . '</a></b></code>' if ($name ne '');
7576   }
7577   else
7578   {
7579     #print STDERR "manual\n";
7580     $type_name .= '<code><b><a href="http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php?title=Documentation:' . $anchor2_name . '">' . $name . '</a></b></code>' if ($name ne '');
7581     $labels = $anchor1 . $anchor2 . $index_label;
7582   }
7583
7584   $type_name .= $arguments;
7585   $type_name .= "<code>)</code>"; ###GAMBIT### added
7586   if (! $DEF_TABLE)
7587   {
7588       return '<dt>'. $index_label. '<u>' . $category_prepared . ':</u>' . $type_name . "</dt>\n";
7589   }
7590   else
7591   {
7592
7593#       return "<tr><td align=\"left\">" . $type_name .  ###GAMBIT### removed
7594#       "</td><td align=\"right\">" . $category_prepared . $index_label . "</td></tr>\n"; ###GAMBIT###
7595       return $labels . "<table width=\"100%\"><tr><td align=\"left\">" . $type_name .  ###GAMBIT### added to move index label to front
7596       "</td><td align=\"right\">" . $category_prepared . "</td></tr></table>\n"; ###GAMBIT###
7597   }
7598}
7599
7600# process definition commands line @deffn for example while removing texi
7601# commands
7602sub t2h_default_def_line_no_texi($$$$$)
7603{
7604   my $category = shift;
7605   my $name = shift;
7606   my $type = shift;
7607   my $arguments = shift;
7608   $name = '' if (!defined($name) or ($name =~ /^\s*$/));
7609   $type = '' if (!defined($type) or $type =~ /^\s*$/);
7610   if (!defined($arguments) or $arguments =~ /^\s*$/)
7611   {
7612       $arguments = '';
7613   }
7614   my $type_name = '';
7615   $type_name = " $type" if ($type ne '');
7616   $type_name .= ' ' . $name if ($name ne '');
7617   $type_name .= $arguments;
7618   if (! $DEF_TABLE)
7619   {
7620       return $category . ':' . $type_name . "\n";
7621   }
7622   else
7623   {
7624
7625       return $type_name . "    " . $category . "\n";
7626   }
7627}
7628
7629# a cartouche
7630sub t2h_default_cartouche($$)
7631{
7632    my $text = shift;
7633
7634    if ($text =~ /\S/)
7635    {
7636        return "<table class=\"cartouche\" border=\"1\"><tr><td>\n" . $text . "</td></tr></table>\n";
7637    }
7638    return '';
7639}
7640
7641# key:
7642# origin_href:
7643# entry:
7644# texi entry:
7645# element_href:
7646# element_text:
7647sub t2h_default_index_summary_file_entry ($$$$$$$$$)
7648{
7649    my $index_name = shift;
7650    my $key = shift;
7651    my $origin_href = shift;
7652    my $entry = shift;
7653    my $texi_entry = shift;
7654    my $element_href = shift;
7655    my $element_text = shift;
7656    my $is_printed = shift;
7657    my $manual_name = shift;
7658
7659    print IDXFILE "key: $key\n  origin_href: $origin_href\n  entry: $entry\n"
7660      . "  texi_entry: $texi_entry\n"
7661      . "  element_href: $element_href\n  element_text: $element_text\n";
7662}
7663
7664sub t2h_default_index_summary_file_begin($$$)
7665{
7666    my $name = shift;
7667    my $is_printed = shift;
7668    my $manual_name = shift;
7669
7670    open(IDXFILE, ">$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx")
7671       || die "Can't open >$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx for writing: $!\n";
7672}
7673
7674sub t2h_default_index_summary_file_end($$$)
7675{
7676    my $name = shift;
7677    my $is_printed = shift;
7678    my $manual_name = shift;
7679
7680    close (IDXFILE);
7681}
7682
7683sub t2h_default_sp($$)
7684{
7685   my $number = shift;
7686   my $preformatted = shift;
7687   return "<br>\n" x $number if (!$preformatted);
7688   return "\n" x $number;
7689}
7690
7691sub t2h_default_acronym_like($$$$$$)
7692{
7693    my $command = shift;
7694    my $acronym_texi = shift;
7695    my $acronym_text = shift;
7696    my $with_explanation = shift;
7697    my $explanation_lines = shift;
7698    my $explanation_text = shift;
7699    my $explanation_simply_formatted = shift;
7700
7701    my $attribute = $command;
7702    my $opening = "<$attribute>";
7703    if (defined($explanation_simply_formatted))
7704    {
7705        $opening = "<$attribute title=\"$explanation_simply_formatted\">";
7706    }
7707    if ($with_explanation)
7708    {
7709        return &$I('%{acronym_like} (%{explanation})', {'acronym_like' => $opening . $acronym_text . "</$attribute>", 'explanation' => $explanation_text},{'duplicate'=>1})
7710    }
7711    else
7712    {
7713        return  $opening . $acronym_text . "</$attribute>";
7714    }
7715}
7716
7717sub t2h_default_quotation_prepend_text($$)
7718{
7719    my $command = shift;
7720    my $text = shift;
7721    return undef if (!defined($text) or $text =~ /^$/);
7722    $text =~ s/^\s*//;
7723# FIXME if there is a @ protecting the end of line the result is
7724# @b{some text @:}
7725# It is likely not to be what was intended
7726    chomp($text);
7727    return &$I('@b{%{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1});
7728}
7729
7730sub t2h_default_quotation($$$$)
7731{
7732    my $command = shift;
7733    my $text = shift;
7734    my $argument_text = shift;
7735    my $argument_text_texi = shift;
7736    my $class_text = '';
7737    $class_text = " class=\"$command\"" if ($command ne 'quotation');
7738    return "<blockquote$class_text>" . $text . "</blockquote>\n";
7739}
7740
7741# format the text within a paragraph style format,
7742#
7743# argument:
7744# format name
7745# text within the format
7746sub t2h_default_paragraph_style_command($$)
7747{
7748    my $format = shift;
7749    my $text = shift;
7750    return $text;
7751}
7752
7753# format a whole index
7754#
7755# argument:
7756# index text
7757# index name
7758sub t2h_default_print_index($$)
7759{
7760    my $text = shift;
7761    my $name = shift;
7762    return '' if (!defined($text));
7763    return "<table border=\"0\" class=\"index-$name\">\n" .
7764    "<tr><td></td><th align=\"left\">" . &$I('Index Entry') . "</th><th align=\"left\"> " . &$I('Section') . "</th></tr>\n"
7765    . "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n" . $text .
7766    "</table>\n";
7767}
7768
7769# format a letter entry in an index page. The letter entry contains
7770# the index entries for the words beginning with that letter. It is
7771# a target for links pointing from the summary of the index.
7772#
7773# arguments:
7774# the letter
7775# identifier for the letter entry. This should be used to make the target
7776#     identifier
7777# text of the index entries
7778sub t2h_default_index_letter($$$)
7779{
7780     my $letter = shift;
7781     my $id = shift;
7782     my $text = shift;
7783     return '<tr><th>' . &$anchor($id,'',&$protect_text($letter)) .
7784     "</th><td></td><td></td></tr>\n" . $text .
7785     "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n";
7786}
7787
7788# format an index entry (in a letter entry).
7789#
7790# arguments:
7791# href to the main text, linking to the place where the index entry appears
7792# entry text
7793# href to the main text, linking to the section or node where the index
7794#      entry appears
7795# section or node heading
7796sub t2h_default_index_entry($$$$$$$$)
7797{
7798    my $text_href = shift;
7799    my $entry = shift;
7800    my $element_href = shift;
7801    my $element_text = shift;
7802    my $entry_file = shift;
7803    my $current_element_file = shift;
7804    my $entry_target = shift;
7805    my $entry_element_target = shift;
7806
7807    return '<tr><td></td><td valign="top">' . &$anchor('', $text_href, $entry)
7808    . '</td><td valign="top">' .  &$anchor('', $element_href, $element_text)
7809    . "</td></tr>\n";
7810}
7811
7812
7813sub t2h_default_copying_comment($$$$)
7814{
7815    my $copying_lines = shift;
7816    my $copying_text = shift;
7817    my $copying_no_texi = shift;
7818    my $copying_simple_text = shift;
7819    return '' if ($copying_no_texi eq '');
7820    my $text = &$comment($copying_no_texi);
7821    return $text;
7822}
7823
7824# return value is currently ignored
7825sub t2h_default_documentdescription($$$$)
7826{
7827    my $decription_lines = shift;
7828    my $description_text = shift;
7829    my $description_no_texi = shift;
7830    my $description_simple_text = shift;
7831
7832    if (defined($DOCUMENT_DESCRIPTION))
7833    {
7834        $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = $DOCUMENT_DESCRIPTION;
7835        return $DOCUMENT_DESCRIPTION;
7836    }
7837
7838    #return '' if ($description_no_texi eq '');
7839    #my @documentdescription = split (/\n/, $description_no_texi);
7840    if ($description_simple_text eq '')
7841    {
7842        $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = undef;
7843        return undef;
7844    }
7845    my @documentdescription = split (/\n/, $description_simple_text);
7846    my $document_description = shift @documentdescription;
7847    chomp $document_description;
7848    foreach my $line (@documentdescription)
7849    {
7850        chomp $line;
7851        $document_description .= ' ' . $line;
7852    }
7853    $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = $document_description;
7854    return $document_description;
7855}
7856
7857# format an index summary. This is a list of letters linking to the letter
7858# entries.
7859#
7860# arguments:
7861# array reference containing the formatted alphabetical letters
7862# array reference containing the formatted non lphabetical letters
7863sub t2h_default_index_summary($$)
7864{
7865    my $alpha = shift;
7866    my $nonalpha = shift;
7867
7868    my $join = '';
7869    my $nonalpha_text = '';
7870    my $alpha_text = '';
7871    $join = " &nbsp; \n<br>\n" if (@$nonalpha and @$alpha);
7872    if (@$nonalpha)
7873    {
7874       $nonalpha_text = join("\n &nbsp; \n", @$nonalpha) . "\n";
7875    }
7876    if (@$alpha)
7877    {
7878       $alpha_text = join("\n &nbsp; \n", @$alpha) . "\n &nbsp; \n";
7879    }
7880    return "<table><tr><th valign=\"top\">" . &$I('Jump to') .": &nbsp; </th><td>" .
7881    $nonalpha_text . $join . $alpha_text . "</td></tr></table>\n";
7882}
7883
7884# return the heading with number texinfo text
7885# also called for nodes.
7886sub t2h_default_heading_texi($$$)
7887{
7888    my $tag = shift;
7889    my $texi = shift;
7890    my $number = shift;
7891    $texi =~ s/\s*$//;
7892    $texi =~ s/^\s*//;
7893    return "$number $texi" if ($NUMBER_SECTIONS and defined($number) and ($number !~ /^\s*$/)) ;
7894    return $texi;
7895}
7896
7897# return the heading texinfo text for split index sections
7898sub t2h_default_index_element_heading_texi($$$)
7899{ # FIXME i18n
7900    my $heading_texi = shift;
7901    my $tag = shift;
7902    my $texi = shift;
7903    my $number = shift;
7904    my $first_letter = shift;
7905    my $last_letter = shift;
7906    return "$heading_texi: $first_letter -- $last_letter" if ($last_letter ne $first_letter);
7907    return "$heading_texi: $first_letter";
7908}
7909
7910sub t2h_default_element_label($$$$)
7911{
7912    my $id = shift;
7913    my $element = shift;
7914    my $command = shift;
7915    my $line = shift;
7916
7917    return &$anchor($id) . "\n";
7918}
7919
7920sub t2h_default_misc_element_label($$)
7921{
7922    my $id = shift;
7923    my $misc_page_name = shift;
7924    return &$anchor($id) . "\n";
7925}
7926
7927sub t2h_default_anchor_label($$$)
7928{
7929    my $id = shift;
7930    my $anchor_text = shift;
7931    my $anchor_reference = shift;
7932    return &$anchor($id);
7933}
7934
7935sub t2h_default_colon_command($)
7936{
7937   my $punctuation_character = shift;
7938   return $colon_command_punctuation_characters{$punctuation_character} if defined($colon_command_punctuation_characters{$punctuation_character});
7939   return $punctuation_character;
7940}
7941
7942sub t2h_default_tab_item_texi($$$$$$)
7943{
7944   my $comand = shift;
7945   my $commands_stack = shift;
7946   my $state = shift;
7947   my $stack = shift;
7948   my $line = shift;
7949   my $line_nr = shift;
7950
7951   if (defined($commands_stack) and @$commands_stack and $commands_stack->[-1] eq 'multitable' and @t2h_default_multitable_stack)
7952   {
7953      $t2h_default_multitable_stack[-1]->[1] = -1;
7954   }
7955   return undef;
7956}
7957
79581;
7959
7960require "$T2H_HOME/texi2html.init"
7961    if ($0 =~ /\.pl$/ &&
7962        -e "$T2H_HOME/texi2html.init" && -r "$T2H_HOME/texi2html.init");
7963
7964my $translation_file = 'translations.pl'; # file containing all the translations
7965my $T2H_OBSOLETE_STRINGS;
7966
7967# leave this within comments, and keep the require statement
7968# This way, you can directly run texi2html.pl,
7969# if $T2H_HOME/translations.pl exists.
7970#
7971# @T2H_TRANSLATIONS_FILE@
7972$LANGUAGES->{'de'} = {
7973                       '  The buttons in the navigation panels have the following meaning:' => ' Die Links in der Navigationsleiste haben die folgende Bedeutung: ',
7974                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' wobei das @strong{ Beispiel } annimmt, dass die aktuelle Position bei @strong{ Unterabschnitt 1-2-3 } in einem Dokument mit folgender Struktur liegt:',
7975                       ' Up ' => ' Nach oben ',
7976                       '%{acronym_like} (%{explanation})' => '%{acronym_like} (%{explanation})',
7977                       '%{month} %{day}, %{year}' => '%{day}. %{month} %{year}',
7978                       '%{name} of %{class}' => '',
7979                       '%{name} on %{class}' => '',
7980                       '%{node_file_href}' => '',
7981                       '%{node_file_href} @cite{%{book}}' => '',
7982                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} in Abschnitt `%{section}\' in @cite{%{book}}',
7983                       '%{reference_name}' => '%{reference_name}',
7984                       '%{style} %{number}' => '%{style} %{number}',
7985                       '%{style}: %{caption_first_line}' => '%{style}: %{caption_first_line}',
7986                       '%{style}: %{shortcaption_first_line}' => '%{style}: %{shortcaption_first_line}',
7987                       '@b{%{quotation_arg}:} ' => '@b{%{quotation_arg}:} ',
7988                       '@cite{%{book}}' => '@cite{%{book}}',
7989                       'About' => '@"Uber',
7990                       'About (help)' => '@"Uber (Hilfe)',
7991                       'About This Document' => '@"Uber dieses Dokument',
7992                       'April' => 'April',
7993                       'August' => 'August',
7994                       'Back' => 'Zur@"uck',
7995                       'Back section in previous file' => '',
7996                       'Beginning of this chapter or previous chapter' => 'Anfang dieses oder des letzten Kapitels',
7997                       'Button' => '',
7998                       'Contents' => 'Inhalt',
7999                       'Cover (top) of document' => 'Titelseite des Dokuments',
8000                       'Current Position' => 'Aktuelle Position',
8001                       'Current section' => 'Aktueller Abschnitt',
8002                       'December' => 'Dezember',
8003                       'FastBack' => '',
8004                       'FastForward' => '',
8005                       'February' => 'Februar',
8006                       'First' => '',
8007                       'First section in reading order' => 'Erster Abschnitt in Lesereihenfolge',
8008                       'Following' => '',
8009                       'Following node' => 'N@"achster Knoten',
8010                       'Footnotes' => 'Fu@ss{}noten',
8011                       'Forward' => 'Nach vorne',
8012                       'Forward section in next file' => '',
8013                       'From 1.2.3 go to' => 'Von 1.2.3 gehe zu',
8014                       'Go to' => 'Gehe zu',
8015                       'Index' => 'Index',
8016                       'Index Entry' => 'Indexeintrag',
8017                       'January' => 'Januar',
8018                       'July' => 'Juli',
8019                       'Jump to' => 'Springe zu',
8020                       'June' => 'Juni',
8021                       'Last' => '',
8022                       'Last section in reading order' => 'Letzter Abschnitt in Lesereihenfolge',
8023                       'March' => 'M@"arz',
8024                       'May' => 'Mai',
8025                       'Menu:' => 'Auswahl:',
8026                       'Name' => 'Name',
8027                       'Next' => '',
8028                       'Next chapter' => 'N@"achstes Kapitel',
8029                       'Next file' => '',
8030                       'Next node' => 'N@"achster Knoten',
8031                       'Next section in reading order' => 'N@"achster Abschnitt in Lesereihenfolge',
8032                       'Next section on same level' => 'N@"achster Abschitt derselben Ebene',
8033                       'NextFile' => '',
8034                       'Node following in node reading order' => 'N@"achster Abschnitt in Lesereihenfolge',
8035                       'Node up' => 'Knoten nach oben',
8036                       'NodeNext' => '',
8037                       'NodePrev' => '',
8038                       'NodeUp' => '',
8039                       'November' => 'November',
8040                       'October' => 'Oktober',
8041                       'Overview' => '@"Ubersicht',
8042                       'Overview:' => '@"Ubersicht:',
8043                       'Prev' => '',
8044                       'PrevFile' => '',
8045                       'Previous file' => '',
8046                       'Previous node' => 'Voriger Knoten',
8047                       'Previous section in reading order' => 'Voriger Abschnitt in Lesereihenfolge',
8048                       'Previous section on same level' => 'Voriger Abschnitt derselben Ebene',
8049                       'Section' => 'Abschnitt',
8050                       'Section One' => 'Abschnitt 1',
8051                       'See %{node_file_href}' => 'Siehe %{node_file_href}',
8052                       'See %{node_file_href} @cite{%{book}}' => 'Siehe %{node_file_href} @cite{%{book}}',
8053                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Siehe %{node_file_href} in Abschnitt `%{section}\' in @cite{%{book}}',
8054                       'See %{reference_name}' => '',
8055                       'See @cite{%{book}}' => '',
8056                       'See section %{reference_name}' => '',
8057                       'See section `%{section}\' in @cite{%{book}}' => 'Siehe Abschnitt `%{section}\' in @cite{%{book}}',
8058                       'September' => 'September',
8059                       'Short Table of Contents' => 'Kurzes Inhaltsverzeichnis',
8060                       'Short table of contents' => 'Kurzes Inhaltsverzeichnis',
8061                       'Subsection One-Four' => 'Unterabschnitt 1-4',
8062                       'Subsection One-One' => 'Unterabschnitt 1-1',
8063                       'Subsection One-Three' => 'Unterabschnitt 1-3',
8064                       'Subsection One-Two' => 'Unterabschnitt 1-2',
8065                       'Subsubsection One-Two-Four' => 'Unterabschnitt 1-2-4',
8066                       'Subsubsection One-Two-One' => 'Unterabschnitt 1-2-1',
8067                       'Subsubsection One-Two-Three' => 'Unterabschnitt 1-2-3',
8068                       'Subsubsection One-Two-Two' => 'Unterabschnitt 1-2-2',
8069                       'T2H_today' => '',
8070                       'Table of Contents' => 'Inhaltsverzeichnis',
8071                       'Table of contents' => 'Inhaltsverzeichnis',
8072                       'The node you are looking for is at %{href}.' => 'Der Knoten, den Sie sehen, befindet sich bei %{href}',
8073                       'This' => '',
8074                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Dieses Dokument wurde erzeugt von @emph{%{user}} am @emph{%{date}} durch @uref{%{program_homepage}, @emph{%{program}}}.',
8075                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Dieses Dokument wurde erzeugt von @emph{%{user}} durch @uref{%{program_homepage}, @emph{%{program}}}.',
8076                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Dieses Dokument wurde erzeugt am @i{%{date}} durch @uref{%{program_homepage}, @i{%{program}}}.',
8077                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Dieses Dokument wurde erzeugt durch @uref{%{program_homepage}, @emph{%{program}}}.',
8078                       'Top' => 'Anfang',
8079                       'Untitled Document' => 'Unbenanntes Dokumen',
8080                       'Up' => 'Nach oben',
8081                       'Up node' => 'Knoten nach oben',
8082                       'Up section' => 'Abschnitt nach oben',
8083                       'by @emph{%{user}}' => 'von @emph{%{user}}',
8084                       'by @emph{%{user}} on @emph{%{date}}' => 'von @emph{%{user}} am @emph{%{date}}',
8085                       'current' => '',
8086                       'on @emph{%{date}}' => 'am @emph{%{date}}',
8087                       'section `%{section}\' in @cite{%{book}}' => 'Abschnitt `%{section}\' in @cite{%{book}}',
8088                       'see %{node_file_href}' => 'siehe %{node_file_href}',
8089                       'see %{node_file_href} @cite{%{book}}' => 'siehe %{node_file_href} @cite{%{book}}',
8090                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'siehe %{node_file_href} im Abschnitt `%{section}\' in @cite{%{book}}',
8091                       'see %{reference_name}' => 'siehe %{reference_name}',
8092                       'see @cite{%{book}}' => 'siehe @cite{%{book}}',
8093                       'see section %{reference_name}' => 'siehe Abschnitt %{reference_name}',
8094                       'see section `%{section}\' in @cite{%{book}}' => 'siehe Abschnitt `%{section}\' in @cite{%{book}}',
8095                       'unknown' => 'unbekannt'
8096                     };
8097
8098$T2H_OBSOLETE_STRINGS->{'de'} = {
8099                                  'See' => 'Siehe',
8100                                  'section' => 'Abschnitt',
8101                                  'see' => 'siehe'
8102                                };
8103
8104
8105$LANGUAGES->{'en'} = {
8106                       '  The buttons in the navigation panels have the following meaning:' => '',
8107                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
8108                       ' Up ' => '',
8109                       '%{acronym_like} (%{explanation})' => '',
8110                       '%{month} %{day}, %{year}' => '',
8111                       '%{name} of %{class}' => '',
8112                       '%{name} on %{class}' => '',
8113                       '%{node_file_href}' => '',
8114                       '%{node_file_href} @cite{%{book}}' => '',
8115                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8116                       '%{reference_name}' => '',
8117                       '%{style} %{number}' => '',
8118                       '%{style}: %{caption_first_line}' => '',
8119                       '%{style}: %{shortcaption_first_line}' => '',
8120                       '@b{%{quotation_arg}:} ' => '',
8121                       '@cite{%{book}}' => '',
8122                       'About' => '',
8123                       'About (help)' => '',
8124                       'About This Document' => '',
8125                       'April' => '',
8126                       'August' => '',
8127                       'Back' => '',
8128                       'Back section in previous file' => '',
8129                       'Beginning of this chapter or previous chapter' => '',
8130                       'Button' => '',
8131                       'Contents' => '',
8132                       'Cover (top) of document' => '',
8133                       'Current Position' => '',
8134                       'Current section' => '',
8135                       'December' => '',
8136                       'FastBack' => '',
8137                       'FastForward' => '',
8138                       'February' => '',
8139                       'First' => '',
8140                       'First section in reading order' => '',
8141                       'Following' => '',
8142                       'Following node' => '',
8143                       'Footnotes' => '',
8144                       'Forward' => '',
8145                       'Forward section in next file' => '',
8146                       'From 1.2.3 go to' => '',
8147                       'Go to' => '',
8148                       'Index' => '',
8149                       'Index Entry' => '',
8150                       'January' => '',
8151                       'July' => '',
8152                       'Jump to' => '',
8153                       'June' => '',
8154                       'Last' => '',
8155                       'Last section in reading order' => '',
8156                       'March' => '',
8157                       'May' => '',
8158                       'Menu:' => '',
8159                       'Name' => '',
8160                       'Next' => '',
8161                       'Next chapter' => '',
8162                       'Next file' => '',
8163                       'Next node' => '',
8164                       'Next section in reading order' => '',
8165                       'Next section on same level' => '',
8166                       'NextFile' => '',
8167                       'Node following in node reading order' => '',
8168                       'Node up' => '',
8169                       'NodeNext' => '',
8170                       'NodePrev' => '',
8171                       'NodeUp' => '',
8172                       'November' => '',
8173                       'October' => '',
8174                       'Overview' => '',
8175                       'Overview:' => '',
8176                       'Prev' => '',
8177                       'PrevFile' => '',
8178                       'Previous file' => '',
8179                       'Previous node' => '',
8180                       'Previous section in reading order' => '',
8181                       'Previous section on same level' => '',
8182                       'Section' => '',
8183                       'Section One' => '',
8184                       'See %{node_file_href}' => '',
8185                       'See %{node_file_href} @cite{%{book}}' => '',
8186                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8187                       'See %{reference_name}' => '',
8188                       'See @cite{%{book}}' => '',
8189                       'See section %{reference_name}' => '',
8190                       'See section `%{section}\' in @cite{%{book}}' => '',
8191                       'September' => '',
8192                       'Short Table of Contents' => '',
8193                       'Short table of contents' => '',
8194                       'Subsection One-Four' => '',
8195                       'Subsection One-One' => '',
8196                       'Subsection One-Three' => '',
8197                       'Subsection One-Two' => '',
8198                       'Subsubsection One-Two-Four' => '',
8199                       'Subsubsection One-Two-One' => '',
8200                       'Subsubsection One-Two-Three' => '',
8201                       'Subsubsection One-Two-Two' => '',
8202                       'T2H_today' => '%s, %d %d',
8203                       'Table of Contents' => '',
8204                       'Table of contents' => '',
8205                       'The node you are looking for is at %{href}.' => '',
8206                       'This' => '',
8207                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8208                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8209                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
8210                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8211                       'Top' => '',
8212                       'Untitled Document' => '',
8213                       'Up' => '',
8214                       'Up node' => '',
8215                       'Up section' => '',
8216                       'by @emph{%{user}}' => '',
8217                       'by @emph{%{user}} on @emph{%{date}}' => '',
8218                       'current' => '',
8219                       'on @emph{%{date}}' => '',
8220                       'section `%{section}\' in @cite{%{book}}' => '',
8221                       'see %{node_file_href}' => '',
8222                       'see %{node_file_href} @cite{%{book}}' => '',
8223                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8224                       'see %{reference_name}' => '',
8225                       'see @cite{%{book}}' => '',
8226                       'see section %{reference_name}' => '',
8227                       'see section `%{section}\' in @cite{%{book}}' => '',
8228                       'unknown' => ''
8229                     };
8230
8231$T2H_OBSOLETE_STRINGS->{'en'} = {};
8232
8233
8234$LANGUAGES->{'es'} = {
8235                       '  The buttons in the navigation panels have the following meaning:' => '  Los botones de los paneles de navegaci@\'on tienen el significado siguiente:',
8236                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '  donde el @strong{ Ejemplo } supone que la posición actual está en la @strong{ Sub-subsecci@\'on uno-dos-tres } de un documento de la estructura siguiente:',
8237                       ' Up ' => ' Subir ',
8238                       '%{acronym_like} (%{explanation})' => '',
8239                       '%{month} %{day}, %{year}' => 'el %{day} %{month} %{year}',
8240                       '%{name} of %{class}' => '%{name} de %{class}',
8241                       '%{name} on %{class}' => '%{name} en %{class}',
8242                       '%{node_file_href}' => '',
8243                       '%{node_file_href} @cite{%{book}}' => '',
8244                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} secci@\'on `%{section}\' en @cite{%{book}}',
8245                       '%{reference_name}' => '',
8246                       '%{style} %{number}' => '',
8247                       '%{style}: %{caption_first_line}' => '',
8248                       '%{style}: %{shortcaption_first_line}' => '',
8249                       '@b{%{quotation_arg}:} ' => '',
8250                       '@cite{%{book}}' => '',
8251                       'About' => 'Acerca de',
8252                       'About (help)' => 'Acerca de (p@\'agina de ayuda)',
8253                       'About This Document' => 'Acerca de este documento',
8254                       'April' => 'abril',
8255                       'August' => 'agosto',
8256                       'Back' => 'Atr@\'as',
8257                       'Back section in previous file' => 'Retroceder secci@\'on en el archivo anterior',
8258                       'Beginning of this chapter or previous chapter' => 'Inicio de este cap@\'itulo o cap@\'itulo anterior',
8259                       'Button' => 'Bot@\'on',
8260                       'Contents' => '@\'Indice general',
8261                       'Cover (top) of document' => 'Portada del documento',
8262                       'Current Position' => 'Posici@\'on actual',
8263                       'Current section' => 'Secci@\'on actual',
8264                       'December' => 'diciembre',
8265                       'FastBack' => 'Retroceso r@\'apido',
8266                       'FastForward' => 'Avance r@\'apido',
8267                       'February' => 'febrero',
8268                       'First' => 'Primero',
8269                       'First section in reading order' => 'Primera secci@\'on en orden de lectura',
8270                       'Following' => 'Siguiente',
8271                       'Following node' => 'Nodo siguiente',
8272                       'Footnotes' => 'Notas el pie',
8273                       'Forward' => 'Adelante',
8274                       'Forward section in next file' => 'Avanzar secci@\'on en el pr@\'oximo archivo',
8275                       'From 1.2.3 go to' => 'Desde 1.2.3 ir a',
8276                       'Go to' => 'Ir a',
8277                       'Index' => '@\'Indice',
8278                       'Index Entry' => 'Entrada de @\'indice',
8279                       'January' => 'enero',
8280                       'July' => 'julio',
8281                       'Jump to' => 'Saltar a',
8282                       'June' => 'junio',
8283                       'Last' => '@\'Ultimo',
8284                       'Last section in reading order' => '@\'Ultima secci@\'on en orden de lectura',
8285                       'March' => 'marzo',
8286                       'May' => 'mayo',
8287                       'Menu:' => 'Men@\'u:',
8288                       'Name' => 'Nombre',
8289                       'Next' => 'Siguiente',
8290                       'Next chapter' => 'Cap@\'itulo siguiente',
8291                       'Next file' => 'Archivo siguiente',
8292                       'Next node' => 'Nodo siguiente',
8293                       'Next section in reading order' => 'Secci@\'on siguiente en orden de lectura',
8294                       'Next section on same level' => 'Secci@\'on siguiente en el mismo nivel',
8295                       'NextFile' => 'ArchivoSiguiente',
8296                       'Node following in node reading order' => 'Nodo siguiente en orden de lectura de nodos',
8297                       'Node up' => 'Subir nodo',
8298                       'NodeNext' => 'NodoSiguiente',
8299                       'NodePrev' => 'NodoAnterior',
8300                       'NodeUp' => 'SubirNodo',
8301                       'November' => 'noviembre',
8302                       'October' => 'octubre',
8303                       'Overview' => 'Panor@\'amica',
8304                       'Overview:' => 'Panor@\'amica:',
8305                       'Prev' => 'Ant',
8306                       'PrevFile' => 'ArchivoAnt',
8307                       'Previous file' => 'Archivo anterior',
8308                       'Previous node' => 'Nodo anterior',
8309                       'Previous section in reading order' => 'Secci@\'on anterior en orden de lectura',
8310                       'Previous section on same level' => 'Secci@\'on anterior en el mismo nivel',
8311                       'Section' => 'Secci@\'on',
8312                       'Section One' => 'Secci@\'on Uno',
8313                       'See %{node_file_href}' => 'V@\'ease %{node_file_href}',
8314                       'See %{node_file_href} @cite{%{book}}' => 'V@\'ease %{node_file_href} @cite{%{book}}',
8315                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'V@\'ease %{node_file_href} secci@\'on `%{section}\' en @cite{%{book}}',
8316                       'See %{reference_name}' => 'V@\'ease %{reference_name}',
8317                       'See @cite{%{book}}' => 'V@\'ease @cite{%{book}}',
8318                       'See section %{reference_name}' => 'V@\'ease la secci@\'on  %{reference_name}',
8319                       'See section `%{section}\' in @cite{%{book}}' => 'V@\'ease la secci@\'on `%{section}\' en @cite{%{book}}',
8320                       'September' => 'septiembre',
8321                       'Short Table of Contents' => 'Resumen del Contenido',
8322                       'Short table of contents' => 'Resumen del contenido',
8323                       'Subsection One-Four' => 'Subsecci@\'on uno-cuatro',
8324                       'Subsection One-One' => 'Subsecci@\'on uno-uno',
8325                       'Subsection One-Three' => 'Subsecci@\'on uno-tres',
8326                       'Subsection One-Two' => 'Subsecci@\'on uno-dos',
8327                       'Subsubsection One-Two-Four' => 'Sub-subsecci@\'on uno-dos-cuatro',
8328                       'Subsubsection One-Two-One' => 'Sub-subsecci@\'on uno-dos-uno',
8329                       'Subsubsection One-Two-Three' => 'Sub-subsecci@\'on uno-dos-tres',
8330                       'Subsubsection One-Two-Two' => 'Sub-subsecci@\'on uno-dos-dos',
8331                       'T2H_today' => '%2$d %1$s %3$d',
8332                       'Table of Contents' => '@\'{@dotless{I}}ndice General',
8333                       'Table of contents' => '@\'{@dotless{I}}ndice general',
8334                       'The node you are looking for is at %{href}.' => 'El nodo que busca se encuentra en %{href}.',
8335                       'This' => 'Este',
8336                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Este documento ha sido generado por @emph{%{user}} el @emph{%{date}} utilizando @uref{%{program_homepage}, @emph{%{program}}}.',
8337                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Este documento ha sido generado por @emph{%{user}} utilizando @uref{%{program_homepage}, @emph{%{program}}}.',
8338                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Este documento se generó el @i{%{date}} utilizando @uref{%{program_homepage}, @i{%{program}}}.',
8339                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Este documento se generó utilizando @uref{%{program_homepage}, @emph{%{program}}}.',
8340                       'Top' => 'Arriba',
8341                       'Untitled Document' => 'Documento sin t@\'itulo',
8342                       'Up' => 'Subir',
8343                       'Up node' => 'Subir nodo',
8344                       'Up section' => 'Subir secci@\'on',
8345                       'by @emph{%{user}}' => 'por @emph{%{user}',
8346                       'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} el @emph{%{date}}',
8347                       'current' => 'actual',
8348                       'on @emph{%{date}}' => 'el @emph{%{date}}',
8349                       'section `%{section}\' in @cite{%{book}}' => 'secci@\'on `%{section}\' en @cite{%{book}}',
8350                       'see %{node_file_href}' => 'v@\'ease %{node_file_href}',
8351                       'see %{node_file_href} @cite{%{book}}' => 'v@\'ease %{node_file_href} @cite{%{book}}',
8352                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'v@\'ease %{node_file_href} secci@\'on `%{section}\' en @cite{%{book}}',
8353                       'see %{reference_name}' => 'v@\'ease %{reference_name}',
8354                       'see @cite{%{book}}' => 'v@\'ease @cite{%{book}}',
8355                       'see section %{reference_name}' => 'v@\'ease la secci@\'on %{reference_name}',
8356                       'see section `%{section}\' in @cite{%{book}}' => 'v@\'ease la secci@\'on `%{section}\' en @cite{%{book}}',
8357                       'unknown' => 'desconocido'
8358                     };
8359
8360$T2H_OBSOLETE_STRINGS->{'es'} = {
8361                                  'See' => 'V@\'ease',
8362                                  'section' => 'secci@\'on',
8363                                  'see' => 'v@\'ease'
8364                                };
8365
8366
8367$LANGUAGES->{'fr'} = {
8368                       '  The buttons in the navigation panels have the following meaning:' => '  Les boutons de navigation ont la signification suivante :',
8369                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '  Dans cet exemple on est @`a @strong{ Sous sous section un-deux-trois } dans un document dont la structure est :',
8370                       ' Up ' => 'Plus haut',
8371                       '%{acronym_like} (%{explanation})' => '',
8372                       '%{month} %{day}, %{year}' => 'le %{day} %{month} %{year}',
8373                       '%{name} of %{class}' => '%{name} de %{class}',
8374                       '%{name} on %{class}' => '%{name} de %{class}',
8375                       '%{node_file_href}' => '',
8376                       '%{node_file_href} @cite{%{book}}' => '',
8377                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} section `%{section}\' dans @cite{%{book}}',
8378                       '%{reference_name}' => '',
8379                       '%{style} %{number}' => '',
8380                       '%{style}: %{caption_first_line}' => '',
8381                       '%{style}: %{shortcaption_first_line}' => '',
8382                       '@b{%{quotation_arg}:} ' => '',
8383                       '@cite{%{book}}' => '',
8384                       'About' => 'A propos',
8385                       'About (help)' => 'A propos (page d\'aide)',
8386                       'About This Document' => 'A propos de ce document',
8387                       'April' => 'avril',
8388                       'August' => 'ao@^ut',
8389                       'Back' => 'Retour',
8390                       'Back section in previous file' => '',
8391                       'Beginning of this chapter or previous chapter' => 'D@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent',
8392                       'Button' => 'Bouton',
8393                       'Contents' => 'Table des mati@`eres',
8394                       'Cover (top) of document' => 'Couverture (top) du document',
8395                       'Current Position' => 'Position',
8396                       'Current section' => 'Section actuelle',
8397                       'December' => 'd@\'ecembre',
8398                       'FastBack' => 'RetourRapide',
8399                       'FastForward' => 'AvanceRapide',
8400                       'February' => 'f@\'evrier',
8401                       'First' => 'Premier',
8402                       'First section in reading order' => 'Premi@`e section dans l\'ordre de lecture',
8403                       'Following' => 'Suivant',
8404                       'Following node' => 'N@oe{}ud suivant',
8405                       'Footnotes' => 'Notes de bas de page',
8406                       'Forward' => 'Avant',
8407                       'Forward section in next file' => '',
8408                       'From 1.2.3 go to' => 'Depuis 1.2.3 aller @`a',
8409                       'Go to' => 'Aller @`a',
8410                       'Index' => 'Index',
8411                       'Index Entry' => 'Entr@\'ee d\'index',
8412                       'January' => 'janvier',
8413                       'July' => 'juillet',
8414                       'Jump to' => 'Aller @`a',
8415                       'June' => 'juin',
8416                       'Last' => 'Dernier',
8417                       'Last section in reading order' => 'Derni@`ere section dans l\'ordre de lecture',
8418                       'March' => 'mars',
8419                       'May' => 'mai',
8420                       'Menu:' => 'Menu@ :',
8421                       'Name' => 'Nom',
8422                       'Next' => 'Suivant',
8423                       'Next chapter' => 'Chapitre suivant',
8424                       'Next file' => 'Fichier suivant',
8425                       'Next node' => 'N@oe{}ud suivant',
8426                       'Next section in reading order' => 'Section suivante dans l\'ordre de lecture',
8427                       'Next section on same level' => 'Section suivante au m@^eme niveau',
8428                       'NextFile' => 'FichierSuivant',
8429                       'Node following in node reading order' => 'N@oe{}ud suivant dans l\'ordre de lecture',
8430                       'Node up' => 'N@oe{}ud au dessus',
8431                       'NodeNext' => 'N@oe{}udSuivant',
8432                       'NodePrev' => 'N@oe{}udPr@\'ec@\'edent',
8433                       'NodeUp' => 'N@oe{}udMonter',
8434                       'November' => 'novembre',
8435                       'October' => 'octobre',
8436                       'Overview' => 'Vue d\'ensemble',
8437                       'Overview:' => 'Vue d\'ensemble@ :',
8438                       'Prev' => 'Pr@\'ec@\'edent',
8439                       'PrevFile' => '',
8440                       'Previous file' => 'Fichier pr@\'ec@\'edent',
8441                       'Previous node' => 'N@oe{}ud pr@\'ec@\'edent',
8442                       'Previous section in reading order' => 'Section pr@\'ec@\'edente dans l\'ordre de lecture',
8443                       'Previous section on same level' => 'Section pr@\'ec@\'edente au m@^eme niveau',
8444                       'Section' => '',
8445                       'Section One' => 'Section un',
8446                       'See %{node_file_href}' => 'Voir %{node_file_href}',
8447                       'See %{node_file_href} @cite{%{book}}' => 'Voir %{node_file_href} @cite{%{book}}',
8448                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Voir %{node_file_href} section `%{section}\' dans @cite{%{book}}',
8449                       'See %{reference_name}' => 'Voir %{reference_name}',
8450                       'See @cite{%{book}}' => 'Voir @cite{%{book}}',
8451                       'See section %{reference_name}' => 'Voir la section %{reference_name}',
8452                       'See section `%{section}\' in @cite{%{book}}' => 'Voir la section `%{section}\' dans @cite{%{book}}',
8453                       'September' => 'septembre',
8454                       'Short Table of Contents' => 'R@\'esum@\'e du contenu',
8455                       'Short table of contents' => 'R@\'esum@\'e du contenu',
8456                       'Subsection One-Four' => 'Sous section un-quatre',
8457                       'Subsection One-One' => 'Sous section un-un',
8458                       'Subsection One-Three' => 'Sous section un-trois',
8459                       'Subsection One-Two' => 'Sous section un-deux',
8460                       'Subsubsection One-Two-Four' => 'Sous sous section un-deux-quatre',
8461                       'Subsubsection One-Two-One' => 'Sous sous section un-deux-un',
8462                       'Subsubsection One-Two-Three' => 'Sous sous section un-deux-trois',
8463                       'Subsubsection One-Two-Two' => 'Sous sous section un-deux-deux',
8464                       'T2H_today' => '%2$d %1$s %3$d',
8465                       'Table of Contents' => 'Table des mati@`eres',
8466                       'Table of contents' => 'Table des mati@`eres',
8467                       'The node you are looking for is at %{href}.' => 'Le n@oe{}ud que vous recherchez est ici@ : %{href}.',
8468                       'This' => 'Ici',
8469                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e le @emph{%{date}} par @emph{%{user}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.',
8470                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.',
8471                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e le @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}',
8472                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e en utilisant @uref{%{program_homepage}, @emph{%{program}}}.',
8473                       'Top' => 'Racine',
8474                       'Untitled Document' => 'Document sans titre',
8475                       'Up' => 'Monter',
8476                       'Up node' => 'N@oe{}ud au dessus',
8477                       'Up section' => 'Section sup@\'erieure',
8478                       'by @emph{%{user}}' => 'par @emph{%{user}}',
8479                       'by @emph{%{user}} on @emph{%{date}}' => 'par @emph{%{user}} le @emph{%{date}}',
8480                       'current' => 'courante',
8481                       'on @emph{%{date}}' => 'le @emph{%{date}}',
8482                       'section `%{section}\' in @cite{%{book}}' => 'section `%{section}\' dans @cite{%{book}}',
8483                       'see %{node_file_href}' => 'voir %{node_file_href}',
8484                       'see %{node_file_href} @cite{%{book}}' => 'voir %{node_file_href} @cite{%{book}}',
8485                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'voir %{node_file_href} section `%{section}\' dans @cite{%{book}}',
8486                       'see %{reference_name}' => 'voir %{reference_name}',
8487                       'see @cite{%{book}}' => 'voir @cite{%{book}}',
8488                       'see section %{reference_name}' => 'voir la section %{reference_name}',
8489                       'see section `%{section}\' in @cite{%{book}}' => 'voir la section `%{section}\' dans @cite{{book}}',
8490                       'unknown' => 'inconnu'
8491                     };
8492
8493$T2H_OBSOLETE_STRINGS->{'fr'} = {
8494                                  '  This document was generated %{who_and_when_generated} using %{program_homepage_href}.' => '  Ce document a &eacute;t&eacute; g&eacute;n&eacute;r&eacute; %{who_and_when_generated} en utilisant %{program_homepage_href}.',
8495                                  '  where the <strong> Example </strong> assumes that the current position is at <strong> Subsubsection One-Two-Three </strong> of a document of the following structure:' => '  Dans cet exemple on est &agrave; <strong> Sous section un-deux-trois </strong> dans un document dont la structure est :',
8496                                  '%{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => '%{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
8497                                  'See' => 'Voir',
8498                                  'See %{node_file_href} <cite>%{book}</cite>' => 'Voir %{node_file_href} <cite>%{book}</cite>',
8499                                  'See %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'Voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
8500                                  'See <cite>%{book}</cite>' => 'Voir <cite>%{book}</cite>',
8501                                  'See section `%{section}\' in <cite>%{book}</cite>' => 'Voir la section `%{section}\' dans <cite>%{book}</cite>',
8502                                  'This document was generated by <i>%{user}</i> on <i>%{date}</i> using %{program_homepage_href}.' => 'Ce document a &eacute;t&eacute; g&eacute;n&eacute;r&eacute; par <i>%{user}</i> <i>%{date}</i> en utilisant %{program_homepage_href}.',
8503                                  'This document was generated by <i>%{user}</i> using %{program_homepage_href}.' => 'Ce document a &eacute;t&eacute; g&eacute;n&eacute;r&eacute; par <i>%{user}</i> en utilisant %{program_homepage_href}.',
8504                                  'This document was generated by @emph{%{user}} on @emph{%{date}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} @emph{%{date}} en utilisant %{program_homepage_href}.',
8505                                  'This document was generated by @emph{%{user}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} en utilisant %{program_homepage_href}.',
8506                                  'This document was generated on <i>%{date}</i> using %{program_homepage_href}.' => 'Ce document a &eacute;t&eacute; g&eacute;n&eacute;r&eacute; <i>%{date}</i> en utilisant %{program_homepage_href}.',
8507                                  'This document was generated on @emph{%{date}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant %{program_homepage_href}.',
8508                                  'This document was generated on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.',
8509                                  'This document was generated using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e en utilisant %{program_homepage_href}.',
8510                                  'about (help)' => '@`a propos (page d\'aide)',
8511                                  'about (this page)' => 'a propos (cette page)',
8512                                  'beginning of this chapter or previous chapter' => 'd@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent',
8513                                  'by <i>%{user}</i>' => 'par <i>%{user}</i>',
8514                                  'by <i>%{user}</i> on <i>%{date}</i>' => 'par <i>%{user}</i> <i>%{date}</i>',
8515                                  'concept index' => 'index',
8516                                  'cover (top) of document' => 'couverture (top) du document',
8517                                  'current section' => 'section actuelle',
8518                                  'first section in reading order' => 'premi@`e section dans l\'ordre de lecture',
8519                                  'following node' => 'node suivant',
8520                                  'index' => 'index',
8521                                  'last section in reading order' => 'derni@`ere section dans l\'ordre de lecture',
8522                                  'next chapter' => 'chapitre suivant',
8523                                  'next node' => 'node suivant',
8524                                  'next section in reading order' => 'section suivante dans l\'ordre de lecture',
8525                                  'next section on same level' => 'section suivante au m@^eme niveau',
8526                                  'node following in node reading order' => 'node suivant dans l\'ordre des nodes',
8527                                  'node up' => 'node au dessus',
8528                                  'on <i>%{date}</i>' => '<i>%{date}</i>',
8529                                  'previous node' => 'node pr@\'ec@\'edent',
8530                                  'previous section in reading order' => 'section pr@\'ec@\'edente dans l\'ordre de lecture',
8531                                  'previous section on same level' => 'section pr@\'ec@\'edente au m@^eme niveau',
8532                                  'section' => 'section',
8533                                  'section `%{section}\' in <cite>%{book}</cite>' => 'section `%{section}\' dans <cite>%{book}</cite>',
8534                                  'see' => 'voir',
8535                                  'see %{node_file_href} <cite>%{book}</cite>' => 'voir %{node_file_href} <cite>%{book}</cite>',
8536                                  'see %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
8537                                  'see <cite>%{book}</cite>' => 'voir <cite>%{book}</cite>',
8538                                  'see section `%{section}\' in <cite>%{book}</cite>' => 'voir la section `%{section}\' dans <cite>%{book}</cite>',
8539                                  'short table of contents' => 'table des mati@`eres r@\'esum@\'ee',
8540                                  'table of contents' => 'table des mati@`eres',
8541                                  'up node' => 'node au dessus',
8542                                  'up section' => 'section sup@\'erieure'
8543                                };
8544
8545
8546$LANGUAGES->{'ja'} = {
8547                       '  The buttons in the navigation panels have the following meaning:' => 'ナビゲーションパネル中のボタンには以下の意味があります。',
8548                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '@strong{例}では、以下に示す構造を持つ文書の@strong{1.2.3項}を現在位置に仮定しています。',
8549                       ' Up ' => '上',
8550                       '%{acronym_like} (%{explanation})' => '',
8551                       '%{month} %{day}, %{year}' => '%{year}年%{month}月%{day}日',
8552                       '%{name} of %{class}' => '',
8553                       '%{name} on %{class}' => '',
8554                       '%{node_file_href}' => '',
8555                       '%{node_file_href} @cite{%{book}}' => '',
8556                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8557                       '%{reference_name}' => '',
8558                       '%{style} %{number}' => '',
8559                       '%{style}: %{caption_first_line}' => '',
8560                       '%{style}: %{shortcaption_first_line}' => '',
8561                       '@b{%{quotation_arg}:} ' => '',
8562                       '@cite{%{book}}' => '',
8563                       'About' => '',
8564                       'About (help)' => '',
8565                       'About This Document' => 'この文書について',
8566                       'April' => '4月',
8567                       'August' => '8月',
8568                       'Back' => '',
8569                       'Back section in previous file' => '',
8570                       'Beginning of this chapter or previous chapter' => '',
8571                       'Button' => 'ボタン',
8572                       'Contents' => '目次',
8573                       'Cover (top) of document' => '',
8574                       'Current Position' => '現在位置',
8575                       'Current section' => '',
8576                       'December' => '12月',
8577                       'FastBack' => '',
8578                       'FastForward' => '',
8579                       'February' => '2月',
8580                       'First' => '',
8581                       'First section in reading order' => '',
8582                       'Following' => '',
8583                       'Following node' => '',
8584                       'Footnotes' => '脚注',
8585                       'Forward' => '',
8586                       'Forward section in next file' => '',
8587                       'From 1.2.3 go to' => '1.2.3項からの移動先',
8588                       'Go to' => '移動先',
8589                       'Index' => '見出し',
8590                       'Index Entry' => '見出し一覧',
8591                       'January' => '1月',
8592                       'July' => '7月',
8593                       'Jump to' => '移動',
8594                       'June' => '6月',
8595                       'Last' => '',
8596                       'Last section in reading order' => '',
8597                       'March' => '3月',
8598                       'May' => '5月',
8599                       'Menu:' => 'メニュー',
8600                       'Name' => '名称',
8601                       'Next' => '次',
8602                       'Next chapter' => '',
8603                       'Next file' => '',
8604                       'Next node' => '',
8605                       'Next section in reading order' => '',
8606                       'Next section on same level' => '',
8607                       'NextFile' => '',
8608                       'Node following in node reading order' => '',
8609                       'Node up' => '',
8610                       'NodeNext' => '',
8611                       'NodePrev' => '',
8612                       'NodeUp' => '',
8613                       'November' => '11月',
8614                       'October' => '10月',
8615                       'Overview' => '概要',
8616                       'Overview:' => '概要:',
8617                       'Prev' => '前',
8618                       'PrevFile' => '',
8619                       'Previous file' => '',
8620                       'Previous node' => '',
8621                       'Previous section in reading order' => '',
8622                       'Previous section on same level' => '',
8623                       'Section' => '項',
8624                       'Section One' => '第1項',
8625                       'See %{node_file_href}' => '',
8626                       'See %{node_file_href} @cite{%{book}}' => '',
8627                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8628                       'See %{reference_name}' => '',
8629                       'See @cite{%{book}}' => '',
8630                       'See section %{reference_name}' => '',
8631                       'See section `%{section}\' in @cite{%{book}}' => '',
8632                       'September' => '9月',
8633                       'Short Table of Contents' => '簡略化した目次',
8634                       'Short table of contents' => '',
8635                       'Subsection One-Four' => '第1.4項',
8636                       'Subsection One-One' => '第1.1項',
8637                       'Subsection One-Three' => '第1.3項',
8638                       'Subsection One-Two' => '第1.2項',
8639                       'Subsubsection One-Two-Four' => '第1.2.4項',
8640                       'Subsubsection One-Two-One' => '第1.2.1項',
8641                       'Subsubsection One-Two-Three' => '第1.2.3項',
8642                       'Subsubsection One-Two-Two' => '第1.2.2項',
8643                       'T2H_today' => '%s, %d %d',
8644                       'Table of Contents' => '目次',
8645                       'Table of contents' => '',
8646                       'The node you are looking for is at %{href}.' => '',
8647                       'This' => '',
8648                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@emph{%{user}}によって@emph{%{date}}に@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
8649                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@emph{%{user}}によって@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
8650                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'この文書は@emph{%{date}}に@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
8651                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
8652                       'Top' => '冒頭',
8653                       'Untitled Document' => '無題の文書',
8654                       'Up' => '',
8655                       'Up node' => '',
8656                       'Up section' => '',
8657                       'by @emph{%{user}}' => '@emph{%{user}}',
8658                       'by @emph{%{user}} on @emph{%{date}}' => '@emph{%{user}}, @emph{%{date}',
8659                       'current' => '現在位置',
8660                       'on @emph{%{date}}' => '@emph{%{date}}',
8661                       'section `%{section}\' in @cite{%{book}}' => '@cite{%{book}}の `%{section}\' ',
8662                       'see %{node_file_href}' => '%{node_file_href}参照',
8663                       'see %{node_file_href} @cite{%{book}}' => '%{node_file_href} @cite{%{book}}参照',
8664                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8665                       'see %{reference_name}' => '',
8666                       'see @cite{%{book}}' => '',
8667                       'see section %{reference_name}' => '',
8668                       'see section `%{section}\' in @cite{%{book}}' => '',
8669                       'unknown' => '不明'
8670                     };
8671
8672$T2H_OBSOLETE_STRINGS->{'ja'} = {
8673                                  'about (help)' => '使用法 (ヘルプ)',
8674                                  'beginning of this chapter or previous chapter' => 'この章または前の章の冒頭',
8675                                  'cover (top) of document' => '文書の表紙 (トップ)',
8676                                  'current section' => '現在の節',
8677                                  'first section in reading order' => '文書順で前の項',
8678                                  'following node' => '次の節',
8679                                  'index' => '見出し',
8680                                  'last section in reading order' => '文書順で最後の項',
8681                                  'next chapter' => '次の章',
8682                                  'next node' => '次の節',
8683                                  'next section in reading order' => '文書順で次の項',
8684                                  'next section on same level' => '同じ階層にある次の項',
8685                                  'node following in node reading order' => '文書順で次の節',
8686                                  'node up' => '上の節へ',
8687                                  'previous node' => '前の節',
8688                                  'previous section in reading order' => '文書順で前の節',
8689                                  'previous section on same level' => '同じ階層にある前の項',
8690                                  'short table of contents' => '簡略化した目次',
8691                                  'table of contents' => '文書の目次',
8692                                  'up node' => '上の節',
8693                                  'up section' => '上の項'
8694                                };
8695
8696
8697$LANGUAGES->{'nl'} = {
8698                       '  The buttons in the navigation panels have the following meaning:' => '',
8699                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
8700                       ' Up ' => '',
8701                       '%{acronym_like} (%{explanation})' => '',
8702                       '%{month} %{day}, %{year}' => '',
8703                       '%{name} of %{class}' => '',
8704                       '%{name} on %{class}' => '',
8705                       '%{node_file_href}' => '',
8706                       '%{node_file_href} @cite{%{book}}' => '',
8707                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8708                       '%{reference_name}' => '',
8709                       '%{style} %{number}' => '',
8710                       '%{style}: %{caption_first_line}' => '',
8711                       '%{style}: %{shortcaption_first_line}' => '',
8712                       '@b{%{quotation_arg}:} ' => '',
8713                       '@cite{%{book}}' => '',
8714                       'About' => '',
8715                       'About (help)' => '',
8716                       'About This Document' => 'No translation available!',
8717                       'April' => 'April',
8718                       'August' => 'Augustus',
8719                       'Back' => '',
8720                       'Back section in previous file' => '',
8721                       'Beginning of this chapter or previous chapter' => '',
8722                       'Button' => '',
8723                       'Contents' => '',
8724                       'Cover (top) of document' => '',
8725                       'Current Position' => '',
8726                       'Current section' => '',
8727                       'December' => 'December',
8728                       'FastBack' => '',
8729                       'FastForward' => '',
8730                       'February' => 'Februari',
8731                       'First' => '',
8732                       'First section in reading order' => '',
8733                       'Following' => '',
8734                       'Following node' => '',
8735                       'Footnotes' => 'No translation available!',
8736                       'Forward' => '',
8737                       'Forward section in next file' => '',
8738                       'From 1.2.3 go to' => '',
8739                       'Go to' => '',
8740                       'Index' => 'Index',
8741                       'Index Entry' => '',
8742                       'January' => 'Januari',
8743                       'July' => 'Juli',
8744                       'Jump to' => '',
8745                       'June' => 'Juni',
8746                       'Last' => '',
8747                       'Last section in reading order' => '',
8748                       'March' => 'Maart',
8749                       'May' => 'Mei',
8750                       'Menu:' => '',
8751                       'Name' => '',
8752                       'Next' => '',
8753                       'Next chapter' => '',
8754                       'Next file' => '',
8755                       'Next node' => '',
8756                       'Next section in reading order' => '',
8757                       'Next section on same level' => '',
8758                       'NextFile' => '',
8759                       'Node following in node reading order' => '',
8760                       'Node up' => '',
8761                       'NodeNext' => '',
8762                       'NodePrev' => '',
8763                       'NodeUp' => '',
8764                       'November' => 'November',
8765                       'October' => 'Oktober',
8766                       'Overview' => '',
8767                       'Overview:' => '',
8768                       'Prev' => '',
8769                       'PrevFile' => '',
8770                       'Previous file' => '',
8771                       'Previous node' => '',
8772                       'Previous section in reading order' => '',
8773                       'Previous section on same level' => '',
8774                       'Section' => '',
8775                       'Section One' => '',
8776                       'See %{node_file_href}' => '',
8777                       'See %{node_file_href} @cite{%{book}}' => '',
8778                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8779                       'See %{reference_name}' => '',
8780                       'See @cite{%{book}}' => '',
8781                       'See section %{reference_name}' => '',
8782                       'See section `%{section}\' in @cite{%{book}}' => '',
8783                       'September' => 'September',
8784                       'Short Table of Contents' => 'Korte inhoudsopgave',
8785                       'Short table of contents' => '',
8786                       'Subsection One-Four' => '',
8787                       'Subsection One-One' => '',
8788                       'Subsection One-Three' => '',
8789                       'Subsection One-Two' => '',
8790                       'Subsubsection One-Two-Four' => '',
8791                       'Subsubsection One-Two-One' => '',
8792                       'Subsubsection One-Two-Three' => '',
8793                       'Subsubsection One-Two-Two' => '',
8794                       'T2H_today' => '',
8795                       'Table of Contents' => 'Inhoudsopgave',
8796                       'Table of contents' => '',
8797                       'The node you are looking for is at %{href}.' => '',
8798                       'This' => '',
8799                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8800                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8801                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
8802                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8803                       'Top' => '',
8804                       'Untitled Document' => '',
8805                       'Up' => '',
8806                       'Up node' => '',
8807                       'Up section' => '',
8808                       'by @emph{%{user}}' => '',
8809                       'by @emph{%{user}} on @emph{%{date}}' => '',
8810                       'current' => '',
8811                       'on @emph{%{date}}' => '',
8812                       'section `%{section}\' in @cite{%{book}}' => '',
8813                       'see %{node_file_href}' => '',
8814                       'see %{node_file_href} @cite{%{book}}' => '',
8815                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8816                       'see %{reference_name}' => '',
8817                       'see @cite{%{book}}' => '',
8818                       'see section %{reference_name}' => '',
8819                       'see section `%{section}\' in @cite{%{book}}' => '',
8820                       'unknown' => ''
8821                     };
8822
8823$T2H_OBSOLETE_STRINGS->{'nl'} = {
8824                                  'See' => 'Zie',
8825                                  'section' => 'sectie',
8826                                  'see' => 'zie'
8827                                };
8828
8829
8830$LANGUAGES->{'no'} = {
8831                       '  The buttons in the navigation panels have the following meaning:' => '',
8832                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
8833                       ' Up ' => '',
8834                       '%{acronym_like} (%{explanation})' => '',
8835                       '%{month} %{day}, %{year}' => '',
8836                       '%{name} of %{class}' => '',
8837                       '%{name} on %{class}' => '',
8838                       '%{node_file_href}' => '',
8839                       '%{node_file_href} @cite{%{book}}' => '',
8840                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8841                       '%{reference_name}' => '',
8842                       '%{style} %{number}' => '',
8843                       '%{style}: %{caption_first_line}' => '',
8844                       '%{style}: %{shortcaption_first_line}' => '',
8845                       '@b{%{quotation_arg}:} ' => '',
8846                       '@cite{%{book}}' => '',
8847                       'About' => '',
8848                       'About (help)' => '',
8849                       'About This Document' => 'No translation available!',
8850                       'April' => 'april',
8851                       'August' => 'august',
8852                       'Back' => '',
8853                       'Back section in previous file' => '',
8854                       'Beginning of this chapter or previous chapter' => '',
8855                       'Button' => '',
8856                       'Contents' => '',
8857                       'Cover (top) of document' => '',
8858                       'Current Position' => '',
8859                       'Current section' => '',
8860                       'December' => 'desember',
8861                       'FastBack' => '',
8862                       'FastForward' => '',
8863                       'February' => 'februar',
8864                       'First' => '',
8865                       'First section in reading order' => '',
8866                       'Following' => '',
8867                       'Following node' => '',
8868                       'Footnotes' => 'No translation available!',
8869                       'Forward' => '',
8870                       'Forward section in next file' => '',
8871                       'From 1.2.3 go to' => '',
8872                       'Go to' => '',
8873                       'Index' => 'Indeks',
8874                       'Index Entry' => '',
8875                       'January' => 'januar',
8876                       'July' => 'juli',
8877                       'Jump to' => '',
8878                       'June' => 'juni',
8879                       'Last' => '',
8880                       'Last section in reading order' => '',
8881                       'March' => 'mars',
8882                       'May' => 'mai',
8883                       'Menu:' => '',
8884                       'Name' => '',
8885                       'Next' => '',
8886                       'Next chapter' => '',
8887                       'Next file' => '',
8888                       'Next node' => '',
8889                       'Next section in reading order' => '',
8890                       'Next section on same level' => '',
8891                       'NextFile' => '',
8892                       'Node following in node reading order' => '',
8893                       'Node up' => '',
8894                       'NodeNext' => '',
8895                       'NodePrev' => '',
8896                       'NodeUp' => '',
8897                       'November' => 'november',
8898                       'October' => 'oktober',
8899                       'Overview' => '',
8900                       'Overview:' => '',
8901                       'Prev' => '',
8902                       'PrevFile' => '',
8903                       'Previous file' => '',
8904                       'Previous node' => '',
8905                       'Previous section in reading order' => '',
8906                       'Previous section on same level' => '',
8907                       'Section' => '',
8908                       'Section One' => '',
8909                       'See %{node_file_href}' => '',
8910                       'See %{node_file_href} @cite{%{book}}' => '',
8911                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8912                       'See %{reference_name}' => '',
8913                       'See @cite{%{book}}' => '',
8914                       'See section %{reference_name}' => '',
8915                       'See section `%{section}\' in @cite{%{book}}' => '',
8916                       'September' => 'september',
8917                       'Short Table of Contents' => 'Kort innholdsfortegnelse',
8918                       'Short table of contents' => '',
8919                       'Subsection One-Four' => '',
8920                       'Subsection One-One' => '',
8921                       'Subsection One-Three' => '',
8922                       'Subsection One-Two' => '',
8923                       'Subsubsection One-Two-Four' => '',
8924                       'Subsubsection One-Two-One' => '',
8925                       'Subsubsection One-Two-Three' => '',
8926                       'Subsubsection One-Two-Two' => '',
8927                       'T2H_today' => '',
8928                       'Table of Contents' => 'Innholdsfortegnelse',
8929                       'Table of contents' => '',
8930                       'The node you are looking for is at %{href}.' => '',
8931                       'This' => '',
8932                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8933                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8934                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
8935                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
8936                       'Top' => '',
8937                       'Untitled Document' => '',
8938                       'Up' => '',
8939                       'Up node' => '',
8940                       'Up section' => '',
8941                       'by @emph{%{user}}' => '',
8942                       'by @emph{%{user}} on @emph{%{date}}' => '',
8943                       'current' => '',
8944                       'on @emph{%{date}}' => '',
8945                       'section `%{section}\' in @cite{%{book}}' => '',
8946                       'see %{node_file_href}' => '',
8947                       'see %{node_file_href} @cite{%{book}}' => '',
8948                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
8949                       'see %{reference_name}' => '',
8950                       'see @cite{%{book}}' => '',
8951                       'see section %{reference_name}' => '',
8952                       'see section `%{section}\' in @cite{%{book}}' => '',
8953                       'unknown' => ''
8954                     };
8955
8956$T2H_OBSOLETE_STRINGS->{'no'} = {
8957                                  'See' => 'Se',
8958                                  'section' => 'avsnitt',
8959                                  'see' => 'se'
8960                                };
8961
8962
8963$LANGUAGES->{'pt'} = {
8964                       '  The buttons in the navigation panels have the following meaning:' => '  Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:',
8965                       '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '  onde o @strong{ Exemplo } assume que a posi@,{c}@~ao atual localiza-se em @strong{ Subsub@,{c}@~ao Um-Dois-Tr@^es } de um documento com a seguinte estrutura:',
8966                       ' Up ' => ' Acima ',
8967                       '%{acronym_like} (%{explanation})' => '',
8968                       '%{month} %{day}, %{year}' => '%{day} de %{month} de %{year}',
8969                       '%{name} of %{class}' => '%{name} da %{class}',
8970                       '%{name} on %{class}' => '%{name} na %{class}',
8971                       '%{node_file_href}' => '',
8972                       '%{node_file_href} @cite{%{book}}' => '',
8973                       '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
8974                       '%{reference_name}' => '',
8975                       '%{style} %{number}' => '',
8976                       '%{style}: %{caption_first_line}' => '',
8977                       '%{style}: %{shortcaption_first_line}' => '',
8978                       '@b{%{quotation_arg}:} ' => '',
8979                       '@cite{%{book}}' => '',
8980                       'About' => 'Sobre',
8981                       'About (help)' => 'Sobre (ajuda)',
8982                       'About This Document' => 'Sobre Esse Documento',
8983                       'April' => 'Abril',
8984                       'August' => 'Agosto',
8985                       'Back' => 'Volta',
8986                       'Back section in previous file' => '',
8987                       'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
8988                       'Button' => 'Bot@~ao',
8989                       'Contents' => 'Conte@\'udo',
8990                       'Cover (top) of document' => 'In@\'icio (topo) do documento',
8991                       'Current Position' => 'Posi@,{c}@~ao Atual',
8992                       'Current section' => 'Se@,{c}@~ao atual',
8993                       'December' => 'Dezembro',
8994                       'FastBack' => 'Voltar R@\'apido',
8995                       'FastForward' => 'Avan@,{c}ar R@\'apido',
8996                       'February' => 'Fevereiro',
8997                       'First' => 'Primeiro',
8998                       'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura',
8999                       'Following' => 'Seguinte',
9000                       'Following node' => 'Nodo seguinte',
9001                       'Footnotes' => 'Notas de Rodap@\'e',
9002                       'Forward' => 'Avan@,{c}ar',
9003                       'Forward section in next file' => '',
9004                       'From 1.2.3 go to' => 'De 1.2.3 v@\'a para',
9005                       'Go to' => 'V@\'a para',
9006                       'Index' => '@\'Indice',
9007                       'Index Entry' => 'Entrada de @\'Indice',
9008                       'January' => 'Janeiro',
9009                       'July' => 'Julho',
9010                       'Jump to' => 'Pular para',
9011                       'June' => 'Junho',
9012                       'Last' => '@\'Ultimo',
9013                       'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
9014                       'March' => 'Mar@,{c}o',
9015                       'May' => 'Maio',
9016                       'Menu:' => '',
9017                       'Name' => 'Nome',
9018                       'Next' => 'Pr@\'oximo',
9019                       'Next chapter' => 'Pr@\'oximo cap@\'itulo',
9020                       'Next file' => '',
9021                       'Next node' => 'Pr@\'oximo nodo',
9022                       'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura',
9023                       'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
9024                       'NextFile' => '',
9025                       'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos',
9026                       'Node up' => 'Nodo acima',
9027                       'NodeNext' => 'Pr@\'oximo Nodo',
9028                       'NodePrev' => 'Nodo Anterior',
9029                       'NodeUp' => 'Nodo Acima',
9030                       'November' => 'Novembro',
9031                       'October' => 'Outubro',
9032                       'Overview' => 'Vis@~ao geral',
9033                       'Overview:' => 'Vis@~ao geral:',
9034                       'Prev' => 'Pr@\'evio',
9035                       'PrevFile' => '',
9036                       'Previous file' => '',
9037                       'Previous node' => 'Nodo anterior',
9038                       'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura',
9039                       'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel',
9040                       'Section' => 'Se@,{c}@~ao',
9041                       'Section One' => 'Se@,{c}@~ao Um',
9042                       'See %{node_file_href}' => 'Veja %{node_file_href}',
9043                       'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}',
9044                       'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9045                       'See %{reference_name}' => 'Veja %{reference_name}',
9046                       'See @cite{%{book}}' => 'Veja @cite{%{book}}',
9047                       'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}',
9048                       'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9049                       'September' => 'Setembro',
9050                       'Short Table of Contents' => 'Breve Sum@\'ario',
9051                       'Short table of contents' => 'Breve sum@\'ario',
9052                       'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro',
9053                       'Subsection One-One' => 'Subse@,{c}@~ao Um-Um',
9054                       'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es',
9055                       'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois',
9056                       'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro',
9057                       'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um',
9058                       'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es',
9059                       'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois',
9060                       'T2H_today' => '',
9061                       'Table of Contents' => 'Sum@\'ario',
9062                       'Table of contents' => 'Sum@\'ario',
9063                       'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.',
9064                       'This' => 'Esse',
9065                       'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gereado por @emph{%{user}} em @emph{%{date}} usando @uref{%{program_homepage}, @emph{%{program}}}.',
9066                       'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado por @emph{%{user}} usando @uref{%{program_homepage}, @emph{%{program}}}.',
9067                       'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Esse documento foi gerado em @i{%{date}} usando @uref{%{program_homepage}, @i{%{program}}}.',
9068                       'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.',
9069                       'Top' => 'Topo',
9070                       'Untitled Document' => 'Documento Sem Nome',
9071                       'Up' => 'Acima',
9072                       'Up node' => 'Nodo acima',
9073                       'Up section' => 'Se@,{c}@~ao acima',
9074                       'by @emph{%{user}}' => 'por  @emph{%{user}}',
9075                       'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}',
9076                       'current' => 'atual',
9077                       'on @emph{%{date}}' => 'em @emph{%{date}}',
9078                       'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9079                       'see %{node_file_href}' => 'veja %{node_file_href}',
9080                       'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}',
9081                       'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9082                       'see %{reference_name}' => 'veja %{reference_name}',
9083                       'see @cite{%{book}}' => 'veja @cite{%{book}}',
9084                       'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}',
9085                       'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9086                       'unknown' => 'desconhecido'
9087                     };
9088
9089$T2H_OBSOLETE_STRINGS->{'pt'} = {
9090                                  'See' => 'Veja',
9091                                  'about (help)' => 'sobre (ajuda)',
9092                                  'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
9093                                  'cover (top) of document' => 'in@\'icio (topo) do documento',
9094                                  'current section' => 'se@,{c}@~ao atual',
9095                                  'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura',
9096                                  'following node' => 'nodo seguinte',
9097                                  'index' => '@\'indice',
9098                                  'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura',
9099                                  'next chapter' => 'pr@\'oximo cap@\'itulo',
9100                                  'next node' => 'pr@\'oximo nodo',
9101                                  'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura',
9102                                  'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
9103                                  'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos',
9104                                  'node up' => 'nodo acima',
9105                                  'previous node' => 'nodo anterior',
9106                                  'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura',
9107                                  'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel',
9108                                  'section' => 'Se@,{c}@~ao',
9109                                  'see' => 'veja',
9110                                  'short table of contents' => 'breve sum@\'ario',
9111                                  'table of contents' => 'sum@\'ario',
9112                                  'up node' => 'nodo acima',
9113                                  'up section' => 'se@,{c}@~ao acima'
9114                                };
9115
9116
9117$LANGUAGES->{'pt_BR'} = {
9118                          '  The buttons in the navigation panels have the following meaning:' => '  Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:',
9119                          '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '  onde o @strong{ Exemplo } assume que a posi@,{c}@~ao atual localiza-se em @strong{ Subsub@,{c}@~ao Um-Dois-Tr@^es } de um documento com a seguinte estrutura:',
9120                          ' Up ' => ' Acima ',
9121                          '%{acronym_like} (%{explanation})' => '',
9122                          '%{month} %{day}, %{year}' => '%{day} de %{month} de %{year}',
9123                          '%{name} of %{class}' => '%{name} da %{class}',
9124                          '%{name} on %{class}' => '%{name} na %{class}',
9125                          '%{node_file_href}' => '',
9126                          '%{node_file_href} @cite{%{book}}' => '',
9127                          '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9128                          '%{reference_name}' => '',
9129                          '%{style} %{number}' => '',
9130                          '%{style}: %{caption_first_line}' => '',
9131                          '%{style}: %{shortcaption_first_line}' => '',
9132                          '@b{%{quotation_arg}:} ' => '',
9133                          '@cite{%{book}}' => '',
9134                          'About' => 'Sobre',
9135                          'About (help)' => 'Sobre (ajuda)',
9136                          'About This Document' => 'Sobre Esse Documento',
9137                          'April' => 'Abril',
9138                          'August' => 'Agosto',
9139                          'Back' => 'Volta',
9140                          'Back section in previous file' => '',
9141                          'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
9142                          'Button' => 'Bot@~ao',
9143                          'Contents' => 'Conte@\'udo',
9144                          'Cover (top) of document' => 'In@\'icio (topo) do documento',
9145                          'Current Position' => 'Posi@,{c}@~ao Atual',
9146                          'Current section' => 'Se@,{c}@~ao atual',
9147                          'December' => 'Dezembro',
9148                          'FastBack' => 'Voltar R@\'apido',
9149                          'FastForward' => 'Avan@,{c}ar R@\'apido',
9150                          'February' => 'Fevereiro',
9151                          'First' => 'Primeiro',
9152                          'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura',
9153                          'Following' => 'Seguinte',
9154                          'Following node' => 'Nodo seguinte',
9155                          'Footnotes' => 'Notas de Rodap@\'e',
9156                          'Forward' => 'Avan@,{c}ar',
9157                          'Forward section in next file' => '',
9158                          'From 1.2.3 go to' => 'De 1.2.3 v@\'a para',
9159                          'Go to' => 'V@\'a para',
9160                          'Index' => '@\'Indice',
9161                          'Index Entry' => 'Entrada de @\'Indice',
9162                          'January' => 'Janeiro',
9163                          'July' => 'Julho',
9164                          'Jump to' => 'Pular para',
9165                          'June' => 'Junho',
9166                          'Last' => '@\'Ultimo',
9167                          'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
9168                          'March' => 'Mar@,{c}o',
9169                          'May' => 'Maio',
9170                          'Menu:' => '',
9171                          'Name' => 'Nome',
9172                          'Next' => 'Pr@\'oximo',
9173                          'Next chapter' => 'Pr@\'oximo cap@\'itulo',
9174                          'Next file' => '',
9175                          'Next node' => 'Pr@\'oximo nodo',
9176                          'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura',
9177                          'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
9178                          'NextFile' => '',
9179                          'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos',
9180                          'Node up' => 'Nodo acima',
9181                          'NodeNext' => 'Pr@\'oximo Nodo',
9182                          'NodePrev' => 'Nodo Anterior',
9183                          'NodeUp' => 'Nodo Acima',
9184                          'November' => 'Novembro',
9185                          'October' => 'Outubro',
9186                          'Overview' => 'Vis@~ao geral',
9187                          'Overview:' => 'Vis@~ao geral:',
9188                          'Prev' => 'Pr@\'evio',
9189                          'PrevFile' => '',
9190                          'Previous file' => '',
9191                          'Previous node' => 'Nodo anterior',
9192                          'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura',
9193                          'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel',
9194                          'Section' => 'Se@,{c}@~ao',
9195                          'Section One' => 'Se@,{c}@~ao Um',
9196                          'See %{node_file_href}' => 'Veja %{node_file_href}',
9197                          'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}',
9198                          'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9199                          'See %{reference_name}' => 'Veja %{reference_name}',
9200                          'See @cite{%{book}}' => 'Veja @cite{%{book}}',
9201                          'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}',
9202                          'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9203                          'September' => 'Setembro',
9204                          'Short Table of Contents' => 'Breve Sum@\'ario',
9205                          'Short table of contents' => 'Breve sum@\'ario',
9206                          'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro',
9207                          'Subsection One-One' => 'Subse@,{c}@~ao Um-Um',
9208                          'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es',
9209                          'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois',
9210                          'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro',
9211                          'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um',
9212                          'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es',
9213                          'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois',
9214                          'T2H_today' => '',
9215                          'Table of Contents' => 'Sum@\'ario',
9216                          'Table of contents' => 'Sum@\'ario',
9217                          'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.',
9218                          'This' => 'Esse',
9219                          'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gereado por @emph{%{user}} em @emph{%{date}} usando @uref{%{program_homepage}, @emph{%{program}}}.',
9220                          'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado por @emph{%{user}} usando @uref{%{program_homepage}, @emph{%{program}}}.',
9221                          'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Esse documento foi gerado em @i{%{date}} usando @uref{%{program_homepage}, @i{%{program}}}.',
9222                          'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.',
9223                          'Top' => 'Topo',
9224                          'Untitled Document' => 'Documento Sem Nome',
9225                          'Up' => 'Acima',
9226                          'Up node' => 'Nodo acima',
9227                          'Up section' => 'Se@,{c}@~ao acima',
9228                          'by @emph{%{user}}' => 'por  @emph{%{user}}',
9229                          'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}',
9230                          'current' => 'atual',
9231                          'on @emph{%{date}}' => 'em @emph{%{date}}',
9232                          'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9233                          'see %{node_file_href}' => 'veja %{node_file_href}',
9234                          'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}',
9235                          'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9236                          'see %{reference_name}' => 'veja %{reference_name}',
9237                          'see @cite{%{book}}' => 'veja @cite{%{book}}',
9238                          'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}',
9239                          'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
9240                          'unknown' => 'desconhecido'
9241                        };
9242
9243$T2H_OBSOLETE_STRINGS->{'pt_BR'} = {
9244                                     'See' => 'Veja',
9245                                     'about (help)' => 'sobre (ajuda)',
9246                                     'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
9247                                     'cover (top) of document' => 'in@\'icio (topo) do documento',
9248                                     'current section' => 'se@,{c}@~ao atual',
9249                                     'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura',
9250                                     'following node' => 'nodo seguinte',
9251                                     'index' => '@\'indice',
9252                                     'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura',
9253                                     'next chapter' => 'pr@\'oximo cap@\'itulo',
9254                                     'next node' => 'pr@\'oximo nodo',
9255                                     'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura',
9256                                     'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
9257                                     'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos',
9258                                     'node up' => 'nodo acima',
9259                                     'previous node' => 'nodo anterior',
9260                                     'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura',
9261                                     'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel',
9262                                     'section' => 'Se@,{c}@~ao',
9263                                     'see' => 'veja',
9264                                     'short table of contents' => 'breve sum@\'ario',
9265                                     'table of contents' => 'sum@\'ario',
9266                                     'up node' => 'nodo acima',
9267                                     'up section' => 'se@,{c}@~ao acima'
9268                                   };
9269
9270
9271
9272require "$T2H_HOME/$translation_file"
9273    if ($0 =~ /\.pl$/ &&
9274        -e "$T2H_HOME/$translation_file" && -r "$T2H_HOME/$translation_file");
9275
9276#
9277# Some functions used to override normal formatting functions in specific
9278# cases. The user shouldn't want to change them, but can use them.
9279#
9280
9281# used to utf8 encode the result
9282sub t2h_utf8_accent($$$)
9283{
9284    my $accent = shift;
9285    my $args = shift;
9286    my $style_stack = shift;
9287
9288    my $text = $args->[0];
9289    #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n";
9290
9291    # special handling of @dotless{i}
9292    if ($accent eq 'dotless')
9293    {
9294        if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
9295        {
9296             return "\x{0131}";
9297        }
9298        #return "\x{}" if ($text eq 'j'); # not found !
9299        return $text;
9300    }
9301
9302    # FIXME \x{0131}\x{0308} for @dotless{i} @" doesn't lead to NFC 00ef.
9303    return Unicode::Normalize::NFC($text . chr(hex($unicode_diacritical{$accent})))
9304        if (defined($unicode_diacritical{$accent}));
9305    return ascii_accents($text, $accent);
9306}
9307
9308sub t2h_utf8_normal_text($$$$$)
9309{
9310    my $text = shift;
9311    my $in_raw_text = shift;
9312    my $in_preformatted = shift;
9313    my $in_code = shift;
9314    my $in_simple = shift;
9315    my $style_stack = shift;
9316
9317    $text = &$protect_text($text) unless($in_raw_text);
9318    $text = uc($text) if (in_small_caps($style_stack));
9319
9320    if (!$in_code and !$in_preformatted)
9321    {
9322        $text =~ s/---/\x{2014}/g;
9323        $text =~ s/--/\x{2013}/g;
9324        $text =~ s/``/\x{201C}/g;
9325        $text =~ s/''/\x{201D}/g;
9326    }
9327    return Unicode::Normalize::NFC($text);
9328}
9329
9330# these are unlikely to be used by users, as they are essentially
9331# used to follow the html external refs specification in texinfo
9332sub t2h_cross_manual_normal_text($$$$$)
9333{
9334    my $text = shift;
9335    my $in_raw_text = shift;
9336    my $in_preformatted = shift;
9337    my $in_code =shift;
9338    my $in_simple =shift;
9339    my $style_stack = shift;
9340
9341    $text = uc($text) if (in_small_caps($style_stack));
9342    return $text if ($USE_UNICODE);
9343    return t2h_no_unicode_cross_manual_normal_text($text, 0);
9344}
9345
9346sub t2h_cross_manual_normal_text_transliterate($$$$$)
9347{
9348    my $text = shift;
9349    my $in_raw_text = shift;
9350    my $in_preformatted = shift;
9351    my $in_code =shift;
9352    my $in_simple =shift;
9353    my $style_stack = shift;
9354
9355    $text = uc($text) if (in_small_caps($style_stack));
9356    return $text if ($USE_UNICODE);
9357    return t2h_no_unicode_cross_manual_normal_text($text, 1);
9358}
9359
9360sub t2h_no_unicode_cross_manual_normal_text($$)
9361{
9362    # if there is no unicode support, we do all the transformations here
9363    my $text = shift;
9364    my $transliterate = shift;
9365    my $result = '';
9366
9367    my $encoding = $Texi2HTML::THISDOC{'DOCUMENT_ENCODING'};
9368    if (defined($encoding) and exists($t2h_encoding_aliases{$encoding}))
9369    {
9370        $encoding = $t2h_encoding_aliases{$encoding};
9371    }
9372
9373    while ($text ne '')
9374    {
9375        if ($text =~ s/^([A-Za-z0-9]+)//o)
9376        {
9377             $result .= $1;
9378        }
9379        elsif ($text =~ s/^ //o)
9380        {
9381             $result .= '-';
9382        }
9383        elsif ($text =~ s/^(.)//o)
9384        {
9385             if (exists($ascii_character_map{$1}))
9386             {
9387                 $result .= '_' . lc($ascii_character_map{$1});
9388             }
9389             else
9390             {
9391                  my $character = $1;
9392                  my $charcode = uc(sprintf("%02x",ord($1)));
9393                  my $done = 0;
9394                  if (defined($encoding) and exists($eight_bit_to_unicode{$encoding})
9395                      and exists($eight_bit_to_unicode{$encoding}->{$charcode}))
9396                  {
9397                      $done = 1;
9398                      my $unicode_point =  $eight_bit_to_unicode{$encoding}->{$charcode};
9399                      if (!$transliterate)
9400                      {
9401                           $result .= '_' . lc($unicode_point);
9402                      }
9403                      elsif (exists($transliterate_map{$unicode_point}))
9404                      {
9405                           $result .= $transliterate_map{$unicode_point};
9406                      }
9407                      elsif (exists($unicode_diacritical{$unicode_point}))
9408                      {
9409                           $result .= '';
9410                      }
9411                      else
9412                      {
9413                          $done = 0;
9414                      }
9415                  }
9416
9417                  if (!$done)
9418                  { # wild guess that work for latin1, and thus, should fail
9419                      $result .= '_' . '00' . lc($charcode);
9420                  }
9421             }
9422        }
9423        else
9424        {
9425             echo_error("Bug: unknown character in cross ref (likely in infinite loop)");
9426        }
9427    }
9428
9429    return $result;
9430}
9431
9432sub t2h_nounicode_cross_manual_accent($$$)
9433{
9434    my $accent = shift;
9435    my $args = shift;
9436    my $style_stack = shift;
9437
9438    my $text = $args->[0];
9439
9440    if ($accent eq 'dotless')
9441    {
9442        if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
9443        {
9444             return "_0131";
9445        }
9446        #return "\x{}" if ($text eq 'j'); # not found !
9447        return $text;
9448    }
9449    return '_' . lc($unicode_accents{$accent}->{$text})
9450        if (defined($unicode_accents{$accent}->{$text}));
9451    return ($text . '_' . lc($unicode_diacritical{$accent}))
9452        if (defined($unicode_diacritical{$accent}));
9453    return ascii_accents($text, $accent);
9454}
9455
9456sub t2h_transliterate_cross_manual_accent($$)
9457{
9458    my $accent = shift;
9459    my $args = shift;
9460
9461    my $text = $args->[0];
9462
9463    if (exists($unicode_accents{$accent}->{$text}) and
9464        exists ($transliterate_map{$unicode_accents{$accent}->{$text}}))
9465    {
9466         return $transliterate_map{$unicode_accents{$accent}->{$text}};
9467    }
9468    return $text;
9469}
9470
9471
9472} # end package Texi2HTML::Config
9473
9474use vars qw(
9475%value
9476%alias
9477);
9478
9479# variables which might be redefined by the user but aren't likely to be
9480# they seem to be in the main namespace
9481use vars qw(
9482%index_names
9483%index_prefix_to_name
9484%predefined_index
9485%valid_index
9486%reference_sec2level
9487%code_style_map
9488%forbidden_index_name
9489);
9490
9491# Some global variables are set in the script, and used in the subroutines
9492# they are in the Texi2HTML namespace, thus prefixed with Texi2HTML::.
9493# see texi2html.init for details.
9494
9495#+++############################################################################
9496#                                                                              #
9497# Pasted content of File $(srcdir)/MySimple.pm: Command-line processing        #
9498#                                                                              #
9499#---############################################################################
9500
9501# leave this within comments, and keep the require statement
9502# This way, you can directly run texi2html.pl, if $T2H_HOME/MySimple.pm
9503# exists.
9504
9505# @MYSIMPLE@
9506package Getopt::MySimple;
9507
9508# Name:
9509#	Getopt::MySimple.
9510#
9511# Documentation:
9512#	POD-style (incomplete) documentation is in file MySimple.pod
9513#
9514# Tabs:
9515#	4 spaces || die.
9516#
9517# Author:
9518#	Ron Savage	rpsavage@ozemail.com.au.
9519#	1.00	19-Aug-97	Initial version.
9520#	1.10	13-Oct-97	Add arrays of switches (eg '=s@').
9521#	1.20	 3-Dec-97	Add 'Help' on a per-switch basis.
9522#	1.30	11-Dec-97	Change 'Help' to 'verbose'. Make all hash keys lowercase.
9523#	1.40	10-Nov-98	Change width of help report. Restructure tests.
9524#               1-Jul-00        Modifications for Texi2html
9525
9526# --------------------------------------------------------------------------
9527# Locally modified by obachman (Display type instead of env, order by cmp)
9528# $Id: MySimple.pm,v 1.6 2008/11/26 19:09:01 pertusus Exp $
9529
9530# use strict;
9531# no strict 'refs';
9532
9533use vars qw(@EXPORT @EXPORT_OK @ISA);
9534use vars qw($fieldWidth $opt $VERSION);
9535
9536use Exporter();
9537use Getopt::Long;
9538
9539@ISA		= qw(Exporter);
9540@EXPORT		= qw();
9541@EXPORT_OK	= qw($opt);	# An alias for $self -> {'opt'}.
9542
9543# --------------------------------------------------------------------------
9544
9545$fieldWidth	= 20;
9546$VERSION	= '1.41';
9547
9548# --------------------------------------------------------------------------
9549
9550sub byOrder
9551{
9552	my($self) = @_;
9553
9554	return uc($a) cmp (uc($b));
9555}
9556
9557# --------------------------------------------------------------------------
9558
9559sub dumpOptions
9560{
9561	my($self) = @_;
9562
9563	print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n";
9564
9565	for (sort byOrder keys(%{$self -> {'opt'} }) )
9566	{
9567	  print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n";
9568	}
9569
9570	print "\n";
9571
9572}	# End of dumpOptions.
9573
9574# --------------------------------------------------------------------------
9575# Return:
9576#	0 -> Error.
9577#	1 -> Ok.
9578
9579sub getOptions
9580{
9581	push(@_, 0) if ($#_ == 2);	# Default for $ignoreCase is 0.
9582	push(@_, 1) if ($#_ == 3);	# Default for $helpThenExit is 1.
9583
9584	my($self, $default, $helpText, $versionText,
9585	   $helpThenExit, $versionThenExit, $ignoreCase) = @_;
9586
9587	$helpThenExit = 1 unless (defined($helpThenExit));
9588	$versionThenExit = 1 unless (defined($versionThenExit));
9589	$ignoreCase = 0 unless (defined($ignoreCase));
9590
9591	$self -> {'default'}		= $default;
9592	$self -> {'helpText'}		= $helpText;
9593	$self -> {'versionText'}        = $versionText;
9594	$Getopt::Long::ignorecase	= $ignoreCase;
9595
9596	unless (defined($self -> {'default'}{'help'}))
9597	{
9598	  $self -> {'default'}{'help'} =
9599	  {
9600	   type => ':i',
9601	   default => '',
9602	   linkage => sub {$self->helpOptions($_[1]); sleep 5;exit (0) if $helpThenExit;},
9603	   verbose => "print help and exit"
9604	  };
9605	}
9606
9607	unless (defined($self -> {'default'}{'version'}))
9608	{
9609	  $self -> {'default'}{'version'} =
9610	  {
9611	   type => '',
9612	   default => '',
9613	   linkage => sub {print $self->{'versionText'};  exit (0) if $versionThenExit;},
9614	   verbose => "print version and exit"
9615	  };
9616	}
9617
9618	for (keys(%{$self -> {'default'} }) )
9619	{
9620	  next unless (ref(${$self -> {'default'} }{$_}) eq 'HASH');
9621	  my $type = ${$self -> {'default'} }{$_}{'type'};
9622	  push(@{$self -> {'type'} }, "$_$type");
9623	  $self->{'opt'}->{$_} =  ${$self -> {'default'} }{$_}{'linkage'}
9624            if ${$self -> {'default'} }{$_}{'linkage'};
9625	}
9626
9627	my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} });
9628
9629        return $result unless $result;
9630
9631	for (keys(%{$self -> {'default'} }) )
9632	{
9633 	   if (! defined(${$self -> {'opt'} }{$_})) #{
9634            {
9635 	     ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'};
9636            }
9637	}
9638
9639	$result;
9640}	# End of getOptions.
9641
9642# --------------------------------------------------------------------------
9643
9644sub helpOptions
9645{
9646	my($self) = shift;
9647	my($noHelp) = shift;
9648	$noHelp = 0 unless $noHelp;
9649	my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth)
9650	  = (10, 5, 9, 78, 4, 11);
9651
9652	print "$self->{'helpText'}" if ($self -> {'helpText'});
9653
9654	print ' Option', ' ' x ($optwidth - length('Option') -1 ),
9655		'Type', ' ' x ($typewidth - length('Type') + 1),
9656		'Default', ' ' x ($defaultwidth - length('Default') ),
9657	        "Description\n";
9658
9659	for (sort byOrder keys(%{$self -> {'default'} }) )
9660	{
9661	  my($line, $help, $option, $val);
9662	  $option = $_;
9663	  next if ${$self->{'default'} }{$_}{'noHelp'} && ${$self->{'default'} }{$_}{'noHelp'} > $noHelp;
9664          #$line = " -$_" . ' ' x ($optwidth - (2 + length) ) .
9665          #      	"${$self->{'default'} }{$_}{'type'} ".
9666          #      	' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
9667		$line = " --$_" . "${$self->{'default'} }{$_}{'type'}".
9668			' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
9669
9670                 $val = ${$self->{'default'} }{$_}{'linkage'};
9671                if ($val)
9672                {
9673                  if ((ref($val) eq 'SCALAR') and (defined($$val)))
9674		  {
9675		    $val = $$val;
9676		  }
9677		  else
9678		  {
9679		    $val = '';
9680		  }
9681                }
9682		elsif (defined(${$self->{'default'} }{$_}{'default'}))
9683		{
9684		  $val = ${$self->{'default'} }{$_}{'default'};
9685		}
9686		else
9687		{
9688		  $val = '';
9689		}
9690	        $line .= "$val  ";
9691		$line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line));
9692
9693		if (defined(${$self -> {'default'} }{$_}{'verbose'}) &&
9694		  ${$self -> {'default'} }{$_}{'verbose'} ne '')
9695	      {
9696		$help = "${$self->{'default'} }{$_}{'verbose'}";
9697	      }
9698	      else
9699	      {
9700		$help = ' ';
9701	      }
9702	      if ((length("$line") + length($help)) < $maxlinewidth)
9703	      {
9704		print $line , $help, "\n";
9705	      }
9706	      else
9707	      {
9708		print $line, "\n", ' ' x $valind, $help, "\n";
9709	      }
9710	      for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}}))
9711	      {
9712	        print ' ' x ($valind + 2);
9713                print $val, '  ', ' ' x ($valwidth - length($val) - 2);
9714	        print ${$self->{'default'}}{$option}{'values'}{$val}, "\n";
9715	      }
9716	}
9717
9718	print <<EOT;
9719Note: 'Options' may be abbreviated. -- prefix may be replaced by a single -.
9720'Type' specifications mean:
9721 <none>| !    no argument: variable is set to 1 on -foo (or, to 0 on -nofoo)
9722    =s | :s   mandatory (or, optional)  string argument
9723    =i | :i   mandatory (or, optional)  integer argument
9724EOT
9725}	# End of helpOptions.
9726
9727#-------------------------------------------------------------------
9728
9729sub new
9730{
9731	my($class)				= @_;
9732	my($self)				= {};
9733	$self -> {'default'}	= {};
9734	$self -> {'helpText'}	= '';
9735	$self -> {'opt'}		= {};
9736	$opt					= $self -> {'opt'};	 # An alias for $self -> {'opt'}.
9737	$self -> {'type'}		= ();
9738
9739	return bless $self, $class;
9740
9741}	# End of new.
9742
9743# --------------------------------------------------------------------------
9744
97451;
9746
9747# End MySimple.pm
9748
9749require "$T2H_HOME/MySimple.pm"
9750    if ($0 =~ /\.pl$/ &&
9751        -e "$T2H_HOME/MySimple.pm" && -r "$T2H_HOME/MySimple.pm");
9752
9753#+++########################################################################
9754#                                                                          #
9755# Pasted content of File $(srcdir)/T2h_i18n.pm: Internationalisation       #
9756#                                                                          #
9757#---########################################################################
9758
9759# leave this within comments, and keep the require statement
9760# This way, you can directly run texi2html.pl, if $T2H_HOME/T2h_i18n.pm
9761# exists.
9762
9763# @T2H_I18N@
9764#+##############################################################################
9765#
9766# T2h_i18n.pm: Internationalization for texi2html
9767#
9768#    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
9769#                             Derek Price <derek@ximbiot.com>,
9770#                             Adrian Aichner <adrian@xemacs.org>,
9771#                           & others.
9772#
9773#    This program is free software; you can redistribute it and/or modify
9774#    it under the terms of the GNU General Public License as published by
9775#    the Free Software Foundation; either version 2 of the License, or
9776#    (at your option) any later version.
9777#
9778#    This program is distributed in the hope that it will be useful,
9779#    but WITHOUT ANY WARRANTY; without even the implied warranty of
9780#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9781#    GNU General Public License for more details.
9782#
9783#    You should have received a copy of the GNU General Public License
9784#    along with this program; if not, write to the Free Software
9785#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
9786#
9787#-##############################################################################
9788
9789# This requires perl version 5 or higher
9790require 5.0;
9791
9792package Texi2HTML::I18n;
9793
9794use strict;
9795
9796use vars qw(
9797@ISA
9798@EXPORT
9799);
9800
9801use Exporter;
9802@ISA = qw(Exporter);
9803@EXPORT = qw(pretty_date);
9804
9805my $language;
9806my $i18n_dir = 'i18n'; # name of the directory containing the per language files
9807#my $translation_file = 'translations.pl'; # file containing all the translations
9808#my @known_languages = ('de', 'nl', 'es', 'no', 'pt', 'fr'); # The supported
9809                                               # languages
9810
9811########################################################################
9812# Language dependencies:
9813# To add a new language extend the WORDS hash and create $T2H_<...>_WORDS hash
9814# To redefine one word, simply do:
9815# $T2h_i18n::T2H_LANGUAGES->{<language>}->{<word>} = 'whatever' in your personal init file.
9816#
9817
9818# Those hashes are obsolete but retained here for reference
9819
9820my $T2H_WORDS_EN =
9821{
9822 # titles  of pages
9823 #'Table of Contents'       => 'Table of Contents',
9824 #'Short Table of Contents'  => 'Short Table of Contents',
9825 #'Index'     => 'Index',
9826 #'About This Document'     => 'About This Document',
9827 #'Footnotes' => 'Footnotes',
9828 #'See'             => 'See',
9829 #'see'             => 'see',
9830 #'section'         => 'section',
9831 'About This Document'       => '',
9832 'Table of Contents'         => '',
9833 'Short Table of Contents',  => '',
9834 'Index'                     => '',
9835 'Footnotes'                 => '',
9836 'See'                       => '',
9837 'see'                       => '',
9838 'section'                   => '',
9839 'Top'                       => '',
9840 'Untitled Document'         => '',
9841 # If necessary, we could extend this as follows:
9842 #  # text for buttons
9843 #  'Top_Button' => 'Top',
9844 #  'ToC_Button' => 'Contents',
9845 #  'Overview_Button' => 'Overview',
9846 #  'Index_button' => 'Index',
9847 #  'Back_Button' => 'Back',
9848 #  'FastBack_Button' => 'FastBack',
9849 #  'Prev_Button' => 'Prev',
9850 #  'Up_Button' => 'Up',
9851 #  'Next_Button' => 'Next',
9852 #  'Forward_Button' =>'Forward',
9853 #  'FastWorward_Button' => 'FastForward',
9854 #  'First_Button' => 'First',
9855 #  'Last_Button' => 'Last',
9856 #  'About_Button' => 'About'
9857 'January' => '',
9858 'February' => '',
9859 'March' => '',
9860 'April' => '',
9861 'May' => '',
9862 'June' => '',
9863 'July' => '',
9864 'August' => '',
9865 'September' => '',
9866 'October' => '',
9867 'November' => '',
9868 'December' => '',
9869 'T2H_today' => '%s, %d %d',
9870};
9871
9872my $T2H_WORDS_DE =
9873{
9874 'Table of Contents'       => 'Inhaltsverzeichniss',
9875 'Short Table of Contents'  => 'Kurzes Inhaltsverzeichniss',
9876 'Index'     => 'Index',
9877 'About This Document'     => '&Uuml;ber dieses Dokument',
9878 'Footnotes' => 'Fu&szlig;noten',
9879 'See'             => 'Siehe',
9880 'see'             => 'siehe',
9881 'section'         => 'Abschnitt',
9882 'January' => 'Januar',
9883 'February' => 'Februar',
9884 'March' => 'M&auml;rz',
9885 'April' => 'April',
9886 'May' => 'Mai',
9887 'June' => 'Juni',
9888 'July' => 'Juli',
9889 'August' => 'August',
9890 'September' => 'September',
9891 'October' => 'Oktober',
9892 'November' => 'November',
9893 'December' => 'Dezember',
9894};
9895
9896my $T2H_WORDS_NL =
9897{
9898 'Table of Contents'       => 'Inhoudsopgave',
9899 'Short Table of Contents'  => 'Korte inhoudsopgave',
9900 'Index'     => 'Index',      #Not sure ;-)
9901 'About This Document'     => 'No translation available!', #No translation available!
9902 'Footnotes' => 'No translation available!', #No translation available!
9903 'See'             => 'Zie',
9904 'see'             => 'zie',
9905 'section'         => 'sectie',
9906 'January' => 'Januari',
9907 'February' => 'Februari',
9908 'March' => 'Maart',
9909 'April' => 'April',
9910 'May' => 'Mei',
9911 'June' => 'Juni',
9912 'July' => 'Juli',
9913 'August' => 'Augustus',
9914 'September' => 'September',
9915 'October' => 'Oktober',
9916 'November' => 'November',
9917 'December' => 'December',
9918};
9919
9920my $T2H_WORDS_ES =
9921{
9922 'Table of Contents'       => '&iacute;ndice General',
9923 'Short Table of Contents'  => 'Resumen del Contenido',
9924 'Index'     => 'Index',      #Not sure ;-)
9925 'About This Document'     => 'No translation available!', #No translation available!
9926 'Footnotes' => 'Fu&szlig;noten',
9927 'See'             => 'V&eacute;ase',
9928 'see'             => 'v&eacute;ase',
9929 'section'         => 'secci&oacute;n',
9930 'January' => 'enero',
9931 'February' => 'febrero',
9932 'March' => 'marzo',
9933 'April' => 'abril',
9934 'May' => 'mayo',
9935 'June' => 'junio',
9936 'July' => 'julio',
9937 'August' => 'agosto',
9938 'September' => 'septiembre',
9939 'October' => 'octubre',
9940 'November' => 'noviembre',
9941 'December' => 'diciembre',
9942};
9943
9944my $T2H_WORDS_NO =
9945{
9946 'Table of Contents'       => 'Innholdsfortegnelse',
9947 'Short Table of Contents'  => 'Kort innholdsfortegnelse',
9948 'Index'     => 'Indeks',     #Not sure ;-)
9949 'About This Document'     => 'No translation available!', #No translation available!
9950 'Footnotes' => 'No translation available!',
9951 'See'             => 'Se',
9952 'see'             => 'se',
9953 'section'         => 'avsnitt',
9954 'January' => 'januar',
9955 'February' => 'februar',
9956 'March' => 'mars',
9957 'April' => 'april',
9958 'May' => 'mai',
9959 'June' => 'juni',
9960 'July' => 'juli',
9961 'August' => 'august',
9962 'September' => 'september',
9963 'October' => 'oktober',
9964 'November' => 'november',
9965 'December' => 'desember',
9966};
9967
9968my $T2H_WORDS_PT =
9969{
9970 'Table of Contents'       => 'Sum&aacute;rio',
9971 'Short Table of Contents'  => 'Breve Sum&aacute;rio',
9972 'Index'     => '&Iacute;ndice', #Not sure ;-)
9973 'About This Document'     => 'No translation available!', #No translation available!
9974 'Footnotes' => 'No translation available!',
9975 'See'             => 'Veja',
9976 'see'             => 'veja',
9977 'section'         => 'Se&ccedil;&atilde;o',
9978 'January' => 'Janeiro',
9979 'February' => 'Fevereiro',
9980 'March' => 'Mar&ccedil;o',
9981 'April' => 'Abril',
9982 'May' => 'Maio',
9983 'June' => 'Junho',
9984 'July' => 'Julho',
9985 'August' => 'Agosto',
9986 'September' => 'Setembro',
9987 'October' => 'Outubro',
9988 'November' => 'Novembro',
9989 'December' => 'Dezembro',
9990};
9991
9992my $T2H_WORDS_FR =
9993{
9994 'Table of Contents'       => 'Table des mati&egrave;res',
9995 'Short Table of Contents'  => 'R&eacute;sum&eacute;e du contenu',
9996 'Index'     => 'Index',
9997 'About This Document'     => 'A propos de ce document',
9998 'Footnotes' => 'Notes de bas de page',
9999 'See'             => 'Voir',
10000 'see'             => 'voir',
10001 'section'         => 'section',
10002 'January' => 'Janvier',
10003 'February' => 'F&eacute;vrier',
10004 'March' => 'Mars',
10005 'April' => 'Avril',
10006 'May' => 'Mai',
10007 'June' => 'Juin',
10008 'July' => 'Juillet',
10009 'August' => 'Ao&ucirc;t',
10010 'September' => 'Septembre',
10011 'October' => 'Octobre',
10012 'November' => 'Novembre',
10013 'December' => 'D&eacute;cembre',
10014 'T2H_today' => 'le %2$d %1$s %3$d'
10015};
10016
10017#$T2H_LANGUAGES =
10018#{
10019# 'en' => $T2H_WORDS_EN,
10020# 'de' => $T2H_WORDS_DE,
10021# 'nl' => $T2H_WORDS_NL,
10022# 'es' => $T2H_WORDS_ES,
10023# 'no' => $T2H_WORDS_NO,
10024# 'pt' => $T2H_WORDS_PT,
10025# 'fr' => $T2H_WORDS_FR,
10026#};
10027
10028sub set_language($)
10029{
10030    my $lang = shift;
10031    if (defined($lang) && exists($Texi2HTML::Config::LANGUAGES->{$lang}) && defined($Texi2HTML::Config::LANGUAGES->{$lang}))
10032    {
10033         $language = $lang;
10034         return 1;
10035    }
10036    else
10037    {
10038         return 0;
10039    }
10040}
10041
10042sub get_language()
10043{
10044    return $language;
10045}
10046
10047my @MONTH_NAMES =
10048    (
10049     'January', 'February', 'March', 'April', 'May',
10050     'June', 'July', 'August', 'September', 'October',
10051     'November', 'December'
10052    );
10053
10054my $I = \&get_string;
10055
10056sub pretty_date($)
10057{
10058    my $lang = shift;
10059    my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
10060
10061    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
10062    $year += ($year < 70) ? 2000 : 1900;
10063    # obachman: Let's do it as the Americans do
10064    #return($MONTH_NAMES->{$lang}[$mon] . ", " . $mday . " " . $year);
10065	#return(sprintf(&$I('T2H_today'), (get_string($MONTH_NAMES[$mon]), $mday, $year)));
10066	return &$I('%{month} %{day}, %{year}', { 'month' => get_string($MONTH_NAMES[$mon]),
10067          'day' => $mday, 'year' => $year });
10068}
10069
10070my $error_no_en = 0;
10071
10072my %missing_strings;
10073
10074# arguments should already be converted
10075sub get_string($;$$)
10076{
10077    my $string = shift;
10078    my $arguments = shift;
10079    my $state = shift;
10080    # if duplicate is passed, it means that we are in the text and so should
10081    # use the main state
10082    if (defined($state) and $state->{'duplicate'} and defined($Texi2HTML::THISDOC{'state'}))
10083    {
10084        $state = main::duplicate_formatting_state($Texi2HTML::THISDOC{'state'});
10085    }
10086
10087    my $T2H_LANGUAGES = $Texi2HTML::Config::LANGUAGES;
10088    if (! exists($T2H_LANGUAGES->{'en'}))
10089    {
10090        unless($error_no_en)
10091        {
10092            print STDERR "i18n: no LANGUAGES->{'en'} hash\n";
10093            $error_no_en = 1;
10094        }
10095    }
10096    else
10097    {
10098        unless (exists ($T2H_LANGUAGES->{'en'}->{$string}))
10099        {
10100            unless (exists($missing_strings{$string}))
10101            {
10102                print STDERR "i18n: missing string $string\n";
10103                $missing_strings{$string} = 1;
10104            }
10105        }
10106        if (defined ($T2H_LANGUAGES->{$language}->{$string}) and
10107           ($T2H_LANGUAGES->{$language}->{$string} ne ''))
10108        {
10109            $string = $T2H_LANGUAGES->{$language}->{$string};
10110        }
10111        elsif (defined ($T2H_LANGUAGES->{'en'}->{$string}) and
10112            ($T2H_LANGUAGES->{'en'}->{$string} ne ''))
10113        {
10114            $string = $T2H_LANGUAGES->{'en'}->{$string};
10115        }
10116    }
10117    return main::substitute_line($string, $state) unless (defined($arguments) or !keys(%$arguments));
10118    # if there are arguments, we must protect the %{arg} constructs before
10119    # doing substitute_line. So there is a first pass here to change %{arg}
10120    # to %@{arg@}
10121    my $result = '';
10122    if (!$state->{'keep_texi'})
10123    {
10124        while ($string)
10125        {
10126            if ($string =~ s/^([^%]*)%//)
10127            {
10128                $result .= $1 if (defined($1));
10129                $result .= '%';
10130                if ($string =~ s/^%//)
10131                {
10132                     $result .= '%';
10133                }
10134                elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
10135                {
10136                     $string =~ s/^\{(\w+)\}//;
10137                     $result .= "\@\{$1\@\}";
10138                }
10139                else
10140                {
10141                     $result .= '%';
10142                }
10143                next;
10144            }
10145            else
10146            {
10147                $result .= $string;
10148                last;
10149            }
10150        }
10151        # the arguments are not already there. But the @-commands in the
10152        # strings are substituted.
10153        $string = main::substitute_line($result, $state);
10154    }
10155    # now we substitute the arguments
10156    $result = '';
10157    while ($string)
10158    {
10159        if ($string =~ s/^([^%]*)%//)
10160        {
10161            $result .= $1 if (defined($1));
10162            if ($string =~ s/^%//)
10163            {
10164                 $result .= '%';
10165            }
10166            elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
10167            {
10168                 $string =~ s/^\{(\w+)\}//;
10169                 $result .= $arguments->{$1};
10170            }
10171            else
10172            {
10173                 $result .= '%';
10174            }
10175            next;
10176        }
10177        else
10178        {
10179            $result .= $string;
10180            last;
10181        }
10182    }
10183    return $result;
10184}
10185
101861;
10187require "$T2H_HOME/T2h_i18n.pm"
10188    if ($0 =~ /\.pl$/ &&
10189        -e "$T2H_HOME/T2h_i18n.pm" && -r "$T2H_HOME/T2h_i18n.pm");
10190
10191
10192#########################################################################
10193#
10194# latex2html code
10195#
10196#---######################################################################
10197
10198{
10199# leave this within comments, and keep the require statement
10200# This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_l2h.pm
10201# exists.
10202
10203# @T2H_L2H@
10204#+##############################################################################
10205#
10206# T2h_l2h.pm: interface to LaTeX2HTML
10207#
10208#    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
10209#                             Derek Price <derek@ximbiot.com>,
10210#                             Adrian Aichner <adrian@xemacs.org>,
10211#                           & others.
10212#
10213#    This program is free software; you can redistribute it and/or modify
10214#    it under the terms of the GNU General Public License as published by
10215#    the Free Software Foundation; either version 2 of the License, or
10216#    (at your option) any later version.
10217#
10218#    This program is distributed in the hope that it will be useful,
10219#    but WITHOUT ANY WARRANTY; without even the implied warranty of
10220#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10221#    GNU General Public License for more details.
10222#
10223#    You should have received a copy of the GNU General Public License
10224#    along with this program; if not, write to the Free Software
10225#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
10226#    02110-1301  USA
10227#
10228#-##############################################################################
10229
10230require 5.0;
10231use strict;
10232
10233package Texi2HTML::LaTeX2HTML;
10234use Cwd;
10235
10236
10237# latex2html conversions consist of three stages:
10238# 1) ToLatex: Put "latex" code into a latex file
10239# 2) ToHtml: Use latex2html to generate corresponding html code and images
10240# 3) FromHtml: Extract generated code and images from latex2html run
10241#
10242
10243# init l2h defaults for files and names
10244
10245# global variable used for caching
10246use vars qw(
10247            %l2h_cache
10248           );
10249
10250my ($l2h_name, $l2h_latex_file, $l2h_cache_file, $l2h_html_file, $l2h_prefix);
10251
10252# holds the status of latex2html operations. If 0 it means that there was
10253# an error
10254my $status = 0;
10255
10256my $debug;
10257my $verbose;
10258my $docu_rdir;
10259my $docu_name;
10260my $docu_ext;
10261my $ERROR = '***';
10262
10263# init_from_html
10264my $extract_error_count;
10265my $invalid_counter_count;
10266
10267# change_image_file_names
10268my %l2h_img;            # associate src file to destination file
10269                        # such that files are not copied twice
10270my $image_count;
10271
10272# do_tex
10273my $html_output_count = 0;   # html text outputed in html result file
10274
10275##########################
10276#
10277# First stage: Generation of Latex file
10278# Initialize with: init
10279# Add content with: to_latex ($text) --> HTML placeholder comment
10280# Finish with: finish_to_latex
10281#
10282
10283my $l2h_latex_preamble = <<EOT;
10284% This document was automatically generated by the l2h extenstion of texi2html
10285% DO NOT EDIT !!!
10286\\documentclass{article}
10287\\usepackage{html}
10288\\begin{document}
10289EOT
10290
10291my $l2h_latex_closing = <<EOT;
10292\\end{document}
10293EOT
10294
10295my %l2h_to_latex = ();         # associate a latex text with the index in the
10296                               # html result array.
10297my @l2h_to_latex = ();         # array used to associate the index with
10298                               # the original latex text.
10299my $latex_count = 0;           # number of latex texts really stored
10300my $latex_converted_count = 0; # number of latex texts passed through latex2html
10301my $to_latex_count = 0;        # total number of latex texts processed
10302my $cached_count = 0;          # number of cached latex texts
10303%l2h_cache = ();               # the cache hash. Associate latex text with
10304                               # html from the previous run
10305my @l2h_from_html;             # array of resulting html
10306
10307my %global_count = ();         # associate a command name and the
10308                               # corresponding counter to the index in the
10309                               # html result array
10310
10311# set $status to 1, if l2h could be initalized properly, to 0 otherwise
10312sub init()
10313{
10314
10315   %l2h_to_latex = ();         # associate a latex text with the index in the
10316                               # html result array.
10317   @l2h_to_latex = ();         # array used to associate the index with
10318                               # the original latex text.
10319   $latex_count = 0;           # number of latex texts really stored
10320   $latex_converted_count = 0; # number of latex texts passed through latex2html
10321   $to_latex_count = 0;        # total number of latex texts processed
10322   $cached_count = 0;          # number of cached latex texts
10323   %l2h_cache = ();            # the cache hash. Associate latex text with
10324                               # html from the previous run
10325   @l2h_from_html = ();        # array of resulting html
10326
10327   %global_count = ();         # associate a command name and the
10328                               # corresponding counter to the index in the
10329                               # html result array
10330   $extract_error_count = 0;
10331   $invalid_counter_count = 0;
10332   %l2h_img = ();       # associate src file to destination file
10333                        # such that files are not copied twice
10334   $image_count = 1;
10335
10336   $html_output_count = 0;   # html text outputed in html result file
10337   $status = 0;
10338
10339    $docu_name = $Texi2HTML::THISDOC{'file_base_name'};
10340    $docu_rdir = $Texi2HTML::THISDOC{'destination_directory'};
10341    $docu_rdir = '' if (!defined($docu_rdir));
10342    $docu_ext = $Texi2HTML::THISDOC{'extension'};
10343    $l2h_name =  "${docu_name}_l2h";
10344    $l2h_latex_file = "$docu_rdir${l2h_name}.tex";
10345    $l2h_cache_file = "${docu_rdir}${docu_name}-l2h_cache.pm";
10346    # destination dir -- generated images are put there, should be the same
10347    # as dir of enclosing html document --
10348    $l2h_html_file = "$docu_rdir${l2h_name}.html";
10349    $l2h_prefix = "${l2h_name}_";
10350    $debug = $Texi2HTML::THISDOC{'debug_l2h'};
10351    $verbose = $Texi2HTML::Config::VERBOSE;
10352
10353    unless ($Texi2HTML::Config::L2H_SKIP)
10354    {
10355        unless (open(L2H_LATEX, ">$l2h_latex_file"))
10356        {
10357            warn "$ERROR l2h: Can't open latex file '$l2h_latex_file' for writing: $!\n";
10358            $status = 0;
10359            return;
10360        }
10361        warn "# l2h: use ${l2h_latex_file} as latex file\n" if ($verbose);
10362        print L2H_LATEX $l2h_latex_preamble;
10363    }
10364    # open the database that holds cached text
10365    init_cache();
10366    $status = 1;
10367}
10368
10369
10370# print text (2nd arg) into latex file (if not already there nor in cache)
10371# which can be later on replaced by the latex2html generated text.
10372#
10373sub to_latex($$$)
10374{
10375    my $command = shift;
10376    my $text = shift;
10377    my $counter = shift;
10378    if ($command eq 'tex')
10379    {
10380        $text .= ' ';
10381    }
10382    elsif ($command eq 'math')
10383    {
10384        $text = "\$".$text."\$";
10385    }
10386    $to_latex_count++;
10387    $text =~ s/(\s*)$//;
10388    # try whether we have text already on things to do
10389    my $count = $l2h_to_latex{$text};
10390    unless ($count)
10391    {
10392        $latex_count++;
10393        $count = $latex_count;
10394        # try whether we can get it from cache
10395        my $cached_text = from_cache($text);
10396        if (defined($cached_text))
10397        {
10398             $cached_count++;
10399             # put the cached result in the html result array
10400             $l2h_from_html[$count] = $cached_text;
10401        }
10402        else
10403        {
10404             $latex_converted_count++;
10405             unless ($Texi2HTML::Config::L2H_SKIP)
10406             {
10407                 print L2H_LATEX "\\begin{rawhtml}\n";
10408                 print L2H_LATEX "<!-- l2h_begin $l2h_name $count -->\n";
10409                 print L2H_LATEX "\\end{rawhtml}\n";
10410
10411                 print L2H_LATEX "$text\n";
10412
10413                 print L2H_LATEX "\\begin{rawhtml}\n";
10414                 print L2H_LATEX "<!-- l2h_end $l2h_name $count -->\n";
10415                 print L2H_LATEX "\\end{rawhtml}\n";
10416            }
10417        }
10418        $l2h_to_latex[$count] = $text;
10419        $l2h_to_latex{$text} = $count;
10420    }
10421    $global_count{"${command}_$counter"} = $count;
10422    return 1;
10423}
10424
10425# print closing into latex file and close it
10426sub finish_to_latex()
10427{
10428    my $reused = $to_latex_count - $latex_converted_count - $cached_count;
10429    unless ($Texi2HTML::Config::L2H_SKIP)
10430    {
10431        print L2H_LATEX $l2h_latex_closing;
10432        close (L2H_LATEX);
10433    }
10434    warn "# l2h: finished to latex ($cached_count cached, $reused reused, $latex_converted_count to process)\n" if ($verbose);
10435    unless ($latex_count)
10436    {
10437        # no @tex nor @math
10438        finish();
10439        return 0;
10440    }
10441    return 1;
10442}
10443
10444###################################
10445# Second stage: Use latex2html to generate corresponding html code and images
10446#
10447# to_html([$l2h_latex_file, [$l2h_html_dir]]):
10448#   Call latex2html on $l2h_latex_file
10449#   Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir
10450#   Return 1, on success
10451#          0, otherwise
10452#
10453sub to_html()
10454{
10455    my ($call, $dotbug);
10456    # when there are no tex constructs to convert (happens in case everything
10457    # comes from the cache), there is no latex2html run
10458    if ($Texi2HTML::Config::L2H_SKIP or ($latex_converted_count == 0))
10459    {
10460        warn "# l2h: skipping latex2html run\n" if ($verbose);
10461        return 1;
10462    }
10463    # Check for dot in directory where dvips will work
10464    if ($Texi2HTML::Config::L2H_TMP)
10465    {
10466        if ($Texi2HTML::Config::L2H_TMP =~ /\./)
10467        {
10468            warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
10469            $dotbug = 1;
10470        }
10471    }
10472    else
10473    {
10474        if (cwd() =~ /\./)
10475        {
10476            warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
10477            $dotbug = 1;
10478        }
10479    }
10480    # fix it, if necessary and hope that it works
10481    $Texi2HTML::Config::L2H_TMP = "/tmp" if ($dotbug);
10482
10483    $call = $Texi2HTML::Config::L2H_L2H;
10484    # use init file, if specified
10485    my $init_file = main::locate_init_file($Texi2HTML::Config::L2H_FILE);
10486    $call = $call . " -init_file " . $init_file if ($init_file);
10487    # set output dir
10488    $call .=  (($docu_rdir ne '') ? " -dir $docu_rdir" : " -no_subdir");
10489    # use l2h_tmp, if specified
10490    $call .= " -tmp $Texi2HTML::Config::L2H_TMP"
10491         if (defined($Texi2HTML::Config::L2H_TMP) and $Texi2HTML::Config::L2H_TMP ne '');
10492    # use a given html version if specified
10493    $call .= " -html_version $Texi2HTML::Config::L2H_HTML_VERSION"
10494      if (defined($Texi2HTML::Config::L2H_HTML_VERSION) and $Texi2HTML::Config::L2H_HTML_VERSION ne '');
10495    # options we want to be sure of
10496    $call .= " -address 0 -info 0 -split 0 -no_navigation -no_auto_link";
10497    $call .= " -prefix $l2h_prefix $l2h_latex_file";
10498
10499    warn "# l2h: executing '$call'\n" if ($verbose);
10500    if (system($call))
10501    {
10502        warn "$ERROR l2h: '${call}' did not succeed\n";
10503        return 0;
10504    }
10505    else
10506    {
10507        warn "# l2h: latex2html finished successfully\n" if ($verbose);
10508        return 1;
10509    }
10510}
10511
10512##########################
10513# Third stage: Extract generated contents from latex2html run
10514# Initialize with: init_from_html
10515#   open $l2h_html_file for reading
10516#   reads in contents into array indexed by numbers
10517#   return 1,  on success -- 0, otherwise
10518# Finish with: finish
10519#   closes $l2h_html_dir/$l2h_name.".$docu_ext"
10520
10521# the images generated by latex2html have names like ${docu_name}_l2h_img?.png
10522# they are copied to ${docu_name}_?.png, and html is changed accordingly.
10523
10524# %l2h_img;            # associate src file to destination file
10525                        # such that files are not copied twice
10526sub change_image_file_names($)
10527{
10528    my $content = shift;
10529    my @images = ($content =~ /SRC="(.*?)"/g);
10530    my ($src, $dest);
10531
10532    for $src (@images)
10533    {
10534        $dest = $l2h_img{$src};
10535        unless ($dest)
10536        {
10537            my $ext = '';
10538            if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
10539            {
10540                $ext = ".$1";
10541            }
10542            else
10543            { # FIXME what is that check about?
10544                warn "$ERROR: L2h image $src has invalid extension\n";
10545                next;
10546            }
10547            while (-e "$docu_rdir${docu_name}_${image_count}$ext")
10548            {
10549                $image_count++;
10550            }
10551            $dest = "${docu_name}_${image_count}$ext";
10552# FIXME this isn't portable. + error condition not checked.
10553            system("cp -f $docu_rdir$src $docu_rdir$dest");
10554            $l2h_img{$src} = $dest;
10555# FIXME error condition not checked
10556            unlink "$docu_rdir$src" unless ($debug);
10557        }
10558        $content =~ s/SRC="$src"/SRC="$dest"/g;
10559    }
10560    return $content;
10561}
10562
10563sub init_from_html()
10564{
10565    # when there are no tex constructs to convert (happens in case everything
10566    # comes from the cache), the html file that was generated by previous
10567    # latex2html runs isn't reused.
10568    if ($latex_converted_count == 0)
10569    {
10570        return 1;
10571    }
10572
10573    if (! open(L2H_HTML, "<$l2h_html_file"))
10574    {
10575        warn "$ERROR l2h: Can't open $l2h_html_file for reading\n";
10576        return 0;
10577    }
10578    warn "# l2h: use $l2h_html_file as html file\n" if ($verbose);
10579
10580    my $html_converted_count = 0;   # number of html resulting texts
10581                                    # retrieved in the file
10582
10583    my ($count, $h_line);
10584    while ($h_line = <L2H_HTML>)
10585    {
10586        if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
10587        {
10588            $count = $1;
10589            my $h_content = '';
10590            my $h_end_found = 0;
10591            while ($h_line = <L2H_HTML>)
10592            {
10593                if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
10594                {
10595                    $h_end_found = 1;
10596                    chomp $h_content;
10597                    chomp $h_content;
10598                    $html_converted_count++;
10599                    # transform image file names and copy image files
10600                    $h_content = change_image_file_names($h_content);
10601                    # store result in the html result array
10602                    $l2h_from_html[$count] = $h_content;
10603                    # also add the result in cache hash
10604                    $l2h_cache{$l2h_to_latex[$count]} = $h_content;
10605                    last;
10606                }
10607                $h_content = $h_content.$h_line;
10608            }
10609            unless ($h_end_found)
10610            { # couldn't found the closing comment. Certainly  a bug.
10611                warn "$ERROR l2h(BUG): l2h_end $l2h_name $count not found\n";
10612                close(L2H_HTML);
10613                return 0;
10614            }
10615        }
10616    }
10617
10618    # Not the same number of converted elements and retrieved elements
10619    if ($latex_converted_count != $html_converted_count)
10620    {
10621        warn "$ERROR l2h(BUG): waiting for $latex_converted_count elements found $html_converted_count\n";
10622    }
10623
10624    warn "# l2h: Got $html_converted_count of $latex_count html contents\n"
10625        if ($verbose);
10626
10627    close(L2H_HTML);
10628    return 1;
10629}
10630
10631# $html_output_count = 0;   # html text outputed in html result file
10632
10633# called each time a construct handled by latex2html is encountered, should
10634# output the corresponding html
10635sub do_tex($$$$)
10636{
10637    my $style = shift;
10638    my $counter = shift;
10639    my $state = shift;
10640    my $count = $global_count{"${style}_$counter"};
10641    ################################## begin debug section (incorrect counts)
10642    if (!defined($count))
10643    {
10644         # counter is undefined
10645         $invalid_counter_count++;
10646         warn "$ERROR l2h(BUG): undefined count for ${style}_$counter\n";
10647         return ("<!-- l2h: ". __LINE__ . " undef count for ${style}_$counter -->")
10648                if ($debug);
10649         return '';
10650    }
10651    elsif(($count <= 0) or ($count > $latex_count))
10652    {
10653        # counter out of range
10654        $invalid_counter_count++;
10655        warn "$ERROR l2h(BUG): Request of $count content which is out of valide range [0,$latex_count)\n";
10656         return ("<!-- l2h: ". __LINE__ . " out of range count $count -->")
10657                if ($debug);
10658         return '';
10659    }
10660    ################################## end debug section (incorrect counts)
10661
10662    # this seems to be a valid counter
10663    my $result = '';
10664    $result = "<!-- l2h_begin $l2h_name $count -->" if ($debug);
10665    if (defined($l2h_from_html[$count]))
10666    {
10667         $html_output_count++;
10668         # maybe we could also have something if simple_format
10669         # with Texi2HTML::Config::protect_text, once simple_format
10670         # may happen for anything else than lines
10671         if ($state->{'remove_texi'})
10672         {# don't protect anything
10673             $result .= $l2h_to_latex[$count];
10674         }
10675         else
10676         {
10677             $result .= $l2h_from_html[$count];
10678         }
10679    }
10680    else
10681    {
10682    # if the result is not in @l2h_from_html, there is an error somewhere.
10683        $extract_error_count++;
10684        warn "$ERROR l2h(BUG): can't extract content $count from html\n";
10685        # try simple (ordinary) substitution (without l2h)
10686        $result .= "<!-- l2h: ". __LINE__ . " use texi2html -->" if ($debug);
10687        $result .= main::substitute_text({}, undef, $l2h_to_latex[$count]);
10688    }
10689    $result .= "<!-- l2h_end $l2h_name $count -->" if ($debug);
10690    return $result;
10691}
10692
10693# store results in the cache and remove temporary files.
10694sub finish()
10695{
10696    return unless($status);
10697    if ($verbose)
10698    {
10699        if ($extract_error_count + $invalid_counter_count)
10700        {
10701            warn "# l2h: finished from html ($extract_error_count extract and $invalid_counter_count invalid counter errors)\n";
10702        }
10703        else
10704        {
10705            warn "# l2h: finished from html (no error)\n";
10706        }
10707        if ($html_output_count != $latex_converted_count)
10708        { # this may happen if @-commands are collected at some places
10709          # but @-command at those places are not expanded later. For
10710          # example @math on @multitable lines.
10711             warn "# l2h: $html_output_count html outputed for $latex_converted_count converted\n";
10712        }
10713    }
10714    store_cache();
10715    if ($Texi2HTML::Config::L2H_CLEAN)
10716    {
10717        local ($_);
10718        warn "# l2h: removing temporary files generated by l2h extension\n"
10719            if $verbose;
10720        while (<"$docu_rdir$l2h_name"*>)
10721        {
10722# FIXME error condition not checked
10723            unlink $_;
10724        }
10725    }
10726    warn "# l2h: Finished\n" if $verbose;
10727    return 1;
10728}
10729
10730# the driver of end of first pass, second pass and beginning of third pass
10731#
10732sub latex2html()
10733{
10734    return unless($status);
10735    return unless ($status = finish_to_latex());
10736    return unless ($status = to_html());
10737    return unless ($status = init_from_html());
10738}
10739
10740
10741##############################
10742# stuff for l2h caching
10743#
10744
10745# I tried doing this with a dbm data base, but it did not store all
10746# keys/values. Hence, I did as latex2html does it
10747sub init_cache
10748{
10749    if (-r "$l2h_cache_file")
10750    {
10751        my $rdo = do "$l2h_cache_file";
10752        warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
10753            unless ($rdo);
10754    }
10755}
10756
10757# store all the text obtained through latex2html
10758sub store_cache
10759{
10760    return unless $latex_count;
10761    my ($key, $value);
10762    unless (open(FH, ">$l2h_cache_file"))
10763    {
10764        warn "$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
10765        return;
10766    }
10767    while (($key, $value) = each %l2h_cache)
10768    {
10769        # escape stuff
10770        $key =~ s|/|\\/|g;
10771        $key =~ s|\\\\/|\\/|g;
10772        # weird, a \ at the end of the key results in an error
10773        # maybe this also broke the dbm database stuff
10774        $key =~ s|\\$|\\\\|;
10775        $value =~ s/\|/\\\|/go;
10776        $value =~ s/\\\\\|/\\\|/go;
10777        $value =~ s|\\\\|\\\\\\\\|g;
10778        print FH "\n\$l2h_cache_key = q/$key/;\n";
10779        print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n";
10780    }
10781    print FH "1;";
10782    close (FH);
10783}
10784
10785# return cached html, if it exists for text, and if all pictures
10786# are there, as well
10787sub from_cache($)
10788{
10789    my $text = shift;
10790    my $cached = $l2h_cache{$text};
10791    if (defined($cached))
10792    {
10793        while ($cached =~ m/SRC="(.*?)"/g)
10794        {
10795            unless (-e "$docu_rdir$1")
10796            {
10797                return undef;
10798            }
10799        }
10800        return $cached;
10801    }
10802    return undef;
10803}
10804
108051;
10806
10807require "$T2H_HOME/T2h_l2h.pm"
10808    if ($0 =~ /\.pl$/ &&
10809        -e "$T2H_HOME/T2h_l2h.pm" && -r "$T2H_HOME/T2h_l2h.pm");
10810
10811}
10812
10813{
10814package Texi2HTML::LaTeX2HTML::Config;
10815
10816# latex2html variables
10817# These variables are not used. They are here for information only, and
10818# an example of config file for latex2html file is included.
10819my $ADDRESS;
10820my $ANTI_ALIAS;
10821my $ANTI_ALIAS_TEXT;
10822my $ASCII_MODE;
10823my $AUTO_LINK;
10824my $AUTO_PREFIX;
10825my $CHILDLINE;
10826my $DEBUG;
10827my $DESTDIR;
10828my $DVIPS;
10829my $ERROR;
10830my $EXTERNAL_FILE;
10831my $EXTERNAL_IMAGES;
10832my $EXTERNAL_UP_LINK;
10833my $EXTERNAL_UP_TITLE;
10834my $FIGURE_SCALE_FACTOR;
10835my $HTML_VERSION;
10836my $IMAGES_ONLY;
10837my $INFO;
10838my $LINE_WIDTH;
10839my $LOCAL_ICONS;
10840my $LONG_TITLES;
10841my $MATH_SCALE_FACTOR;
10842my $MAX_LINK_DEPTH;
10843my $MAX_SPLIT_DEPTH;
10844my $NETSCAPE_HTML;
10845my $NOLATEX;
10846my $NO_FOOTNODE;
10847my $NO_IMAGES;
10848my $NO_NAVIGATION;
10849my $NO_SIMPLE_MATH;
10850my $NO_SUBDIR;
10851my $PAPERSIZE;
10852my $PREFIX;
10853my $PS_IMAGES;
10854my $REUSE;
10855my $SCALABLE_FONTS;
10856my $SHORTEXTN;
10857my $SHORT_INDEX;
10858my $SHOW_SECTION_NUMBERS;
10859my $SPLIT;
10860my $TEXDEFS;
10861my $TITLE;
10862my $TITLES_LANGUAGE;
10863my $TMP;
10864my $VERBOSE;
10865my $WORDS_IN_NAVIGATION_PANEL_TITLES;
10866my $WORDS_IN_PAGE;
10867
10868# @T2H_L2H_INIT@
10869
10870######################################################################
10871# from here on, its l2h init stuff
10872#
10873
10874## initialization for latex2html as for Singular manual generation
10875## obachman 3/99
10876
10877#
10878# Options controlling Titles, File-Names, Tracing and Sectioning
10879#
10880$TITLE = '';
10881
10882$SHORTEXTN = 0;
10883
10884$LONG_TITLES = 0;
10885
10886#$DESTDIR = '';
10887
10888$NO_SUBDIR = 1;
10889
10890#$PREFIX = '';
10891
10892$AUTO_PREFIX = 0;
10893
10894$AUTO_LINK = 0;
10895
10896$SPLIT = 0;
10897
10898$MAX_LINK_DEPTH = 0;
10899
10900#$TMP = '';
10901
10902$DEBUG = 0;
10903
10904$VERBOSE = 1;
10905
10906#
10907# Options controlling Extensions and Special Features
10908#
10909#$HTML_VERSION = "3.2";         # set by command line
10910
10911$TEXDEFS = 1;                   # we absolutely need that
10912
10913$EXTERNAL_FILE = '';
10914
10915$SCALABLE_FONTS = 1;
10916
10917$NO_SIMPLE_MATH = 1;
10918
10919$LOCAL_ICONS = 1;
10920
10921$SHORT_INDEX = 0;
10922
10923$NO_FOOTNODE = 1;
10924
10925$ADDRESS = '';
10926
10927$INFO = '';
10928
10929#
10930# Switches controlling Image Generation
10931#
10932$ASCII_MODE = 0;
10933
10934$NOLATEX = 0;
10935
10936$EXTERNAL_IMAGES = 0;
10937
10938$PS_IMAGES = 0;
10939
10940$NO_IMAGES = 0;
10941
10942$IMAGES_ONLY = 0;
10943
10944$REUSE = 2;
10945
10946$ANTI_ALIAS = 1;
10947
10948$ANTI_ALIAS_TEXT = 1;
10949
10950#
10951#Switches controlling Navigation Panels
10952#
10953$NO_NAVIGATION = 1;
10954$ADDRESS = '';
10955$INFO = 0;                      # 0 = do not make a "About this document..." section
10956
10957#
10958#Switches for Linking to other documents
10959#
10960# currently -- we don't care
10961
10962$MAX_SPLIT_DEPTH = 0;           # Stop making separate files at this depth
10963
10964$MAX_LINK_DEPTH = 0;            # Stop showing child nodes at this depth
10965
10966$NOLATEX = 0;                   # 1 = do not pass unknown environments to Latex
10967
10968$EXTERNAL_IMAGES = 0;           # 1 = leave the images outside the document
10969
10970$ASCII_MODE = 0;                # 1 = do not use any icons or internal images
10971
10972# 1 =  use links to external postscript images rather than inlined bitmap
10973# images.
10974$PS_IMAGES = 0;
10975$SHOW_SECTION_NUMBERS = 0;
10976
10977### Other global variables ###############################################
10978
10979# put dvips stderr on stdout since latex2html is alread very verbose
10980$DVIPS = "$DVIPS ".' 2>&1';
10981
10982$CHILDLINE = "";
10983
10984# This is the line width measured in pixels and it is used to right justify
10985# equations and equation arrays;
10986$LINE_WIDTH = 500;
10987
10988# Used in conjunction with AUTO_NAVIGATION
10989$WORDS_IN_PAGE = 300;
10990
10991# The value of this variable determines how many words to use in each
10992# title that is added to the navigation panel (see below)
10993#
10994$WORDS_IN_NAVIGATION_PANEL_TITLES = 0;
10995
10996# This number will determine the size of the equations, special characters,
10997# and anything which will be converted into an inlined image
10998# *except* "image generating environments" such as "figure", "table"
10999# or "minipage".
11000# Effective values are those greater than 0.
11001# Sensible values are between 0.1 - 4.
11002$MATH_SCALE_FACTOR = 1.5;
11003
11004# This number will determine the size of
11005# image generating environments such as "figure", "table" or "minipage".
11006# Effective values are those greater than 0.
11007# Sensible values are between 0.1 - 4.
11008$FIGURE_SCALE_FACTOR = 1.6;
11009
11010
11011#  If both of the following two variables are set then the "Up" button
11012#  of the navigation panel in the first node/page of a converted document
11013#  will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set
11014#  to some text which describes this external link.
11015$EXTERNAL_UP_LINK = "";
11016$EXTERNAL_UP_TITLE = "";
11017
11018# If this is set then the resulting HTML will look marginally better if viewed
11019# with Netscape.
11020$NETSCAPE_HTML = 1;
11021
11022# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0"
11023# Paper sizes has no effect other than in the time it takes to create inlined
11024# images and in whether large images can be created at all ie
11025#  - larger paper sizes *MAY* help with large image problems
11026#  - smaller paper sizes are quicker to handle
11027$PAPERSIZE = "a4";
11028
11029# Replace "english" with another language in order to tell LaTeX2HTML that you
11030# want some generated section titles (eg "Table of Contents" or "References")
11031# to appear in a different language. Currently only "english" and "french"
11032# is supported but it is very easy to add your own. See the example in the
11033# file "latex2html.config"
11034$TITLES_LANGUAGE = "english";
11035
110361;                              # This must be the last non-comment line
11037
11038# End File l2h.init
11039######################################################################
11040
11041}
11042
11043package main;
11044
11045#
11046# flush stdout and stderr after every write
11047#
11048select(STDERR);
11049$| = 1;
11050select(STDOUT);
11051$| = 1;
11052
11053my $I = \&Texi2HTML::I18n::get_string;
11054
11055########################################################################
11056#
11057# Global variable initialization
11058#
11059########################################################################
11060#
11061# pre-defined indices
11062#
11063
11064%index_prefix_to_name = ();
11065
11066%index_names =
11067(
11068 'cp' => { 'prefix' => ['cp','c']},
11069 'fn' => { 'prefix' => ['fn', 'f'], code => 1},
11070 'vr' => { 'prefix' => ['vr', 'v'], code => 1},
11071 'ky' => { 'prefix' => ['ky', 'k'], code => 1},
11072 'pg' => { 'prefix' => ['pg', 'p'], code => 1},
11073 'tp' => { 'prefix' => ['tp', 't'], code => 1}
11074);
11075
11076foreach my $name(keys(%index_names))
11077{
11078    foreach my $prefix (@{$index_names{$name}->{'prefix'}})
11079    {
11080        $forbidden_index_name{$prefix} = 1;
11081        $index_prefix_to_name{$prefix} = $name;
11082    }
11083}
11084
11085foreach my $other_forbidden_index_name ('info','ps','pdf','htm',
11086   'log','aux','dvi','texi','txi','texinfo','tex','bib')
11087{
11088    $forbidden_index_name{$other_forbidden_index_name} = 1;
11089}
11090
11091# commands with ---, -- '' and `` preserved
11092# usefull with the old interface
11093
11094%code_style_map = (
11095           'code'    => 1,
11096           'command' => 1,
11097           'env'     => 1,
11098           'file'    => 1,
11099           'kbd'     => 1,
11100           'option'  => 1,
11101           'samp'    => 1,
11102           'verb'    => 1,
11103);
11104
11105my @element_directions = ('Up', 'Forward', 'Back', 'Next', 'Prev',
11106'SectionNext', 'SectionPrev', 'SectionUp', 'FastForward', 'FastBack',
11107'This', 'NodeUp', 'NodePrev', 'NodeNext', 'Following', 'NextFile', 'PrevFile',
11108'ToplevelNext', 'ToplevelPrev');
11109$::simple_map_ref = \%Texi2HTML::Config::simple_map;
11110$::simple_map_pre_ref = \%Texi2HTML::Config::simple_map_pre;
11111$::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
11112$::style_map_ref = \%Texi2HTML::Config::style_map;
11113$::style_map_pre_ref = \%Texi2HTML::Config::style_map_pre;
11114$::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
11115$::things_map_ref = \%Texi2HTML::Config::things_map;
11116$::pre_map_ref = \%Texi2HTML::Config::pre_map;
11117$::texi_map_ref = \%Texi2HTML::Config::texi_map;
11118
11119#print STDERR "MAPS: $::simple_map_ref $::simple_map_pre_ref $::simple_map_texi_ref $::style_map_ref $::style_map_pre_ref $::style_map_texi_ref $::things_map_ref $::pre_map_ref $::texi_map_ref\n";
11120
11121# delete from hash if we are using the new interface
11122foreach my $code (keys(%code_style_map))
11123{
11124    delete ($code_style_map{$code})
11125       if (ref($::style_map_ref->{$code}) eq 'HASH');
11126}
11127
11128# no paragraph in these commands
11129my %no_paragraph_macro = (
11130           'xref'         => 1,
11131           'ref'          => 1,
11132           'pxref'        => 1,
11133           'inforef'      => 1,
11134           'anchor'       => 1,
11135);
11136
11137
11138#
11139# texinfo section names to level
11140#
11141my %reference_sec2level = (
11142	      'top', 0,
11143	      'chapter', 1,
11144	      'unnumbered', 1,
11145	      'chapheading', 1,
11146	      'appendix', 1,
11147	      'section', 2,
11148	      'unnumberedsec', 2,
11149	      'heading', 2,
11150	      'appendixsec', 2,
11151	      'subsection', 3,
11152	      'unnumberedsubsec', 3,
11153	      'subheading', 3,
11154	      'appendixsubsec', 3,
11155	      'subsubsection', 4,
11156	      'unnumberedsubsubsec', 4,
11157	      'subsubheading', 4,
11158	      'appendixsubsubsec', 4,
11159         );
11160
11161# the reverse mapping. There is an entry for each sectionning command.
11162# The value is a ref on an array containing at each index the corresponding
11163# sectionning command name.
11164my %level2sec;
11165{
11166    my $sections = [ ];
11167    my $appendices = [ ];
11168    my $unnumbered = [ ];
11169    my $headings = [ ];
11170    foreach my $command (keys (%reference_sec2level))
11171    {
11172        if ($command =~ /^appendix/)
11173        {
11174            $level2sec{$command} = $appendices;
11175        }
11176        elsif ($command =~ /^unnumbered/ or $command eq 'top')
11177        {
11178            $level2sec{$command} = $unnumbered;
11179        }
11180        elsif ($command =~ /section$/ or $command eq 'chapter')
11181        {
11182            $level2sec{$command} = $sections;
11183        }
11184        else
11185        {
11186            $level2sec{$command} = $headings;
11187        }
11188        $level2sec{$command}->[$reference_sec2level{$command}] = $command;
11189    }
11190}
11191
11192# this are synonyms
11193$reference_sec2level{'appendixsection'} = 2;
11194# sec2level{'majorheading'} is also 1 and not 0
11195$reference_sec2level{'majorheading'} = 1;
11196$reference_sec2level{'chapheading'} = 1;
11197$reference_sec2level{'centerchap'} = 1;
11198
11199
11200sub set_no_line_macro($$)
11201{
11202   my $macro = shift;
11203   my $value = shift;
11204   $Texi2HTML::Config::no_paragraph_commands{$macro} = $value
11205      unless defined($Texi2HTML::Config::no_paragraph_commands{$macro});
11206}
11207
11208# those macros aren't considered as beginning a paragraph
11209foreach my $no_line_macro ('alias', 'macro', 'unmacro', 'rmacro',
11210 'titlefont', 'include', 'copying', 'end copying', 'tab', 'item',
11211 'itemx', '*', 'float', 'end float', 'caption', 'shortcaption', 'cindex',
11212 'image')
11213{
11214    set_no_line_macro($no_line_macro, 1);
11215}
11216
11217foreach my $key (keys(%Texi2HTML::Config::misc_command), keys(%reference_sec2level))
11218{
11219    set_no_line_macro($key, 1);
11220}
11221
11222# a hash associating a format @thing / @end thing with the type of the format
11223# 'complex_format' 'simple_format' 'deff' 'list' 'menu' 'paragraph_format'
11224my %format_type = ();
11225
11226foreach my $simple_format (keys(%Texi2HTML::Config::format_map))
11227{
11228   $format_type{$simple_format} = 'simple_format';
11229}
11230foreach my $paragraph_style (keys(%Texi2HTML::Config::paragraph_style))
11231{
11232   $format_type{$paragraph_style} = 'paragraph_format';
11233}
11234foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map))
11235{
11236   $format_type{$complex_format} = 'complex_format';
11237}
11238foreach my $table (('table', 'ftable', 'vtable'))
11239{
11240   $format_type{$table} = 'table';
11241}
11242$format_type{'multitable'} = 'multitable';
11243foreach my $def_format (keys(%Texi2HTML::Config::def_map))
11244{
11245   $format_type{$def_format} = 'deff';
11246}
11247$format_type{'itemize'} = 'list';
11248$format_type{'enumerate'} = 'list';
11249
11250$format_type{'menu'} = 'menu';
11251$format_type{'detailmenu'} = 'menu';
11252
11253$format_type{'cartouche'} = 'cartouche';
11254
11255$format_type{'float'} = 'float';
11256
11257$format_type{'quotation'} = 'quotation';
11258$format_type{'smallquotation'} = 'quotation';
11259
11260$format_type{'group'} = 'group';
11261
11262$format_type{'titlepage'} = 'region';
11263$format_type{'copying'} = 'region';
11264$format_type{'documentdescription'} = 'region';
11265
11266foreach my $key (keys(%format_type))
11267{
11268   set_no_line_macro($key, 1);
11269   set_no_line_macro("end $key", 1);
11270}
11271
11272foreach my $macro (keys(%Texi2HTML::Config::format_in_paragraph))
11273{
11274   set_no_line_macro($macro, 1);
11275   set_no_line_macro("end $macro", 1);
11276}
11277
11278# fake format at the bottom of the stack
11279$format_type{'noformat'} = '';
11280
11281# fake formats are formats used internally within other formats
11282# we associate them with a real format, for the error messages
11283my %fake_format = (
11284     'line' => 'table',
11285     'term' => 'table',
11286     'item' => 'list or table',
11287     'row' => 'multitable row',
11288     'cell' => 'multitable cell',
11289     'deff_item' => 'definition command',
11290     'menu_comment' => 'menu',
11291     'menu_description' => 'menu',
11292  );
11293
11294foreach my $key (keys(%fake_format))
11295{
11296    $format_type{$key} = 'fake';
11297}
11298
11299# raw formats which are expanded especially
11300my @raw_regions = ('html', 'verbatim', 'tex', 'xml', 'docbook');
11301
11302# The css formats are associated with complex format commands, and associated
11303# with the 'pre_style' key
11304foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map))
11305{
11306    next if (defined($Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'}));
11307    $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = '';
11308    $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = $Texi2HTML::Config::css_map{"pre.$complex_format"} if (exists($Texi2HTML::Config::css_map{"pre.$complex_format"}));
11309}
11310
11311#+++############################################################################
11312#                                                                              #
11313# Argument parsing, initialisation                                             #
11314#                                                                              #
11315#---############################################################################
11316
11317my $T2H_USER; # user running the script
11318
11319# shorthand for Texi2HTML::Config::VERBOSE
11320my $T2H_VERBOSE;
11321my $T2H_DEBUG;
11322
11323sub echo_warn($;$);
11324#print STDERR "" . &$I('test i18n: \' , \a \\ %% %{unknown}a %known % %{known}  \\', { 'known' => 'a known string', 'no' => 'nope'}); exit 0;
11325
11326# file:        file name to locate. It can be a file path.
11327# all_files:   if true collect all the files with that name, otherwise stop
11328#              at first match.
11329# directories: a reference on a array containing a list of directories to
11330#              search the file in. default is
11331#              @Texi2HTML::Config::CONF_DIRS, @texi2html_config_dirs.
11332sub locate_init_file($;$$)
11333{
11334    my $file = shift;
11335    my $all_files = shift;
11336    my $directories = shift;
11337
11338    $directories = [ @Texi2HTML::Config::CONF_DIRS, @texi2html_config_dirs ] if !defined($directories);
11339
11340    if ($file =~ /^\//)
11341    {
11342         return $file if (-e $file and -r $file);
11343    }
11344    else
11345    {
11346         my @files;
11347         foreach my $dir (@$directories)
11348         {
11349              next unless (-d "$dir");
11350              if ($all_files)
11351              {
11352                  push (@files, "$dir/$file") if (-e "$dir/$file" and -r "$dir/$file");
11353              }
11354              else
11355              {
11356                  return "$dir/$file" if (-e "$dir/$file" and -r "$dir/$file");
11357              }
11358         }
11359         return @files if ($all_files);
11360    }
11361    return undef;
11362}
11363
11364# called on -init-file
11365sub load_init_file
11366{
11367    # First argument is option
11368    shift;
11369    # second argument is value of options
11370    my $init_file = shift;
11371    my $file;
11372    if ($file = locate_init_file($init_file))
11373    {
11374        print STDERR "# reading initialization file from $file\n"
11375            if ($T2H_VERBOSE);
11376        # require the file in the Texi2HTML::Config namespace
11377        return (Texi2HTML::Config::load($file));
11378    }
11379    else
11380    {
11381        print STDERR "$ERROR Error: can't read init file $init_file\n";
11382        return 0;
11383    }
11384}
11385
11386sub set_date()
11387{
11388    if (!$Texi2HTML::Config::TEST)
11389    {
11390        print STDERR "# Setting date in $Texi2HTML::THISDOC{'current_lang'}\n" if ($T2H_DEBUG);
11391        $Texi2HTML::THISDOC{'today'} = Texi2HTML::I18n::pretty_date($Texi2HTML::THISDOC{'current_lang'});  # like "20 September 1993";
11392    }
11393    else
11394    {
11395        $Texi2HTML::THISDOC{'today'} = 'a sunny day';
11396    }
11397    $Texi2HTML::THISDOC{'today'} = $Texi2HTML::Config::DATE
11398        if (defined($Texi2HTML::Config::DATE));
11399    $::things_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
11400    $::pre_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
11401    $::texi_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
11402}
11403
11404#
11405# called on -lang, and when a @documentlanguage appears
11406sub set_document_language ($;$$$)
11407{
11408    my $lang = shift;
11409    my $from_command_line = shift;
11410    my $silent = shift;
11411    my $line_nr = shift;
11412
11413    my @langs = ($lang);
11414
11415    my $main_lang;
11416    if ($lang =~ /^([a-z]+)_([A-Z]+)/)
11417    {
11418        $main_lang = $1;
11419        push @langs, $main_lang;
11420    }
11421
11422    my @files = locate_init_file("$i18n_dir/$lang", 1);
11423    if (! scalar(@files) and defined($main_lang))
11424    {
11425        @files = locate_init_file("$i18n_dir/$main_lang", 1);
11426    }
11427
11428    foreach  my $file (@files)
11429    {
11430        Texi2HTML::Config::load($file);
11431    }
11432    foreach my $language (@langs)
11433    {
11434        if (Texi2HTML::I18n::set_language($language))
11435        {
11436            print STDERR "# using '$language' as document language\n" if ($T2H_VERBOSE);
11437            $Texi2HTML::THISDOC{'current_lang'} = $language;
11438            # when processing the command line everything isn't already
11439            # set, so we cannot set the date. It is done as soon as possible
11440            # after arguments parsing and initializations, for a file.
11441            if ($from_command_line)
11442            {
11443                $Texi2HTML::GLOBAL{'current_lang'} = $language;
11444            }
11445            else
11446            {
11447                set_date();
11448            }
11449            return 1;
11450        }
11451    }
11452
11453    echo_error ("Language specs for '$lang' do not exists. Reverting to '$Texi2HTML::THISDOC{'current_lang'}'", $line_nr) unless ($silent);
11454    return 0;
11455}
11456
11457# used to manage expanded sections from the command line
11458sub set_expansion($$)
11459{
11460    my $region = shift;
11461    my $set = shift;
11462    $set = 1 if (!defined($set));
11463    if ($set)
11464    {
11465         push (@Texi2HTML::Config::EXPAND, $region) unless (grep {$_ eq $region} @Texi2HTML::Config::EXPAND);
11466    }
11467    else
11468    {
11469         @Texi2HTML::Config::EXPAND = grep {$_ ne $region} @Texi2HTML::Config::EXPAND;
11470    }
11471}
11472
11473# manage footnote style
11474sub set_footnote_style($$)
11475{
11476    if ($_[1] eq 'separate')
11477    {
11478         $Texi2HTML::Config::SEPARATED_FOOTNOTES = 1;
11479    }
11480    elsif ($_[1] eq 'end')
11481    {
11482         $Texi2HTML::Config::SEPARATED_FOOTNOTES = 0;
11483    }
11484    else
11485    {
11486         echo_error ('Bad argument for --footnote-style');
11487    }
11488}
11489
11490
11491# find the encoding alias.
11492# with encoding support (USE_UNICODE), may return undef if no alias was found
11493sub encoding_alias($)
11494{
11495    my $encoding = shift;
11496    return $encoding if (!defined($encoding) or $encoding eq '');
11497    if ($Texi2HTML::Config::USE_UNICODE)
11498    {
11499         if (! Encode::resolve_alias($encoding))
11500         {
11501              echo_warn("Encoding name unknown: $encoding");
11502              return undef;
11503         }
11504         print STDERR "# Using encoding " . Encode::resolve_alias($encoding) . "\n"
11505             if ($T2H_VERBOSE);
11506         return Encode::resolve_alias($encoding);
11507    }
11508    else
11509    {
11510         #echo_warn("No alias searched for encoding");
11511         if (exists($Texi2HTML::Config::t2h_encoding_aliases{$encoding}))
11512         {
11513             $encoding = $Texi2HTML::Config::t2h_encoding_aliases{$encoding};
11514             echo_warn ("Document encoding is utf8, but there is no unicode support") if ($encoding eq 'utf-8');
11515             return $encoding;
11516         }
11517         echo_warn("Encoding certainly poorly supported");
11518         return $encoding;
11519    }
11520}
11521
11522
11523my %nodes;             # nodes hash. The key is the texi node name
11524my %cross_reference_nodes;  # normalized node names arrays
11525
11526#
11527# %value hold texinfo variables, see also -D, -U, @set and @clear.
11528# we predefine html (the output format) and texi2html (the translator)
11529# it is initialized with %value_initial at the beginning of the
11530# document parsing and filled and emptied as @set and @clear are
11531# encountered
11532my %value_initial =
11533      (
11534          'html' => 1,
11535          'texi2html' => $THISVERSION,
11536      );
11537
11538#
11539# _foo: internal variables to track @foo
11540#
11541foreach my $key ('_author', '_title', '_subtitle', '_shorttitlepage',
11542	 '_settitle', '_setfilename', '_titlefont')
11543{
11544    $value_initial{$key} = '';            # prevent -w warnings
11545}
11546
11547
11548sub unicode_to_protected($)
11549{
11550    my $text = shift;
11551    my $result = '';
11552    while ($text ne '')
11553    {
11554        if ($text =~ s/^([A-Za-z0-9]+)//o)
11555        {
11556             $result .= $1;
11557        }
11558        elsif ($text =~ s/^ //o)
11559        {
11560             $result .= '-';
11561        }
11562        elsif ($text =~ s/^(.)//o)
11563        {
11564             my $char = $1;
11565             if (exists($Texi2HTML::Config::ascii_character_map{$char}))
11566             {
11567                 $result .= '_' . lc($Texi2HTML::Config::ascii_character_map{$char});
11568             }
11569             else
11570             {
11571                 if (ord($char) <= hex(0xFFFF))
11572                 {
11573                     $result .= '_' . lc(sprintf("%04x",ord($char)));
11574                 }
11575                 else
11576                 {
11577                     $result .= '__' . lc(sprintf("%06x",ord($char)));
11578                 }
11579             }
11580        }
11581        else
11582        {
11583             print STDERR "Bug: unknown character in a cross ref (likely in infinite loop)\n";
11584             print STDERR "Text: !!$text!!\n";
11585             sleep 1;
11586        }
11587    }
11588    return $result;
11589}
11590
11591sub unicode_to_transliterate($)
11592{
11593    my $text = shift;
11594    my $result = '';
11595    while ($text ne '')
11596    {
11597        if ($text =~ s/^([A-Za-z0-9 ]+)//o)
11598        {
11599             $result .= $1;
11600        }
11601        elsif ($text =~ s/^(.)//o)
11602        {
11603             my $char = $1;
11604             if (exists($Texi2HTML::Config::ascii_character_map{$char}))
11605             {
11606                 $result .= $char;
11607             }
11608             elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($char)))}))
11609             {
11610                 $result .= $Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($char)))};
11611             }
11612             elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::unicode_diacritical{uc(sprintf("%04x",ord($char)))}))
11613             {
11614                 $result .= '';
11615             }
11616             # in this case, we want to avoid calling unidecode, as we are sure
11617             # that there is no useful transliteration of the unicode character
11618             # instead we want to keep it as is.
11619             # This is the case, for example, for @exclamdown, is corresponds
11620             # with x00a1, but unidecode transliterates it to a !, we want
11621             # to avoid that and keep x00a1.
11622             elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::no_transliterate_map{uc(sprintf("%04x",ord($char)))}))
11623             {
11624                 $result .= $char;
11625             }
11626             else
11627             {
11628                 if ($Texi2HTML::Config::USE_UNIDECODE)
11629                 {
11630                      $result .= unidecode($char);
11631                 }
11632                 else
11633                 {
11634                      $result .= $char;
11635                 }
11636             }
11637        }
11638        else
11639        {
11640             print STDERR "Bug: unknown character in cross ref transliteration (likely in infinite loop)\n";
11641             sleep 1;
11642        }
11643    }
11644    return $result;
11645}
11646
11647# T2H_OPTIONS is a hash whose keys are the (long) names of valid
11648# command-line options and whose values are a hash with the following keys:
11649# type    ==> one of !|=i|:i|=s|:s (see Getopt::Long for more info)
11650# linkage ==> ref to scalar, array, or subroutine (see Getopt::Long for more info)
11651# verbose ==> short description of option (displayed by -h)
11652# noHelp  ==> if 1 -> for "not so important options": only print description on -h 1
11653#                2 -> for obsolete options: only print description on -h 2
11654my $T2H_OPTIONS;
11655$T2H_OPTIONS -> {'debug'} =
11656{
11657 type => '=i',
11658 linkage => \$Texi2HTML::Config::DEBUG,
11659 verbose => 'output HTML with debuging information',
11660};
11661
11662$T2H_OPTIONS -> {'doctype'} =
11663{
11664 type => '=s',
11665 linkage => \$Texi2HTML::Config::DOCTYPE,
11666 verbose => 'document type which is output in header of HTML files',
11667 noHelp => 1
11668};
11669
11670$T2H_OPTIONS -> {'frameset-doctype'} =
11671{
11672 type => '=s',
11673 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
11674 verbose => 'document type for HTML frameset documents',
11675 noHelp => 1
11676};
11677
11678$T2H_OPTIONS -> {'test'} =
11679{
11680 type => '!',
11681 linkage => \$Texi2HTML::Config::TEST,
11682 verbose => 'use predefined information to avoid differences with reference files',
11683 noHelp => 1
11684};
11685
11686$T2H_OPTIONS -> {'dump-texi'} =
11687{
11688 type => '!',
11689 linkage => \$Texi2HTML::Config::DUMP_TEXI,
11690 verbose => 'dump the output of first pass into a file with extension passfirst and exit',
11691 noHelp => 1
11692};
11693
11694$T2H_OPTIONS -> {'E'} =
11695{
11696 type => '=s',
11697 linkage => \$Texi2HTML::Config::MACRO_EXPAND,
11698 verbose => 'output macro expanded source in <file>',
11699 noHelp => 2
11700};
11701
11702$T2H_OPTIONS -> {'macro-expand'} =
11703{
11704 type => '=s',
11705 linkage => \$Texi2HTML::Config::MACRO_EXPAND,
11706 verbose => 'output macro expanded source in <file>',
11707};
11708
11709$T2H_OPTIONS -> {'expand'} =
11710{
11711 type => '=s',
11712 linkage => sub {set_expansion($_[1], 1);},
11713 verbose => 'Expand info|tex|none section of texinfo source',
11714 noHelp => 1,
11715};
11716
11717$T2H_OPTIONS -> {'no-expand'} =
11718{
11719 type => '=s',
11720 linkage => sub {set_expansion ($_[1], 0);},
11721 verbose => 'Don\'t expand the given section of texinfo source',
11722};
11723
11724$T2H_OPTIONS -> {'noexpand'} =
11725{
11726 type => '=s',
11727 linkage => $T2H_OPTIONS->{'no-expand'}->{'linkage'},
11728 verbose => $T2H_OPTIONS->{'no-expand'}->{'verbose'},
11729 noHelp  => 1,
11730};
11731
11732$T2H_OPTIONS -> {'ifhtml'} =
11733{
11734 type => '!',
11735 linkage => sub { set_expansion('html', $_[1]); },
11736 verbose => "expand ifhtml and html sections",
11737};
11738
11739$T2H_OPTIONS -> {'ifinfo'} =
11740{
11741 type => '!',
11742 linkage => sub { set_expansion('info', $_[1]); },
11743 verbose => "expand ifinfo",
11744};
11745
11746$T2H_OPTIONS -> {'ifxml'} =
11747{
11748 type => '!',
11749 linkage => sub { set_expansion('xml', $_[1]); },
11750 verbose => "expand ifxml and xml sections",
11751};
11752
11753$T2H_OPTIONS -> {'ifdocbook'} =
11754{
11755 type => '!',
11756 linkage => sub { set_expansion('docbook', $_[1]); },
11757 verbose => "expand ifdocbook and docbook sections",
11758};
11759
11760$T2H_OPTIONS -> {'iftex'} =
11761{
11762 type => '!',
11763 linkage => sub { set_expansion('tex', $_[1]); },
11764 verbose => "expand iftex and tex sections",
11765};
11766
11767$T2H_OPTIONS -> {'ifplaintext'} =
11768{
11769 type => '!',
11770 linkage => sub { set_expansion('plaintext', $_[1]); },
11771 verbose => "expand ifplaintext sections",
11772};
11773
11774# actually a noop, since it is not used anywhere
11775$T2H_OPTIONS -> {'invisible'} =
11776{
11777 type => '=s',
11778 linkage => \$Texi2HTML::Config::INVISIBLE_MARK,
11779 verbose => 'use text in invisble anchor',
11780 noHelp  => 2,
11781};
11782
11783$T2H_OPTIONS -> {'iso'} =
11784{
11785 type => 'iso',
11786 linkage => \$Texi2HTML::Config::USE_ISO,
11787 verbose => 'if set, ISO8859 characters are used for special symbols (like copyright, etc)',
11788 noHelp => 1,
11789};
11790
11791$T2H_OPTIONS -> {'I'} =
11792{
11793 type => '=s',
11794 linkage => \@Texi2HTML::Config::INCLUDE_DIRS,
11795 verbose => 'append $s to the @include search path',
11796};
11797
11798$T2H_OPTIONS -> {'conf-dir'} =
11799{
11800 type => '=s',
11801 linkage => \@Texi2HTML::Config::CONF_DIRS,
11802 verbose => 'append $s to the init file directories',
11803};
11804
11805$T2H_OPTIONS -> {'P'} =
11806{
11807 type => '=s',
11808 linkage => sub {unshift (@Texi2HTML::Config::PREPEND_DIRS, $_[1]);},
11809 verbose => 'prepend $s to the @include search path',
11810};
11811
11812$T2H_OPTIONS -> {'top-file'} =
11813{
11814 type => '=s',
11815 linkage => \$Texi2HTML::Config::TOP_FILE,
11816 verbose => 'use $s as top file, instead of <docname>.html',
11817};
11818
11819$T2H_OPTIONS -> {'toc-file'} =
11820{
11821 type => '=s',
11822 linkage => \$Texi2HTML::Config::TOC_FILE,
11823 verbose => 'use $s as ToC file, instead of <docname>_toc.html',
11824};
11825
11826$T2H_OPTIONS -> {'frames'} =
11827{
11828 type => '!',
11829 linkage => \$Texi2HTML::Config::FRAMES,
11830 verbose => 'output files which use HTML 4.0 frames (experimental)',
11831 noHelp => 1,
11832};
11833
11834$T2H_OPTIONS -> {'menu'} =
11835{
11836 type => '!',
11837 linkage => \$Texi2HTML::Config::SHOW_MENU,
11838 verbose => 'output Texinfo menus',
11839};
11840
11841$T2H_OPTIONS -> {'number-sections'} =
11842{
11843 type => '!',
11844 linkage => \$Texi2HTML::Config::NUMBER_SECTIONS,
11845 verbose => 'use numbered sections',
11846};
11847
11848$T2H_OPTIONS -> {'use-nodes'} =
11849{
11850 type => '!',
11851 linkage => \$Texi2HTML::Config::USE_NODES,
11852 verbose => 'use nodes for sectionning',
11853};
11854
11855$T2H_OPTIONS -> {'node-files'} =
11856{
11857 type => '!',
11858 linkage => \$Texi2HTML::Config::NODE_FILES,
11859 verbose => 'produce one file per node for cross references'
11860};
11861
11862$T2H_OPTIONS -> {'footnote-style'} =
11863{
11864 type => '=s',
11865 linkage => sub {set_footnote_style ($_[0], $_[1]);},
11866 verbose => 'output footnotes separate|end',
11867};
11868
11869$T2H_OPTIONS -> {'toc-links'} =
11870{
11871 type => '!',
11872 linkage => \$Texi2HTML::Config::TOC_LINKS,
11873 verbose => 'create links from headings to toc entries'
11874};
11875
11876$T2H_OPTIONS -> {'split'} =
11877{
11878 type => '=s',
11879 linkage => \$Texi2HTML::Config::SPLIT,
11880 verbose => 'split document on section|chapter|node else no splitting',
11881};
11882
11883$T2H_OPTIONS -> {'no-split'} =
11884{
11885 type => '!',
11886 linkage => sub {$Texi2HTML::Config::SPLIT = '';},
11887 verbose => 'no splitting of document',
11888 noHelp => 1,
11889};
11890
11891$T2H_OPTIONS -> {'header'} =
11892{
11893 type => '!',
11894 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
11895 verbose => 'output navigation headers for each section',
11896};
11897
11898$T2H_OPTIONS -> {'subdir'} =
11899{
11900 type => '=s',
11901 linkage => \$Texi2HTML::Config::SUBDIR,
11902 verbose => 'put files in directory $s, not $cwd',
11903 noHelp => 1,
11904};
11905
11906$T2H_OPTIONS -> {'short-ext'} =
11907{
11908 type => '!',
11909 linkage => \$Texi2HTML::Config::SHORTEXTN,
11910 verbose => 'use "htm" extension for output HTML files',
11911};
11912
11913$T2H_OPTIONS -> {'prefix'} =
11914{
11915 type => '=s',
11916 linkage => \$Texi2HTML::Config::PREFIX,
11917 verbose => 'use as prefix for output files, instead of <docname>',
11918};
11919
11920$T2H_OPTIONS -> {'o'} =
11921{
11922 type => '=s',
11923 linkage => \$Texi2HTML::Config::OUT,
11924 verbose => 'output goes to $s (directory if split)',
11925 noHelp => 2,
11926};
11927
11928$T2H_OPTIONS -> {'output'} =
11929{
11930 type => '=s',
11931 linkage => \$Texi2HTML::Config::OUT,
11932 verbose => 'output goes to $s (directory if split)',
11933};
11934
11935$T2H_OPTIONS -> {'no-validate'} =
11936{
11937 type => '!',
11938 linkage => \$Texi2HTML::Config::NOVALIDATE,
11939 verbose => 'suppress node cross-reference validation',
11940};
11941
11942$T2H_OPTIONS -> {'short-ref'} =
11943{
11944 type => '!',
11945 linkage => \$Texi2HTML::Config::SHORT_REF,
11946 verbose => 'if set, references are without section numbers',
11947};
11948
11949$T2H_OPTIONS -> {'idx-sum'} =
11950{
11951 type => '!',
11952 linkage => \$Texi2HTML::Config::IDX_SUMMARY,
11953 verbose => 'if set, also output index summary',
11954 noHelp  => 1,
11955};
11956
11957$T2H_OPTIONS -> {'def-table'} =
11958{
11959 type => '!',
11960 linkage => \$Texi2HTML::Config::DEF_TABLE,
11961 verbose => 'if set, \@def.. are converted using tables.',
11962 noHelp  => 1,
11963};
11964
11965# disambiguate verbose and version, like makeinfo does
11966$T2H_OPTIONS -> {'v'} =
11967{
11968 type => '!',
11969 linkage=> \$Texi2HTML::Config::VERBOSE,
11970 verbose => 'print progress info to stdout',
11971 noHelp  => 2,
11972};
11973
11974$T2H_OPTIONS -> {'verbose'} =
11975{
11976 type => '!',
11977 linkage=> \$Texi2HTML::Config::VERBOSE,
11978 verbose => 'print progress info to stdout',
11979};
11980
11981$T2H_OPTIONS -> {'document-language'} =
11982{
11983 type => '=s',
11984 linkage => sub {set_document_language($_[1], 1)},
11985 verbose => 'use $s as document language',
11986};
11987
11988$T2H_OPTIONS -> {'ignore-preamble-text'} =
11989{
11990  type => '!',
11991  linkage => \$Texi2HTML::Config::IGNORE_PREAMBLE_TEXT,
11992  verbose => 'if set, ignore the text before @node and sectionning commands',
11993  noHelp => 1,
11994};
11995
11996$T2H_OPTIONS -> {'html-xref-prefix'} =
11997{
11998 type => '=s',
11999 linkage => \$Texi2HTML::Config::EXTERNAL_DIR,
12000 verbose => '$s is the base dir for external manual references',
12001 noHelp => 1,
12002};
12003
12004$T2H_OPTIONS -> {'l2h'} =
12005{
12006 type => '!',
12007 linkage => \$Texi2HTML::Config::L2H,
12008 verbose => 'if set, uses latex2html for @math and @tex',
12009};
12010
12011$T2H_OPTIONS -> {'l2h-l2h'} =
12012{
12013 type => '=s',
12014 linkage => \$Texi2HTML::Config::L2H_L2H,
12015 verbose => 'program to use for latex2html translation',
12016 noHelp => 1,
12017};
12018
12019$T2H_OPTIONS -> {'l2h-skip'} =
12020{
12021 type => '!',
12022 linkage => \$Texi2HTML::Config::L2H_SKIP,
12023 verbose => 'if set, tries to reuse previously latex2html output',
12024 noHelp => 1,
12025};
12026
12027$T2H_OPTIONS -> {'l2h-tmp'} =
12028{
12029 type => '=s',
12030 linkage => \$Texi2HTML::Config::L2H_TMP,
12031 verbose => 'if set, uses $s as temporary latex2html directory',
12032 noHelp => 1,
12033};
12034
12035$T2H_OPTIONS -> {'l2h-file'} =
12036{
12037 type => '=s',
12038 linkage => \$Texi2HTML::Config::L2H_FILE,
12039 verbose => 'if set, uses $s as latex2html init file',
12040 noHelp => 1,
12041};
12042
12043
12044$T2H_OPTIONS -> {'l2h-clean'} =
12045{
12046 type => '!',
12047 linkage => \$Texi2HTML::Config::L2H_CLEAN,
12048 verbose => 'if set, do not keep intermediate latex2html files for later reuse',
12049 noHelp => 1,
12050};
12051
12052$T2H_OPTIONS -> {'D'} =
12053{
12054 type => '=s',
12055 linkage => sub {$value_initial{$_[1]} = 1;},
12056 verbose => 'equivalent to Texinfo "@set $s 1"',
12057 noHelp => 1,
12058};
12059
12060$T2H_OPTIONS -> {'U'} =
12061{
12062 type => '=s',
12063 linkage => sub {delete $value_initial{$_[1]};},
12064 verbose => 'equivalent to Texinfo "@clear $s"',
12065 noHelp => 1,
12066};
12067
12068$T2H_OPTIONS -> {'init-file'} =
12069{
12070 type => '=s',
12071 linkage => \&load_init_file,
12072 verbose => 'load init file $s'
12073};
12074
12075$T2H_OPTIONS -> {'css-include'} =
12076{
12077 type => '=s',
12078 linkage => \@Texi2HTML::Config::CSS_FILES,
12079 verbose => 'use css file $s'
12080};
12081
12082$T2H_OPTIONS -> {'css-ref'} =
12083{
12084 type => '=s',
12085 linkage => \@Texi2HTML::Config::CSS_REFS,
12086 verbose => 'generate reference to the CSS URL $s'
12087};
12088
12089$T2H_OPTIONS -> {'transliterate-file-names'} =
12090{
12091 type => '!',
12092 linkage=> \$Texi2HTML::Config::TRANSLITERATE_NODE,
12093 verbose => 'produce file names in ASCII transliteration',
12094};
12095
12096$T2H_OPTIONS -> {'error-limit'} =
12097{
12098 type => '=i',
12099 linkage => \$Texi2HTML::Config::ERROR_LIMIT,
12100 verbose => 'quit after NUM errors (default 1000).',
12101};
12102
12103$T2H_OPTIONS -> {'monolithic'} =
12104{
12105 type => '!',
12106 linkage => \$Texi2HTML::Config::MONOLITHIC,
12107 verbose => 'output only one file including ToC, About...',
12108 noHelp => 1
12109};
12110##
12111## obsolete cmd line options
12112##
12113my $T2H_OBSOLETE_OPTIONS;
12114
12115$T2H_OBSOLETE_OPTIONS -> {'out-file'} =
12116{
12117 type => '=s',
12118 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
12119 verbose => 'if set, all HTML output goes into file $s, obsoleted by "-output" with different semantics',
12120 noHelp => 2
12121};
12122
12123$T2H_OBSOLETE_OPTIONS -> {'lang'} =
12124{
12125 type => '=s',
12126 linkage => sub {set_document_language($_[1], 1)},
12127 verbose => 'obsolete, use "--document-language" instead',
12128 noHelp => 2
12129};
12130
12131$T2H_OBSOLETE_OPTIONS -> {'number'} =
12132{
12133 type => '!',
12134 linkage => \$Texi2HTML::Config::NUMBER_SECTIONS,
12135 verbose => 'obsolete, use "--number-sections" instead',
12136 noHelp => 2
12137};
12138
12139
12140$T2H_OBSOLETE_OPTIONS -> {'separated-footnotes'} =
12141{
12142 type => '!',
12143 linkage => \$Texi2HTML::Config::SEPARATED_FOOTNOTES,
12144 verbose => 'obsolete, use "--footnote-style" instead',
12145 noHelp => 2
12146};
12147
12148$T2H_OBSOLETE_OPTIONS -> {'Verbose'} =
12149{
12150 type => '!',
12151 linkage=> \$Texi2HTML::Config::VERBOSE,
12152 verbose => 'obsolete, use "--verbose" instead',
12153 noHelp => 2
12154};
12155
12156
12157$T2H_OBSOLETE_OPTIONS -> {init_file} =
12158{
12159 type => '=s',
12160 linkage => \&load_init_file,
12161 verbose => 'obsolete, use "-init-file" instead',
12162 noHelp => 2
12163};
12164
12165$T2H_OBSOLETE_OPTIONS -> {l2h_clean} =
12166{
12167 type => '!',
12168 linkage => \$Texi2HTML::Config::L2H_CLEAN,
12169 verbose => 'obsolete, use "-l2h-clean" instead',
12170 noHelp => 2,
12171};
12172
12173$T2H_OBSOLETE_OPTIONS -> {l2h_l2h} =
12174{
12175 type => '=s',
12176 linkage => \$Texi2HTML::Config::L2H_L2H,
12177 verbose => 'obsolete, use "-l2h-l2h" instead',
12178 noHelp => 2
12179};
12180
12181$T2H_OBSOLETE_OPTIONS -> {l2h_skip} =
12182{
12183 type => '!',
12184 linkage => \$Texi2HTML::Config::L2H_SKIP,
12185 verbose => 'obsolete, use "-l2h-skip" instead',
12186 noHelp => 2
12187};
12188
12189$T2H_OBSOLETE_OPTIONS -> {l2h_tmp} =
12190{
12191 type => '=s',
12192 linkage => \$Texi2HTML::Config::L2H_TMP,
12193 verbose => 'obsolete, use "-l2h-tmp" instead',
12194 noHelp => 2
12195};
12196
12197$T2H_OBSOLETE_OPTIONS -> {out_file} =
12198{
12199 type => '=s',
12200 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
12201 verbose => 'obsolete, use "-out-file" instead',
12202 noHelp => 2
12203};
12204
12205$T2H_OBSOLETE_OPTIONS -> {short_ref} =
12206{
12207 type => '!',
12208 linkage => \$Texi2HTML::Config::SHORT_REF,
12209 verbose => 'obsolete, use "-short-ref" instead',
12210 noHelp => 2
12211};
12212
12213$T2H_OBSOLETE_OPTIONS -> {idx_sum} =
12214{
12215 type => '!',
12216 linkage => \$Texi2HTML::Config::IDX_SUMMARY,
12217 verbose => 'obsolete, use "-idx-sum" instead',
12218 noHelp  => 2
12219};
12220
12221$T2H_OBSOLETE_OPTIONS -> {def_table} =
12222{
12223 type => '!',
12224 linkage => \$Texi2HTML::Config::DEF_TABLE,
12225 verbose => 'obsolete, use "-def-table" instead',
12226 noHelp  => 2
12227};
12228
12229$T2H_OBSOLETE_OPTIONS -> {short_ext} =
12230{
12231 type => '!',
12232 linkage => \$Texi2HTML::Config::SHORTEXTN,
12233 verbose => 'obsolete, use "-short-ext" instead',
12234 noHelp  => 2
12235};
12236
12237$T2H_OBSOLETE_OPTIONS -> {sec_nav} =
12238{
12239 type => '!',
12240 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
12241 verbose => 'obsolete, use "-header" instead',
12242 noHelp  => 2
12243};
12244
12245$T2H_OBSOLETE_OPTIONS -> {'sec-nav'} =
12246{
12247 type => '!',
12248 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
12249 verbose => 'obsolete, use "--header" instead',
12250 noHelp  => 2
12251};
12252
12253$T2H_OBSOLETE_OPTIONS -> {top_file} =
12254{
12255 type => '=s',
12256 linkage => \$Texi2HTML::Config::TOP_FILE,
12257 verbose => 'obsolete, use "-top-file" instead',
12258 noHelp  => 2
12259};
12260
12261$T2H_OBSOLETE_OPTIONS -> {toc_file} =
12262{
12263 type => '=s',
12264 linkage => \$Texi2HTML::Config::TOC_FILE,
12265 verbose => 'obsolete, use "-toc-file" instead',
12266 noHelp  => 2
12267};
12268
12269$T2H_OBSOLETE_OPTIONS -> {glossary} =
12270{
12271 type => '!',
12272 linkage => \$Texi2HTML::Config::USE_GLOSSARY,
12273 verbose => "this does nothing",
12274 noHelp  => 2,
12275};
12276
12277$T2H_OBSOLETE_OPTIONS -> {check} =
12278{
12279 type => '!',
12280 linkage => sub {exit 0;},
12281 verbose => "exit without doing anything",
12282 noHelp  => 2,
12283};
12284
12285$T2H_OBSOLETE_OPTIONS -> {dump_texi} =
12286{
12287 type => '!',
12288 linkage => \$Texi2HTML::Config::DUMP_TEXI,
12289 verbose => 'obsolete, use "-dump-texi" instead',
12290 noHelp => 1
12291};
12292
12293$T2H_OBSOLETE_OPTIONS -> {frameset_doctype} =
12294{
12295 type => '=s',
12296 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
12297 verbose => 'obsolete, use "-frameset-doctype" instead',
12298 noHelp => 2
12299};
12300
12301$T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} =
12302{
12303 type => '!',
12304 linkage => sub {$Texi2HTML::Config::SECTION_NAVIGATION = 0;},
12305 verbose => 'obsolete, use -nosec_nav',
12306 noHelp => 2,
12307};
12308my $use_acc; # not used
12309$T2H_OBSOLETE_OPTIONS -> {use_acc} =
12310{
12311 type => '!',
12312 linkage => \$use_acc,
12313 verbose => 'obsolete, set to true unconditionnaly',
12314 noHelp => 2
12315};
12316$T2H_OBSOLETE_OPTIONS -> {expandinfo} =
12317{
12318 type => '!',
12319 linkage => sub {push @Texi2HTML::Config::EXPAND, 'info';},
12320 verbose => 'obsolete, use "-expand info" instead',
12321 noHelp => 2,
12322};
12323$T2H_OBSOLETE_OPTIONS -> {expandtex} =
12324{
12325 type => '!',
12326 linkage => sub {push @Texi2HTML::Config::EXPAND, 'tex';},
12327 verbose => 'obsolete, use "-expand tex" instead',
12328 noHelp => 2,
12329};
12330$T2H_OBSOLETE_OPTIONS -> {split_node} =
12331{
12332 type => '!',
12333 linkage => sub{$Texi2HTML::Config::SPLIT = 'section';},
12334 verbose => 'obsolete, use "-split section" instead',
12335 noHelp => 2,
12336};
12337$T2H_OBSOLETE_OPTIONS -> {split_chapter} =
12338{
12339 type => '!',
12340 linkage => sub{$Texi2HTML::Config::SPLIT = 'chapter';},
12341 verbose => 'obsolete, use "-split chapter" instead',
12342 noHelp => 2,
12343};
12344$T2H_OBSOLETE_OPTIONS -> {no_verbose} =
12345{
12346 type => '!',
12347 linkage => sub {$Texi2HTML::Config::VERBOSE = 0;},
12348 verbose => 'obsolete, use -noverbose instead',
12349 noHelp => 2,
12350};
12351$T2H_OBSOLETE_OPTIONS -> {output_file} =
12352{
12353 type => '=s',
12354 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
12355 verbose => 'obsolete, use --out-file instead',
12356 noHelp => 2
12357};
12358
12359$T2H_OBSOLETE_OPTIONS -> {section_navigation} =
12360{
12361 type => '!',
12362 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
12363 verbose => 'obsolete, use --sec-nav instead',
12364 noHelp => 2,
12365};
12366
12367$T2H_OBSOLETE_OPTIONS -> {verbose} =
12368{
12369 type => '!',
12370 linkage=> \$Texi2HTML::Config::VERBOSE,
12371 verbose => 'obsolete, use -Verbose instead',
12372 noHelp => 2
12373};
12374
12375# read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc
12376# (this is obsolete)
12377my @rc_files = ();
12378push @rc_files, "$sysconfdir/texi2htmlrc" if defined($sysconfdir);
12379push @rc_files, "$ENV{'HOME'}/.texi2htmlrc" if (defined($ENV{HOME}));
12380foreach my $i (@rc_files)
12381{
12382    if (-e $i and -r $i)
12383    {
12384        print STDERR "# reading initialization file from $i\n"
12385	    if ($T2H_VERBOSE);
12386        print STDERR "Reading config from $i is obsolete, use texi2html/$conf_file_name instead\n";
12387        Texi2HTML::Config::load($i);
12388    }
12389}
12390
12391# read initialization files
12392foreach my $file (locate_init_file($conf_file_name, 1))
12393{
12394    print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE);
12395    Texi2HTML::Config::load($file);
12396}
12397
12398
12399#+++############################################################################
12400#                                                                              #
12401# parse command-line options
12402#                                                                              #
12403#---############################################################################
12404
12405
12406my $T2H_USAGE_TEXT = <<EOT;
12407Usage: texi2html  [OPTIONS] TEXINFO-FILE
12408Translates Texinfo source documentation to HTML.
12409EOT
12410my $T2H_FAILURE_TEXT = <<EOT;
12411Try 'texi2html --help' for usage instructions.
12412EOT
12413
12414my $options = new Getopt::MySimple;
12415
12416$T2H_OPTIONS -> {'help'} =
12417{
12418 type => ':i',
12419 default => '',
12420 linkage => sub {$options->helpOptions($_[1]);
12421    print "\nSend bugs and suggestions to <texi2html-bug\@nongnu.org>\n";
12422    exit (0);},
12423 verbose => "print help and exit"
12424};
12425
12426# this avoids getOptions defining twice 'help' and 'version'.
12427$T2H_OBSOLETE_OPTIONS->{'help'} = 0;
12428$T2H_OBSOLETE_OPTIONS->{'version'} = 0;
12429$T2H_OBSOLETE_OPTIONS->{'verbose'} = 0;
12430
12431# this is more compatible with makeinfo. But it changes how command lines
12432# are parsed, for example -init file.init dodesn't work anymore.
12433#Getopt::Long::Configure ("gnu_getopt");
12434
12435# some older version of GetOpt::Long don't have
12436# Getopt::Long::Configure("pass_through")
12437eval {Getopt::Long::Configure("pass_through");};
12438my $Configure_failed = $@ && <<EOT;
12439**WARNING: Parsing of obsolete command-line options could have failed.
12440           Consider to use only documented command-line options (run
12441           'texi2html --help 2' for a complete list) or upgrade to perl
12442           version 5.005 or higher.
12443EOT
12444if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
12445{
12446    print STDERR "$Configure_failed" if $Configure_failed;
12447    die $T2H_FAILURE_TEXT;
12448}
12449if (@ARGV > 1)
12450{
12451    eval {Getopt::Long::Configure("no_pass_through");};
12452    if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
12453    {
12454        print STDERR "$Configure_failed" if $Configure_failed;
12455        die $T2H_FAILURE_TEXT;
12456    }
12457}
12458
12459# $T2H_DEBUG and $T2H_VERBOSE are shorthands
12460$T2H_DEBUG = $Texi2HTML::Config::DEBUG;
12461$T2H_VERBOSE = $Texi2HTML::Config::VERBOSE;
12462
12463#
12464# read texi2html extensions (if any)
12465# It is obsolete (obsoleted by -init-file). we keep it for backward
12466# compatibility.
12467my $extensions = 'texi2html.ext';  # extensions in working directory
12468if (-f $extensions)
12469{
12470    print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
12471    require($extensions);
12472}
12473my $progdir;
12474($progdir = $0) =~ s/[^\/]+$//;
12475if ($progdir && ($progdir ne './'))
12476{
12477    $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
12478    if (-f $extensions)
12479    {
12480	print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
12481	require($extensions);
12482    }
12483}
12484
12485
12486#+++############################################################################
12487#                                                                              #
12488# evaluation of cmd line options
12489#                                                                              #
12490#---############################################################################
12491
12492# set the default 'args' entry to normal for each style hash (and each command
12493# within)
12494my $name_index = -1;
12495my @hash_names = ('style_map', 'style_map_pre', 'style_map_texi', 'simple_format_style_map_texi');
12496foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi)
12497{
12498    $name_index++;
12499    my $name = $hash_names[$name_index]; # name associated with hash ref
12500    foreach my $style (keys(%{$hash}))
12501    {
12502        next unless (ref($hash->{$style}) eq 'HASH');
12503        $hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'}));
12504        die "Bug: args not defined, but existing, for $style in $name" if (!defined($hash->{$style}->{'args'}));
12505#print STDERR "DEFAULT($name, $hash) add normal as arg for $style ($hash->{$style}), $hash->{$style}->{'args'}\n";
12506    }
12507}
12508
12509my (%cross_ref_simple_map_texi, %cross_ref_style_map_texi,
12510  %cross_ref_texi_map, %cross_transliterate_style_map_texi,
12511  %cross_transliterate_texi_map);
12512
12513# setup hashes used for html manual cross references in texinfo
12514%cross_ref_texi_map = %Texi2HTML::Config::texi_map;
12515
12516$cross_ref_texi_map{'enddots'} = '...';
12517
12518%cross_ref_simple_map_texi = %Texi2HTML::Config::simple_map_texi;
12519
12520%cross_transliterate_texi_map = %cross_ref_texi_map;
12521
12522foreach my $command (keys(%Texi2HTML::Config::style_map_texi))
12523{
12524    $cross_ref_style_map_texi{$command} = {};
12525    $cross_transliterate_style_map_texi{$command} = {};
12526    foreach my $key (keys (%{$Texi2HTML::Config::style_map_texi{$command}}))
12527    {
12528#print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n";
12529         $cross_ref_style_map_texi{$command}->{$key} =
12530              $Texi2HTML::Config::style_map_texi{$command}->{$key};
12531         $cross_transliterate_style_map_texi{$command}->{$key} =
12532              $Texi2HTML::Config::style_map_texi{$command}->{$key};
12533    }
12534}
12535
12536$cross_ref_simple_map_texi{"\n"} = ' ';
12537$cross_ref_simple_map_texi{"*"} = ' ';
12538
12539
12540# Fill in the %style_type hash, a hash associating style @-comand with
12541# the type, 'accent', real 'style', simple' style, or 'special'.
12542# 'simple_style' styles don't extend accross lines.
12543my %style_type = ();
12544my @simple_styles = ('ctrl', 'w', 'url','uref','indicateurl','email',
12545    'titlefont');
12546foreach my $style (keys(%Texi2HTML::Config::style_map))
12547{
12548    if (exists $Texi2HTML::Config::command_type{$style})
12549    {
12550        $style_type{$style} = $Texi2HTML::Config::command_type{$style};
12551        next;
12552    }
12553    if (ref($Texi2HTML::Config::style_map{$style} eq 'HASH'))
12554    {
12555        $style_type{$style} = $Texi2HTML::Config::style_map{$style}->{'type'}
12556          if (exists($Texi2HTML::Config::style_map{$style}->{'type'}));
12557    }
12558    else
12559    {
12560        $style_type{$style} = 'simple_style' if (grep {$_ eq $style} @simple_styles);
12561    }
12562    $style_type{$style} = 'style' unless (defined($style_type{$style}));
12563}
12564
12565foreach my $accent (keys(%Texi2HTML::Config::unicode_accents), 'tieaccent', 'dotless')
12566{
12567    if (exists $Texi2HTML::Config::command_type{$accent})
12568    {
12569        $style_type{$accent} = $Texi2HTML::Config::command_type{$accent};
12570        next;
12571    }
12572    $style_type{$accent} = 'accent';
12573}
12574
12575
12576
12577
12578foreach my $special ('footnote', 'ref', 'xref', 'pxref', 'inforef', 'anchor', 'image', 'hyphenation')
12579{
12580    if (exists $Texi2HTML::Config::command_type{$special})
12581    {
12582        $style_type{$special} = $Texi2HTML::Config::command_type{$special};
12583        next;
12584    }
12585    $style_type{$special} = 'special';
12586}
12587
12588# retro compatibility for $Texi2HTML::Config::EXPAND
12589push (@Texi2HTML::Config::EXPAND, $Texi2HTML::Config::EXPAND) if ($Texi2HTML::Config::EXPAND);
12590
12591# correct %Texi2HTML::Config::texi_formats_map based on command line and init
12592# variables
12593$Texi2HTML::Config::texi_formats_map{'menu'} = 1 if ($Texi2HTML::Config::SHOW_MENU);
12594
12595foreach my $expanded (@Texi2HTML::Config::EXPAND)
12596{
12597    $Texi2HTML::Config::texi_formats_map{"if$expanded"} = 1 if (exists($Texi2HTML::Config::texi_formats_map{"if$expanded"}));
12598    next unless (exists($Texi2HTML::Config::texi_formats_map{$expanded}));
12599    if (grep {$_ eq $expanded} @raw_regions)
12600    {
12601         $Texi2HTML::Config::texi_formats_map{$expanded} = 'raw';
12602    }
12603    else
12604    {
12605         $Texi2HTML::Config::texi_formats_map{$expanded} = 1;
12606    }
12607}
12608
12609foreach my $key (keys(%Texi2HTML::Config::texi_formats_map))
12610{
12611    unless ($Texi2HTML::Config::texi_formats_map{$key} eq 'raw')
12612    {
12613        set_no_line_macro($key, 1);
12614        set_no_line_macro("end $key", 1);
12615    }
12616}
12617
12618# handle ifnot regions
12619foreach my $region (keys (%Texi2HTML::Config::texi_formats_map))
12620{
12621    next if ($region =~ /^ifnot/);
12622    if ($Texi2HTML::Config::texi_formats_map{$region} and $region =~ /^if(\w+)$/)
12623    {
12624        $Texi2HTML::Config::texi_formats_map{"ifnot$1"} = 0;
12625    }
12626}
12627
12628if ($T2H_VERBOSE)
12629{
12630    print STDERR "# Expanded: ";
12631    foreach my $text_macro (keys(%Texi2HTML::Config::texi_formats_map))
12632    {
12633        print STDERR "$text_macro " if ($Texi2HTML::Config::texi_formats_map{$text_macro});
12634    }
12635    print STDERR "\n";
12636}
12637
12638# This is kept in that file although it is html formatting as it seems to
12639# be rather obsolete
12640$Texi2HTML::Config::INVISIBLE_MARK = '<img src="invisible.xbm" alt="">' if $Texi2HTML::Config::INVISIBLE_MARK eq 'xbm';
12641
12642$T2H_DEBUG |= $DEBUG_TEXI if ($Texi2HTML::Config::DUMP_TEXI);
12643
12644# no user provided USE_UNICODE, use configure provided
12645if (!defined($Texi2HTML::Config::USE_UNICODE))
12646{
12647    $Texi2HTML::Config::USE_UNICODE = '1';
12648}
12649
12650# no user provided nor configured, run time test
12651if ($Texi2HTML::Config::USE_UNICODE eq '@' .'USE_UNICODE@')
12652{
12653    $Texi2HTML::Config::USE_UNICODE = 1;
12654    eval {
12655        require Encode;
12656        require Unicode::Normalize;
12657        Encode->import('encode');
12658    };
12659    $Texi2HTML::Config::USE_UNICODE = 0 if ($@);
12660}
12661elsif ($Texi2HTML::Config::USE_UNICODE)
12662{# user provided or set by configure
12663    require Encode;
12664    require Unicode::Normalize;
12665    Encode->import('encode');
12666}
12667
12668# no user provided USE_UNIDECODE, use configure provided
12669if (!defined($Texi2HTML::Config::USE_UNIDECODE))
12670{
12671    $Texi2HTML::Config::USE_UNIDECODE = '0';
12672}
12673
12674# no user provided nor configured, run time test
12675if ($Texi2HTML::Config::USE_UNIDECODE eq '@' .'USE_UNIDECODE@')
12676{
12677    $Texi2HTML::Config::USE_UNIDECODE = 1;
12678    eval {
12679        require Text::Unidecode;
12680        Text::Unidecode->import('unidecode');
12681    };
12682    $Texi2HTML::Config::USE_UNIDECODE = 0 if ($@);
12683}
12684elsif ($Texi2HTML::Config::USE_UNIDECODE)
12685{# user provided or set by configure
12686    require Text::Unidecode;
12687    Text::Unidecode->import('unidecode');
12688}
12689
12690print STDERR "# USE_UNICODE $Texi2HTML::Config::USE_UNICODE, USE_UNIDECODE $Texi2HTML::Config::USE_UNIDECODE \n"
12691  if ($T2H_VERBOSE);
12692
12693# Construct hashes used for cross references generation
12694# Do it now as the user may have changed $USE_UNICODE
12695
12696foreach my $key (keys(%Texi2HTML::Config::unicode_map))
12697{
12698    if ($Texi2HTML::Config::unicode_map{$key} ne '')
12699    {
12700        if ($Texi2HTML::Config::USE_UNICODE)
12701        {
12702            $cross_ref_texi_map{$key} = chr(hex($Texi2HTML::Config::unicode_map{$key}));
12703             # cross_transliterate_texi_map is only used if USE_UNICODE or
12704             # USE_UNIDECODE is unset and TRANSLITERATE_NODE is set
12705             if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}))
12706             {
12707                $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
12708             }
12709             else
12710             {
12711                 $cross_transliterate_texi_map{$key} = chr(hex($Texi2HTML::Config::unicode_map{$key}));
12712             }
12713        }
12714        else
12715        {
12716            $cross_ref_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
12717             # cross_transliterate_texi_map is only used if USE_UNICODE or
12718             # USE_UNIDECODE is unset and TRANSLITERATE_NODE is set
12719             if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}))
12720             {
12721                 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
12722             }
12723             else
12724             {
12725                  $cross_transliterate_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
12726             }
12727        }
12728    }
12729}
12730#if ($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::TRANSLITERATE_NODE
12731if ($Texi2HTML::Config::TRANSLITERATE_NODE and (
12732    ($Texi2HTML::Config::USE_UNICODE and ! $Texi2HTML::Config::USE_UNIDECODE)
12733    or !$Texi2HTML::Config::USE_UNICODE))
12734{
12735    foreach my $key (keys (%Texi2HTML::Config::transliterate_accent_map))
12736    {
12737        $Texi2HTML::Config::transliterate_map{$key} = $Texi2HTML::Config::transliterate_accent_map{$key};
12738    }
12739}
12740
12741foreach my $key (keys(%cross_ref_style_map_texi))
12742{
12743    if ($style_type{$key} eq 'accent'
12744        and (ref($cross_ref_style_map_texi{$key}) eq 'HASH'))
12745    {
12746        if ($Texi2HTML::Config::USE_UNICODE)
12747        {
12748             $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_utf8_accent;
12749        }
12750        else
12751        {
12752             $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_nounicode_cross_manual_accent;
12753        }
12754        # this is only used if TRANSLITERATE_NODE is set and USE_UNICODE
12755        # or USE_UNIDECODE is not set
12756        $cross_transliterate_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_transliterate_cross_manual_accent;
12757    }
12758}
12759
12760if ($Texi2HTML::Config::L2H)
12761{
12762   push @Texi2HTML::Config::command_handler_init, \&Texi2HTML::LaTeX2HTML::init;
12763   push @Texi2HTML::Config::command_handler_process, \&Texi2HTML::LaTeX2HTML::latex2html;
12764   push @Texi2HTML::Config::command_handler_finish, \&Texi2HTML::LaTeX2HTML::finish;
12765   $Texi2HTML::Config::command_handler{'math'} =
12766     { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex,
12767       'expand' => \&Texi2HTML::LaTeX2HTML::do_tex
12768     };
12769   $Texi2HTML::Config::command_handler{'tex'} =
12770     { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex,
12771       'expand' => \&Texi2HTML::LaTeX2HTML::do_tex
12772     };
12773}
12774
12775if (defined($Texi2HTML::Config::DO_CONTENTS))
12776{
12777   $Texi2HTML::GLOBAL{'DO_CONTENTS'} = $Texi2HTML::Config::DO_CONTENTS;
12778}
12779if (defined($Texi2HTML::Config::DO_SCONTENTS))
12780{
12781   $Texi2HTML::GLOBAL{'DO_SCONTENTS'} = $Texi2HTML::Config::DO_SCONTENTS;
12782}
12783
12784# FIXME encoding for first file or all files?
12785if (defined($Texi2HTML::Config::IN_ENCODING))
12786{
12787   $Texi2HTML::GLOBAL{'IN_ENCODING'} = $Texi2HTML::Config::IN_ENCODING;
12788}
12789
12790if (defined($Texi2HTML::Config::DOCUMENT_ENCODING))
12791{
12792   $Texi2HTML::GLOBAL{'DOCUMENT_ENCODING'} = $Texi2HTML::Config::DOCUMENT_ENCODING;
12793}
12794
12795# Backward compatibility for deprecated $Texi2HTML::Config::ENCODING
12796$Texi2HTML::Config::ENCODING_NAME = $Texi2HTML::Config::ENCODING
12797  if (!defined($Texi2HTML::Config::ENCODING_NAME) and defined($Texi2HTML::Config::ENCODING));
12798
12799# APA: There's got to be a better way:
12800if ($Texi2HTML::Config::TEST)
12801{
12802    # to generate files similar to reference ones to be able to check for
12803    # real changes we use these dummy values if -test is given
12804    $T2H_USER = 'a tester';
12805    $THISPROG = 'texi2html';
12806    setlocale( LC_ALL, "C" );
12807}
12808else
12809{
12810    # the eval prevents this from breaking on system which do not have
12811    # a proper getpwuid implemented
12812    eval { ($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//;}; # Who am i
12813    # APA: Provide Windows NT workaround until getpwuid gets
12814    # implemented there.
12815    $T2H_USER = $ENV{'USERNAME'} unless (defined($T2H_USER));
12816}
12817$T2H_USER = &$I('unknown') unless (defined($T2H_USER));
12818
12819
12820$Texi2HTML::GLOBAL{'debug_l2h'} = 1 if ($T2H_DEBUG & $DEBUG_L2H);
12821
12822#
12823# can I use ISO8859 characters? (HTML+)
12824#
12825if ($Texi2HTML::Config::USE_ISO)
12826{
12827    foreach my $thing (keys(%Texi2HTML::Config::iso_symbols))
12828    {
12829         next unless exists ($::things_map_ref->{$thing});
12830         $::things_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
12831         $::pre_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
12832         $Texi2HTML::Config::simple_format_texi_map{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
12833    }
12834    # we don't override the user defined quote, but beware that this works
12835    # only if the hardcoded defaults, '`' and "'" match with the defaults
12836    # in the default init file
12837    $Texi2HTML::Config::OPEN_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{'`'}
12838        if (exists($Texi2HTML::Config::iso_symbols{'`'}) and ($Texi2HTML::Config::OPEN_QUOTE_SYMBOL eq '`'));
12839    $Texi2HTML::Config::CLOSE_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{"'"}
12840       if (exists($Texi2HTML::Config::iso_symbols{"'"}) and ($Texi2HTML::Config::CLOSE_QUOTE_SYMBOL eq "'"));
12841}
12842
12843# parse texinfo cnf file for external manual specifications. This was
12844# discussed on texinfo list but not in makeinfo for now.
12845my @texinfo_htmlxref_files = locate_init_file ($texinfo_htmlxref, 1, \@texinfo_config_dirs);
12846foreach my $file (@texinfo_htmlxref_files)
12847{
12848    print STDERR "html refs config file: $file\n" if ($T2H_DEBUG);
12849    unless (open (HTMLXREF, $file))
12850    {
12851         warn "Cannot open html refs config file ${file}: $!";
12852         next;
12853    }
12854    while (my $hline = <HTMLXREF>)
12855    {
12856        my $line = $hline;
12857        $hline =~ s/[#]\s.*//;
12858        $hline =~ s/^\s*//;
12859        next if $hline =~ /^\s*$/;
12860        my @htmlxref = split /\s+/, $hline;
12861        my $manual = shift @htmlxref;
12862        my $split_or_mono = shift @htmlxref;
12863        if (!defined($split_or_mono) or ($split_or_mono ne 'split' and $split_or_mono ne 'mono'))
12864        {
12865            echo_warn("Bad line in $file: $line");
12866            next;
12867        }
12868        my $href = shift @htmlxref;
12869        next if (exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}) and exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'}));
12870
12871        if (defined($href))
12872        {
12873            $href =~ s/\/*$// if ($split_or_mono eq 'split');
12874            $Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'} = $href;
12875        }
12876        else
12877        {
12878            $Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono} = {};
12879        }
12880    }
12881    close (HTMLXREF);
12882}
12883
12884if ($T2H_DEBUG)
12885{
12886    foreach my $manual (keys(%{$Texi2HTML::GLOBAL{'htmlxref'}}))
12887    {
12888         foreach my $split ('split', 'mono')
12889         {
12890              my $href = 'NO';
12891              next unless (exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split}));
12892              $href = $Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split}->{'href'} if
12893                  exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split}->{'href'});
12894              print STDERR "$manual: $split, href: $href\n";
12895         }
12896    }
12897}
12898
12899# resulting files splitting
12900if ($Texi2HTML::Config::SPLIT =~ /section/i)
12901{
12902    $Texi2HTML::Config::SPLIT = 'section';
12903}
12904elsif ($Texi2HTML::Config::SPLIT =~ /node/i)
12905{
12906    $Texi2HTML::Config::SPLIT = 'node';
12907}
12908elsif ($Texi2HTML::Config::SPLIT =~ /chapter/i)
12909{
12910    $Texi2HTML::Config::SPLIT = 'chapter';
12911}
12912else
12913{
12914    $Texi2HTML::Config::SPLIT = '';
12915}
12916
12917$Texi2HTML::Config::SPLIT_INDEX = 0 unless $Texi2HTML::Config::SPLIT;
12918
12919# Something like backward compatibility
12920if ($Texi2HTML::Config::SPLIT and defined($Texi2HTML::Config::SUBDIR)
12921    and ($Texi2HTML::Config::SUBDIR ne '') and
12922   (!defined($Texi2HTML::Config::OUT) or ($Texi2HTML::Config::OUT eq '')))
12923{
12924    $Texi2HTML::Config::OUT = $Texi2HTML::Config::SUBDIR;
12925}
12926
12927die "output to STDOUT and split or frames incompatible\n"
12928    if (($Texi2HTML::Config::SPLIT or $Texi2HTML::Config::FRAMES) and ($Texi2HTML::Config::OUT eq '-'));
12929
12930if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq '.'))
12931{# This is to avoid trouble with latex2html
12932    $Texi2HTML::Config::OUT = '';
12933}
12934
12935my @include_dirs_orig = @Texi2HTML::Config::INCLUDE_DIRS;
12936
12937# extension
12938$Texi2HTML::GLOBAL{'extension'} = $Texi2HTML::Config::EXTENSION;
12939if ($Texi2HTML::Config::SHORTEXTN)
12940{
12941   $Texi2HTML::GLOBAL{'extension'} = "htm";
12942}
12943
12944#
12945# file name business
12946#
12947
12948my $docu_dir;            # directory of the document
12949my $docu_name;           # basename of the document
12950my $docu_rdir;           # directory for the output
12951my $docu_toc;            # document's table of contents
12952my $docu_stoc;           # document's short toc
12953my $docu_foot;           # document's footnotes
12954my $docu_about;          # about this document
12955my $docu_top;            # document top
12956my $docu_doc;            # document (or document top of split)
12957my $docu_frame;          # main frame file
12958my $docu_toc_frame;      # toc frame file
12959my $path_to_working_dir; # relative path leading to the working
12960                         # directory from the document directory
12961my $docu_doc_file;
12962my $docu_toc_file;
12963my $docu_stoc_file;
12964my $docu_foot_file;
12965my $docu_about_file;
12966my $docu_top_file;
12967my $docu_frame_file;
12968my $docu_toc_frame_file;
12969
12970sub set_docu_names($$)
12971{
12972   my $docu_base_name = shift;
12973   my $file_nr = shift;
12974   if ($docu_base_name =~ /(.*\/)/)
12975   {
12976      $docu_dir = $1;
12977      chop($docu_dir);
12978      $docu_name = $docu_base_name;
12979      $docu_name =~ s/.*\///;
12980   }
12981   else
12982   {
12983      $docu_dir = '.';
12984      $docu_name = $docu_base_name;
12985   }
12986
12987   @Texi2HTML::Config::INCLUDE_DIRS = @include_dirs_orig;
12988   unshift(@Texi2HTML::Config::INCLUDE_DIRS, $docu_dir);
12989   unshift(@Texi2HTML::Config::INCLUDE_DIRS, @Texi2HTML::Config::PREPEND_DIRS);
12990# AAAA
12991   $docu_name = $Texi2HTML::Config::PREFIX if ($Texi2HTML::Config::PREFIX
12992       and ($file_nr == 0));
12993
12994# subdir
12995   $docu_rdir = '';
12996
12997   if ($Texi2HTML::Config::SPLIT)
12998   {
12999      if (defined($Texi2HTML::Config::OUT) and ($file_nr == 0))
13000      {
13001         $docu_rdir = $Texi2HTML::Config::OUT;
13002      }
13003      else
13004      {
13005         $docu_rdir = $docu_name;
13006      }
13007      if ($docu_rdir ne '')
13008      {
13009         $docu_rdir =~ s|/*$||;
13010         $docu_rdir .= '/';
13011      }
13012   }
13013   else
13014   {
13015      my $out_file;
13016# AAAA
13017   # even if the out file is not set by OUT, in case it is not the first
13018   # file, the out directory is still used
13019      if (defined($Texi2HTML::Config::OUT) and $Texi2HTML::Config::OUT ne '')
13020      {
13021         $out_file = $Texi2HTML::Config::OUT;
13022      }
13023      else
13024      {
13025         $out_file = $docu_name;
13026      }
13027
13028      if ($out_file =~ m|(.*)/|)
13029      {# there is a leading directories
13030         $docu_rdir = "$1/";
13031      }
13032   }
13033
13034   if ($docu_rdir ne '')
13035   {
13036      unless (-d $docu_rdir)
13037      {
13038         if ( mkdir($docu_rdir, oct(755)))
13039         {
13040            print STDERR "# created directory $docu_rdir\n" if ($T2H_VERBOSE);
13041         }
13042         else
13043         {
13044            die "$ERROR can't create directory $docu_rdir\n";
13045         }
13046     }
13047     print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
13048   }
13049   else
13050   {
13051      print STDERR "# putting result files into current directory \n" if ($T2H_VERBOSE);
13052   }
13053   # We don't use "./" as $docu_rdir when $docu_rdir is the current directory
13054   # because it is problematic for latex2html. To test writability with -w,
13055   # however we need a real directory.
13056   my $result_rdir = $docu_rdir;
13057   $result_rdir = "." if ($docu_rdir eq '');
13058   unless (-w $result_rdir)
13059   {
13060      $docu_rdir = 'current directory' if ($docu_rdir eq '');
13061      die "$ERROR $docu_rdir not writable\n";
13062   }
13063
13064   # relative path leading to the working directory from the document directory
13065   $path_to_working_dir = $docu_rdir;
13066   if ($docu_rdir ne '')
13067   {
13068      my $cwd = cwd;
13069      my $docu_path = $docu_rdir;
13070      $docu_path = $cwd . '/' . $docu_path unless ($docu_path =~ /^\//);
13071      my @result = ();
13072      # this code simplify the paths. The cwd is absolute, while in the
13073      # document path there may be some .., a .. is removed with the
13074      # previous path element, such that something like
13075      # /cwd/directory/../somewhere/
13076      # leads to
13077      # /cwd/somewhere/
13078      # with directory/.. removed
13079      foreach my $element (split /\//, File::Spec->canonpath($docu_path))
13080      {
13081         if ($element eq '')
13082         {
13083            push @result, '';
13084         }
13085         elsif ($element eq '..')
13086         {
13087            if (@result and ($result[-1] eq ''))
13088            {
13089               print STDERR "Too much .. in absolute file name\n";
13090            }
13091            elsif (@result and ($result[-1] ne '..'))
13092            {
13093               pop @result;
13094            }
13095            else
13096            {
13097               push @result, $element;
13098            }
13099         }
13100         else
13101         {
13102            push @result, $element;
13103         }
13104      }
13105      $path_to_working_dir = File::Spec->abs2rel($cwd, join ('/', @result));
13106      # this should not be needed given what canonpath does
13107      $path_to_working_dir =~ s:/*$::;
13108      $path_to_working_dir .= '/' unless($path_to_working_dir eq '');
13109   }
13110
13111   my $docu_ext = $Texi2HTML::THISDOC{'extension'};
13112   # out_dir is undocummented, should never be used, use destination_directory
13113   $Texi2HTML::THISDOC{'out_dir'} = $docu_rdir;
13114
13115   $Texi2HTML::THISDOC{'destination_directory'} = $docu_rdir;
13116   $Texi2HTML::THISDOC{'file_base_name'} = $docu_name;
13117
13118   $docu_doc = $docu_name . (defined($docu_ext) ? ".$docu_ext" : ""); # document's contents
13119   if ($Texi2HTML::Config::SPLIT)
13120   {
13121# AAAA
13122      if (defined($Texi2HTML::Config::TOP_FILE) and ($Texi2HTML::Config::TOP_FILE ne '') and ($file_nr == 0))
13123      {
13124         $docu_top = $Texi2HTML::Config::TOP_FILE;
13125      }
13126      else
13127      {
13128         $docu_top = $docu_doc;
13129      }
13130   }
13131   else
13132   {
13133# AAAA
13134      if (defined($Texi2HTML::Config::OUT) and ($file_nr == 0))
13135      {
13136         my $out_file = $Texi2HTML::Config::OUT;
13137         $out_file =~ s|.*/||;
13138         $docu_doc = $out_file if ($out_file !~ /^\s*$/);
13139      }
13140      if (defined $Texi2HTML::Config::element_file_name)
13141      {
13142         my $docu_doc_set = &$Texi2HTML::Config::element_file_name
13143           (undef, "doc", $docu_name);
13144         $docu_doc = $docu_doc_set if (defined($docu_doc_set));
13145      }
13146      $docu_top = $docu_doc;
13147   }
13148
13149   if ($Texi2HTML::Config::SPLIT or !$Texi2HTML::Config::MONOLITHIC)
13150   {
13151      if (defined $Texi2HTML::Config::element_file_name)
13152      {
13153         $docu_toc = &$Texi2HTML::Config::element_file_name
13154            (undef, "toc", $docu_name);
13155         $docu_stoc = &$Texi2HTML::Config::element_file_name
13156            (undef, "stoc", $docu_name);
13157         $docu_foot = &$Texi2HTML::Config::element_file_name
13158            (undef, "foot", $docu_name);
13159         $docu_about = &$Texi2HTML::Config::element_file_name
13160            (undef, "about", $docu_name);
13161	# $docu_top may be overwritten later.
13162      }
13163      if (!defined($docu_toc))
13164      {
13165         my $default_toc = "${docu_name}_toc";
13166         $default_toc .= ".$docu_ext" if (defined($docu_ext));
13167# AAAA
13168      if (defined($Texi2HTML::Config::TOC_FILE) and ($Texi2HTML::Config::TOC_FILE ne '') and ($file_nr == 0))
13169         {
13170            $docu_toc = $Texi2HTML::Config::TOC_FILE;
13171         }
13172         else
13173         {
13174            $docu_toc = $default_toc;
13175         }
13176      }
13177      if (!defined($docu_stoc))
13178      {
13179         $docu_stoc  = "${docu_name}_ovr";
13180         $docu_stoc .= ".$docu_ext" if (defined($docu_ext));
13181      }
13182      if (!defined($docu_foot))
13183      {
13184         $docu_foot  = "${docu_name}_fot";
13185         $docu_foot .= ".$docu_ext" if (defined($docu_ext));
13186      }
13187      if (!defined($docu_about))
13188      {
13189         $docu_about = "${docu_name}_abt";
13190         $docu_about .= ".$docu_ext" if (defined($docu_ext));
13191      }
13192   }
13193   else
13194   {
13195      $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_doc;
13196   }
13197
13198   # Note that file extension has already been added here.
13199   if ($Texi2HTML::Config::FRAMES)
13200   {
13201      if (defined $Texi2HTML::Config::element_file_name)
13202      {
13203         $docu_frame = &$Texi2HTML::Config::element_file_name
13204            (undef, "frame", $docu_name);
13205         $docu_toc_frame = &$Texi2HTML::Config::element_file_name
13206           (undef, "toc_frame", $docu_name);
13207      }
13208   }
13209
13210   if (!defined($docu_frame))
13211   {
13212      $docu_frame = "${docu_name}_frame";
13213      $docu_frame .= ".$docu_ext" if (defined($docu_ext));
13214   }
13215   if (!defined($docu_toc_frame))
13216   {
13217      $docu_toc_frame  = "${docu_name}_toc_frame";
13218      $docu_toc_frame .= ".$docu_ext" if (defined($docu_ext));
13219   }
13220
13221   if ($T2H_VERBOSE)
13222   {
13223      print STDERR "# Files and directories:\n";
13224      print STDERR "# rdir($docu_rdir) path_to_working_dir($path_to_working_dir)\n";
13225      print STDERR "# doc($docu_doc) top($docu_top) toc($docu_toc) stoc($docu_stoc)\n";
13226      print STDERR "# foot($docu_foot) about($docu_about) frame($docu_toc) toc_frame($docu_toc_frame)\n";
13227   }
13228
13229   $docu_doc_file = "$docu_rdir$docu_doc";
13230   $docu_toc_file  = "$docu_rdir$docu_toc";
13231   $docu_stoc_file = "$docu_rdir$docu_stoc";
13232   $docu_foot_file = "$docu_rdir$docu_foot";
13233   $docu_about_file = "$docu_rdir$docu_about";
13234   $docu_top_file  = "$docu_rdir$docu_top";
13235   $docu_frame_file = "$docu_rdir$docu_frame";
13236   $docu_toc_frame_file = "$docu_rdir$docu_toc_frame";
13237
13238# For use in init files
13239   $Texi2HTML::THISDOC{'filename'}->{'top'} = $docu_top;
13240   $Texi2HTML::THISDOC{'filename'}->{'foot'} = $docu_foot;
13241   $Texi2HTML::THISDOC{'filename'}->{'stoc'} = $docu_stoc;
13242   $Texi2HTML::THISDOC{'filename'}->{'about'} = $docu_about;
13243   $Texi2HTML::THISDOC{'filename'}->{'toc'} = $docu_toc;
13244# FIXME document that
13245   $Texi2HTML::THISDOC{'filename'}->{'toc_frame'} = $docu_toc_frame;
13246   $Texi2HTML::THISDOC{'filename'}->{'frame'} = $docu_frame;
13247}
13248
13249#
13250# Common initializations
13251#
13252
13253sub texinfo_initialization($)
13254{
13255    my $pass = shift;
13256
13257    # All the initialization used the last @documentlanguage found during
13258    # pass_structure. Now we reset it, if it is not set on the command line
13259    # such that the @documentlanguage macros are used when they arrive
13260
13261    # FIXME ask on bug-texinfo
13262    if (!$Texi2HTML::GLOBAL{'current_lang'})
13263    {
13264        set_document_language($Texi2HTML::Config::LANG) if defined($Texi2HTML::Config::LANG);
13265        # $LANG isn't known
13266        set_document_language('en') unless ($Texi2HTML::THISDOC{'current_lang'});
13267    }
13268    # reset the @set/@clear values
13269    %value = %value_initial;
13270#    set_special_names();
13271    foreach my $init_mac ('everyheading', 'everyfooting', 'evenheading',
13272        'evenfooting', 'oddheading', 'oddfooting', 'headings',
13273        'allowcodebreaks', 'frenchspacing', 'exampleindent',
13274        'firstparagraphindent', 'paragraphindent', 'clickstyle')
13275    {
13276        $Texi2HTML::THISDOC{$init_mac} = undef;
13277        delete $Texi2HTML::THISDOC{$init_mac};
13278    }
13279}
13280
13281#+++###########################################################################
13282#                                                                             #
13283# Pass texi: read source, handle variable, ignored text,                      #
13284#                                                                             #
13285#---###########################################################################
13286
13287my @fhs = ();			# hold the file handles to read
13288#my @lines = ();             # whole document
13289#my @lines_numbers = ();     # line number, originating file associated with
13290                            # whole document
13291my $macros = undef;         # macros. reference on a hash
13292my %info_enclose = ();      # macros defined with definfoenclose
13293my @floats = ();            # floats list
13294my %floats = ();            # floats by style
13295
13296sub initialise_state_texi($)
13297{
13298    my $state = shift;
13299    $state->{'texi'} = 1;           # for substitute_text and close_stack:
13300                                    # 1 if pass_texi/scan_texi is to be used
13301    $state->{'macro_inside'} = 0 unless(defined($state->{'macro_inside'}));
13302    $state->{'ifvalue_inside'} = 0 unless(defined($state->{'ifvalue_inside'}));
13303    $state->{'arg_expansion'} = 0 unless(defined($state->{'arg_expansion'}));
13304}
13305
13306
13307sub pass_texi($)
13308{
13309    my $input_file_name = shift;
13310    #my $texi_line_number = { 'file_name' => '', 'line_nr' => 0, 'macro' => '' };
13311
13312    my @lines = ();             # whole document
13313    my @lines_numbers = ();     # line number, originating file associated with
13314                                # whole document
13315    my @first_lines = ();
13316    my $first_lines = 1;        # is it the first lines
13317    my $state = {};
13318                                # holds the informations about the context
13319                                # to pass it down to the functions
13320    initialise_state_texi($state);
13321    my $texi_line_number;
13322    ($texi_line_number, $state->{'input_spool'}) =
13323          open_file($input_file_name, '');
13324    my @stack;
13325    my $text;
13326    my $cline;
13327 INPUT_LINE: while (1)
13328    {
13329        ($cline, $state->{'input_spool'}) = next_line($texi_line_number);
13330        last if (!defined($cline));
13331        #
13332        # remove the lines preceding \input or an @-command
13333        #
13334        if ($first_lines)
13335        {
13336            if ($cline =~ /^\\input/)
13337            {
13338                push @first_lines, $cline;
13339                $first_lines = 0;
13340                next;
13341            }
13342            if ($cline =~ /^\s*\@/)
13343            {
13344                $first_lines = 0;
13345            }
13346            else
13347            {
13348                push @first_lines, $cline;
13349                next;
13350            }
13351        }
13352	#print STDERR "PASS_TEXI($texi_line_number->{'line_nr'})$cline";
13353        my $chomped_line = $cline;
13354        if (scan_texi ($cline, \$text, \@stack, $state, $texi_line_number) and chomp($chomped_line))
13355        {
13356        #print STDERR "==> new page (line_nr $texi_line_number->{'line_nr'},$texi_line_number->{'file_name'},$texi_line_number->{'macro'})\n";
13357            push (@lines_numbers, { 'file_name' => $texi_line_number->{'file_name'},
13358                  'line_nr' => $texi_line_number->{'line_nr'},
13359                  'macro' => $texi_line_number->{'macro'} });
13360        }
13361        #dump_stack (\$text, \@stack, $state);
13362        if ($state->{'bye'})
13363        {
13364            #dump_stack(\$text, \@stack, $state);
13365            # close stack after bye
13366            #print STDERR "close stack after bye\n";
13367            close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number);
13368            #dump_stack(\$text, \@stack, $state);
13369        }
13370        next if (@stack);
13371        $cline = $text;
13372        $text = '';
13373        if (!defined($cline))
13374        {# FIXME: remove the error message if it is reported too often
13375            print STDERR "# \$cline undefined after scan_texi. This may be a bug, or not.\n";
13376            print STDERR "# Report (with texinfo file) if you want, otherwise ignore that message.\n";
13377            next unless ($state->{'bye'});
13378        }
13379        push @lines, split_lines($cline);
13380        last if ($state->{'bye'});
13381    }
13382    # close stack at the end of pass texi
13383    #print STDERR "close stack at the end of pass texi\n";
13384    close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number);
13385    push @lines, split_lines($text);
13386    print STDERR "# end of pass texi\n" if $T2H_VERBOSE;
13387    return (\@lines, \@first_lines, \@lines_numbers);
13388}
13389
13390#+++###########################################################################
13391#                                                                             #
13392# Pass structure: parse document structure                                    #
13393#                                                                             #
13394#---###########################################################################
13395
13396sub initialise_state_structure($)
13397{
13398    my $state = shift;
13399    $state->{'structure'} = 1;      # for substitute_text and close_stack:
13400                                    # 1 if pass_structure/scan_structure is
13401                                    # to be used
13402    $state->{'menu'} = 0;           # number of opened menus
13403    $state->{'detailmenu'} = 0;     # number of opened detailed menus
13404    $state->{'sectionning_base'} = 0;         # current base sectionning level
13405    $state->{'table_stack'} = [ "no table" ]; # a stack of opened tables/lists
13406    # seems to be only debug
13407    if (exists($state->{'region_lines'}) and !defined($state->{'region_lines'}))
13408    {
13409        delete ($state->{'region_lines'});
13410        print STDERR "Bug: state->{'region_lines'} exists but undef.\n";
13411    }
13412}
13413# This is a virtual element for things appearing before @node and
13414# sectionning commands
13415my $element_before_anything;
13416
13417#
13418# initial counters. Global variables for pass_structure.
13419#
13420my $document_idx_num;
13421my $document_sec_num;
13422my $document_head_num;
13423my $document_anchor_num;
13424
13425# section to level hash not taking into account raise and lower sections
13426my %sec2level;
13427# initial state for the special regions.
13428my %region_initial_state;
13429my %region_lines;
13430
13431# This is a place for index entries, anchors and so on appearing in
13432# copying or documentdescription
13433my $no_element_associated_place;
13434
13435
13436my @nodes_list;             # nodes in document reading order
13437                            # each member is a reference on a hash
13438my @sections_list;          # sections in reading order
13439                            # each member is a reference on a hash
13440my @all_elements;           # sectionning elements (nodes and sections)
13441                            # in reading order. Each member is a reference
13442                            # on a hash which also appears in %nodes,
13443                            # @sections_list @nodes_list, @elements_list
13444my @elements_list;          # all the resulting elements in document order
13445my %sections;               # sections hash. The key is the section number
13446my %headings;               # headings hash. The key is the heading number
13447my $section_top;            # @top section
13448my $element_top;            # Top element
13449my $node_top;               # Top node
13450my $node_first;             # First node
13451my $element_index;          # element with first index
13452my $element_chapter_index;  # chapter with first index
13453my $element_first;          # first element
13454my $element_last;           # last element
13455my %special_commands;       # hash for the commands specially handled
13456                            # by the user
13457
13458# element for content and shortcontent if on a separate page
13459my %content_element;
13460
13461# common code for headings and sections
13462sub new_section_heading($$$)
13463{
13464    my $command = shift;
13465    my $name = shift;
13466    my $state = shift;
13467    $name = normalise_space($name);
13468    $name = '' if (!defined($name));
13469    # no increase if in @copying and the like. Also no increase if it is top
13470    # since top has number 0.
13471    my $docid;
13472    my $num;
13473
13474    my $section_ref = { 'texi' => $name,
13475       'level' => $sec2level{$command},
13476       'tag' => $command,
13477    };
13478    return $section_ref;
13479}
13480
13481sub scan_node_line($)
13482{
13483    my $node_line = shift;
13484    $node_line =~ s/^\@node\s+//;
13485    $node_line =~ s/\s*$//;
13486
13487    my @command_stack;
13488    my @results;
13489    my $node_arg = '';
13490    while (1)
13491    {
13492        if ($node_line =~ s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $node_line =~ s/^([^{}@,]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or $node_line =~ s/^([^{},@]*)\@([a-zA-Z][\w-]*)$//o)
13493        {
13494            $node_arg .= $1;
13495            my $macro = $2;
13496            $node_arg .= "\@$macro";
13497            $macro = $alias{$macro} if (exists($alias{$macro}));
13498            if ($node_line =~ s/^{//)
13499            {
13500                push @command_stack, $macro;
13501                $node_arg .= '{';
13502            }
13503
13504        }
13505        elsif ($node_line =~ s/^([^{},]*)([{}])//o)
13506        {
13507            $node_arg .= $1 . $2;
13508            my $brace = $2;
13509            if (@command_stack)
13510            {
13511                pop @command_stack;
13512            }
13513        }
13514        elsif ($node_line =~ s/^([^,]*)[,]//o)
13515        {
13516            $node_arg .= $1;
13517            if (@command_stack)
13518            {
13519                $node_arg .= ',';
13520            }
13521            else
13522            {
13523                push @results, normalise_node($node_arg);
13524                $node_arg = '';
13525            }
13526        }
13527        else
13528        {
13529            $node_arg .= $node_line;
13530            push @results, normalise_node($node_arg);
13531            return @results;
13532        }
13533    }
13534}
13535
13536sub pass_structure($$)
13537{
13538    my $texi_lines = shift;
13539    my $lines_numbers = shift;
13540
13541    my @doc_lines;              # whole document
13542    my @doc_numbers;            # whole document line numbers and file names
13543
13544    my $state = {};
13545                                # holds the informations about the context
13546                                # to pass it down to the functions
13547    initialise_state_structure($state);
13548    $state->{'element'} = $element_before_anything;
13549    $state->{'place'} = $element_before_anything->{'place'};
13550    my @stack;
13551    my $text;
13552    my $line_nr;
13553
13554    while (@$texi_lines or $state->{'in_deff_line'})
13555    {
13556        my $cline = shift @$texi_lines;
13557        my $chomped_line = $cline;
13558        if (@$texi_lines and !chomp($chomped_line))
13559        {
13560             $texi_lines->[0] = $cline . $texi_lines->[0];
13561             next;
13562        }
13563        if ($state->{'in_deff_line'})
13564        { # line stored in $state->{'in_deff_line'} was protected by @
13565          # and can be concatenated with the next line
13566            if (defined($cline))
13567            {
13568                $cline = $state->{'in_deff_line'} . $cline;
13569            }
13570            else
13571            {# end of line protected at the very end of the file
13572                $cline = $state->{'in_deff_line'};
13573            }
13574            delete $state->{'in_deff_line'};
13575        }
13576        $line_nr = shift (@$lines_numbers);
13577        #print STDERR "PASS_STRUCTURE: $cline";
13578        if (!$state->{'raw'} and !$state->{'verb'})
13579        {
13580            my $tag = '';
13581            if ($cline =~ /^\s*\@(\w+)\b/)
13582            {
13583                $tag = $1;
13584            }
13585
13586            #
13587            # analyze the tag
13588            #
13589            if ($tag and $tag eq 'node' or (defined($sec2level{$tag}) and ($tag !~ /heading/)) or $tag eq 'printindex' or ($tag eq 'insertcopying' and $Texi2HTML::Config::INLINE_INSERTCOPYING))
13590            {
13591                my @added_lines = ($cline);
13592                my @added_numbers = ($line_nr);
13593                if ($tag eq 'node' or defined($sec2level{$tag}))
13594                {# in pass structure node shouldn't appear in formats
13595                    close_stack_texi_structure(\$text, \@stack, $state, $line_nr);
13596                    if (exists($state->{'region_lines'}))
13597                    {
13598                        push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($text);
13599                        push @doc_lines, split_lines($text) if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}});
13600                        $state->{'region_lines'}->{'number'} = 0;
13601                        close_region($state);
13602                    }
13603                    else
13604                    {
13605                        push @doc_lines, split_lines($text);
13606                    }
13607                    $text = '';
13608                }
13609                if ($tag eq 'node')
13610                {
13611                    my $node_ref;
13612                    my $auto_directions;
13613                    my @node_res = scan_node_line($cline);
13614                    $auto_directions = 1 if (scalar(@node_res) == 1);
13615                    my ($node, $node_next, $node_prev, $node_up) = @node_res;
13616                    if (defined($node) and ($node ne ''))
13617                    {
13618                        if (exists($nodes{$node}) and defined($nodes{$node})
13619                             and $nodes{$node}->{'seen'})
13620                        {
13621                            echo_error ("Duplicate node found: $node", $line_nr);
13622                            next;
13623                        }
13624                        else
13625                        {
13626                            if (exists($nodes{$node}) and defined($nodes{$node}))
13627                            { # node appeared in a menu
13628                                $node_ref = $nodes{$node};
13629                            }
13630                            else
13631                            {
13632                                my $first;
13633                                $first = 1 if (!defined($node_ref));
13634                                $node_ref = {};
13635                                $node_first = $node_ref if ($first);
13636                                $nodes{$node} = $node_ref;
13637                            }
13638                            $node_ref->{'node'} = 1;
13639                            $node_ref->{'tag'} = 'node';
13640                            $node_ref->{'tag_level'} = 'node';
13641                            $node_ref->{'texi'} = $node;
13642                            $node_ref->{'seen'} = 1;
13643                            $node_ref->{'automatic_directions'} = $auto_directions;
13644                            $node_ref->{'place'} = [];
13645                            $node_ref->{'current_place'} = [];
13646                            merge_element_before_anything($node_ref);
13647                            $node_ref->{'index_names'} = [];
13648                            $state->{'place'} = $node_ref->{'current_place'};
13649                            $state->{'element'} = $node_ref;
13650                            $state->{'node_ref'} = $node_ref;
13651                            # makeinfo treats differently case variants of
13652                            # top in nodes and anchors and in refs commands and
13653                            # refs from nodes.
13654                            if ($node =~ /^top$/i)
13655                            {
13656                                if (!defined($node_top))
13657                                {
13658                                    $node_top = $node_ref;
13659                                    $node_top->{'texi'} = 'Top';
13660                                    delete $nodes{$node};
13661                                    $nodes{$node_top->{'texi'}} = $node_ref;
13662                                }
13663                                else
13664                                { # All the refs are going to point to the first Top
13665                                    echo_warn ("Top node already exists", $line_nr);
13666                                    #warn "$WARN Top node already exists\n";
13667                                }
13668                            }
13669                            unless (@nodes_list)
13670                            {
13671                                $node_ref->{'first'} = 1;
13672                            }
13673                            push (@nodes_list, $node_ref);
13674                            push @all_elements, $node_ref;
13675                        }
13676                    }
13677                    else
13678                    {
13679                        echo_error ("Node is undefined: $cline (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)", $line_nr);
13680                        next;
13681                    }
13682
13683                    if (defined($node_next) and ($node_next ne ''))
13684                    {
13685                        $node_ref->{'node_next'} = $node_next;
13686                    }
13687                    if (defined($node_prev) and ($node_prev ne ''))
13688                    {
13689                        $node_ref->{'node_prev'} = $node_prev;
13690                    }
13691                    if (defined($node_up) and ($node_up ne ''))
13692                    {
13693                        $node_ref->{'node_up'} = $node_up;
13694                    }
13695                }
13696                elsif (defined($sec2level{$tag}))
13697                { # section
13698                    if ($cline =~ /^\@$tag\s*(.*)$/)
13699                    {
13700                        my $name = $1;
13701                        my $section_ref = new_section_heading($tag, $name, $state);
13702                        $document_sec_num++ if($tag ne 'top');
13703
13704                        $section_ref->{'sec_num'} = $document_sec_num;
13705                        $section_ref->{'id'} = "SEC$document_sec_num";
13706                        $section_ref->{'seen'} = 1;
13707                        $section_ref->{'index_names'} = [];
13708                        $section_ref->{'current_place'} = [];
13709                        $section_ref->{'place'} = [];
13710                        $section_ref->{'section'} = 1;
13711
13712                        if ($tag eq 'top')
13713                        {
13714                            $section_ref->{'top'} = 1;
13715                            $section_ref->{'number'} = '';
13716                            $section_ref->{'id'} = "SEC_Top";
13717                            $section_ref->{'sec_num'} = 0;
13718                            $sections{0} = $section_ref;
13719                            $section_top = $section_ref;
13720                        }
13721                        else
13722                        {
13723                            $sections{$section_ref->{'sec_num'}} = $section_ref;
13724                        }
13725                        merge_element_before_anything($section_ref);
13726                        if ($state->{'node_ref'})
13727                        {
13728                            $section_ref->{'node_ref'} = $state->{'node_ref'};
13729                            push @{$state->{'node_ref'}->{'sections'}}, $section_ref;
13730                        }
13731                        if ($state->{'node_ref'} and !exists($state->{'node_ref'}->{'with_section'}))
13732                        {
13733                            my $node_ref = $state->{'node_ref'};
13734                            $section_ref->{'with_node'} = $node_ref;
13735                            $section_ref->{'titlefont'} = $node_ref->{'titlefont'};
13736                            $node_ref->{'with_section'} = $section_ref;
13737                            $node_ref->{'top'} = 1 if ($tag eq 'top');
13738                        }
13739                        if (! $name and $section_ref->{'level'})
13740                        {
13741                            echo_warn ("$tag without name", $line_nr);
13742                        }
13743                        push @sections_list, $section_ref;
13744                        push @all_elements, $section_ref;
13745                        $state->{'element'} = $section_ref;
13746                        $state->{'place'} = $section_ref->{'current_place'};
13747                        ################# debug
13748                        my $node_ref = "NO NODE";
13749                        my $node_texi ='';
13750                        if ($state->{'node_ref'})
13751                        {
13752                            $node_ref = $state->{'node_ref'};
13753                            $node_texi = $state->{'node_ref'}->{'texi'};
13754                        }
13755                        print STDERR "# pass_structure node($node_ref)$node_texi, tag \@$tag($section_ref->{'level'}) ref $section_ref, num,id $section_ref->{'sec_num'},$section_ref->{'id'}\n   $name\n"
13756                           if $T2H_DEBUG & $DEBUG_ELEMENTS;
13757                        ################# end debug
13758                    }
13759                }
13760                elsif ($cline =~ /^\@printindex\s+(\w+)/)
13761                {
13762                    unless (@all_elements)
13763                    {
13764                        echo_warn ("Printindex before document beginning: \@printindex $1", $line_nr);
13765                        next;
13766                    }
13767                    my $index_name = $1;
13768                    # $element_index is the first element with index
13769                    $element_index = $all_elements[-1] unless (defined($element_index));
13770                    # associate the index to the element
13771                    my $printindex = { 'element' => $all_elements[-1], 'name' => $index_name, 'command' => 'printindex' };
13772                    push @{$state->{'place'}}, $printindex;
13773                    push @{$Texi2HTML::THISDOC{'indices'}->{$index_name}}, $printindex;
13774                    push @{$Texi2HTML::THISDOC{'printindices'}}, $printindex;
13775                }
13776                elsif ($cline =~ /^\@insertcopying\s*/)
13777                {
13778                    @added_lines = @{$region_lines{'copying'}};
13779                    @added_numbers = ();
13780                    my $copying_line_nr = 0;
13781                    foreach my $line_added (@added_lines)
13782                    {
13783                       $copying_line_nr++;
13784                       push @added_numbers, { 'file_name' => '', 'macro' => 'copying', 'line_nr' => $copying_line_nr };
13785                    }
13786                    unshift (@$texi_lines, @added_lines);
13787                    unshift (@$lines_numbers, @added_numbers);
13788                    next;
13789                }
13790                if (exists($state->{'region_lines'}))
13791                {
13792                    push @{$region_lines{$state->{'region_lines'}->{'format'}}}, @added_lines;
13793                    if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}})
13794                    {
13795                        push @doc_lines, @added_lines;
13796                        push @doc_numbers, @added_numbers;
13797                    }
13798                }
13799                else
13800                {
13801                    push @doc_lines, @added_lines;
13802                    push @doc_numbers, @added_numbers;
13803                }
13804                next;
13805            }
13806        }
13807        if (scan_structure ($cline, \$text, \@stack, $state, $line_nr) and (!exists($state->{'region_lines'}) or $Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}))
13808        {
13809            push (@doc_numbers, $line_nr);
13810        }
13811        next if (scalar(@stack) or $state->{'in_deff_line'});
13812        $cline = $text;
13813        $text = '';
13814        next if (!defined($cline));
13815        if ($state->{'region_lines'})
13816        {
13817            # the first line is like @copying, it is not put in the region
13818            # lines
13819            push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($cline) unless ($state->{'region_lines'}->{'first_line'});
13820            delete $state->{'region_lines'}->{'first_line'};
13821            push @doc_lines, split_lines($cline) if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}});
13822        }
13823        else
13824        {
13825            push @doc_lines, split_lines($cline);
13826        }
13827    }
13828    if (@stack)
13829    {# close stack at the end of pass structure
13830        close_stack_texi_structure(\$text, \@stack, $state, $line_nr);
13831        if ($text)
13832        {
13833            if (exists($state->{'region_lines'}))
13834            {
13835                push @{$region_lines{$state->{'region_lines'}->{'format'}}},
13836                   split_lines($text);
13837                push @doc_lines, split_lines($text) if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}});
13838            }
13839            else
13840            {
13841                push @doc_lines, split_lines($text);
13842            }
13843        }
13844    }
13845    echo_warn ("At end of document, $state->{'region_lines'}->{'number'} $state->{'region_lines'}->{'format'} not closed") if (exists($state->{'region_lines'}));
13846    print STDERR "# end of pass structure\n" if $T2H_VERBOSE;
13847    # To remove once they are handled
13848    #print STDERR "No node nor section, texi2html won't be able to place things rightly\n" if ($element_before_anything->{'place'} and @{$element_before_anything->{'place'}});
13849    return (\@doc_lines, \@doc_numbers);
13850}
13851
13852# split line at end of line and put each resulting line in an array
13853# FIXME there must be a more perlish way to do it... Not a big deal
13854# as long as it work
13855sub split_lines($)
13856{
13857   my $line = shift;
13858   my @result = ();
13859   return @result if (!defined($line));
13860   my $i = 0;
13861   while ($line ne '')
13862   {
13863       $result[$i] = '';
13864       $line =~ s/^(.*)//;
13865       $result[$i] .= $1;
13866       $result[$i] .= "\n" if ($line =~ s/^\n//);
13867       #print STDERR "$i: $result[$i]";
13868       $i++;
13869   }
13870   return @result;
13871}
13872
13873# handle @documentlanguage
13874sub do_documentlanguage($$$$)
13875{
13876    my $macro = shift;
13877    my $line = shift;
13878    my $silent = shift;
13879    my $line_nr = shift;
13880    my $return_value = 0;
13881    if ($line =~ /\s+(\w+)/)
13882    {
13883        my $lang = $1;
13884        if (!$Texi2HTML::GLOBAL{'current_lang'} && $lang)
13885        {
13886            $return_value = set_document_language($lang, 0, $silent, $line_nr);
13887            # warning, this is not the language of the document but the one that
13888            # appear in the texinfo. It could have been different
13889            # if $Texi2HTML::GLOBAL{'current_lang'} was set and not
13890            # taken into account in the if
13891            $Texi2HTML::THISDOC{$macro} = $lang;
13892        }
13893    }
13894    return $return_value;
13895}
13896
13897# actions that should be done in more than one pass. In fact most are not
13898# to be done in pass_texi. The $pass argument is the number of the pass,
13899# 0 for pass_texi, 1 for pass_structure, 2 for pass_text
13900sub common_misc_commands($$$$)
13901{
13902    my $macro = shift;
13903    my $line = shift;
13904    my $pass = shift;
13905    my $line_nr = shift;
13906
13907    # track variables
13908    if ($macro eq 'set')
13909    {
13910        if ($line =~ /^(\s+)($VARRE)(\s+)(.*)$/)
13911        {
13912             $value{$2} = $4;
13913        }
13914        else
13915        {
13916             echo_warn ("Missing argument for \@$macro", $line_nr) if (!$pass);
13917        }
13918    }
13919    elsif ($macro eq 'clear')
13920    {
13921        if ($line =~ /^(\s+)($VARRE)/)
13922        {
13923            delete $value{$2};
13924        }
13925        else
13926        {
13927            echo_warn ("Missing argument for \@$macro", $line_nr) if (!$pass);
13928        }
13929    }
13930    elsif ($macro eq 'clickstyle')
13931    {
13932        if ($line =~ /^\s+@([^\s\{\}\@]+)/)
13933        {
13934            $Texi2HTML::THISDOC{$macro} = $1;
13935        }
13936        else
13937        {
13938            echo_error ("\@$macro should only accept a macro as argument", $line_nr) if ($pass == 1);
13939        }
13940    }
13941    if ($pass)
13942    { # these commands are only taken into account here in pass_structure 1
13943      # and pass_text 2
13944        if ($macro eq 'setfilename')
13945        {
13946            my $filename = $line;
13947            $filename =~ s/^\s*//;
13948            $filename =~ s/\s*$//;
13949            if ($filename ne '')
13950            {
13951                $filename = substitute_line($filename, {'code_style' => 1, 'remove_texi' => 1});
13952                #$filename = substitute_line($filename, {'code_style' => 1});
13953                $Texi2HTML::THISDOC{$macro} = $filename;
13954                $value{"_$macro"} = $filename if ($pass == 1);
13955            }
13956        }
13957        elsif ($macro eq 'paragraphindent')
13958        {
13959            if ($line =~ /\s+([0-9]+)/)
13960            {
13961                $Texi2HTML::THISDOC{$macro} = $1;
13962            }
13963            elsif (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(asis)[^\w\-]/))
13964            {
13965                $Texi2HTML::THISDOC{$macro} = $1;
13966            }
13967            else
13968            {
13969                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
13970            }
13971        }
13972        elsif ($macro eq 'firstparagraphindent')
13973        {
13974            if (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(insert)[^\w\-]/))
13975            {
13976                $Texi2HTML::THISDOC{$macro} = $1;
13977            }
13978            else
13979            {
13980                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
13981            }
13982        }
13983        elsif ($macro eq 'exampleindent')
13984        {
13985            if ($line =~ /^\s+([0-9]+)/)
13986            {
13987                $Texi2HTML::THISDOC{$macro} = $1;
13988            }
13989            elsif ($line =~ /^\s+(asis)[^\w\-]/)
13990            {
13991                $Texi2HTML::THISDOC{$macro} = $1;
13992            }
13993            else
13994            {
13995                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
13996            }
13997        }
13998        elsif ($macro eq 'frenchspacing')
13999        {
14000            if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/))
14001            {
14002                $Texi2HTML::THISDOC{$macro} = $1;
14003            }
14004            else
14005            {
14006                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
14007            }
14008        }
14009        elsif (grep {$macro eq $_} ('everyheading', 'everyfooting',
14010              'evenheading', 'evenfooting', 'oddheading', 'oddfooting'))
14011        { # FIXME have a _texi and without texi, and without texi,
14012          # and expand rightly @this*? And use @| to separate, and give
14013          # an array for user consumption? This should be done for each new
14014          # chapter, section, and page. What is a page is not necessarily
14015          # well defined in html, however...
14016          # @thisfile is the @include file. Shoule be in $line_nr.
14017            my $arg = $line;
14018            $arg =~ s/^\s+//;
14019            $Texi2HTML::THISDOC{$macro} = $arg;
14020        }
14021        elsif ($macro eq 'allowcodebreaks')
14022        {
14023            if (($line =~ /^\s+(true)[^\w\-]/) or ($line =~ /^\s+(false)[^\w\-]/))
14024            {
14025                $Texi2HTML::THISDOC{$macro} = $1;
14026            }
14027            else
14028            {
14029                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
14030            }
14031        }
14032        elsif ($macro eq 'headings')
14033        {
14034            my $valid_arg = 0;
14035            foreach my $possible_arg (('off','on','single','double',
14036                          'singleafter','doubleafter'))
14037            {
14038                if ($line =~ /^\s+($possible_arg)[^\w\-]/)
14039                {
14040                    $valid_arg = 1;
14041                    $Texi2HTML::THISDOC{$macro} = $possible_arg;
14042                    last;
14043                }
14044            }
14045            unless ($valid_arg)
14046            {
14047                echo_error ("Bad \@$macro", $line_nr) if ($pass == 1);
14048            }
14049        }
14050        elsif ($macro eq 'documentlanguage')
14051        {
14052            if (do_documentlanguage($macro, $line, $pass -1, $line_nr))
14053            {
14054                &$Texi2HTML::Config::translate_names();
14055                set_special_names();
14056            }
14057        }
14058    }
14059}
14060
14061sub misc_command_texi($$$$)
14062{
14063   my $line = shift;
14064   my $macro = shift;
14065   my $state = shift;
14066   my $line_nr = shift;
14067   my $text;
14068   my $args;
14069
14070   if (!$state->{'ignored'} and !$state->{'arg_expansion'})
14071   {
14072      if ($macro eq 'documentencoding')
14073      {
14074         #my $encoding = '';
14075         if ($line =~ /(\s+)([0-9\w\-]+)/)
14076         {
14077            my $encoding = $2;
14078            #$Texi2HTML::Config::DOCUMENT_ENCODING = $encoding;
14079            $Texi2HTML::THISDOC{'documentencoding'} = $encoding;
14080            $Texi2HTML::THISDOC{'DOCUMENT_ENCODING'} = $Texi2HTML::THISDOC{'documentencoding'} unless (defined($Texi2HTML::Config::DOCUMENT_ENCODING));
14081            my $from_encoding;
14082            if (!defined($Texi2HTML::Config::IN_ENCODING))
14083            {
14084               $from_encoding = encoding_alias($encoding);
14085               $Texi2HTML::THISDOC{'IN_ENCODING'} = $from_encoding
14086                 if (defined($from_encoding));
14087            }
14088            #$Texi2HTML::Config::IN_ENCODING = $from_encoding if
14089            #   defined($from_encoding);
14090            if (defined($from_encoding) and $Texi2HTML::Config::USE_UNICODE)
14091            {
14092               foreach my $file (@fhs)
14093               {
14094                  binmode($file->{'fh'}, ":encoding($from_encoding)");
14095               }
14096            }
14097         }
14098      }
14099      else
14100      {
14101          if ($macro eq 'setfilename' and $Texi2HTML::Config::USE_SETFILENAME)
14102          {
14103             my $filename = $line;
14104             $filename =~ s/^\s*//;
14105             $filename =~ s/\s*$//;
14106             #$filename = substitute_line($filename, {'code_style' => 1});
14107             $filename = substitute_line($filename, {'code_style' => 1, 'remove_texi' => 1});
14108             # remove extension
14109             $filename =~ s/\.[^\.]*$//;
14110             init_with_file_name ($filename) if ($filename ne '');
14111          }
14112          # in reality, do only set, clear and clickstyle.
14113          # though we should never go there for clickstyle...
14114          common_misc_commands($macro, $line, 0, $line_nr);
14115      }
14116   }
14117
14118   ($text, $line, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $macro);
14119   return ($text, $line);
14120}
14121
14122# initial kdb styles
14123my $kept_kdb_style;
14124my $kept_kdb_pre_style;
14125# novalidate seen?
14126my $novalidate;
14127
14128# handle misc commands and misc command args
14129sub misc_command_structure($$$$)
14130{
14131    my $line = shift;
14132    my $macro = shift;
14133    my $state = shift;
14134    my $line_nr = shift;
14135    my $text;
14136    my $args;
14137
14138    if ($macro eq 'lowersections')
14139    {
14140        my ($sec, $level);
14141        while (($sec, $level) = each %sec2level)
14142        {
14143            $sec2level{$sec} = $level + 1;
14144        }
14145        $state->{'sectionning_base'}--;
14146    }
14147    elsif ($macro eq 'raisesections')
14148    {
14149        my ($sec, $level);
14150        while (($sec, $level) = each %sec2level)
14151        {
14152            $sec2level{$sec} = $level - 1;
14153        }
14154        $state->{'sectionning_base'}++;
14155    }
14156    elsif (($macro eq 'contents') or ($macro eq 'summarycontents') or ($macro eq 'shortcontents'))
14157    {
14158        if ($macro eq 'contents')
14159        {
14160            $Texi2HTML::THISDOC{'DO_CONTENTS'} = 1 unless (defined($Texi2HTML::Config::DO_CONTENTS));
14161            $Texi2HTML::THISDOC{$macro} = 1;
14162        }
14163        else
14164        {
14165            $macro = 'shortcontents';
14166            $Texi2HTML::THISDOC{'DO_SCONTENTS'} = 1 unless (defined($Texi2HTML::Config::DO_SCONTENTS));
14167            $Texi2HTML::THISDOC{$macro} = 1;
14168        }
14169        push @{$state->{'place'}}, $content_element{$macro};
14170    }
14171    elsif ($macro eq 'novalidate')
14172    {
14173        $novalidate = 1;
14174        $Texi2HTML::THISDOC{$macro} = 1;
14175    }
14176    elsif (grep {$_ eq $macro} ('settitle','shorttitlepage','title')
14177             and ($line =~ /^\s+(.*)$/))
14178    {
14179        my $arg = $1;
14180        chomp($arg);
14181        $value{"_$macro"} = $arg;
14182        # backward compatibility
14183        if ($macro eq 'title')
14184        {
14185            $Texi2HTML::THISDOC{"${macro}s_texi"} = [ $arg ];
14186            $Texi2HTML::THISDOC{"${macro}s"} = [ $arg ];
14187        }
14188    }
14189    elsif (grep {$_ eq $macro} ('author','subtitle')
14190             and ($line =~ /^\s+(.*)$/))
14191    {
14192        my $arg = $1;
14193        $value{"_$macro"} .= $arg."\n";
14194        chomp($arg);
14195        push @{$Texi2HTML::THISDOC{"${macro}s_texi"}}, $arg;
14196        push @{$Texi2HTML::THISDOC{"${macro}s"}}, $arg;
14197    }
14198    elsif ($macro eq 'synindex' || $macro eq 'syncodeindex')
14199    {
14200        if ($line =~ /^\s+(\w+)\s+(\w+)/)
14201        {
14202            my $index_from = $1;
14203            my $index_to = $2;
14204            echo_error ("unknown from index name $index_from in \@$macro", $line_nr)
14205                unless $index_names{$index_from};
14206            echo_error ("unknown to index name $index_to in \@$macro", $line_nr)
14207                unless $index_names{$index_to};
14208            if ($index_names{$index_from} and $index_names{$index_to})
14209            {
14210                if ($macro eq 'syncodeindex')
14211                {
14212                    $index_names{$index_to}->{'associated_indices_code'}->{$index_from} = 1;
14213                }
14214                else
14215                {
14216                    $index_names{$index_to}->{'associated_indices'}->{$index_from} = 1;
14217                }
14218                push @{$Texi2HTML::THISDOC{$macro}}, [$index_from,$index_to];
14219            }
14220        }
14221        else
14222        {
14223            echo_error ("Bad $macro line: $line", $line_nr);
14224        }
14225    }
14226    elsif ($macro eq 'defindex' || $macro eq 'defcodeindex')
14227    {
14228        if ($line =~ /^\s+(\w+)\s*$/)
14229        {
14230            my $name = $1;
14231            if ($forbidden_index_name{$name})
14232            {
14233                echo_error("Reserved index name $name", $line_nr);
14234            }
14235            else
14236            {
14237                @{$index_names{$name}->{'prefix'}} = ($name);
14238                $index_names{$name}->{'code'} = 1 if $macro eq 'defcodeindex';
14239                $index_prefix_to_name{$name} = $name;
14240                push @{$Texi2HTML::THISDOC{$macro}}, $name;
14241            }
14242        }
14243        else
14244        {# makeinfo don't warn and even accepts index with empty name
14245         # and index with numbers only. I reported it on the mailing list
14246         # this should be fixed in future makeinfo versions.
14247            echo_error ("Bad $macro line: $line", $line_nr);
14248        }
14249    }
14250    elsif ($macro eq 'kbdinputstyle')
14251    {# makeinfo ignores that with --html. I reported it and it should be
14252     # fixed in future makeinfo releases
14253
14254     # FIXME it should be dynamically defined in pass 2
14255        if ($line =~ /\s+([a-z]+)/)
14256        {
14257            if ($1 eq 'code')
14258            {
14259                $::style_map_ref->{'kbd'} = $::style_map_ref->{'code'};
14260                $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'};
14261                $Texi2HTML::THISDOC{$macro} = $1;
14262            }
14263            elsif ($1 eq 'example')
14264            {
14265                $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'};
14266                $Texi2HTML::THISDOC{$macro} = $1;
14267            }
14268            elsif ($1 eq 'distinct')
14269            {
14270                $Texi2HTML::THISDOC{$macro} = $1;
14271                $::style_map_ref->{'kbd'} = $kept_kdb_style;
14272                $::style_map_pre_ref->{'kbd'} = $kept_kdb_pre_style;
14273            }
14274            else
14275            {
14276                echo_error ("Unknown argument for \@$macro: $1", $line_nr);
14277            }
14278        }
14279        else
14280        {
14281            echo_error ("Bad \@$macro", $line_nr);
14282        }
14283    }
14284    elsif (grep {$_ eq $macro} ('everyheadingmarks','everyfootingmarks',
14285        'evenheadingmarks','oddheadingmarks','evenfootingmarks','oddfootingmarks'))
14286    {
14287        if (($line =~ /^\s+(top)[^\w\-]/) or ($line =~ /^\s+(bottom)[^\w\-]/))
14288        {
14289            $Texi2HTML::THISDOC{$macro} = $1;
14290        }
14291        else
14292        {
14293            echo_error ("Bad \@$macro", $line_nr);
14294        }
14295    }
14296    elsif ($macro eq 'fonttextsize')
14297    {
14298        if (($line =~ /^\s+(10)[^\w\-]/) or ($line =~ /^\s+(11)[^\w\-]/))
14299        {
14300            $Texi2HTML::THISDOC{$macro} = $1;
14301        }
14302        else
14303        {
14304            echo_error ("Bad \@$macro", $line_nr);
14305        }
14306    }
14307    elsif ($macro eq 'pagesizes')
14308    {
14309        if ($line =~ /^\s+(.*)\s*$/)
14310        {
14311            $Texi2HTML::THISDOC{$macro} = $1;
14312        }
14313    }
14314    elsif ($macro eq 'footnotestyle')
14315    {
14316        if (($line =~ /^\s+(end)[^\w\-]/) or ($line =~ /^\s+(separate)[^\w\-]/))
14317        {
14318            $Texi2HTML::THISDOC{$macro} = $1;
14319        }
14320        else
14321        {
14322            echo_error ("Bad \@$macro", $line_nr);
14323        }
14324    }
14325    elsif ($macro eq 'setchapternewpage')
14326    {
14327        if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/)
14328                or ($line =~ /^\s+(odd)[^\w\-]/))
14329        {
14330            $Texi2HTML::THISDOC{$macro} = $1;
14331        }
14332        else
14333        {
14334            echo_error ("Bad \@$macro", $line_nr);
14335        }
14336    }
14337    elsif ($macro eq 'setcontentsaftertitlepage' or $macro eq 'setshortcontentsaftertitlepage')
14338    {
14339        $Texi2HTML::THISDOC{$macro} = 1;
14340        my $tag = 'contents';
14341        $tag = 'shortcontents' if ($macro ne 'setcontentsaftertitlepage');
14342        $content_element{$tag}->{'aftertitlepage'} = 1;
14343    }
14344    elsif ($macro eq 'need')
14345    { # only a warning
14346        unless (($line =~ /^\s+([0-9]+(\.[0-9]*)?)[^\w\-]/) or
14347                 ($line =~ /^\s+(\.[0-9]+)[^\w\-]/))
14348        {
14349            echo_warn ("Bad \@$macro", $line_nr);
14350        }
14351    }
14352    else
14353    {
14354        common_misc_commands($macro, $line, 1, $line_nr);
14355    }
14356
14357    ($text, $line, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $macro);
14358    return ($text, $line);
14359}
14360
14361sub set_special_names()
14362{
14363    $Texi2HTML::NAME{'About'} = &$I('About This Document');
14364    $Texi2HTML::NAME{'Contents'} = &$I('Table of Contents');
14365    $Texi2HTML::NAME{'Overview'} = &$I('Short Table of Contents');
14366    $Texi2HTML::NAME{'Footnotes'} = &$I('Footnotes');
14367    $Texi2HTML::NO_TEXI{'About'} = &$I('About This Document', {}, {'remove_texi' => 1} );
14368    $Texi2HTML::NO_TEXI{'Contents'} = &$I('Table of Contents', {}, {'remove_texi' => 1} );
14369    $Texi2HTML::NO_TEXI{'Overview'} = &$I('Short Table of Contents', {}, {'remove_texi' => 1} );
14370    $Texi2HTML::NO_TEXI{'Footnotes'} = &$I('Footnotes', {}, {'remove_texi' => 1} );
14371    $Texi2HTML::SIMPLE_TEXT{'About'} = &$I('About This Document', {}, {'simple_format' => 1});
14372    $Texi2HTML::SIMPLE_TEXT{'Contents'} = &$I('Table of Contents',{},  {'simple_format' => 1});
14373    $Texi2HTML::SIMPLE_TEXT{'Overview'} = &$I('Short Table of Contents', {}, {'simple_format' => 1});
14374    $Texi2HTML::SIMPLE_TEXT{'Footnotes'} = &$I('Footnotes', {},{'simple_format' => 1});
14375}
14376
14377# return the line after removing things according to misc_command map.
14378# if the skipped macro has an effect it is done here
14379# this is used during pass_text
14380sub misc_command_text($$$$$$)
14381{
14382    my $line = shift;
14383    my $macro = shift;
14384    my $stack = shift;
14385    my $state = shift;
14386    my $text = shift;
14387    my $line_nr = shift;
14388    my ($skipped, $remaining, $args);
14389
14390    # The strange condition associated with 'keep_texi' is
14391    # there because for an argument appearing on an @itemize
14392    # line (we're in 'check_item'), meant to be prepended to an
14393    # @item we don't want to keep @c or @comment as otherwise it
14394    # eats the @item line. Other commands could do that too but
14395    # then the user deserves what he gets.
14396    if ($state->{'keep_texi'} and
14397        (!$state->{'check_item'} or ($macro ne 'c' and $macro ne 'comment')))
14398    {
14399        ($remaining, $skipped, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $macro);
14400        add_prev($text, $stack, "\@$macro". $skipped);
14401        return $remaining;
14402    }
14403
14404    # if it is true the command args are kept so the user can modify how
14405    # they are skipped and handle them as unknown @-commands
14406    my $keep = $Texi2HTML::Config::misc_command{$macro}->{'keep'};
14407
14408    if ($macro eq 'sp')
14409    {
14410        my $sp_number;
14411        if ($line =~ /^\s+(\d+)\s/)
14412        {
14413            $sp_number = $1;
14414        }
14415        elsif ($line =~ /(\s*)$/)
14416        {
14417            $sp_number = '';
14418        }
14419        else
14420        {
14421            echo_error ("\@$macro needs a numeric arg or no arg", $line_nr);
14422        }
14423        $sp_number = 1 if ($sp_number eq '');
14424        if (!$state->{'remove_texi'})
14425        {
14426            add_prev($text, $stack, &$Texi2HTML::Config::sp($sp_number, $state->{'preformatted'}));
14427        }
14428    }
14429    elsif($macro eq 'verbatiminclude' and !$keep)
14430    {
14431        if ($line =~ /\s+(.+)/)
14432        {
14433            my $arg = $1;
14434            my $file = locate_include_file(substitute_line($arg, {'code_style' => 1}));
14435            if (defined($file))
14436            {
14437                if (!open(VERBINCLUDE, $file))
14438                {
14439                    echo_warn ("Can't read file $file: $!",$line_nr);
14440                }
14441                else
14442                {
14443                    my $verb_text = '';
14444                    while (my $line = <VERBINCLUDE>)
14445                    {
14446                        $verb_text .= $line;
14447                    }
14448
14449                    if ($state->{'remove_texi'})
14450                    {
14451                        add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi('verbatim', $verb_text));
14452                    }
14453                    else
14454                    {
14455                        add_prev($text, $stack, &$Texi2HTML::Config::raw('verbatim', $verb_text));
14456                    }
14457                    close VERBINCLUDE;
14458                }
14459            }
14460            else
14461            {
14462                echo_error ("Can't find $arg, skipping", $line_nr);
14463            }
14464        }
14465        else
14466        {
14467            echo_error ("Bad \@$macro line: $line", $line_nr);
14468        }
14469    }
14470    elsif ($macro eq 'indent' or $macro eq 'noindent')
14471    {
14472        $state->{'paragraph_indent'} = $macro;
14473    }
14474    else
14475    {
14476        common_misc_commands($macro, $line, 2, $line_nr);
14477    }
14478
14479    ($remaining, $skipped, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $macro);
14480#print STDERR "ZZZZZZZZZZZ r $remaining ZZ a @$args ZZZZ s `$skipped'\n" if ($keep);
14481    return ($skipped.$remaining) if ($keep);
14482    return $remaining if ($remaining ne '');
14483    return undef;
14484}
14485
14486# merge the things appearing before the first @node or sectionning command
14487# (held by element_before_anything) with the current element
14488# do that only once.
14489sub merge_element_before_anything($)
14490{
14491    my $element = shift;
14492    if (exists($element_before_anything->{'place'}))
14493    {
14494        $element->{'current_place'} = $element_before_anything->{'place'};
14495        delete $element_before_anything->{'place'};
14496        foreach my $placed_thing (@{$element->{'current_place'}})
14497        {
14498            $placed_thing->{'element'} = $element if (exists($placed_thing->{'element'}));
14499        }
14500    }
14501    # this is certainly redundant with the above condition, but cleaner
14502    # that way
14503    if (exists($element_before_anything->{'titlefont'}))
14504    {
14505        $element->{'titlefont'} = $element_before_anything->{'titlefont'};
14506        delete $element_before_anything->{'titlefont'};
14507    }
14508}
14509
14510# find menu_prev, menu_up... for a node in menu
14511sub menu_entry_texi($$$)
14512{
14513    my $node = shift;
14514    my $state = shift;
14515    my $line_nr = shift;
14516    my $node_menu_ref = {};
14517    if (exists($nodes{$node}))
14518    {
14519        $node_menu_ref = $nodes{$node};
14520    }
14521    else
14522    {
14523        $nodes{$node} = $node_menu_ref;
14524        $node_menu_ref->{'texi'} = $node;
14525        $node_menu_ref->{'external_node'} = 1 if ($node =~ /^\(.+\)/);
14526    }
14527    return if ($state->{'detailmenu'});
14528    if ($state->{'node_ref'})
14529    {
14530        $node_menu_ref->{'menu_up'} = $state->{'node_ref'};
14531        $node_menu_ref->{'menu_up_hash'}->{$state->{'node_ref'}->{'texi'}} = 1;
14532    }
14533    else
14534    {
14535        echo_warn ("menu entry without previous node: $node", $line_nr) unless ($node =~ /\(.+\)/);
14536    }
14537    if ($state->{'prev_menu_node'})
14538    {
14539        $node_menu_ref->{'menu_prev'} = $state->{'prev_menu_node'};
14540        $state->{'prev_menu_node'}->{'menu_next'} = $node_menu_ref;
14541    }
14542    elsif ($state->{'node_ref'} and !$state->{'node_ref'}->{'menu_child'})
14543    {
14544        $state->{'node_ref'}->{'menu_child'} = $node_menu_ref;
14545    }
14546    $state->{'prev_menu_node'} = $node_menu_ref;
14547}
14548
14549sub prepare_indices()
14550{
14551  foreach my $index_name (keys(%{$Texi2HTML::THISDOC{'indices'}}))
14552  {
14553    #my ($pages, $entries) = get_index($index_name, undef, 1);
14554    #my $entries = get_index($index_name, undef, 1);
14555    my $entries = get_index($index_name);
14556    foreach my $printindex (@{$Texi2HTML::THISDOC{'indices'}->{$index_name}})
14557    {
14558      $printindex->{'entries'} = $entries;
14559    }
14560  }
14561  Texi2HTML::Config::t2h_default_init_split_indices();
14562}
14563
14564my @index_labels;                  # array corresponding with @?index commands
14565                                   # constructed during pass_structure, used to
14566                                   # put labels in pass_text
14567
14568# This function is used to construct link names from node names as
14569# specified for texinfo
14570sub cross_manual_links()
14571{
14572    print STDERR "# Doing ".scalar(keys(%nodes))." cross manual links ".
14573      scalar(@index_labels). "index entries\n"
14574       if ($T2H_DEBUG);
14575    my $normal_text_kept = $Texi2HTML::Config::normal_text;
14576    $::simple_map_texi_ref = \%cross_ref_simple_map_texi;
14577    $::style_map_texi_ref = \%cross_ref_style_map_texi;
14578    $::texi_map_ref = \%cross_ref_texi_map;
14579    $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text;
14580
14581    foreach my $key (keys(%nodes))
14582    {
14583        my $node = $nodes{$key};
14584        #print STDERR "CROSS_MANUAL:$key,$node\n";
14585        if (!defined($node->{'texi'}))
14586        {
14587            ###################### debug section
14588            foreach my $key (keys(%$node))
14589            {
14590                #print STDERR "$key:$node->{$key}!!!\n";
14591            }
14592            ###################### end debug section
14593        }
14594        else
14595        {
14596            $node->{'cross_manual_target'} = remove_texi($node->{'texi'});
14597            if ($Texi2HTML::Config::USE_UNICODE)
14598            {
14599                $node->{'cross_manual_target'} = Unicode::Normalize::NFC($node->{'cross_manual_target'});
14600                if ($Texi2HTML::Config::TRANSLITERATE_NODE and $Texi2HTML::Config::USE_UNIDECODE)
14601                {
14602                     $node->{'cross_manual_file'} =
14603                       unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_target'}));
14604                }
14605                $node->{'cross_manual_target'} =
14606                    unicode_to_protected($node->{'cross_manual_target'});
14607            }
14608#print STDERR "CROSS_MANUAL_TARGET $node->{'cross_manual_target'}\n";
14609            unless ($node->{'external_node'})
14610            {
14611                if (exists($cross_reference_nodes{$node->{'cross_manual_target'}}))
14612                {
14613                    my $other_node_array = $cross_reference_nodes{$node->{'cross_manual_target'}};
14614                    my $node_seen;
14615                    foreach my $other_node (@{$other_node_array})
14616                    { # find the first node seen for the error message
14617                        $node_seen = $other_node;
14618                        last if ($nodes{$other_node}->{'seen'})
14619                    }
14620                    echo_error("Node equivalent with `$node->{'texi'}' already used `$node_seen'");
14621                    push @{$other_node_array}, $node->{'texi'};
14622                }
14623                else
14624                {
14625                    push @{$cross_reference_nodes{$node->{'cross_manual_target'}}}, $node->{'texi'};
14626                }
14627            }
14628        }
14629    }
14630
14631
14632    if ($Texi2HTML::Config::TRANSLITERATE_NODE and
14633         (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
14634    {
14635        $::style_map_texi_ref = \%cross_transliterate_style_map_texi;
14636        $::texi_map_ref = \%cross_transliterate_texi_map;
14637        $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text_transliterate if (!$Texi2HTML::Config::USE_UNICODE);
14638
14639        foreach my $key (keys(%nodes))
14640        {
14641            my $node = $nodes{$key};
14642            if (defined($node->{'texi'}))
14643            {
14644                 $node->{'cross_manual_file'} = remove_texi($node->{'texi'});
14645                 $node->{'cross_manual_file'} = unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_file'})) if ($Texi2HTML::Config::USE_UNICODE);
14646            }
14647        }
14648
14649        foreach my $entry (@index_labels, values(%sections), values(%headings))
14650        {
14651            $entry->{'cross'} = remove_texi($entry->{'texi'});
14652            $entry->{'cross'} = unicode_to_protected(unicode_to_transliterate($entry->{'cross'})) if ($Texi2HTML::Config::USE_UNICODE);
14653        }
14654    }
14655    else
14656    {
14657        foreach my $entry (@index_labels, values(%sections), values(%headings))
14658        {
14659            $entry->{'cross'} = remove_texi($entry->{'texi'});
14660            if ($Texi2HTML::Config::USE_UNICODE)
14661            {
14662                $entry->{'cross'} = Unicode::Normalize::NFC($entry->{'cross'});
14663                if ($Texi2HTML::Config::TRANSLITERATE_NODE and $Texi2HTML::Config::USE_UNIDECODE) # USE_UNIDECODE is redundant
14664                {
14665                     $entry->{'cross'} =
14666                       unicode_to_protected(unicode_to_transliterate($entry->{'cross'}));
14667                }
14668                else
14669                {
14670                     $entry->{'cross'} =
14671                        unicode_to_protected($entry->{'cross'});
14672                }
14673            }
14674        }
14675    }
14676
14677    $Texi2HTML::Config::normal_text = $normal_text_kept;
14678    $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
14679    $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
14680    $::texi_map_ref = \%Texi2HTML::Config::texi_map;
14681}
14682
14683# This function is used to construct a link name from a node name as
14684# specified for texinfo
14685sub cross_manual_line($;$)
14686{
14687    my $text = shift;
14688    my $transliterate = shift;
14689#print STDERR "cross_manual_line $text\n";
14690#print STDERR "remove_texi text ". remove_texi($text)."\n\n\n";
14691    $::simple_map_texi_ref = \%cross_ref_simple_map_texi;
14692    $::style_map_texi_ref = \%cross_ref_style_map_texi;
14693    $::texi_map_ref = \%cross_ref_texi_map;
14694    my $normal_text_kept = $Texi2HTML::Config::normal_text;
14695    $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text;
14696
14697    my ($cross_ref_target, $cross_ref_file);
14698    if ($Texi2HTML::Config::USE_UNICODE)
14699    {
14700         $cross_ref_target = Unicode::Normalize::NFC(remove_texi($text));
14701         if ($transliterate and $Texi2HTML::Config::USE_UNIDECODE)
14702         {
14703             $cross_ref_file =
14704                unicode_to_protected(unicode_to_transliterate($cross_ref_target));
14705         }
14706         $cross_ref_target = unicode_to_protected($cross_ref_target);
14707    }
14708    else
14709    {
14710         $cross_ref_target = remove_texi($text);
14711    }
14712
14713    if ($transliterate and
14714         (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
14715    {
14716         $::style_map_texi_ref = \%cross_transliterate_style_map_texi;
14717         $::texi_map_ref = \%cross_transliterate_texi_map;
14718         $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text_transliterate if (!$Texi2HTML::Config::USE_UNICODE);
14719         $cross_ref_file = remove_texi($text);
14720         $cross_ref_file = unicode_to_protected(unicode_to_transliterate($cross_ref_file))
14721               if ($Texi2HTML::Config::USE_UNICODE);
14722    }
14723
14724    $Texi2HTML::Config::normal_text = $normal_text_kept;
14725    $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
14726    $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
14727    $::texi_map_ref = \%Texi2HTML::Config::texi_map;
14728#print STDERR "\n\ncross_ref $cross_ref\n";
14729    unless ($transliterate)
14730    {
14731        return $cross_ref_target;
14732    }
14733#    print STDERR "$text|$cross_ref_target|$cross_ref_file\n";
14734    return ($cross_ref_target, $cross_ref_file);
14735}
14736
14737sub equivalent_nodes($)
14738{
14739    my $name = shift;
14740#print STDERR "equivalent_nodes $name\n";
14741    my $node = normalise_node($name);
14742    $name = cross_manual_line($node);
14743    my @equivalent_nodes = ();
14744    if (exists($cross_reference_nodes{$name}))
14745    {
14746        @equivalent_nodes = grep {$_ ne $node} @{$cross_reference_nodes{$name}};
14747    }
14748    return @equivalent_nodes;
14749}
14750
14751sub do_place_target_file($$$)
14752{
14753   my $place = shift;
14754   my $element = shift;
14755   my $context = shift;
14756
14757   $place->{'file'} = $element->{'file'} unless defined($place->{'file'});
14758   $place->{'target'} = $element->{'target'} unless defined($place->{'target'});
14759#   $place->{'doc_nr'} = $element->{'doc_nr'} unless defined($place->{'doc_nr'});
14760   if (defined($Texi2HTML::Config::placed_target_file_name))
14761   {
14762      my ($target, $id, $file) = &$Texi2HTML::Config::placed_target_file_name($place,$element,$place->{'target'}, $place->{'id'}, $place->{'file'},$context);
14763      $place->{'target'} = $target if (defined($target));
14764      $place->{'file'} = $file if (defined($file));
14765      $place->{'id'} = $id if (defined($id));
14766   }
14767}
14768
14769sub do_node_target_file($$)
14770{
14771    my $node = shift;
14772    my $type_of_node = shift;
14773    my $node_file = &$Texi2HTML::Config::node_file_name($node,$type_of_node);
14774    $node->{'node_file'} = $node_file if (defined($node_file));
14775    if (defined($Texi2HTML::Config::node_target_name))
14776    {
14777        my ($target,$id) = &$Texi2HTML::Config::node_target_name($node,$node->{'target'},$node->{'id'}, $type_of_node);
14778        $node->{'target'} = $target if (defined($target));
14779        $node->{'id'} = $id if (defined($id));
14780    }
14781}
14782
14783sub do_element_targets($;$)
14784{
14785   my $element = shift;
14786   my $use_node_file = shift;
14787   my $is_top = '';
14788   $is_top = "top" if ($element->{'top'} or (defined($element->{'with_node'}) and $element->{'with_node'} eq $element_top));
14789   my $file_index_split = Texi2HTML::Config::t2h_default_associate_index_element($element, $is_top, $docu_name, $use_node_file);
14790   $element->{'file'} = $file_index_split if (defined($file_index_split));
14791   if (defined($Texi2HTML::Config::element_file_name))
14792   {
14793      my $previous_file_name = $element->{'file'};
14794      my $filename =
14795          &$Texi2HTML::Config::element_file_name ($element, $is_top, $docu_name);
14796      if (defined($filename))
14797      {
14798         foreach my $place (@{$element->{'place'}})
14799         {
14800            $place->{'file'} = $filename if (defined($place->{'file'}) and ($place->{'file'} eq $previous_file_name));
14801         }
14802         $element->{'file'} = $filename;
14803      }
14804   }
14805   print STDERR "file !defined for element $element->{'texi'}\n" if (!defined($element->{'file'}));
14806   if (defined($Texi2HTML::Config::element_target_name))
14807   {
14808       my ($target,$id) = &$Texi2HTML::Config::element_target_name($element, $element->{'target'}, $element->{'id'});
14809       $element->{'target'} = $target if (defined($target));
14810       $element->{'id'} = $id if (defined($id));
14811   }
14812   foreach my $place(@{$element->{'place'}})
14813   {
14814      do_place_target_file($place, $element, '');
14815   }
14816}
14817
14818sub add_t2h_element($$$)
14819{
14820    my $element = shift;
14821    my $elements_list = shift;
14822    my $prev_element = shift;
14823
14824    push @$elements_list, $element;
14825    $element->{'element_ref'} = $element;
14826    $element->{'this'} = $element;
14827
14828    if (defined($prev_element))
14829    {
14830        $element->{'back'} = $prev_element;
14831        $prev_element->{'forward'} = $element;
14832    }
14833    push @{$element->{'place'}}, $element;
14834    push @{$element->{'place'}}, @{$element->{'current_place'}};
14835    return $element;
14836}
14837
14838sub add_t2h_dependent_element ($$)
14839{
14840    my $element = shift;
14841    my $element_ref = shift;
14842    $element->{'element_ref'} = $element_ref;
14843    $element_index = $element_ref if ($element_index and ($element_index eq $element));
14844    push @{$element_ref->{'place'}}, $element;
14845    push @{$element_ref->{'place'}}, @{$element->{'current_place'}};
14846}
14847
14848my %files = ();   # keys are files. This is used to avoid reusing an already
14849                  # used file name
14850my %empty_indices = (); # value is true for an index name key if the index
14851                        # is empty
14852my %printed_indices = (); # value is true for an index name not empty and
14853                          # printed
14854# This is a virtual element used to have the right hrefs for index entries
14855# and anchors in footnotes.
14856my $footnote_element;
14857
14858# find next, prev, up, back, forward, fastback, fastforward
14859# find element id and file
14860# split index pages
14861# associate placed items (items which have links to them) with the right
14862# file and id
14863# associate nodes with sections
14864sub rearrange_elements()
14865{
14866    print STDERR "# find sections levels and toplevel\n"
14867        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
14868
14869    my $toplevel = 4;
14870    # correct level if raisesections or lowersections overflowed
14871    # and find toplevel level
14872    # use %sections and %headings to modify also the headings
14873    foreach my $section (values(%sections), values(%headings))
14874    {
14875        my $level = $section->{'level'};
14876        if ($level > $MAX_LEVEL)
14877        {
14878             $section->{'level'} = $MAX_LEVEL;
14879        }
14880        elsif ($level < $MIN_LEVEL and !$section->{'top'})
14881        {
14882             $section->{'level'} = $MIN_LEVEL;
14883        }
14884        else
14885        {
14886             $section->{'level'} = $level;
14887        }
14888        $section->{'toc_level'} = $section->{'level'};
14889        # This is for top
14890        $section->{'toc_level'} = $MIN_LEVEL if ($section->{'level'} < $MIN_LEVEL);
14891        # find the new tag corresponding with the level of the section
14892        if ($section->{'tag'} !~ /heading/ and ($level ne $reference_sec2level{$section->{'tag'}}))
14893        {
14894             $section->{'tag_level'} = $level2sec{$section->{'tag'}}->[$section->{'level'}];
14895        }
14896        else
14897        {
14898             $section->{'tag_level'} = $section->{'tag'};
14899        }
14900        $toplevel = $section->{'level'} if (($section->{'level'} < $toplevel) and ($section->{'level'} > 0 and ($section->{'tag'} !~ /heading/)));
14901        print STDERR "# section level $level: $section->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
14902    }
14903
14904    print STDERR "# find sections structure, construct section numbers (toplevel=$toplevel)\n"
14905        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
14906    my $in_appendix = 0;
14907    # these arrays have an element per sectionning level.
14908    my @previous_numbers = ();   # holds the number of the previous sections
14909                                 # at the same and upper levels
14910    my @previous_sections = ();  # holds the ref of the previous sections
14911    my $previous_toplevel;
14912
14913    foreach my $section (@sections_list)
14914    {
14915        ########################### debug
14916        print STDERR "BUG: node or section_ref defined for section $section->{'texi'}\n"
14917            if (exists($section->{'node'}) or exists($section->{'section_ref'}));
14918        ########################### end debug
14919        # associate with first node if it is a section appearing before
14920        # the first node
14921        $section->{'node_ref'} = $nodes_list[0] if ($nodes_list[0] and !$section->{'node_ref'});
14922        print STDERR "Bug level undef for ($section) $section->{'texi'}\n" if (!defined($section->{'level'}));
14923        # we track the toplevel next and previous because there is no
14924        # strict child parent relationship between chapters and top. Indeed
14925        # a chapter may appear before @top, it may be better to consider them
14926        # on the same toplevel.
14927        if ($section->{'level'} <= $toplevel)
14928        {
14929            $section->{'toplevel'} = 1;
14930            if (defined($previous_toplevel))
14931            {
14932                $previous_toplevel->{'toplevelnext'} = $section;
14933                $section->{'toplevelprev'} = $previous_toplevel;
14934            }
14935            $previous_toplevel = $section;
14936            if (defined($section_top) and $section ne $section_top)
14937            {
14938                $section->{'sectionup'} = $section_top;
14939            }
14940        }
14941        # undef things under that section level
14942        my $section_level = $section->{'level'};
14943        # if it is the top element, the previous chapter is not wiped out
14944        $section_level++ if ($section->{'tag'} eq 'top');
14945        for (my $level = $section_level + 1; $level < $MAX_LEVEL + 1 ; $level++)
14946        {
14947            $previous_numbers[$level] = undef unless ($section->{'tag'} =~ /unnumbered/);
14948            $previous_sections[$level] = undef;
14949        }
14950        my $number_set;
14951        # find number at the current level
14952        if ($section->{'tag'} =~ /appendix/ and !$in_appendix)
14953        {
14954            $previous_numbers[$toplevel] = 'A';
14955            $in_appendix = 1;
14956            $number_set = 1 if ($section->{'level'} <= $toplevel);
14957        }
14958        if (!defined($previous_numbers[$section->{'level'}]) and !$number_set)
14959        {
14960            if ($section->{'tag'} =~ /unnumbered/)
14961            {
14962                 $previous_numbers[$section->{'level'}] = undef;
14963            }
14964            else
14965            {
14966                $previous_numbers[$section->{'level'}] = 1;
14967            }
14968        }
14969        elsif ($section->{'tag'} !~ /unnumbered/ and !$number_set)
14970        {
14971            $previous_numbers[$section->{'level'}]++;
14972        }
14973        # construct the section number
14974        $section->{'number'} = '';
14975
14976        unless ($section->{'tag'} =~ /unnumbered/ or $section->{'tag'} eq 'top')
14977        {
14978            my $level = $section->{'level'};
14979            while ($level > $toplevel)
14980            {
14981                my $number = $previous_numbers[$level];
14982                $number = 0 if (!defined($number));
14983                if ($section->{'number'})
14984                {
14985                    $section->{'number'} = "$number.$section->{'number'}";
14986                }
14987                else
14988                {
14989                    $section->{'number'} = $number;
14990                }
14991                $level--;
14992            }
14993            my $toplevel_number = $previous_numbers[$toplevel];
14994            $toplevel_number = 0 if (!defined($toplevel_number));
14995            $section->{'number'} = "$toplevel_number.$section->{'number'}";
14996        }
14997        # find the previous section
14998        if (defined($previous_sections[$section->{'level'}]))
14999        {
15000            my $prev_section = $previous_sections[$section->{'level'}];
15001            $section->{'sectionprev'} = $prev_section;
15002            $prev_section->{'sectionnext'} = $section;
15003        }
15004        # find the up section
15005        my $level = $section->{'level'} - 1;
15006        while (!defined($previous_sections[$level]) and ($level >= 0))
15007        {
15008            $level--;
15009        }
15010        if ($level >= 0)
15011        {
15012            $section->{'sectionup'} = $previous_sections[$level];
15013            # 'child' is the first child
15014            $section->{'sectionup'}->{'child'} = $section unless ($section->{'sectionprev'});
15015            push @{$section->{'sectionup'}->{'section_childs'}}, $section;
15016        }
15017        $previous_sections[$section->{'level'}] = $section;
15018        # This is what is used in the .init file.
15019        $section->{'up'} = $section->{'sectionup'};
15020        # Not used but documented.
15021        $section->{'next'} = $section->{'sectionnext'};
15022        $section->{'prev'} = $section->{'sectionprev'};
15023
15024        ############################# debug
15025        my $up = "NO_UP";
15026        $up = $section->{'sectionup'} if (defined($section->{'sectionup'}));
15027        print STDERR "# numbering section ($section->{'level'}): $section->{'number'}: (up: $up) $section->{'texi'}\n"
15028            if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15029        ############################# end debug
15030    }
15031
15032    # at that point there are still some node structures that are not
15033    # in %nodes, (the external nodes, and unknown nodes in case
15034    # novalidate is true) so we cannot find the id. The consequence is that
15035    # some node equivalent with another node may not be catched during
15036    # that pass. We mark the nodes that have directions for unreferenced
15037    # nodes and make a second pass for these nodes afterwards.
15038    my @nodes_with_unknown_directions = ();
15039
15040    my %node_directions = (
15041         'node_prev' => 'nodeprev',
15042         'node_next' => 'nodenext',
15043         'node_up' => 'nodeup');
15044    # handle nodes
15045    # the node_prev... are texinfo strings, find the associated node references
15046    print STDERR "# Resolve nodes directions\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15047    foreach my $node (@nodes_list)
15048    {
15049        foreach my $direction (keys(%node_directions))
15050        {
15051            if (defined($node->{$direction}))
15052            {
15053                if ($nodes{$node->{$direction}} and $nodes{$node->{$direction}}->{'seen'})
15054                {
15055                     $node->{$node_directions{$direction}} = $nodes{$node->{$direction}};
15056                }
15057                elsif (($node->{$direction} =~ /^\(.*\)/) or $novalidate)
15058                { # ref to an external node
15059                    if (exists($nodes{$node->{$direction}}))
15060                    {
15061                        $node->{$node_directions{$direction}} = $nodes{$node->{$direction}};
15062                    }
15063                    else
15064                    {
15065                        # FIXME if {'seen'} this is a node appearing in the
15066                        # document and a node like `(file)node'. What to
15067                        # do then ?
15068                        my $node_ref = { 'texi' => $node->{$direction} };
15069                        $node_ref->{'external_node'} = 1 if ($node->{$direction} =~ /^\(.*\)/);
15070                        $nodes{$node->{$direction}} = $node_ref;
15071                        $node->{$node_directions{$direction}} = $node_ref;
15072                    }
15073                }
15074                else
15075                {
15076                     push @nodes_with_unknown_directions, $node;
15077                }
15078            }
15079        }
15080    }
15081
15082    # Find cross manual links as explained on the texinfo mailing list
15083    # The  specification is such that cross manual links formatting should
15084    # be insensitive to the manual split
15085    cross_manual_links();
15086
15087    # Now it is possible to find the unknown directions that are equivalent
15088    # (have same node id) than an existing node
15089    foreach my $node (@nodes_with_unknown_directions)
15090    {
15091        foreach my $direction (keys(%node_directions))
15092        {
15093            if (defined($node->{$direction}) and !$node->{$node_directions{$direction}})
15094            {
15095                echo_warn ("$direction `$node->{$direction}' for `$node->{'texi'}' not found");
15096                my @equivalent_nodes = equivalent_nodes($node->{$direction});
15097                my $node_seen;
15098                foreach my $equivalent_node (@equivalent_nodes)
15099                {
15100                    if ($nodes{$equivalent_node}->{'seen'})
15101                    {
15102                        $node_seen = $equivalent_node;
15103                        last;
15104                    }
15105                }
15106                if (defined($node_seen))
15107                {
15108                    echo_warn (" ---> but equivalent node `$node_seen' found");
15109                    $node->{$node_directions{$direction}} = $nodes{$node_seen};
15110                }
15111            }
15112        }
15113    }
15114
15115    # nodes are attached to the section preceding them if not already
15116    # associated with a section
15117    my $current_section = $sections_list[0];
15118    foreach my $element (@all_elements)
15119    {
15120        if ($element->{'node'})
15121        {
15122            if ($element->{'with_section'})
15123            { # the node is associated with a section
15124                $element->{'section_ref'} = $element->{'with_section'};
15125            }
15126            elsif (defined($current_section))
15127            {# node appearing after a section, but not before another section,
15128             # or appearing before any section
15129                $element->{'section_ref'} = $current_section;
15130                push @{$current_section->{'node_childs'}}, $element;
15131            }
15132        }
15133        else
15134        {
15135            $current_section = $element;
15136        }
15137    }
15138
15139    print STDERR "# Complete nodes next prev and up based on menus and sections\n"
15140        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15141    # set the default id based on the node number
15142    my $node_nr = 1;
15143    # find the node* directions
15144    # find the directions corresponding with sections
15145    # and set 'up' for the node
15146    foreach my $node (@nodes_list)
15147    {
15148        # first a warning if the node and the equivalent nodes don't
15149        # appear in menus
15150        if (!$node->{'first'} and !$node->{'top'} and !$node->{'menu_up'} and ($node->{'texi'} !~ /^top$/i) and $Texi2HTML::Config::SHOW_MENU)
15151        {
15152            my @equivalent_nodes = equivalent_nodes($node->{'texi'});
15153            my $found = 0;
15154            foreach my $equivalent_node (@equivalent_nodes)
15155            {
15156                if ($nodes{$equivalent_node}->{'first'} or $nodes{$equivalent_node}->{'menu_up'})
15157                {
15158                   $found = 1;
15159                   last;
15160                }
15161            }
15162            unless ($found)
15163            {
15164                warn "$WARN `$node->{'texi'}' doesn't appear in menus\n";
15165            }
15166        }
15167
15168        # use values deduced from menus to complete missing up, next, prev
15169        # or from sectionning commands if automatic sectionning
15170        if (!$node->{'nodeup'})
15171        {
15172            if (defined($node_top) and ($node eq $node_top))
15173            { # Top node has a special up, which is (dir) by default
15174                my $top_nodeup = $Texi2HTML::Config::TOP_NODE_UP;
15175                if (exists($nodes{$top_nodeup}))
15176                {
15177                    $node->{'nodeup'} = $nodes{$top_nodeup};
15178                }
15179                else
15180                {
15181                    my $node_ref = { 'texi' => $top_nodeup };
15182                    $node_ref->{'external_node'} = 1;
15183                    $nodes{$top_nodeup} = $node_ref;
15184                    $node->{'nodeup'} = $node_ref;
15185                }
15186            }
15187            elsif ($node->{'automatic_directions'} and $node->{'with_section'})
15188            {
15189                if (defined($node->{'with_section'}->{'sectionup'}))
15190                {
15191                    $node->{'nodeup'} = get_node($node->{'with_section'}->{'sectionup'});
15192                }
15193                elsif ($node->{'with_section'}->{'toplevel'} and defined($section_top) and ($node->{'with_section'} ne $section_top))
15194                {
15195                    $node->{'nodeup'} = get_node($section_top);
15196                }
15197            }
15198            print STDERR "# Deducing from section node_up $node->{'nodeup'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS and defined($node->{'nodeup'}));
15199        }
15200
15201        if (!$node->{'nodeup'} and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
15202        { # makeinfo don't do that
15203            $node->{'nodeup'} = $node->{'menu_up'};
15204            print STDERR "# Deducing from menu node_up $node->{'menu_up'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15205        }
15206
15207        if ($node->{'nodeup'} and !$node->{'nodeup'}->{'external_node'})
15208        {
15209            # We detect when the up node has no menu entry for that node, as
15210            # there may be infinite loops when finding following node (see below)
15211            unless (defined($node->{'menu_up_hash'}) and ($node->{'menu_up_hash'}->{$node->{'nodeup'}->{'texi'}}))
15212            {
15213                print STDERR "$WARN `$node->{'nodeup'}->{'texi'}' is up for `$node->{'texi'}', but has no menu entry for this node\n" if ($Texi2HTML::Config::SHOW_MENU);
15214                push @{$node->{'up_not_in_menu'}}, $node->{'nodeup'}->{'texi'};
15215            }
15216        }
15217
15218        # Find next node if not already found
15219        if ($node->{'nodenext'}) {}
15220        elsif ($node->{'texi'} eq 'Top')
15221        { # special case as said in the texinfo manual
15222            if ($node->{'menu_child'})
15223            {
15224                $node->{'nodenext'} = $node->{'menu_child'};
15225                $node->{'menu_child'}->{'nodeprev'} = $node;
15226            }
15227        }
15228        elsif ($node->{'automatic_directions'} and defined($node->{'with_section'}))
15229        {
15230            my $next;
15231            my $section = $node->{'with_section'};
15232            if (defined($section->{'sectionnext'}))
15233            {
15234                $next = get_node($section->{'sectionnext'});
15235                if (defined($next) and $Texi2HTML::Config::SHOW_MENU)
15236                {
15237                    echo_warn ("No node following `$node->{'texi'}' in menu, but `$next->{'texi'}' follows in sectionning") if (!defined($node->{'menu_next'}));
15238                    echo_warn ("Node following `$node->{'texi'}' in menu `$node->{'menu_next'}->{'texi'}' and in sectionning `$next->{'texi'}' differ")
15239                       if (defined($node->{'menu_next'}) and $next ne $node->{'menu_next'});
15240                }
15241            }
15242            elsif ($Texi2HTML::Config::USE_UP_FOR_ADJACENT_NODES)
15243            { # makeinfo don't do that
15244                while (defined($section->{'sectionup'}) and !defined($section->{'sectionnext'}))
15245                {
15246                    $section = $section->{'sectionup'};
15247                }
15248                if (defined($section->{'sectionnext'}))
15249                {
15250                    $next = get_node($section->{'sectionnext'});
15251                }
15252            }
15253            $node->{'nodenext'} = $next;
15254        }
15255        # next we try menus. makeinfo don't do that
15256        if (!defined($node->{'nodenext'}) and $node->{'menu_next'}
15257            and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
15258        {
15259            $node->{'nodenext'} = $node->{'menu_next'};
15260        }
15261        # Find prev node
15262        if (!$node->{'nodeprev'} and $node->{'automatic_directions'})
15263        {
15264            if (defined($node->{'with_section'}))
15265            {
15266                my $section = $node->{'with_section'};
15267                if (defined($section->{'sectionprev'}))
15268                {
15269                    $node->{'nodeprev'} = get_node($section->{'sectionprev'});
15270                }
15271                elsif ($Texi2HTML::Config::USE_UP_FOR_ADJACENT_NODES and defined($section->{'sectionup'}))
15272                { # makeinfo don't do that
15273                    $node->{'nodeprev'} = get_node($section->{'sectionup'});
15274                }
15275            }
15276        }
15277        # next we try menus. makeinfo don't do that
15278        if (!defined($node->{'nodeprev'}) and $node->{'menu_prev'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
15279        {
15280            $node->{'nodeprev'} = $node->{'menu_prev'};
15281        }
15282        # the prev node is the parent node
15283        elsif (!defined($node->{'nodeprev'}) and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
15284        {
15285            $node->{'nodeprev'} = $node->{'menu_up'};
15286        }
15287
15288        # the following node is the node following in node reading order
15289        # it is thus first the child, else the next, else the next following
15290        # the up
15291        if ($node->{'menu_child'})
15292        {
15293            $node->{'following'} = $node->{'menu_child'};
15294        }
15295        elsif ($node->{'automatic_directions'} and defined($node->{'with_section'}) and defined($node->{'with_section'}->{'child'}))
15296        {
15297            $node->{'following'} = get_node($node->{'with_section'}->{'child'});
15298        }
15299        elsif (defined($node->{'nodenext'}))
15300        {
15301            $node->{'following'} = $node->{'nodenext'};
15302        }
15303	else
15304        {
15305            my $up = $node->{'nodeup'};
15306            # in order to avoid infinite recursion in case the up node is the
15307            # node itself we use the up node as following when there isn't
15308            # a correct menu structure, here and also below.
15309            $node->{'following'} = $up if (defined($up) and grep {$_ eq $up->{'texi'}} @{$node->{'up_not_in_menu'}});
15310            while ((!defined($node->{'following'})) and (defined($up)))
15311            {
15312                if (($node_top) and ($up eq $node_top))
15313                { # if we are at Top, Top is following
15314                    $node->{'following'} = $node_top;
15315                    $up = undef;
15316                }
15317                if (defined($up->{'nodenext'}))
15318                {
15319                    $node->{'following'} = $up->{'nodenext'};
15320                }
15321                elsif (defined($up->{'nodeup'}))
15322                {
15323                    if (! grep { $_ eq $up->{'nodeup'}->{'texi'} } @{$node->{'up_not_in_menu'}})
15324                    {
15325                        $up = $up->{'nodeup'};
15326                    }
15327                    else
15328                    { # in that case we can go into a infinite loop
15329                        $node->{'following'} = $up->{'nodeup'};
15330                    }
15331                }
15332                else
15333                {
15334                    $up = undef;
15335                }
15336            }
15337        }
15338        # FIXME with_section or node_ref? with with_section, as it is now
15339        # it is only done for the node associated with the section, with
15340        # section_ref it will be done for all the nodes after the section but
15341        # not associated with another section (as it was before)
15342        if (defined($node->{'with_section'}))
15343        {
15344            my $section = $node->{'with_section'};
15345            foreach my $direction ('sectionnext', 'sectionprev', 'sectionup')
15346            {
15347                $node->{$direction} = $section->{$direction}
15348                  if (defined($section->{$direction}));
15349            }
15350            # FIXME the following is wrong now, since it is only done for
15351            # the node->with_section. If done for node->section_ref it
15352            # could be true.
15353            # this is a node appearing within a section but not associated
15354            # with that section. We consider that it is below that section.
15355            $node->{'sectionup'} = $section
15356               if (grep {$node eq $_} @{$section->{'node_childs'}});
15357        }
15358        # 'up' is used in .init files. Maybe should go away.
15359        if (defined($node->{'sectionup'}))
15360        {
15361            $node->{'up'} = $node->{'sectionup'};
15362        }
15363        elsif (defined($node->{'nodeup'}) and
15364             (!$node_top or ($node ne $node_top)))
15365        {
15366            $node->{'up'} = $node->{'nodeup'};
15367        }
15368        # 'next' not used but documented.
15369        if (defined($node->{'sectionnext'}))
15370        {
15371            $node->{'next'} = $node->{'sectionnext'};
15372        }
15373        if (defined($node->{'sectionprev'}))
15374        {
15375            $node->{'prev'} = $node->{'sectionprev'};
15376        }
15377
15378        # default id for nodes. Should be overriden later.
15379        $node->{'id'} = 'NOD' . $node_nr;
15380        $node_nr++;
15381    }
15382
15383    # do node directions for sections
15384    # FIXME: really do that?
15385    foreach my $section (@sections_list)
15386    {
15387        # If the element is not a node, then all the node directions are copied
15388        # if there is an associated node
15389        if (defined($section->{'with_node'}))
15390        {
15391            $section->{'nodenext'} = $section->{'with_node'}->{'nodenext'};
15392            $section->{'nodeprev'} = $section->{'with_node'}->{'nodeprev'};
15393            $section->{'menu_next'} = $section->{'with_node'}->{'menu_next'};
15394            $section->{'menu_prev'} = $section->{'with_node'}->{'menu_prev'};
15395            $section->{'menu_child'} = $section->{'with_node'}->{'menu_child'};
15396            $section->{'menu_up'} = $section->{'with_node'}->{'menu_up'};
15397            $section->{'nodeup'} = $section->{'with_node'}->{'nodeup'};
15398            $section->{'following'} = $section->{'with_node'}->{'following'};
15399        }
15400        else
15401        { # the section has no node associated. Find the node directions using
15402          # sections
15403            if (defined($section->{'toplevelnext'}))
15404            {
15405                 $section->{'nodenext'} = get_node($section->{'toplevelnext'});
15406            }
15407            elsif (defined($section->{'sectionnext'}))
15408            {
15409                 $section->{'nodenext'} = get_node($section->{'sectionnext'});
15410            }
15411            if (defined($section->{'toplevelprev'}))
15412            {
15413                 $section->{'nodeprev'} = get_node($section->{'toplevelprev'});
15414            }
15415            elsif (defined($section->{'sectionprev'}))
15416            {
15417                 $section->{'nodeprev'} = get_node($section->{'sectionprev'});
15418            }
15419            if (defined($section->{'sectionup'}))
15420            {
15421                 $section->{'nodeup'} = get_node($section->{'sectionup'});
15422            }
15423
15424            if ($section->{'child'})
15425            {
15426                $section->{'following'} = get_node($section->{'child'});
15427            }
15428            elsif ($section->{'toplevelnext'})
15429            {
15430                $section->{'following'} = get_node($section->{'toplevelnext'});
15431            }
15432            elsif ($section->{'sectionnext'})
15433            {
15434                $section->{'following'} = get_node($section->{'sectionnext'});
15435            }
15436            elsif ($section->{'sectionup'})
15437            {
15438                my $up = $section;
15439                while ($up->{'sectionup'} and !$section->{'following'})
15440                {
15441                    print STDERR "# Going up, searching next section from $up->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15442                    die "BUG: $up->{'texi'} is up for itself\n" if ($up eq $up->{'sectionup'});
15443                    $up = $up->{'sectionup'};
15444                    if ($up->{'sectionnext'})
15445                    {
15446                        $section->{'following'} = get_node ($up->{'sectionnext'});
15447                    }
15448                }
15449            }
15450        }
15451    }
15452    my $only_nodes = 0;
15453    my $only_sections = 0;
15454
15455    # for legibility
15456    my $use_nodes = $Texi2HTML::Config::USE_NODES;
15457    my $use_sections = $Texi2HTML::Config::USE_SECTIONS;
15458
15459    $only_nodes = 1 if (
15460         (!scalar(@sections_list) and
15461            ($use_nodes or (!$use_sections and !defined($use_nodes))))
15462      or ($use_nodes and !$use_sections)
15463    );
15464    $only_sections = 1 if (!$only_nodes and !$use_nodes and ($use_sections or !defined($use_sections)));
15465    #print STDERR "only_nodes: $only_nodes, only_sections $only_sections\n";
15466
15467    my $prev_element;
15468    print STDERR "# Build the elements list\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15469    foreach my $element (@all_elements)
15470    {
15471        if ($element->{'node'})
15472        {
15473            if (!$only_nodes and $node_top and $element eq $node_top and !$section_top and !$node_top->{'with_section'})
15474            { # special case for the top node if it isn't associated with
15475              # a section.
15476              # FIXME Config variable
15477                print STDERR "# Top not associated with a section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15478                $node_top->{'top_as_section'} = 1;
15479                $node_top->{'section_ref'} = $node_top;
15480                $prev_element = add_t2h_element($element, \@elements_list, $prev_element);
15481            }
15482            elsif ($element->{'section_ref'} and ($only_sections or (!$only_nodes and $element->{'with_section'})))
15483            {
15484                add_t2h_dependent_element ($element, $element->{'section_ref'});
15485                $element->{'toc_level'} = $element->{'section_ref'}->{'toc_level'};
15486            }
15487            elsif (!$only_sections)
15488            {
15489                $prev_element = add_t2h_element($element, \@elements_list, $prev_element);
15490                if ($element->{'section_ref'})
15491                { # may happen if $only_nodes
15492                    $element->{'toc_level'} = $element->{'section_ref'}->{'toc_level'};
15493                }
15494            }
15495            else # $only_section and !$section_ref. This should only
15496                 # happen when there are no sections
15497                 # in that case it is possible that the node_top is an
15498                 # element, so it is associated with this one. Maybe it
15499                 # may happen that the node_top is not an element, not sure
15500                 # what would be the consequence ni that case.
15501            {
15502                if ($node_top)
15503                {
15504                    add_t2h_dependent_element ($element, $node_top);
15505                }
15506                else
15507                {
15508                    #print STDERR "node $element->{'texi'} not associated with an element\n";
15509                }
15510            }
15511            # FIXME use Texi2HTML::Config::NODE_TOC_LEVEL?
15512            $element->{'toc_level'} = $MIN_LEVEL if (!defined($element->{'toc_level'}));
15513        }
15514        else
15515        {
15516            if ($element->{'node_ref'} and $only_nodes)
15517            {
15518                add_t2h_dependent_element ($element, $element->{'node_ref'});
15519            }
15520            elsif (!$only_nodes)
15521            {
15522                $prev_element = add_t2h_element($element, \@elements_list, $prev_element);
15523            }
15524        }
15525    }
15526
15527    # find texi2html specific directions and elements that are not texinfo
15528    # language features.
15529    #
15530    # Maybe Config hooks should be used at that point (up to index
15531    # preparation)
15532    #
15533    # find first, last and top elements
15534    if (@elements_list)
15535    {
15536        $element_first = $elements_list[0];
15537        print STDERR "# element first: $element_first->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15538        # It is the last element before indices split, which may add new
15539        # elements
15540        $element_last = $elements_list[-1];
15541    }
15542    else
15543    {
15544        print STDERR "# \@elements_list is empty\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15545    }
15546    print STDERR "# top node: $node_top->{'texi'}\n" if (defined($node_top) and
15547        ($T2H_DEBUG & $DEBUG_ELEMENTS));
15548    if (defined($section_top))
15549    {
15550    # element top is the element with @top.
15551        $element_top = $section_top;
15552    }
15553    elsif (defined($node_top))
15554    {
15555    # If the top node is associated with a section it is the top_element
15556    # otherwise element top may be the top node
15557        $element_top = $node_top;
15558    }
15559    elsif (defined($element_first))
15560    {
15561    # If there is no @top section no top node the first node is the top element
15562         $element_top = $element_first;
15563    }
15564
15565    if (defined($element_top))
15566    {
15567        $element_top->{'top'} = 1 if ($element_top->{'node'});
15568        print STDERR "# element top: $element_top->{'texi'}\n" if ($element_top and
15569           ($T2H_DEBUG & $DEBUG_ELEMENTS));
15570    }
15571
15572    print STDERR "# find fastback and fastforward\n"
15573       if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15574    foreach my $element (@elements_list)
15575    {
15576        my $up = get_top($element);
15577        # this is a node not associated with a section
15578        $up = get_top($element->{'section_ref'}) if (!defined($up) and $element->{'node'} and $element->{'section_ref'});
15579        next unless (defined($up));
15580        # take the opportunity to set the first chapter with index
15581        $element_chapter_index = $up if ($element_index and ($element_index eq $element));
15582        # fastforward is the next element on same level than the upper parent
15583        # element.
15584        if (exists ($up->{'toplevelnext'}))
15585        {
15586            $element->{'fastforward'} = $up->{'toplevelnext'}
15587        }
15588        # if the element isn't at the highest level, fastback is the
15589        # highest parent element
15590        if ($up and ($up ne $element))
15591        {
15592            $element->{'fastback'} = $up;
15593        }
15594        elsif ($element->{'toplevel'})
15595        {
15596             # the element is a top level element, we adjust the next
15597            # toplevel element fastback
15598            $element->{'fastforward'}->{'fastback'} = $element if ($element->{'fastforward'});
15599        }
15600    }
15601
15602    foreach my $element (@elements_list)
15603    {
15604        # FIXME: certainly wrong. Indeed this causes the section associated
15605        # with the @node Top to be up for a @chapter, even if it is a
15606        # @chapter and not @top. It could even be up and, say, a @section!
15607        if ($element->{'toplevel'} and ($element ne $element_top))
15608        {
15609            $element->{'up'} = $element_top;
15610        }
15611    }
15612
15613    # set 'reference_element' which is used each time there is a cross ref
15614    # to that node.
15615    # It is the section associated with the node if there are only sections
15616    # FIXME with only_nodes there should certainly be a corresponding
15617    # reference_element set.
15618    # also should certainly be done above
15619    if ($only_sections)
15620    {
15621        foreach my $node(@nodes_list)
15622        {
15623            if ($node->{'with_section'})
15624            {
15625                $node->{'reference_element'} = $node->{'with_section'};
15626            }
15627        }
15628    }
15629
15630    # do human readable id
15631    print STDERR "# find float id\n"
15632       if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15633    foreach my $float (@floats)
15634    {
15635        $float->{'style_id'} = cross_manual_line(normalise_space($float->{'style_texi'}));
15636        my $float_style = { };
15637        if (exists($floats{$float->{'style_id'}}))
15638        {
15639            $float_style = $floats{$float->{'style_id'}};
15640        }
15641        else
15642        {
15643            $floats{$float->{'style_id'}} = $float_style;
15644        }
15645        push @{$float_style->{'floats'}}, $float;
15646        $float->{'absolute_nr'} = scalar(@{$float_style->{'floats'}});
15647        my $up = get_top($float->{'element'});
15648        if (defined($up) and (!defined($float_style->{'current_chapter'}) or ($up->{'texi'} ne $float_style->{'current_chapter'})))
15649        {
15650            $float_style->{'current_chapter'} = $up->{'texi'};
15651            $float_style->{'nr_in_chapter'} = 1;
15652        }
15653        else
15654        {
15655            $float_style->{'nr_in_chapter'}++;
15656        }
15657        if (defined($up) and $up->{'number'} ne '')
15658        {
15659            $float->{'chapter_nr'} = $up->{'number'};
15660            $float->{'nr'} = $float->{'chapter_nr'} . $float_style->{'nr_in_chapter'};
15661        }
15662        else
15663        {
15664            $float->{'nr'} = $float->{'absolute_nr'};
15665        }
15666    }
15667
15668    print STDERR "# do human-readable index entries id\n"
15669       if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15670    if ($Texi2HTML::Config::NEW_CROSSREF_STYLE)
15671    {
15672        foreach my $index_entry (@index_labels)
15673        {
15674            my $index_id = "index-" . $index_entry->{'cross'};
15675            my $index = 1;
15676            # $index > 0 should prevent integer overflow, hopefully
15677            while (exists($cross_reference_nodes{$index_id}) and $index > 0)
15678            {
15679                $index_id = "index-" . $index_entry->{'cross'} . "-" .$index;
15680                $index++;
15681            }
15682            $index_entry->{'id'} = $index_id;
15683            $index_entry->{'target'} = $index_id;
15684            my $texi_entry = "index-".$index_entry->{'texi'};
15685            $texi_entry .= "-".$index if ($index > 1);
15686            push @{$cross_reference_nodes{$index_id}}, $texi_entry;
15687        }
15688    }
15689
15690
15691    if ($Texi2HTML::Config::NEW_CROSSREF_STYLE)
15692    {
15693        foreach my $key (keys(%nodes))
15694        {
15695            my $node = $nodes{$key};
15696            next if ($node->{'external_node'});
15697            $node->{'id'} = node_to_id($node->{'cross_manual_target'});
15698            # FIXME if NEW_CROSSREF_STYLE false is it done for anchors?
15699            $node->{'target'} = $node->{'id'};
15700        }
15701    }
15702
15703    # use %sections and %headings to modify also the headings
15704    foreach my $section (values(%sections), values(%headings))
15705    {
15706        if ($Texi2HTML::Config::NEW_CROSSREF_STYLE and ($section->{'cross'} =~ /\S/))
15707        {
15708            my $section_cross = $section->{'cross'};
15709            if (defined($section->{'region'}))
15710            { # for headings appearing in special regions like @copying...
15711                $section_cross = "${target_prefix}-$section->{'region'}_$section_cross";
15712            }
15713            $section->{'cross_manual_target'} = $section_cross;
15714
15715            my $index = 1;
15716            # $index > 0 should prevent integer overflow, hopefully
15717            while (exists($cross_reference_nodes{$section->{'cross_manual_target'}}) and $index > 0)
15718            {
15719                $section->{'cross_manual_target'} = $section_cross . "-" .$index;
15720                $index++;
15721            }
15722            my $texi_entry = $section->{'texi'};
15723            $texi_entry .= "-".$index if ($index > 1);
15724            push @{$cross_reference_nodes{$section->{'cross_manual_target'}}}, $texi_entry;
15725            $section->{'id'} = node_to_id($section->{'cross_manual_target'});
15726        }
15727        if ($Texi2HTML::Config::USE_NODE_TARGET and $section->{'with_node'})
15728        {
15729            $section->{'target'} = $section->{'with_node'}->{'target'};
15730        }
15731        else
15732        {
15733            $section->{'target'} = $section->{'id'};
15734        }
15735    }
15736
15737    # construct human readable tocid
15738    foreach my $section (values(%sections))
15739    {
15740        if ($Texi2HTML::Config::NEW_CROSSREF_STYLE and ($section->{'cross'} =~ /\S/))
15741        {
15742            foreach my $toc_id (['tocid','toc'], ['stocid', 'stoc'])
15743            {
15744                my $id_string = $toc_id->[0];
15745                my $prefix_string = $toc_id->[1];
15746                my $cross_string = '-' . $section->{'cross_manual_target'};
15747                $section->{$id_string} = $prefix_string . $cross_string;
15748                my $index = 1;
15749                # $index > 0 should prevent integer overflow, hopefully
15750                while (exists($cross_reference_nodes{$section->{$id_string}}) and $index > 0)
15751                {
15752                    $section->{$id_string} = $prefix_string . "-" .$index .$cross_string;
15753                    $index++;
15754                }
15755                my $texi_entry = $prefix_string.'-'.$section->{'texi'};
15756                $texi_entry = $prefix_string .'-'.$index.'-'.$section->{'texi'}  if ($index > 1);
15757                push @{$cross_reference_nodes{$section->{$id_string}}}, $texi_entry;
15758            }
15759        }
15760    }
15761    if (!$Texi2HTML::Config::NEW_CROSSREF_STYLE)
15762    {
15763        my $tocnr = 1;
15764        foreach my $element (@elements_list)
15765        {
15766            $element->{'tocid'} = 'TOC' . $tocnr;
15767            $tocnr++;
15768        }
15769    }
15770
15771    # Set file names
15772    # Find node file names and file names for nodes considered as elements
15773    my $node_as_top;
15774    if ($node_top)
15775    {
15776        $node_as_top = $node_top;
15777    }
15778    elsif ($element_top->{'with_node'})
15779    {
15780        $node_as_top = $element_top->{'with_node'};
15781    }
15782    else
15783    {
15784        $node_as_top = $node_first;
15785    }
15786    if ($node_as_top)
15787    {
15788        do_node_target_file($node_as_top, 'top');
15789    }
15790    foreach my $key (keys(%nodes))
15791    {
15792        my $node = $nodes{$key};
15793        next if (defined($node_as_top) and ($node eq $node_as_top));
15794        do_node_target_file($node,'');
15795    }
15796
15797    print STDERR "# split and set files\n"
15798       if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15799    # find document nr and document file for sections and nodes.
15800    # Split according to Texi2HTML::Config::SPLIT.
15801    # find file and id for placed elements (anchors, index entries, headings)
15802    if ($Texi2HTML::Config::SPLIT)
15803    {
15804        $Texi2HTML::THISDOC{'split_level'} = $toplevel;
15805        my $doc_nr = -1;
15806        if ($Texi2HTML::Config::SPLIT eq 'section')
15807        {
15808            $Texi2HTML::THISDOC{'split_level'} = 2 if ($toplevel <= 2);
15809        }
15810        my $previous_file;
15811        foreach my $element (@elements_list)
15812        {
15813            print STDERR "# Splitting ($Texi2HTML::Config::SPLIT:$Texi2HTML::THISDOC{'split_level'}) $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15814            my $new_file = 0;
15815            if (
15816               ($Texi2HTML::Config::SPLIT eq 'node') or
15817               (
15818                 defined($element->{'level'}) and ($element->{'level'} <= $Texi2HTML::THISDOC{'split_level'})
15819               )
15820              )
15821            {
15822                $new_file = 1;
15823                $doc_nr++;
15824            }
15825            $doc_nr = 0 if ($doc_nr < 0); # happens if first elements are nodes
15826            $element->{'doc_nr'} = $doc_nr;
15827            my $is_top = '';
15828            $element->{'file'} = "${docu_name}_$doc_nr"
15829                   . (defined($Texi2HTML::THISDOC{'extension'}) ? ".$Texi2HTML::THISDOC{'extension'}" : '');
15830            my $use_node_file = 0;
15831            if ($element->{'top'} or (defined($element->{'with_node'}) and $element->{'with_node'} eq $element_top))
15832            { # the top elements
15833                $is_top = "top";
15834                $element->{'file'} = $docu_top;
15835            }
15836            elsif ($Texi2HTML::Config::NODE_FILES)
15837            {
15838                $use_node_file = 1;
15839                if ($new_file)
15840                {
15841                    my $node = get_node($element) unless(exists($element->{'with_node'})
15842                        and $element->{'with_node'}->{'element_added'});
15843                    if ($node and defined($node->{'node_file'}))
15844                    {
15845                        $element->{'file'} = $node->{'node_file'};
15846                    }
15847                    $previous_file = $element->{'file'};
15848                }
15849                elsif($previous_file)
15850                {
15851                    $element->{'file'} = $previous_file;
15852                }
15853            }
15854            do_element_targets($element, $use_node_file);
15855            print STDERR "# add_file($use_node_file) $element->{'file'} for $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15856            add_file($element->{'file'});
15857        }
15858    }
15859    else
15860    { # not split
15861        add_file($docu_doc);
15862        foreach my $element(@elements_list)
15863        {
15864            $element->{'file'} = $docu_doc;
15865            $element->{'doc_nr'} = 0;
15866            do_element_targets($element);
15867        }
15868    }
15869    # 'pathological' cases. No texinfo sectionning element at all or no
15870    # texi2html sectionning elements
15871    if (!@elements_list)
15872    {
15873        if (@all_elements)
15874        {
15875            foreach my $element (@all_elements)
15876            {
15877                #print STDERR "# no \@elements_list. Processing $element->{'texi'}\n";
15878                $element->{'file'} = $docu_doc;
15879                $element->{'doc_nr'} = 0;
15880                push @{$element->{'place'}}, @{$element->{'current_place'}};
15881                do_element_targets($element);
15882            }
15883        }
15884        else
15885        {
15886            $element_before_anything->{'file'} = $docu_doc;
15887            $element_before_anything->{'doc_nr'} = 0;
15888            do_element_targets($element_before_anything);
15889        }
15890    }
15891    # correct the id and file for the things placed in footnotes
15892    foreach my $place(@{$footnote_element->{'place'}})
15893    {
15894        do_place_target_file ($place, $footnote_element, 'footnotes');
15895    }
15896    # if setcontentsaftertitlepage is set, the contents should be associated
15897    # with the titlepage. That's wat is done there.
15898    push @$no_element_associated_place, $content_element{'contents'}
15899      if ($Texi2HTML::THISDOC{'DO_CONTENTS'} and $Texi2HTML::THISDOC{'setcontentsaftertitlepage'});
15900    push @$no_element_associated_place, $content_element{'shortcontents'}
15901      if ($Texi2HTML::THISDOC{'DO_SCONTENTS'} and $Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'});
15902    # correct the id and file for the things placed in regions (copying...)
15903    foreach my $place(@$no_element_associated_place)
15904    {
15905#print STDERR "entry $place->{'entry'} texi $place->{'texi'}\n";
15906        $place->{'element'} = $element_top if (exists($place->{'element'}));
15907        do_place_target_file ($place, $element_top, 'no_associated_element');
15908    }
15909    foreach my $content_type(keys(%content_element))
15910    {
15911        # with set*aftertitlepage, there will always be a href to Contents
15912        # or Overview pointing to the top element, even if there is no
15913        # titlepage outputed.
15914        if ((!defined($content_element{$content_type}->{'file'})) and $Texi2HTML::Config::INLINE_CONTENTS)
15915        {
15916            print STDERR "# No content $content_type\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15917            $content_element{$content_type} = undef;
15918        }
15919    }
15920    my ($toc_file, $stoc_file);
15921    $toc_file = $docu_toc;
15922    $stoc_file = $docu_stoc;
15923    if ($Texi2HTML::Config::INLINE_CONTENTS)
15924    {
15925        $toc_file = $content_element{'contents'}->{'file'} if (defined($content_element{'contents'}));
15926        $stoc_file = $content_element{'shortcontents'}->{'file'} if (defined($content_element{'shortcontents'}));
15927    }
15928    $Texi2HTML::THISDOC{'toc_file'} = $toc_file;
15929    $Texi2HTML::THISDOC{'stoc_file'} = $stoc_file;
15930
15931    print STDERR "# find NextFile and PrevFile\n"
15932       if ($T2H_DEBUG & $DEBUG_ELEMENTS);
15933    foreach my $element (@elements_list)
15934    {
15935        my $current_element = $element;
15936        my $file = $current_element->{'file'};
15937        my $previous_file;
15938        while ($current_element->{'back'})
15939        {
15940#print STDERR "Back $current_element->{'texi'}\n";
15941            $current_element = $current_element->{'back'};
15942            if ($current_element->{'file'} ne $file)
15943            {
15944                $previous_file = $current_element->{'file'};
15945                last;
15946            }
15947        }
15948        if (defined($previous_file))
15949        {
15950            while ($current_element->{'back'})
15951            {
15952                if ($current_element->{'back'}->{'file'} ne $previous_file)
15953                {
15954                    last;
15955                }
15956                $current_element = $current_element->{'back'};
15957            }
15958            $element->{'prevfile'} = $current_element;
15959        }
15960
15961        $current_element = $element;
15962        while ($current_element->{'forward'})
15963        {
15964#print STDERR "Fwd $current_element->{'texi'}\n";
15965            $current_element = $current_element->{'forward'};
15966            if ($current_element->{'file'} ne $file)
15967            {
15968                 $element->{'nextfile'} = $current_element;
15969            }
15970        }
15971    }
15972    # convert directions in direction with first letter in all caps, to be
15973    # consistent with the convention used in the .init file.
15974    foreach my $element (@elements_list)
15975    {
15976        foreach my $direction (@element_directions)
15977        {
15978            my $direction_no_caps = $direction;
15979            $direction_no_caps =~ tr/A-Z/a-z/;
15980            $element->{$direction} = $element->{$direction_no_caps};
15981        }
15982    }
15983
15984    ########################### debug prints
15985    foreach my $file (keys(%files))
15986    {
15987        last unless ($T2H_DEBUG & $DEBUG_ELEMENTS);
15988        print STDERR "$file: counter $files{$file}->{'counter'}\n";
15989    }
15990    my $output_elements = \@elements_list;
15991    if (!scalar(@elements_list) and ($T2H_DEBUG & $DEBUG_ELEMENTS))
15992    {
15993        print STDERR "No elements_list, no texi2html elements\n";
15994        $output_elements = \@all_elements;
15995    }
15996    foreach my $element ((@$output_elements, $footnote_element))
15997    {
15998        last unless ($T2H_DEBUG & $DEBUG_ELEMENTS);
15999        my $is_toplevel = 'not toplevel';
16000        $is_toplevel = 'toplevel' if ($element->{'toplevel'});
16001        print STDERR "$element ";
16002        if ($element->{'node'})
16003        {
16004            print STDERR "node($element->{'id'}, toc_level $element->{'toc_level'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n";
16005            print STDERR "  section_ref: $element->{'section_ref'}->{'texi'}\n" if (defined($element->{'section_ref'}));
16006            print STDERR "  with_section: $element->{'with_section'}->{'texi'}\n" if (defined($element->{'with_section'}));
16007        }
16008        elsif ($element->{'footnote'})
16009        {
16010            print STDERR "footnotes($element->{'id'}, file $element->{'file'})\n";
16011        }
16012        else
16013        {
16014            my $number = "UNNUMBERED";
16015            $number = $element->{'number'} if ($element->{'number'});
16016            print STDERR "$number ($element->{'id'}, $is_toplevel, level $element->{'level'}-$element->{'toc_level'}, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n";
16017            print STDERR "  with_node: $element->{'with_node'}->{'texi'}\n" if (defined($element->{'with_node'}));
16018            print STDERR "  node_ref: $element->{'node_ref'}->{'texi'}\n" if (defined($element->{'node_ref'}));
16019        }
16020
16021        if (!$element->{'footnote'})
16022        {
16023            if (!defined($files{$element->{'file'}}))
16024            {
16025               die "Bug: files{\$element->{'file'}} undef element $element->{'texi'}, file $element->{'file'}.";
16026            }
16027            print STDERR "  file: $element->{'file'} $files{$element->{'file'}}, counter $files{$element->{'file'}}->{'counter'}\n";
16028        }
16029        print STDERR "  TOP($toplevel) " if ($element->{'top'});
16030        print STDERR "  u: $element->{'up'}->{'texi'}\n" if (defined($element->{'up'}));
16031        print STDERR "  ch: $element->{'child'}->{'texi'}\n" if (defined($element->{'child'}));
16032        print STDERR "  fb: $element->{'fastback'}->{'texi'}\n" if (defined($element->{'fastback'}));
16033        print STDERR "  b: $element->{'back'}->{'texi'}\n" if (defined($element->{'back'}));
16034        print STDERR "  p: $element->{'prev'}->{'texi'}\n" if (defined($element->{'prev'}));
16035        print STDERR "  u: $element->{'sectionup'}->{'texi'}\n" if (defined($element->{'sectionup'}));
16036        print STDERR "  n: $element->{'sectionnext'}->{'texi'}\n" if (defined($element->{'sectionnext'}));
16037	print STDERR "  t_n: $element->{'toplevelnext'}->{'texi'}\n" if (defined($element->{'toplevelnext'}));
16038	print STDERR "  t_p: $element->{'toplevelprev'}->{'texi'}\n" if (defined($element->{'toplevelprev'}));
16039        print STDERR "  n_u: $element->{'nodeup'}->{'texi'}\n" if (defined($element->{'nodeup'}));
16040        print STDERR "  f: $element->{'forward'}->{'texi'}\n" if (defined($element->{'forward'}));
16041        print STDERR "  follow: $element->{'following'}->{'texi'}\n" if (defined($element->{'following'}));
16042	print STDERR "  m_p: $element->{'menu_prev'}->{'texi'}\n" if (defined($element->{'menu_prev'}));
16043	print STDERR "  m_n: $element->{'menu_next'}->{'texi'}\n" if (defined($element->{'menu_next'}));
16044	print STDERR "  m_u: $element->{'menu_up'}->{'texi'}\n" if (defined($element->{'menu_up'}));
16045	print STDERR "  m_ch: $element->{'menu_child'}->{'texi'}\n" if (defined($element->{'menu_child'}));
16046        print STDERR "  ff: $element->{'fastforward'}->{'texi'}\n" if (defined($element->{'fastforward'}));
16047        print STDERR "  n_f: $element->{'nextfile'}->{'texi'}\n" if (defined($element->{'nextfile'}));
16048        print STDERR "  p_f: $element->{'prevfile'}->{'texi'}\n" if (defined($element->{'prevfile'}));
16049        my $section_childs = '';
16050        if (defined($element->{'section_childs'}))
16051        {
16052            foreach my $child (@{$element->{'section_childs'}})
16053            {
16054                $section_childs .= "$child->{'texi'}|";
16055            }
16056        }
16057        print STDERR "  s_chs: $section_childs\n" if ($section_childs ne '');
16058        my $node_childs = '';
16059        if (defined($element->{'node_childs'}))
16060        {
16061            foreach my $child (@{$element->{'node_childs'}})
16062            {
16063                $node_childs .= "$child->{'texi'}|";
16064            }
16065        }
16066        print STDERR "  n_chs: $node_childs\n" if ($node_childs ne '');
16067
16068        if (defined($element->{'menu_up_hash'}))
16069        {
16070            print STDERR "  parent nodes:\n";
16071            foreach my $menu_up (keys%{$element->{'menu_up_hash'}})
16072            {
16073                print STDERR "   $menu_up ($element->{'menu_up_hash'}->{$menu_up})\n";
16074            }
16075        }
16076        print STDERR "  places: $element->{'place'}\n";
16077        foreach my $place(@{$element->{'place'}})
16078        {
16079            if (!$place->{'entry'} and !$place->{'float'} and !$place->{'texi'} and !$place->{'contents'} and !$place->{'shortcontents'} and (!defined($place->{'command'} or $place->{'command'} ne 'printindex')))
16080            {
16081                 print STDERR "BUG: unknown placed stuff ========\n";
16082                 foreach my $key (keys(%$place))
16083                 {
16084                      print STDERR "$key: $place->{$key}\n";
16085                 }
16086                 print STDERR "==================================\n";
16087            }
16088            elsif ($place->{'entry'})
16089            {
16090                print STDERR "    index($place): $place->{'entry'} ($place->{'id'}, $place->{'file'})\n";
16091            }
16092            elsif ($place->{'anchor'})
16093            {
16094                print STDERR "    anchor: $place->{'texi'} ($place->{'id'}, $place->{'file'})\n";
16095            }
16096            elsif ($place->{'float'})
16097            {
16098                if (defined($place->{'texi'}))
16099                {
16100                    print STDERR "    float($place): $place->{'texi'} ($place->{'id'}, $place->{'file'})\n";
16101                }
16102                else
16103                {
16104                    print STDERR "    float($place): NO LABEL ($place->{'id'}, $place->{'file'})\n";
16105                }
16106            }
16107            elsif ($place->{'contents'})
16108            {
16109                print STDERR "    contents\n";
16110            }
16111            elsif ($place->{'shortcontents'})
16112            {
16113                print STDERR "    shortcontents\n";
16114            }
16115            elsif (defined($place->{'command'}) and $place->{'command'} eq 'printindex')
16116            {
16117                print STDERR "    printindex $place->{'name'}\n";
16118            }
16119            else
16120            {
16121                print STDERR "    heading: $place->{'texi'} ($place->{'id'}, $place->{'file'})\n";
16122            }
16123        }
16124    }
16125    ########################### end debug prints
16126}
16127
16128sub add_file($)
16129{
16130    my  $file = shift;
16131    if ($files{$file})
16132    {
16133         $files{$file}->{'counter'}++;
16134    }
16135    else
16136    {
16137         $files{$file} = {
16138           #'type' => 'section',
16139           'counter' => 1,
16140           'relative_foot_num' => 0,
16141           'foot_lines' => []
16142         };
16143    }
16144}
16145
16146# find parent element which is a top element, or a node within the top section
16147sub get_top($)
16148{
16149   my $element = shift;
16150   my $up = $element;
16151   while (!$up->{'toplevel'} and !$up->{'top'})
16152   {
16153       $up = $up->{'sectionup'};
16154       if (!defined($up))
16155       {
16156           # If there is no section, it is normal not to have toplevel element,
16157           # and it is also the case if there is a low level element before
16158           # a top level element
16159           return undef;
16160       }
16161   }
16162   return $up;
16163}
16164
16165sub get_node($)
16166{
16167    my $element = shift;
16168    return undef if (!defined($element));
16169    return $element if ($element->{'node'});
16170    return $element->{'with_node'} if ($element->{'with_node'});
16171    return $element;
16172}
16173
16174sub do_section_names($$)
16175{
16176    my $number = shift;
16177    my $section = shift;
16178    #$section->{'name'} = substitute_line($section->{'texi'});
16179    my $texi = &$Texi2HTML::Config::heading_texi($section->{'tag'}, $section->{'texi'}, $section->{'number'});
16180    $section->{'text'} = substitute_line($texi);
16181    $section->{'text_nonumber'} = substitute_line($section->{'texi'});
16182    # backward compatibility
16183    $section->{'name'} = $section->{'text_nonumber'};
16184    $section->{'no_texi'} = remove_texi($texi);
16185    $section->{'simple_format'} = simple_format(undef,undef,$texi);
16186    $section->{'heading_texi'} = $texi;
16187}
16188
16189# get the html names from the texi for all elements
16190sub do_names()
16191{
16192    print STDERR "# Doing ". scalar(keys(%nodes)) . " nodes, ".
16193        scalar(keys(%sections)) . " sections, " .
16194        scalar(keys(%headings)) . " headings in ". $#elements_list .
16195        " elements\n" if ($T2H_DEBUG);
16196    # for nodes and anchors we haven't any state defined
16197    # This seems right, however, as we don't want @refs or @footnotes
16198    # or @anchors within nodes, section commands or anchors.
16199    foreach my $node (keys(%nodes))
16200    {
16201        my $texi = &$Texi2HTML::Config::heading_texi($nodes{$node}->{'tag'},
16202           $nodes{$node}->{'texi'}, undef);
16203        $nodes{$node}->{'text'} = substitute_line ($texi, {'code_style' => 1});
16204        $nodes{$node}->{'text_nonumber'} = $nodes{$node}->{'text'};
16205        # backward compatibility -> maybe used to have the name without code_style ?
16206        $nodes{$node}->{'name'} = substitute_line($texi);
16207        $nodes{$node}->{'no_texi'} = remove_texi($texi);
16208        $nodes{$node}->{'simple_format'} = simple_format(undef, undef, $texi);
16209        $nodes{$node}->{'heading_texi'} = $texi;
16210        # FIXME : what to do if $nodes{$node}->{'external_node'} and
16211        # $nodes{$node}->{'seen'}
16212    }
16213    foreach my $number (keys(%sections))
16214    {
16215        do_section_names($number, $sections{$number});
16216    }
16217    foreach my $number (keys(%headings))
16218    {
16219        do_section_names($number, $headings{$number});
16220    }
16221    print STDERR "# Names done\n" if ($T2H_DEBUG);
16222}
16223
16224
16225#+++############################################################################
16226#                                                                              #
16227# Stuff related to Index generation                                            #
16228#                                                                              #
16229#---############################################################################
16230
16231my $index_entries;                 # ref on a hash for the index entries
16232
16233# called during pass_structure
16234sub enter_index_entry($$$$$$$)
16235{
16236    my $prefix = shift;
16237    my $line_nr = shift;
16238    my $entry = shift;
16239    my $place = shift;
16240    my $element = shift;
16241    my $command = shift;
16242    my $region = shift;
16243    unless ($index_prefix_to_name{$prefix})
16244    {
16245        echo_error ("Undefined index command: ${prefix}index", $line_nr);
16246        $entry = '';
16247    }
16248    if (!exists($element->{'tag'}) and !$element->{'footnote'})
16249    {
16250        echo_warn ("Index entry before document: \@${prefix}index $entry", $line_nr);
16251    }
16252    #print STDERR "($region) $key" if $region;
16253    $entry =~ s/\s+$//;
16254    $entry =~ s/^\s*//;
16255    # The $key is mostly usefull for alphabetical sorting.
16256    # beware that an entry beginning with a format will lead to an empty
16257    # key, but with some texi.
16258    # FIXME this should be done later, during formatting.
16259    my $key = remove_texi($entry);
16260    my $id;
16261
16262    my $index_entry_hidden = (($place eq $no_element_associated_place) or $region);
16263    # don't add a specific index target if after a section or the index
16264    # entry is in @copying or the like
16265    unless ($index_entry_hidden)
16266    {
16267        $id = 'IDX' . ++$document_idx_num;
16268    }
16269    my $target = $id;
16270    # entry will later be in @code for code-like index entry. texi stays
16271    # the same.
16272    my $index_entry = {
16273           'entry'    => $entry,
16274           'key'      => $key,
16275           'texi'     => $entry,
16276           'element'  => $element,
16277           'prefix'   => $prefix,
16278           'id'       => $id,
16279           'target'   => $target,
16280           'command'  => $command,
16281    };
16282
16283    print STDERR "# enter \@$command ${prefix}index($key) [$entry] with id $id ($index_entry)\n"
16284        if ($T2H_DEBUG & $DEBUG_INDEX);
16285    if ($entry =~ /^\s*$/)
16286    {
16287        # makeinfo doesn't warn, but texi2dvi breaks.
16288        echo_warn("Empty index entry for \@$command",$line_nr);
16289        # don't add the index entry to the list of index entries used for index
16290        # entry formatting,if the index entry appears in a region like copying
16291        push @index_labels, $index_entry unless $index_entry_hidden;
16292        return;
16293    }
16294    while (exists $index_entries->{$prefix}->{$key})
16295    {
16296        $key .= ' ';
16297    }
16298    $index_entries->{$prefix}->{$key} = $index_entry;
16299    push @$place, $index_entry;
16300    # don't add the index entry to the list of index entries used for index
16301    # entry formatting,if the index entry appears in a region like copying
16302    push @index_labels, $index_entry unless ($index_entry_hidden);
16303}
16304
16305# sort according to cmp if both $a and $b are alphabetical or non alphabetical,
16306# otherwise the alphabetical is ranked first
16307sub by_alpha
16308{
16309    if ($a =~ /^[A-Za-z]/)
16310    {
16311        if ($b =~ /^[A-Za-z]/)
16312        {
16313            return lc($a) cmp lc($b);
16314        }
16315        else
16316        {
16317            return 1;
16318        }
16319    }
16320    elsif ($b =~ /^[A-Za-z]/)
16321    {
16322        return -1;
16323    }
16324    else
16325    {
16326        return lc($a) cmp lc($b);
16327    }
16328}
16329
16330my %indices;                       # hash of indices names containing
16331                                   #[ $pages, $entries ] (page indices and
16332                                   # raw index entries)
16333
16334# return the page and the entries. Cache the result in %indices.
16335sub get_index($;$$)
16336{
16337    my $index_name = shift;
16338    my $line_nr = shift;
16339    my $no_warn = shift;
16340
16341    #return (@{$indices{$index_name}}) if ($indices{$index_name});
16342    return ($indices{$index_name}) if ($indices{$index_name});
16343
16344    unless (exists($index_names{$index_name}))
16345    {
16346        echo_error ("Bad index name: $index_name", $line_nr) unless ($no_warn);
16347        return;
16348    }
16349    # add the index name itself to the index names searched for index
16350    # prefixes. Only those found associated by synindex or syncodeindex are
16351    # already there (unless this code has already been called).
16352    if ($index_names{$index_name}->{'code'})
16353    {
16354        $index_names{$index_name}->{'associated_indices_code'}->{$index_name} = 1;
16355    }
16356    else
16357    {
16358        $index_names{$index_name}->{'associated_indices'}->{$index_name} = 1;
16359    }
16360
16361    # find all the index names associated with the prefixes and then
16362    # all the entries associated with each prefix
16363    my $entries = {};
16364    foreach my $associated_indice(keys %{$index_names{$index_name}->{'associated_indices'}})
16365    {
16366        foreach my $prefix(@{$index_names{$associated_indice}->{'prefix'}})
16367        {
16368            foreach my $key (keys %{$index_entries->{$prefix}})
16369            {
16370                $entries->{$key} = $index_entries->{$prefix}->{$key};
16371            }
16372        }
16373    }
16374
16375    foreach my $associated_indice (keys %{$index_names{$index_name}->{'associated_indices_code'}})
16376    {
16377        unless (exists ($index_names{$index_name}->{'associated_indices'}->{$associated_indice}))
16378        {
16379            foreach my $prefix (@{$index_names{$associated_indice}->{'prefix'}})
16380            {
16381                foreach my $key (keys (%{$index_entries->{$prefix}}))
16382                {
16383                    $entries->{$key} = $index_entries->{$prefix}->{$key};
16384                    # use @code for code style index entry
16385                    $entries->{$key}->{'entry'} = "\@code{$entries->{$key}->{entry}}";
16386                }
16387            }
16388        }
16389    }
16390
16391    return unless %$entries;
16392    $indices{$index_name} = $entries;
16393    return $entries;
16394}
16395
16396# these variables are global, so great care should be taken with
16397# state->{'multiple_state'}, ->{'region'}, ->{'region_pass'} and
16398# {'outside_document'}.
16399my $global_head_num = 0;       # heading index. it is global for the main doc,
16400                               # and taken from the state if in multiple_pass.
16401my $global_foot_num = 0;
16402my $global_relative_foot_num = 0;
16403my @foot_lines = ();           # footnotes
16404my $copying_comment = '';      # comment constructed from text between
16405                               # @copying and @end copying with licence
16406my %acronyms_like = ();        # acronyms or similar commands associated texts
16407                               # the key are the commands, the values are
16408                               # hash references associating shorthands to
16409                               # texts.
16410
16411sub fill_state($)
16412{
16413    my $state = shift;
16414    $state->{'preformatted'} = 0 unless exists($state->{'preformatted'});
16415    $state->{'code_style'} = 0 unless exists($state->{'code_style'});
16416    $state->{'math_style'} = 0 unless exists($state->{'math_style'});
16417    $state->{'keep_texi'} = 0 unless exists($state->{'keep_texi'});
16418    $state->{'keep_nr'} = 0 unless exists($state->{'keep_nr'});
16419    $state->{'detailmenu'} = 0 unless exists($state->{'detailmenu'});     # number of opened detailed menus
16420    $state->{'sec_num'} = 0 unless exists($state->{'sec_num'});
16421    $state->{'paragraph_style'} = [ '' ] unless exists($state->{'paragraph_style'});
16422    $state->{'preformatted_stack'} = [ '' ] unless exists($state->{'preformatted_stack'});
16423    $state->{'menu'} = 0 unless exists($state->{'menu'});
16424    $state->{'command_stack'} = [] unless exists($state->{'command_stack'});
16425    $state->{'quotation_stack'} = [] unless exists($state->{'quotation_stack'});
16426    # if there is no $state->{'element'} the first element is used
16427    if ((!$state->{'element'} or $state->{'element'}->{'before_anything'}) and (@elements_list))
16428    {
16429        $state->{'element'} = $elements_list[0];
16430    }
16431    $state->{'element'} = {'file' => $docu_doc, 'texi' => 'VIRTUAL ELEMENT'} if (!$state->{'element'});
16432        #$state->{'element'} = $elements_list[0] unless ((!@elements_list) or (exists($state->{'element'}) and !$state->{'element'}->{'before_anything'}));
16433}
16434
16435sub do_element_directions ($)
16436{
16437   my $this_element = shift;
16438   #print STDERR "Doing hrefs for $this_element->{'texi'} First ";
16439   $Texi2HTML::HREF{'First'} = href($element_first, $this_element->{'file'});
16440   #print STDERR "Last ";
16441   $Texi2HTML::HREF{'Last'} = href($element_last, $this_element->{'file'});
16442   #print STDERR "Index ";
16443   $Texi2HTML::HREF{'Index'} = href($element_chapter_index, $this_element->{'file'}) if (defined($element_chapter_index));
16444   #print STDERR "Top ";
16445   $Texi2HTML::HREF{'Top'} = href($element_top, $this_element->{'file'});
16446   if ($Texi2HTML::Config::INLINE_CONTENTS)
16447   {
16448      $Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $this_element->{'file'});
16449      $Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $this_element->{'file'});
16450   }
16451   else
16452   {
16453      $Texi2HTML::HREF{'Contents'} = file_target_href($Texi2HTML::THISDOC{'toc_file'}, $this_element->{'file'}, $content_element{'contents'}->{'target'}) if (@{$Texi2HTML::TOC_LINES} and defined($content_element{'contents'}));
16454      $Texi2HTML::HREF{'Overview'} = file_target_href($Texi2HTML::THISDOC{'stoc_file'}, $this_element->{'file'}, $content_element{'shortcontents'}->{'target'}) if (@{$Texi2HTML::OVERVIEW} and defined($content_element{'shortcontents'}));
16455   }
16456   if ($Texi2HTML::THISDOC{'do_about'})
16457   {
16458      $Texi2HTML::HREF{'About'} = file_target_href($docu_about, $this_element->{'file'}, $Texi2HTML::Config::misc_pages_targets{'About'});
16459   }
16460   $Texi2HTML::HREF{'Footnotes'} = file_target_href($docu_foot, $this_element->{'file'}, $Texi2HTML::Config::misc_pages_targets{'Footnotes'});
16461   foreach my $direction (@element_directions)
16462   {
16463      my $elem = $this_element->{$direction};
16464      $Texi2HTML::NODE{$direction} = undef;
16465      $Texi2HTML::HREF{$direction} = undef;
16466      $Texi2HTML::NAME{$direction} = undef;
16467      #print STDERR "$direction \n";
16468      next unless (defined($elem));
16469      if ($elem->{'node'} or $elem->{'external_node'} or !$elem->{'seen'})
16470      {
16471         $Texi2HTML::NODE{$direction} = $elem->{'text'};
16472      }
16473      elsif ($elem->{'with_node'})
16474      {
16475         $Texi2HTML::NODE{$direction} = $elem->{'with_node'}->{'text'};
16476      }
16477      if (!$elem->{'seen'})
16478      {
16479         $Texi2HTML::HREF{$direction} = do_external_href($elem->{'texi'});
16480      }
16481      else
16482      {
16483         $Texi2HTML::HREF{$direction} = href($elem, $this_element->{'file'});
16484      }
16485      $Texi2HTML::NAME{$direction} = $elem->{'text'};
16486      $Texi2HTML::NO_TEXI{$direction} = $elem->{'no_texi'};
16487      $Texi2HTML::SIMPLE_TEXT{$direction} = $elem->{'simple_format'};
16488      #print STDERR "$direction ($this_element->{'texi'}): \n  NO_TEXI: $Texi2HTML::NO_TEXI{$direction}\n  NAME $Texi2HTML::NAME{$direction}\n  NODE $Texi2HTML::NODE{$direction}\n  HREF $Texi2HTML::HREF{$direction}\n\n";
16489   }
16490   #print STDERR "\nDone hrefs for $this_element->{'texi'}\n";
16491}
16492
16493sub open_out_file($)
16494{
16495  my $new_file = shift;
16496  my $do_page_head = 0;
16497  if ($files{$new_file}->{'filehandle'})
16498  {
16499    $Texi2HTML::THISDOC{'FH'} = $files{$new_file}->{'filehandle'};
16500  }
16501  else
16502  {
16503    $Texi2HTML::THISDOC{'FH'} = open_out("$docu_rdir$new_file");
16504#print STDERR "OPEN $docu_rdir$file, $Texi2HTML::THISDOC{'FH'}". scalar($Texi2HTML::THISDOC{'FH'})."\n";
16505    $files{$new_file}->{'filehandle'} = $Texi2HTML::THISDOC{'FH'};
16506    $do_page_head = 1;
16507  }
16508  return $do_page_head;
16509}
16510
16511sub pass_text($$)
16512{
16513    my $doc_lines = shift;
16514    my $doc_numbers = shift;
16515    my %state;
16516    fill_state(\%state);
16517    my @stack;
16518    my $text;
16519    my $doc_nr;
16520    my $in_doc = 0;
16521    my @text =();
16522    my $one_section = 1 if (@elements_list <= 1);
16523
16524    push_state(\%state);
16525
16526    set_special_names();
16527    # We set titlefont only if the titlefont appeared in the top element
16528    if (defined($element_top->{'titlefont'}))
16529    {
16530         $value{'_titlefont'} = $element_top->{'titlefont'};
16531    }
16532
16533    # prepare %Texi2HTML::THISDOC
16534    $Texi2HTML::THISDOC{'command_stack'} = $state{'command_stack'};
16535
16536#    $Texi2HTML::THISDOC{'settitle_texi'} = $value{'_settitle'};
16537    $Texi2HTML::THISDOC{'fulltitle_texi'} = '';
16538    $Texi2HTML::THISDOC{'title_texi'} = '';
16539    foreach my $possible_fulltitle (('_settitle', '_title', '_shorttitlepage', '_titlefont'))
16540    {
16541        if ($value{$possible_fulltitle} ne '')
16542        {
16543            $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{$possible_fulltitle};
16544            last;
16545        }
16546    }
16547#    foreach my $possible_title_texi ($value{'_settitle'}, $Texi2HTML::THISDOC{'fulltitle_texi'})
16548#    {
16549#        if ($possible_title_texi ne '')
16550#        {
16551#            $Texi2HTML::THISDOC{'title_texi'} = $possible_title_texi;
16552#            last;
16553#        }
16554#    }
16555
16556#    $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'};
16557#    $Texi2HTML::THISDOC{'title_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'};
16558    foreach my $texi_cmd (('shorttitlepage', 'settitle', 'author', 'title',
16559           'titlefont', 'subtitle'))
16560    {
16561        $Texi2HTML::THISDOC{$texi_cmd . '_texi'} = $value{'_' . $texi_cmd};
16562    }
16563    foreach my $doc_thing (('shorttitlepage', 'settitle', 'author',
16564           'titlefont', 'subtitle', 'title', 'fulltitle'))
16565    {
16566        my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'};
16567        $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi);
16568        $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} =
16569           remove_texi($thing_texi);
16570        $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} =
16571           simple_format(undef, undef, $thing_texi);
16572    }
16573
16574    # find Top name
16575    my $element_top_text = '';
16576    my $top_no_texi = '';
16577    my $top_simple_format = '';
16578    my $top_name;
16579    if ($element_top and $element_top->{'text'} and (!$node_top or ($element_top ne $node_top)))
16580    {
16581        $element_top_text = $element_top->{'text'};
16582        $top_no_texi = $element_top->{'no_texi'};
16583        $top_simple_format =  $element_top->{'simple_format'};
16584    }
16585    foreach my $possible_top_name ($Texi2HTML::Config::TOP_HEADING,
16586         $element_top_text, $Texi2HTML::THISDOC{'fulltitle'},
16587         #$Texi2HTML::THISDOC{'shorttitle'},
16588         &$I('Top'))
16589    {
16590         if (defined($possible_top_name) and $possible_top_name ne '')
16591         {
16592             $top_name = $possible_top_name;
16593             last;
16594         }
16595    }
16596    foreach my $possible_top_no_texi ($Texi2HTML::Config::TOP_HEADING,
16597         $top_no_texi, $Texi2HTML::THISDOC{'fulltitle_no_texi'},
16598         #$Texi2HTML::THISDOC{'shorttitle_no_texi'},
16599         &$I('Top',{},{'remove_texi' => 1}))
16600    {
16601         if (defined($possible_top_no_texi) and $possible_top_no_texi ne '')
16602         {
16603             $top_no_texi = $possible_top_no_texi;
16604             last;
16605         }
16606    }
16607
16608    foreach my $possible_top_simple_format ($top_simple_format,
16609         $Texi2HTML::THISDOC{'fulltitle_simple_format'},
16610         #$Texi2HTML::THISDOC{'shorttitle_simple_format'},
16611         &$I('Top',{}, {'simple_format' => 1}))
16612    {
16613         if (defined($possible_top_simple_format) and $possible_top_simple_format ne '')
16614         {
16615             $top_simple_format = $possible_top_simple_format;
16616             last;
16617         }
16618    }
16619
16620
16621#    my $top_name = $Texi2HTML::Config::TOP_HEADING || $element_top_text || $Texi2HTML::THISDOC{'title'} || $Texi2HTML::THISDOC{'shorttitle'} || &$I('Top');
16622
16623    if ($Texi2HTML::THISDOC{'fulltitle_texi'} eq '')
16624    {
16625         $Texi2HTML::THISDOC{'fulltitle_texi'} = &$I('Untitled Document',{},
16626           {'keep_texi' => 1});
16627    }
16628    #$Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'settitle_texi'};
16629    #$Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'fulltitle_texi'}
16630    #        if ($Texi2HTML::THISDOC{'title_texi'} eq '');
16631
16632    foreach my $doc_thing (('fulltitle')) # title
16633    {
16634        my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'};
16635        $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi);
16636        $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} =
16637           remove_texi($thing_texi);
16638        $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} =
16639           simple_format(undef, undef, $thing_texi);
16640    }
16641
16642    $Texi2HTML::THISDOC{'program'} = $THISPROG;
16643    $Texi2HTML::THISDOC{'program_homepage'} = $T2H_HOMEPAGE;
16644    $Texi2HTML::THISDOC{'program_authors'} = $T2H_AUTHORS;
16645    $Texi2HTML::THISDOC{'user'} = $T2H_USER;
16646    $Texi2HTML::THISDOC{'user'} = $Texi2HTML::Config::USER if (defined($Texi2HTML::Config::USER));
16647    $Texi2HTML::THISDOC{'authors'} = [] if (!defined($Texi2HTML::THISDOC{'authors'}));
16648    $Texi2HTML::THISDOC{'subtitles'} = [] if (!defined($Texi2HTML::THISDOC{'subtitles'}));
16649    # backward compatibility, titles should go away
16650    $Texi2HTML::THISDOC{'titles'} = [] if (!defined($Texi2HTML::THISDOC{'titles'}));
16651    foreach my $command (('authors', 'subtitles', 'titles'))
16652    {
16653        my $i;
16654        for ($i = 0; $i < $#{$Texi2HTML::THISDOC{$command}} + 1; $i++)
16655        {
16656            chomp ($Texi2HTML::THISDOC{$command}->[$i]);
16657            $Texi2HTML::THISDOC{$command}->[$i] = substitute_line($Texi2HTML::THISDOC{$command}->[$i]);
16658            #print STDERR "$command:$i: $Texi2HTML::THISDOC{$command}->[$i]\n";
16659        }
16660    }
16661
16662    $Texi2HTML::THISDOC{'do_about'} = 1 unless (defined($Texi2HTML::THISDOC{'do_about'}) or $one_section or (not $Texi2HTML::Config::SPLIT and not $Texi2HTML::Config::SECTION_NAVIGATION));
16663
16664    $Texi2HTML::NAME{'First'} = $element_first->{'text'};
16665    $Texi2HTML::NAME{'Last'} = $element_last->{'text'};
16666    $Texi2HTML::NAME{'Top'} = $top_name;
16667    $Texi2HTML::NAME{'Index'} = $element_chapter_index->{'text'} if (defined($element_chapter_index));
16668    $Texi2HTML::NAME{'Index'} = $Texi2HTML::Config::INDEX_CHAPTER if ($Texi2HTML::Config::INDEX_CHAPTER ne '');
16669
16670    $Texi2HTML::NO_TEXI{'First'} = $element_first->{'no_texi'};
16671    $Texi2HTML::NO_TEXI{'Last'} = $element_last->{'no_texi'};
16672    $Texi2HTML::NO_TEXI{'Top'} = $top_no_texi;
16673    $Texi2HTML::NO_TEXI{'Index'} = $element_chapter_index->{'no_texi'} if (defined($element_chapter_index));
16674    $Texi2HTML::SIMPLE_TEXT{'First'} = $element_first->{'simple_format'};
16675    $Texi2HTML::SIMPLE_TEXT{'Last'} = $element_last->{'simple_format'};
16676    $Texi2HTML::SIMPLE_TEXT{'Top'} = $top_simple_format;
16677    $Texi2HTML::SIMPLE_TEXT{'Index'} = $element_chapter_index->{'simple_format'} if (defined($element_chapter_index));
16678
16679    # FIXME we do the regions formatting here, even if they never appear.
16680    # so we should be very carefull to take into accout 'outside_document' to
16681    # avoid messing with information that has to be set in the main document.
16682    # also the error messages will appear even though the corresponding
16683    # texinfo is never used.
16684    my ($region_text, $region_no_texi, $region_simple_format);
16685    ($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('documentdescription');
16686    &$Texi2HTML::Config::documentdescription($region_lines{'documentdescription'},$region_text, $region_no_texi, $region_simple_format);
16687
16688    # do copyright notice inserted in comment at the beginning of the files
16689    ($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('copying');
16690    $copying_comment = &$Texi2HTML::Config::copying_comment($region_lines{'copying'}, $region_text, $region_no_texi, $region_simple_format);
16691
16692    $Texi2HTML::THISDOC{'copying_comment'} = $copying_comment;
16693    # must be after toc_body, but before titlepage
16694    foreach my $command ('contents', 'shortcontents')
16695    {
16696        next if (!defined($content_element{$command}));
16697        my $toc_lines = &$Texi2HTML::Config::inline_contents(undef, $command, $content_element{$command});
16698        @{$Texi2HTML::THISDOC{'inline_contents'}->{$command}} = @$toc_lines if (defined($toc_lines));
16699    }
16700
16701    ($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('titlepage');
16702
16703    &$Texi2HTML::Config::titlepage($region_lines{'titlepage'}, $region_text, $region_no_texi, $region_simple_format);
16704
16705    &$Texi2HTML::Config::init_out();
16706
16707    ############################################################################
16708    # print frame and frame toc file
16709    #
16710    if ( $Texi2HTML::Config::FRAMES )
16711    {
16712        my $FH = open_out($docu_frame_file);
16713        print STDERR "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
16714        &$Texi2HTML::Config::print_frame($FH, $docu_toc_frame_file, $docu_top_file);
16715        close_out($FH, $docu_frame_file);
16716
16717        $FH = open_out($docu_toc_frame_file);
16718        print STDERR "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
16719        &$Texi2HTML::Config::print_toc_frame($FH, $Texi2HTML::OVERVIEW);
16720        close_out($FH, $docu_toc_frame_file);
16721    }
16722
16723    texinfo_initialization(2);
16724
16725
16726    ############################################################################
16727    # Start processing the document
16728    #
16729
16730    #my $FH;
16731    my $line_nr;
16732    my $current_file;
16733    my $first_section = 0; # 1 if it is the first section of a page
16734    my $previous_is_top = 0; # 1 if it is the element following the top element
16735
16736    my $cline;
16737    # this is true for the state that goes through the document
16738    $state{'inside_document'} = 1;
16739    while (@$doc_lines)
16740    {
16741        $cline = shift @$doc_lines;
16742        my $chomped_line = $cline;
16743        if (!chomp($chomped_line) and @$doc_lines)
16744        { # if the line has no end of line it is concatenated with the next
16745             $doc_lines->[0] = $cline . $doc_lines->[0];
16746             next;
16747        }
16748        $line_nr = shift (@$doc_numbers);
16749        #print STDERR "$line_nr->{'file_name'}($line_nr->{'macro'},$line_nr->{'line_nr'}) $cline" if ($line_nr);
16750	#print STDERR "PASS_TEXT: $cline";
16751	#dump_stack(\$text, \@stack, \%state);
16752
16753        # make sure the current state from here is $Texi2HTML::THIS_ELEMENT
16754        # in case it was set by the user.
16755        $state{'element'} = $Texi2HTML::THIS_ELEMENT if (defined($Texi2HTML::THIS_ELEMENT));
16756        if (!$state{'raw'} and !$state{'verb'})
16757        {
16758            my $tag = '';
16759            $tag = $1 if ($cline =~ /^\@(\w+)/);
16760            if ($tag eq 'setfilename' and $Texi2HTML::Config::IGNORE_BEFORE_SETFILENAME)
16761            {
16762                @{$Texi2HTML::THIS_SECTION} = ();
16763            }
16764
16765            if (($tag eq 'node') or (defined($sec2level{$tag}) and ($tag !~ /heading/)))
16766            {
16767                if (@stack or (defined($text) and $text ne ''))
16768                {# in pass text node and section shouldn't appear in formats
16769			#print STDERR "close_stack before \@$tag\n";
16770			#print STDERR "text!$text%" if (! @stack);
16771                    close_stack(\$text, \@stack, \%state, $line_nr);
16772                    push @{$Texi2HTML::THIS_SECTION}, $text;
16773                    $text = '';
16774                }
16775                $state{'sec_num'}++ if ($sec2level{$tag} and ($tag ne 'top'));
16776                my $new_element;
16777                my $current_element;
16778
16779                # handle node and structuring elements
16780                $current_element = shift (@all_elements);
16781                ########################## begin debug section
16782                if ($current_element->{'node'})
16783                {
16784                    print STDERR 'NODE ' . "$current_element->{'texi'}($current_element->{'file'})" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
16785                    print STDERR "($current_element->{'section_ref'}->{'texi'})" if ($current_element->{'section_ref'} and ($T2H_DEBUG & $DEBUG_ELEMENTS));
16786                }
16787                else
16788                {
16789                    print STDERR 'SECTION ' . $current_element->{'texi'} if ($T2H_DEBUG & $DEBUG_ELEMENTS);
16790                }
16791                print STDERR ": $cline" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
16792                ########################## end debug section
16793
16794                # The element begins a new section if there is no previous
16795                # or the reference element is not the same
16796                #if (!$Texi2HTML::THIS_ELEMENT or (defined($current_element->{'element_ref'}) and $current_element->{'element_ref'} ne $Texi2HTML::THIS_ELEMENT))
16797                if (defined($current_element->{'element_ref'}) and (!$Texi2HTML::THIS_ELEMENT or ($current_element->{'element_ref'} ne $Texi2HTML::THIS_ELEMENT)))
16798                {
16799                    $new_element = $current_element->{'element_ref'};
16800
16801                    ########################### debug
16802                    my $old = 'NO_OLD';
16803                    $old = $Texi2HTML::THIS_ELEMENT->{'texi'} if (defined($Texi2HTML::THIS_ELEMENT));
16804                    print STDERR "NEW: $new_element->{'texi'}, OLD: $old\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
16805                    # print the element that just finished
16806                    ########################### end debug
16807                    if ($Texi2HTML::THIS_ELEMENT)
16808                    {
16809                        finish_element($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, $new_element, $first_section);
16810                        $first_section = 0;
16811                        $previous_is_top = 0 if (!$Texi2HTML::THIS_ELEMENT->{'top'});
16812                        @{$Texi2HTML::THIS_SECTION} = ();
16813                    }
16814                    else
16815                    {
16816                        print STDERR "# Writing elements:" if ($T2H_VERBOSE);
16817                        if ($Texi2HTML::Config::IGNORE_PREAMBLE_TEXT)
16818                        {
16819                             @{$Texi2HTML::THIS_SECTION} = ();
16820                        }
16821                        # remove empty for the first document lines
16822                        shift @{$Texi2HTML::THIS_SECTION} while (@{$Texi2HTML::THIS_SECTION} and ($Texi2HTML::THIS_SECTION->[0] =~ /^\s*$/));
16823                    }
16824                    # begin new element
16825                    #my $previous_file;
16826                    #$previous_file = $Texi2HTML::THIS_ELEMENT->{'file'} if (defined($Texi2HTML::THIS_ELEMENT));
16827                    $Texi2HTML::THIS_ELEMENT = $new_element;
16828                    $state{'element'} = $Texi2HTML::THIS_ELEMENT;
16829
16830                    do_element_directions($Texi2HTML::THIS_ELEMENT);
16831                    $files{$Texi2HTML::THIS_ELEMENT->{'file'}}->{'counter'}--;
16832                    #if (!defined($previous_file) or ($Texi2HTML::THIS_ELEMENT->{'file'} ne $previous_file))
16833                    if (!defined($current_file) or ($Texi2HTML::THIS_ELEMENT->{'file'} ne $current_file))
16834                    {
16835                        $current_file = $Texi2HTML::THIS_ELEMENT->{'file'};
16836                        print STDERR "\n" if ($T2H_VERBOSE and !$T2H_DEBUG);
16837                        print STDERR "# Writing to $docu_rdir$current_file " if $T2H_VERBOSE;
16838                        my $do_page_head = open_out_file($current_file);
16839                        if ($Texi2HTML::THIS_ELEMENT->{'top'})
16840                        {
16841                             &$Texi2HTML::Config::print_Top_header($Texi2HTML::THISDOC{'FH'}, $do_page_head);
16842                             $previous_is_top = 1;
16843                        }
16844                        else
16845                        {
16846                             &$Texi2HTML::Config::print_page_head($Texi2HTML::THISDOC{'FH'}) if ($do_page_head);
16847                             &$Texi2HTML::Config::print_chapter_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if $Texi2HTML::Config::SPLIT eq 'chapter';
16848                             &$Texi2HTML::Config::print_section_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if $Texi2HTML::Config::SPLIT eq 'section';
16849                        }
16850                        $first_section = 1;
16851                    }
16852                    print STDERR "." if ($T2H_VERBOSE);
16853                    print STDERR "\n" if ($T2H_DEBUG);
16854                }
16855
16856                my $cmd_line = $cline;
16857                $cmd_line =~ s/\@$tag\s*//;
16858                my $heading_formatted = &$Texi2HTML::Config::element_heading($current_element, $tag, $cmd_line, substitute_line($cmd_line), undef, $one_section, $current_element->{'this'}, $first_section, $current_element->{'top'}, $previous_is_top, $cline, $current_element->{'id'}, $new_element);
16859                push @{$Texi2HTML::THIS_SECTION}, $heading_formatted if (defined($heading_formatted) and ($heading_formatted ne ''));
16860                next;
16861            }
16862            elsif ($tag eq 'printindex')
16863            {
16864                $cline =~ s/\s+(\w+)\s*//;
16865                my $name = $1;
16866                close_paragraph(\$text, \@stack, \%state);
16867                if (!@stack)
16868                {
16869                    push @{$Texi2HTML::THIS_SECTION}, $text;
16870                    $text = '';
16871                }
16872                add_prev(\$text, \@stack, &$Texi2HTML::Config::printindex($name));
16873                if (!@stack)
16874                {
16875                    push @{$Texi2HTML::THIS_SECTION}, $text;
16876                    $text = '';
16877                }
16878                begin_paragraph (\@stack, \%state) if ($state{'preformatted'});
16879                next;
16880            }
16881            elsif (($tag eq 'contents') or ($tag eq 'summarycontents') or ($tag eq 'shortcontents'))
16882            {
16883                my $element_tag = $tag;
16884                $element_tag = 'shortcontents' if ($element_tag ne 'contents');
16885                # at that point the content_element is defined for sure since
16886                # we already saw the tag
16887                if ($Texi2HTML::Config::INLINE_CONTENTS and !$content_element{$element_tag}->{'aftertitlepage'})
16888                {
16889                    if (@stack or (defined($text) and $text ne ''))
16890                    {# in pass text contents  shouldn't appear in formats
16891                        close_stack(\$text, \@stack, \%state, $line_nr);
16892                        push @{$Texi2HTML::THIS_SECTION}, $text;
16893                        $text = '';
16894                    }
16895                    my $toc_lines = &$Texi2HTML::Config::inline_contents($Texi2HTML::THISDOC{'FH'}, $tag, $content_element{$element_tag});
16896                    push (@{$Texi2HTML::THIS_SECTION}, @$toc_lines) if (defined($toc_lines)) ;
16897                }
16898                next unless (exists($Texi2HTML::Config::misc_command{$tag}) and $Texi2HTML::Config::misc_command{$tag}->{'keep'});
16899            }
16900        }
16901        scan_line($cline, \$text, \@stack, \%state, $line_nr);
16902	#print STDERR "after scan_line: $cline";
16903	#dump_stack(\$text, \@stack, \%state);
16904        next if (@stack);
16905        if ($text ne '' )
16906        {
16907            push @{$Texi2HTML::THIS_SECTION}, $text;
16908            $text = '';
16909        }
16910    }
16911    if (@stack)
16912    {# close stack at the end of pass text
16913        close_stack(\$text, \@stack, \%state, $line_nr);
16914    }
16915    if (defined($text))
16916    {
16917        push @{$Texi2HTML::THIS_SECTION}, $text;
16918    }
16919    print STDERR "\n" if ($T2H_VERBOSE);
16920
16921    # if no sections, then simply print document as is
16922    if ($one_section)
16923    {
16924        # may happen if there are 0 sections
16925        if (! defined($Texi2HTML::THISDOC{'FH'}))
16926        {
16927          open_out_file($docu_doc);
16928          &$Texi2HTML::Config::print_page_head($Texi2HTML::THISDOC{'FH'});
16929        }
16930        if (@foot_lines)
16931        {
16932            &$Texi2HTML::Config::foot_section (\@foot_lines);
16933            push @{$Texi2HTML::THIS_SECTION}, @foot_lines;
16934        }
16935        print STDERR "# Write the section $Texi2HTML::THIS_ELEMENT->{'texi'}\n" if ($T2H_VERBOSE);
16936        &$Texi2HTML::Config::one_section($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT);
16937        close_out($Texi2HTML::THISDOC{'FH'});
16938        # no misc element is done
16939        return;
16940    }
16941
16942    finish_element ($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, undef, $first_section);
16943
16944    ############################################################################
16945    # Print ToC, Overview, Footnotes
16946    #
16947    foreach my $direction (@element_directions)
16948    {
16949        $Texi2HTML::HREF{$direction} = undef;
16950        delete $Texi2HTML::HREF{$direction};
16951        # it is better to undef in case the references to these hash entries
16952        # are used, as if deleted, the
16953        # references are still refering to the old, undeleted element
16954        # (we could do both)
16955        $Texi2HTML::NAME{$direction} = undef;
16956        $Texi2HTML::NO_TEXI{$direction} = undef;
16957        $Texi2HTML::SIMPLE_TEXT{$direction} = undef;
16958        $Texi2HTML::NODE{$direction} = undef;
16959
16960        $Texi2HTML::THIS_ELEMENT = undef;
16961    }
16962    my $about_body;
16963    $about_body = &$Texi2HTML::Config::about_body();
16964    # @foot_lines is emptied in finish_element if SEPARATED_FOOTNOTES
16965    my %misc_page_infos = (
16966       'Footnotes' => { 'file' => $docu_foot_file,
16967          'relative_file' => $docu_foot,
16968          'process' => $Texi2HTML::Config::print_Footnotes,
16969          'section' => \@foot_lines },
16970       'Contents' => { 'file' => $docu_toc_file,
16971           'relative_file' => $docu_toc,
16972           'process' => $Texi2HTML::Config::print_Toc,
16973           'section' => $Texi2HTML::TOC_LINES },
16974       'Overview' => { 'file' => $docu_stoc_file,
16975           'relative_file' => $docu_stoc,
16976           'process' => $Texi2HTML::Config::print_Overview,
16977           'section' => $Texi2HTML::OVERVIEW },
16978       'About' => { 'file' => $docu_about_file,
16979           'relative_file' => $docu_about,
16980            'process' => $Texi2HTML::Config::print_About,
16981            'section' => [$about_body] }
16982    );
16983    $misc_page_infos{'Footnotes'}->{'do'} = 1 if (@foot_lines);
16984    $misc_page_infos{'Contents'}->{'do'} = 1 if
16985       (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::Config::INLINE_CONTENTS);
16986    $misc_page_infos{'Overview'}->{'do'} = 1 if
16987       (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::Config::INLINE_CONTENTS);
16988    #FIXME: ... and $Texi2HTML::THISDOC{'do_about'}) ?
16989    $misc_page_infos{'About'}->{'do'} = 1 if ($about_body);
16990
16991    foreach my $misc_page('Footnotes', 'Contents', 'Overview', 'About')
16992    {
16993        next unless ($misc_page_infos{$misc_page}->{'do'});
16994        my $file = $misc_page_infos{$misc_page}->{'file'};
16995        my $relative_file = $misc_page_infos{$misc_page}->{'relative_file'};
16996        print STDERR "# writing $misc_page in $file\n" if $T2H_VERBOSE;
16997        my $saved_FH;
16998        my $open_new = 0;
16999        if ($relative_file ne $docu_doc)
17000        {
17001            $saved_FH = $Texi2HTML::THISDOC{'FH'};
17002            # FIXME the file may have the same name than another file. Use
17003            # open_out_file?
17004            $Texi2HTML::THISDOC{'FH'} = open_out ($file);
17005            print STDERR "# Opening $file for $misc_page\n" if $T2H_VERBOSE;
17006            $open_new = 1;
17007        }
17008        else
17009        {
17010            print STDERR "# writing $misc_page in current file\n" if $T2H_VERBOSE;
17011        }
17012        foreach my $href_page (keys(%misc_page_infos))
17013        {
17014            $Texi2HTML::HREF{$href_page} = file_target_href(
17015               $misc_page_infos{$href_page}->{'relative_file'}, $relative_file,
17016               $Texi2HTML::Config::misc_pages_targets{$href_page})
17017                 if ($misc_page_infos{$href_page}->{'do'});
17018        }
17019        #print STDERR "Doing hrefs for $misc_page First ";
17020        $Texi2HTML::HREF{'First'} = href($element_first, $relative_file);
17021        #print STDERR "Last ";
17022        $Texi2HTML::HREF{'Last'} = href($element_last, $relative_file);
17023        #print STDERR "Index ";
17024        $Texi2HTML::HREF{'Index'} = href($element_chapter_index, $relative_file) if (defined($element_chapter_index));
17025        #print STDERR "Top ";
17026        $Texi2HTML::HREF{'Top'} = href($element_top, $relative_file);
17027        if ($Texi2HTML::Config::INLINE_CONTENTS)
17028        {
17029            $Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $relative_file);
17030            $Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $relative_file);
17031        }
17032        $Texi2HTML::HREF{$misc_page} = '#' . $Texi2HTML::Config::misc_pages_targets{$misc_page};
17033        $Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{$misc_page};
17034        $Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{$misc_page};
17035        $Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{$misc_page};
17036        $Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{$misc_page};
17037        $Texi2HTML::THIS_SECTION = $misc_page_infos{$misc_page}->{'section'}
17038            if defined($misc_page_infos{$misc_page}->{'section'});
17039        &{$misc_page_infos{$misc_page}->{'process'}}($Texi2HTML::THISDOC{'FH'}, $open_new, $misc_page);
17040
17041        if ($open_new)
17042        {
17043            close_out($Texi2HTML::THISDOC{'FH'}, $file);
17044            $Texi2HTML::THISDOC{'FH'} = $saved_FH;
17045        }
17046    }
17047
17048    unless ($Texi2HTML::Config::SPLIT)
17049    {
17050        &$Texi2HTML::Config::print_page_foot($Texi2HTML::THISDOC{'FH'});
17051        close_out ($Texi2HTML::THISDOC{'FH'});
17052    }
17053    pop_state();
17054}
17055
17056# print section, close file if needed.
17057sub finish_element($$$$)
17058{
17059    my $FH = shift;
17060    my $element = shift;
17061    my $new_element = shift;
17062    my $first_section = shift;
17063#print STDERR "FINISH_ELEMENT($FH)($element->{'texi'})[$element->{'file'}] counter $files{$element->{'file'}}->{'counter'}\n";
17064
17065    # handle foot notes
17066    if ($Texi2HTML::Config::SPLIT and scalar(@foot_lines)
17067        and !$Texi2HTML::Config::SEPARATED_FOOTNOTES
17068        and  (! $new_element or
17069        ($element and ($new_element->{'file'} ne $element->{'file'})))
17070       )
17071    {
17072        if ($files{$element->{'file'}}->{'counter'})
17073        {# there are other elements in that page we are not on its foot
17074            $files{$element->{'file'}}->{'relative_foot_num'}
17075               = $global_relative_foot_num;
17076            push @{$files{$element->{'file'}}->{'foot_lines'}},
17077                @foot_lines;
17078        }
17079        else
17080        {# we output the footnotes as we are at the file end
17081             unshift @foot_lines, @{$files{$element->{'file'}}->{'foot_lines'}};
17082             &$Texi2HTML::Config::foot_section (\@foot_lines);
17083             push @{$Texi2HTML::THIS_SECTION}, @foot_lines;
17084        }
17085        if ($new_element)
17086        {
17087            $global_relative_foot_num =
17088               $files{$new_element->{'file'}}->{'relative_foot_num'};
17089        }
17090        @foot_lines = ();
17091    }
17092    if ($element->{'top'})
17093    {
17094        my $top_file = $docu_top_file;
17095        #print STDERR "TOP $element->{'texi'}, @{$Texi2HTML::THIS_SECTION}\n";
17096        print STDERR "# Doing element top\n"
17097           if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17098        print STDERR "[Top]" if ($T2H_VERBOSE);
17099        $Texi2HTML::HREF{'Top'} = href($element_top, $element->{'file'});
17100        &$Texi2HTML::Config::print_Top($FH, $element->{'titlefont'}, $element);
17101        my $end_page = 0;
17102        if ($Texi2HTML::Config::SPLIT)
17103        {
17104            if (!$files{$element->{'file'}}->{'counter'})
17105            {
17106                $end_page = 1;
17107            }
17108        }
17109        &$Texi2HTML::Config::print_Top_footer($FH, $end_page, $element);
17110        close_out($FH, $top_file) if ($end_page);
17111    }
17112    else
17113    {
17114        print STDERR "# do element $element->{'texi'}\n"
17115           if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17116        &$Texi2HTML::Config::print_section($FH, $first_section, 0, $element);
17117        ################# debug
17118        my $new_elem_file = 'NO ELEM';
17119        $new_elem_file = $new_element->{'file'} if (defined($new_element));
17120        print STDERR "# FILES new: $new_elem_file old: $element->{'file'}\n"
17121           if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17122        ################# end debug
17123        if (defined($new_element) and ($new_element->{'file'} ne $element->{'file'}))
17124        {
17125            print STDERR "# End of section with change in file\n"
17126                 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17127             if (!$files{$element->{'file'}}->{'counter'})
17128             {
17129                 &$Texi2HTML::Config::print_chapter_footer($FH, $element) if ($Texi2HTML::Config::SPLIT eq 'chapter');
17130                 &$Texi2HTML::Config::print_section_footer($FH, $element) if ($Texi2HTML::Config::SPLIT eq 'section');
17131                 print STDERR "# Close file after $element->{'texi'}\n"
17132                     if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17133                 &$Texi2HTML::Config::print_page_foot($FH);
17134                 close_out($FH);
17135             }
17136             else
17137             {
17138                 print STDERR "# Counter $files{$element->{'file'}}->{'counter'} ne 0, file $element->{'file'}\n"
17139                     if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17140             }
17141        }
17142        elsif (!defined($new_element))
17143        {
17144            print STDERR "# End of last section\n"
17145                 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17146            if ($Texi2HTML::Config::SPLIT)
17147            { # end of last splitted section
17148                &$Texi2HTML::Config::print_chapter_footer($FH, $element) if ($Texi2HTML::Config::SPLIT eq 'chapter');
17149                &$Texi2HTML::Config::print_section_footer($FH, $element) if ($Texi2HTML::Config::SPLIT eq 'section');
17150                &$Texi2HTML::Config::print_page_foot($FH);
17151                close_out($FH);
17152            }
17153            else
17154            { # end of last unsplit section
17155                &$Texi2HTML::Config::end_section($FH, 1, $element);
17156            }
17157        }
17158        elsif ($new_element->{'top'})
17159        {
17160            print STDERR "# Section followed by Top\n"
17161                     if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17162            &$Texi2HTML::Config::end_section($FH, 1, $element);
17163        }
17164        else
17165        { # end of section followed by another one
17166            print STDERR "# Section followed by another one\n"
17167                     if ($T2H_DEBUG & $DEBUG_ELEMENTS);
17168            &$Texi2HTML::Config::end_section($FH, 0, $element);
17169        }
17170    }
17171}
17172
17173# write to files with name the node name for cross manual references.
17174sub do_node_files()
17175{
17176    foreach my $key (keys(%nodes))
17177    {
17178        my $node = $nodes{$key};
17179        next unless ($node->{'node_file'});
17180        my $redirection_file = $docu_doc;
17181        $redirection_file = $node->{'file'} if ($Texi2HTML::Config::SPLIT);
17182        if (!$redirection_file)
17183        {
17184             print STDERR "Bug: file for redirection for `$node->{'texi'}' don't exist\n" unless ($novalidate or !$node->{'seen'});
17185             next;
17186        }
17187        next if ($redirection_file eq $node->{'node_file'});
17188        my $file = "${docu_rdir}$node->{'node_file'}";
17189        $Texi2HTML::NODE{'This'} = $node->{'text'};
17190        $Texi2HTML::NO_TEXI{'This'} = $node->{'no_texi'};
17191        $Texi2HTML::SIMPLE_TEXT{'This'} = $node->{'simple_format'};
17192        $Texi2HTML::NAME{'This'} = $node->{'text'};
17193        $Texi2HTML::HREF{'This'} = "$node->{'file'}#$node->{'id'}";
17194        my $NODEFILE = open_out ($file);
17195        &$Texi2HTML::Config::print_redirection_page ($NODEFILE);
17196        close $NODEFILE || die "$ERROR: Can't close $file: $!\n";
17197    }
17198}
17199
17200#+++############################################################################
17201#                                                                              #
17202# Low level functions                                                          #
17203#                                                                              #
17204#---############################################################################
17205
17206sub locate_include_file($)
17207{
17208    my $file = shift;
17209
17210    # APA: Don't implicitely search ., to conform with the docs!
17211    # return $file if (-e $file && -r $file);
17212    foreach my $dir (@Texi2HTML::Config::INCLUDE_DIRS)
17213    {
17214        return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file");
17215    }
17216    return undef;
17217}
17218
17219sub open_file($$)
17220{
17221    my $name = shift;
17222#    my $line_number = shift;
17223    my $macro = shift;
17224
17225    my $line_number;
17226    my $input_spool;
17227
17228    local *FH;
17229    if (open(*FH, "<$name"))
17230    {
17231        if (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and $Texi2HTML::Config::USE_UNICODE)
17232        {
17233            binmode(*FH, ":encoding($Texi2HTML::THISDOC{'IN_ENCODING'})");
17234        }
17235        my $file = { 'fh' => *FH,
17236           'input_spool' => { 'spool' => [],
17237                              'macro' => '' },
17238           'name' => $name,
17239           'line_nr' => 0 };
17240        unshift(@fhs, $file);
17241        $input_spool = $file->{'input_spool'};
17242        $line_number->{'file_name'} = $name;
17243        $line_number->{'line_nr'} = 1;
17244        $line_number->{'macro'} = $macro;
17245    }
17246    else
17247    {
17248        warn "$ERROR Can't read file $name: $!\n";
17249    }
17250    return ($line_number, $input_spool);
17251}
17252
17253sub open_out($)
17254{
17255    my $file = shift;
17256    local *FILE;
17257#print STDERR "open_out $file $Texi2HTML::THISDOC{'OUT_ENCODING'}\n";
17258    if ($file eq '-')
17259    {
17260        binmode(STDOUT, ":encoding($Texi2HTML::THISDOC{'OUT_ENCODING'})") if (defined($Texi2HTML::THISDOC{'OUT_ENCODING'}) and $Texi2HTML::Config::USE_UNICODE);
17261        return \*STDOUT;
17262    }
17263
17264    unless (open(FILE, ">$file"))
17265    {
17266        die "$ERROR Can't open $file for writing: $!\n";
17267    }
17268    if (defined($Texi2HTML::THISDOC{'OUT_ENCODING'}) and $Texi2HTML::Config::USE_UNICODE)
17269    {
17270        if ($Texi2HTML::THISDOC{'OUT_ENCODING'} eq 'utf8' or $Texi2HTML::THISDOC{'OUT_ENCODING'} eq 'utf-8-strict')
17271        {
17272            binmode(FILE, ':utf8');
17273        }
17274	else
17275        {
17276            binmode(FILE, ':bytes');
17277        }
17278        binmode(FILE, ":encoding($Texi2HTML::THISDOC{'OUT_ENCODING'})");
17279    }
17280    return *FILE;
17281}
17282
17283# FIXME not used when split
17284sub close_out($;$)
17285{
17286    my $FH = shift;
17287    my $file = shift;
17288    $file = '' if (!defined($file));
17289    return if ($file eq '-');
17290#print STDERR "close_out $file\n";
17291    close ($FH) || die "$ERROR: Error occurred when closing $file: $!\n";
17292}
17293
17294sub next_line($$)
17295{
17296    my $line_number = shift;
17297    my $input_spool;
17298    while (@fhs)
17299    {
17300        my $file = $fhs[0];
17301        $line_number->{'file_name'} = $file->{'name'};
17302        $input_spool = $file->{'input_spool'};
17303        if (@{$input_spool->{'spool'}})
17304        {
17305             $line_number->{'macro'} = $file->{'input_spool'}->{'macro'};
17306             $line_number->{'line_nr'} = $file->{'line_nr'};
17307             my $line = shift(@{$input_spool->{'spool'}});
17308             print STDERR "# unspooling $line" if ($T2H_DEBUG & $DEBUG_MACROS);
17309             return($line, $input_spool);
17310        }
17311        else
17312        {
17313             $file->{'input_spool'}->{'macro'} = '';
17314             $line_number->{'macro'} = '';
17315        }
17316        my $fh = $file->{'fh'};
17317        no strict "refs";
17318        my $line = <$fh>;
17319        use strict "refs";
17320        my $chomped_line = $line;
17321        $file->{'line_nr'}++ if (defined($line) and chomp($chomped_line));
17322        $line_number->{'line_nr'} = $file->{'line_nr'};
17323        return($line, $input_spool) if (defined($line));
17324        no strict "refs";
17325        close($fh);
17326        use strict "refs";
17327        shift(@fhs);
17328    }
17329    return(undef, $input_spool);
17330}
17331
17332# echo a warning
17333sub echo_warn($;$)
17334{
17335    my $text = shift;
17336    chomp ($text);
17337    my $line_number = shift;
17338    warn "$WARN $text " . format_line_number($line_number) . "\n";
17339}
17340
17341my $error_nrs = 0;
17342sub echo_error($;$)
17343{
17344    my $text = shift;
17345    chomp ($text);
17346    my $line_number = shift;
17347    warn "$ERROR $text " . format_line_number($line_number) . "\n";
17348    $error_nrs ++;
17349    die "Max error number exceeded\n" if ($error_nrs >= $Texi2HTML::Config::ERROR_LIMIT);
17350}
17351
17352sub format_line_number($)
17353{
17354    my $line_number = shift;
17355    my $macro_text = '';
17356    #$line_number = undef;
17357    return '' unless (defined($line_number));
17358    $macro_text = " in \@$line_number->{'macro'}" if ($line_number->{'macro'} ne '');
17359    my $file_text = '(';
17360    $file_text = "(in $line_number->{'file_name'} " if ($line_number->{'file_name'} ne $Texi2HTML::THISDOC{'input_file_name'});
17361    return "${file_text}l. $line_number->{'line_nr'}" . $macro_text . ')';
17362}
17363
17364# to debug, dump the result of pass_texi and pass_structure in a file
17365sub dump_texi($$;$$)
17366{
17367    my $lines = shift;
17368    my $pass = shift;
17369    my $numbers = shift;
17370    my $file = shift;
17371    $file = "$docu_rdir$docu_name" . ".pass$pass" if (!defined($file));
17372    my $FH = open_out($file);
17373    print STDERR "# Dump texi\n" if ($T2H_VERBOSE);
17374    my $index = 0;
17375    foreach my $line (@$lines)
17376    {
17377        my $number_information = '';
17378        my $chomped_line = $line;
17379        # if defined, it means that an output of the file is asked for
17380        if (defined($numbers))
17381        {
17382           my $basefile = $numbers->[$index]->{'file_name'};
17383           $basefile = 'no file' if (!defined($basefile));
17384           $basefile =~ s|.*/||;
17385           my $macro_name = $numbers->[$index]->{'macro'};
17386           $macro_name = '' if (!defined($macro_name));
17387           my $line_number = $numbers->[$index]->{'line_nr'};
17388           $line_number = '' if (!defined($line_number));
17389           $number_information = "${basefile}($macro_name,$line_number) ";
17390        }
17391        print $FH "${number_information}$line";
17392        $index++ if (chomp($chomped_line));
17393    }
17394    close_out ($FH, $file);
17395}
17396
17397
17398# return next tag on the line
17399sub next_tag($)
17400{
17401    my $line = shift;
17402    # macro_regexp
17403    if ($line =~ /^\s*\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])/o or $line =~ /^\s*\@([a-zA-Z][\w-]*)([\s\{\}\@])/ or $line =~ /^\s*\@([a-zA-Z][\w-]*)$/)
17404    {
17405        return ($1);
17406    }
17407    return '';
17408}
17409
17410sub next_end_tag($)
17411{
17412    my $line = shift;
17413    if ($line =~ /^\s*\@end\s+([a-zA-Z][\w-]*)/)
17414    {
17415        return $1;
17416    }
17417    return '';
17418}
17419
17420sub next_tag_or_end_tag($)
17421{
17422    my $line = shift;
17423    my $next_tag = next_tag($line);
17424    return $next_tag if (defined($next_tag) and $next_tag ne '');
17425    return next_end_tag($line);
17426}
17427
17428sub top_stack($;$)
17429{
17430    my $stack = shift;
17431    my $ignore_para = shift;
17432
17433    my $index = scalar (@$stack);
17434    return undef unless ($index);
17435
17436    return $stack->[-1] unless ($ignore_para);
17437    if ($ignore_para == 1)
17438    {
17439       if (exists($stack->[-1]->{'format'}) and ($stack->[-1]->{'format'} eq 'paragraph' or $stack->[-1]->{'format'} eq 'preformatted'))
17440       {
17441          if (exists($stack->[-2]))
17442          {
17443              return $stack->[-2];
17444          }
17445          else
17446          {
17447              return undef;
17448          }
17449       }
17450       else
17451       {
17452          return $stack->[-1];
17453       }
17454    }
17455    else
17456    {
17457        while ($index and
17458          (
17459           (exists($stack->[$index-1]->{'format'})
17460            and ($stack->[$index-1]->{'format'} eq 'paragraph' or $stack->[$index-1]->{'format'} eq 'preformatted'))
17461           or (exists($stack->[$index-1]->{'style'}))
17462          ))
17463       {
17464           $index--;
17465       }
17466    }
17467    return undef unless ($index);
17468    return $stack->[$index-1];
17469}
17470
17471# return the next element with balanced {}
17472sub next_bracketed($$;$)
17473{
17474    my $line = shift;
17475    my $line_nr = shift;
17476    my $report = shift;
17477    my $opened_braces = 0;
17478    my $result = '';
17479    my $spaces;
17480#print STDERR "next_bracketed  $line";
17481    if ($line =~ /^(\s*)$/)
17482    {
17483        return ('','',$1);
17484    }
17485    while ($line !~ /^\s*$/)
17486    {
17487#print STDERR "next_bracketed($opened_braces): $result !!! $line";
17488        if (!$opened_braces)
17489        { # beginning of item
17490            $line =~ s/^(\s*)//;
17491            $spaces = $1;
17492            #if ($line =~ s/^([^\{\}\s]+)//)
17493            if ($line =~ s/^([^\{\}]+?)(\s+)/$2/ or $line =~ s/^([^\{\}]+?)$//)
17494            {
17495                $result = $1;
17496                $result =~ s/\s*$//;
17497                return ($result, $line, $spaces);
17498            }
17499            elsif ($line =~ s/^([^\{\}]+?)([\{\}])/$2/)
17500            {
17501                $result = $1;
17502            }
17503        }
17504        elsif($line =~ s/^([^\{\}]+)//)
17505        {
17506            $result .= $1;
17507        }
17508        if ($line =~ s/^([\{\}])//)
17509        {
17510            my $brace = $1;
17511            $opened_braces++ if ($brace eq '{');
17512            $opened_braces-- if ($brace eq '}');
17513
17514            if ($opened_braces < 0)
17515            {
17516                echo_error("too much '}' in specification", $line_nr) if ($report);
17517                $opened_braces = 0;
17518                #next;
17519            }
17520            $result .= $brace;
17521            return ($result, $line, $spaces) if ($opened_braces == 0);
17522        }
17523    }
17524    if ($opened_braces)
17525    {
17526        echo_error("'{' not closed in specification", $line_nr) if ($report);
17527        return ($result, '', $spaces);
17528        #return ($result . ( '}' x $opened_braces), '', $spaces);
17529    }
17530    print STDERR "BUG: at the end of next_bracketed\n";
17531    return undef;
17532}
17533
17534# def prams are also split at @-commands if not in brackets
17535sub next_def_param($$;$)
17536{
17537    my $line = shift;
17538    my $line_nr = shift;
17539    my $report = shift;
17540    my ($item, $spaces);
17541    ($item, $line, $spaces) = next_bracketed($line, $line_nr, $report);
17542    return ($item, $line, $spaces) if (!defined($item));
17543    if ($item =~ /^\{/)
17544    {
17545        $item =~ s/^\{(.*)\}$/$1/;
17546    }
17547    else
17548    {
17549        my $delimeter_quoted = quotemeta($Texi2HTML::Config::def_argument_separator_delimiters);
17550        if ($item =~ s/^([^\@$delimeter_quoted]+)//)
17551        {
17552            $line = $item . $line;
17553            $item = $1;
17554        }
17555        elsif ($item =~ s/^([$delimeter_quoted])//)
17556        {
17557            $line = $item . $line;
17558            $item = $1;
17559        }
17560        elsif ($item =~ s/^(\@[^\@\{]+)(\@)/$2/)
17561        {
17562            $line = $item . $line;
17563            $item = $1;
17564        }
17565    }
17566    return ($item, $line, $spaces);
17567}
17568
17569# do a href using file and id and taking care of ommitting file if it is
17570# the same
17571# element: structuring element to point to
17572# file: current file
17573sub href($$;$)
17574{
17575    my $element = shift;
17576    my $file = shift;
17577    my $line_nr = shift;
17578    return '' unless defined($element);
17579    my $href = '';
17580    echo_error("Bug: $element->{'texi'}, target undef", $line_nr) if (!defined($element->{'target'}));
17581    echo_error("Bug: $element->{'texi'}, file undef", $line_nr) if (!defined($element->{'file'}));
17582    echo_error("Bug: file undef in href", $line_nr) if (!defined($file));
17583#foreach my $key (keys(%{$element}))
17584#{
17585#   my $value = 'UNDEF'; $value =  $element->{$key} if defined($element->{$key});
17586#   print STDERR "$key: $value\n";
17587#}print STDERR "\n";
17588    $href .= $element->{'file'} if (defined($element->{'file'}) and $file ne $element->{'file'});
17589    $href .= "#$element->{'target'}" if (defined($element->{'target'}));
17590    return $href;
17591}
17592
17593sub file_target_href($$$)
17594{
17595    my $dest_file = shift;
17596    my $orig_file = shift;
17597    my $target = shift;
17598    my $href = '';
17599    $href .= $dest_file if (defined($dest_file) and ($dest_file ne $orig_file));
17600    $href .= "#$target" if (defined($target));
17601    return $href;
17602}
17603
17604sub normalise_space($)
17605{
17606   return undef unless (defined ($_[0]));
17607   my $text = shift;
17608   $text =~ s/\s+/ /go;
17609   $text =~ s/ $//;
17610   $text =~ s/^ //;
17611   return $text;
17612}
17613
17614sub normalise_node($)
17615{
17616    return undef unless (defined ($_[0]));
17617    my $text = shift;
17618    $text = normalise_space($text);
17619    $text =~ s/^top$/Top/i;
17620    return $text;
17621}
17622
17623sub do_anchor_label($$$$)
17624{
17625    my $command = shift;
17626    #my $anchor = shift;
17627    my $args = shift;
17628    my $anchor = $args->[0];
17629    my $style_stack = shift;
17630    my $state = shift;
17631    my $line_nr = shift;
17632
17633    # FIXME anchor may appear twice when outside document and first time
17634    # it appears in the document
17635    return '' if (($state->{'region'} and $state->{'multiple_pass'} > 0) or $state->{'remove_texi'});
17636    $anchor = normalise_node($anchor);
17637    if (!exists($nodes{$anchor}) or !defined($nodes{$anchor}->{'id'}))
17638    {
17639        print STDERR "Bug: unknown anchor `$anchor'\n";
17640    }
17641    return &$Texi2HTML::Config::anchor_label($nodes{$anchor}->{'id'}, $anchor, $nodes{$anchor});
17642}
17643
17644sub get_format_command($)
17645{
17646    my $format = shift;
17647    my $command = '';
17648    my $format_name = '';
17649    my $term = 0;
17650    my $item_nr;
17651    my $paragraph_number;
17652    my $enumerate_type;
17653    my $number;
17654
17655    $command = $format->{'command'} if (defined($format->{'command'}));
17656    $format_name =  $format->{'format'} if (defined($format->{'format'}));
17657
17658    return ($format_name,$command,\$format->{'paragraph_number'},$term,
17659        $format->{'item_nr'}, $format->{'spec'},  $format->{'number'},
17660        $format->{'stack_at_beginning'}, $format->{'command_opened'});
17661}
17662
17663sub do_paragraph($$;$)
17664{
17665    my $text = shift;
17666    my $state = shift;
17667    my $stack = shift;
17668
17669    if (!defined ($state->{'paragraph_context'}))
17670    {
17671        echo_error ("paragraph_context undef");
17672        dump_stack (undef, $stack, $state);
17673    }
17674
17675    my ($format, $paragraph_command, $paragraph_number, $term, $item_nr,
17676        $enumerate_type, $number,$stack_at_beginning, $command_opened)
17677         = get_format_command ($state->{'paragraph_context'});
17678    delete $state->{'paragraph_context'};
17679
17680    my $indent_style = '';
17681    if (exists($state->{'paragraph_indent'}))
17682    {
17683        $indent_style = $state->{'paragraph_indent'};
17684        $state->{'paragraph_indent'} = undef;
17685        delete $state->{'paragraph_indent'};
17686    }
17687    my $paragraph_command_formatted;
17688    $state->{'paragraph_nr'}--;
17689    (print STDERR "Bug text undef in do_paragraph", return '') unless defined($text);
17690    my $align = '';
17691    $align = $state->{'paragraph_style'}->[-1] if ($state->{'paragraph_style'}->[-1]);
17692
17693    if (exists($::style_map_ref->{$paragraph_command}) and
17694       !exists($Texi2HTML::Config::special_list_commands{$format}->{$paragraph_command}) and $command_opened)
17695    {
17696        if ($format eq 'itemize')
17697        {
17698            chomp ($text);
17699            $text = do_simple($paragraph_command, $text, $state, [$text]);
17700            $text = $text . "\n";
17701        }
17702    }
17703    elsif (exists($::things_map_ref->{$paragraph_command}))
17704    {
17705        $paragraph_command_formatted = do_simple($paragraph_command, '', $state);
17706    }
17707    return &$Texi2HTML::Config::paragraph($text, $align, $indent_style, $paragraph_command, $paragraph_command_formatted, $paragraph_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning);
17708}
17709
17710sub do_preformatted($$;$)
17711{
17712    my $text = shift;
17713    my $state = shift;
17714    my $stack = shift;
17715
17716    if (!defined ($state->{'preformatted_context'}))
17717    {
17718        echo_error ("preformatted_context undef");
17719        dump_stack (undef, $stack, $state);
17720    }
17721
17722    my ($format, $leading_command, $preformatted_number, $term, $item_nr,
17723        $enumerate_type, $number,$stack_at_beginning, $command_opened)
17724        = get_format_command($state->{'preformatted_context'});
17725    delete ($state->{'preformatted_context'});
17726    my $leading_command_formatted;
17727    my $pre_style = '';
17728    my $class = '';
17729    $pre_style = $state->{'preformatted_stack'}->[-1]->{'pre_style'} if ($state->{'preformatted_stack'}->[-1]->{'pre_style'});
17730    $class = $state->{'preformatted_stack'}->[-1]->{'class'};
17731    print STDERR "BUG: !state->{'preformatted_stack'}->[-1]->{'class'}\n" unless ($class);
17732    if (exists($::style_map_ref->{$leading_command}) and
17733       !exists($Texi2HTML::Config::special_list_commands{$format}->{$leading_command}) and ($style_type{$leading_command} eq 'style'))
17734    {
17735        $text = do_simple($leading_command, $text, $state,[$text]) if ($format eq 'itemize');
17736    }
17737    elsif (exists($::things_map_ref->{$leading_command}))
17738    {
17739        $leading_command_formatted = do_simple($leading_command, '', $state);
17740    }
17741    return &$Texi2HTML::Config::preformatted($text, $pre_style, $class, $leading_command, $leading_command_formatted, $preformatted_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning);
17742}
17743
17744sub do_external_href($)
17745{
17746    # node_id is a unique node identifier with only letters, digits, - and _
17747    # node_xhtml_id is almost the same, but xhtml id can only begin with
17748    # letters, so a prefix has to be appended
17749    my $texi_node = shift;
17750    my $file = '';
17751    my $node_file = '';
17752    my $node_id = '';
17753    my $node_xhtml_id = '';
17754
17755#print STDERR "do_external_href $texi_node\n";
17756
17757    if ($texi_node =~ s/^\((.+?)\)//)
17758    {
17759         $file = $1;
17760    }
17761    $texi_node = normalise_node($texi_node);
17762    if ($texi_node ne '')
17763    {
17764         if (exists($nodes{$texi_node}) and ($nodes{$texi_node}->{'cross_manual_target'}))
17765         {
17766               $node_id = $nodes{$texi_node}->{'cross_manual_target'};
17767               if ($Texi2HTML::Config::TRANSLITERATE_NODE)
17768               {
17769                   $node_file = $nodes{$texi_node}->{'cross_manual_file'};
17770               }
17771         }
17772         else
17773         {
17774              if ($Texi2HTML::Config::TRANSLITERATE_NODE)
17775              {
17776                  ($node_id, $node_file) = cross_manual_line($texi_node,1);
17777              }
17778              else
17779              {
17780                  $node_id = cross_manual_line($texi_node);
17781              }
17782         }
17783         $node_xhtml_id = node_to_id($node_id);
17784         $node_file = $node_id unless ($Texi2HTML::Config::TRANSLITERATE_NODE);
17785    }
17786    return &$Texi2HTML::Config::external_href($texi_node, $node_file,
17787        $node_xhtml_id, $file);
17788}
17789
17790# transform node for cross ref name to id suitable for xhtml: an xhtml id
17791# must begin with a letter.
17792sub node_to_id($)
17793{
17794    my $cross_ref_node_name = shift;
17795    $cross_ref_node_name =~ s/^([0-9_])/g_t$1/;
17796    return $cross_ref_node_name;
17797}
17798
17799# return an empty string if the command is not a index command, the prefix
17800# if it is one
17801sub index_command_prefix($)
17802{
17803   my $command = shift;
17804   return $1 if ($command =~ /^(\w+?)index/ and ($1 ne 'print') and ($1 ne 'syncode') and ($1 ne 'syn') and ($1 ne 'def') and ($1 ne 'defcode'));
17805   return '';
17806}
17807
17808# return 1 if the following tag shouldn't begin a line
17809sub no_line($)
17810{
17811    my $line = shift;
17812    my $next_tag = next_tag($line);
17813    return 1 if (($line =~ /^\s*$/) or $Texi2HTML::Config::no_paragraph_commands{$next_tag} or
17814       ($Texi2HTML::Config::no_paragraph_commands{'cindex'} and (index_command_prefix($next_tag) ne '')) or
17815       (($line =~ /^\@end\s+(\w+)/) and  $Texi2HTML::Config::no_paragraph_commands{"end $1"}));
17816    return 0;
17817}
17818
17819sub no_paragraph($$)
17820{
17821    my $state = shift;
17822    my $line = shift;
17823    return ($state->{'paragraph_context'} or $state->{'preformatted'} or $state->{'remove_texi'} or no_line($line) or $state->{'no_paragraph'});
17824}
17825
17826# We restart the preformatted format which was stopped
17827# by the format if in preformatted, and start a paragraph
17828# for the text following the end of the format, if needed
17829sub begin_paragraph_after_command($$$$)
17830{
17831    my $state = shift;
17832    my $stack = shift;
17833    my $command = shift;
17834    my $text_following = shift;
17835
17836    #if (($state->{'preformatted'}
17837    #       and !$Texi2HTML::Config::format_in_paragraph{$command})
17838    if ($state->{'preformatted'}
17839        or (!no_paragraph($state,$text_following)))
17840    {
17841        begin_paragraph($stack, $state);
17842    }
17843}
17844
17845# handle raw formatting, ignored regions...
17846sub do_text_macro($$$$$)
17847{
17848    my $type = shift;
17849    my $line = shift;
17850    my $state = shift;
17851    my $stack = shift;
17852    my $line_nr = shift;
17853    my $value;
17854    #print STDERR "do_text_macro $type\n";
17855
17856    if ($Texi2HTML::Config::texi_formats_map{$type} eq 'raw')
17857    {
17858        $state->{'raw'} = $type;
17859        #print STDERR "RAW\n";
17860        if ($state->{'raw'})
17861        {
17862             push @$stack, { 'style' => $type, 'text' => '' };
17863        }
17864    }
17865    elsif ($Texi2HTML::Config::texi_formats_map{$type} eq 'value')
17866    {
17867        if (($line =~ s/(\s+)($VARRE)$//) or ($line =~ s/(\s+)($VARRE)(\s)//))
17868        {
17869            $value = $1 . $2;
17870            $value .= $3 if defined($3);
17871            if ($state->{'ignored'})
17872            {
17873                if ($type eq $state->{'ignored'})
17874                {
17875                    $state->{'ifvalue_inside'}++;
17876                }
17877                # if 'ignored' we don't care about the command as long as
17878                # the nesting is correct
17879                return ($line,'');
17880            }
17881            my $open_ifvalue = 0;
17882            if ($type eq 'ifclear')
17883            {
17884                if (defined($value{$2}))
17885                {
17886                    $open_ifvalue = 1;
17887                }
17888                else
17889                {
17890                    push @{$state->{'text_macro_stack'}}, $type;
17891                }
17892            }
17893            elsif ($type eq 'ifset')
17894            {
17895                unless (defined($value{$2}))
17896                {
17897                    $open_ifvalue = 1;
17898                }
17899                else
17900                {
17901                    push @{$state->{'text_macro_stack'}}, $type;
17902                }
17903            }
17904            if ($open_ifvalue)
17905            {
17906                $state->{'ignored'} = $type;
17907                $state->{'ifvalue'} = $type;
17908                $state->{'ifvalue_inside'} = 1;
17909                # We add at the top of the stack to be able to close all
17910                # opened comands when closing the ifset/ifclear (and ignore
17911                # everything that is in those commands)
17912                push @$stack, { 'style' => 'ifvalue', 'text' => '' };
17913            }
17914        }
17915        else
17916        { # we accept a lone @ifset or @ifclear if it is inside an
17917            if ($type eq $state->{'ifvalue'})
17918            {
17919                $state->{'ifvalue_inside'}++;
17920                return ($line,'');
17921            }
17922            echo_error ("Bad $type line: $line", $line_nr) unless ($state->{'ignored'});
17923        }
17924    }
17925    elsif (not $Texi2HTML::Config::texi_formats_map{$type})
17926    { # ignored text
17927        $state->{'ignored'} = $type;
17928        #print STDERR "IGNORED\n";
17929    }
17930    else
17931    {
17932        push @{$state->{'text_macro_stack'}}, $type unless($state->{'ignored'}) ;
17933    }
17934    my $text = "\@$type";
17935    $text .= $value if defined($value);
17936    return ($line, $text);
17937}
17938
17939# do regions handled specially, currently only tex, going through latex2html
17940sub init_special($$)
17941{
17942    my $style = shift;
17943    my $text = shift;
17944    if (defined($Texi2HTML::Config::command_handler{$style}) and
17945       defined($Texi2HTML::Config::command_handler{$style}->{'init'}))
17946    {
17947        $special_commands{$style}->{'count'} = 0 if (!defined($special_commands{$style}));
17948        if ($Texi2HTML::Config::command_handler{$style}->{'init'}($style,$text,
17949               $special_commands{$style}->{'count'} +1))
17950        {
17951            $special_commands{$style}->{'count'}++;
17952            return "\@special_${style}_".$special_commands{$style}->{'count'}."{}";
17953        }
17954        return '';
17955    }
17956}
17957
17958# FIXME we cannot go through the commands too 'often'. The error messages
17959# are duplicated and global stuff is changed.
17960# -> identify what is global
17961# -> use local state
17962sub do_special_region_lines($;$)
17963{
17964    my $region = shift;
17965    my $state = shift;
17966
17967    # this case covers something like
17968    # @copying
17969    # @insertcopying
17970    # @end copying
17971    if (defined($state) and exists($state->{'region'}) and ($region eq $state->{'region'}))
17972    {
17973         echo_error("Recursively expanding region $region in $state->{'region'}");
17974         return ('','', '');
17975
17976    }
17977
17978    print STDERR "# do_special_region_lines for region $region ($region_initial_state{$region}->{'multiple_pass'}, region_initial_state{$region}->{'region_pass'})" if ($T2H_DEBUG);
17979    if (!defined($state))
17980    {
17981        fill_state($state);
17982        $state->{'outside_document'} = 1;
17983        print STDERR " outside document\n" if ($T2H_DEBUG);
17984    }
17985    elsif (!$state->{'outside_document'})
17986    {
17987        $region_initial_state{$region}->{'multiple_pass'}++;
17988        print STDERR " multiple pass $region_initial_state{$region}->{'multiple_pass'}\n" if ($T2H_DEBUG);
17989    }
17990    else
17991    {
17992        print STDERR " in $state->{'region'}, outside document\n" if ($T2H_DEBUG);
17993    }
17994
17995    return ('','','') unless @{$region_lines{$region}};
17996    my $new_state = duplicate_formatting_state($state);
17997    foreach my $key (keys(%{$region_initial_state{$region}}))
17998    {
17999        $new_state->{$key} = $region_initial_state{$region}->{$key};
18000    }
18001    &$Texi2HTML::Config::begin_special_region($region,$new_state,$region_lines{$region})
18002      if (defined($Texi2HTML::Config::begin_special_region));
18003    my $text = substitute_text($new_state, undef, @{$region_lines{$region}});
18004    $text = &$Texi2HTML::Config::end_special_region($region,$new_state,$text)
18005      if (defined($Texi2HTML::Config::end_special_region));
18006
18007    $region_initial_state{$region}->{'region_pass'}++;
18008
18009    my $remove_texi_state = duplicate_formatting_state($state);
18010    $remove_texi_state->{'remove_texi'} = 1;
18011    foreach my $key (keys(%{$region_initial_state{$region}}))
18012    {
18013        $remove_texi_state->{$key} = $region_initial_state{$region}->{$key};
18014    }
18015    &$Texi2HTML::Config::begin_special_region($region,$remove_texi_state,$region_lines{$region})
18016      if (defined($Texi2HTML::Config::begin_special_region));
18017    print STDERR "# remove texi\n" if ($T2H_DEBUG);
18018    my $removed_texi = substitute_text($remove_texi_state, undef, @{$region_lines{$region}});
18019    $removed_texi = &$Texi2HTML::Config::end_special_region($region,$remove_texi_state, $removed_texi)
18020      if (defined($Texi2HTML::Config::end_special_region));
18021    $region_initial_state{$region}->{'region_pass'}++;
18022
18023    my $simple_format_state = duplicate_formatting_state($state);
18024    foreach my $key (keys(%{$region_initial_state{$region}}))
18025    {
18026        $simple_format_state->{$key} = $region_initial_state{$region}->{$key};
18027    }
18028
18029    &$Texi2HTML::Config::begin_special_region($region,$simple_format_state,$region_lines{$region})
18030      if (defined($Texi2HTML::Config::begin_special_region));
18031    print STDERR "# simple format\n" if ($T2H_DEBUG);
18032    my $simple_format = simple_format($simple_format_state, undef, @{$region_lines{$region}});
18033    $simple_format = &$Texi2HTML::Config::end_special_region($region,$simple_format_state, $simple_format)
18034      if (defined($Texi2HTML::Config::end_special_region));
18035    $region_initial_state{$region}->{'region_pass'}++;
18036
18037    return ($text, $removed_texi, $simple_format);
18038}
18039
18040sub do_insertcopying($)
18041{
18042    my $state = shift;
18043    my ($text, $comment, $simple_formatted) = do_special_region_lines('copying', $state);
18044    return &$Texi2HTML::Config::insertcopying($text, $comment, $simple_formatted);
18045}
18046
18047sub get_deff_index($$$)
18048{
18049    my $tag = shift;
18050    my $line = shift;
18051    my $line_nr = shift;
18052
18053    $tag =~ s/x$//;
18054    my ($command, $style, $category, $name, $type, $class, $arguments, $args_array, $args_type_array);
18055    ($command, $style, $category, $name, $type, $class, $arguments, $args_array, $args_type_array) = parse_def($tag, $line, $line_nr, 1);
18056    $name = &$Texi2HTML::Config::definition_index_entry($name, $class, $style, $command);
18057    return ($style, '') if (!defined($name) or ($name =~ /^\s*$/));
18058    return ($style, $name, $arguments);
18059}
18060
18061sub parse_def($$$;$)
18062{
18063    my $command = shift;
18064    my $line = shift;
18065    my $line_nr = shift;
18066    my $report = shift;
18067
18068    my $format = $command;
18069
18070    if (!ref ($Texi2HTML::Config::def_map{$command}))
18071    {
18072        # substitute shortcuts for definition commands
18073        my $substituted = $Texi2HTML::Config::def_map{$command};
18074        $substituted =~ s/(\w+)//;
18075        $format = $1;
18076        $line = $substituted . $line;
18077    }
18078#print STDERR "PARSE_DEF($command,$format) $line";
18079    my ($category, $name, $type, $class, $arguments);
18080    my @arguments = ();
18081    my @args = @{$Texi2HTML::Config::def_map{$format}};
18082    my $style = shift @args;
18083    my @arg_types = ();
18084    while (@args and $args[0] ne 'arg' and $args[0] ne 'argtype')
18085    {
18086        my $arg = shift @args;
18087        # backward compatibility, it was possible to have a { in front.
18088        $arg =~  s/^\{//;
18089        my ($item, $spaces);
18090        ($item, $line, $spaces) = next_def_param($line, $line_nr, $report);
18091        last if (!defined($item));
18092        #$item =~ s/^\{(.*)\}$/$1/ if ($item =~ /^\{/);
18093        if ($arg eq 'category')
18094        {
18095            $category = $item;
18096        }
18097        elsif ($arg eq 'name')
18098        {
18099            $name = $item;
18100        }
18101        elsif ($arg eq 'type')
18102        {
18103            $type = $item;
18104        }
18105        elsif ($arg eq 'class')
18106        {
18107            $class = $item;
18108        }
18109        push @arg_types, $arg;
18110        push @arguments, $item;
18111    }
18112    my $line_remaining = $line;
18113    $line = '';
18114    my $arg_and_type = 1;
18115    foreach my $arg (@args)
18116    {
18117        if ($arg eq 'arg')
18118        {
18119            $arg_and_type = 0;
18120            last;
18121        }
18122        elsif ($arg eq 'argtype')
18123        {
18124            last;
18125        }
18126    }
18127
18128    my $always_delimiter_quoted = quotemeta($Texi2HTML::Config::def_always_delimiters);
18129    my $in_type_delimiter_quoted = quotemeta($Texi2HTML::Config::def_in_type_delimiters);
18130    my $after_type = 0;
18131    while ($line_remaining !~ /^\s*$/)
18132    {
18133        my ($item, $spaces);
18134        ($item, $line_remaining,$spaces) = next_def_param($line_remaining, $line_nr);
18135        if ($item =~ /^([$always_delimiter_quoted])/ or (!$arg_and_type and  $item =~ /^([$in_type_delimiter_quoted].*)/))
18136        {
18137           $item = $1;
18138           push @arg_types, 'delimiter';
18139           $after_type = 0;
18140        }
18141        elsif (!$arg_and_type or $item =~ /^\@/ or $after_type)
18142        {
18143           push @arg_types, 'param';
18144           $after_type = 0;
18145        }
18146        elsif ($item =~ /^([$in_type_delimiter_quoted])/)
18147        {
18148           push @arg_types, 'delimiter';
18149        }
18150        else
18151        {
18152           push @arg_types, 'paramtype';
18153           $after_type = 1;
18154        }
18155
18156        #$item =~ s/^\{(.*)\}$/$1/ if ($item =~ /^\{/);
18157        $line .= $spaces . $item;
18158        push @arguments, $spaces .$item;
18159    }
18160#print STDERR "PARSE_DEF (style $style, category $category, name $name, type $type, class $class, line $line)\n";
18161    return ($format, $style, $category, $name, $type, $class, $line, \@arguments, \@arg_types);
18162}
18163
18164sub begin_paragraph($$)
18165{
18166    my $stack = shift;
18167    my $state = shift;
18168
18169    my $command = { };
18170    my $top_format = top_format($stack);
18171    if (defined($top_format))
18172    {
18173        $command = $top_format;
18174    }
18175    $command->{'stack_at_beginning'} = [ @{$state->{'command_stack'}} ];
18176    my $paragraph_or_preformatted = 'paragraph';
18177    if ($state->{'preformatted'})
18178    {
18179        $paragraph_or_preformatted = 'preformatted';
18180        $state->{'preformatted_context'} = $command;
18181    }
18182    else
18183    {
18184       $state->{'paragraph_context'} = $command;
18185       $state->{'paragraph_nr'}++;
18186    }
18187    push @$stack, {'format' => $paragraph_or_preformatted, 'text' => '' };
18188    # FIXME give line, and modify line?
18189    &$Texi2HTML::Config::begin_paragraph_texi($paragraph_or_preformatted,
18190      $state->{'paragraph_macros'}, $command, $state, $stack)
18191        if (defined($Texi2HTML::Config::begin_paragraph_texi));
18192    # if there are macros which weren't closed when the previous
18193    # paragraph was closed we reopen them here
18194    push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'};
18195    delete $state->{'paragraph_macros'};
18196}
18197
18198sub parse_format_command($$)
18199{
18200    my $line = shift;
18201    my $tag = shift;
18202    my $command = '';
18203    # macro_regexp
18204    if ($line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?$/ or $line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?\s/)
18205    {
18206        my $macro = $1;
18207        $macro = $alias{$macro} if (exists($alias{$macro}));
18208        if ($::things_map_ref->{$macro} or defined($::style_map_ref->{$macro}))
18209        {
18210        # macro_regexp
18211            $line =~ s/^\s*\@([A-Za-z][\w-]*)(\{\})?\s*//;
18212            $command = $1;
18213        }
18214    }
18215    return ('', $command) if ($line =~ /^\s*$/);
18216    chomp $line;
18217    $line = substitute_text ({'keep_nr' => 1, 'keep_texi' => 1, 'check_item' => $tag}, undef, $line);
18218    return ($line, $command);
18219}
18220
18221sub parse_enumerate($)
18222{
18223    my $line = shift;
18224    my $spec;
18225    if ($line =~ /^\s*(\w)\b/ and ($1 ne '_'))
18226    {
18227        $spec = $1;
18228        $line =~ s/^\s*(\w)\s*//;
18229    }
18230    return ($line, $spec);
18231}
18232
18233sub parse_multitable($$)
18234{
18235    my $line = shift;
18236    my $line_nr = shift;
18237    # first find the table width
18238    my $table_width = 0;
18239    my $fractions;
18240    my $elements;
18241    if ($line =~ s/^\s+\@columnfractions\s+//)
18242    {
18243        @$fractions = split /\s+/, $line;
18244        $table_width = scalar(@$fractions);
18245        foreach my $fraction (@$fractions)
18246        {
18247            unless ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/)
18248            {
18249                echo_error ("column fraction not a number: $fraction", $line_nr);
18250                #warn "$ERROR column fraction not a number: $fraction";
18251            }
18252        }
18253    }
18254    else
18255    {
18256        my $element;
18257        my $line_orig = $line;
18258        while ($line !~ /^\s*$/)
18259        {
18260            my $spaces;
18261            ($element, $line, $spaces) = next_bracketed($line, $line_nr, 1);
18262            if ($element =~ /^\{/)
18263            {
18264                $table_width++;
18265                $element =~ s/^\{//;
18266                $element =~ s/\}\s*$//;
18267                push @$elements, $element;
18268            }
18269            else
18270            {
18271                echo_warn ("garbage in multitable specification: $element", $line_nr);
18272            }
18273        }
18274    }
18275    return ($table_width, $fractions, $elements);
18276}
18277
18278sub end_format($$$$$)
18279{
18280    my $text = shift;
18281    my $stack = shift;
18282    my $state = shift;
18283    my $format = shift;
18284    my $line_nr = shift;
18285    #print STDERR "END FORMAT $format ".format_line_number($line_nr)."\n";
18286    #dump_stack($text, $stack, $state);
18287    #sleep 1;
18288    if ($format_type{$format} eq 'menu')
18289    {
18290        $state->{$format}--;
18291        if ($state->{$format} < 0)
18292        { # FIXME currently happens, see invalid/not_closed_in_menu.texi
18293             echo_error("Too many menu closed", $line_nr);
18294             #print STDERR "Bug, $format counter negative: $state->{$format}\n";
18295             #dump_stack($text, $stack, $state);
18296             #exit 1;
18297             $state->{$format} = 0;
18298        }
18299        close_menu_comment($text, $stack, $state, $line_nr);
18300    }
18301
18302    if ($format_type{$format} eq 'list')
18303    { # those functions return if they detect an inapropriate context
18304        add_item($text, $stack, $state, $line_nr); # handle lists
18305    }
18306    elsif ($format eq 'multitable')
18307    {
18308        add_row($text, $stack, $state, $line_nr); # handle multitable
18309    }
18310    elsif ($format_type{$format} eq 'table')
18311    {
18312        add_term($text, $stack, $state, $line_nr); # handle table
18313        add_line($text, $stack, $state, $line_nr); # handle table
18314    }
18315
18316    #print STDERR "END_FORMAT\n";
18317    #dump_stack($text, $stack, $state);
18318
18319    # set to 1 if there is a mismatch between the closed format and format
18320    # opened before
18321    my $format_mismatch = 0;
18322    # set to 1 in normal menu context after an end menu or detailmenu
18323    my $begin_menu_comment_after_end_format = 0;
18324
18325    my $format_ref = pop @$stack;
18326
18327    ######################### debug
18328    if (!defined($format_ref->{'text'}))
18329    {
18330        push @$stack, $format_ref;
18331        print STDERR "Bug: text undef in end_format $format\n";
18332        dump_stack($text, $stack, $state);
18333        pop @$stack;
18334    }
18335    ######################### end debug
18336
18337    if ($region_lines{$format})
18338    {
18339        ######################### debug
18340        if ($format ne $state->{'region_lines'}->{'format'})
18341        {
18342            echo_warn ("Bug: mismatched region `$format' ne `$state->{'region_lines'}->{'format'}'");
18343        }
18344        ######################### end debug
18345        $state->{'region_lines'}->{'number'}--;
18346        if ($state->{'region_lines'}->{'number'} == 0)
18347        {
18348            close_region($state);
18349        }
18350    }
18351    if (defined($Texi2HTML::Config::def_map{$format}))
18352    {
18353        close_stack($text, $stack, $state, $line_nr, 'deff_item')
18354           unless ($format_ref->{'format'} eq 'deff_item');
18355        add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'}, $format_ref->{'only_inter_commands'}));
18356        $format_ref = pop @$stack; # pop deff
18357        ######################################### debug
18358        if (!defined($format_ref->{'format'}) or !defined($Texi2HTML::Config::def_map{$format_ref->{'format'}}))
18359        {
18360             print STDERR "Bug: not a def* under deff_item\n";
18361             push (@$stack, $format_ref);
18362             dump_stack($text, $stack, $state);
18363             pop @$stack;
18364        }
18365        ######################################### end debug
18366        elsif ($format_ref->{'format'} ne $format)
18367        {
18368             $format_mismatch = 1;
18369             echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format", $line_nr);
18370        }
18371        add_prev($text, $stack, &$Texi2HTML::Config::def($format_ref->{'text'}));
18372    }
18373    elsif ($format_type{$format} eq 'cartouche')
18374    {
18375        add_prev($text, $stack, &$Texi2HTML::Config::cartouche($format_ref->{'text'},$state->{'command_stack'}));
18376    }
18377    elsif ($format eq 'float')
18378    {
18379        unless (defined($state->{'float'}))
18380        {
18381            print STDERR "Bug: state->{'float'} not defined in float\n";
18382            next;
18383        }
18384        my ($caption_lines, $shortcaption_lines) = &$Texi2HTML::Config::caption_shortcaption($state->{'float'});
18385        my ($caption_text, $shortcaption_text);
18386        my $caption_state = duplicate_formatting_state($state);
18387        push @{$caption_state->{'command_stack'}}, 'caption';
18388        $caption_text = substitute_text($caption_state, undef, @$caption_lines) if (defined($caption_lines));
18389        my $shortcaption_state = duplicate_formatting_state($state);
18390        push @{$shortcaption_state->{'command_stack'}}, 'shortcaption';
18391        $shortcaption_text = substitute_text($shortcaption_state,undef, @$shortcaption_lines) if (defined($shortcaption_lines));
18392        add_prev($text, $stack, &$Texi2HTML::Config::float($format_ref->{'text'}, $state->{'float'}, $caption_text, $shortcaption_text));
18393        delete $state->{'float'};
18394    }
18395    elsif (exists ($Texi2HTML::Config::complex_format_map->{$format}))
18396    {
18397        $state->{'preformatted'}--;
18398        pop @{$state->{'preformatted_stack'}};
18399        # debug
18400        if (!defined($Texi2HTML::Config::complex_format_map->{$format_ref->{'format'}}->{'begin'}))
18401        {
18402            print STDERR "Bug undef $format_ref->{'format'}" . "->{'begin'} (for $format...)\n";
18403            dump_stack ($text, $stack, $state);
18404        }
18405        if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/)
18406        {
18407           # discard empty fake formats
18408        }
18409        #print STDERR "before $format\n";
18410        #dump_stack ($text, $stack, $state);
18411        else
18412        {
18413            add_prev($text, $stack, &$Texi2HTML::Config::complex_format($format_ref->{'format'}, $format_ref->{'text'}));
18414        }
18415        #print STDERR "after $format\n";
18416        #dump_stack ($text, $stack, $state);
18417    }
18418    elsif ($format_type{$format} eq 'table' or $format_type{$format} eq 'list' or $format eq 'multitable')
18419    {
18420	    #print STDERR "CLOSE $format ($format_ref->{'format'})\n$format_ref->{'text'}\n";
18421	#dump_stack($text, $stack, $state);
18422        if ($format_ref->{'format'} ne $format)
18423        { # for example vtable closing a table. Cannot be known
18424          # before if in a cell
18425             $format_mismatch = 1;
18426             echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format  ", $line_nr);
18427        }
18428        if ($Texi2HTML::Config::format_map{$format})
18429        { # table or list has a simple format
18430            add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}, $state));
18431        }
18432        else
18433        { # table or list handler defined by the user
18434            add_prev($text, $stack, &$Texi2HTML::Config::table_list($format_ref->{'format'}, $format_ref->{'text'}, $format_ref->{'command'}, $format_ref->{'formatted_command'}, $format_ref->{'item_nr'}, $format_ref->{'spec'}, $format_ref->{'prepended'}, $format_ref->{'prepended_formatted'}, $format_ref->{'columnfractions'}, $format_ref->{'prototype_row'}, $format_ref->{'prototype_lengths'}, $format_ref->{'max_columns'}));
18435        }
18436    }
18437    elsif ($format_type{$format} eq 'quotation')
18438    {
18439        my $quotation_args = pop @{$state->{'quotation_stack'}};
18440        #add_prev($text, $stack, &$Texi2HTML::Config::quotation($format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'style_texi'}, $quotation_args->{'style_id'}));
18441        add_prev($text, $stack, &$Texi2HTML::Config::quotation($format, $format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'text_texi'}));
18442    }
18443    elsif ($Texi2HTML::Config::paragraph_style{$format})
18444    {
18445        if ($state->{'paragraph_style'}->[-1] eq $format)
18446        {
18447            pop @{$state->{'paragraph_style'}};
18448        }
18449        if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/)
18450        {
18451           # discard empty fake formats
18452        }
18453        else
18454        {
18455            add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command($format_ref->{'format'},$format_ref->{'text'}));
18456        }
18457    }
18458    elsif (exists($Texi2HTML::Config::format_map{$format}))
18459    {
18460        if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/)
18461        {
18462           # discard empty fake formats
18463        }
18464        else
18465        {
18466            add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}, $state));
18467        }
18468    }
18469    elsif ($format_type{$format} eq 'menu')
18470    {
18471    # it should be short-circuited if $Texi2HTML::Config::SIMPLE_MENU
18472        if ($state->{'preformatted'})
18473        {
18474            # remove the fake complex style
18475            $state->{'preformatted'}--;
18476            pop @{$state->{'preformatted_stack'}};
18477        }
18478
18479        # backward compatibility with 1.78
18480        if (defined($Texi2HTML::Config::menu))
18481        {
18482           if ($format eq 'menu')
18483           {
18484               add_prev($text, $stack, &$Texi2HTML::Config::menu($format_ref->{'text'}));
18485           }
18486           else # detailmenu
18487           {
18488               add_prev($text, $stack, $format_ref->{'text'});
18489           }
18490        }
18491        else
18492        {
18493           add_prev($text, $stack, &$Texi2HTML::Config::menu_command($format, $format_ref->{'text'}, $state->{'preformatted'}));
18494        }
18495        $begin_menu_comment_after_end_format = 1;
18496    }
18497    else
18498    {
18499        echo_warn("Unknown format $format", $line_nr);
18500    }
18501
18502    # fake formats are not on the command_stack
18503    return 1 if ($fake_format{$format_ref->{'format'}});
18504    # special case for center as it is at the bottom of the stack
18505    my $removed_from_stack;
18506    if ($format eq 'center')
18507    {
18508        $removed_from_stack = shift @{$state->{'command_stack'}};
18509    }
18510    else
18511    {
18512        $removed_from_stack = pop @{$state->{'command_stack'}};
18513    }
18514    if ($removed_from_stack ne $format and !$format_mismatch)
18515    {
18516        #echo_error ("Bug: removed_from_stack $removed_from_stack ne format $format", $line_nr);
18517        # it may not be a bug. Consider, for example a @code{in code
18518        # @end cartouche
18519        # The @code is closed when the paragraph is closed by
18520        # @end cartouche but not really closed since it might have been
18521        # a multiple paragraph @code. So it is not removed from
18522        # command_stack but still have disapeared from the stack!
18523        echo_error("Closing format $format, got $removed_from_stack", $line_nr);
18524    }
18525    if ($begin_menu_comment_after_end_format and $state->{'menu'})
18526    {
18527        begin_format($text, $stack, $state, 'menu_comment', '', $line_nr);
18528        return 0;
18529    }
18530    return 1;
18531}
18532
18533sub push_complex_format_style($$$)
18534{
18535    my $command = shift;
18536    my $complex_format = shift;
18537    my $state = shift;
18538    my $class = $command;
18539    $class = $complex_format->{'class'} if (defined($complex_format->{'class'}));
18540    my $format_style = {'pre_style' =>$complex_format->{'pre_style'}, 'class' => $class, 'command' => $command };
18541    if (defined($complex_format->{'style'}))
18542    {
18543        $format_style->{'style'} = $complex_format->{'style'};
18544    }
18545    else
18546    {
18547        if ($state->{'preformatted'} and defined($state->{'preformatted_stack'}->[-1]->{'style'}))
18548        {
18549            $format_style->{'style'} = $state->{'preformatted_stack'}->[-1]->{'style'};
18550        }
18551        my $index = scalar(@{$state->{'preformatted_stack'}}) -1;
18552        # since preformatted styles are not nested, the preformatted format
18553        # of the first format with style has to be used
18554        if ($index > 0)
18555        {
18556            while ($index)
18557            {
18558                if ($state->{'preformatted_stack'}->[$index]->{'style'})
18559                {
18560                    $format_style->{'class'} = $state->{'preformatted_stack'}->[$index]->{'class'} if (defined($state->{'preformatted_stack'}->[$index]->{'class'}));
18561                    last;
18562                }
18563                $index--;
18564            }
18565        }
18566    }
18567    $state->{'preformatted'}++;
18568    push @{$state->{'preformatted_stack'}}, $format_style;
18569}
18570
18571sub prepare_state_multiple_pass($$)
18572{
18573    my $command = shift;
18574    my $state = shift;
18575    my $return_state = {
18576         'multiple_pass' => 1,
18577          'region_pass' => 1,
18578          'element' => $state->{'element'},
18579         };
18580    if (defined($command))
18581    {
18582        $return_state->{'region'} = $command;
18583        $return_state->{'command_stack'} = ["$command"];
18584    }
18585    return $return_state;
18586}
18587
18588sub begin_format($$$$$$);
18589
18590sub begin_format($$$$$$)
18591{
18592    my $text = shift;
18593    my $stack = shift;
18594    my $state = shift;
18595    my $macro = shift;
18596    my $line = shift;
18597    my $line_nr = shift;
18598    #print STDERR "BEGIN FORMAT $macro".format_line_number($line_nr)."\n";
18599
18600
18601    if ($format_type{$macro} eq 'menu')
18602    {
18603        if ($state->{'menu'})
18604        {
18605            # there should not be any paragraph/preformatted to close
18606            # if the comment or the description were closed since they
18607            # close it
18608            if (! close_menu_comment($text, $stack, $state, $line_nr)
18609               and !close_menu_description($text, $stack, $state, $line_nr))
18610            {
18611               close_paragraph($text, $stack, $state, $line_nr);
18612            }
18613        }
18614        else
18615        {
18616            close_paragraph($text, $stack, $state, $line_nr);
18617        }
18618        $state->{$macro}++;
18619    }
18620    else
18621    {
18622        close_paragraph($text, $stack, $state, $line_nr);
18623    }
18624
18625    $line = &$Texi2HTML::Config::begin_format_texi($macro, $line, $state)
18626        unless($fake_format{$macro});
18627
18628    push (@{$state->{'command_stack'}}, $macro) unless ($fake_format{$macro});
18629    if ($region_lines{$macro})
18630    {
18631        open_region($macro,$state);
18632    }
18633    # A deff like macro
18634    if (defined($Texi2HTML::Config::def_map{$macro}))
18635    {
18636        my $top_format = top_format($stack);
18637        if (defined($top_format) and ("$top_format->{'format'}x" eq $macro))
18638        {
18639          # this is a matching @DEFx command.
18640          # the @DEFx macro has been put at the top of the
18641          # command_stack, although there is no real format opening
18642             pop @{$state->{'command_stack'}};
18643             $macro =~ s/x$//o;
18644             my $deff_item = pop @$stack;
18645             if ($deff_item->{'text'} !~ /s^\*$/)
18646             {
18647                  add_prev($text, $stack,
18648                      &$Texi2HTML::Config::def_item($deff_item->{'text'}, $deff_item->{'only_inter_commands'}));
18649             }
18650             #print STDERR "DEFx $macro\n";
18651        }
18652        else
18653        {
18654             # a new @def.
18655             $macro =~ s/x$//o;
18656             # we remove what is on the stack and put it back,
18657             # to make sure that it is the form without x.
18658             pop @{$state->{'command_stack'}};
18659             push @{$state->{'command_stack'}}, $macro;
18660             #print STDERR "DEF begin $macro\n";
18661             $top_format = { 'format' => $macro, 'text' => '' };
18662             push @$stack, $top_format;
18663        }
18664        #print STDERR "BEGIN_DEFF $macro\n";
18665        #dump_stack ($text, $stack, $state);
18666
18667        my ($command, $style, $category, $name, $type, $class, $args_array, $args_type_array);
18668        ($command, $style, $category, $name, $type, $class, $line, $args_array, $args_type_array) = parse_def($macro, $line, $line_nr);
18669        #print STDERR "AFTER parse_def $line";
18670        my @formatted_args = ();
18671        my $arguments = '';
18672        my %formatted_arguments = ();
18673        my @types = @$args_type_array;
18674        foreach my $arg (@$args_array)
18675        {
18676            my $type = shift @types;
18677            my $substitution_state = duplicate_formatting_state($state);
18678            $substitution_state->{'code_style'}++;
18679            push @formatted_args, substitute_line($arg, $substitution_state, $line_nr);
18680            if (grep {$_ eq $type} ('param', 'paramtype', 'delimiter'))
18681            {
18682                $arguments .= $formatted_args[-1];
18683            }
18684            else
18685            {
18686                $formatted_arguments{$type} = $formatted_args[-1];
18687            }
18688
18689            #if (grep {$_ eq $type} ('param', 'paramtype', 'delimiter'))
18690            #{
18691            #    if ($arg =~ /^\s*\@/)
18692            #    {
18693            #        push @formatted_args, substitute_line($arg, $substitution_state, $line_nr);
18694            #    }
18695            #    else
18696            #    {
18697            #        $substitution_state->{'code_style'}++;
18698            #        push @formatted_args, substitute_line($arg, $substitution_state, $line_nr);
18699            #    }
18700            #    $arguments .= $formatted_args[-1];
18701            #}
18702            #else
18703            #{
18704            #    push @formatted_args, substitute_line($arg, $substitution_state, $line_nr);
18705            #    $formatted_arguments{$type} = $formatted_args[-1];
18706            #}
18707        }
18708        $name = $formatted_arguments{'name'};
18709        $category = $formatted_arguments{'category'};
18710        $type = $formatted_arguments{'type'};
18711        $class = $formatted_arguments{'class'};
18712
18713        $name = '' if (!defined($name));
18714        $category = '' if (!defined($category));
18715
18716        my $class_category = &$Texi2HTML::Config::definition_category($category, $class, $style, $command);
18717        my $class_name = &$Texi2HTML::Config::definition_index_entry($name, $class, $style, $command);
18718        my ($index_entry, $index_label) = do_index_entry_label($macro, $state,$line_nr);
18719        add_prev($text, $stack, &$Texi2HTML::Config::def_line($class_category, $name, $type, $arguments, $index_label, \@formatted_args, $args_type_array, $args_array, $command, $class_name, $category, $class, $style, $macro));
18720        $line = '';
18721        push @$stack, { 'format' => 'deff_item', 'text' => '', 'only_inter_commands' => 1, 'format_ref' => $top_format};
18722        begin_paragraph_after_command($state, $stack, $macro, $line);
18723    }
18724    elsif (exists ($Texi2HTML::Config::complex_format_map->{$macro}))
18725    { # handle menu if SIMPLE_MENU. see texi2html.init
18726        my $complex_format =  $Texi2HTML::Config::complex_format_map->{$macro};
18727        my $format = { 'format' => $macro, 'text' => '', 'pre_style' => $complex_format->{'pre_style'} };
18728        push_complex_format_style($macro, $complex_format, $state);
18729        push @$stack, $format;
18730
18731        begin_paragraph($stack, $state);
18732    }
18733    elsif ($Texi2HTML::Config::paragraph_style{$macro})
18734    {
18735        push (@$stack, { 'format' => $macro, 'text' => '' });
18736        begin_paragraph_after_command($state,$stack,$macro,$line);
18737        push @{$state->{'paragraph_style'}}, $macro;
18738        if ($macro eq 'center')
18739        {
18740            # @center may be in a weird state with regard with
18741            # nesting, so we put it on the bottom of the stack
18742            pop @{$state->{'command_stack'}};
18743            unshift @{$state->{'command_stack'}}, $macro;
18744            # for similar reasons, we may have a bad stack nesting
18745            # which results in } after a closing.
18746            # The following isn't really true anymore, I think: for example
18747            # @center @samp{something @center end of samp}
18748            # resulted to samp being kept in the 'command_stack'
18749
18750        }
18751    }
18752    elsif ($format_type{$macro} eq 'list' or $format_type{$macro} eq 'table' or $macro eq 'multitable')
18753    {
18754        my $format;
18755        #print STDERR "LIST_TABLE $macro\n";
18756        #dump_stack($text, $stack, $state);
18757        if ($macro eq 'itemize' or $format_type{$macro} eq 'table')
18758        {
18759            my $command;
18760            my $prepended;
18761            ($prepended, $command) = parse_format_command($line,$macro);
18762            $command = 'asis' if (($command eq '') and ($macro ne 'itemize'));
18763            my $prepended_formatted;
18764            $prepended_formatted = substitute_line($prepended, prepare_state_multiple_pass('item', $state)) if (defined($prepended));
18765            $format = { 'format' => $macro, 'text' => '', 'command' => $command, 'prepended' => $prepended, 'prepended_formatted' => $prepended_formatted };
18766            $line = '';
18767        }
18768        elsif ($macro eq 'enumerate')
18769        {
18770            my $spec;
18771            ($line, $spec) = parse_enumerate ($line);
18772            $spec = 1 if (!defined($spec));
18773            $format = { 'format' => $macro, 'text' => '', 'spec' => $spec, 'item_nr' => 0 };
18774        }
18775        elsif ($macro eq 'multitable')
18776        {
18777            my ($max_columns, $fractions, $prototype_row) = parse_multitable ($line, $line_nr);
18778            if (!$max_columns)
18779            {
18780                echo_warn ("empty multitable", $line_nr);
18781                $max_columns = 0;
18782            }
18783            my @prototype_lengths = ();
18784            if (defined($prototype_row))
18785            {
18786                foreach my $prototype (@$prototype_row)
18787                {
18788                   push @prototype_lengths, 2+length(substitute_line($prototype, prepare_state_multiple_pass('columnfractions', $state)));
18789                }
18790            }
18791            $format = { 'format' => $macro, 'text' => '', 'max_columns' => $max_columns, 'columnfractions' => $fractions, 'prototype_row' => $prototype_row, 'prototype_lengths' => \@prototype_lengths, 'cell' => 1 };
18792        }
18793        $format->{'first'} = 1;
18794        $format->{'paragraph_number'} = 0;
18795        push @$stack, $format;
18796        if ($format_type{$macro} eq 'table')
18797        {
18798            push @$stack, { 'format' => 'line', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1};
18799        }
18800        elsif ($macro eq 'multitable')
18801        {
18802            push @$stack, { 'format' => 'row', 'text' => '', 'format_ref' => $format, 'item_cmd' => $macro };
18803            push @$stack, { 'format' => 'cell', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1};
18804        }
18805        if ($format_type{$macro} eq 'list')
18806        {
18807            push @$stack, { 'format' => 'item', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1};
18808        }
18809        begin_paragraph_after_command($state,$stack,$macro,$line)
18810           if ($macro ne 'multitable');
18811        return '' unless ($macro eq 'enumerate');
18812    }
18813    elsif ($macro eq 'float' or $format_type{$macro} eq 'quotation')
18814    {
18815        push @$stack, {'format' => $macro, 'text' => '' };
18816        if ($macro eq 'float')
18817        {
18818             open_cmd_line($stack, $state, ['keep','keep'], \&do_float_line);
18819        }
18820        elsif ($format_type{$macro} eq 'quotation')
18821        {
18822             open_cmd_line($stack, $state, ['keep'], \&do_quotation_line);
18823        }
18824        #dump_stack($text, $stack, $state);
18825        #next;
18826    }
18827    # keep this one at the end as there are some other formats
18828    # which are also in format_map
18829    elsif (defined($Texi2HTML::Config::format_map{$macro}) or ($format_type{$macro} eq 'cartouche'))
18830    {
18831        push @$stack, { 'format' => $macro, 'text' => '' };
18832        $state->{'code_style'}++ if ($Texi2HTML::Config::format_code_style{$macro});
18833        begin_paragraph_after_command($state,$stack,$macro,$line);
18834    }
18835    elsif ($format_type{$macro} eq 'menu')
18836    {
18837        # if $Texi2HTML::Config::SIMPLE_MENU we won't get there
18838        # as the menu is a complex format in that case, so it
18839        # is handled above
18840        push @$stack, { 'format' => $macro, 'text' => '' };
18841        if ($state->{'preformatted'})
18842        {
18843        # add a fake complex style in order to have a given pre style
18844        # FIXME check 'style' on bug-texinfo
18845            push_complex_format_style('menu',
18846              $Texi2HTML::Config::MENU_PRE_COMPLEX_FORMAT
18847#                {
18848#              'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE,
18849#              'class' => 'menu-preformatted',
18850##              'style' => 'code'
18851#                 }
18852                 , $state);
18853            begin_paragraph_after_command($state,$stack,$macro,$line);
18854        }
18855        else
18856        {
18857            begin_format($text, $stack, $state, 'menu_comment', $line, $line_nr);
18858        }
18859    }
18860    return $line;
18861}
18862
18863sub do_text($;$)
18864{
18865    my $text = shift;
18866    my $state = shift;
18867    return $text if ($state->{'keep_texi'});
18868    my $remove_texi = 1 if ($state->{'remove_texi'} and !$state->{'simple_format'});
18869    my $preformatted_style = 0;
18870    if ($state->{'preformatted'})
18871    {
18872        $preformatted_style = $state->{'preformatted_stack'}->[-1]->{'style'};
18873    }
18874    return (&$Texi2HTML::Config::normal_text($text, $remove_texi, $preformatted_style, $state->{'code_style'},$state->{'simple_format'},$state->{'command_stack'}, $state));
18875}
18876
18877sub end_simple_format($$$)
18878{
18879    my $command = shift;
18880    my $text = shift;
18881    my $state = shift;
18882
18883    my $element = $Texi2HTML::Config::format_map{$command};
18884
18885    my $result = &$Texi2HTML::Config::format($command, $element, $text);
18886    $state->{'code_style'}-- if ($Texi2HTML::Config::format_code_style{$command});
18887    return $result;
18888}
18889
18890# only get there if not in SIMPLE_MENU and not in preformatted and
18891# right in @menu
18892sub close_menu_comment($$$$)
18893{
18894    my $text = shift;
18895    my $stack = shift;
18896    my $state = shift;
18897    my $line_nr = shift;
18898
18899    my $top_format = top_stack($stack,2);
18900    if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'menu_comment')
18901    { # this is needed to avoid empty menu-comments <tr>...<pre></pre>
18902        abort_empty_preformatted($stack, $state);
18903
18904        close_paragraph($text, $stack, $state, $line_nr);
18905        end_format($text, $stack, $state, 'menu_comment', $line_nr);
18906        return 1;
18907    }
18908}
18909
18910# never get there if in $SIMPLE_MENU
18911# the last arg is used only if in description and an empty line may
18912# stop it and begin a menu_comment
18913sub close_menu_description($$$$;$)
18914{
18915    my $text = shift;
18916    my $stack = shift;
18917    my $state = shift;
18918    my $line_nr = shift;
18919    my $line = shift;
18920
18921    my $top_format = top_stack($stack,1);
18922    if (!$state->{'preformatted'})
18923    {
18924       $top_format = top_stack($stack);
18925    }
18926
18927    if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'menu_description' and (!defined($line) or $line =~ /^\s*$/) )
18928    {
18929        close_paragraph($text, $stack, $state, $line_nr) if ($state->{'preformatted'});
18930        my $descr = pop(@$stack);
18931        add_prev($text, $stack, do_menu_description($descr, $state));
18932        print STDERR "# close_menu: close description\n" if ($T2H_DEBUG & $DEBUG_MENU);
18933        $state->{'code_style'}-- if ($Texi2HTML::Config::format_code_style{'menu_description'});
18934        return 1;
18935    }
18936}
18937
18938# Format menu link
18939# FIXME also pass node and name?
18940sub do_menu_link($$$)
18941{
18942    my $state = shift;
18943    my $line_nr = shift;
18944    my $menu_entry = shift;
18945#    my $menu_entry = $state->{'menu_entry'};
18946    my $file = $state->{'element'}->{'file'};
18947    my $node_name = normalise_node($menu_entry->{'node'});
18948    # normalise_node is used in fact to determine if name is empty.
18949    # It is not passed down to the function reference.
18950    my $name = normalise_node($menu_entry->{'name'});
18951
18952    my $node_substitution_state = duplicate_formatting_state($state);
18953    my $name_substitution_state = duplicate_formatting_state($state);
18954    # normalise_node is not used, so that spaces are kept, like makeinfo.
18955    # also code_style is used, like makeinfo.
18956    $node_substitution_state->{'code_style'} = 1;
18957    $name_substitution_state->{'code_style'} = 1 if ($Texi2HTML::Config::format_code_style{'menu_name'});
18958    my $node_formatted = substitute_line($menu_entry->{'node'}, $node_substitution_state, $line_nr);
18959    my $name_formatted;
18960    my $has_name = 0;
18961    if (defined($name) and $name ne '')
18962    {
18963        $name_formatted = substitute_line($menu_entry->{'name'}, $name_substitution_state, $line_nr);
18964        $has_name = 1;
18965    }
18966    else
18967    {
18968        $name_formatted = substitute_line($menu_entry->{'node'}, $name_substitution_state);
18969    }
18970
18971    my $entry = '';
18972    my $href;
18973    my $element = $nodes{$node_name};
18974
18975    # menu points to an unknown node
18976    if (!$element->{'seen'})
18977    {
18978        if ($menu_entry->{'node'} =~ /^\s*\(.*\)/o or $novalidate)
18979        {
18980            # menu entry points to another info manual or invalid nodes
18981            # and novalidate is set
18982            #$href = $nodes{$node_name}->{'file'};
18983            $href = do_external_href($node_name);
18984        }
18985        else
18986        {
18987            echo_error ("Unknown node in menu entry `$node_name'", $line_nr);
18988            # try to find an equivalent node
18989            my @equivalent_nodes = equivalent_nodes($node_name);
18990            my $node_seen;
18991            foreach my $equivalent_node (@equivalent_nodes)
18992            {
18993                if ($nodes{$equivalent_node}->{'seen'})
18994                {
18995                    $node_seen = $equivalent_node;
18996                    last;
18997                }
18998            }
18999            if (defined($node_seen))
19000            {
19001                echo_warn (" ---> but equivalent node `$node_seen' found");
19002                $element = $nodes{$node_seen};
19003            }
19004        }
19005    }
19006
19007    # the original node or an equivalent node was seen
19008    if ($element->{'seen'})
19009    {
19010        if ($element->{'reference_element'})
19011        {
19012            $element = $element->{'reference_element'};
19013        }
19014
19015        #print STDERR "SUBHREF in menu for `$element->{'texi'}'\n";
19016        $href = href($element, $file, $line_nr);
19017        if (! $element->{'node'})
19018        {
19019            $entry = $element->{'text'}; # this is the section/node name
19020            $entry = "$Texi2HTML::Config::MENU_SYMBOL $entry" if (($entry ne '') and (!defined($element->{'number'}) or ($element->{'number'} =~ /^\s*$/)) and $Texi2HTML::Config::UNNUMBERED_SYMBOL_IN_MENU);
19021        }
19022    }
19023    # save the element used for the href for the description
19024    $menu_entry->{'menu_reference_element'} = $element;
19025
19026    return &$Texi2HTML::Config::menu_link($entry, $state, $href, $node_formatted, $name_formatted, $menu_entry->{'ending'}, $has_name, $state->{'command_stack'}, $state->{'preformatted'});
19027}
19028
19029sub do_menu_description($$)
19030{
19031    my $descr = shift;
19032    my $state = shift;
19033    my $text = $descr->{'text'};
19034    my $menu_entry = $descr->{'menu_entry'};
19035
19036    my $element = $menu_entry->{'menu_reference_element'};
19037
19038    return &$Texi2HTML::Config::menu_description($text, duplicate_formatting_state($state),$element->{'text_nonumber'}, $state->{'command_stack'}, $state->{'preformatted'});
19039}
19040
19041sub do_xref($$$$)
19042{
19043    my $macro = shift;
19044    my $args = shift;
19045    my $style_stack = shift;
19046    my $state = shift;
19047    my $line_nr = shift;
19048
19049    my $result = '';
19050    my @args = @$args;
19051
19052    my $j;
19053    for ($j = 0; $j <= $#$args; $j++)
19054    {
19055        $args[$j] = normalise_space($args[$j]);
19056    #     print STDERR " ($j)$args[$j]\n";
19057    }
19058    #print STDERR "DO_XREF: $macro\n";
19059    if ($macro eq 'inforef')
19060    {
19061        if ((@args < 1) or $args[0] eq '')
19062        {
19063            echo_error ("First argument to \@$macro may not be empty", $line_nr);
19064            return '';
19065        }
19066    }
19067
19068    #print STDERR "XREF: (@args)\n";
19069    my $i;
19070    my $new_state = duplicate_formatting_state($state);
19071    $new_state->{'keep_texi'} = 0;
19072    $new_state->{'keep_nr'} = 0;
19073
19074    my $remove_texi = $new_state->{'remove_texi'};
19075
19076    my @formatted_args;
19077    for ($i = 0; $i < 5; $i++)
19078    {
19079        $args[$i] = '' if (!defined($args[$i]));
19080        my $in_file_style;
19081        $in_file_style = 1 if ($i == 2 and $macro eq 'inforef' or $i == 3 and $macro ne 'inforef');
19082        $new_state->{'code_style'}++ if ($in_file_style or $i == 0);
19083        $new_state->{'remove_texi'} = 1 if ($in_file_style);
19084        $formatted_args[$i] = substitute_line($args[$i], $new_state, $line_nr);
19085        $new_state->{'code_style'}-- if ($in_file_style or $i == 0);
19086        $new_state->{'remove_texi'} = $remove_texi if ($in_file_style);
19087    }
19088
19089    my $node_texi = $args[0];
19090    $node_texi = normalise_node($node_texi);
19091
19092    my ($file_texi, $file);
19093    if ($macro eq 'inforef')
19094    {
19095       $file_texi = $args[2];
19096       $file = $formatted_args[2];
19097    }
19098    else
19099    {
19100       $file_texi = $args[3];
19101       $file = $formatted_args[3];
19102    }
19103
19104    # can be an argument or extracted from the node name
19105    my $file_arg_or_node_texi = $file_texi;
19106    my $file_arg_or_node = $file;
19107
19108    my $node_name;
19109    # the file in parenthesis is removed from node_without_file_texi if needed
19110    my $node_without_file_texi = $node_texi;
19111    # node with file, like (file)node
19112    my $node_and_file_texi;
19113    # the file in parenthesis present with the node
19114    my ($file_of_node_texi, $file_of_node);
19115    if ($node_without_file_texi =~ s/^\(([^\)]+)\)\s*//)
19116    {
19117       $file_of_node_texi = $1;
19118       $file_of_node = substitute_line($file_of_node_texi, $new_state);
19119       $node_name = substitute_line($node_without_file_texi, $new_state);
19120       $file_arg_or_node_texi = $file_of_node_texi if ($file_arg_or_node_texi eq '');
19121       $file_arg_or_node = $file_of_node if ($file_arg_or_node eq '');
19122       # the file argument takes precedence
19123       $node_and_file_texi = "($file_arg_or_node_texi)$node_without_file_texi";
19124    }
19125    else
19126    {
19127        $node_name = $formatted_args[0];
19128        if (defined ($file_texi) and $file_texi ne '')
19129        {
19130            $node_and_file_texi = "($file_texi)$node_texi";
19131        }
19132    }
19133
19134    my $node_and_file;
19135    if (defined($node_and_file_texi))
19136    {
19137       $node_and_file = substitute_line($node_and_file_texi, $new_state);
19138    }
19139    else
19140    {
19141       $node_and_file_texi = $node_texi;
19142       $node_and_file = $node_name;
19143    }
19144
19145    my $cross_ref_texi = $args[1];
19146    my $cross_ref = $formatted_args[1];
19147
19148    my ($manual_texi, $section_texi, $manual, $section);
19149    if ($macro ne 'inforef')
19150    {
19151        $manual_texi = $args[4];
19152        $section_texi = $args[2];
19153        $manual = $formatted_args[4];
19154        $section = $formatted_args[2];
19155    }
19156    else
19157    {
19158        $manual = $section = '';
19159    }
19160
19161    #print STDERR "XREF: (@args)\n";
19162
19163    if (($macro eq 'inforef') or ($file_arg_or_node_texi ne '') or ($manual_texi ne ''))
19164    {# external ref
19165        my $href = '';
19166        if ($file_arg_or_node_texi ne '')
19167        {
19168            $href = do_external_href($node_and_file_texi);
19169        }
19170        else
19171        {
19172            $node_and_file = '';
19173        }
19174        my $section_or_node = '';
19175        if ($manual ne '')
19176        {
19177            $section_or_node = $node_name;
19178            if ($section ne '')
19179            {
19180                $section_or_node = $section;
19181            }
19182        }
19183        $result = &$Texi2HTML::Config::external_ref($macro, $section_or_node, $manual, $node_and_file, $href, $cross_ref, \@args, \@formatted_args);
19184    }
19185    else
19186    {
19187        my $element = $nodes{$node_without_file_texi};
19188        if ($element and $element->{'seen'})
19189        {
19190            if ($element->{'reference_element'})
19191            {
19192                $element = $element->{'reference_element'};
19193            }
19194            my $file = '';
19195            if (defined($state->{'element'}))
19196            {
19197                $file = $state->{'element'}->{'file'};
19198            }
19199            else
19200            {
19201                echo_warn ("\@$macro not in text (in anchor, node, section...)", $line_nr);
19202                # if Texi2HTML::Config::SPLIT the file is '' which ensures
19203                # a href with the file name. if ! Texi2HTML::Config::SPLIT
19204                # the 2 file will be the same thus there won't be the file name
19205                $file = $element->{'file'} unless ($Texi2HTML::Config::SPLIT);
19206            }
19207	    #print STDERR "SUBHREF in ref to node `$node_texi'";
19208            my $href = href($element, $file, $line_nr);
19209            my $section_or_cross_ref = $section;
19210            $section_or_cross_ref = $cross_ref if ($section eq '');
19211            my $name = $section_or_cross_ref;
19212            my $short_name = $section_or_cross_ref;
19213            if ($section_or_cross_ref eq '')
19214            {
19215                # FIXME maybe one should use 'text' instead of 'text_nonumber'
19216                # However the real fix would be to have an internal_ref call
19217                # with more informations
19218                $name = $element->{'text_nonumber'};
19219                $short_name = $node_name;
19220            }
19221            $result = &$Texi2HTML::Config::internal_ref ($macro, $href, $short_name, $name, $element->{'section'}, \@args, \@formatted_args);
19222        }
19223        else
19224        {
19225           if (($node_texi eq '') or !$novalidate)
19226           {
19227               echo_error ("Undefined node `$node_texi' in \@$macro", $line_nr);
19228               my $text = '';
19229               for (my $i = 0; $i < @$args -1; $i++)
19230               {
19231                    $text .= $args->[$i] .',';
19232               }
19233               $text .= $args->[-1];
19234               $result = "\@$macro"."{${text}}";
19235           }
19236           else
19237           {
19238               $result = &$Texi2HTML::Config::external_ref($macro, '', '', $node_name, do_external_href($node_texi), $cross_ref, \@args, \@formatted_args);
19239           }
19240        }
19241    }
19242    return $result;
19243}
19244
19245sub do_acronym_like($$$$$)
19246{
19247    my $command = shift;
19248    my $args = shift;
19249    my $acronym_texi = shift @$args;
19250    my $explanation = shift @$args;
19251    my $style_stack = shift;
19252    my $state = shift;
19253    my $line_nr = shift;
19254
19255    my $explanation_lines;
19256    my $explanation_text;
19257    my $explanation_simple_format;
19258
19259    if (defined($explanation))
19260    {
19261        $explanation =~ s/^\s*//;
19262        $explanation =~ s/\s*$//;
19263        $explanation = undef if ($explanation eq '');
19264    }
19265    $acronym_texi =~ s/^\s*//;
19266    $acronym_texi =~ s/\s*$//;
19267
19268    return '' if ($acronym_texi eq '');
19269
19270    my $with_explanation = 0;
19271    my $normalized_text =  cross_manual_line(normalise_node($acronym_texi));
19272    if (defined($explanation))
19273    {
19274        $with_explanation = 1;
19275        $acronyms_like{$command}->{$normalized_text} = $explanation;
19276    }
19277    elsif (exists($acronyms_like{$command}->{$normalized_text}))
19278    {
19279        $explanation = $acronyms_like{$command}->{$normalized_text};
19280    }
19281
19282    if (defined($explanation))
19283    {
19284         @$explanation_lines = map {$_ = $_."\n"} split (/\n/, $explanation);
19285         my $text = '';
19286         foreach my $line(@$explanation_lines)
19287         {
19288              $line .= ' ' if (chomp ($line));
19289              $text .= $line
19290         }
19291         $text =~ s/ $//;
19292         $explanation_simple_format = simple_format($state, undef, $text);
19293         $explanation_text = substitute_line($text, duplicate_formatting_state($state), $line_nr);
19294    }
19295    return &$Texi2HTML::Config::acronym_like($command, $acronym_texi, substitute_line($acronym_texi, duplicate_formatting_state($state), $line_nr),
19296       $with_explanation, $explanation_lines, $explanation_text, $explanation_simple_format);
19297}
19298
19299sub do_caption_shortcaption($$$$$)
19300{
19301    my $command = shift;
19302    my $args = shift;
19303    my $text_texi = $args->[0];
19304    my $style_stack = shift;
19305    my $state = shift;
19306    my $line_nr = shift;
19307
19308    if (!exists($state->{'float'}))
19309    {
19310#dump_stack(\"", [], $state);
19311         echo_error("\@$command outside of float", $line_nr);
19312         return '';
19313    }
19314    my $float = $state->{'float'};
19315    my @texi_lines = map {$_ = $_."\n"} split (/\n/, $text_texi);
19316    $float->{"${command}_texi"} = \@texi_lines;
19317    return  &$Texi2HTML::Config::caption_shortcaption_command($command,
19318       substitute_text(prepare_state_multiple_pass($command, $state) , undef, @texi_lines), \@texi_lines, $float);
19319}
19320
19321# function called when a @float is encountered. Don't do any output
19322# but prepare $state->{'float'}
19323sub do_float_line($$$$$)
19324{
19325    my $command = shift;
19326    my $args = shift;
19327    my $style_stack = shift;
19328    my $state = shift;
19329    my $line_nr = shift;
19330
19331    my @args = @$args;
19332    my $style_texi = shift @args;
19333    my $label_texi = shift @args;
19334
19335    $style_texi = undef if (defined($style_texi) and $style_texi=~/^\s*$/);
19336    $label_texi = undef if (defined($label_texi) and $label_texi=~/^\s*$/);
19337    if (defined($label_texi))
19338    { # the float is considered as a node as it may be a target for refs.
19339      # it was entered as a node in the pass_structure and the float
19340      # line was parsed at that time
19341         $state->{'float'} = $nodes{normalise_node($label_texi)};
19342         #print STDERR "float: $state->{'float'}, $state->{'float'}->{'texi'}\n";
19343    }
19344    else
19345    { # a float without label. It can't be the target for refs.
19346         $state->{'float'} = { 'float' => 1 };
19347         if (defined($style_texi))
19348         {
19349              $state->{'float'}->{'style_texi'} = normalise_space($style_texi);
19350              $state->{'float'}->{'style_id'} =
19351                  cross_manual_line($state->{'float'}->{'style_texi'});
19352         }
19353         #print STDERR "float: (no label) $state->{'float'}\n";
19354    }
19355    $state->{'float'}->{'style'} = substitute_line($state->{'float'}->{'style_texi'}, undef, $line_nr);
19356#    $state->{'cmd_line'} = 0;
19357    return '';
19358}
19359
19360sub do_quotation_line($$$$$)
19361{
19362    my $command = shift;
19363    my $args = shift;
19364    my @args = @$args;
19365    my $text_texi = shift @args;
19366    my $style_stack = shift;
19367    my $state = shift;
19368    my $line_nr = shift;
19369    my $text;
19370
19371    $text_texi = undef if (defined($text_texi) and $text_texi=~/^\s*$/);
19372    if (defined($text_texi))
19373    {
19374         $text = substitute_line($text_texi, duplicate_formatting_state($state), $line_nr);
19375         $text =~ s/\s*$//;
19376    }
19377    my $quotation_args = { 'text' => $text, 'text_texi' => $text_texi };
19378    push @{$state->{'quotation_stack'}}, $quotation_args;
19379    $state->{'prepend_text'} = &$Texi2HTML::Config::quotation_prepend_text($command, $text_texi);
19380#    $state->{'cmd_line'} = 0;
19381    return '';
19382}
19383
19384sub do_footnote($$$$)
19385{
19386    my $command = shift;
19387    my $args = shift;
19388    my $text = $args->[0];
19389    my $style_stack = shift;
19390    my $doc_state = shift;
19391    my $line_nr = shift;
19392
19393    $text .= "\n";
19394
19395#print STDERR "FOOTNOTE($global_foot_num, $doc_state->{'outside_document'} or $doc_state->{'multiple_pass'}) $text";
19396    my $foot_state = duplicate_state($doc_state);
19397    fill_state($foot_state);
19398    push @{$foot_state->{'command_stack'}}, 'footnote';
19399
19400    push_state($foot_state);
19401
19402    my ($foot_num, $relative_foot_num);
19403    if (!$foot_state->{'region'})
19404    {
19405        $foot_num = \$global_foot_num;
19406        $relative_foot_num = \$global_relative_foot_num;
19407    }
19408    else
19409    {
19410        $foot_num = \$doc_state->{'foot_num'};
19411        $relative_foot_num = \$doc_state->{'relative_foot_num'};
19412    }
19413    $$foot_num++;
19414    $$relative_foot_num++;
19415
19416    my $docid  = "DOCF$$foot_num";
19417    my $footid = "FOOT$$foot_num";
19418    if ($doc_state->{'region'})
19419    {
19420        $docid = $target_prefix . $doc_state->{'region'} . "_$docid";
19421        $footid = $target_prefix . $doc_state->{'region'} . "_$footid";
19422    }
19423    my $from_file = $docu_doc;
19424    if ($doc_state->{'element'})
19425    {
19426        $from_file = $doc_state->{'element'}->{'file'};
19427    }
19428
19429    if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
19430    {
19431        $foot_state->{'element'} = $footnote_element;
19432    }
19433
19434    $foot_state->{'footnote_number_in_doc'} = $$foot_num;
19435    $foot_state->{'footnote_number_in_page'} = $$relative_foot_num;
19436    $foot_state->{'footnote_footnote_id'} = $footid;
19437    $foot_state->{'footnote_place_id'} = $docid;
19438    $foot_state->{'footnote_document_file'} = $from_file;
19439    $foot_state->{'footnote_footnote_file'} = $foot_state->{'element'}->{'file'};
19440    $foot_state->{'footnote_document_state'} = $doc_state;
19441
19442    # FIXME use split_lines ? It seems to work like it is now ?
19443    my @lines = substitute_text($foot_state, undef, map {$_ = $_."\n"} split (/\n/, $text));
19444    my ($foot_lines, $foot_label) = &$Texi2HTML::Config::foot_line_and_ref($$foot_num,
19445         $$relative_foot_num, $footid, $docid, $from_file, $foot_state->{'element'}->{'file'}, \@lines, $doc_state);
19446    if ($doc_state->{'outside_document'} or ($doc_state->{'region'} and $doc_state->{'multiple_pass'} > 0))
19447    {
19448#print STDERR "multiple_pass $doc_state->{'multiple_pass'}, 'outside_document' $doc_state->{'outside_document'}\n";
19449#print STDERR "REGION FOOTNOTE($$foot_num): $doc_state->{'region'} ($doc_state->{'region_pass'})\n";
19450        $region_initial_state{$doc_state->{'region'}}->{'footnotes'}->{$$foot_num}->{$doc_state->{'region_pass'}} = $foot_lines;
19451    }
19452    else
19453    {
19454#print STDERR "GLOBAL FOOTNOTE($$foot_num)\n";
19455         push(@foot_lines, @{$foot_lines});
19456    }
19457    pop_state();
19458    return $foot_label;
19459}
19460
19461sub do_image($$$$$)
19462{
19463    # replace images
19464    my $command = shift;
19465    my $args = shift;
19466    my $style_stack = shift;
19467    my $state = shift;
19468    my $line_nr = shift;
19469    my @args;
19470    foreach my $arg (@$args)
19471    {
19472       $arg =~ s/^\s*//;
19473       $arg =~ s/\s*$//;
19474       push @args, $arg;
19475    }
19476    #my $base = substitute_line($args[0], {'code_style' => 1});
19477    my $base = substitute_line($args[0], {'code_style' => 1, 'remove_texi' => 1});
19478    my $base_simple = substitute_line($args[0], {'simple_format' => 1, 'code_style' => 1});
19479    if ($base eq '')
19480    {
19481         echo_error ("no file argument for \@image", $line_nr);
19482         return '';
19483    }
19484    $args[4] = '' if (!defined($args[4]));
19485    $args[3] = '' if (!defined($args[3]));
19486    my $image;
19487    #my $extension = substitute_line($args[4], {'code_style' => 1});
19488    my $extension = substitute_line($args[4], {'code_style' => 1, 'remove_texi' => 1});
19489    my $extension_simple = substitute_line($args[4], {'simple_format' => 1, 'code_style' => 1});
19490    my ($file_name, $image_name, $simple_file_name);
19491    my @file_locations;
19492    my @file_names = &$Texi2HTML::Config::image_files($base,$extension,$args[0],$args[4]);
19493#    $image = locate_include_file("$base.$args[4]") if ($args[4] ne '');
19494    foreach my $file (@file_names)
19495    {
19496        my $simple_file = substitute_line($file->[1], {'simple_format' => 1, 'code_style' => 1});
19497        if ($image = locate_include_file($file->[0]))
19498        {
19499            if (!defined($file_name))
19500            {
19501                $file_name = $file->[0];
19502                $image_name = $image;
19503                $simple_file_name = $simple_file;
19504            }
19505            push @file_locations, [$file, $image, $simple_file];
19506        }
19507        else
19508        {
19509            push @file_locations, [$file, undef, $simple_file];
19510        }
19511    }
19512    $image_name = '' if (!defined($image_name));
19513    $simple_file_name = '' if (!defined($simple_file_name));
19514
19515    my $alt;
19516    if ($args[3] =~ /\S/)
19517    {
19518        $alt = substitute_line($args[3], {'simple_format' => 1}, $line_nr);
19519    }
19520    return &$Texi2HTML::Config::image($path_to_working_dir . $image_name,
19521        $base,
19522        $state->{'preformatted'}, $file_name, $alt, $args[1], $args[2],
19523        $args[3], $extension, $path_to_working_dir, $image_name,
19524        $state->{'paragraph_context'}, \@file_locations, $base_simple,
19525        $extension_simple, $simple_file_name);
19526}
19527
19528# usefull if we want to duplicate only the global state, nothing related with
19529# formatting
19530sub duplicate_state($)
19531{
19532    my $state = shift;
19533    my $new_state = { 'element' => $state->{'element'},
19534         'multiple_pass' => $state->{'multiple_pass'},
19535         'region_pass' => $state->{'region_pass'},
19536         'region' => $state->{'region'},
19537         'sec_num' => $state->{'sec_num'},
19538         'outside_document' => $state->{'outside_document'},
19539         'inside_document' => $state->{'inside_document'},
19540         'duplicated' => 1
19541    };
19542    return $new_state;
19543}
19544
19545# duplicate global and formatting state.
19546sub duplicate_formatting_state($)
19547{
19548    my $state = shift;
19549    my $new_state = duplicate_state($state);
19550
19551    # Things passed here should be things that are not emptied/set to 0 by
19552    # any command. Also they shouldn't need anything to be on the
19553    # stack. This rules out paragraphs, for example.
19554    foreach my $format_key ('preformatted', 'code_style', 'keep_texi',
19555          'keep_nr', 'preformatted_stack')
19556    {
19557        $new_state->{$format_key} = $state->{$format_key};
19558    }
19559# this is needed for preformatted
19560    my $command_stack = $state->{'command_stack'};
19561    $command_stack = [] if (!defined($command_stack));
19562    $new_state->{'command_stack'} = [ @$command_stack ];
19563    $new_state->{'preformatted_context'} = {'stack_at_beginning' => [ @$command_stack ]};
19564    $new_state->{'code_style'} = 0 if (!defined($new_state->{'code_style'}));
19565    return $new_state;
19566}
19567
19568sub expand_macro($$$$$)
19569{
19570    my $name = shift;
19571    my $args = shift;
19572    my $end_line = shift;
19573    my $line_nr = shift;
19574    my $state = shift;
19575
19576    # we dont expand macros when in ignored environment.
19577    return if ($state->{'ignored'});
19578
19579    die "Bug end_line not defined" if (!defined($end_line));
19580
19581    my $index = 0;
19582    foreach my $arg (@$args)
19583    { # expand @macros in arguments. It is complicated because we must be
19584      # carefull not to expand macros in @ignore section or the like, and
19585      # still keep every single piece of text (including the @ignore macros).
19586        $args->[$index] = substitute_text({'texi' => 1, 'arg_expansion' => 1}, undef, split_lines($arg));
19587        $index++;
19588    }
19589    # retrieve the macro definition
19590    my $macrobody = $macros->{$name}->{'body'};
19591    my $formal_args = $macros->{$name}->{'args'};
19592    my $args_index =  $macros->{$name}->{'args_index'};
19593
19594    my $i;
19595    for ($i=0; $i<=$#$formal_args; $i++)
19596    {
19597        $args->[$i] = "" unless (defined($args->[$i]));
19598        print STDERR "# arg($i): $args->[$i]\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19599    }
19600    echo_error ("too much arguments for macro $name", $line_nr) if (defined($args->[$i + 1]));
19601    my $result = '';
19602    while ($macrobody ne '')
19603    {
19604        if ($macrobody =~ s/^([^\\]*)\\//o)
19605        {
19606            $result .= $1 if defined($1);
19607            if ($macrobody =~ s/^\\//)
19608            {
19609                $result .= '\\';
19610            }
19611            elsif ($macrobody =~ s/^(\@end\sr?macro)$// or $macrobody =~ s/^(\@end\sr?macro\s)// or $macrobody =~ s/^(\@r?macro\s+\w+\s*.*)//)
19612            { # \ protect @end macro
19613                $result .= $1;
19614            }
19615            elsif ($macrobody =~ s/^([^\\]*)\\//)
19616            {
19617               my $arg = $1;
19618               if (defined($args_index->{$arg}))
19619               {
19620                   $result .= $args->[$args_index->{$arg}];
19621               }
19622               else
19623               {
19624                   warn "$ERROR \\ not followed by \\ or an arg but by $arg in macro\n";
19625                   $result .= '\\' . $arg;
19626               }
19627            }
19628            next;
19629        }
19630        $result .= $macrobody;
19631        last;
19632    }
19633    my @result = split(/^/m, $result);
19634    # for a completly empty macro, $result = '', and the split leads
19635    # to an empty array, so add back an empty string
19636    @result = ('') if (!scalar(@result));
19637    # Add the result of the macro expansion back to the input_spool.
19638    # Set the macro name if in the outer macro
19639    if ($state->{'arg_expansion'})
19640    { # in that case we are in substitute_text for an arg
19641        unshift @{$state->{'spool'}}, (@result, $end_line);
19642    }
19643    else
19644    {
19645        #$result[-1].=$end_line;
19646#foreach my $res (@result)
19647#{
19648#   print STDERR "RESULT:$res";
19649#}
19650#print STDERR "#########end->$end_line";
19651        my $last_line = $result[-1];
19652        if (chomp($last_line))
19653        {
19654            push @result, $end_line;
19655        }
19656        else
19657        {
19658            $result[-1] .= $end_line;
19659        }
19660        unshift @{$state->{'input_spool'}->{'spool'}}, (@result); #, $end_line);
19661        $state->{'input_spool'}->{'macro'} = $name if ($state->{'input_spool'}->{'macro'} eq '');
19662    }
19663    if ($T2H_DEBUG & $DEBUG_MACROS)
19664    {
19665        print STDERR "# macro expansion result:\n";
19666        #print STDERR "$first_line";
19667        foreach my $line (@result)
19668        {
19669            print STDERR "$line";
19670        }
19671        print STDERR "# macro expansion result end\n";
19672    }
19673}
19674
19675sub do_index_summary_file($$)
19676{
19677    my $name = shift;
19678    my $docu_name = shift;
19679    my $entries = get_index($name);
19680    &$Texi2HTML::Config::index_summary_file_begin ($name, $printed_indices{$name}, $docu_name);
19681    print STDERR "# writing $name index summary for $docu_name\n" if $T2H_VERBOSE;
19682
19683    foreach my $key (sort keys %$entries)
19684    {
19685        my $entry = $entries->{$key};
19686        my $indexed_element = $entry->{'element'};
19687        my $entry_element = $indexed_element;
19688        $entry_element = $entry_element->{'element_ref'} if (defined($entry_element->{'element_ref'}));
19689        my $origin_href = $entry->{'file'};
19690   #print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n";
19691        if ($entry->{'target'})
19692        {
19693             $origin_href .= '#' . $entry->{'target'};
19694        }
19695        else
19696        {
19697            $origin_href .= '#' . $indexed_element->{'target'};
19698        }
19699        &$Texi2HTML::Config::index_summary_file_entry ($name,
19700          $key, $origin_href,
19701          substitute_line($entry->{'entry'}), $entry->{'entry'},
19702          href($entry_element, ''),
19703          $entry_element->{'text'},
19704          $printed_indices{$name},
19705          $docu_name);
19706    }
19707    &$Texi2HTML::Config::index_summary_file_end ($name, $printed_indices{$name}, $docu_name);
19708}
19709
19710sub get_index_entry_infos($$;$)
19711{
19712    my $entry = shift;
19713    my $element = shift;
19714    my $line_nr = shift;
19715    my $indexed_element = $entry->{'element'};
19716    my $entry_element = $indexed_element;
19717    # we always use the associated element_ref, instead of the original
19718    # element
19719    $entry_element = $entry_element->{'element_ref'} if (defined($entry_element->{'element_ref'}));
19720    my $origin_href = '';
19721    print STDERR "BUG: entry->{'file'} not defined for `$entry->{'entry'}'\n"
19722       if (!defined($entry->{'file'}));
19723    print STDERR "BUG: element->{'file'} not defined for `$entry->{'entry'}', `$element->{'texi'}'\n"
19724       if (!defined($element->{'file'}));
19725    $origin_href = $entry->{'file'} if ($entry->{'file'} ne $element->{'file'});
19726#print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n";
19727    if (defined($entry->{'target'}))
19728    {
19729         $origin_href .= '#' . $entry->{'target'};
19730    }
19731    else
19732    { # this means that the index entry is in a special region like @copying...
19733         $origin_href .= '#' . $indexed_element->{'target'};
19734    }
19735   #print STDERR "SUBHREF in index entry `$entry->{'entry'}' for `$entry_element->{'texi'}'\n";
19736    return ($origin_href,
19737            $entry->{'file'},
19738            $element->{'file'},
19739            $entry->{'target'},
19740            $indexed_element->{'target'},
19741            substitute_line($entry->{'entry'}),
19742            href($entry_element, $element->{'file'}, $line_nr),
19743            $entry_element->{'text'});
19744}
19745
19746# remove texi commands, replacing with what seems adequate. see simple_map_texi
19747# and texi_map.
19748# Doesn't protect html
19749sub remove_texi(@)
19750{
19751    return substitute_text ({ 'remove_texi' => 1}, undef, @_);
19752}
19753
19754# Same as remove texi but protect text and use special maps for @-commands
19755sub simple_format($$@)
19756{
19757    my $state = shift;
19758    my $line_nr = shift;
19759    if (!defined($state))
19760    {
19761        $state = {};
19762    }
19763    else
19764    {
19765        $state = duplicate_formatting_state($state);
19766    }
19767    $state->{'remove_texi'} = 1;
19768    $state->{'simple_format'} = 1;
19769    $::simple_map_texi_ref = \%Texi2HTML::Config::simple_format_simple_map_texi;
19770    $::style_map_texi_ref = \%Texi2HTML::Config::simple_format_style_map_texi;
19771    $::texi_map_ref = \%Texi2HTML::Config::simple_format_texi_map;
19772    my $text = substitute_text($state, $line_nr, @_);
19773    $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
19774    $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
19775    $::texi_map_ref = \%Texi2HTML::Config::texi_map;
19776    return $text;
19777}
19778
19779sub enter_table_index_entry($$$$)
19780{
19781    my $text = shift;
19782    my $stack = shift;
19783    my $state = shift;
19784    my $line_nr = shift;
19785    if ($state->{'item'} and ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/))
19786    {
19787         my $index = $1;
19788         my $macro = $state->{'item'};
19789         delete $state->{'item'};
19790         close_stack($text, $stack, $state, $line_nr, 'index_item');
19791         my $item = pop @$stack;
19792         my $element = $state->{'element'};
19793         $element = $state->{'node_ref'} unless ($element);
19794         enter_index_entry($index, $line_nr, $item->{'text'},
19795            $state->{'place'}, $element, $state->{'table_stack'}->[-1], $state->{'region'});
19796         add_prev($text, $stack, "\@$macro" . $item->{'text'});
19797    }
19798}
19799
19800sub scan_texi($$$$;$)
19801{
19802    my $line = shift;
19803    my $text = shift;
19804    my $stack = shift;
19805    my $state = shift;
19806    my $line_nr = shift;
19807
19808    die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
19809    my $cline = $line;
19810
19811    while(1)
19812    {
19813        # scan_texi
19814        #print STDERR "WHILE:$cline";
19815        #print STDERR "ARG_EXPANSION: $state->{'arg_expansion'}\n" if ($state->{'arg_expansion'});
19816        #dump_stack($text, $stack, $state);
19817        #print STDERR "ifvalue_inside $state->{'ifvalue_inside'}\n";
19818
19819
19820        # first we handle special cases:
19821        # macro definition: $state->{'macro_inside'}
19822        # macro arguments:  $state->{'macro_name'}
19823        # raw format:       $state->{'raw'}
19824        # @verb:            $state->{'verb'}
19825        # ignored:          $state->{'ignored'}
19826        # and then the remaining text/macros.
19827
19828        # in macro definition
19829        if ($state->{'macro_inside'})
19830        {
19831            if ($cline =~ s/^([^\\\@]*\\)//)
19832            {# protected character or @end macro
19833                 $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
19834                 if ($cline =~ s/^\\//)
19835                 {
19836                      $state->{'macro'}->{'body'} .= '\\' unless ($state->{'ignored'});
19837                      next;
19838                 }
19839                 # I believe it is correct, although makeinfo don't do that.
19840                 elsif ($cline =~ s/^(\@end\sr?macro)$//o or $cline =~ s/^(\@end\sr?macro\s)//o
19841                      or $cline =~ s/^(\@r?macro\s+\w+\s*.*)//o)
19842                 {
19843                      $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
19844                      next;
19845                 }
19846            }
19847            #if ($cline =~ s/^(.*?)\@end\sr?macro$//o or $cline =~ s/^(.*?)\@end\sr?macro\s+//o)
19848            if ($cline =~ s/^(\@end\sr?macro)$//o or $cline =~ s/^(\@end\sr?macro\s+)//o)
19849            {
19850                 $state->{'macro_inside'}--;
19851                 next if ($state->{'ignored'});
19852                 if ($state->{'macro_inside'})
19853                 {
19854                     $state->{'macro'}->{'body'} .= $1;
19855                     next;
19856                 }
19857                 chomp $state->{'macro'}->{'body'};
19858                 print STDERR "# end macro def. Body:\n$state->{'macro'}->{'body'}"
19859                     if ($T2H_DEBUG & $DEBUG_MACROS);
19860                 delete $state->{'macro'};
19861                 return if ($cline =~ /^\s*$/);
19862                 next;
19863            }
19864            elsif($cline =~ /^(\@r?macro\s+\w+\s*.*)/)
19865            {
19866                 $state->{'macro'}->{'body'} .= $cline unless ($state->{'ignored'});
19867                 $state->{'macro_inside'}++;
19868                 return;
19869            }
19870            elsif ($cline =~ s/^\@(.)//)
19871            {
19872                 $state->{'macro'}->{'body'} .= '@' . $1 unless ($state->{'ignored'});
19873                 next;
19874            }
19875            elsif ($cline =~ s/^\@//)
19876            {
19877                 $state->{'macro'}->{'body'} .= '@' unless ($state->{'ignored'});
19878                 next;
19879            }
19880            else
19881            {
19882                 $cline =~ s/([^\@\\]*)//;
19883                 if ($state->{'ignored'})
19884                 {
19885                     return if ($cline =~ /^$/);
19886                     next;
19887                 }
19888                 $state->{'macro'}->{'body'} .= $1 if (defined($1));
19889                 if ($cline =~ /^$/)
19890                 {
19891                      $state->{'macro'}->{'body'} .= $cline;
19892                      return;
19893                 }
19894                 next;
19895            }
19896        }
19897        # in macro arguments parsing/expansion. Here \ { } and , if this is a
19898        # multi args macro have a signification, the remaining is passed
19899        # unmodified
19900        if (defined($state->{'macro_name'}))
19901        {
19902            my $special_chars = quotemeta ('\{}');
19903            my $multi_args = 0;
19904            my $formal_args = $macros->{$state->{'macro_name'}}->{'args'};
19905            $multi_args = 1 if ($#$formal_args >= 1);
19906            $special_chars .= quotemeta(',') if ($multi_args);
19907            if ($state->{'macro_args'}->[-1] eq '')
19908            {# remove space at the very beginning
19909                $cline =~ s/^\s*//o;
19910            }
19911            if ($cline =~ s/^([^$special_chars]*)([$special_chars])//)
19912            {
19913                $state->{'macro_args'}->[-1] .= $1 if defined($1);
19914                # \ protects any character in macro arguments
19915                if ($2 eq '\\')
19916                {
19917                    print STDERR "# macro call: protected char\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19918                    if ($cline =~ s/^(.)//)
19919                    {
19920                        $state->{'macro_args'}->[-1] .= $1;
19921                    }
19922                    else
19923                    {
19924                        $state->{'macro_args'}->[-1] .= '\\';
19925                    }
19926                }
19927                elsif ($2 eq ',')
19928                { # in texinfo 4.8.90 a comma in braces is protected
19929                    if ($state->{'macro_depth'} > 1)
19930                    {
19931                        $state->{'macro_args'}->[-1] .= ',';
19932                    }
19933                    else
19934                    { # separate args
19935                        print STDERR "# macro call: new arg\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19936                        $cline =~ s/^\s*//o;
19937                        push @{$state->{'macro_args'}}, '';
19938                    }
19939                }
19940                elsif ($2 eq '}')
19941                { # balanced } ends the macro call, otherwise it is in the arg
19942                    $state->{'macro_depth'}--;
19943                    if ($state->{'macro_depth'} == 0)
19944                    {
19945#print STDERR "BEFORE: $cline";
19946                        print STDERR "# expanding macro $state->{'macro_name'}\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19947                        $cline = expand_macro($state->{'macro_name'}, $state->{'macro_args'}, $cline, $line_nr, $state);
19948                        delete $state->{'macro_name'};
19949                        delete $state->{'macro_depth'};
19950                        delete $state->{'macro_args'};
19951#print STDERR "AFTER: $cline";
19952                        return;
19953                    }
19954                    else
19955                    {
19956                        print STDERR "# macro call: closing }\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19957                        add_text('}', \$state->{'macro_args'}->[-1]);
19958                    }
19959                }
19960                elsif ($2 eq '{')
19961                {
19962                    print STDERR "# macro call: opening {\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19963                    $state->{'macro_depth'}++;
19964                    add_text('{', \$state->{'macro_args'}->[-1]);
19965                }
19966                next;
19967            }
19968            print STDERR "# macro call: end of line\n" if ($T2H_DEBUG & $DEBUG_MACROS);
19969            $state->{'macro_args'}->[-1] .= $cline;
19970            return;
19971        }
19972        # in a raw format, verbatim, tex or html
19973        if ($state->{'raw'})
19974        {
19975            my $tag = $state->{'raw'};
19976
19977            # debugging
19978            if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
19979            {
19980                print STDERR "Bug: raw or special: $tag but not on top of stack\n";
19981                print STDERR "line: $cline";
19982                dump_stack($text, $stack, $state);
19983                exit 1;
19984            }
19985
19986            # macro_regexp
19987            if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $tag))
19988            {
19989                $cline =~ s/^(.*?)(\@end\s$tag)//;
19990            # we add it even if 'ignored', it'll be discarded when there is
19991            # the @end
19992                add_prev ($text, $stack, $1);
19993                my $end = $2;
19994                my $style = pop @$stack;
19995                if ($style->{'text'} !~ /^\s*$/ or $state->{'arg_expansion'})
19996                # FIXME if 'arg_expansion' and also 'ignored' is true,
19997                # theoretically we should keep
19998                # what is in the raw format however
19999                # it will be removed later anyway
20000                {# ARG_EXPANSION
20001                    add_prev ($text, $stack, $style->{'text'} . $end) unless ($state->{'ignored'});
20002                    delete $state->{'raw'};
20003                }
20004                next;
20005            }
20006            else
20007            {# we add it even if 'ignored', it'll be discarded when there is
20008             # the @end
20009                 add_prev ($text, $stack, $cline);
20010                 last;
20011            }
20012        }
20013
20014        # in a @verb{ .. } macro
20015        if (defined($state->{'verb'}))
20016        {
20017            #dump_stack($text, $stack, $state);
20018            my $char = quotemeta($state->{'verb'});
20019            #print STDERR "VERB $char\n";
20020            if ($cline =~ s/^(.*?)$char\}/\}/)
20021            {# we add it even if 'ignored', it'll be discarded when closing
20022                 add_prev($text, $stack, $1 . $state->{'verb'});
20023                 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
20024                 delete $state->{'verb'};
20025                 next;
20026            }
20027            else
20028            {# we add it even if 'ignored', it'll be discarded when closing
20029                 add_prev($text, $stack, $cline);
20030                 last;
20031            }
20032        }
20033        # In ignored region
20034        if ($state->{'ignored'})
20035        {
20036            #print STDERR "IGNORED(ifvalue($state->{'ifvalue_inside'})): $state->{'ignored'}\n";
20037            if ($cline =~ /^.*?\@end(\s+)([a-zA-Z]\w+)/)
20038            {
20039                if ($2 eq $state->{'ignored'})
20040                {
20041                    $cline =~ s/^(.*?\@end)(\s+)([a-zA-Z]\w+)//;
20042                    my $end_ignore = $1.$2.$3;
20043                    if (($state->{'ifvalue_inside'}) and $state->{'ignored'} eq $state->{'ifvalue'})
20044                    {
20045                         if ($state->{'ifvalue_inside'} == 1)
20046                         {# closing still opened @-commands with braces
20047                             pop (@$stack) while (@$stack and $stack->[-1]->{'style'} ne 'ifvalue')
20048                         }
20049                         pop (@$stack);
20050                         $state->{'ifvalue_inside'}--;
20051                    }
20052                    $state->{'ignored'} = undef;
20053                    delete $state->{'ignored'};
20054                    # We are stil in the ignored ifset or ifclear section
20055                    $state->{'ignored'} = $state->{'ifvalue'} if ($state->{'ifvalue_inside'});
20056                    #dump_stack($text, $stack, $state);
20057                    # MACRO_ARG => keep ignored text
20058                    if ($state->{'arg_expansion'})
20059                    {# this may not be very usefull as it'll be remove later
20060                        add_prev ($text, $stack, $end_ignore);
20061                        next;
20062                    }
20063                    return if ($cline =~ /^\s*$/o);
20064                    next;
20065                }
20066            }
20067            add_prev ($text, $stack, $cline) if ($state->{'arg_expansion'});
20068            # we could theoretically continue for ignored commands other
20069            # than ifset or ifclear, however it isn't usefull.
20070            return unless ($state->{'ifvalue_inside'} and ($state->{'ignored'} eq $state->{'ifvalue'}));
20071        }
20072
20073
20074        # an @end tag
20075        # macro_regexp
20076        if ($cline =~ s/^([^{}@]*)\@end(\s+)([a-zA-Z][\w-]*)//)
20077        {
20078            my $leading_text = $1;
20079            my $space = $2;
20080            my $end_tag = $3;
20081            # when 'ignored' we don't open environments that aren't associated
20082            # with ignored regions, so we don't need to close them.
20083            next if ($state->{'ignored'});# ARG_EXPANSION
20084            add_prev($text, $stack, $leading_text);
20085            if (defined($state->{'text_macro_stack'})
20086               and @{$state->{'text_macro_stack'}}
20087               and ($end_tag eq $state->{'text_macro_stack'}->[-1]))
20088            {
20089                pop @{$state->{'text_macro_stack'}};
20090                # we keep menu and titlepage for the following pass
20091                if ((($end_tag eq 'menu') and $Texi2HTML::Config::texi_formats_map{'menu'}) or ($region_lines{$end_tag}) or $state->{'arg_expansion'})
20092                {
20093                     add_prev($text, $stack, "\@end${space}$end_tag");
20094                }
20095                else
20096                {
20097                    #print STDERR "End $end_tag\n";
20098                    #dump_stack($text, $stack, $state);
20099                    return if ($cline =~ /^\s*$/);
20100                }
20101            }
20102            elsif ($Texi2HTML::Config::texi_formats_map{$end_tag})
20103            {
20104                echo_error ("\@end $end_tag without corresponding element", $line_nr);
20105            }
20106            else
20107            {# ARG_EXPANSION
20108                add_prev($text, $stack, "\@end${space}$end_tag");
20109            }
20110            next;
20111        }
20112        # macro_regexp
20113        elsif ($cline =~ s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
20114        {# ARG_EXPANSION
20115            add_prev($text, $stack, $1) unless $state->{'ignored'};
20116            my $macro = $2;
20117            # FIXME: if it is an alias, it is substituted below, in the
20118            # diverse add_prev and output of \@$macro. Maybe it could be
20119            # kept and only substituted in the last passes?
20120            $macro = $alias{$macro} if (exists($alias{$macro}));
20121	    #print STDERR "MACRO $macro\n";
20122            # handle skipped @-commands
20123            $state->{'bye'} = 1 if ($macro eq 'bye' and !$state->{'ignored'} and !$state->{'arg_expansion'});
20124            # 'ignored' and 'arg_expansion' are handled in misc_command_texi
20125            # these are the commands in which the @value and @macro
20126            # and @-commands in general should not be expanded
20127            if (defined($Texi2HTML::Config::misc_command{$macro}) and
20128                 ($macro eq 'c' or $macro eq 'comment' or $macro eq 'set'
20129                   or $macro eq 'clear' or $macro eq 'bye'))
20130            {
20131                ($cline, $line) = misc_command_texi($cline, $macro, $state,
20132                       $line_nr);
20133                add_prev ($text, $stack, "\@$macro" . $line) unless $state->{'ignored'};
20134            }
20135            elsif ($macro eq 'setfilename' or $macro eq 'documentencoding'
20136                      or $macro eq 'definfoenclose' or $macro eq 'include')
20137            { # special commands whose arguments will have @macro and
20138              # @value expanded, and that are processed in this pass
20139                if ($state->{'ignored'})
20140                {
20141                    $cline = '';
20142                }
20143                elsif ($state->{'arg_expansion'})
20144                {
20145                    add_prev($text, $stack, "\@$macro" . $cline);
20146                    return;
20147                }
20148                else
20149                {
20150                    $cline =~ s/^(\s+)//;
20151                    my $space = $1;
20152                    # not sure if it happpens at end of line, or with
20153                    # special char following the @-command or only at end of file
20154                    $space = '' if (!defined($space));
20155                    if (!$state->{'line_command'})
20156                    {
20157                        #print STDERR "LINE_COMMAND Start line_command $macro, cline $cline";
20158                        $state->{'line_command'} = $macro;
20159                        push @$stack, { 'line_command' => $macro, 'text' => $space };
20160                    }
20161                    else
20162                    {# FIXME warn/error? or just discard?
20163                        add_prev($text, $stack, "\@$macro" . $space);
20164                    }
20165                }
20166            }
20167            # pertusus: it seems that value substitution are performed after
20168            # macro argument expansions: if we have
20169            # @set comma ,
20170            # and a call to a macro @macro {arg1 @value{comma} arg2}
20171            # the macro arg is arg1 , arg2 and the comma don't separate
20172            # args. Likewise it seems that the @value are not expanded
20173            # in macro definitions
20174
20175            elsif ($macro =~ /^r?macro$/)
20176            { #FIXME what to do if 'arg_expansion' is true (ie within another
20177              # macro call arguments?
20178                if ($cline =~ /^\s+(\w[\w-]*)\s*(.*)/)
20179                {
20180                    my $name = $1;
20181                    unless ($state->{'ignored'})
20182                    {
20183                         if (exists($macros->{$name}))
20184                         {
20185                             echo_warn ("macro `$name' already defined " .
20186                                 format_line_number($macros->{$name}->{'line_nr'}) . " redefined", $line_nr);
20187                         }
20188
20189                    }
20190                    $state->{'macro_inside'} = 1;
20191                    next if ($state->{'ignored'});
20192                    # if in 'arg_expansion' we really want to take into account
20193                    # that we are in an ignored ifclear.
20194                    my @args = ();
20195                    @args = split(/\s*,\s*/ , $1)
20196                       if ($2 =~ /^\s*{\s*(.*?)\s*}\s*/);
20197                    # keep the context information of the definition
20198                    $macros->{$name}->{'line_nr'} = { 'file_name' => $line_nr->{'file_name'},
20199                         'line_nr' => $line_nr->{'line_nr'}, 'macro' => $line_nr->{'macro'} } if (defined($line_nr));
20200                    $macros->{$name}->{'args'} = \@args;
20201                    my $arg_index = 0;
20202                    my $debug_msg = '';
20203                    foreach my $arg (@args)
20204                    { # when expanding macros, the argument index is retrieved
20205                      # with args_index
20206                        $macros->{$name}->{'args_index'}->{$arg} = $arg_index;
20207                        $debug_msg .= "$arg($arg_index) ";
20208                        $arg_index++;
20209                    }
20210                    $macros->{$name}->{'body'} = '';
20211                    $state->{'macro'} = $macros->{$name};
20212                    print STDERR "# macro def $name: $debug_msg\n"
20213                         if ($T2H_DEBUG & $DEBUG_MACROS);
20214                }
20215                else
20216                {# it means we have a macro without a name
20217                    echo_error ("Macro definition without macro name $cline", $line_nr)
20218                        unless ($state->{'ignored'});
20219                }
20220                return;
20221            }
20222            elsif (defined($Texi2HTML::Config::texi_formats_map{$macro}))
20223            {
20224                my $tag;
20225                ($cline, $tag) = do_text_macro($macro, $cline, $state, $stack, $line_nr);
20226                # if it is a raw formatting command or a menu command
20227                # we must keep it for later, unless we are in an 'ignored'.
20228                # if in 'arg_expansion' we keep everything.
20229                my $macro_kept;
20230                if ((($state->{'raw'} or (($macro eq 'menu') and $Texi2HTML::Config::texi_formats_map{'menu'}) or (exists($region_lines{$macro}))) and !$state->{'ignored'}) or $state->{'arg_expansion'})
20231                {
20232                    add_prev($text, $stack, $tag);
20233                    $macro_kept = 1;
20234                }
20235                #dump_stack ($text, $stack, $state);
20236                next if $macro_kept;
20237                return if ($cline =~ /^\s*$/);
20238            }
20239#            elsif ($macro eq 'definfoenclose')
20240#            {
20241#                die "Not here definfoenclose expansion";
20242#                # FIXME if 'ignored' or 'arg_expansion' maybe we could parse
20243#                # the args anyway and don't take away the whole line?
20244#
20245#                # as in the makeinfo doc 'definfoenclose' may override
20246#                # texinfo @-commands like @i. It is what we do here.
20247#                if ($state->{'arg_expansion'})
20248#                {
20249#                    add_prev($text, $stack, "\@$macro" . $cline);
20250#                    return;
20251#                }
20252#                return if ($state->{'ignored'});
20253#                if ($cline =~ s/^\s+([a-z]+)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//)
20254#                {
20255#                    $info_enclose{$1} = [ $2, $3 ];
20256#                }
20257#                else
20258#                {
20259#                    echo_error("Bad \@$macro", $line_nr);
20260#                }
20261#                return if ($cline =~ /^\s*$/);
20262#                $cline =~ s/^\s*//;
20263#            }
20264#            elsif ($macro eq 'include')
20265#            {
20266#                die "Not here include expansion";
20267#                if ($state->{'arg_expansion'})
20268#                {
20269#                    add_prev($text, $stack, "\@$macro" . $cline);
20270#                    return;
20271#                }
20272#                return if ($state->{'ignored'});
20273#                #if (s/^\s+([\/\w.+-]+)//o)
20274#                if ($cline =~ s/^(\s+)(.*)//o)
20275#                {
20276#                    my $file_name = $2;
20277#                    $file_name =~ s/\s*$//;
20278#                    my $file = locate_include_file($file_name);
20279#                    if (defined($file))
20280#                    {
20281#                        open_file($file, $line_nr);
20282#                        print STDERR "# including $file\n" if $T2H_VERBOSE;
20283#                    }
20284#                    else
20285#                    {
20286#                        echo_error ("Can't find $file_name, skipping", $line_nr);
20287#                    }
20288#                }
20289#                else
20290#                {
20291#                    echo_error ("Bad include line: $cline", $line_nr);
20292#                    return;
20293#                }
20294#                return;
20295#            }
20296            elsif ($macro eq 'value')
20297            {
20298                if ($cline =~ s/^{($VARRE)}//)
20299                {
20300                    my $value = $1;
20301                    if ($state->{'arg_expansion'})
20302                    {
20303                        add_prev($text, $stack, "\@$macro" .'{'. $value .'}');
20304                        next;
20305                    }
20306                    next if ($state->{'ignored'});
20307                    my $expansion = "No value for $value";
20308                    $expansion = $value{$value} if (defined($value{$value}));
20309                    $cline = $expansion . $cline;
20310                }
20311                else
20312                {
20313                    if ($state->{'arg_expansion'})
20314                    {
20315                        add_prev($text, $stack, "\@$macro");
20316                        next;
20317                    }
20318                    next if ($state->{'ignored'});
20319                    echo_error ("bad \@value macro", $line_nr);
20320                }
20321            }
20322            elsif ($macro eq 'unmacro')
20323            { #FIXME with 'arg_expansion' should it be passed unmodified ?
20324                if ($state->{'ignored'})
20325                {
20326                    $cline =~ s/^\s+(\w+)//;
20327                }
20328                else
20329                {
20330                    delete $macros->{$1} if ($cline =~ s/^\s+(\w+)//);
20331                }
20332                return if ($cline =~ /^\s*$/);
20333                $cline =~ s/^\s*//;
20334            }
20335            elsif ($macro eq 'alias')
20336            { # FIXME what to do with 'arg_expansion' ?
20337                if ($cline =~ s/(\s+)([a-zA-Z][\w-]*)(\s*=\s*)([a-zA-Z][\w-]*)(\s*)//)
20338                {
20339                    if ($state->{'arg_expansion'})
20340                    {
20341                         my $line = "\@$macro" . $1.$2.$3.$4;
20342                         $line .= $5 if (defined($4));
20343                         add_prev($text, $stack, $line);
20344                         next;
20345                    }
20346                    next if $state->{'ignored'};
20347                    $alias{$2} = $4;
20348                }
20349                else
20350                {
20351                    echo_error ("bad \@alias line", $line_nr);
20352                }
20353            }
20354            elsif (exists($macros->{$macro}))
20355            {# it must be before the handling of {, otherwise it is considered
20356             # to be regular texinfo @-command. Maybe it could be placed higher
20357             # if we want user defined macros to override texinfo @-commands
20358
20359             # in 'ignored' we parse macro defined args anyway as it removes
20360             # some text, but we don't expand the macro
20361
20362                my $ref = $macros->{$macro}->{'args'};
20363                # we remove any space/new line before the argument
20364                if ($cline =~ s/^\s*{\s*//)
20365                { # the macro has args
20366                    $state->{'macro_args'} = [ "" ];
20367                    $state->{'macro_name'} = $macro;
20368                    $state->{'macro_depth'} = 1;
20369                }
20370                elsif (($#$ref >= 1) or ($#$ref <0))
20371                { # no brace -> no arg
20372                    $cline = expand_macro ($macro, [], $cline, $line_nr, $state);
20373                    return;
20374                }
20375                else
20376                { # macro with one arg on the line
20377                    chomp $cline;
20378                    $cline = expand_macro ($macro, [$cline], "\n", $line_nr, $state);
20379                    return;
20380                }
20381            }
20382            elsif ($cline =~ s/^{//)
20383            {# we add nested commands in a stack. verb is also on the stack
20384             # but handled specifically.
20385             # we add it the comands even in 'ignored' as their result is
20386             # discarded when the closing brace appear, or the ifset or
20387             # iclear is closed.
20388                if ($macro eq 'verb')
20389                {
20390                    if ($cline =~ /^$/)
20391                    {
20392                        echo_error ("without associated character", $line_nr);
20393                        #warn "$ERROR verb at end of line";
20394                    }
20395                    else
20396                    {
20397                        $cline =~ s/^(.)//;
20398                        $state->{'verb'} = $1;
20399                    }
20400                }
20401                push (@$stack, { 'style' => $macro, 'text' => '' });
20402            }
20403            else
20404            {
20405                $cline = do_unknown(0, $macro, $cline, $text, $stack, $state, $line_nr);
20406            }
20407            next;
20408        }
20409        #elsif(s/^([^{}@]*)\@(.)//o)
20410        elsif($cline =~ s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
20411        {# ARG_EXPANSION
20412            # No need to warn here for @ followed by a character that
20413            # is not in any @-command and it is done later
20414            add_prev($text, $stack, $1) unless($state->{'ignored'});
20415            $cline = do_unknown(0, $2, $cline, $text, $stack, $state, $line_nr);
20416            next;
20417        }
20418        elsif ($cline =~ s/^([^{}]*)([{}])//o)
20419        {
20420         # in ignored section we cannot be sure that there is an @-command
20421         # already opened so we must discard the text.
20422         # ARG_EXPANSION
20423            add_prev($text, $stack, $1) unless($state->{'ignored'});
20424            if ($2 eq '{')
20425            {
20426              # this empty style is for a lone brace.
20427              # we add it even in 'ignored' as it is discarded when the closing
20428              # brace appear, or the ifset or iclear is closed.
20429                push @$stack, { 'style' => '', 'text' => '' };
20430            }
20431            else
20432            {
20433                if (@$stack)
20434                {
20435                    my $style = pop @$stack;
20436                    my $result;
20437                    if (($style->{'style'} ne '') and exists($info_enclose{$style->{'style'}}) and !$state->{'arg_expansion'})
20438                    {
20439                        $result = $info_enclose{$style->{'style'}}->[0] . $style->{'text'} . $info_enclose{$style->{'style'}}->[1];
20440                    }
20441                    elsif ($style->{'style'} ne '')
20442                    {
20443                        $result = '@' . $style->{'style'} . '{' . $style->{'text'} . '}';
20444                    }
20445                    else
20446                    {
20447                        $result = '{' . $style->{'text'};
20448                        # don't close { if we are closing stack as we are not
20449                        # sure this is a { ... } construct. i.e. we are
20450                        # not sure that the user properly closed the matching
20451                        # brace, so we don't close it ourselves
20452                        $result .= '}' unless ($state->{'close_stack'} or $state->{'arg_expansion'});
20453                    }
20454                    if ($state->{'ignored'})
20455                    {# ARG_EXPANSION
20456                        print STDERR "# Popped `$style->{'style'}' in ifset/ifclear\n" if ($T2H_DEBUG);
20457                        next;
20458                    }
20459                    add_prev ($text, $stack, $result);
20460                    #print STDERR "MACRO end $style->{'style'} remaining: $cline";
20461                    next;
20462                }
20463                else
20464                {# ARG_EXPANSION
20465                    # we warn in the last pass that there is a } without open
20466                    add_prev ($text, $stack, '}') unless($state->{'ignored'});
20467                }
20468            }
20469        }
20470        else
20471        {# ARG_EXPANSION
20472            #print STDERR "END_LINE $cline";
20473            add_prev($text, $stack, $cline) unless($state->{'ignored'});
20474            if ($state->{'line_command'})
20475            {
20476               if (!scalar(@$stack))
20477               {
20478                   print STDERR "BUG: empty state for $state->{'line_command'}\n";
20479                   return;
20480                   delete $state->{'line_command'};
20481               }
20482               while (!defined($stack->[-1]->{'line_command'}))
20483               {
20484                  my $top = pop @$stack;
20485                  # defer this to later?
20486                  echo_error ("unclosed command in \@$state->{'line_command'}: $top->{'style'}");
20487                  add_prev($text, $stack, "\@$top->{'style'}".'{'.$top->{'text'}.'}');
20488               }
20489               my $command = pop @$stack;
20490               ###################### debug
20491               if (!defined($command) or !defined($command->{'text'}) or
20492                 !defined($command->{'line_command'}) or ($command->{'line_command'} ne $state->{'line_command'}))
20493               {
20494                   print STDERR "BUG: messed $state->{'line_command'} stack\n";
20495                   delete $state->{'line_command'};
20496                   return;
20497               }
20498               ###################### end debug
20499               else
20500               {
20501                   delete $state->{'line_command'};
20502                   my $macro = $command->{'line_command'};
20503                   # definfoenclose and include are not kept
20504                   if ($macro eq 'definfoenclose')
20505                   {
20506                   # FIXME if 'ignored' or 'arg_expansion' maybe we could parse
20507                   # the args anyway and don't take away the whole line?
20508
20509                   # as in the makeinfo doc 'definfoenclose' may override
20510                   # texinfo @-commands like @i. It is what we do here.
20511                       if ($command->{'text'} =~ s/^\s+([a-z]+)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//)
20512                       {
20513                           $info_enclose{$1} = [ $2, $3 ];
20514                       }
20515                       else
20516                       {
20517                           echo_error("Bad \@$macro", $line_nr);
20518#print STDERR "arg: $command->{'text'}\n";
20519                       }
20520                       # ignore everything else on the line
20521                       return;# if ($cline =~ /^\s*$/);
20522                       #$cline =~ s/^\s*//;
20523                   }
20524                   elsif ($macro eq 'include')
20525                   {
20526                    #if (s/^\s+([\/\w.+-]+)//o)
20527                       if ($command->{'text'} =~ s/^(\s+)(.*)//o)
20528                       {
20529                           my $file_name = $2;
20530                           $file_name =~ s/\s*$//;
20531                           #$file_name = substitute_line($file_name, {'code_style' => 1});
20532                           $file_name = substitute_line($file_name, {'code_style' => 1, 'remove_texi' => 1});
20533                           my $file = locate_include_file($file_name);
20534                           if (defined($file))
20535                           {
20536                               my ($line_nr_file, $input_spool_file) = open_file($file, $line_nr->{'macro'});
20537                               ($line_nr, $state->{'input_spool'}) = ($line_nr_file, $input_spool_file) if (defined($line_nr_file));
20538                               print STDERR "# including $file\n" if $T2H_VERBOSE;
20539                           }
20540                           else
20541                           {
20542                              echo_error ("Can't find $file_name, skipping", $line_nr);
20543                           }
20544                       }
20545                       else
20546                       {
20547                           echo_error ("Bad include line: $command->{'text'}", $line_nr);
20548                       }
20549                       return;
20550                   }
20551                   else
20552                   { # these are kept (setfilename and documentencoding)
20553                       ($cline, $line) = misc_command_texi($command->{'text'},
20554                         $macro, $state, $line_nr);
20555                       add_prev ($text, $stack, "\@$macro" . $line);
20556                       next;
20557                   }
20558               }
20559            }
20560            last;
20561        }
20562    }
20563    return undef if ($state->{'ignored'});
20564    return 1;
20565} # end scan_texi
20566
20567sub close_structure_command($$$$)
20568{
20569    my $cmd_ref = shift;
20570    my $state = shift;
20571    my $unclosed_commands = shift;
20572    my $line_nr = shift;
20573    my $result;
20574
20575    if ($cmd_ref->{'style'} eq 'anchor')
20576    {
20577        my $anchor = $cmd_ref->{'text'};
20578        $anchor = normalise_node($anchor);
20579        if ($nodes{$anchor})
20580        {
20581            echo_error ("Duplicate node for anchor found: $anchor", $line_nr);
20582            return '';
20583        }
20584        $document_anchor_num++;
20585        $nodes{$anchor} = { 'anchor' => 1, 'seen' => 1, 'texi' => $anchor, 'id' => 'ANC' . $document_anchor_num};
20586        push @{$state->{'place'}}, $nodes{$anchor};
20587    }
20588    elsif ($cmd_ref->{'style'} eq 'footnote')
20589    {
20590        if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
20591        {
20592            $state->{'element'} = $state->{'footnote_element'};
20593            $state->{'place'} = $state->{'footnote_place'};
20594        }
20595    }
20596    elsif ($cmd_ref->{'style'} eq 'caption' or $cmd_ref->{'style'}
20597       eq 'shortcaption' and $state->{'float'})
20598    {
20599        my @texi_lines = map {$_ = $_."\n"} split (/\n/, $cmd_ref->{'text'});
20600        $state->{'float'}->{$cmd_ref->{'style'} . "_texi"} = \@texi_lines;
20601    }
20602    if (($cmd_ref->{'style'} eq 'titlefont') and ($cmd_ref->{'text'} =~ /\S/))
20603    {
20604        $state->{'element'}->{'titlefont'} = $cmd_ref->{'text'} unless ((exists($state->{'region'}) and ($state->{'region'} eq 'titlepage')) or defined($state->{'element'}->{'titlefont'})) ;
20605    }
20606    if (defined($Texi2HTML::Config::command_handler{$cmd_ref->{'style'}}))
20607    {
20608        $result = init_special($cmd_ref->{'style'},$cmd_ref->{'text'});
20609        if ($unclosed_commands)
20610        {
20611            $result .= "\n"; # the end of line is eaten by init_special
20612            echo_error("Closing specially handled \@-command $cmd_ref->{'style'}",$line_nr);
20613        }
20614    }
20615    elsif ($cmd_ref->{'style'})
20616    {
20617        $result = '@' . $cmd_ref->{'style'} . '{' . $cmd_ref->{'text'};
20618        $result .= '}' unless ($unclosed_commands);
20619    }
20620    else
20621    {
20622        $result = '{' . $cmd_ref->{'text'};
20623        # don't close { if we are closing stack as we are not
20624        # sure this is a licit { ... } construct.
20625        $result .= '}' unless ($unclosed_commands);
20626    }
20627    return $result;
20628}
20629
20630sub scan_structure($$$$;$)
20631{
20632    my $line = shift;
20633    my $text = shift;
20634    my $stack = shift;
20635    my $state = shift;
20636    my $line_nr = shift;
20637
20638    die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
20639    my $cline = $line;
20640    #print STDERR "SCAN_STRUCTURE: $line";
20641    #dump_stack ($text, $stack, $state);
20642    if (!$state->{'raw'} and (!exists($state->{'region_lines'})))
20643    {
20644        if (!$state->{'verb'} and $state->{'menu'} and $cline =~ /^\*/o)
20645        {
20646        # new menu entry
20647            my $menu_line = $cline;
20648            my $node;
20649            if ($cline =~ /^\*\s+($NODERE)::/)
20650            {
20651                $node = $1;
20652            }
20653            elsif ($cline =~ /^\*\s+([^:]+):\s*([^\t,\n]*?)([\t,\n]|\.\s)/)
20654            {
20655                #$name = $1;
20656                $node = $2;
20657            }
20658            if ($node)
20659            {
20660                menu_entry_texi(normalise_node($node), $state, $line_nr);
20661            }
20662        }
20663    }
20664
20665    while(1)
20666    {
20667        # scan structure
20668	#print STDERR "WHILE (s):$cline";
20669	#dump_stack($text, $stack, $state);
20670
20671        # as texinfo 4.5
20672        # verbatim might begin at another position than beginning
20673        # of line, and end verbatim might too. To end a verbatim section
20674        # @end verbatim must have exactly one space between end and verbatim
20675        # things following end verbatim are not ignored.
20676        #
20677        # html might begin at another position than beginning
20678        # of line, but @end html must begin the line, and have
20679        # exactly one space. Things following end html are ignored.
20680        # tex and ignore works like html
20681        #
20682        # ifnothtml might begin at another position than beginning
20683        # of line, and @end  ifnothtml might too, there might be more
20684        # than one space between @end and ifnothtml but nothing more on
20685        # the line.
20686        # @end itemize, @end ftable works like @end ifnothtml.
20687        # except that @item on the same line than @end vtable doesn't work
20688        #
20689        # text right after the itemize before an item is displayed.
20690        # @item might be somewhere in a line.
20691        # strangely @item on the same line than @end vtable doesn't work
20692        # there should be nothing else than a command following @itemize...
20693        #
20694        # see more examples in formatting directory
20695
20696        if ($state->{'raw'})
20697        {
20698            my $tag = $state->{'raw'};
20699            ################# debug
20700            if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
20701            {
20702                print STDERR "Bug: raw or special: $tag but not on top of stack\n";
20703                print STDERR "line: $cline";
20704                dump_stack($text, $stack, $state);
20705                exit 1;
20706            }
20707            ################# end debug
20708            # macro_regexp
20709            if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $tag))
20710            {
20711                $cline =~ s/^(.*?)\@end\s$tag//;
20712                add_prev ($text, $stack, $1);
20713                delete $state->{'raw'};
20714                my $style = pop @$stack;
20715                if (defined($Texi2HTML::Config::command_handler{$tag}))
20716                { # replace the special region by what init_special give
20717                    if ($style->{'text'} !~ /^\s*$/)
20718                    {
20719                        add_prev ($text, $stack, init_special($style->{'style'}, $style->{'text'}));
20720                    }
20721
20722                }
20723                else
20724                {
20725                    add_prev ($text, $stack, $style->{'text'} . "\@end $tag");
20726                }
20727                next;
20728            }
20729            else
20730            {
20731                add_prev ($text, $stack, $cline);
20732                return if (defined($Texi2HTML::Config::command_handler{$tag}));
20733                last;
20734            }
20735        }
20736
20737        if (defined($state->{'verb'}))
20738        {
20739            my $char = quotemeta($state->{'verb'});
20740            if ($cline =~ s/^(.*?)$char\}/\}/)
20741            {
20742                add_prev($text, $stack, $1 . $state->{'verb'});
20743                $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
20744                delete $state->{'verb'};
20745                next;
20746            }
20747            else
20748            {
20749                add_prev($text, $stack, $cline);
20750                last;
20751            }
20752        }
20753
20754        # macro_regexp
20755        if ($cline =~ s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
20756        {
20757            add_prev($text, $stack, $1);
20758            my $end_tag = $2;
20759            #print STDERR "END STRUCTURE $end_tag\n";
20760            $state->{'detailmenu'}-- if ($end_tag eq 'detailmenu' and $state->{'detailmenu'});
20761            if (defined($state->{'text_macro_stack'})
20762               and @{$state->{'text_macro_stack'}}
20763               and ($end_tag eq $state->{'text_macro_stack'}->[-1]))
20764            {
20765                pop @{$state->{'text_macro_stack'}};
20766                if (exists($region_lines{$end_tag}))
20767                { # end a region_line macro, like documentdescription, copying
20768                    print STDERR "Bug: end_tag $end_tag ne $state->{'region_lines'}->{'format'}\n"
20769                        if ($end_tag ne $state->{'region_lines'}->{'format'});
20770                    print STDERR "Bug: end_tag $end_tag ne $state->{'region'}\n"
20771                        if ($end_tag ne $state->{'region'});
20772                    $state->{'region_lines'}->{'number'}--;
20773                    if ($state->{'region_lines'}->{'number'} == 0)
20774                    {
20775                        close_region($state);
20776                    }
20777		    #dump_stack($text, $stack, $state);
20778                }
20779                if ($end_tag eq 'menu' or $Texi2HTML::Config::region_formats_kept{$end_tag})
20780                {
20781                    add_prev($text, $stack, "\@end $end_tag");
20782                }
20783                else
20784                {
20785			#print STDERR "End $end_tag\n";
20786			#dump_stack($text, $stack, $state);
20787                    return if ($cline =~ /^\s*$/);
20788                }
20789                $state->{'menu'}-- if ($end_tag eq 'menu');
20790            }
20791            elsif ($Texi2HTML::Config::texi_formats_map{$end_tag})
20792            {
20793                echo_error ("\@end $end_tag without corresponding element", $line_nr);
20794                #dump_stack($text, $stack, $state);
20795            }
20796            else
20797            {
20798                if ($end_tag eq 'float' and $state->{'float'})
20799                {
20800                    delete $state->{'float'};
20801                }
20802                elsif ($end_tag eq $state->{'table_stack'}->[-1])
20803                {
20804                    enter_table_index_entry($text, $stack, $state, $line_nr);
20805                    pop @{$state->{'table_stack'}};
20806                }
20807                #add end tag
20808                add_prev($text, $stack, "\@end $end_tag");
20809            }
20810            next;
20811        }
20812        #elsif ($cline =~ s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
20813        # macro_regexp
20814        elsif ($cline =~ s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
20815        {
20816            add_prev($text, $stack, $1);
20817            my $macro = $2;
20818            #print STDERR "MACRO $macro\n";
20819            $macro = $alias{$macro} if (exists($alias{$macro}));
20820            if (defined($Texi2HTML::Config::misc_command{$macro}))
20821            {
20822                 my $line;
20823                 ($cline, $line) = misc_command_structure($cline, $macro, $state,
20824                       $line_nr);
20825                 add_prev ($text, $stack, "\@$macro".$line);
20826                 next;
20827            }
20828            elsif ($macro eq 'detailmenu')
20829            {
20830                add_prev ($text, $stack, "\@$macro" .  $cline);
20831                $state->{'detailmenu'}++;
20832                last;
20833            }
20834            elsif ($sec2level{$macro})
20835            {
20836                if ($cline =~ /^\s*(.*)$/)
20837                {
20838                    my $name = $1;
20839                    my $heading_ref = new_section_heading($macro, $name, $state);
20840                    #if ($state->{'place'} eq $no_element_associated_place)
20841                    if (exists($state->{'region_lines'}) and $state->{'region_lines'}->{'format'})
20842                    {
20843                        my $region = $state->{'region_lines'}->{'format'};
20844                        $state->{'region_lines'}->{'head_num'}++;
20845                        my $num = $state->{'region_lines'}->{'head_num'};
20846                        $heading_ref->{'id'} = "${target_prefix}${region}_HEAD$num";
20847                        $heading_ref->{'sec_num'} = "${region}_$num";
20848                        $heading_ref->{'region'} = $region;
20849                        $heading_ref->{'region_head_num'} = $num;
20850                    }
20851                    else
20852                    {
20853                        $document_head_num++;
20854                        $heading_ref->{'id'} = "HEAD$document_head_num";
20855                        $heading_ref->{'sec_num'} = $document_head_num;
20856                    }
20857                    # this is only used when there is a index entry after the
20858                    # heading
20859                    $heading_ref->{'target'} = $heading_ref->{'id'};
20860                    $heading_ref->{'heading'} = 1;
20861                    $heading_ref->{'tag_level'} = $macro;
20862                    $heading_ref->{'number'} = '';
20863
20864                    $state->{'element'} = $heading_ref;
20865                    push @{$state->{'place'}}, $heading_ref;
20866                    $headings{$heading_ref->{'sec_num'}} = $heading_ref;
20867                }
20868                add_prev ($text, $stack, "\@$macro" .  $cline);
20869                last;
20870            }
20871            elsif (index_command_prefix($macro) ne '')
20872            { # if we are already in a (v|f)table the construct is quite
20873              # wrong
20874              # FIXME should it be discarded?
20875              #  if ($state->{'item'})
20876              #  {
20877              #     echo_error("ignored \@$macro already in an \@$state->{'item'} entry", $line_nr);
20878              #     next;
20879              #  }
20880                my $index_prefix = index_command_prefix($macro);
20881                my $key = $cline;
20882                $key =~ s/^\s*//;
20883                enter_index_entry($index_prefix, $line_nr, $key, $state->{'place'}, $state->{'element'}, $macro, $state->{'region'});
20884                add_prev ($text, $stack, "\@$macro" .  $cline);
20885                last;
20886            }
20887            elsif (defined($Texi2HTML::Config::texi_formats_map{$macro}))
20888            {
20889                my $macro_kept;
20890                #print STDERR "TEXT_MACRO: $macro\n";
20891                if ($Texi2HTML::Config::texi_formats_map{$macro} eq 'raw')
20892                {
20893                    $state->{'raw'} = $macro;
20894                    #print STDERR "RAW\n";
20895                }
20896                elsif ($macro eq 'menu')
20897                {
20898                    $state->{'menu'}++;
20899                    delete ($state->{'prev_menu_node'});
20900                    push @{$state->{'text_macro_stack'}}, $macro;
20901                    #print STDERR "MENU (text_macro_stack: @{$state->{'text_macro_stack'}})\n";
20902                }
20903                elsif (exists($region_lines{$macro}))
20904                {
20905                    if (exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} ne $macro))
20906                    {
20907                        echo_error("\@$macro not allowed within $state->{'region_lines'}->{'format'}", $line_nr);
20908                        next;
20909                    }
20910                    open_region ($macro, $state);
20911                    if ($Texi2HTML::Config::region_formats_kept{$macro})
20912                    {
20913                        add_prev($text, $stack, "\@$macro");
20914                        $macro_kept = 1;
20915                        $state->{'region_lines'}->{'first_line'} = 1;
20916                    }
20917                    push @{$state->{'text_macro_stack'}}, $macro;
20918                }
20919                # if it is a raw formatting command or a menu command
20920                # we must keep it for later
20921                if (($state->{'raw'} and (!defined($Texi2HTML::Config::command_handler{$macro}))) or ($macro eq 'menu'))
20922                {
20923                    add_prev($text, $stack, "\@$macro");
20924                    $macro_kept = 1;
20925                }
20926                if ($state->{'raw'})
20927                {
20928                    push @$stack, { 'style' => $macro, 'text' => '' };
20929                }
20930                next if $macro_kept;
20931                #dump_stack ($text, $stack, $state);
20932                return if ($cline =~ /^\s*$/);
20933            }
20934            elsif ($macro eq 'float')
20935            {
20936                my ($style_texi, $label_texi) = split(/,/, $cline);
20937                $style_texi = normalise_space($style_texi);
20938                $label_texi = undef if (defined($label_texi) and ($label_texi =~ /^\s*$/));
20939                if (defined($label_texi))
20940                { # The float may be a target for refs if it has a label
20941                    $label_texi = normalise_node($label_texi);
20942                    if (exists($nodes{$label_texi}) and defined($nodes{$label_texi})
20943                         and $nodes{$label_texi}->{'seen'})
20944                    {
20945                        echo_error ("Duplicate label found: $label_texi", $line_nr);
20946                        while ($cline =~ /,/)
20947                        {
20948                            $cline =~ s/,.*$//;
20949                        }
20950                    }
20951                    else
20952                    {
20953                        my $float = { };
20954                        if (exists($nodes{$label_texi}) and defined($nodes{$label_texi}))
20955                        { # float appeared in a menu
20956                            $float = $nodes{$label_texi};
20957                        }
20958                        else
20959                        {
20960                            $nodes{$label_texi} = $float;
20961                        }
20962                        $float->{'float'} = 1;
20963                        $float->{'tag'} = 'float';
20964                        $float->{'texi'} = $label_texi;
20965                        $float->{'seen'} = 1;
20966                        $float->{'id'} = $label_texi;
20967                        $float->{'target'} = $label_texi;
20968#print STDERR "FLOAT: $float $float->{'texi'}, place $state->{'place'}\n";
20969                        push @{$state->{'place'}}, $float;
20970                        $float->{'element'} = $state->{'element'};
20971                        $state->{'float'} = $float;
20972                        $float->{'style_texi'} = $style_texi;
20973                        push @floats, $float;
20974                    }
20975                }
20976                add_prev($text, $stack, "\@$macro" . $cline);
20977                last;
20978            }
20979            elsif (defined($Texi2HTML::Config::def_map{$macro}))
20980            {
20981                # @ may protect end of line in @def. We reconstruct lines here.
20982                # in the texinfo manual is said that spaces after @ collapse
20983                if ($cline =~ /(\@+)\s*$/)
20984                {
20985                    my $at_at_end_of_line = $1;
20986                    if ((length($at_at_end_of_line) % 2) == 1)
20987                    {
20988                        #print STDERR "Line continue $cline";
20989                        my $def_line = $cline;
20990                        $def_line =~ s/\@\s*$//;
20991                        chomp($def_line);
20992                        $state->{'in_deff_line'} = "\@$macro" .$def_line;
20993                        return;
20994                    }
20995                }
20996                #We must enter the index entries
20997                my ($prefix, $entry, $argument) = get_deff_index($macro, $cline, $line_nr);
20998                # use deffn instead of deffnx for @-command record
20999                # associated with index entry
21000                my $idx_macro = $macro;
21001                $idx_macro =~ s/x$//;
21002                enter_index_entry($prefix, $line_nr, $entry, $state->{'place'},
21003                   $state->{'element'}, $idx_macro, $state->{'region'}) if ($prefix);
21004                $cline =~ s/(.*)//;
21005                add_prev($text, $stack, "\@$macro" . $1);
21006                # the text is discarded but we must handle correctly bad
21007                # texinfo with 2 @def-like commands on the same line
21008                substitute_text({'structure' => 1, 'place' => $state->{'place'} },undef, $argument);
21009            }
21010            elsif ($macro =~ /^itemx?$/)
21011            {
21012                enter_table_index_entry($text, $stack, $state, $line_nr);
21013                if ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/)
21014                {
21015                    $state->{'item'} = $macro;
21016                    push @$stack, { 'format' => 'index_item', 'text' => '' };
21017                }
21018                else
21019                {
21020                    add_prev($text, $stack, "\@$macro");
21021                }
21022            }
21023            elsif ($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'list' or $macro eq 'multitable'))
21024            { # We must enter the index entries of (v|f)table thus we track
21025              # in which table we are
21026                push @{$state->{'table_stack'}}, $macro;
21027                add_prev($text, $stack, "\@$macro");
21028            }
21029            elsif ($cline =~ s/^{//)
21030            {
21031                if ($macro eq 'verb')
21032                {
21033                    if ($cline =~ /^$/)
21034                    {
21035                        # We already warned in pass texi
21036                        #warn "$ERROR verb at end of line";
21037                    }
21038                    else
21039                    {
21040                        $cline =~ s/^(.)//;
21041                        $state->{'verb'} = $1;
21042                    }
21043                }
21044                elsif ($macro eq 'footnote' and $Texi2HTML::Config::SEPARATED_FOOTNOTES)
21045                {
21046                    $state->{'footnote_element'} = $state->{'element'};
21047                    $state->{'footnote_place'} = $state->{'place'};
21048                    $state->{'element'} = $footnote_element;
21049                    $state->{'place'} = $footnote_element->{'place'};
21050                }
21051                push (@$stack, { 'style' => $macro, 'text' => '' });
21052            }
21053            else
21054            {
21055                $cline = do_unknown (1, $macro, $cline, $text, $stack, $state, $line_nr);
21056            }
21057            next;
21058        }
21059        #elsif($cline =~ s/^([^{}@]*)\@(.)//o)
21060        elsif($cline =~ s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
21061        {
21062            add_prev($text, $stack, $1);
21063            $cline = do_unknown (1, $2, $cline, $text, $stack, $state, $line_nr);
21064            next;
21065        }
21066        elsif ($cline =~ s/^([^{}]*)([{}])//o)
21067        {
21068            add_prev($text, $stack, $1);
21069            if ($2 eq '{')
21070            {
21071                push @$stack, { 'style' => '', 'text' => '' };
21072            }
21073            else
21074            {
21075                if (@$stack)
21076                {
21077                    my $style = pop @$stack;
21078                    my $result;
21079                    add_prev ($text, $stack, close_structure_command($style,
21080                         $state, 0, $line_nr));
21081                    next;
21082                }
21083                else
21084                {
21085                    # We warn in the last pass
21086                    add_prev ($text, $stack, '}');
21087                }
21088            }
21089        }
21090        else
21091        {
21092            #print STDERR "END_LINE $cline";
21093            add_prev($text, $stack, $cline);
21094            enter_table_index_entry($text, $stack, $state, $line_nr);
21095            last;
21096        }
21097    }
21098    return 1;
21099} # end scan_structure
21100
21101sub close_style_command($$$$$)
21102{
21103  my $text = shift;
21104  my $stack = shift;
21105  my $state = shift;
21106  my $line_nr = shift;
21107  my $line = shift;
21108
21109  my $style = pop @$stack;
21110  my $command = $style->{'style'};
21111  my $result;
21112  if (!defined($command))
21113  {
21114     print STDERR "Bug: empty style in pass_text\n";
21115     return ($result, $command);
21116  }
21117  if (ref($::style_map_ref->{$command}) eq 'HASH')
21118  {
21119    push (@{$style->{'args'}}, $style->{'text'});
21120    $style->{'fulltext'} .= $style->{'text'};
21121    #my $number = 0;
21122    #foreach my $arg(@{$style->{'args'}})
21123    #{
21124       #print STDERR "  $number: $arg\n";
21125    #     $number++;
21126    #}
21127    $style->{'text'} = $style->{'fulltext'};
21128    $state->{'keep_texi'} = 0 if (
21129     ($::style_map_ref->{$command}->{'args'}->[$style->{'arg_nr'}] eq 'keep')
21130    and ($state->{'keep_nr'} == 1));
21131  }
21132  $state->{'no_paragraph'}-- if ($no_paragraph_macro{$command});
21133  $style->{'no_close'} = 1 if ($state->{'no_close'});
21134  if ($::style_map_ref->{$command} and (defined($style_type{$command})) and ((!$style->{'no_close'} and ($style_type{$command} eq 'style')) or ($style_type{$command} eq 'accent')))
21135  {
21136    my $style_command = pop @{$state->{'command_stack'}};
21137    ############################ debug
21138    if ($style_command ne $command)
21139    {
21140      print STDERR "Bug: $style_command on 'command_stack', not $command\n";
21141      push @$stack, $style;
21142      push @{$state->{'command_stack'}}, $style_command;
21143      print STDERR "Stacks before pop top:\n";
21144      dump_stack($text, $stack, $state);
21145      pop @$stack;
21146    }
21147    ############################ end debug
21148  }
21149  if ($state->{'keep_texi'})
21150  { # don't expand @-commands in anchor, refs...
21151    close_arg ($command, $style->{'arg_nr'}, $state);
21152    $result = '@' . $command . '{' . $style->{'text'} . '}';
21153  }
21154  else
21155  {
21156    $result = do_simple($command, $style->{'text'}, $state, $style->{'args'}, $line_nr, $style->{'no_open'}, $style->{'no_close'});
21157    if ($state->{'code_style'} < 0)
21158    {
21159      echo_error ("Bug: negative code_style: $state->{'code_style'}, line:$line", $line_nr);
21160    }
21161    if ($state->{'math_style'} < 0)
21162    {
21163      echo_error ("Bug: negative math_style: $state->{'math_style'}, line:$line", $line_nr);
21164    }
21165  }
21166  return ($result, $command);
21167}
21168
21169sub top_stack_is_menu($)
21170{
21171   my $stack = shift;
21172   my $top_stack = top_stack($stack, 1);
21173   return 0 if (!$format_type{$top_stack->{'format'}} or $format_type{$top_stack->{'format'}} ne 'menu');
21174   return 1;
21175}
21176
21177sub scan_line($$$$;$)
21178{
21179    my $original_line = shift;
21180    my $text = shift;
21181    my $stack = shift;
21182    my $state = shift;
21183    my $line_nr = shift;
21184
21185    die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
21186    my $cline = $original_line;
21187    #print STDERR "SCAN_LINE (@{$state->{'command_stack'}})".format_line_number($line_nr).": $original_line";
21188    #dump_stack($text, $stack,  $state );
21189    my $new_menu_entry; # true if there is a new menu entry
21190#    my $menu_description_in_format; # true if we are in a menu description
21191#                                # but in another format section (@table....)
21192
21193    # this can happen currently with quotations
21194    if (defined($state->{'prepend_text'}))
21195    {
21196        $cline = $state->{'prepend_text'} . $cline;
21197        $state->{'prepend_text'} = undef;
21198        delete $state->{'prepend_text'};
21199    }
21200
21201    # end of lines are really protected only for @def*
21202    # this cannot happen anymore, because the lines are concatenated
21203    # in pass_structure
21204    unless ($state->{'end_of_line_protected'}) # and $in_some_format)
21205    {
21206        if (!$state->{'raw'} and !$state->{'verb'} and $state->{'menu'})
21207        { # new menu entry
21208            my ($node, $name, $ending);
21209            if ($cline =~ s/^\*(\s+$NODERE)(::)//o)
21210            {
21211                $node = $1;
21212                $ending = $2;
21213            }
21214            elsif ($cline =~ s/^\*(\s+[^:]+):(\s*[^\t,\n]*?)(([\t,\n])|((\.)(\s)))//o)
21215            {
21216                $name = $1;
21217                $node = $2;
21218                $ending = $4;
21219                $ending = $6 if (!$ending);
21220                $cline = $7.$cline if (defined($7));
21221            }
21222            if ($node)
21223            {
21224                print STDERR "# Potential menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU);
21225                $new_menu_entry = 1;
21226                my $menu_entry = { 'name' => $name, 'node' => $node, 'ending' => $ending };
21227                # in SIMPLE_MENU case we don't begin a description, description is
21228                # just some normal (preformatted) text
21229                if ($Texi2HTML::Config::SIMPLE_MENU)
21230                {
21231                    add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry));
21232                    #dump_stack($text, $stack, $state);
21233                }
21234                else
21235                {
21236                    # close description and comment, if they are opened.
21237                    if (!close_menu_comment($text, $stack, $state, $line_nr)
21238                      and !close_menu_description($text, $stack, $state, $line_nr)
21239                      and $state->{'preformatted'})
21240                    {
21241                        close_paragraph($text, $stack, $state, $line_nr);
21242                    }
21243                    print STDERR "# New menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU);
21244                    my $fusionned_description = 0;
21245                    # fusionned looks better in preformatted. But some formats
21246                    # want to always distinguish link and description
21247                    if ($Texi2HTML::Config::SEPARATE_DESCRIPTION or !$state->{'preformatted'})
21248                    {
21249                        add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry));
21250                    }
21251                    else
21252                    {
21253                        $fusionned_description = 1;
21254                    }
21255                    push @$stack, {'format' => 'menu_description', 'text' => '', 'menu_entry' => $menu_entry, 'fusionned_description' => $fusionned_description};
21256                    $state->{'code_style'}++ if ($Texi2HTML::Config::format_code_style{'menu_description'});
21257                    if ($fusionned_description)
21258                    {
21259                        begin_paragraph($stack, $state) if $state->{'preformatted'};
21260                        add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry));
21261                    }
21262                 }
21263            }
21264            # we may be in a menu entry description, we close it
21265            # if there is an empty line, so the last arg is $cline
21266             if (!$new_menu_entry and close_menu_description($text, $stack, $state, $line_nr, $cline))
21267             {
21268                if ($state->{'preformatted'})
21269                {
21270                    begin_paragraph($stack, $state);
21271                }
21272                else
21273                {
21274                   # only start a menu_comment if right in menu and not in
21275                   # an en format below a menu because if not right
21276                   # in a menu we have no way to distinguish a menu_comment
21277                   # and some normal text in the format.
21278                   # also it is not started in preformatted environment
21279                   begin_format($text, $stack, $state, 'menu_comment', $cline, $line_nr) if ($stack->[-1]->{'format'} and $format_type{$stack->[-1]->{'format'}} and $format_type{$stack->[-1]->{'format'}} eq 'menu');
21280                }
21281            }
21282        }
21283        my $top_stack = top_stack($stack);
21284        if (($top_stack->{'format'} and $top_stack->{'format'} eq 'menu_description') or $state->{'raw'} or $state->{'preformatted'}  or $state->{'no_paragraph'} or $state->{'keep_texi'} or $state->{'remove_texi'})
21285        { # empty lines are left unmodified in these contexts.
21286          # it is also possible to be in preformatted within a menu_description
21287            if ($cline =~ /^\s*$/)
21288            {
21289                add_prev($text, $stack, do_text($cline,$state));
21290                return;
21291            }
21292        }
21293        else
21294        {
21295            if ($cline =~ /^\s*$/)
21296            {
21297                if ($state->{'paragraph_context'})
21298                { # An empty line ends a paragraph
21299                    close_paragraph($text, $stack, $state, $line_nr);
21300                }
21301                add_prev($text, $stack, &$Texi2HTML::Config::empty_line($cline,$state));
21302                return 1;
21303            }
21304            else
21305            {
21306                if (!no_paragraph($state,$cline))
21307                { # open a paragraph, unless the line begins with a macro that
21308                  # shouldn't trigger a paragraph opening
21309                    begin_paragraph($stack, $state);
21310                }
21311            }
21312        }
21313        # we flag specially deff_item and table line that contain only
21314        # inter_item_command, which typically is be @c, @comment, @*index, such
21315        # that the formatter can treat those specifically.
21316        my $top_format = top_stack($stack,2);
21317        if ($top_format->{'only_inter_commands'} and !$state->{'keep_texi'})
21318        {
21319            my $real_format = $top_format->{'format_ref'}->{'format'};
21320            my $next_tag = next_tag($cline);
21321            $next_tag = '' if (!defined($next_tag));
21322            my $next_end_tag = next_end_tag($cline);
21323            $next_end_tag = '' if (!defined($next_end_tag));
21324#print STDERR "$top_format->{'format'} $next_tag, end $next_end_tag :::$cline";
21325            delete $top_format->{'only_inter_commands'} unless
21326             (
21327              $Texi2HTML::Config::inter_item_commands{$next_tag} or
21328              (index_command_prefix($next_tag) ne '' and $Texi2HTML::Config::inter_item_commands{'cindex'}) or
21329              ($top_format->{'format'} eq 'deff_item' and "${real_format}x" eq $next_tag) or
21330              ($top_format->{'format'} ne 'deff_item' and $next_tag =~ /^itemx?$/) or
21331              ( $next_end_tag eq $real_format )
21332             );
21333              #print STDERR "STILL $top_format->{'only_inter_commands'}\n" if ($top_format->{'only_inter_commands'});
21334        }
21335    }
21336    delete $state->{'end_of_line_protected'}
21337       if ($state->{'end_of_line_protected'});
21338
21339    while(1)
21340    {
21341        # scan_line
21342        #print STDERR "WHILE (l): $cline|";
21343        # dump_stack($text, $stack, $state);
21344        # we're in a raw format (html, tex if !L2H, verbatim)
21345        if (defined($state->{'raw'}))
21346        {
21347            (dump_stack($text, $stack, $state), die "Bug for raw ($state->{'raw'})") if (! @$stack or ! ($stack->[-1]->{'style'} eq $state->{'raw'}));
21348            # macro_regexp
21349            if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $state->{'raw'}))
21350            # don't protect html, it is done by Texi2HTML::Config::raw if needed
21351            {
21352                $cline =~ s/^(.*?)\@end\s$state->{'raw'}//;
21353                print STDERR "# end raw $state->{'raw'}\n" if ($T2H_DEBUG & $DEBUG_FORMATS);
21354                add_prev ($text, $stack, $1);
21355                my $style = pop @$stack;
21356                if ($style->{'text'} !~ /^\s*$/)
21357                {
21358                    if ($state->{'keep_texi'})
21359                    {
21360                        add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}");
21361                    }
21362                    elsif ($state->{'remove_texi'})
21363                    {
21364                        add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi($style->{'style'}, $style->{'text'}));
21365                    }
21366                    else
21367                    {
21368                        add_prev($text, $stack, &$Texi2HTML::Config::raw($style->{'style'}, $style->{'text'}));
21369                    }
21370                }
21371                if (!$state->{'keep_texi'} and !$state->{'remove_texi'})
21372                {
21373                    # reopen preformatted if it was interrupted by the raw format
21374                    # if raw format is html the preformatted wasn't interrupted
21375                    begin_paragraph($stack, $state) if ($state->{'preformatted'} and (!$Texi2HTML::Config::format_in_paragraph{$state->{'raw'}}));
21376                    delete $state->{'raw'};
21377                    return if ($cline =~ /^\s*$/);
21378                }
21379                delete $state->{'raw'};
21380                next;
21381            }
21382            else
21383            {
21384                print STDERR "#within raw $state->{'raw'}:$cline" if ($T2H_DEBUG & $DEBUG_FORMATS);
21385                add_prev ($text, $stack, $cline);
21386                last;
21387            }
21388        }
21389
21390        # we are within a @verb
21391        if (defined($state->{'verb'}))
21392        {
21393            my $char = quotemeta($state->{'verb'});
21394            if ($cline =~ s/^(.*?)$char\}/\}/)
21395            {
21396                 if ($state->{'keep_texi'})
21397                 {
21398                     add_prev($text, $stack, $1 . $state->{'verb'});
21399                     $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
21400                 }
21401                 else
21402                 {
21403                     add_prev($text, $stack, do_text($1, $state));
21404                 }
21405                 delete $state->{'verb'};
21406                 next;
21407            }
21408            else
21409            {
21410                 add_prev($text, $stack, $cline);
21411                 last;
21412            }
21413        }
21414
21415        # a special case for @ followed by an end of line in deff
21416        # FIXME this is similar with makeinfo, but shouldn't that
21417        # be done for @floats and @quotations too? and @item, @center?
21418        # this piece of code is required, to avoid the 'cmd_line' to be
21419        # closed below
21420        # this cannot happen anymore, because the lines are concatenated
21421        # in pass_structure
21422        if ($state->{'end_of_line_protected'})# and in some format
21423        {
21424            print STDERR "Bug: 'end_of_line_protected' with text following: $cline\n"
21425                unless $cline =~ /^$/;
21426            return;
21427        }
21428
21429        # We handle now the end tags
21430        # macro_regexp
21431        if ($state->{'keep_texi'} and $cline =~ s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
21432        {
21433            my $end_tag = $2;
21434            add_prev($text, $stack, $1 . "\@end $end_tag");
21435            next;
21436        }
21437        # macro_regexp
21438        elsif ($state->{'remove_texi'} and $cline =~ s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
21439        {
21440            add_prev($text, $stack, $1);
21441            next;
21442        }
21443	# macro_regexp
21444        #if (s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)\s//o or s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)$//o)
21445        if ($cline =~ s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)//o)
21446        {
21447            add_prev($text, $stack, do_text($1, $state));
21448            my $end_tag = $2;
21449	    #print STDERR "END_MACRO $end_tag\n";
21450	    #dump_stack ($text, $stack, $state);
21451
21452            # First we test if the stack is not empty.
21453            # Then we test if the end tag is a format tag.
21454            # We then close paragraphs and preformatted at top of the stack.
21455            # We handle the end tag (even when it was not the tag which appears
21456            # on the top of the stack; in that case we close anything
21457            # until that element)
21458            my $top_stack = top_stack($stack);
21459            if (!$top_stack)
21460            {
21461                echo_error ("\@end $end_tag without corresponding opening", $line_nr);
21462                add_prev($text, $stack, "\@end $end_tag");
21463                next;
21464            }
21465
21466            if (!$format_type{$end_tag})
21467            {
21468                echo_warn ("Unknown \@end $end_tag", $line_nr);
21469                #warn "$ERROR Unknown \@end $end_tag\n";
21470                add_prev($text, $stack, "\@end $end_tag");
21471                next;
21472            }
21473            if (!close_menu_description($text, $stack, $state, $line_nr))
21474            {
21475               close_paragraph($text, $stack, $state, $line_nr);
21476            }
21477
21478            $top_stack = top_stack($stack);
21479            if (!$top_stack or (!defined($top_stack->{'format'})))
21480            {
21481                echo_error ("\@end $end_tag without corresponding opening element", $line_nr);
21482                add_prev($text, $stack, "\@end $end_tag");
21483                dump_stack ($text, $stack, $state) if ($T2H_DEBUG);
21484                next;
21485            }
21486            # Warn if the format on top of stack is not compatible with the
21487            # end tag, and find the end tag.
21488            unless (
21489                ($top_stack->{'format'} eq $end_tag)
21490                or
21491                (
21492                 $format_type{$end_tag} eq 'menu' and
21493                  $top_stack->{'format'} eq 'menu_comment'
21494                ) or
21495                (
21496                 $end_tag eq 'multitable' and $top_stack->{'format'} eq 'cell'
21497                ) or
21498                (
21499                 $format_type{$end_tag} eq 'list' and $top_stack->{'format'} eq 'item'
21500                ) or
21501                (
21502                  $format_type{$end_tag} eq 'table'
21503                  and
21504                  ($top_stack->{'format'} eq 'term' or $top_stack->{'format'} eq 'line')
21505                ) or
21506                (
21507                 defined($Texi2HTML::Config::def_map{$end_tag}) and
21508                 $top_stack->{'format'} eq 'deff_item'
21509                )
21510               )
21511            {
21512                # this is not the right format. We try to close other
21513                # formats to find the format we are searching for.
21514                # First we close paragraphs, as with a wrong $end_format
21515                # they may not be closed properly.
21516
21517                #print STDERR "  MISMATCH got $top_stack->{'format'} waited \@end $end_tag($top_stack->{'format'})\n";
21518                #dump_stack ($text, $stack, $state);
21519                close_paragraph($text, $stack, $state, $line_nr);
21520                $top_stack = top_stack($stack);
21521                if (!$top_stack or (!defined($top_stack->{'format'})))
21522                {
21523                    echo_error ("\@end $end_tag without corresponding opening element", $line_nr);
21524                    add_prev($text, $stack, "\@end $end_tag");
21525                    # at that point the dump_stack is not very useful, since
21526                    # close_paragraph above may hide interesting info
21527                    dump_stack ($text, $stack, $state) if ($T2H_DEBUG);
21528                    next;
21529                }
21530                my $waited_format = $top_stack->{'format'};
21531                $waited_format = $fake_format{$top_stack->{'format'}} if ($format_type{$top_stack->{'format'}} eq 'fake');
21532                echo_error ("waiting for end of $waited_format, found \@end $end_tag", $line_nr);
21533                #dump_stack ($text, $stack, $state);
21534                close_stack($text, $stack, $state, $line_nr, $end_tag);
21535                # FIXME this is too complex
21536                # an empty preformatted may appear when closing things as
21537                # when closed, formats reopen the preformatted environment
21538                # in case there is some text following, but we know it isn't
21539                # the case here, thus we can close paragraphs.
21540                close_paragraph($text, $stack, $state);
21541                my $new_top_stack = top_stack($stack);
21542                next unless ($new_top_stack and defined($new_top_stack->{'format'}) and (($new_top_stack->{'format'} eq $end_tag)
21543                   or (($format_type{$new_top_stack->{'format'}} eq 'fake') and ($fake_format{$new_top_stack->{'format'}} eq $format_type{$end_tag}))));
21544            }
21545            # We should now be able to handle the format
21546            if (defined($format_type{$end_tag}))
21547            {# remove the space or new line following the @end command
21548                $cline =~ s/\s//;
21549                if (end_format($text, $stack, $state, $end_tag, $line_nr))
21550                { # if end_format is false, paragraph is already begun
21551                    begin_paragraph_after_command($state,$stack,$end_tag,$cline);
21552                }
21553            }
21554            next;
21555        }
21556        # This is a macro
21557	#elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
21558        # macro_regexp
21559        elsif ($cline =~ s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@,]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or $cline =~ s/^([^{},@]*)\@([a-zA-Z][\w-]*)$//o)
21560        {
21561            my $before_macro = $1;
21562            my $macro = $2;
21563            $macro = $alias{$macro} if (exists($alias{$macro}));
21564            my $punct;
21565            if (!$state->{'keep_texi'} and $macro eq ':' and $before_macro =~ /(.)$/ and $Texi2HTML::Config::colon_command_punctuation_characters{$1})
21566            {
21567                $before_macro =~ s/(.)$//;
21568                $punct = $1;
21569            }
21570            add_prev($text, $stack, do_text($before_macro, $state));
21571            add_prev($text, $stack, &$Texi2HTML::Config::colon_command($punct)) if (defined($punct));
21572	    #print STDERR "MACRO $macro\n";
21573	    #print STDERR "LINE $cline";
21574	    #dump_stack ($text, $stack, $state);
21575
21576            close_paragraph($text, $stack, $state, $line_nr, 1) if ($Texi2HTML::Config::stop_paragraph_command{$macro} and !$state->{'keep_texi'});
21577
21578            if (defined($Texi2HTML::Config::misc_command{$macro}))
21579            {
21580                # Handle the misc command
21581                $cline = misc_command_text($cline, $macro, $stack, $state, $text, $line_nr);
21582                return unless (defined($cline));
21583                unless ($Texi2HTML::Config::misc_command{$macro}->{'keep'})
21584                {
21585                     begin_paragraph($stack, $state) if
21586                       (!no_paragraph($state,$cline));
21587                     next;
21588                }
21589            }
21590            if ($macro eq 'listoffloats')
21591            {
21592                if ($state->{'keep_texi'})
21593                {
21594                    if ($cline =~ s/(.*)//o)
21595                    {
21596                        add_prev($text, $stack, "\@$macro" . $1);
21597                    }
21598                    next;
21599                }
21600                return undef if ($state->{'remove_texi'});
21601
21602                if ($cline =~ s/^(\s+)(.*)//o)
21603                {
21604                    my $arg = $2;
21605                    my $style_id = cross_manual_line(normalise_space($arg));
21606                    my $style = substitute_line (&$Texi2HTML::Config::listoffloats_style($arg));
21607                    if (exists ($floats{$style_id}))
21608                    {
21609                         close_paragraph($text, $stack, $state, $line_nr);
21610                         my @listoffloats_entries = ();
21611                         foreach my $float (@{$floats{$style_id}->{'floats'}})
21612                         {
21613                              my $float_style = substitute_line(&$Texi2HTML::Config::listoffloats_float_style($arg, $float));
21614                              my $caption_lines = &$Texi2HTML::Config::listoffloats_caption($float);
21615                              # we set 'multiple_pass', 'region' and
21616                              # 'region_pass'such that index entries
21617                              # and anchors are not handled one more time;
21618                              # the caption has already been formatted,
21619                              # and these have been handled at the right place
21620                              # FIXME footnotes?
21621                              my $caption = substitute_text(prepare_state_multiple_pass($macro, $state), undef, @$caption_lines);
21622                              push @listoffloats_entries, &$Texi2HTML::Config::listoffloats_entry($arg, $float, $float_style, $caption, href($float, $state->{'element'}->{'file'}, $line_nr));
21623                         }
21624                         add_prev($text, $stack, &$Texi2HTML::Config::listoffloats($arg, $style, \@listoffloats_entries));
21625                    }
21626                    else
21627                    {
21628                         echo_warn ("Unknown float style $arg", $line_nr);
21629                    }
21630                }
21631                else
21632                {
21633                    echo_error ("Bad \@$macro line: $cline", $line_nr);
21634                }
21635                return undef;
21636            }
21637            # This is a @macroname{...} construct. We add it on top of stack
21638            # It will be handled when we encounter the '}'
21639            # There is a special case for def macros as @deffn{def} is licit
21640            if (!$Texi2HTML::Config::def_map{$macro} and $cline =~ s/^{//) #}
21641            {
21642                if ($macro eq 'verb')
21643                {
21644                    if ($cline =~ /^$/)
21645                    {
21646                        # Allready warned
21647                        #warn "$ERROR verb at end of line";
21648                    }
21649                    else
21650                    {
21651                        $cline =~ s/^(.)//;
21652                        $state->{'verb'} = $1;
21653                    }
21654                }
21655                # currently if remove_texi and anchor/ref/footnote
21656                # the text within the command is ignored
21657                # see t2h_remove_command in texi2html.init
21658                push (@$stack, { 'style' => $macro, 'text' => '', 'arg_nr' => 0 });
21659                $state->{'no_paragraph'}++ if ($no_paragraph_macro{$macro});
21660                open_arg($macro, 0, $state);
21661                my $real_style_command = 0;
21662                if (defined($style_type{$macro}) and (($style_type{$macro} eq 'style') or ($style_type{$macro} eq 'accent')))
21663                {
21664                     push (@{$state->{'command_stack'}}, $macro);
21665                     $real_style_command = 1;
21666                     #print STDERR "# Stacked $macro (@{$state->{'command_stack'}})\n" if ($T2H_DEBUG);
21667                }
21668                # FIXME give line, and modify line?
21669                &$Texi2HTML::Config::begin_style_texi($macro, $state, $stack, $real_style_command)
21670                  if (defined($Texi2HTML::Config::begin_style_texi)
21671                      and !($state->{'keep_texi'} or $state->{'remove_texi'}));
21672                next;
21673            }
21674
21675            # special case if we are checking itemize line. In that case
21676            # we want to make sure that there is no @item on the @itemize
21677            # line, otherwise it will be added on the front of another @item,
21678            # leading to an infinite loop...
21679
21680            if ($state->{'check_item'} and ($macro =~ /^itemx?$/ or $macro eq 'headitem'))
21681            {
21682                echo_error("\@$macro on \@$state->{'check_item'} line", $line_nr);
21683                next;
21684            }
21685
21686            # if we're keeping texi unmodified we can do it now
21687            if ($state->{'keep_texi'})
21688            {
21689                # We treat specially formats accepting {} on command line
21690                if ($macro eq 'multitable' or defined($Texi2HTML::Config::def_map{$macro}) or defined($sec2level{$macro}))
21691                {
21692                    add_prev($text, $stack, "\@$macro" . $cline);
21693                    $cline = '';
21694                    next;
21695                }
21696                # @ at the end of line may protect the end of line even when
21697                # keeping texi
21698                # FIXME: with deff handled differently, now this is unused.
21699                # in any case it should only be done in specific contexts
21700              #  if ($macro eq "\n")
21701              #  {
21702              #       $state->{'end_of_line_protected'} = 1;
21703              #       #print STDERR "PROTECTING END OF LINE\n";
21704              #  }
21705
21706                add_prev($text, $stack, "\@$macro");
21707                if ($Texi2HTML::Config::texi_formats_map{$macro} and $Texi2HTML::Config::texi_formats_map{$macro} eq 'raw')
21708                {
21709                    $state->{'raw'} = $macro;
21710                    push (@$stack, {'style' => $macro, 'text' => ''});
21711                }
21712                next;
21713            }
21714
21715            # If we are removing texi, the following macros are not removed
21716            # as is but modified. So they are collected first, as if we were
21717            # in normal text
21718
21719            # a raw macro beginning
21720            if ($Texi2HTML::Config::texi_formats_map{$macro} and $Texi2HTML::Config::texi_formats_map{$macro} eq 'raw')
21721            {
21722                if (!$Texi2HTML::Config::format_in_paragraph{$macro})
21723                { # close paragraph before verbatim (and tex if !L2H)
21724                    close_paragraph($text, $stack, $state, $line_nr);
21725                }
21726                $state->{'raw'} = $macro;
21727                push (@$stack, {'style' => $macro, 'text' => ''});
21728                return if ($cline =~ /^\s*$/);
21729                next;
21730            }
21731            my $simple_macro = 1;
21732            # An accent macro
21733            if (exists($Texi2HTML::Config::accent_map{$macro}))
21734            {
21735                # the command itself is not in the command stack, since with
21736                # braces, it is already popped when do_simple is called
21737                #push (@{$state->{'command_stack'}}, $macro);
21738                $cline =~ s/^\s*// if ($macro =~ /^[a-zA-Z]/);
21739                if ($cline =~ s/^(\S)//o)
21740                {
21741                    add_prev($text, $stack, do_simple($macro, $1, $state, [ $1 ], $line_nr));
21742                }
21743                else
21744                { # The accent is at end of line
21745                    add_prev($text, $stack, do_text($macro, $state));
21746                }
21747                #pop @{$state->{'command_stack'}};
21748            }
21749            # an @-command which should be like @command{}. We handle it...
21750            elsif ($::things_map_ref->{$macro})
21751            {
21752                echo_warn ("$macro requires {}", $line_nr);
21753                add_prev($text, $stack, do_simple($macro, '', $state));
21754            }
21755            # an @-command like @command
21756            elsif (defined($::simple_map_ref->{$macro}))
21757            {
21758                add_prev($text, $stack, do_simple($macro, '', $state));
21759            }
21760            else
21761            {
21762                $simple_macro = 0;
21763            }
21764            if ($simple_macro)
21765            {# if the macro didn't triggered a paragraph start it might now
21766                begin_paragraph($stack, $state) if
21767                   ($Texi2HTML::Config::no_paragraph_commands{$macro} and !no_paragraph($state,$cline));
21768                next;
21769            }
21770            # the following macros are modified or ignored if we are
21771            # removing texi, and they are not handled like macros in normal text
21772            if ($state->{'remove_texi'})
21773            {
21774                 # handle specially some macros
21775                 if ((index_command_prefix($macro) ne '') or
21776                      ($macro eq 'itemize') or
21777                      ($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'quotation'))
21778                      or ($macro eq 'multitable'))
21779                 {
21780                      return;
21781                 }
21782                 elsif ($macro eq 'enumerate')
21783                 {
21784                      my $spec;
21785                      ($cline, $spec) = parse_enumerate ($cline);
21786                      return if ($cline =~ /^\s*$/);
21787                      next;
21788                 }
21789                 elsif (defined($Texi2HTML::Config::def_map{$macro}))
21790                 {
21791                     my ($command, $style, $category, $name, $type, $class, $arguments, $args_array);
21792                     ($command, $style, $category, $name, $type, $class, $arguments, $args_array) = parse_def($macro, $cline, $line_nr);
21793                     # FIXME -- --- ''... lead to simple text in texi2html
21794                     # while they are kept as is in html coments by makeinfo
21795                     $category = remove_texi($category) if (defined($category));
21796                     $name = remove_texi($name) if (defined($name));
21797                     $type = remove_texi($type) if (defined($type));
21798                     $class = remove_texi($class) if (defined($class));
21799                     $arguments = remove_texi($arguments) if (defined($arguments));
21800                     chomp($arguments);
21801                     add_prev($text, $stack, &$Texi2HTML::Config::def_line_no_texi($category, $name, $type, $arguments));
21802                     return;
21803                }
21804                elsif (defined($sec2level{$macro}))
21805                { #FIXME  there is certainly more intelligent stuff to do
21806                    my $num;
21807                    if ($state->{'region'})
21808                    {
21809                        $state->{'head_num'}++;
21810                        $num = "$state->{'region'}_$state->{'head_num'}";
21811                    }
21812                    else
21813                    {
21814#                        $global_head_num++;
21815                        $num = $global_head_num;
21816                    }
21817                    my $heading_element = $headings{$num};
21818                    add_prev($text, $stack, &$Texi2HTML::Config::heading_no_texi($heading_element, $macro, $cline));
21819                    return;
21820                }
21821
21822                # ignore other macros
21823                next;
21824            }
21825
21826            # handle the other macros, we are in the context of normal text
21827            if (defined($sec2level{$macro}))
21828            {
21829                 #dump_stack($text, $stack, $state);
21830                 my $num;
21831                 if ($state->{'region'})
21832                 {
21833                     $state->{'head_num'}++;
21834                     $num = "$state->{'region'}_$state->{'head_num'}";
21835                     #$num = $state->{'head_num'};
21836                 }
21837                 else
21838                 {
21839                     $global_head_num++;
21840                     $num = $global_head_num;
21841                 }
21842                 my $heading_element = $headings{$num};
21843                 add_prev($text, $stack, &$Texi2HTML::Config::element_label($heading_element->{'id'}, $heading_element, $macro, $cline));
21844                 add_prev($text, $stack, &$Texi2HTML::Config::heading($heading_element, $macro, $cline, substitute_line($cline), $state->{'preformatted'}));
21845                 return;
21846            }
21847
21848            if (index_command_prefix($macro) ne '')
21849            {
21850                my $index_name = index_command_prefix($macro);
21851                $cline =~ s/^\s*//;
21852                my $entry_texi = $cline;
21853                chomp($entry_texi);
21854                $entry_texi =~ s/\s*$//;
21855                # FIXME multiple_pass?
21856                my $entry_text = substitute_line($entry_texi, prepare_state_multiple_pass($macro, $state));
21857                my ($index_entry, $index_label) = do_index_entry_label($macro,$state,$line_nr);
21858
21859                if (defined($index_entry))
21860                {
21861                   echo_warn ("(bug?) Index out of sync `$index_entry->{'texi'}' ne `$entry_texi'", $line_nr) if ($index_entry->{'texi'} ne $entry_texi);
21862                }
21863                add_prev($text, $stack, &$Texi2HTML::Config::index_entry_command($macro, $index_name, $index_label, $entry_texi, $entry_text));
21864                # it eats the end of line and therefore don't start
21865                # table entries nor close @center. These should be stopped
21866                # on the next line, though.
21867                return;
21868            }
21869            if ($macro eq 'insertcopying')
21870            {
21871                #close_paragraph($text, $stack, $state, $line_nr);
21872                add_prev($text, $stack, do_insertcopying($state));
21873                # reopen a preformatted format if it was interrupted by the macro
21874                begin_paragraph ($stack, $state) if ($state->{'preformatted'});
21875                return;
21876            }
21877            if ($macro =~ /^itemx?$/o or ($macro eq 'headitem'))
21878            {
21879		    #print STDERR "ITEM: $cline";
21880		    #dump_stack($text, $stack, $state);
21881                abort_empty_preformatted($stack, $state);
21882                # FIXME let the user be able not to close the paragraph
21883                close_paragraph($text, $stack, $state, $line_nr);
21884
21885                if (defined($Texi2HTML::Config::tab_item_texi))
21886                {
21887                   my $resline = &$Texi2HTML::Config::tab_item_texi($macro, $state->{'command_stack'}, $stack, $state, $cline, $line_nr);
21888                   $cline = $resline if (defined($resline));
21889                }
21890		    #print STDERR "ITEM after close para: $cline";
21891		    #dump_stack($text, $stack, $state);
21892                # these functions return the format if in the right context
21893                my $format;
21894                if ($format = add_item($text, $stack, $state, $line_nr))
21895                { # handle lists
21896                    push (@$stack, { 'format' => 'item', 'text' => '', 'format_ref' => $format });
21897                    begin_paragraph($stack, $state) unless (!$state->{'preformatted'} and no_line($cline));
21898#print STDERR "BEGIN ITEM $format->{'format'}\n";
21899#dump_stack($text, $stack, $state);
21900                }
21901                elsif ($format = add_term($text, $stack, $state, $line_nr))
21902                {# handle table @item term and restart another one
21903                    push (@$stack, { 'format' => 'term', 'text' => '', 'format_ref' => $format });
21904                    #$state->{'no_paragraph'}++;
21905                }
21906                elsif ($format = add_line($text, $stack, $state, $line_nr))
21907                {# close table text and erstart a term
21908                    push (@$stack, { 'format' => 'term', 'text' => '', 'format_ref' => $format });
21909                    #$state->{'no_paragraph'}++;
21910                }
21911                if ($format)
21912                {
21913                    my ($line, $open_command) = &$Texi2HTML::Config::format_list_item_texi($format->{'format'}, $cline, $format->{'prepended'}, $format->{'command'});
21914                    $cline = $line if (defined($line));
21915                    if ($open_command)
21916                    {
21917                         open_arg($format->{'command'},0, $state);
21918                         $format->{'command_opened'} = 1;
21919                    }
21920                    $format->{'item_cmd'} = $macro;
21921                    next;
21922                }
21923                $format = add_row ($text, $stack, $state, $line_nr); # handle multitable
21924                if (!$format)
21925                {
21926                    echo_warn ("\@$macro outside of table or list", $line_nr);
21927                }
21928                else
21929                {
21930                    push @$stack, {'format' => 'row', 'text' => '', 'item_cmd' => $macro, 'format_ref' => $format };
21931                    push @$stack, {'format' => 'cell', 'text' => '', 'format_ref' => $format};
21932                    $format->{'cell'} = 1;
21933                    if ($format->{'max_columns'})
21934                    {
21935                        begin_paragraph_after_command($state,$stack,$macro,$cline);
21936                    }
21937                    else
21938                    {
21939                        echo_warn ("\@$macro in empty multitable", $line_nr);
21940                    }
21941                }
21942                next;
21943            }
21944
21945            if ($macro eq 'tab')
21946            {
21947                abort_empty_preformatted($stack, $state);
21948                # FIXME let the user be able not to close the paragraph?
21949                close_paragraph($text, $stack, $state, $line_nr);
21950
21951                if (defined($Texi2HTML::Config::tab_item_texi))
21952                {
21953                   my $resline = &$Texi2HTML::Config::tab_item_texi($macro, $state->{'command_stack'}, $stack, $state, $cline, $line_nr);
21954                   $cline = $resline if (defined($resline));
21955                }
21956                my $format = add_cell ($text, $stack, $state);
21957                if (!$format)
21958                {
21959                    echo_warn ("\@$macro outside of multitable", $line_nr);
21960                }
21961                else
21962                {
21963                    push @$stack, {'format' => 'cell', 'text' => '', 'format_ref' => $format};
21964                    if (!$format->{'max_columns'})
21965                    {
21966                       echo_warn ("\@$macro in empty multitable", $line_nr);
21967                    }
21968                    elsif ($format->{'cell'} > $format->{'max_columns'})
21969                    {
21970                       echo_warn ("too much \@$macro (multitable has only $format->{'max_columns'} column(s))", $line_nr);
21971                    }
21972                }
21973                begin_paragraph_after_command($state,$stack,$macro,$cline);
21974                next;
21975            }
21976            # Macro opening a format (table, list, deff, example...)
21977            if ($format_type{$macro} and ($format_type{$macro} ne 'fake'))
21978            {
21979                $cline = begin_format($text, $stack, $state, $macro, $cline, $line_nr);
21980                # we keep the end of line for @center, and for formats
21981                # that have cmd_line opened and need to see the end of line
21982                next if (($macro eq 'center') or
21983                   (defined($Texi2HTML::Config::def_map{$macro}))
21984                   or ($macro eq 'float') or ($format_type{$macro} eq 'quotation'));
21985                return if ($cline =~ /^\s*$/);
21986                next;
21987            }
21988            $cline = do_unknown (2, $macro, $cline, $text, $stack, $state, $line_nr);
21989            next;
21990        }
21991        elsif($cline =~ s/^([^{}@,]*)\@([^\s\}\{\@]*)//o)
21992        { # A macro with a character which shouldn't appear in macro name
21993            add_prev($text, $stack, do_text($1, $state));
21994            $cline = do_unknown (2, $2, $cline, $text, $stack, $state, $line_nr);
21995            next;
21996        }
21997        # a brace, or an end of line and 'cmd_line' is on the top
21998        # of the stack
21999        elsif ($cline =~ s/^([^{},]*)([{}])//o or (@$stack and
22000             defined($stack->[-1]->{'style'}) and
22001             ($stack->[-1]->{'style'} eq 'cmd_line') and $cline =~ /^([^{},]*)$/o))
22002        {
22003            my $leading_text = $1;
22004            my $brace = $2;
22005            add_prev($text, $stack, do_text($leading_text, $state));
22006            if (defined($brace) and ($brace eq '{')) #'}'
22007            {
22008                add_prev($text, $stack, do_text('{',$state)); #}
22009                if ($state->{'math_style'})
22010                {
22011                    $state->{'math_brace'}++;
22012                }
22013                else
22014                {
22015                    unless ($state->{'keep_texi'} or $state->{'remove_texi'})
22016                    {
22017                        echo_error ("'{' without macro. Before: $cline", $line_nr);
22018                    }
22019                }
22020            }
22021            elsif (defined($brace) and ($brace eq '}') and
22022                    (!@$stack or (!defined($stack->[-1]->{'style'}))
22023            # with a non empty stack, but with 'cmd_line' as first item on
22024            # the stack there should not be a }
22025                       or ($stack->[-1]->{'style'} eq 'cmd_line'))
22026            # braces are allowed in math
22027                    or $state->{'math_brace'})
22028            {
22029                if ($state->{'keep_texi'})
22030                {
22031                    add_prev($text, $stack, '}');
22032                }
22033                elsif($state->{'math_style'} and $state->{'math_brace'})
22034                {
22035                    add_prev($text, $stack, do_text('}',$state));
22036                    $state->{'math_brace'}--;
22037                }
22038                else
22039                {
22040                    echo_error("'}' without opening '{' before: $cline", $line_nr);
22041                    #dump_stack($text, $stack, $state);
22042                }
22043            }
22044            else
22045            { # A @-command{ ...} is closed
22046                my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, $cline);
22047                add_prev($text, $stack, $result);
22048                if ($command eq 'cmd_line')
22049                {
22050                    if ($state->{'preformatted'})
22051                    { # inconditionally begin a preformatted section if needed
22052                        begin_paragraph($stack, $state);
22053                    }
22054                    $state->{'no_paragraph'}--;
22055                    return;
22056                }
22057                elsif ($Texi2HTML::Config::no_paragraph_commands{$command}
22058                  and !$state->{'keep_texi'} and !no_paragraph($state,$cline))
22059                {
22060                   begin_paragraph($stack, $state);
22061                }
22062            }
22063        }
22064        elsif ($cline =~ s/^([^,]*)[,]//o)
22065        {
22066             add_prev($text, $stack, do_text($1, $state));
22067             if (@$stack and defined($stack->[-1]->{'style'})
22068                  and (ref($::style_map_ref->{$stack->[-1]->{'style'}}) eq 'HASH'))
22069             {
22070                  my $macro = $stack->[-1]->{'style'};
22071                  my $style_args = $::style_map_ref->{$macro}->{'args'};
22072                  if (defined($style_args->[$stack->[-1]->{'arg_nr'} + 1]))
22073                  {
22074                       push (@{$stack->[-1]->{'args'}}, $stack->[-1]->{'text'});
22075                       $stack->[-1]->{'fulltext'} .= $stack->[-1]->{'text'} . do_text(',', $state);
22076                       $stack->[-1]->{'text'} = '';
22077                       close_arg ($macro, $stack->[-1]->{'arg_nr'}, $state);
22078                       $stack->[-1]->{'arg_nr'}++;
22079                       open_arg ($macro, $stack->[-1]->{'arg_nr'}, $state);
22080                       next;
22081                  }
22082             }
22083             add_prev($text, $stack, do_text(',', $state));
22084        }
22085        else
22086        { # no macro nor '}', but normal text
22087            add_prev($text, $stack, do_text($cline, $state));
22088            # @center/line term is closed at the end of line. When a
22089            # @-command which
22090            # keeps the texi as is happens on the @center line, the @center
22091            # is closed at the end of line appearing after the @-command
22092            # closing (for example @ref, @footnote).
22093            last if ($state->{'keep_texi'});
22094            #print STDERR "END LINE:$cline!!!\n";
22095            #dump_stack($text, $stack, $state);
22096            my $maybe_format_to_close = 1;
22097            my $in_table;
22098            while ($maybe_format_to_close)
22099            {
22100               $maybe_format_to_close = 0;
22101               my $top_format = top_stack($stack, 1);
22102               # the stack cannot easily be used, because there may be
22103               # opened commands in paragraphs if the center is in a
22104               # style command, like
22105               # @b{
22106               # bold
22107               #
22108               # @center centered bold
22109               #
22110               # }
22111               #
22112               # Therefore $state->{'paragraph_style'}->[-1] is used.
22113               #
22114               # The close_stack until 'center' is needed because
22115               # of constructs like
22116               #
22117               # @center something @table
22118               #
22119               # In that case what would be removed from the stack after
22120               # paragraph closing wold not be the @center. Such construct
22121               # is certainly incorrect, though.
22122               #
22123               # when 'closing_center' is true we don't retry to close
22124               # the @center line.
22125               if ($state->{'paragraph_style'}->[-1] eq 'center'
22126                   and !$state->{'closing_center'} and !$state->{'keep_texi'})
22127               {
22128                   $state->{'closing_center'} = 1;
22129                   close_paragraph($text, $stack, $state, $line_nr);
22130                   close_stack($text, $stack, $state, $line_nr, 'center');
22131                   delete $state->{'closing_center'};
22132                   my $center = pop @$stack;
22133                   add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command('center',$center->{'text'}));
22134                   my $top_paragraph_style = pop @{$state->{'paragraph_style'}};
22135
22136                   # center is at the bottom of the comand_stack because it
22137                   # may be nested in many way
22138                   my $bottom_command_stack = shift @{$state->{'command_stack'}};
22139                   print STDERR "Bug: closing center, top_paragraph_style: $top_paragraph_style, bottom_command_stack: $bottom_command_stack.\n"
22140                      if ($bottom_command_stack ne 'center' or $top_paragraph_style ne 'center');
22141                   $maybe_format_to_close = 1;
22142                   next;
22143               }
22144
22145               # @item line is closed by end of line. In general there should
22146               # not be a paragraph in a term. However it may currently
22147               # happen in construct like
22148               #
22149               # @table @asis
22150               # @item @cindex index entry
22151               # some text still in term, and in paragraph
22152               # Not in term anymore
22153               # ....
22154               #
22155               if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'term')
22156               {
22157                   close_paragraph($text, $stack, $state, $line_nr)
22158                       if ($state->{'paragraph_context'});
22159                   $in_table = add_term($text, $stack, $state, $line_nr);
22160                   if ($in_table)
22161                   {
22162                      $maybe_format_to_close = 1;
22163                      next;
22164                   }
22165               }
22166            }
22167            if ($in_table)
22168            {
22169               push (@$stack, { 'format' => 'line', 'text' => '', 'only_inter_commands' => 1, 'format_ref' => $in_table });
22170               begin_paragraph($stack, $state) if ($state->{'preformatted'});
22171            }
22172            last;
22173        }
22174    }
22175    return 1;
22176} # end scan_line
22177
22178sub open_arg($$$)
22179{
22180    my $macro = shift;
22181    my $arg_nr = shift;
22182    my $state = shift;
22183    if (ref($::style_map_ref->{$macro}) eq 'HASH')
22184    {
22185         my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
22186         if ($arg eq 'keep')
22187         {
22188             $state->{'keep_nr'}++;
22189             $state->{'keep_texi'} = 1;
22190         }
22191         elsif (!$state->{'keep_texi'})
22192         {
22193             if ($arg eq 'code')
22194             {
22195                 $state->{'code_style'}++;
22196             }
22197             elsif ($arg eq 'math')
22198             {
22199                 $state->{'math_style'}++;
22200                 if ($state->{'math_style'} == 1)
22201                 {
22202                     $state->{'math_brace'} = 0;
22203                     # FIXME quick hack to define @\ in @math
22204                     $::simple_map_ref->{'\\'} = $Texi2HTML::Config::simple_map_math{'\\'};
22205                     $::simple_map_pre_ref->{'\\'} = $Texi2HTML::Config::simple_map_pre_math{'\\'};
22206                     $::simple_map_texi_ref->{'\\'} = $Texi2HTML::Config::simple_map_texi_math{'\\'};
22207                 }
22208             }
22209         }
22210    }
22211    elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
22212    {
22213         $state->{'code_style'}++;
22214    }
22215}
22216
22217sub close_arg($$$)
22218{
22219    my $macro = shift;
22220    my $arg_nr = shift;
22221    my $state = shift;
22222    if (ref($::style_map_ref->{$macro}) eq 'HASH')
22223    {
22224         my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
22225         if ($arg eq 'keep')
22226         {
22227             $state->{'keep_nr'}--;
22228             $state->{'keep_texi'} = 0 if ($state->{'keep_nr'} == 0);
22229         }
22230         elsif (!$state->{'keep_texi'})
22231         {
22232             if ($arg eq 'code')
22233             {
22234                 $state->{'code_style'}--;
22235             }
22236             elsif ($arg eq 'math')
22237             {
22238                 $state->{'math_style'}--;
22239                 if ($state->{'math_style'} == 0)
22240                 {
22241                     delete $::simple_map_ref->{'\\'};
22242                     delete $::simple_map_pre_ref->{'\\'};
22243                     delete $::simple_map_texi_ref->{'\\'};
22244                 }
22245             }
22246         }
22247#print STDERR "c $arg_nr $macro $arg $state->{'code_style'}\n";
22248    }
22249    elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
22250    {
22251         $state->{'code_style'}--;
22252    }
22253}
22254
22255# add a special style on the top of the stack. This is used for commands
22256# that extend until the end of the line. Also add an entry in the @-command
22257# hashes for this fakes style.
22258sub open_cmd_line($$$$)
22259{
22260    my $stack = shift;
22261    my $state = shift;
22262    my $args = shift;
22263    my $function = shift;
22264    push @$stack, {'style' => 'cmd_line', 'text' => '', 'arg_nr' => 0};
22265    foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi)
22266    {
22267         $hash->{'cmd_line'}->{'args'} = $args;
22268         $hash->{'cmd_line'}->{'function'} = $function;
22269    }
22270    $state->{'no_paragraph'}++;
22271#    $state->{'cmd_line'} = 1;
22272    open_arg ('cmd_line', 0, $state);
22273}
22274
22275# finish @item line in @*table
22276sub add_term($$$$)
22277{
22278    my $text = shift;
22279    my $stack = shift;
22280    my $state = shift;
22281    my $line_nr = shift;
22282
22283    my $top_format = top_stack($stack);
22284    # FIXME: if there is a style on the stack, the closing of the term is
22285    # postpopned until the next end of line without opened @-command.
22286    # It is demonstrated in formatting/tables.texi.
22287    # to avoid that we should search deeper in the stack and close until
22288    # the term (what was done before)
22289    return unless (defined($top_format->{'format'}) and $top_format->{'format'} eq 'term');
22290
22291    #print STDERR "ADD_TERM\n";
22292
22293    my $term = pop @$stack;
22294    my $format = $stack->[-1];
22295    $format->{'paragraph_number'} = 0;
22296    my $formatted_command;
22297    my $leading_spaces;
22298    my $trailing_spaces;
22299    my $term_formatted;
22300    chomp ($term->{'text'});
22301    if (exists($::style_map_ref->{$format->{'command'}}) and ($style_type{$format->{'command'}} eq 'style'))
22302# and
22303#       !exists($Texi2HTML::Config::special_list_commands{$format->{'format'}}->{$format->{'command'}}) and ($style_type{$format->{'command'}} eq 'style'))
22304    {
22305         $leading_spaces = '';
22306         $trailing_spaces = '';
22307         $term_formatted = $term->{'text'};
22308         $term_formatted  =~ s/^(\s*)//o;
22309         $leading_spaces = $1 if (defined($1));
22310         $term_formatted  =~ s/(\s*)$//o;
22311         $trailing_spaces = $1 if (defined($1));
22312         unless ($format->{'command_opened'})
22313         {
22314             open_arg($format->{'command'}, 0, $state);
22315         }
22316         $term_formatted = do_simple($format->{'command'}, $term_formatted, $state, [$term_formatted]);
22317#         $term->{'text'} = $leading_spaces. $term->{'text'} .$trailing_spaces;
22318    }
22319    elsif (exists($::things_map_ref->{$format->{'command'}}))
22320    {
22321        $formatted_command = do_simple($format->{'command'}, '', $state);
22322        $format->{'formatted_command'} = $formatted_command;
22323    }
22324    my $index_label;
22325    if ($format->{'format'} =~ /^(f|v)/o)
22326    {
22327        my $index_entry;
22328        ($index_entry, $index_label) = do_index_entry_label($format->{'format'}, $state,$line_nr);
22329        print STDERR "Bug: no index entry for $term->{'text'}" unless defined($index_label);
22330    }
22331    add_prev($text, $stack, &$Texi2HTML::Config::table_item($term->{'text'}, $index_label,$format->{'format'},$format->{'command'}, $formatted_command,$state->{'command_stack'}, $term_formatted, $leading_spaces, $trailing_spaces, $format->{'item_cmd'}));
22332    #$state->{'no_paragraph'}--;
22333    return $format;
22334}
22335
22336sub add_row($$$$)
22337{
22338    my $text = shift;
22339    my $stack = shift;
22340    my $state = shift;
22341    my $line_nr = shift;
22342
22343    my $top_format = top_stack($stack);
22344    # @center a @item
22345    # will lead to row not being closed since a close paragraph doesn't
22346    # end the center.
22347    return unless (defined($top_format->{'format'}) and $top_format->{'format'} eq 'cell');
22348    my $cell = $top_format;
22349    my $format = $stack->[-3];
22350    print STDERR "Bug under row cell row not a multitable\n" if (!defined($format->{'format'}) or $format->{'format'} ne 'multitable');
22351    # print STDERR "ADD_ROW\n";
22352    # dump_stack($text, $stack, $state);
22353
22354    my $empty_first;
22355    if ($format->{'first'} and $format->{'cell'} == 1 and $stack->[-1]->{'text'} =~ /^\s*$/)
22356    {
22357       $empty_first = 1;
22358    }
22359    if ($format->{'cell'} > $format->{'max_columns'} or $empty_first)
22360    {
22361       my $cell = pop @$stack;
22362       print STDERR "Bug: not a cell ($cell->{'format'}) in multitable\n" if ($cell->{'format'} ne 'cell');
22363    }
22364    else
22365    {
22366       add_cell($text, $stack, $state);
22367    }
22368    my $row = pop @$stack;
22369    print STDERR "Bug: not a row ($row->{'format'}) in multitable\n" if ($row->{'format'} ne 'row');
22370    if ($format->{'max_columns'} and !$empty_first)
22371    {
22372       # FIXME have the cell count in row and not in table. table could have
22373       # the whole structure, but cell count doesn't make much sense
22374       add_prev($text, $stack, &$Texi2HTML::Config::row($row->{'text'}, $row->{'item_cmd'}, $format->{'columnfractions'}, $format->{'prototype_row'}, $format->{'prototype_lengths'}, $format->{'max_columns'}, $cell->{'only_inter_commands'}, $format->{'first'}));
22375    }
22376
22377    $format->{'first'} = 0 if ($format->{'first'});
22378
22379    return $format;
22380}
22381
22382# FIXME remove and merge, too much double checks and code
22383sub add_cell($$$$)
22384{
22385    my $text = shift;
22386    my $stack = shift;
22387    my $state = shift;
22388    my $line_nr = shift;
22389    my $top_format = top_stack($stack);
22390
22391    return unless (defined($top_format) and $top_format->{'format'} eq 'cell');
22392
22393    my $cell = pop @$stack;
22394    my $row = top_stack($stack);
22395    print STDERR "Bug: top_stack of cell not a row\n" if (!defined($row->{'format'}) or ($row->{'format'} ne 'row'));
22396    my $format = $stack->[-2];
22397    print STDERR "Bug under cell row not a multitable\n" if (!defined($format->{'format'}) or $format->{'format'} ne 'multitable');
22398    if ($format->{'cell'} <= $format->{'max_columns'})
22399    {
22400        add_prev($text, $stack, &$Texi2HTML::Config::cell($cell->{'text'}, $row->{'item_cmd'}, $format->{'columnfractions'}, $format->{'prototype_row'}, $format->{'prototype_lengths'}, $format->{'max_columns'}, $cell->{'only_inter_commands'}, $format->{'first'}));
22401    }
22402    $format->{'cell'}++;
22403    return $format;
22404}
22405
22406sub add_line($$$$)
22407{
22408    my $text = shift;
22409    my $stack = shift;
22410    my $state = shift;
22411    my $line_nr = shift;
22412    my $top_stack = top_stack($stack);
22413
22414    # if there is something like
22415    # @center centered @item new item
22416    # the item isn't opened since it is in @center, and center isn't closed
22417    # by an @item appearing here (unlike a paragraph).
22418    # the error message is '@item outside of table or list'.
22419    # texi2dvi also has issue, but makeinfo is happy, however it
22420    # produces bad nesting.
22421    return unless(defined($top_stack->{'format'}) and $top_stack->{'format'} eq 'line');
22422    #print STDERR "ADD_LINE\n";
22423    #dump_stack($text, $stack, $state);
22424
22425    my $line = pop @$stack;
22426    my $format = $stack->[-1];
22427    $format->{'paragraph_number'} = 0;
22428    if ($format->{'first'})
22429    {
22430        $format->{'first'} = 0;
22431        # we must have <dd> or <dt> following <dl> thus we do a
22432        # &$Texi2HTML::Config::table_line here too, although it could have
22433        # been a normal paragraph.
22434        add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}, $line->{'only_inter_commands'}, 1)) if ($line->{'text'} =~ /\S/o);
22435    }
22436    else
22437    {
22438        add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}, $line->{'only_inter_commands'}, 0));
22439    }
22440    return $format;
22441}
22442
22443# finish @enumerate or @itemize @item
22444sub add_item($$$$)
22445{
22446    my $text = shift;
22447    my $stack = shift;
22448    my $state = shift;
22449    my $line_nr = shift;
22450
22451    my $top_stack = top_stack($stack);
22452
22453    return unless (defined($top_stack->{'format'}) and $top_stack->{'format'} eq 'item');
22454    #print STDERR "ADD_ITEM: \n";
22455    #dump_stack($text, $stack, $state);
22456    # as in pre the end of line are kept, we must explicitely abort empty
22457    # preformatted, close_stack doesn't do that.
22458    my $item = pop @$stack;
22459    my $format = $stack->[-1];
22460
22461    $format->{'paragraph_number'} = 0;
22462    if ($format->{'format'} eq 'enumerate')
22463    {
22464        $format->{'number'} = '';
22465        my $spec = $format->{'spec'};
22466        $format->{'item_nr'}++;
22467        if ($spec =~ /^[0-9]$/)
22468        {
22469            $format->{'number'} = $spec + $format->{'item_nr'} - 1;
22470        }
22471        else
22472        {
22473            my $base_letter = ord('a');
22474            $base_letter = ord('A') if (ucfirst($spec) eq $spec);
22475
22476            my @letter_ords = decompose(ord($spec) - $base_letter + $format->{'item_nr'} - 1, 26);
22477            foreach my $ord (@letter_ords)
22478            {# FIXME we go directly to 'ba' after 'z', and not 'aa'
22479             #because 'ba' is 1,0 and 'aa' is 0,0.
22480                $format->{'number'} = chr($base_letter + $ord) . $format->{'number'};
22481            }
22482        }
22483    }
22484
22485    #dump_stack ($text, $stack, $state);
22486    # the element following ol or ul must be li. Thus even though there
22487    # is no @item we put a normal item.
22488    # don't do an item if it is the first and it is empty
22489    if (!$format->{'first'} or ($item->{'text'} =~ /\S/o))
22490    {
22491        my $formatted_command;
22492        if (defined($format->{'command'}) and exists($::things_map_ref->{$format->{'command'}}))
22493        {
22494            $formatted_command = do_simple($format->{'command'}, '', $state);
22495            $format->{'formatted_command'} = $formatted_command;
22496        }
22497	#chomp($item->{'text'});
22498        add_prev($text, $stack, &$Texi2HTML::Config::list_item($item->{'text'},$format->{'format'},$format->{'command'}, $formatted_command, $format->{'item_nr'}, $format->{'spec'}, $format->{'number'}, $format->{'prepended'}, $format->{'prepended_formatted'}, $item->{'only_inter_commands'}, $format->{'first'}));
22499    }
22500    if ($format->{'first'})
22501    {
22502        $format->{'first'} = 0;
22503    }
22504
22505    return $format;
22506}
22507
22508# format ``simple'' macros, that is macros without arg or style macros
22509sub do_simple($$$;$$$$)
22510{
22511    my $macro = shift;
22512    my $text = shift;
22513    my $state = shift;
22514    my $args = shift;
22515    my $line_nr = shift;
22516    my $no_open = shift;
22517    my $no_close = shift;
22518
22519    my $arg_nr = 0;
22520    $arg_nr = @$args - 1 if (defined($args));
22521
22522#print STDERR "DO_SIMPLE $macro ".format_line_number($line_nr)." $args $arg_nr (@$args)\n" if (defined($args));
22523    if (defined($::simple_map_ref->{$macro}))
22524    {
22525        # \n may in certain circumstances, protect end of lines
22526        # FIXME this cannot happen anymore, because the lines are concatenated
22527        # in pass_structure
22528       # if ($macro eq "\n")
22529       # {
22530       #     $state->{'end_of_line_protected'} = 1;
22531       #     #print STDERR "PROTECTING END OF LINE\n";
22532       # }
22533        if ($state->{'keep_texi'})
22534        {
22535            return "\@$macro";
22536        }
22537        elsif ($state->{'remove_texi'})
22538        {
22539#print STDERR "DO_SIMPLE remove_texi $macro\n";
22540            return  $::simple_map_texi_ref->{$macro};
22541        }
22542        else
22543        {
22544            return &$Texi2HTML::Config::simple_command($macro, $state->{'preformatted'}, $line_nr, $state);
22545        }
22546    }
22547    if (defined($::things_map_ref->{$macro}))
22548    {
22549        my $result;
22550        if ($state->{'keep_texi'})
22551        {
22552            return  "\@$macro" . '{}'.$text;
22553        }
22554        elsif ($state->{'remove_texi'})
22555        {
22556            return  $::texi_map_ref->{$macro}.$text;
22557#print STDERR "DO_SIMPLE remove_texi texi_map $macro\n";
22558        }
22559        else
22560        {
22561            return &$Texi2HTML::Config::thing_command($macro, $text, $state->{'preformatted'}, $line_nr, $state);
22562        }
22563    }
22564    elsif (defined($::style_map_ref->{$macro}))
22565    {
22566        if ($state->{'keep_texi'})
22567        {
22568            return "\@$macro" . '{' . $text . '}';
22569        }
22570        else
22571        {
22572            my $style;
22573            my $result;
22574            if ($state->{'remove_texi'})
22575            {
22576#print STDERR "REMOVE $macro, $style_map_texi_ref->{$macro}, fun $style_map_texi_ref->{$macro}->{'function'} remove cmd " . \&Texi2HTML::Config::t2h_remove_command . " ascii acc " . \&t2h_default_ascii_accent;
22577                $style = $::style_map_texi_ref->{$macro};
22578            }
22579            elsif ($state->{'preformatted'})
22580            {
22581                $style = $::style_map_pre_ref->{$macro};
22582            }
22583            else
22584            {
22585                $style = $::style_map_ref->{$macro};
22586            }
22587            if (defined($style))
22588            {                           # known style
22589                $result = &$Texi2HTML::Config::style($style, $macro, $text, $args, $no_close, $no_open, $line_nr, $state, $state->{'command_stack'});
22590            }
22591            if (!$no_close)
22592            {
22593                close_arg($macro,$arg_nr, $state);
22594            }
22595            return $result;
22596        }
22597    }
22598    elsif ($macro =~ /^special_(\w+)_(\d+)$/o)
22599    {
22600        my $style = $1;
22601        my $count = $2;
22602        print STDERR "Bug? text in \@$macro not empty.\n" if ($text ne '');
22603        if ($state->{'keep_texi'})
22604        {# text should be empty
22605            return "\@$macro" . '{' . $text . '}';
22606        }
22607        if (defined($Texi2HTML::Config::command_handler{$style}) and
22608          defined($Texi2HTML::Config::command_handler{$style}->{'expand'}))
22609        {
22610            my $struct_count = 1+ $special_commands{$style}->{'max'} - $special_commands{$style}->{'count'};
22611            if (($count != $struct_count) and $T2H_DEBUG)
22612            {
22613                print STDERR "count $count in \@special $style and structure $struct_count differ\n";
22614            }
22615            $special_commands{$style}->{'count'}--;
22616        }
22617        my $result = $Texi2HTML::Config::command_handler{$style}->{'expand'}
22618              ($style,$count,$state,$text);
22619        $result = '' if (!defined($result));
22620        return $result;
22621    }
22622    # Unknown macro
22623    my $result = '';
22624    my ($done, $result_text, $message) = &$Texi2HTML::Config::unknown_style($macro, $text,$state);
22625    if ($done)
22626    {
22627        echo_warn($message, $line_nr) if (defined($message));
22628        if (defined($result_text))
22629        {
22630            $result = $result_text;
22631        }
22632    }
22633    else
22634    {
22635        unless ($no_open)
22636        { # we warn only if no_open is true, i.e. it is the first time we
22637          # close the macro for a multiline macro
22638            echo_warn ("Unknown command with braces `\@$macro'", $line_nr);
22639            $result = do_text("\@$macro") . "{";
22640        }
22641        $result .= $text;
22642        $result .= '}' unless ($no_close);
22643    }
22644    return $result;
22645}
22646
22647sub do_unknown($$$$$$$)
22648{
22649    my $pass = shift;
22650    my $macro = shift;
22651    my $line = shift;
22652    my $text = shift;
22653    my $stack = shift;
22654    my $state = shift;
22655    my $line_nr = shift;
22656    #print STDERR "do_unknown[$pass]($macro) ::: $line";
22657
22658    my ($result_line, $result, $result_text, $message) = &$Texi2HTML::Config::unknown($macro, $line, $pass, $stack,$state);
22659    if ($result)
22660    {
22661         add_prev ($text, $stack, $result_text) if (defined($result_text));
22662         echo_warn($message, $line_nr) if (defined($message));
22663         # if $state->{'preformatted'}, assume that the preformatted is
22664         # already opened. Otherwise we may end up opening one each time
22665         # there is an unknown command.
22666         begin_paragraph_after_command($state, $stack, $macro, $result_line)
22667              if (!$state->{'preformatted'});
22668         return $result_line;
22669    }
22670    elsif ($pass == 2)
22671    {
22672         echo_warn ("Unknown command `\@$macro' (left as is)", $line_nr);
22673         add_prev ($text, $stack, do_text("\@$macro"));
22674         return $line;
22675    }
22676    elsif ($pass == 1)
22677    {
22678         add_prev ($text, $stack, "\@$macro");
22679         return $line;
22680    }
22681    elsif ($pass == 0)
22682    {
22683         add_prev ($text, $stack, "\@$macro") unless($state->{'ignored'});
22684         return $line;
22685    }
22686}
22687
22688# used only during @macro processing
22689sub add_text($@)
22690{
22691    my $string = shift;
22692
22693    return if (!defined($string));
22694    foreach my $scalar_ref (@_)
22695    {
22696        next unless defined($scalar_ref);
22697        if (!defined($$scalar_ref))
22698        {
22699            $$scalar_ref = $string;
22700        }
22701        else
22702        {
22703            $$scalar_ref .= $string;
22704        }
22705        return;
22706    }
22707}
22708
22709sub add_prev ($$$)
22710{
22711    my $text = shift;
22712    my $stack = shift;
22713    my $string = shift;
22714
22715    unless (defined($text) and ref($text) eq "SCALAR")
22716    {
22717       die "text not a SCALAR ref: " . ref($text) . "";
22718    }
22719    #if (!defined($stack) or (ref($stack) ne "ARRAY"))
22720    #{
22721    #    $string = $stack;
22722    #    $stack = [];
22723    #}
22724
22725    return if (!defined($string));
22726    if (@$stack)
22727    {
22728        $stack->[-1]->{'text'} .= $string;
22729        return;
22730    }
22731
22732    if (!defined($$text))
22733    {
22734         $$text = $string;
22735    }
22736    else
22737    {
22738         $$text .= $string;
22739    }
22740}
22741
22742sub close_stack_texi_structure($$$$)
22743{
22744    my $text = shift;
22745    my $stack = shift;
22746    my $state = shift;
22747    my $line_nr = shift;
22748
22749    return undef unless (@$stack or $state->{'raw'} or $state->{'macro'} or $state->{'macro_name'} or $state->{'ignored'});
22750
22751    #print STDERR "close_stack_texi_structure\n";
22752    #dump_stack ($text, $stack, $state);
22753    my $stack_level = $#$stack + 1;
22754    my $string = '';
22755
22756    if ($state->{'ignored'})
22757    {
22758        $string .= "\@end $state->{'ignored'} ";
22759        echo_warn ("closing $state->{'ignored'}", $line_nr);
22760    }
22761    if ($state->{'texi'})
22762    {
22763        if ($state->{'macro'})
22764        {
22765            $string .= "\@end macro ";
22766            echo_warn ("closing macro", $line_nr);
22767        }
22768        elsif ($state->{'macro_name'})
22769        {
22770            $string .= ('}' x $state->{'macro_depth'}) . " ";
22771            echo_warn ("closing $state->{'macro_name'} ($state->{'macro_depth'} braces missing)", $line_nr);
22772        }
22773        elsif ($state->{'verb'})
22774        {
22775            echo_warn ("closing \@verb", $line_nr);
22776            $string .= $state->{'verb'} . '}';
22777        }
22778        elsif ($state->{'raw'})
22779        {
22780            echo_warn ("closing \@$state->{'raw'} raw format", $line_nr);
22781            $string .= "\@end $state->{'raw'}";
22782        }
22783        if ($string ne '')
22784        {
22785            #print STDERR "close_stack scan_texi ($string)\n";
22786            scan_texi ($string, $text, $stack, $state, $line_nr);
22787            $string = '';
22788        }
22789    }
22790    elsif ($state->{'verb'})
22791    {
22792        $string .= $state->{'verb'};
22793    }
22794
22795    while ($stack_level--)
22796    {
22797        my $stack_text = $stack->[$stack_level]->{'text'};
22798        $stack_text = '' if (!defined($stack_text));
22799        if ($stack->[$stack_level]->{'format'})
22800        {
22801            my $format = $stack->[$stack_level]->{'format'};
22802            if ($format eq 'index_item')
22803            {
22804                enter_table_index_entry($text, $stack, $state, $line_nr);
22805                next;
22806            }
22807            elsif (!defined($format_type{$format}) or ($format_type{$format} ne 'fake'))
22808            {
22809                $stack_text = "\@$format\n" . $stack_text;
22810            }
22811        }
22812        elsif (defined($stack->[$stack_level]->{'style'}))
22813        {
22814            if ($state->{'structure'})
22815            {
22816                $stack_text = close_structure_command($stack->[$stack_level],
22817                   $state,1,$line_nr)
22818            }
22819            else
22820            {
22821                my $style = $stack->[$stack_level]->{'style'};
22822                if ($style ne '')
22823                {
22824                    $stack_text = "\@$style\{" . $stack_text;
22825                }
22826                else
22827                {# this is a lone opened brace. We readd it there.
22828                    $stack_text = "\{" . $stack_text;
22829                }
22830            }
22831        }
22832        pop @$stack;
22833        add_prev($text, $stack, $stack_text);
22834    }
22835    $stack = [ ];
22836
22837    $state->{'close_stack'} = 1;
22838    if ($string ne '')
22839    {
22840        if ($state->{'texi'})
22841        {
22842            #print STDERR "scan_texi in close_stack ($string)\n";
22843            scan_texi($string, $text, $stack, $state, $line_nr);
22844        }
22845        elsif ($state->{'structure'})
22846        {
22847            #print STDERR "scan_structure in close_stack ($string)\n";
22848            scan_structure($string, $text, $stack, $state, $line_nr);
22849        }
22850    }
22851    delete $state->{'close_stack'};
22852}
22853
22854sub open_region($$)
22855{
22856    my $command = shift;
22857    my $state = shift;
22858    if (!exists($state->{'region_lines'}))
22859    {
22860        $state->{'region_lines'}->{'format'} = $command;
22861        $state->{'region_lines'}->{'number'} = 1;
22862        $state->{'region_lines'}->{'kept_place'} = $state->{'place'};
22863        $state->{'place'} = $no_element_associated_place;
22864        $state->{'region'} = $command;
22865        $state->{'multiple_pass'}++;
22866        $state->{'region_pass'} = 1;
22867    }
22868    else
22869    {
22870        $state->{'region_lines'}->{'number'}++;
22871    }
22872}
22873
22874# close region like @insertcopying, titlepage...
22875# restore $state and delete the structure
22876sub close_region($)
22877{
22878    my $state = shift;
22879    $state->{'place'} = $state->{'region_lines'}->{'kept_place'};
22880    $state->{'multiple_pass'}--;
22881    delete $state->{'region_lines'}->{'number'};
22882    delete $state->{'region_lines'}->{'format'};
22883    delete $state->{'region_lines'}->{'kept_place'};
22884    delete $state->{'region_lines'};
22885    delete $state->{'region'};
22886    delete $state->{'region_pass'};
22887}
22888
22889# close the stack, closing @-commands and formats left open.
22890# if a $format is given if $format is encountered the closing stops
22891sub close_stack($$$$;$)
22892{
22893    my $text = shift;
22894    my $stack = shift;
22895    my $state = shift;
22896    my $line_nr = shift;
22897    my $format = shift;
22898
22899    #print STDERR "sub_close_stack\n";
22900    return unless (@$stack);
22901
22902    my $stack_level = $#$stack + 1;
22903
22904    #debugging
22905    #my $print_format = 'NO FORMAT';
22906    #$print_format = $format if ($format);
22907    #print STDERR "Close_stack: format $print_format\n";
22908
22909    while ($stack_level--)
22910    {
22911        if ($stack->[$stack_level]->{'format'})
22912        {
22913            my $stack_format = $stack->[$stack_level]->{'format'};
22914            last if (defined($format) and $stack_format eq $format);
22915            # We silently close paragraphs, preformatted sections and fake formats
22916            if ($stack_format eq 'paragraph')
22917            {
22918                my $paragraph = pop @$stack;
22919                add_prev ($text, $stack, do_paragraph($paragraph->{'text'}, $state, $stack));
22920            }
22921            elsif ($stack_format eq 'preformatted')
22922            {
22923                my $paragraph = pop @$stack;
22924                add_prev ($text, $stack, do_preformatted($paragraph->{'text'}, $state, $stack));
22925            }
22926            else
22927            {
22928                if ($fake_format{$stack_format})
22929                {
22930                    warn "# Closing a fake format `$stack_format'\n" if ($T2H_VERBOSE);
22931                }
22932                elsif ($stack_format ne 'center')
22933                { # we don't warn for center
22934                    echo_error ("closing `$stack_format'", $line_nr);
22935                    #dump_stack ($text, $stack, $state);
22936                }
22937                if ($state->{'keep_texi'})
22938                {
22939                   add_prev($text, $stack, "\@end $stack_format");
22940                }
22941                elsif (!$state->{'remove_texi'})
22942                {
22943                   end_format($text, $stack, $state, $stack_format, $line_nr)
22944                        unless ($format_type{$stack_format} eq 'fake');
22945                }
22946            }
22947        }
22948        else
22949        {
22950            my $style =  $stack->[$stack_level]->{'style'};
22951            ########################## debug
22952            if (!defined($style))
22953            {
22954                print STDERR "Bug: style not defined, on stack\n";
22955                dump_stack ($text, $stack, $state); # bug
22956            }
22957            ########################## end debug
22958            echo_warn ("closing \@-command $style", $line_nr) if ($style);
22959            my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, '');
22960            add_prev($text, $stack, $result) if (defined($result));
22961        }
22962    }
22963}
22964
22965# given a stack and a list of formats, return true if the stack contains
22966# these formats, first on top
22967sub stack_order($@)
22968{
22969    my $stack = shift;
22970    my $stack_level = $#$stack + 1;
22971    while (@_)
22972    {
22973        my $format = shift;
22974        while ($stack_level--)
22975        {
22976            if ($stack->[$stack_level]->{'format'})
22977            {
22978                if ($stack->[$stack_level]->{'format'} eq $format)
22979                {
22980                    $format = undef;
22981                    last;
22982                }
22983                else
22984                {
22985                    return 0;
22986                }
22987            }
22988        }
22989        return 0 if ($format);
22990    }
22991    return 1;
22992}
22993
22994sub top_format($)
22995{
22996    my $stack = shift;
22997    my $stack_level = $#$stack + 1;
22998    while ($stack_level--)
22999    {
23000        if ($stack->[$stack_level]->{'format'} and !$fake_format{$stack->[$stack_level]->{'format'}})
23001        {
23002             return $stack->[$stack_level];
23003        }
23004    }
23005    return undef;
23006}
23007
23008sub close_paragraph($$$;$$)
23009{
23010    my $text = shift;
23011    my $stack = shift;
23012    my $state = shift;
23013    my $line_nr = shift;
23014    my $no_preformatted_closing = shift;
23015    #print STDERR "CLOSE_PARAGRAPH\n";
23016    #dump_stack($text, $stack, $state);
23017
23018    #  close until the first format,
23019    #  duplicate stack of styles not closed
23020    my $new_stack;
23021    my $stack_level = $#$stack + 1;
23022
23023    while ($stack_level--)
23024    {
23025        last if ($stack->[$stack_level]->{'format'});
23026        my $style =  $stack->[$stack_level]->{'style'};
23027        # FIXME images, footnotes, xrefs, anchors?
23028        # seems that it is not possible, as
23029        # close_paragraph shouldn't be called with keep_texi
23030        # and when the arguments are expanded, there is a
23031        # substitute_line or similar with a new stack.
23032
23033        # the !exists($style_type{$style}) condition catches the unknown
23034        # @-commands: by default they are considered as style commands
23035        if (!exists($style_type{$style}) or $style_type{$style} eq 'style')
23036        {
23037            unshift @$new_stack, { 'style' => $style, 'text' => '', 'no_open' => 1, 'arg_nr' => 0 };
23038        }
23039        elsif (($style_type{$style} eq 'simple_style') or ($style_type{$style} eq 'accent'))
23040        {
23041        }
23042        else
23043        {
23044            print STDERR "BUG: special $style while closing paragraph\n";
23045        }
23046        $state->{'no_close'} = 1;
23047        my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, '');
23048        add_prev($text, $stack, $result) if (defined($result));
23049        delete $state->{'no_close'};
23050    }
23051
23052    if (!$state->{'paragraph_context'} and !$state->{'preformatted'} and defined($new_stack) and scalar(@$new_stack))
23053    { # in that case the $new_stack isn't recorded in $state->{'paragraph_macros'}
23054      # and therefore, it is lost
23055       print STDERR "BUG: closing paragraph, but not in paragraph/preformatted, and new_stack not empty ".format_line_number($line_nr)."\n";
23056       dump_stack($text, $stack, $state);
23057    }
23058    my $top_stack = top_stack($stack);
23059    if ($top_stack and !defined($top_stack->{'format'}))
23060    { #debug
23061         print STDERR "Bug: no format on top stack\n";
23062         dump_stack($text, $stack, $state);
23063    }
23064    if ($top_stack and ($top_stack->{'format'} eq 'paragraph'))
23065    {
23066        my $paragraph = pop @$stack;
23067        add_prev($text, $stack, do_paragraph($paragraph->{'text'}, $state, $stack));
23068        $state->{'paragraph_macros'} = $new_stack;
23069        return 1;
23070    }
23071    elsif ($top_stack and ($top_stack->{'format'} eq 'preformatted') and !$no_preformatted_closing)
23072    {
23073        my $paragraph = pop @$stack;
23074        add_prev($text, $stack, do_preformatted($paragraph->{'text'}, $state, $stack));
23075        $state->{'paragraph_macros'} = $new_stack;
23076        return 1;
23077    }
23078    return;
23079}
23080
23081sub abort_empty_preformatted($$)
23082{
23083    my $stack = shift;
23084    my $state = shift;
23085    if (@$stack and $stack->[-1]->{'format'}
23086       and ($stack->[-1]->{'format'} eq 'preformatted')
23087       and ($stack->[-1]->{'text'} !~ /\S/))
23088    {
23089        pop @$stack;
23090    }
23091}
23092
23093# for debugging
23094sub dump_stack($$$)
23095{
23096    my $text = shift;
23097    my $stack = shift;
23098    my $state = shift;
23099
23100    if (defined($$text))
23101    {
23102        print STDERR "text: $$text\n";
23103    }
23104    else
23105    {
23106        print STDERR "text: UNDEF\n";
23107    }
23108    my $in_remove = 0;
23109    my $in_simple_format = 0;
23110    my $in_keep = 0;
23111    $in_keep = 1 if ($state->{'keep_texi'});
23112    if (!$in_keep)
23113    {
23114        $in_simple_format = 1 if ($state->{'simple_format'});
23115        $in_remove = 1 if ($state->{'remove_texi'}  and !$in_simple_format);
23116    }
23117    print STDERR "state(k${in_keep}s${in_simple_format}r${in_remove}): ";
23118    foreach my $key (keys(%$state))
23119    {
23120        my $value = 'UNDEF';
23121        $value = $state->{$key} if (defined($state->{$key}));
23122        print STDERR "$key: $value " if (!ref($value));
23123    }
23124    print STDERR "\n";
23125    my $stack_level = $#$stack + 1;
23126    while ($stack_level--)
23127    {
23128        print STDERR " $stack_level-> ";
23129        foreach my $key (keys(%{$stack->[$stack_level]}))
23130        {
23131            my $value = 'UNDEF';
23132            $value = $stack->[$stack_level]->{$key} if
23133                (defined($stack->[$stack_level]->{$key}));
23134            print STDERR "$key: $value ";
23135        }
23136        print STDERR "\n";
23137    }
23138    if (defined($state->{'command_stack'}))
23139    {
23140        print STDERR "command_stack: ";
23141        foreach my $style (@{$state->{'command_stack'}})
23142        {
23143            print STDERR "($style) ";
23144        }
23145        print STDERR "\n";
23146    }
23147    if (defined($state->{'region_lines'}))
23148    {
23149        print STDERR "region_lines($state->{'region_lines'}->{'number'}): $state->{'region_lines'}->{'format'}\n";
23150    }
23151    if (defined($state->{'paragraph_macros'}))
23152    {
23153        print STDERR "paragraph_macros: ";
23154        foreach my $style (@{$state->{'paragraph_macros'}})
23155        {
23156            print STDERR "($style->{'style'})";
23157        }
23158        print STDERR "\n";
23159    }
23160    if (defined($state->{'preformatted_stack'}))
23161    {
23162        print STDERR "preformatted_stack: ";
23163        foreach my $preformatted_style (@{$state->{'preformatted_stack'}})
23164        {
23165            if ($preformatted_style eq '')
23166            {
23167               print STDERR ".";
23168               next;
23169            }
23170            my $pre_style = '';
23171            $pre_style = $preformatted_style->{'pre_style'} if (exists $preformatted_style->{'pre_style'});
23172            my $class = '';
23173            $class = $preformatted_style->{'class'} if (exists $preformatted_style->{'class'});
23174            my $style = '';
23175            $style = $preformatted_style->{'style'} if (exists $preformatted_style->{'style'});
23176            print STDERR "($pre_style, $class,$style)";
23177        }
23178        print STDERR "\n";
23179    }
23180    if (defined($state->{'text_macro_stack'}) and @{$state->{'text_macro_stack'}})
23181    {
23182        print STDERR "text_macro_stack: (@{$state->{'text_macro_stack'}})\n";
23183    }
23184}
23185
23186# for debugging
23187sub print_elements($)
23188{
23189    my $elements = shift;
23190    foreach my $elem(@$elements)
23191    {
23192        if ($elem->{'node'})
23193        {
23194            print STDERR "node-> $elem ";
23195        }
23196        else
23197        {
23198            print STDERR "chap=> $elem ";
23199        }
23200        foreach my $key (keys(%$elem))
23201        {
23202            my $value = "UNDEF";
23203            $value = $elem->{$key} if (defined($elem->{$key}));
23204            print STDERR "$key: $value ";
23205        }
23206        print STDERR "\n";
23207    }
23208}
23209
23210my @states_stack = ();
23211
23212sub push_state($)
23213{
23214   my $new_state = shift;
23215   push @states_stack, $new_state;
23216   $Texi2HTML::THISDOC{'state'} = $new_state;
23217}
23218
23219sub pop_state()
23220{
23221   pop @states_stack;
23222   if (@states_stack)
23223   {
23224       $Texi2HTML::THISDOC{'state'} = $states_stack[-1];
23225   }
23226   else
23227   {
23228       $Texi2HTML::THISDOC{'state'} = undef;
23229   }
23230}
23231
23232sub substitute_line($;$$)
23233{
23234    my $line = shift;
23235    my $state = shift;
23236    my $line_nr = shift;
23237    $state = {} if (!defined($state));
23238    $state->{'no_paragraph'} = 1;
23239    # this is usefull when called from &$I, and also for image files
23240    return simple_format($state, $line_nr, $line) if ($state->{'simple_format'});
23241    return substitute_text($state, $line_nr, $line);
23242}
23243
23244sub substitute_text($$@)
23245{
23246    my $state = shift;
23247    my $line_nr = shift;
23248    my @stack = ();
23249    my $text = '';
23250    my $result = '';
23251    if ($state->{'structure'})
23252    {
23253        initialise_state_structure($state);
23254    }
23255    elsif ($state->{'texi'})
23256    { # only in arg_expansion
23257        initialise_state_texi($state);
23258    }
23259    else
23260    {
23261#print STDERR "FILL_STATE substitute_text ($state->{'preformatted'}): @_\n";
23262        fill_state($state);
23263    }
23264    $state->{'spool'} = [];
23265    #print STDERR "SUBST_TEXT begin\n";
23266    push_state($state);
23267
23268    while (@_ or @{$state->{'spool'}} or $state->{'in_deff_line'})
23269    {
23270        my $line;
23271        if (@{$state->{'spool'}})
23272        {
23273             $line = shift @{$state->{'spool'}};
23274        }
23275        else
23276        {
23277            $line = shift @_;
23278        }
23279        if ($state->{'in_deff_line'})
23280        {
23281            if (defined($line))
23282            {
23283                $line = $state->{'in_deff_line'} . $line;
23284            }
23285            else
23286            {
23287                $line = $state->{'in_deff_line'};
23288            }
23289            delete $state->{'in_deff_line'};
23290        }
23291        else
23292        {
23293            next unless (defined($line));
23294        }
23295        #{ my $p_line = $line; chomp($p_line); print STDERR "SUBST_TEXT $p_line\n"; }
23296        if ($state->{'structure'})
23297        {
23298            scan_structure ($line, \$text, \@stack, $state);
23299        }
23300        elsif ($state->{'texi'})
23301        {
23302            scan_texi ($line, \$text, \@stack, $state);
23303        }
23304        else
23305        {
23306            scan_line($line, \$text, \@stack, $state, $line_nr);
23307        }
23308        next if (@stack);
23309        $result .= $text;
23310        $text = '';
23311    }
23312    # FIXME could we have the line number ?
23313    # close stack in substitute_text
23314    if ($state->{'texi'} or $state->{'structure'})
23315    {
23316        close_stack_texi_structure(\$text, \@stack, $state, undef);
23317    }
23318    else
23319    {
23320        close_stack(\$text, \@stack, $state, $line_nr);
23321    }
23322    #print STDERR "SUBST_TEXT end\n";
23323    pop_state();
23324    return $result . $text;
23325}
23326
23327sub print_lines($;$)
23328{
23329    my ($fh, $lines) = @_;
23330    $lines = $Texi2HTML::THIS_SECTION unless $lines;
23331    my @cnt;
23332    my $cnt;
23333    for my $line (@$lines)
23334    {
23335        print $fh $line;
23336	if (defined($Texi2HTML::Config::WORDS_IN_PAGE) and ($Texi2HTML::Config::SPLIT eq 'node'))
23337        {
23338            @cnt = split(/\W*\s+\W*/, $line);
23339            $cnt += scalar(@cnt);
23340        }
23341    }
23342    return $cnt;
23343}
23344
23345sub do_index_entry_label($$$)
23346{
23347    my $command = shift;
23348    my $state = shift;
23349    my $line_nr = shift;
23350    # index entries are not entered in special regions
23351    return (undef,'') if ($state->{'region'});
23352#    return '' if ($state->{'multiple_pass'} or $state->{'outside_document'});
23353    my $entry = shift @index_labels;
23354    if (!defined($entry))
23355    {
23356        echo_warn ("Not enough index entries !", $line_nr);
23357        return (undef,'');
23358    }
23359    if ($command ne $entry->{'command'})
23360    {
23361        # happens with bad texinfo with a line like
23362        # @deffn func aaaa args  @defvr c--ategory d--efvr_name
23363        echo_warn ("Waiting for index cmd \@$entry->{'command'}, got \@$command", $line_nr);
23364    }
23365
23366    print STDERR "(index $command) [$entry->{'entry'}] $entry->{'id'}\n"
23367        if ($T2H_DEBUG & $DEBUG_INDEX);
23368    return ($entry, &$Texi2HTML::Config::index_entry_label ($entry->{'id'}, $state->{'preformatted'}, substitute_line($entry->{'entry'}, prepare_state_multiple_pass("${command}_index", $state)),
23369      $index_prefix_to_name{$entry->{'prefix'}},
23370       $command, $entry->{'texi'}, substitute_line($entry->{'texi'}, prepare_state_multiple_pass("${command}_index", $state))));
23371}
23372
23373# decompose a decimal number on a given base. The algorithm looks like
23374# the division with growing powers (division suivant les puissances
23375# croissantes) ?
23376sub decompose($$)
23377{
23378    my $number = shift;
23379    my $base = shift;
23380    my @result = ();
23381
23382    return (0) if ($number == 0);
23383    my $power = 1;
23384    my $remaining = $number;
23385
23386    while ($remaining)
23387    {
23388         my $factor = $remaining % ($base ** $power);
23389         $remaining -= $factor;
23390         push (@result, $factor / ($base ** ($power - 1)));
23391         $power++;
23392    }
23393    return @result;
23394}
23395
23396# process a css file
23397sub process_css_file ($$)
23398{
23399    my $fh =shift;
23400    my $file = shift;
23401    my $in_rules = 0;
23402    my $in_comment = 0;
23403    my $in_import = 0;
23404    my $in_string = 0;
23405    my $rules = [];
23406    my $imports = [];
23407    while (my $line = <$fh>)
23408    {
23409	    #print STDERR "Line: $line";
23410        if ($in_rules)
23411        {
23412            push @$rules, $line;
23413            next;
23414        }
23415        my $text = '';
23416        while (1)
23417        {
23418		#sleep 1;
23419		#print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $line";
23420             if ($in_comment)
23421             {
23422                 if ($line =~ s/^(.*?\*\/)//)
23423                 {
23424                     $text .= $1;
23425                     $in_comment = 0;
23426                 }
23427                 else
23428                 {
23429                     push @$imports, $text . $line;
23430                     last;
23431                 }
23432             }
23433             elsif (!$in_string and $line =~ s/^\///)
23434             { # what do '\' do here ?
23435                 if ($line =~ s/^\*//)
23436                 {
23437                     $text .= '/*';
23438                     $in_comment = 1;
23439                 }
23440                 else
23441                 {
23442                     push (@$imports, $text. "\n") if ($text ne '');
23443                     push (@$rules, '/' . $line);
23444                     $in_rules = 1;
23445                     last;
23446                 }
23447             }
23448             elsif (!$in_string and $in_import and $line =~ s/^([\"\'])//)
23449             { # strings outside of import start rules
23450                 $text .= "$1";
23451                 $in_string = quotemeta("$1");
23452             }
23453             elsif ($in_string and $line =~ s/^(\\$in_string)//)
23454             {
23455                 $text .= $1;
23456             }
23457             elsif ($in_string and $line =~ s/^($in_string)//)
23458             {
23459                 $text .= $1;
23460                 $in_string = 0;
23461             }
23462             elsif ((! $in_string and !$in_import) and ($line =~ s/^([\\]?\@import)$// or $line =~ s/^([\\]?\@import\s+)//))
23463             {
23464                 $text .= $1;
23465                 $in_import = 1;
23466             }
23467             elsif (!$in_string and $in_import and $line =~ s/^\;//)
23468             {
23469                 $text .= ';';
23470                 $in_import = 0;
23471             }
23472             elsif (($in_import or $in_string) and $line =~ s/^(.)//)
23473             {
23474                  $text .= $1;
23475             }
23476             elsif (!$in_import and $line =~ s/^([^\s])//)
23477             {
23478                  push (@$imports, $text. "\n") if ($text ne '');
23479                  push (@$rules, $1 . $line);
23480                  $in_rules = 1;
23481                  last;
23482             }
23483             elsif ($line =~ s/^(\s)//)
23484             {
23485                  $text .= $1;
23486             }
23487             elsif ($line eq '')
23488             {
23489                  push (@$imports, $text);
23490                  last;
23491             }
23492        }
23493    }
23494    warn "$WARN string not closed in css file $file\n" if ($in_string);
23495    warn "$WARN comment not closed in css file $file\n" if ($in_comment);
23496    warn "$WARN \@import not finished in css file $file\n"  if ($in_import and !$in_comment and !$in_string);
23497    return ($imports, $rules);
23498}
23499
23500sub collect_all_css_files()
23501{
23502   my @css_import_lines;
23503   my @css_rule_lines;
23504
23505  # process css files
23506   foreach my $file (@Texi2HTML::Config::CSS_FILES)
23507   {
23508      my $css_file_fh;
23509      my $css_file;
23510      if ($file eq '-')
23511      {
23512         $css_file_fh = \*STDIN;
23513         $css_file = '-';
23514      }
23515      else
23516      {
23517         $css_file = locate_include_file ($file);
23518         unless (defined($css_file))
23519         {
23520            warn "css file $file not found\n";
23521            next;
23522         }
23523         unless (open (CSSFILE, "$css_file"))
23524         {
23525            warn "Cannot open ${css_file}: $!";
23526            next;
23527         }
23528         $css_file_fh = \*CSSFILE;
23529      }
23530      my ($import_lines, $rules_lines);
23531      ($import_lines, $rules_lines) = process_css_file ($css_file_fh, $css_file);
23532      push @css_import_lines, @$import_lines;
23533      push @css_rule_lines, @$rules_lines;
23534   }
23535
23536
23537   if ($T2H_DEBUG & $DEBUG_USER)
23538   {
23539      if (@css_import_lines)
23540      {
23541         print STDERR "# css import lines\n";
23542         foreach my $line (@css_import_lines)
23543         {
23544            print STDERR "$line";
23545         }
23546      }
23547      if (@css_rule_lines)
23548      {
23549         print STDERR "# css rule lines\n";
23550         foreach my $line (@css_rule_lines)
23551         {
23552            print STDERR "$line";
23553         }
23554      }
23555   }
23556   return (\@css_import_lines, \@css_rule_lines);
23557}
23558
23559sub init_with_file_name($)
23560{
23561   my $base_file = shift;
23562   set_docu_names($base_file, $Texi2HTML::THISDOC{'input_file_number'});
23563
23564   foreach my $handler(@Texi2HTML::Config::command_handler_init)
23565   {
23566      &$handler;
23567   }
23568}
23569
23570
23571#######################################################################
23572#
23573# Main processing, process all the files given on the command line
23574#
23575#######################################################################
23576
23577die "$0: missing file argument.\n$T2H_FAILURE_TEXT" unless (scalar(@ARGV) >= 1);
23578
23579my $file_number = 0;
23580# main processing
23581while(@ARGV)
23582{
23583   my $input_file_name = shift(@ARGV);
23584
23585   %Texi2HTML::THISDOC = ();
23586   $Texi2HTML::THIS_ELEMENT = undef;
23587
23588   foreach my $global_key (keys(%Texi2HTML::GLOBAL))
23589   {
23590      $Texi2HTML::THISDOC{$global_key} = $Texi2HTML::GLOBAL{$global_key};
23591   }
23592
23593   set_date() if ($Texi2HTML::GLOBAL{'current_lang'});
23594
23595   $Texi2HTML::THISDOC{'input_file_name'} = $input_file_name;
23596   $Texi2HTML::THISDOC{'input_file_number'} = $file_number;
23597
23598   my $input_file_base = $input_file_name;
23599   $input_file_base =~ s/\.te?x(i|info)?$//;
23600
23601   @{$Texi2HTML::TOC_LINES} = ();            # table of contents
23602   @{$Texi2HTML::OVERVIEW} = ();           # short table of contents
23603   # this could be done here, but perl warns that
23604   # `"Texi2HTML::TITLEPAGE" used only once' and it is reset in
23605   # &$Texi2HTML::Config::titlepage anyway
23606   # $Texi2HTML::TITLEPAGE = undef;
23607   @{$Texi2HTML::THIS_SECTION} = ();
23608
23609   # the reference to these hashes may be used before this point (for example
23610   # see makeinfo.init), so they should be kept as is and the values undef
23611   # but the key should not be deleted because the ref is on the key.
23612   foreach my $hash (\%Texi2HTML::HREF, \%Texi2HTML::NAME, \%Texi2HTML::NODE,
23613        \%Texi2HTML::NO_TEXI, \%Texi2HTML::SIMPLE_TEXT)
23614   {
23615       foreach my $key (keys(%$hash))
23616       {
23617           $hash->{$key} = undef;
23618       }
23619   }
23620
23621   $docu_dir = undef;    # directory of the document
23622   $docu_name = undef;   # basename of the document
23623   $docu_rdir = undef;   # directory for the output
23624   $docu_toc = undef;    # document's table of contents
23625   $docu_stoc = undef;   # document's short toc
23626   $docu_foot = undef;   # document's footnotes
23627   $docu_about = undef;  # about this document
23628   $docu_top = undef;    # document top
23629   $docu_doc = undef;    # document (or document top of split)
23630   $docu_frame = undef;  # main frame file
23631   $docu_toc_frame = undef;       # toc frame file
23632   $path_to_working_dir = undef;  # relative path leading to the working
23633                                  # directory from the document directory
23634   $docu_doc_file = undef;
23635   $docu_toc_file = undef;
23636   $docu_stoc_file = undef;
23637   $docu_foot_file = undef;
23638   $docu_about_file = undef;
23639   $docu_top_file = undef;
23640   $docu_frame_file = undef;
23641   $docu_toc_frame_file = undef;
23642
23643   if (!$Texi2HTML::Config::USE_SETFILENAME)
23644   {
23645      init_with_file_name ($input_file_base);
23646   }
23647
23648   # FIXME when to do that?
23649   ($Texi2HTML::THISDOC{'css_import_lines'}, $Texi2HTML::THISDOC{'css_lines'})
23650      = collect_all_css_files();
23651
23652   %region_lines = (
23653          'titlepage'            => [ ],
23654          'documentdescription'  => [ ],
23655          'copying'              => [ ],
23656   );
23657
23658   texinfo_initialization(0);
23659
23660   print STDERR "# reading from $input_file_name\n" if $T2H_VERBOSE;
23661
23662   @fhs = ();			# hold the file handles to read
23663
23664   $macros = undef;         # macros. reference on a hash
23665   %info_enclose = ();      # macros defined with definfoenclose
23666   @floats = ();            # floats list
23667   %floats = ();            # floats by style
23668   %nodes = ();             # nodes hash. The key is the texi node name
23669   %cross_reference_nodes = ();  # normalized node names arrays
23670
23671
23672   my ($texi_lines, $first_texi_lines, $lines_numbers)
23673        = pass_texi($input_file_name);
23674
23675   if ($Texi2HTML::Config::USE_SETFILENAME and !defined($docu_name))
23676   {
23677      init_with_file_name ($input_file_base);
23678   }
23679
23680   Texi2HTML::Config::t2h_default_set_out_encoding();
23681   dump_texi($texi_lines, 'texi', $lines_numbers) if ($T2H_DEBUG & $DEBUG_TEXI);
23682   if (defined($Texi2HTML::Config::MACRO_EXPAND))
23683   {
23684       my @texi_lines = (@$first_texi_lines, @$texi_lines);
23685       dump_texi(\@texi_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND);
23686   }
23687
23688   %content_element =
23689   (
23690     'contents' => { 'id' => $Texi2HTML::Config::misc_pages_targets{'Contents'},
23691         'target' => $Texi2HTML::Config::misc_pages_targets{'Contents'},
23692         'contents' => 1, 'texi' => '_contents' },
23693     'shortcontents' => {
23694        'id' => $Texi2HTML::Config::misc_pages_targets{'Overview'},
23695        'target' => $Texi2HTML::Config::misc_pages_targets{'Overview'},
23696        'shortcontents' => 1, 'texi' => '_shortcontents' },
23697   );
23698
23699   %sec2level = %reference_sec2level;
23700
23701   $element_before_anything =
23702   {
23703      'before_anything' => 1,
23704      'place' => [],
23705      'texi' => 'VIRTUAL ELEMENT BEFORE ANYTHING',
23706   };
23707
23708
23709   $footnote_element =
23710   {
23711      'id' => $Texi2HTML::Config::misc_pages_targets{'Footnotes'},
23712      'target' => $Texi2HTML::Config::misc_pages_targets{'Footnotes'},
23713      'file' => $docu_foot,
23714      'footnote' => 1,
23715      'place' => [],
23716   };
23717
23718   %region_initial_state = (
23719          'titlepage'            => { },
23720          'documentdescription'  => { },
23721          'copying'              => { },
23722   );
23723
23724# to determine if a command has to be processed the following are interesting
23725# (and can be faked):
23726# 'region': the name of the special region we are processing
23727# 'region_pass': the number of passes in that specific region (both outside
23728#                of the main document, and in the main document)
23729# 'multiple_pass': the number of pass in the formatting of the region in the
23730#                  main document
23731# 'outside_document': set to 1 if outside of the main document formatting
23732   foreach my $key (keys(%region_initial_state))
23733   {
23734      $region_initial_state{$key}->{'multiple_pass'} = -1;
23735      $region_initial_state{$key}->{'region_pass'} = 0;
23736      $region_initial_state{$key}->{'num_head'} = 0;
23737      $region_initial_state{$key}->{'foot_num'} = 0;
23738      $region_initial_state{$key}->{'relative_foot_num'} = 0;
23739      $region_initial_state{$key}->{'region'} = $key;
23740   }
23741
23742   texinfo_initialization(1);
23743
23744
23745   $no_element_associated_place = [];
23746
23747   $document_idx_num = 0;
23748   $document_sec_num = 0;
23749   $document_head_num = 0;
23750   $document_anchor_num = 0;
23751
23752   $novalidate = $Texi2HTML::Config::NOVALIDATE; # @novalidate appeared
23753
23754   @nodes_list = ();        # nodes in document reading order
23755                            # each member is a reference on a hash
23756   @sections_list = ();     # sections in reading order
23757                            # each member is a reference on a hash
23758   @all_elements = ();      # sectionning elements (nodes and sections)
23759                            # in reading order. Each member is a reference
23760                            # on a hash which also appears in %nodes,
23761                            # @sections_list @nodes_list, @elements_list
23762   @elements_list = ();     # all the resulting elements in document order
23763   %sections = ();          # sections hash. The key is the section number
23764   %headings = ();          # headings hash. The key is the heading number
23765   $section_top = undef;    # @top section
23766   $element_top = undef;    # Top element
23767   $node_top = undef;       # Top node
23768   $node_first = undef;     # First node
23769   $element_index = undef;  # element with first index
23770   $element_chapter_index = undef;  # chapter with first index
23771   $element_first = undef;  # first element
23772   $element_last = undef;   # last element
23773   %special_commands = ();  # hash for the commands specially handled
23774                            # by the user
23775
23776   @index_labels = ();             # array corresponding with @?index commands
23777                                   # constructed during pass_texi, used to
23778                                   # put labels in pass_text
23779   $index_entries = undef;
23780
23781   # original kdb styles used if @kbdinputstyle distinct
23782   $kept_kdb_style = $::style_map_ref->{'kbd'};
23783   $kept_kdb_pre_style = $::style_map_pre_ref->{'kbd'};
23784
23785   my ($doc_lines, $doc_numbers) = pass_structure($texi_lines, $lines_numbers);
23786   if ($T2H_DEBUG & $DEBUG_TEXI)
23787   {
23788      dump_texi($doc_lines, 'first', $doc_numbers);
23789      if (defined($Texi2HTML::Config::MACRO_EXPAND and $Texi2HTML::Config::DUMP_TEXI))
23790      {
23791          unshift (@$doc_lines, @$first_texi_lines);
23792          push (@$doc_lines, "\@bye\n");
23793          dump_texi($doc_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND . ".first");
23794      }
23795   }
23796   next if ($Texi2HTML::Config::DUMP_TEXI or defined($Texi2HTML::Config::MACRO_EXPAND));
23797
23798   foreach my $style (keys(%special_commands))
23799   {
23800      $special_commands{$style}->{'max'} = $special_commands{$style}->{'count'};
23801   }
23802
23803   %files = ();   # keys are files. This is used to avoid reusing an already
23804                  # used file name
23805   %empty_indices = (); # value is true for an index name key if the index
23806                        # is empty
23807   %printed_indices = (); # value is true for an index name not empty and
23808                          # printed
23809   %indices = ();                  # hash of indices names containing
23810                                   #[ $pages, $entries ] (page indices and
23811                                   # raw index entries)
23812   prepare_indices();
23813   rearrange_elements();
23814   do_names();
23815
23816#Texi2HTML::LaTeX2HTML::latex2html();
23817   foreach my $handler(@Texi2HTML::Config::command_handler_process)
23818   {
23819       &$handler;
23820   }
23821
23822# maybe do that later to have more elements ready?
23823   &$Texi2HTML::Config::toc_body(\@elements_list);
23824
23825   &$Texi2HTML::Config::css_lines($Texi2HTML::THISDOC{'css_import_lines'},
23826        $Texi2HTML::THISDOC{'css_lines'});
23827
23828
23829   $global_head_num = 0;       # heading index. it is global for the main doc,
23830                               # and taken from the state if in multiple_pass.
23831   $global_foot_num = 0;
23832   $global_relative_foot_num = 0;
23833   @foot_lines = ();           # footnotes
23834   $copying_comment = '';      # comment constructed from text between
23835                               # @copying and @end copying with licence
23836   %acronyms_like = ();        # acronyms or similar commands associated texts
23837                               # the key are the commands, the values are
23838                               # hash references associating shorthands to
23839                               # texts.
23840   @states_stack = ();
23841
23842   pass_text($doc_lines, $doc_numbers);
23843   print STDERR "BUG: " . scalar(@index_labels) . " index entries pending\n"
23844      if (scalar(@index_labels));
23845   foreach my $special (keys(%special_commands))
23846   {
23847      my $count = $special_commands{$special}->{'count'};
23848      if (($count != 0) and $T2H_VERBOSE)
23849      {
23850         echo_warn ("$count special \@$special were not processed.\n");
23851      }
23852   }
23853   if ($Texi2HTML::Config::IDX_SUMMARY)
23854   {
23855      foreach my $entry (keys(%index_names))
23856      {
23857         do_index_summary_file($entry, $docu_name) unless ($empty_indices{$entry});
23858      }
23859   }
23860   do_node_files() if ($Texi2HTML::Config::NODE_FILES);
23861#l2h_FinishFromHtml() if ($Texi2HTML::Config::L2H);
23862#l2h_Finish() if($Texi2HTML::Config::L2H);
23863#Texi2HTML::LaTeX2HTML::finish();
23864   foreach my $handler(@Texi2HTML::Config::command_handler_finish)
23865   {
23866       &$handler;
23867   }
23868   &$Texi2HTML::Config::finish_out();
23869
23870   print STDERR "# File ($file_number) $input_file_name processed\n" if $T2H_VERBOSE;
23871   $file_number++;
23872}
23873print STDERR "# that's all folks\n" if $T2H_VERBOSE;
23874exit(0);
23875
23876
23877##############################################################################
23878
23879# These next few lines are legal in both Perl and nroff.
23880
23881.00 ;                           # finish .ig
23882
23883'di			\" finish diversion--previous line must be blank
23884.nr nl 0-1		\" fake up transition to first page again
23885.nr % 0			\" start at page 1
23886'; __END__ ############# From here on it's a standard manual page ############
23887    .so ${datarootdir}/man/man1/texi2html.1
23888