fixed packaging
[platform/upstream/libunistring.git] / build-aux / texi2html
1 #! /usr/bin/perl -- # perl
2 'di ';
3 'ig 00 ';
4 #+##############################################################################
5 #
6 # texi2html: Program to transform Texinfo documents to HTML
7 #
8 #    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
9 #                             Derek Price <derek@ximbiot.com>,
10 #                             Adrian Aichner <adrian@xemacs.org>,
11 #                           & others.
12 #
13 #    This program is free software; you can redistribute it and/or modify
14 #    it under the terms of the GNU General Public License as published by
15 #    the Free Software Foundation; either version 2 of the License, or
16 #    (at your option) any later version.
17 #
18 #    This program is distributed in the hope that it will be useful,
19 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
20 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 #    GNU General Public License for more details.
22 #
23 #    You should have received a copy of the GNU General Public License
24 #    along with this program; if not, write to the Free Software
25 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #    02110-1301  USA
27 #
28 #-##############################################################################
29 # The man page for this program is included at the end of this file and can be
30 # viewed using the command 'nroff -man texi2html'.
31
32 # for POSIX::setlocale and File::Spec
33 require 5.00405;
34 # Perl pragma to restrict unsafe constructs
35 use strict;
36 # used in case of tests, to revert to "C" locale.
37 use POSIX qw(setlocale LC_ALL LC_CTYPE);
38 # used to obtain the name of the current working directory
39 use Cwd;
40 # used to find a relative path back to the current working directory
41 use File::Spec;
42
43 #
44 # According to
45 # larry.jones@sdrc.com (Larry Jones)
46 # this pragma is not present in perl5.004_02:
47 #
48 # Perl pragma to control optional warnings
49 # use warnings;
50
51 #++##########################################################################
52 #
53 # NOTE FOR DEBUGGING THIS SCRIPT:
54 # You can run 'perl texi2html.pl' directly, provided you have
55 # the environment variable T2H_HOME set to the directory containing
56 # the texi2html.init, T2h_i18n.pm, translations.pl, l2h.init, 
57 # T2h_l2h.pm files
58 #
59 #--##########################################################################
60
61 # CVS version:
62 # $Id: texi2html.pl,v 1.182 2007/05/07 22:56:02 pertusus Exp $
63
64 # Homepage:
65 my $T2H_HOMEPAGE = "http://www.nongnu.org/texi2html/";
66
67 # Authors (appears in comments):
68 my $T2H_AUTHORS = <<EOT;
69 Written by: Lionel Cons <Lionel.Cons\@cern.ch> (original author)
70             Karl Berry  <karl\@freefriends.org>
71             Olaf Bachmann <obachman\@mathematik.uni-kl.de>
72             and many others.
73 Maintained by: Many creative people.
74 Send bugs and suggestions to <texi2html-bug\@nongnu.org>
75 EOT
76
77 # Version: set in configure.in
78 my $THISVERSION = '1.78a';
79 my $THISPROG = "texi2html $THISVERSION"; # program name and version
80
81 #+++########################################################################
82 #                                                                          #
83 # Paths and file names                                                     #
84 #                                                                          #
85 #---########################################################################
86
87 # set by configure, prefix for the sysconfdir and so on
88 my $prefix = '/usr/local';
89 my $sysconfdir;
90 my $pkgdatadir;
91 my $datadir;
92
93 # We need to eval as $prefix has to be expanded. However when we haven't
94 # run configure @sysconfdir will be expanded as an array, thus we verify
95 # whether configure was run or not
96 if ('${prefix}/etc' ne '@' . 'sysconfdir@')
97 {
98     $sysconfdir = eval '"${prefix}/etc"';
99 }
100 else
101 {
102     $sysconfdir = "/usr/local/etc";
103 }
104
105 if ('${prefix}/share' ne '@' . 'datadir@')
106 {
107     $pkgdatadir = eval '"${prefix}/share/texi2html"';
108     $datadir = eval '"${prefix}/share"';
109 }
110 else
111 {
112     $pkgdatadir = "/usr/local/share/texi2html";
113     $datadir = "/usr/local/share";
114 }
115
116 my $i18n_dir = 'i18n'; # name of the directory containing the per language files
117 my $conf_file_name = 'Config' ;
118 my $texinfo_htmlxref = 'htmlxref.cnf';
119
120 # directories for texi2html init files
121 my @texi2html_config_dirs = ('./');
122 push @texi2html_config_dirs, "$ENV{'HOME'}/.texi2html/" if (defined($ENV{'HOME'}));
123 push @texi2html_config_dirs, "$sysconfdir/texi2html/" if (defined($sysconfdir));
124 push @texi2html_config_dirs, "$pkgdatadir" if (defined($pkgdatadir));
125
126 # directories for texinfo configuration files
127 my @texinfo_config_dirs = ('./.texinfo/');
128 push @texinfo_config_dirs, "$ENV{'HOME'}/.texinfo/" if (defined($ENV{'HOME'}));
129 push @texinfo_config_dirs, "$sysconfdir/texinfo/" if (defined($sysconfdir));
130 push @texinfo_config_dirs, "$datadir/texinfo/" if (defined($datadir));
131
132
133 #+++########################################################################
134 #                                                                          #
135 # Constants                                                                #
136 #                                                                          #
137 #---########################################################################
138
139 my $DEBUG_MENU   =  1;
140 my $DEBUG_INDEX =  2;
141 my $DEBUG_TEXI  =  4;
142 my $DEBUG_MACROS =  8;
143 my $DEBUG_FORMATS   = 16;
144 my $DEBUG_ELEMENTS  = 32;
145 my $DEBUG_USER  = 64;
146 my $DEBUG_L2H   = 128;
147
148 my $ERROR = "***";                 # prefix for errors
149 my $WARN  = "**";                  # prefix for warnings
150
151 my $VARRE = '[\w\-]+';          # RE for a variable name
152 my $NODERE = '[^:]+';             # RE for node names
153
154 my $MAX_LEVEL = 4;
155 my $MIN_LEVEL = 1;
156
157 #+++###########################################################################
158 #                                                                             #
159 # Initialization                                                              #
160 # Some declarations, some functions that are GPL and therefore cannot be in   #
161 # texi2html.init, some functions that are not to be customized.               #
162 # Pasted content of File $(srcdir)/texi2html.init: Default initializations    #
163 #                                                                             #
164 #---###########################################################################
165
166 {
167 package Texi2HTML::Config;
168
169
170 sub load($) 
171 {
172     my $file = shift;
173     eval { require($file) ;};
174     if ($@ ne '')
175     {
176         print STDERR "error loading $file: $@\n";
177         return 0;
178     }
179     return 1;
180 }
181
182 # customization options variables
183
184 use vars qw(
185 $DEBUG
186 $PREFIX
187 $VERBOSE
188 $SUBDIR
189 $IDX_SUMMARY
190 $SPLIT
191 $SHORT_REF
192 @EXPAND
193 $EXPAND
194 $TOP
195 $DOCTYPE 
196 $FRAMESET_DOCTYPE 
197 $CHECK 
198 $TEST 
199 $DUMP_TEXI
200 $MACRO_EXPAND
201 $USE_GLOSSARY 
202 $INVISIBLE_MARK 
203 $USE_ISO 
204 $TOP_FILE 
205 $TOC_FILE
206 $FRAMES
207 $SHOW_MENU
208 $NUMBER_SECTIONS
209 $USE_NODES
210 $USE_UNICODE
211 $USE_UNIDECODE
212 $TRANSLITERATE_NODE
213 $NODE_FILES
214 $NODE_NAME_IN_MENU
215 $AVOID_MENU_REDUNDANCY
216 $SECTION_NAVIGATION
217 $SHORTEXTN 
218 $EXTENSION
219 $OUT 
220 $NOVALIDATE
221 $DEF_TABLE 
222 $LANG 
223 $DO_CONTENTS
224 $DO_SCONTENTS
225 $SEPARATED_FOOTNOTES
226 $TOC_LINKS
227 $L2H 
228 $L2H_L2H 
229 $L2H_SKIP 
230 $L2H_TMP 
231 $L2H_CLEAN 
232 $L2H_FILE
233 $L2H_HTML_VERSION
234 $EXTERNAL_DIR
235 @INCLUDE_DIRS 
236 @PREPEND_DIRS 
237 @CONF_DIRS 
238 $IGNORE_PREAMBLE_TEXT
239 @CSS_FILES
240 $INLINE_CONTENTS
241 );
242
243 # customization variables
244 # ENCODING is deprecated
245 use vars qw(
246 $ENCODING
247
248 $ENCODING_NAME
249 $DOCUMENT_ENCODING
250 $OUT_ENCODING
251 $IN_ENCODING
252 $DEFAULT_ENCODING
253 $MENU_PRE_STYLE
254 $CENTER_IMAGE
255 $EXAMPLE_INDENT_CELL
256 $SMALL_EXAMPLE_INDENT_CELL
257 $SMALL_FONT_SIZE
258 $SMALL_RULE
259 $DEFAULT_RULE
260 $MIDDLE_RULE
261 $BIG_RULE
262 $TOP_HEADING
263 $INDEX_CHAPTER
264 $SPLIT_INDEX
265 $HREF_DIR_INSTEAD_FILE
266 $USE_MENU_DIRECTIONS
267 $AFTER_BODY_OPEN
268 $PRE_BODY_CLOSE
269 $EXTRA_HEAD
270 $VERTICAL_HEAD_NAVIGATION
271 $WORDS_IN_PAGE
272 $ICONS
273 $UNNUMBERED_SYMBOL_IN_MENU
274 $SIMPLE_MENU
275 $MENU_SYMBOL
276 $OPEN_QUOTE_SYMBOL
277 $CLOSE_QUOTE_SYMBOL
278 $TOC_LIST_STYLE
279 $TOC_LIST_ATTRIBUTE
280 $TOP_NODE_FILE
281 $TOP_NODE_UP
282 $NODE_FILE_EXTENSION
283 $BEFORE_OVERVIEW
284 $AFTER_OVERVIEW
285 $BEFORE_TOC_LINES
286 $AFTER_TOC_LINES
287 $NEW_CROSSREF_STYLE
288 $USER
289 $USE_NUMERIC_ENTITY
290 $DATE
291 %ACTIVE_ICONS
292 %NAVIGATION_TEXT
293 %PASSIVE_ICONS
294 %BUTTONS_NAME
295 %BUTTONS_GOTO
296 %BUTTONS_EXAMPLE
297 @CHAPTER_BUTTONS
298 @MISC_BUTTONS
299 @SECTION_BUTTONS
300 @SECTION_FOOTER_BUTTONS
301 @NODE_FOOTER_BUTTONS
302 @IMAGE_EXTENSIONS
303 );
304
305 # customization variables which may be guessed in the script
306 #our $ADDRESS;
307 use vars qw(
308 $BODYTEXT
309 $CSS_LINES
310 $DOCUMENT_DESCRIPTION
311 $EXTERNAL_CROSSREF_SPLIT
312 );
313
314 # I18n
315 use vars qw(
316 $I
317 $LANGUAGES
318 );
319
320 # customizable subroutines references
321 use vars qw(
322 $print_section
323 $one_section
324 $end_section
325 $print_Top_header
326 $print_Top_footer
327 $print_Top
328 $print_Toc
329 $print_Overview
330 $print_Footnotes
331 $print_About
332 $print_misc_header
333 $print_misc_footer
334 $print_misc
335 $print_section_header
336 $print_section_footer
337 $print_chapter_header
338 $print_chapter_footer
339 $print_page_head
340 $print_page_foot
341 $print_head_navigation
342 $print_foot_navigation
343 $button_icon_img
344 $print_navigation
345 $about_body
346 $print_frame
347 $print_toc_frame
348 $toc_body
349 $titlepage
350 $css_lines
351 $print_redirection_page
352 $init_out
353 $finish_out
354 $node_file_name
355 $element_file_name
356 $inline_contents
357
358 $protect_text
359 $anchor
360 $def_item
361 $def
362 $menu
363 $menu_link
364 $menu_description
365 $menu_comment
366 $simple_menu_link
367 $ref_beginning
368 $info_ref
369 $book_ref
370 $external_href
371 $external_ref
372 $internal_ref
373 $table_item
374 $table_line
375 $row
376 $cell
377 $list_item
378 $comment
379 $def_line
380 $def_line_no_texi
381 $raw
382 $raw_no_texi
383 $heading
384 $paragraph
385 $preformatted
386 $foot_line_and_ref
387 $foot_section
388 $address
389 $image
390 $image_files
391 $index_entry_label
392 $index_entry
393 $index_letter
394 $print_index
395 $index_summary
396 $summary_letter
397 $complex_format
398 $cartouche
399 $sp
400 $definition_category
401 $table_list
402 $copying_comment
403 $index_summary_file_entry
404 $index_summary_file_end
405 $index_summary_file_begin
406 $style
407 $format
408 $normal_text
409 $empty_line
410 $unknown
411 $unknown_style
412 $float
413 $caption_shortcaption
414 $listoffloats
415 $listoffloats_entry
416 $listoffloats_caption
417 $listoffloats_float_style
418 $listoffloats_style
419 $acronym_like
420 $quotation
421 $quotation_prepend_text
422 $paragraph_style_command
423 $heading_texi
424 $index_element_heading_texi
425
426 $PRE_ABOUT
427 $AFTER_ABOUT
428 );
429
430 # hash which entries might be redefined by the user
431 use vars qw(
432 $complex_format_map
433 %accent_map
434 %def_map
435 %format_map
436 %simple_map
437 %simple_map_pre
438 %simple_map_texi
439 %style_map
440 %style_map_pre
441 %style_map_texi
442 %simple_format_simple_map_texi
443 %simple_format_style_map_texi
444 %simple_format_texi_map
445 %command_type
446 %paragraph_style
447 %things_map
448 %pre_map
449 %texi_map
450 %unicode_map
451 %unicode_diacritical
452 %transliterate_map 
453 %transliterate_accent_map
454 %no_transliterate_map
455 %ascii_character_map
456 %ascii_simple_map
457 %ascii_things_map
458 %numeric_entity_map
459 %perl_charset_to_html
460 %iso_symbols
461 %misc_command
462 %css_map
463 %format_in_paragraph
464 %special_list_commands
465 %accent_letters
466 %unicode_accents
467 %special_accents
468 @command_handler_init
469 @command_handler_process
470 @command_handler_finish
471 %command_handler
472 );
473
474 # needed in this namespace for translations
475 $I = \&Texi2HTML::I18n::get_string;
476
477 #
478 # Function refs covered by the GPL as part of the texi2html.pl original
479 # code. As such they cannot appear in texi2html.init which is public 
480 # domain (at least the things coded by me, and, if I'm not wrong also the 
481 # things coded by Olaf -- Pat).
482 #
483
484 $toc_body                 = \&T2H_GPL_toc_body;
485 $style                    = \&T2H_GPL_style;
486 $format                   = \&T2H_GPL_format;
487
488 sub T2H_GPL_toc_body($)
489 {
490     my $elements_list = shift;
491     return unless ($DO_CONTENTS or $DO_SCONTENTS or $FRAMES);
492     my $current_level = 0;
493     my $ul_style = $NUMBER_SECTIONS ? $TOC_LIST_ATTRIBUTE : ''; 
494     foreach my $element (@$elements_list)
495     {
496         next if ($element->{'top'} or $element->{'index_page'});
497         my $ind = '  ' x $current_level;
498         my $level = $element->{'toc_level'};
499         print STDERR "Bug no toc_level for ($element) $element->{'texi'}\n" if (!defined ($level));
500         if ($level > $current_level)
501         {
502             while ($level > $current_level)
503             {
504                 $current_level++;
505                 my $ln = "\n$ind<ul${ul_style}>\n";
506                 $ind = '  ' x $current_level;
507                 push(@{$Texi2HTML::TOC_LINES}, $ln);
508             }
509         }
510         elsif ($level < $current_level)
511         {
512             while ($level < $current_level)
513             {
514                 $current_level--;
515                 $ind = '  ' x $current_level;
516                 my $line = "</li>\n$ind</ul>";
517                 $line .=  "</li>" if ($level == $current_level);
518                 push(@{$Texi2HTML::TOC_LINES}, "$line\n");
519                 
520             }
521         }
522         else
523         {
524             push(@{$Texi2HTML::TOC_LINES}, "</li>\n");
525         }
526         my $file = '';
527         $file = $element->{'file'} if ($SPLIT);
528         my $text = $element->{'text'};
529         #$text = $element->{'name'} unless ($NUMBER_SECTIONS);
530         my $entry = "<li>" . &$anchor ($element->{'tocid'}, "$file#$element->{'id'}",$text);
531         push (@{$Texi2HTML::TOC_LINES}, $ind . $entry);
532         push(@{$Texi2HTML::OVERVIEW}, $entry. "</li>\n") if ($level == 1);
533     }
534     while (0 < $current_level)
535     {
536         $current_level--;
537         my $ind = '  ' x $current_level;
538         push(@{$Texi2HTML::TOC_LINES}, "</li>\n$ind</ul>\n");
539     }
540     @{$Texi2HTML::TOC_LINES} = () unless ($DO_CONTENTS);
541     if (@{$Texi2HTML::TOC_LINES})
542     {
543         unshift @{$Texi2HTML::TOC_LINES}, $BEFORE_TOC_LINES;
544         push @{$Texi2HTML::TOC_LINES}, $AFTER_TOC_LINES;
545     }
546     @{$Texi2HTML::OVERVIEW} = () unless ($DO_SCONTENTS or $FRAMES);
547     if (@{$Texi2HTML::OVERVIEW})
548     {
549         unshift @{$Texi2HTML::OVERVIEW}, "<ul${ul_style}>\n";
550         push @{$Texi2HTML::OVERVIEW}, "</ul>\n";
551         unshift @{$Texi2HTML::OVERVIEW}, $BEFORE_OVERVIEW;
552         push @{$Texi2HTML::OVERVIEW}, $AFTER_OVERVIEW;
553     }
554 }
555
556 sub T2H_GPL_style($$$$$$$$$)
557 {                           # known style
558     my $style = shift;
559     my $command = shift;
560     my $text = shift;
561     my $args = shift;
562     my $no_close = shift;
563     my $no_open = shift;
564     my $line_nr = shift;
565     my $state = shift;
566     my $style_stack = shift;
567
568     my $do_quotes = 0;
569     my $use_attribute = 0;
570     my $use_begin_end = 0;
571     if (ref($style) eq 'HASH')
572     {
573         #print STDERR "GPL_STYLE $command\n";
574         #print STDERR " @$args\n";
575         $do_quotes = $style->{'quote'};
576         if ((@{$style->{'args'}} == 1) and defined($style->{'attribute'}))
577         {
578             $style = $style->{'attribute'};
579             $use_attribute = 1;
580             $text = $args->[0];
581         }
582         elsif (defined($style->{'function'}))
583         {
584             $text = &{$style->{'function'}}($command, $args, $style_stack, $state, $line_nr);
585         }
586     }
587     else
588     {
589         if ($style =~ s/^\"//)
590         {                       # add quotes
591             $do_quotes = 1;
592         }
593         if ($style =~ s/^\&//)
594         {                       # custom
595             $style = 'Texi2HTML::Config::' . $style;
596             eval "\$text = &$style(\$text, \$command, \$style_stack)";
597         }
598         elsif ($style ne '')
599         {
600             $use_attribute = 1;
601         }
602         else
603         {                       # no style
604         }
605     }
606     if ($use_attribute)
607     {                       # good style
608         my $attribute_text = '';
609         if ($style =~ /^(\w+)(\s+.*)/)
610         {
611             $style = $1;
612             $attribute_text = $2;
613         }
614 #        $text = "<${style}$attribute_text>$text</$style>" ;
615         $text = "<${style}$attribute_text>" . "$text" if (!$no_open);
616         $text .= "</$style>" if (!$no_close);
617         if ($do_quotes)
618         {
619              $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
620              $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
621         }
622     }
623     if (ref($style) eq 'HASH')
624     {
625         if (defined($style->{'begin'}) and !$no_open)
626         {
627              $text = $style->{'begin'} . $text;
628         }
629         if (defined($style->{'end'}) and !$no_close)
630         {
631             $text = $text . $style->{'end'};
632         }
633     }
634     if ($do_quotes and !$use_attribute)
635     {
636         $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
637         $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
638     }
639     return $text;
640 }
641
642 sub T2H_GPL_format($$$)
643 {
644     my $tag = shift;
645     my $element = shift;
646     my $text = shift;
647     return '' if (!defined($element) or ($text !~ /\S/));
648     return $text if ($element eq '');
649     my $attribute_text = '';
650     if ($element =~ /^(\w+)(\s+.*)/)
651     {
652         $element = $1;
653         $attribute_text = $2;
654     }
655     return "<${element}$attribute_text>\n" . $text. "</$element>\n";
656 }
657
658 # leave this within comments, and keep the require statement
659 # This way, you can directly run texi2html.pl, if 
660 # $ENV{T2H_HOME}/texi2html.init exists.
661
662 # @INIT@
663 # -*-perl-*-
664 ######################################################################
665 # File: texi2html.init
666 #
667 # Default values for command-line arguments and for various customizable
668 # procedures are set in this file.
669 #
670 # A copy of this file is pasted into the beginning of texi2html by
671 # running './configure'.
672 #
673 # Copy this file, rename it and make changes to it, if you like.
674 # Afterwards, load the file with command-line 
675 # option -init-file <your_init_file>
676 #
677 # $Id: texi2html.init,v 1.116 2007/05/07 22:56:02 pertusus Exp $
678
679 ######################################################################
680 # The following variables can also be set by command-line options
681 #
682 #
683 # The default values are set in this file, texi2html.init and the content
684 # of this file is included at the beginning of the texi2html script file. 
685 # Those values may be overrided by values set in $sysconfdir/texi2htmlrc 
686 # and then by values set in $HOME/texi2htmlrc.
687 #
688 # command line switches may override these values, and values set in files
689 # specified by -init-file are also taken into account.
690 # values set in these files overwrite values set by the command-line
691 # options appearing before -init-file and might still be overwritten by
692 # command-line arguments following the -init-file option.
693
694 # -debug
695 # The integer value specifies what kind of debugging output is generated.
696 $DEBUG = 0;
697
698 # -doctype
699 # The value is the 'SystemLiteral' which identifies the canonical DTD 
700 # for the document.
701 # Definition: The SystemLiteral is called the entity's system
702 # identifier. It is a URI, which may be used to retrieve the entity.
703 # See http://www.xml.com/axml/target.html#NT-ExternalID
704 $DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd">';
705
706 # -frameset-doctype
707 # When frames are used, this SystemLiteral identifies the DTD used for
708 # the file containing the frame description.
709 $FRAMESET_DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html401/frameset.dtd">';
710
711 # -test
712 # If this value is true, some variables which should be dynamically generated 
713 # (the date, the user running texi2html, the version of texi2html) are set to 
714 # fix and given values. This is usefull in case the resulting manual is 
715 # compared with a reference. For example this is used in the tests of test.sh.
716 $TEST = 0;
717
718 # -dump-texi
719 # This value is usefull for debugging purposes. The result of the first pass is
720 # put in <document name>.passtexi, the result of the second pass is put in 
721 # <document name>.passfirst.
722 $DUMP_TEXI = 0;
723
724 # -expand
725 # the @EXPAND array contains the expanded section names.
726 @EXPAND = ('html');
727
728 # -invisible
729 # This seems obsolete and is not used anywhere.
730 # This was a workaround for a known bug of many WWW browsers, including 
731 # netscape. This was used to create invisible destination in anchors.
732 $INVISIBLE_MARK = '';
733 # $INVISIBLE_MARK = '&#160;';
734
735 # -iso
736 # if this value is true, ISO8859 characters are used for special symbols 
737 # (like copyright, etc).
738 $USE_ISO = 1;
739
740 # -I
741 # add a directory to the list of directories where @include files are
742 # searched for (besides the directory of the file). additional '-I' 
743 # args are appended to this list.
744 # (APA: Don't implicitely search ., to conform with the docs!)
745 # my @INCLUDE_DIRS = (".");
746 @INCLUDE_DIRS = ();
747
748 # -P
749 # prepend a directory to the list of directories where @include files are
750 # searched for before the directory of the file. additional '-P' 
751 # args are prepended to this list.
752 @PREPEND_DIRS = ();
753
754 # --conf-dir
755 # append to the files searched for init files.
756 @CONF_DIRS = ();
757
758 # -top-file
759 # This file name is used for the top-level file.
760 # The extension is set appropriately, if necessary.
761 # If empty, <basename of document>.html is used.
762 # Typically, you would set this to "index.html".
763 $TOP_FILE = '';
764
765 # -toc-file
766 # This file name is used for the table of contents.  The
767 # extension is set appropriately, if necessary.
768 # If empty, <basename of document>_toc.html is used.
769 $TOC_FILE = '';
770
771 # -frames
772 # if the value is true, HTML 4.0 "frames" are used. 
773 # A file describing the frame layout is generated, together with a file 
774 # with the short table of contents.
775 $FRAMES = 0;
776
777 # -menu | -nomenu
778 # if the value is true the Texinfo menus are shown.
779 $SHOW_MENU = 1;
780
781 # -number | -nonumber
782 # if this is set the sections are numbered, and section names and numbers 
783 # are used in references and menus (instead of node names).
784 $NUMBER_SECTIONS = 1;
785
786 # -use-nodes
787 # if this is set the nodes are used as sectionning elements. 
788 # Otherwise the nodes are incorporated in sections.
789 $USE_NODES = 0;
790
791 # -node-files
792 # if this is set one file per node is generated, which can be a target for 
793 # cross manual references.
794 $NODE_FILES = 0;
795
796 # -split section|chapter|node|none
797 # if $SPLIT is set to 'section' (resp. 'chapter') one html file per section 
798 # (resp. chapter) is generated. If $SPLIT is set to 'node' one html file per 
799 # node or sectionning element is generated. In all these cases separate pages 
800 # for Top, Table of content (Toc), Overview and About are generated.
801 # Otherwise a monolithic html file that contains the whole document is 
802 # created.
803 #$SPLIT = 'section';
804 $SPLIT = '';
805
806 # -sec-nav|-nosec-nav
807 # if this is set then navigation panels are printed at the beginning of each 
808 # section.
809 # If the document is split at nodes then navigation panels are 
810 # printed at the end if there were more than $WORDS_IN_PAGE words on page.
811 #
812 # If the document is split at sections this is ignored.
813 #
814 # This is most useful if you do not want to have section navigation
815 # with -split chapter. There will be chapter navigation panel at the 
816 # beginning and at the end of chapters anyway.
817 $SECTION_NAVIGATION = 1;
818
819 # -separated-footnotes
820 # if this is set footnotes are on a separated page. Otherwise they are at
821 # the end of each file (if the document is split).
822 $SEPARATED_FOOTNOTES = 1;
823
824 # -toc-links
825 # if this is set, links from headings to toc entries are created.
826 $TOC_LINKS = 0;
827
828 # -subdir
829 # If this is set, then put result files into the specified directory.
830 # If not set, then result files are put into the current directory.
831 #$SUBDIR = 'html';
832 $SUBDIR = '';
833
834 # -short-extn
835 # If this is set, then all HTML files will have extension ".htm" instead of
836 # ".html". This is helpful when shipping the document to DOS-based systems.
837 $SHORTEXTN = 0;
838
839 # -prefix
840 # This set the output file prefix, prepended to all .html, .gif and .pl files.
841 # By default, this is the basename of the document.
842 $PREFIX = '';
843
844 # -o filename
845 # If this is set a monolithic document is outputted into $filename.
846 $OUT = '';
847
848 # -no-validate
849 # suppress node cross-reference validation
850 $NOVALIDATE = 0;
851
852 # -short-ref
853 # if this is set cross-references are given without section numbers.
854 $SHORT_REF = '';
855
856 # -idx-sum
857 # if value is set, then for each @printindex <index name>
858 # <document name>_<index name>.idx is created which contains lines of the form
859 # key ref sorted alphabetically (case matters).
860 $IDX_SUMMARY = 0;
861
862 # -def-table
863 # If this is set a table construction for @def.... instead of definition 
864 # lists.
865 # (New Option: 27.07.2000 Karl Heinz Marbaise)
866 $DEF_TABLE = 0;
867
868 # -verbose
869 # if this is set chatter about what we are doing.
870 $VERBOSE = '';
871
872 # -lang
873 # use &$I('my string') if you want to have translations of 'my string'
874 # and provide the translations in $LANGUAGES->{$LANG} with 'my string'
875 # as key.
876 # To add a new language use ISO 639 language codes (see e.g. perl module 
877 # Locale-Codes-1.02 for  definitions). Supply translations in the 
878 # $LANGUAGES hash and put it in a file with $LANG as name in an i18n 
879 # directory. 
880 # Default's to 'en' if not set or no @documentlanguage is specified.
881 $LANG = 'en';
882
883 # -ignore-preamble-text
884 # If this is set the text before @node and sectionning commands is ignored.
885 $IGNORE_PREAMBLE_TEXT = 0;
886
887 # -html-xref-prefix
888 # base directory for external manuals.
889 #$EXTERNAL_DIR = '../';
890 $EXTERNAL_DIR = undef;
891
892 # -l2h
893 # if this is set, latex2html is used for generation of math content.
894 $L2H = '';
895
896 # -css-include
897 # All the specified css files are used. More precisely the @import sections
898 # are added to the beginning of the CSS_LINES the remaining is added at
899 # the end of the CSS_LINES (after the css rules generated by texi2html).
900 # cf texinfo manual for more info.
901 # - means STDIN
902 @CSS_FILES = ();
903
904 ######################
905 # The following options are only relevant if $L2H is set
906 #
907 # -l2h-l2h
908 # name/location of latex2html program
909 $L2H_L2H = "latex2html";
910
911 # -l2h-skip
912 # If this is set the actual call to latex2html is skipped. The previously
913 # generated content is reused, instead.
914 $L2H_SKIP = '';
915
916 # -l2h-tmp
917 # If this is set l2h uses the specified directory for temporary files. The path
918 # leading to this directory may not contain a dot (i.e., a ".");
919 # otherwise, l2h will fail.
920 $L2H_TMP = '';
921  
922 # -l2h-file
923 # If set, l2h uses the file as latex2html init file
924 $L2H_FILE = 'l2h.init';
925
926 # -l2h-clean
927 # if this is set the intermediate files generated by texi2html in relation with
928 # latex2html are cleaned (they all have the prefix <document name>_l2h_).
929 $L2H_CLEAN = 1;
930
931 ##############################################################################
932 #
933 # The following can only be set in the init file
934 #
935 ##############################################################################
936
937 # If true do table of contents even if there is no @content
938 $DO_CONTENTS = 0;
939
940 # If true do short table of contents even if there is no @shortcontent
941 $DO_SCONTENTS = 0;
942
943 # if set, output the contents where the command is located
944 $INLINE_CONTENTS = 1;
945
946 # if this variable is true, numeric entities are used when there is no
947 # corresponding textual entity.
948 $USE_NUMERIC_ENTITY = 1;
949
950 # if set, then use node names in menu entries, instead of section names
951 $NODE_NAME_IN_MENU = 0;
952
953 # new style for crossrefs
954 $NEW_CROSSREF_STYLE = 1;
955
956 # transliterate node names for external refs (and internal if NODE_FILES)
957 $TRANSLITERATE_NODE = 1;
958
959 # if set and menu entry equals menu description, then do not print 
960 # menu description.
961 # Likewise, if node name equals entry name, do not print entry name.
962 $AVOID_MENU_REDUNDANCY = 1;
963
964 # if set, center @image by default
965 # otherwise, do not center by default
966 # Deprecated and not used anymore
967 $CENTER_IMAGE = 1;
968
969 # used as identation for block enclosing command @example, etc
970 # If not empty, must be enclosed in <td></td>
971 $EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
972
973 # same as above, only for @small
974 $SMALL_EXAMPLE_INDENT_CELL = '<td>&nbsp;</td>';
975
976 # font size for @small
977 $SMALL_FONT_SIZE = '-1';
978
979 # horizontal rules
980 $SMALL_RULE = '<hr size="1">';
981 $DEFAULT_RULE = '<hr>';
982 $MIDDLE_RULE = '<hr size="2">';
983 $BIG_RULE = '<hr size="6">';
984
985 # if non-empty, and no @..heading appeared in Top node, then
986 # use this as header for top node/section, otherwise use value of
987 # @settitle or @shorttitle (in that order)
988 $TOP_HEADING = '';
989
990 # if set, use this chapter for 'Index' button, else
991 # use first chapter with @printindex
992 $INDEX_CHAPTER = '';
993
994 # if set and $SPLIT is set, then split index pages at the next letter
995 # after they have more than that many entries
996 $SPLIT_INDEX = 100;
997
998 # symbol put at the beginning of nodes entry in menu (and optionnaly of 
999 # unnumbered in menus, see next variable)
1000 $MENU_SYMBOL = '&bull;';
1001 #$MENU_SYMBOL = '*';
1002
1003 $SIMPLE_MENU = 0;
1004
1005 $OPEN_QUOTE_SYMBOL = "\`";
1006 $CLOSE_QUOTE_SYMBOL = "'";
1007
1008 # if true put a $MENU_SYMBOL before unnumbered in menus
1009 $UNNUMBERED_SYMBOL_IN_MENU = 0;
1010
1011 # extension for nodes files when NODE_FILES is true
1012 $NODE_FILE_EXTENSION = "html";      
1013
1014 # extension
1015 $EXTENSION = "html";
1016
1017 # file name used for Top node when NODE_FILES is true
1018 $TOP_NODE_FILE = "index";
1019
1020 # node name used for Top node when automatic node directions are used
1021 $TOP_NODE_UP = '(dir)';
1022
1023 # this controls the pre style for menus
1024 $MENU_PRE_STYLE = 'font-family: serif';
1025
1026 # This controls the ul style for toc
1027 $TOC_LIST_STYLE = 'list-style: none';
1028 $TOC_LIST_ATTRIBUTE = ' class="toc"';
1029
1030 # These lines are inserted before and after the shortcontents 
1031 $BEFORE_OVERVIEW = "<div class=\"shortcontents\">\n";
1032 $AFTER_OVERVIEW = "</div>\n";
1033
1034 # These lines are inserted before and after the contents 
1035 $BEFORE_TOC_LINES = "<div class=\"contents\">\n";
1036 $AFTER_TOC_LINES = "</div>\n";
1037
1038 # if set (e.g., to index.html) replace hrefs to this file
1039 # (i.e., to index.html) by ./
1040 # Obsolete. Worked around a bug that is fixed now.
1041 $HREF_DIR_INSTEAD_FILE = '';
1042
1043 # text inserted after <body ...>
1044 $AFTER_BODY_OPEN = '';
1045
1046 # text inserted before </body>, this will be automatically inside <p></p>
1047 $PRE_BODY_CLOSE = '';
1048
1049 # this is added inside <head></head> after <title> and some <meta name>
1050 # stuff, it can be used for eg. <style>, <script>, <meta> etc. tags.
1051 $EXTRA_HEAD = '';
1052
1053 # Specifies the minimum page length required before a navigation panel
1054 # is placed at the bottom of a page 
1055 # FIXME this is not true:
1056 # THIS_WORDS_IN_PAGE holds number of words of current page
1057 $WORDS_IN_PAGE = 300;
1058
1059 # if this is set a vertical navigation panel is used.
1060 $VERTICAL_HEAD_NAVIGATION = 0;
1061
1062 # html version for latex2html
1063 $L2H_HTML_VERSION = "4.0";
1064
1065 # use the information given by menus to complete the node directions
1066 $USE_MENU_DIRECTIONS = 1;
1067
1068 # specify in this array which "buttons" should appear in which order
1069 # in the navigation panel for sections; use ' ' for empty buttons (space)
1070 @SECTION_BUTTONS =
1071     (
1072      'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1073      ' ', ' ', ' ', ' ',
1074      'Top', 'Contents', 'Index', 'About',
1075     );
1076
1077 # buttons for misc stuff
1078 @MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About');
1079
1080 # buttons for chapter file footers
1081 # (and headers but only if SECTION_NAVIGATION is false)
1082 @CHAPTER_BUTTONS =
1083     (
1084      'FastBack', 'FastForward', ' ',
1085      ' ', ' ', ' ', ' ',
1086      'Top', 'Contents', 'Index', 'About',
1087     );
1088
1089 # buttons for section file footers
1090 @SECTION_FOOTER_BUTTONS =
1091     (
1092      'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1093     );
1094
1095 @NODE_FOOTER_BUTTONS =
1096     (
1097      'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1098      ' ', ' ', ' ', ' ',
1099      'Top', 'Contents', 'Index', 'About',
1100 #     'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1101     );
1102
1103 $ICONS = 0;
1104
1105 # insert here name of icon images for buttons
1106 # Icons are used, if $ICONS and resp. value are set
1107 %ACTIVE_ICONS =
1108     (
1109      'Top',         '',
1110      'Contents',    '',
1111      'Overview',    '',
1112      'Index',       '',
1113      'This',        '',
1114      'Back',        '',
1115      'FastBack',    '',
1116      'Prev',        '',
1117      'Up',          '',
1118      'Next',        '',
1119      'NodeUp',      '',
1120      'NodeNext',    '',
1121      'NodePrev',    '',
1122      'Following',   '',
1123      'Forward',     '',
1124      'FastForward', '',
1125      'About' ,      '',
1126      'First',       '',
1127      'Last',        '',
1128      ' ',           ''
1129     );
1130
1131 # insert here name of icon images for these, if button is inactive
1132 %PASSIVE_ICONS =
1133     (
1134      'Top',         '',
1135      'Contents',    '',
1136      'Overview',    '',
1137      'Index',       '',
1138      'This',        '',
1139      'Back',        '',
1140      'FastBack',    '',
1141      'Prev',        '',
1142      'Up',          '',
1143      'Next',        '',
1144      'NodeUp',      '',
1145      'NodeNext',    '',
1146      'NodePrev',    '',
1147      'Following',   '',
1148      'Forward',     '',
1149      'FastForward', '',
1150      'About',       '',
1151      'First',       '',
1152      'Last',        '',
1153     );
1154
1155 @IMAGE_EXTENSIONS = ('png','jpg','jpeg','gif');
1156
1157 $init_out    = \&t2h_default_init_out;
1158 $finish_out    = \&t2h_default_finish_out;
1159
1160 # We have to do this dynamically because of internationalization and because
1161 # in body $LANG could be used.
1162 sub t2h_default_init_out()
1163 {
1164 # Names of text as alternative for icons
1165 # FIXME maybe get those in simple_format?
1166     %NAVIGATION_TEXT =
1167     (
1168      'Top',         &$I('Top'),
1169      'Contents',    &$I('Contents'),
1170      'Overview',    &$I('Overview'),
1171      'Index',       &$I('Index'),
1172      ' ',           ' &nbsp; ',
1173      'This',        &$I('current'),
1174      'Back',        ' &lt; ',
1175      'FastBack',    ' &lt;&lt; ',
1176      'Prev',        &$I('Prev'),
1177      'Up',          &$I(' Up '),
1178      'Next',        &$I('Next'),
1179      'NodeUp',      &$I('Node up'),
1180      'NodeNext',    &$I('Next node'),
1181      'NodePrev',    &$I('Previous node'),
1182      'Following',   &$I('Following node'),
1183      'Forward',     ' &gt; ',
1184      'FastForward', ' &gt;&gt; ',
1185      'About',       ' ? ',
1186      'First',       ' |&lt; ',
1187      'Last',        ' &gt;| '
1188     );
1189
1190     %BUTTONS_GOTO =
1191     (
1192      'Top',         &$I('Cover (top) of document'),
1193      'Contents',    &$I('Table of contents'),
1194      'Overview',    &$I('Short table of contents'),
1195      'Index',       &$I('Index'),
1196      'This',        &$I('Current section'),
1197      'Back',        &$I('Previous section in reading order'),
1198      'FastBack',    &$I('Beginning of this chapter or previous chapter'),
1199      'Prev',        &$I('Previous section on same level'),
1200      'Up',          &$I('Up section'),
1201      'Next',        &$I('Next section on same level'),
1202      'NodeUp',      &$I('Up node'),
1203      'NodeNext',    &$I('Next node'),
1204      'NodePrev',    &$I('Previous node'),
1205      'Following',   &$I('Node following in node reading order'),
1206      'Forward',     &$I('Next section in reading order'),
1207      'FastForward', &$I('Next chapter'),
1208      'About' ,      &$I('About (help)'),
1209      'First',       &$I('First section in reading order'),
1210      'Last',        &$I('Last section in reading order'),
1211     );
1212
1213     %BUTTONS_NAME =
1214     (
1215      'Top',         &$I('Top'),
1216      'Contents',    &$I('Contents'),
1217      'Overview',    &$I('Overview'),
1218      'Index',       &$I('Index'),
1219      ' ',           ' ',
1220      'This',        &$I('This'),
1221      'Back',        &$I('Back'),
1222      'FastBack',    &$I('FastBack'),
1223      'Prev',        &$I('Prev'),
1224      'Up',          &$I('Up'),
1225      'Next',        &$I('Next'),
1226      'NodeUp',      &$I('NodeUp'),
1227      'NodeNext',    &$I('NodeNext'),
1228      'NodePrev',    &$I('NodePrev'),
1229      'Following',   &$I('Following'),
1230      'Forward',     &$I('Forward'),
1231      'FastForward', &$I('FastForward'),
1232      'About',       &$I('About'),
1233      'First',       &$I('First'),
1234      'Last',        &$I('Last')
1235     );
1236
1237     # Set the default body text, inserted between <body ... >
1238     $BODYTEXT = 'lang="' . $LANG . '" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"' unless (defined($BODYTEXT));
1239     if (!defined($EXTERNAL_CROSSREF_SPLIT))
1240     {
1241         if ($SPLIT) 
1242         {
1243             $EXTERNAL_CROSSREF_SPLIT = 1;
1244         }
1245         else
1246         {
1247             $EXTERNAL_CROSSREF_SPLIT = 0;
1248         }
1249     }
1250
1251     $ENCODING_NAME = $ENCODING if (!defined($ENCODING_NAME) and 
1252          defined($ENCODING));
1253
1254     if (!defined($OUT_ENCODING) and (defined($ENCODING_NAME)))
1255     {
1256         $OUT_ENCODING = main::encoding_alias ($ENCODING_NAME);
1257         $OUT_ENCODING = $ENCODING_NAME if (!defined($OUT_ENCODING));
1258     }
1259     if (!defined($OUT_ENCODING) and (defined($IN_ENCODING)))
1260     {
1261         $OUT_ENCODING = $IN_ENCODING;
1262     }
1263     if (!defined($OUT_ENCODING) and (defined($DOCUMENT_ENCODING)))
1264     {
1265         $OUT_ENCODING = main::encoding_alias ($DOCUMENT_ENCODING);
1266         $OUT_ENCODING = $DOCUMENT_ENCODING if (!defined($OUT_ENCODING));
1267     }
1268
1269     if (!defined($ENCODING_NAME))
1270     {
1271          if (defined($OUT_ENCODING) and defined($perl_charset_to_html{$OUT_ENCODING}))
1272          {
1273              $ENCODING_NAME = $perl_charset_to_html{$OUT_ENCODING};
1274          }
1275          elsif (defined($IN_ENCODING) and defined($perl_charset_to_html{$IN_ENCODING}))
1276          {
1277              $ENCODING_NAME = $perl_charset_to_html{$IN_ENCODING};
1278          }
1279          elsif (defined($DOCUMENT_ENCODING) and defined($perl_charset_to_html{$DOCUMENT_ENCODING}))
1280          {
1281              $ENCODING_NAME = $perl_charset_to_html{$DOCUMENT_ENCODING};
1282          }
1283          elsif (defined($OUT_ENCODING))
1284          {
1285              $ENCODING_NAME = $OUT_ENCODING;
1286          }
1287          elsif (defined($IN_ENCODING))
1288          {
1289              $ENCODING_NAME = $IN_ENCODING;
1290          }
1291          elsif (defined($DOCUMENT_ENCODING))
1292          {
1293              $ENCODING_NAME = $DOCUMENT_ENCODING;
1294          }
1295          elsif (defined($perl_charset_to_html{$DEFAULT_ENCODING}))
1296          {
1297              $ENCODING_NAME = $perl_charset_to_html{$DEFAULT_ENCODING};
1298          }
1299          else
1300          {
1301              $ENCODING_NAME = 'us-ascii';
1302          }
1303     }
1304     my $out_encoding = $OUT_ENCODING;
1305     $out_encoding = 'UNDEF' if (!defined($out_encoding));
1306     my $in_encoding = $IN_ENCODING;
1307     $in_encoding = 'UNDEF' if (!defined($in_encoding));
1308     my $document_encoding = $DOCUMENT_ENCODING;
1309     $document_encoding = 'UNDEF' if (!defined($document_encoding));
1310     print STDERR "# Encodings: doc $document_encoding, in $in_encoding out $out_encoding, name $ENCODING_NAME\n" if ($VERBOSE);
1311         
1312     if ($SIMPLE_MENU and !defined($complex_format_map->{'menu'}))
1313     {
1314         $complex_format_map->{'menu'} = { 'begin' => q{''} , 'end' => q{''},
1315            'pre_style' => "$MENU_PRE_STYLE", 'class' => 'menu-preformatted' };
1316     }
1317     
1318     return $OUT_ENCODING;
1319 };
1320
1321 sub t2h_default_finish_out()
1322 {
1323 }
1324
1325 #######################################################################
1326 #
1327 # Values guessed if not set here, set in init_out
1328 #
1329 #######################################################################
1330
1331 $BODYTEXT = undef;
1332
1333 # default used in init_out for the setting of the ENCODING_NAME variable
1334 $DEFAULT_ENCODING = 'utf8';
1335
1336 # In file encoding. The @documentencoding overrides that variable.
1337 $DOCUMENT_ENCODING = undef;
1338
1339 # In file encoding, understandable by perl. Set according to DOCUMENT_ENCODING 
1340 $IN_ENCODING = undef;
1341
1342 # Formatted document encoding name. If undef, set in init_out based on 
1343 # $OUT_ENCODING or $DOCUMENT_ENCODING if they are defined
1344 $ENCODING_NAME = undef;
1345
1346 # Out files encoding, understandable by perl. If undef, set in init_out
1347 # using $ENCODING_NAME or $IN_ENCODING if they are defined
1348 $OUT_ENCODING = undef;
1349
1350 # if undef set to @documentdescription. If there is no @documentdescription,
1351 # set in page_head
1352 $DOCUMENT_DESCRIPTION = undef;
1353
1354 # if undef set 1 if SPLIT, to 0 otherwise
1355 $EXTERNAL_CROSSREF_SPLIT = undef;
1356
1357 $USER = undef;
1358 $DATE = undef;
1359
1360
1361 ########################################################################
1362 # Control of Page layout:
1363 # You can make changes of the Page layout at two levels:
1364 # 1.) For small changes, it is often enough to change the value of
1365 #     some global string/hash/array variables
1366 # 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines,
1367 #     give them another name, and assign them to the respective
1368 #     $<fnc> variable.
1369
1370 # As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, hold
1371 # href, html-name, node-name, name after removal of texi commands of
1372 # This     -- current section (resp. html page)
1373 # Top      -- top element
1374 # Contents -- Table of contents element
1375 # Overview -- Short table of contents element
1376 # Index    -- Index page element
1377 # About    -- page which explain "navigation buttons" element
1378 # First    -- first node element
1379 # Last     -- last node element
1380 #
1381 # Whether or not the following hash values are set, depends on the context
1382 # (all values are w.r.t. 'This' section)
1383 # Next        -- next element of texinfo
1384 # Prev        -- previous element of texinfo
1385 # NodeUp      -- up node of texinfo
1386 # Following   -- following node in node reading order, taking menu into account
1387 # Forward     -- next node in reading order
1388 # Back        -- previous node in reading order
1389 # Up          -- parent given by sectionning commands
1390 # FastForward -- if leave node, up and next, else next node
1391 # FastBackward-- if leave node, up and prev, else prev node
1392 #
1393 # Furthermore, the following global variabels are set:
1394 # $Texi2HTML::THISDOC{title}          -- title as set by @setttile
1395 # $Texi2HTML::THISDOC{title_no_texi}  -- title without texi (without html elements)
1396 # $Texi2HTML::THISDOC{title_texi}     -- title with texinfo @-commands
1397 # $Texi2HTML::THISDOC{fulltitle}      -- full title as set by @title...
1398 # $Texi2HTML::THISDOC{subtitle}       -- subtitle as set by @subtitle
1399 # $Texi2HTML::THISDOC{author}         -- author as set by @author
1400 # $Texi2HTML::THISDOC{copying}        -- text of @copying and @end copying in comment
1401 #
1402 # $Texi2HTML::THISDOC{program}          -- name and version of texi2html
1403 # $Texi2HTML::THISDOC{program_homepage} -- homepage for texi2html
1404 # $Texi2HTML::THISDOC{program_authors}  -- authors of texi2html
1405 # $Texi2HTML::THISDOC{today}            -- date formatted with pretty_date
1406 # $Texi2HTML::THISDOC{toc_file}         -- table of contents file
1407 # $Texi2HTML::THISDOC{file_base_name}   -- base name of the texinfo manual file
1408 # $Texi2HTML::THISDOC{destination_directory}
1409                                  #      -- directory for the resulting files
1410 # $Texi2HTML::THISDOC{user}             -- user running the script
1411 # $Texi2HTML::THISDOC{css_import_lines} -- ref on @import lines in css files
1412 # $Texi2HTML::THISDOC{css_lines}        -- ref on css rules lines
1413 # other $Texi2HTML::THISDOC keys corresponds with texinfo commands, the value
1414 # being the command arg, for the following commands:
1415 # kbdinputstyle, paragraphindent, setchapternewpage, headings, footnotestyle,
1416 # exampleindent, firstparagraphindent, everyheading, everyfooting,
1417 # evenheading, evenfooting, oddheading, oddfooting
1418 #
1419 # and pointer to arrays of lines which need to be printed by main::print_lines
1420 # $Texi2HTML::THIS_SECTION  -- lines of 'This' section
1421 # $Texi2HTML::THIS_HEADER   -- lines preceding navigation panel of 'This' section
1422 # $Texi2HTML::OVERVIEW      -- lines of short table of contents
1423 # $Texi2HTML::TOC_LINES     -- lines of table of contents
1424 # $Texi2HTML::TITLEPAGE     -- lines of title page
1425 #
1426 # $Texi2HTML::THIS_ELEMENT  holds the element reference.  
1427
1428 #
1429 # There are the following subs which control the layout:
1430 #
1431 $print_section            = \&T2H_DEFAULT_print_section;
1432 $end_section              = \&T2H_DEFAULT_end_section;
1433 $one_section              = \&T2H_DEFAULT_one_section;
1434 $print_Top_header         = \&T2H_DEFAULT_print_Top_header;
1435 $print_Top_footer             = \&T2H_DEFAULT_print_Top_footer;
1436 $print_Top                    = \&T2H_DEFAULT_print_Top;
1437 $print_Toc                    = \&T2H_DEFAULT_print_Toc;
1438 $print_Overview       = \&T2H_DEFAULT_print_Overview;
1439 $print_Footnotes              = \&T2H_DEFAULT_print_Footnotes;
1440 $print_About          = \&T2H_DEFAULT_print_About;
1441 $print_misc_header            = \&T2H_DEFAULT_print_misc_header;
1442 $print_misc_footer            = \&T2H_DEFAULT_print_misc_footer;
1443 $print_misc                   = \&T2H_DEFAULT_print_misc;
1444 $print_section_footer     = \&T2H_DEFAULT_print_section_footer;
1445 $print_chapter_header     = \&T2H_DEFAULT_print_chapter_header;
1446 $print_section_header     = \&T2H_DEFAULT_print_section_header;
1447 $print_chapter_footer     = \&T2H_DEFAULT_print_chapter_footer;
1448 $print_page_head              = \&T2H_DEFAULT_print_page_head;
1449 $print_page_foot              = \&T2H_DEFAULT_print_page_foot;
1450 $print_head_navigation    = \&T2H_DEFAULT_print_head_navigation;
1451 $print_foot_navigation    = \&T2H_DEFAULT_print_foot_navigation;
1452 $button_icon_img              = \&T2H_DEFAULT_button_icon_img;
1453 $print_navigation             = \&T2H_DEFAULT_print_navigation;
1454 $about_body                   = \&T2H_DEFAULT_about_body;
1455 $print_frame              = \&T2H_DEFAULT_print_frame;
1456 $print_toc_frame          = \&T2H_DEFAULT_print_toc_frame;
1457 #$toc_body                 = \&T2H_DEFAULT_toc_body;
1458 $titlepage                 = \&T2H_DEFAULT_titlepage;
1459 $css_lines                 = \&T2H_DEFAULT_css_lines;
1460 $print_redirection_page    = \&T2H_DEFAULT_print_redirection_page;
1461 $node_file_name            = \&T2H_DEFAULT_node_file_name;
1462 $inline_contents           = \&T2H_DEFAULT_inline_contents;
1463
1464 ########################################################################
1465 # Layout for html for every sections
1466 #
1467 sub T2H_DEFAULT_print_section
1468 {
1469     my $fh = shift;
1470     my $first_in_page = shift;
1471     my $previous_is_top = shift;
1472     my $buttons = \@SECTION_BUTTONS;
1473
1474     if ($first_in_page and $SECTION_NAVIGATION)
1475     {
1476         &$print_head_navigation($fh, $buttons);
1477     }
1478     else
1479     { # got to do this here, as it isn't done in print_head_navigation
1480         main::print_lines($fh, $Texi2HTML::THIS_HEADER);
1481         &$print_navigation($fh, $buttons) if ($SECTION_NAVIGATION);
1482     }
1483     my $nw = main::print_lines($fh);
1484     if (defined $SPLIT
1485         and (($SPLIT eq 'node') && $SECTION_NAVIGATION))
1486     {
1487         &$print_foot_navigation($fh);
1488         print $fh "$SMALL_RULE\n";
1489         &$print_navigation($fh, \@NODE_FOOTER_BUTTONS) if (!defined($WORDS_IN_PAGE) or (defined ($nw)
1490                                     and $nw >= $WORDS_IN_PAGE));
1491     }
1492 }
1493
1494 sub T2H_DEFAULT_one_section($)
1495 {
1496     my $fh = shift;
1497     main::print_lines($fh, $Texi2HTML::THIS_HEADER);
1498     main::print_lines($fh);
1499     print $fh "$SMALL_RULE\n";
1500     &$print_foot_navigation($fh);
1501     &$print_page_foot($fh);
1502 }
1503
1504 ###################################################################
1505 # Layout of top-page I recommend that you use @ifnothtml, @ifhtml,
1506 # @html within the Top texinfo node to specify content of top-level
1507 # page.
1508 #
1509 # If you enclose everything in @ifnothtml, then title, subtitle,
1510 # author and overview is printed
1511 # Texi2HTML::HREF of Next, Prev, Up, Forward, Back are not defined
1512 # if $T2H_SPLIT then Top page is in its own html file
1513 sub T2H_DEFAULT_print_Top_header($$)
1514 {
1515     my $fh = shift;
1516     my $do_page_head = shift;
1517     &$print_page_head($fh) if ($do_page_head);
1518 }
1519 sub T2H_DEFAULT_print_Top_footer($$)
1520 {
1521     my $fh = shift;
1522     my $end_page = shift;
1523     my $buttons = \@MISC_BUTTONS;
1524     &$print_foot_navigation($fh);
1525     print $fh "$SMALL_RULE\n";
1526     if ($end_page)
1527     {
1528         &$print_navigation($fh, $buttons);
1529         &$print_page_foot($fh);
1530     }
1531 }
1532 sub T2H_DEFAULT_print_Top($$)
1533 {
1534     my $fh = shift;
1535     my $has_top_heading = shift;
1536
1537     # for redefining navigation buttons use:
1538     # my $buttons = [...];
1539     # as it is, 'Top', 'Contents', 'Index', 'About' are printed
1540     my $buttons = \@MISC_BUTTONS;
1541     &$print_head_navigation($fh, $buttons) if ($SPLIT or $SECTION_NAVIGATION);
1542     my $nw;
1543     if (@$Texi2HTML::THIS_SECTION)
1544     {
1545         # if top-level node has content, then print it with extra header
1546         #print $fh "<h1>$Texi2HTML::NAME{Top}</h1>\n"
1547         print $fh "<h1 class=\"settitle\">$Texi2HTML::NAME{Top}</h1>\n"
1548             unless ($has_top_heading);
1549         $nw = main::print_lines($fh, $Texi2HTML::THIS_SECTION);
1550     }
1551     else
1552     {
1553         # top-level node is fully enclosed in @ifnothtml
1554         # print fulltitle, subtitle, author, Overview or table of contents
1555         print $fh $Texi2HTML::TITLEPAGE;
1556         if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'})
1557         {
1558              print $fh '<h2> ' . $Texi2HTML::NAME{'Overview'} . "</h2>\n" . "<blockquote\n";
1559              my $nw = main::print_lines($fh, $Texi2HTML::OVERVIEW);
1560              print $fh "</blockquote>\n";
1561         }
1562         elsif (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::THISDOC{'setcontentsaftertitlepage'})
1563         {
1564              print $fh '<h1> ' . $Texi2HTML::NAME{'Contents'}  . "</h1>\n";
1565              my $nw = main::print_lines($fh, $Texi2HTML::TOC_LINES);
1566         }
1567     }
1568 }
1569
1570 ###################################################################
1571 # Layout of Toc, Overview, and Footnotes pages
1572 # By default, we use "normal" layout
1573 # Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined
1574 # use: my $buttons = [...] to redefine navigation buttons
1575 sub T2H_DEFAULT_print_Toc
1576 {
1577     return &$print_misc(@_);
1578 }
1579 sub T2H_DEFAULT_print_Overview
1580 {
1581     return &$print_misc(@_);
1582 }
1583 sub T2H_DEFAULT_print_Footnotes
1584 {
1585     return &$print_misc(@_);
1586 }
1587 sub T2H_DEFAULT_print_About
1588 {
1589     # if there is no section navigation and it is not split, the 
1590     # navigation information is useless
1591     return &$print_misc(@_) if ($SPLIT or $SECTION_NAVIGATION);
1592 }
1593
1594 sub T2H_DEFAULT_print_misc_header
1595 {
1596     my $fh = shift;
1597     my $buttons = shift;
1598     &$print_page_head($fh) if $SPLIT;
1599     &$print_head_navigation($fh, $buttons) if ($SPLIT or $SECTION_NAVIGATION);
1600 }
1601
1602 sub T2H_DEFAULT_print_misc_footer
1603 {
1604     my $fh = shift;
1605     my $buttons = shift;
1606     my $nwords = shift;
1607     &$print_foot_navigation($fh, $buttons);
1608     print $fh "$SMALL_RULE\n";
1609     if ($SPLIT)
1610     {
1611         &$print_navigation($fh, $buttons);# if ($SPLIT ne 'node');
1612         &$print_page_foot($fh);
1613     }
1614 }
1615
1616 sub T2H_DEFAULT_print_misc
1617 {
1618     my $fh = shift;
1619     my $buttons = \@MISC_BUTTONS;
1620     &$print_misc_header($fh, $buttons);
1621     print $fh "<h1>$Texi2HTML::NAME{This}</h1>\n";
1622     main::print_lines($fh);
1623     &$print_misc_footer($fh, $buttons);
1624 }
1625 ##################################################################
1626 # section_footer is only called if SPLIT eq 'section'
1627 # section_footer: after print_section of last section, before print_page_foot
1628 #
1629
1630 sub T2H_DEFAULT_print_section_footer
1631 {
1632     my $fh = shift;
1633     my $buttons = \@SECTION_FOOTER_BUTTONS;
1634     &$end_section ($fh, 1);
1635     &$print_navigation($fh, $buttons);
1636 }
1637
1638 ###################################################################
1639 # chapter_header and chapter_footer are only called if
1640 # SPLIT eq 'chapter'
1641 # chapter_header: after print_page_head, before print_section
1642 # chapter_footer: after print_section of last section, before print_page_foot
1643 #
1644 # If you want to get rid of navigation stuff after each section,
1645 # redefine print_section such that it does not call print_navigation,
1646 # and put print_navigation into print_chapter_header
1647 sub T2H_DEFAULT_print_chapter_header
1648 {
1649     # nothing to do there, by default, the navigation panel 
1650     # is the section navigation panel
1651     if (! $SECTION_NAVIGATION)
1652     { # in this case print_navigation is called here. 
1653         my $fh = shift;
1654         my $buttons = \@CHAPTER_BUTTONS;
1655         &$print_head_navigation($fh, $buttons); #do that instead ?
1656         #&$print_head_navigation($fh, $buttons); # FIXME VERTICAL_HEAD_NAVIGATION ?
1657         print $fh "\n$MIDDLE_RULE\n";
1658     }
1659 }
1660
1661 sub T2H_DEFAULT_print_chapter_footer
1662 {
1663     my $fh = shift;
1664     my $buttons = \@CHAPTER_BUTTONS;
1665     &$print_foot_navigation($fh);
1666     print $fh "$BIG_RULE\n";
1667     &$print_navigation($fh, $buttons);
1668 }
1669
1670 sub T2H_DEFAULT_print_section_header
1671 {
1672     # nothing to do there, by default
1673     if (! $SECTION_NAVIGATION)
1674     { # in this case print_navigation is called here. 
1675         my $fh = shift;
1676         my $buttons = \@SECTION_BUTTONS;
1677         &$print_head_navigation($fh, $buttons); 
1678     }
1679 }
1680
1681 ###################################################################
1682 # Layout of standard header and footer
1683 #
1684
1685 sub T2H_DEFAULT_print_page_head($)
1686 {
1687     my $fh = shift;
1688     my $longtitle = "$Texi2HTML::THISDOC{'title_simple_format'}";
1689     $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if (defined ($Texi2HTML::SIMPLE_TEXT{'This'}) and ($Texi2HTML::SIMPLE_TEXT{'This'} !~ /^\s*$/) and $SPLIT);
1690     my $description = $DOCUMENT_DESCRIPTION;
1691     $description = $longtitle if (!defined($description));
1692     $description = "<meta name=\"description\" content=\"$description\">" if
1693          ($description ne '');
1694     my $encoding = '';
1695     $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING_NAME\">" if (defined($ENCODING_NAME) and ($ENCODING_NAME ne ''));
1696     print $fh <<EOT;
1697 $DOCTYPE
1698 <html>
1699 $Texi2HTML::THISDOC{'copying'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program} -->
1700 <!--
1701 $Texi2HTML::THISDOC{program_authors}
1702 -->
1703 <head>
1704 <title>$longtitle</title>
1705
1706 $description
1707 <meta name="keywords" content="$longtitle">
1708 <meta name="resource-type" content="document">
1709 <meta name="distribution" content="global">
1710 <meta name="Generator" content="$Texi2HTML::THISDOC{program}">
1711 $encoding
1712 $CSS_LINES
1713 $EXTRA_HEAD
1714 </head>
1715
1716 <body $BODYTEXT>
1717 $AFTER_BODY_OPEN
1718 EOT
1719 }
1720
1721 sub program_string()
1722 {
1723     my $user = $Texi2HTML::THISDOC{'user'};
1724     my $date = $Texi2HTML::THISDOC{'today'};
1725     $user = '' if (!defined($user));
1726     $date = '' if (!defined($date));
1727     if (($user ne '') and ($date ne ''))
1728     {
1729         return  &$I('This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.', {
1730            'user' => $user, 'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} });
1731     }
1732     elsif ($user ne '')
1733     {
1734         return  &$I('This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.', {
1735            'user' => $user, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} });
1736     }
1737     elsif ($date ne '')
1738     {
1739         return  &$I('This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.', {
1740            'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} });
1741     }
1742     return &$I('This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.', {
1743        'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program'
1744 => $Texi2HTML::THISDOC{'program'} });
1745 }
1746
1747 sub T2H_DEFAULT_end_section($$)
1748 {
1749     my $fh = shift;
1750     my $end_foot_navigation = shift;
1751     &$print_foot_navigation($fh) if ($end_foot_navigation);
1752     print $fh "$BIG_RULE\n";
1753 }
1754
1755 sub T2H_DEFAULT_print_page_foot($)
1756 {
1757     my $fh = shift;
1758     my $program_string = program_string();
1759     print $fh <<EOT;
1760 <p>
1761  <font size="-1">
1762   $program_string
1763  </font>
1764  <br>
1765 $PRE_BODY_CLOSE
1766 </p>
1767 </body>
1768 </html>
1769 EOT
1770 }
1771
1772 ###################################################################
1773 # Layout of navigation panel
1774
1775 sub T2H_DEFAULT_print_head_navigation($$)
1776 {
1777     my $fh = shift;
1778     my $buttons = shift;
1779     if ($VERTICAL_HEAD_NAVIGATION)
1780     {
1781         print $fh <<EOT;
1782 <table border="0" cellpadding="0" cellspacing="0">
1783 <tr valign="top">
1784 <td align="left">
1785 EOT
1786     }
1787     main::print_lines($fh, $Texi2HTML::THIS_HEADER);
1788     &$print_navigation($fh, $buttons, $VERTICAL_HEAD_NAVIGATION);
1789     if ($VERTICAL_HEAD_NAVIGATION)
1790     {
1791         print $fh <<EOT;
1792 </td>
1793 <td align="left">
1794 EOT
1795     }
1796     elsif (defined $SPLIT
1797            and ($SPLIT eq 'node'))
1798     {
1799         print $fh "$SMALL_RULE\n";
1800     }
1801 }
1802
1803 sub T2H_DEFAULT_print_foot_navigation
1804 {
1805     my $fh = shift;
1806     if ($VERTICAL_HEAD_NAVIGATION)
1807     {
1808         print $fh <<EOT;
1809 </td>
1810 </tr>
1811 </table>
1812 EOT
1813     }
1814 }
1815
1816 ######################################################################
1817 # navigation panel
1818 #
1819 # how to create IMG tag
1820 sub T2H_DEFAULT_button_icon_img
1821 {
1822     my $button = shift;
1823     my $icon = shift;
1824     my $name = shift;
1825     return '' if (!defined($icon));
1826     $button = "" if (!defined ($button));
1827     $name = '' if (!defined($name));
1828     my $alt = ''; 
1829     if ($name ne '')
1830     {
1831         if ($button ne '')
1832         {
1833             $alt = "$button: $name";
1834         }
1835         else
1836         {
1837             $alt = $name;
1838         }  
1839     }
1840     else
1841     {
1842         $alt = $button;
1843     }
1844     return qq{<img src="$icon" border="0" alt="$alt" align="middle">};
1845 }
1846
1847 sub T2H_DEFAULT_print_navigation
1848 {
1849     my $fh = shift;
1850     my $buttons = shift;
1851     my $vertical = shift;
1852     my $spacing = 1;
1853     print $fh '<table cellpadding="', $spacing, '" cellspacing="', $spacing,
1854       "\" border=\"0\">\n";
1855
1856     print $fh "<tr>" unless $vertical;
1857     for my $button (@$buttons)
1858     {
1859         print $fh qq{<tr valign="top" align="left">\n} if $vertical;
1860         print $fh qq{<td valign="middle" align="left">};
1861
1862         if (ref($button) eq 'CODE')
1863         {
1864             &$button($fh, $vertical);
1865         }
1866         elsif (ref($button) eq 'SCALAR')
1867         {
1868             print $fh "$$button" if defined($$button);
1869         }
1870         elsif (ref($button) eq 'ARRAY')
1871         {
1872             my $text = $button->[1];
1873             my $button_href = $button->[0];
1874             # verify that $button_href is simple text and text is a reference
1875             if (defined($button_href) and !ref($button_href) 
1876                and defined($text) and (ref($text) eq 'SCALAR') and defined($$text))
1877             {             # use given text
1878                 if ($Texi2HTML::HREF{$button_href})
1879                 {
1880                   print $fh "" .
1881                         &$anchor('',
1882                                     $Texi2HTML::HREF{$button_href},
1883                                     $$text
1884                                    ) 
1885                                     ;
1886                 }
1887                 else
1888                 {
1889                   print $fh $$text;
1890                 }
1891             }
1892         }
1893         elsif ($button eq ' ')
1894         {                       # handle space button
1895             print $fh
1896                 ($ICONS && $ACTIVE_ICONS{' '}) ?
1897                     &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) :
1898                         $NAVIGATION_TEXT{' '};
1899             #next;
1900         }
1901         elsif ($Texi2HTML::HREF{$button})
1902         {                       # button is active
1903             my $btitle = $BUTTONS_GOTO{$button} ?
1904                 'title="' . $BUTTONS_GOTO{$button} . '"' : '';
1905             if ($ICONS && $ACTIVE_ICONS{$button})
1906             {                   # use icon
1907                 print $fh '' .
1908                     &$anchor('',
1909                         $Texi2HTML::HREF{$button},
1910                         &$button_icon_img($BUTTONS_NAME{$button},
1911                                    $ACTIVE_ICONS{$button},
1912                                    $Texi2HTML::SIMPLE_TEXT{$button}),
1913                         $btitle
1914                       );
1915             }
1916             else
1917             {                   # use text
1918                 print $fh
1919                     '[' .
1920                         &$anchor('',
1921                                     $Texi2HTML::HREF{$button},
1922                                     $NAVIGATION_TEXT{$button},
1923                                     $btitle
1924                                    ) .
1925                                        ']';
1926             }
1927         }
1928         else
1929         {                       # button is passive
1930             print $fh
1931                 $ICONS && $PASSIVE_ICONS{$button} ?
1932                     &$button_icon_img($BUTTONS_NAME{$button},
1933                                           $PASSIVE_ICONS{$button},
1934                                           $Texi2HTML::SIMPLE_TEXT{$button}) :
1935
1936                                               "[" . $NAVIGATION_TEXT{$button} . "]";
1937         }
1938         print $fh "</td>\n";
1939         print $fh "</tr>\n" if $vertical;
1940     }
1941     print $fh "</tr>" unless $vertical;
1942     print $fh "</table>\n";
1943 }
1944
1945 ######################################################################
1946 # Frames: this is from "Richard Y. Kim" <ryk@coho.net>
1947 # Should be improved to be more conforming to other _print* functions
1948 # FIXME pass toc_file and main_file as args or in $Texi2HTML::THISDOC ?
1949
1950 sub T2H_DEFAULT_print_frame
1951 {
1952     my $fh = shift;
1953     my $toc_file = shift;
1954     my $main_file = shift;
1955     print $fh <<EOT;
1956 $FRAMESET_DOCTYPE
1957 <html>
1958 <head><title>$Texi2HTML::THISDOC{title}</title></head>
1959 <frameset cols="140,*">
1960   <frame name="toc" src="$toc_file">
1961   <frame name="main" src="$main_file">
1962 </frameset>
1963 </html>
1964 EOT
1965 }
1966
1967 sub T2H_DEFAULT_print_toc_frame
1968 {
1969     my $fh = shift;
1970     my $stoc_lines = shift;
1971     &$print_page_head($fh);
1972     print $fh <<EOT;
1973 <h2>Content</h2>
1974 EOT
1975     print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines;
1976     print $fh "</body></html>\n";
1977 }
1978
1979 # This subroutine is intended to fill @Texi2HTML::TOC_LINES and 
1980 # @Texi2HTML::OVERVIEW with the table of contents and short table of
1981 # contents.
1982 #
1983 # arguments:
1984 # ref on an array containing all the elements
1985
1986 # each element is a reference on a hash. The following keys might be of
1987 # use:
1988 # 'top': true if this is the top element
1989 # 'index_page': true if the element is an index page added because of index 
1990 #               splitting
1991 # 'toc_level': level of the element in the table of content. Highest level
1992 #              is 1 for the @top element and for chapters, appendix and so on,
1993 #              2 for section, unnumberedsec and so on... 
1994 # 'tocid': label used for reference linking to the element in table of
1995 #          contents
1996 # 'file': the file containing the element, usefull to do href to that file
1997 #         in case the document is split.
1998 # 'text': text of the element, with section number
1999 # 'text_nonumber': text of the element, without section number
2000
2001 # Relevant configuration variables are:
2002 # $NUMBER_SECTIONS
2003 # $TOC_LIST_ATTRIBUTE: usefull in case a list is used
2004 # $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames. 
2005 # $BEFORE_OVERVIEW
2006 # $AFTER_OVERVIEW
2007 # $BEFORE_TOC_LINES
2008 # $AFTER_TOC_LINES
2009 # $DO_CONTENTS
2010 # $DO_SCONTENTS
2011
2012 sub T2H_DEFAULT_toc_body($)
2013 {
2014 }
2015
2016 sub T2H_DEFAULT_inline_contents($$$)
2017 {
2018     my $fh = shift;
2019     my $command = shift;
2020     my $element = shift;
2021     my $name;
2022     my $lines;
2023
2024     my $result = undef;
2025
2026     if ($command eq 'contents')
2027     {
2028         $name = $Texi2HTML::NAME{'Contents'};
2029         $lines = $Texi2HTML::TOC_LINES;
2030     }
2031     else
2032     {
2033         $name = $Texi2HTML::NAME{'Overview'};
2034         $lines = $Texi2HTML::OVERVIEW;
2035     }
2036     if (@{$lines})
2037     {
2038          $result = [ "".&$anchor($element->{'id'})."\n",
2039             "<h1>$name</h1>\n" ]; 
2040          push @$result, @$lines;
2041     }
2042
2043     return $result;
2044 }
2045
2046 sub T2H_DEFAULT_css_lines ($$)
2047 {
2048     my $import_lines = shift;
2049     my $rule_lines = shift;
2050     return if (defined($CSS_LINES) or (!@$rule_lines and !@$import_lines and (! keys(%css_map))));
2051     $CSS_LINES = "<style type=\"text/css\">\n<!--\n";
2052     $CSS_LINES .= join('',@$import_lines) . "\n" if (@$import_lines);
2053     foreach my $css_rule (sort(keys(%css_map)))
2054     {
2055         next unless ($css_map{$css_rule});
2056         $CSS_LINES .= "$css_rule {$css_map{$css_rule}}\n";
2057     }
2058     $CSS_LINES .= join('',@$rule_lines) . "\n" if (@$rule_lines);
2059     $CSS_LINES .= "-->\n</style>\n";
2060 }
2061
2062 ######################################################################
2063 # About page
2064 #
2065
2066 # PRE_ABOUT can be a function reference or a scalar.
2067 # Note that if it is a scalar, T2H_InitGlobals has not been called,
2068 # and all global variables like $ADDRESS are not available.
2069 $PRE_ABOUT = sub
2070 {
2071     return '  ' . program_string() .  "\n";
2072 };
2073
2074 # If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>.
2075 $AFTER_ABOUT = '';
2076
2077 %BUTTONS_EXAMPLE =
2078     (
2079      'Top',         ' &nbsp; ',
2080      'Contents',    ' &nbsp; ',
2081      'Overview',    ' &nbsp; ',
2082      'Index',       ' &nbsp; ',
2083      'This',        '1.2.3',
2084      'Back',        '1.2.2',
2085      'FastBack',    '1',
2086      'Prev',        '1.2.2',
2087      'Up',          '1.2',
2088      'Next',        '1.2.4',
2089      'NodeUp',      '1.2',
2090      'NodeNext',    '1.2.4',
2091      'NodePrev',    '1.2.2',
2092      'Following',   '1.2.4',
2093      'Forward',     '1.2.4',
2094      'FastForward', '2',
2095      'About',       ' &nbsp; ',
2096      'First',       '1.',
2097      'Last',        '1.2.4',
2098     );
2099
2100 sub T2H_DEFAULT_about_body
2101 {
2102     my $about = "<p>\n";
2103     if (ref($PRE_ABOUT) eq 'CODE')
2104     {
2105         $about .= &$PRE_ABOUT();
2106     }
2107     else
2108     {
2109         $about .= $PRE_ABOUT;
2110     }
2111     $about .= <<EOT;
2112 </p>
2113 <p>
2114 EOT
2115     $about .= &$I('  The buttons in the navigation panels have the following meaning:') . "\n";
2116     $about .= <<EOT;
2117 </p>
2118 <table border="1">
2119   <tr>
2120 EOT
2121     $about .= '    <th> ' . &$I('Button') . " </th>\n" .
2122 '    <th> ' . &$I('Name') . " </th>\n" .
2123 '    <th> ' . &$I('Go to') . " </th>\n" .
2124 '    <th> ' . &$I('From 1.2.3 go to') . "</th>\n" . "  </tr>\n";
2125
2126     for my $button (@SECTION_BUTTONS)
2127     {
2128         next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY';
2129         $about .= "  <tr>\n    <td align=\"center\">";
2130         $about .=
2131             ($ICONS && $ACTIVE_ICONS{$button} ?
2132              &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) :
2133              ' [' . $NAVIGATION_TEXT{$button} . '] ');
2134         $about .= "</td>\n";
2135         $about .= <<EOT;
2136     <td align="center">$BUTTONS_NAME{$button}</td>
2137     <td>$BUTTONS_GOTO{$button}</td>
2138     <td>$BUTTONS_EXAMPLE{$button}</td>
2139   </tr>
2140 EOT
2141     }
2142
2143     $about .= <<EOT;
2144 </table>
2145
2146 <p>
2147 EOT
2148     $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";
2149
2150 #  where the <strong> Example </strong> assumes that the current position
2151 #  is at <strong> Subsubsection One-Two-Three </strong> of a document of
2152 #  the following structure:
2153     $about .= <<EOT;
2154 </p>
2155
2156 <ul>
2157 EOT
2158     $about .= '  <li> 1. ' . &$I('Section One') . "\n" .
2159 "    <ul>\n" .
2160 '      <li>1.1 ' . &$I('Subsection One-One') . "\n";
2161     $about .= <<EOT;
2162         <ul>
2163           <li>...</li>
2164         </ul>
2165       </li>
2166 EOT
2167     $about .= '      <li>1.2 ' . &$I('Subsection One-Two') . "\n" .
2168 "        <ul>\n" .
2169 '          <li>1.2.1 ' . &$I('Subsubsection One-Two-One') . "</li>\n" .
2170 '          <li>1.2.2 ' . &$I('Subsubsection One-Two-Two') . "</li>\n" .
2171 '          <li>1.2.3 ' . &$I('Subsubsection One-Two-Three') . " &nbsp; &nbsp;\n"
2172 .
2173 '            <strong>&lt;== ' . &$I('Current Position') . " </strong></li>\n" .
2174 '          <li>1.2.4 ' . &$I('Subsubsection One-Two-Four') . "</li>\n" .
2175 "        </ul>\n" .
2176 "      </li>\n" .
2177 '      <li>1.3 ' . &$I('Subsection One-Three') . "\n";
2178     $about .= <<EOT;
2179         <ul>
2180           <li>...</li>
2181         </ul>
2182       </li>
2183 EOT
2184     $about .= '      <li>1.4 ' . &$I('Subsection One-Four') . "</li>\n";
2185     $about .= <<EOT;
2186     </ul>
2187   </li>
2188 </ul>
2189 $AFTER_ABOUT
2190 EOT
2191     return $about;
2192 }
2193
2194 sub T2H_DEFAULT_titlepage()
2195 {
2196     my $result = '';
2197     if (@{$Texi2HTML::THISDOC{'titles'}} 
2198         or @{$Texi2HTML::THISDOC{'subtitles'}} 
2199         or @{$Texi2HTML::THISDOC{'authors'}})
2200     {     
2201         $result = "<div align=\"center\">\n";
2202         foreach my $title (@{$Texi2HTML::THISDOC{'titles'}})
2203         {
2204             $result .= '<h1>' . $title . "</h1>\n";
2205         }    
2206         foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}})
2207         {
2208             $result .= '<h2>' . $subtitle . "</h2>\n";
2209         }
2210         foreach my $author (@{$Texi2HTML::THISDOC{'authors'}})
2211         {
2212             $result .= '<strong> ' . $author . " </strong><br>\n";
2213         }
2214         $result .= "</div>\n$DEFAULT_RULE\n";
2215     }
2216
2217     $Texi2HTML::TITLEPAGE = $result . $Texi2HTML::TITLEPAGE;
2218     
2219     if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
2220     {
2221         foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
2222         {
2223             $Texi2HTML::TITLEPAGE .= $line;
2224         }
2225         $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
2226     }
2227     if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
2228     {
2229         foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
2230         {
2231             $Texi2HTML::TITLEPAGE .= $line;
2232         }
2233         $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
2234     }
2235 }
2236
2237 # FIXME Honor DOCUMENT_DESCRIPTION? 
2238 sub T2H_DEFAULT_print_redirection_page($)
2239 {
2240     my $fh = shift;
2241     my $longtitle = "$Texi2HTML::THISDOC{'title_simple_format'}";
2242     $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if exists $Texi2HTML::SIMPLE_TEXT{'This'};
2243     my $description = $longtitle;
2244     my $encoding = '';
2245     $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING_NAME\">" if (defined($ENCODING_NAME) and ($ENCODING_NAME ne ''));
2246     my $href = &$anchor('', $Texi2HTML::HREF{'This'}, $Texi2HTML::NAME{'This'}); 
2247     my $string = &$I('The node you are looking for is at %{href}.',
2248        { 'href' => $href });
2249     print $fh <<EOT;
2250 $DOCTYPE
2251 <html>
2252 <!-- Created on $Texi2HTML::THISDOC{'today'} by $Texi2HTML::THISDOC{'program'} -->
2253 <!--
2254 $Texi2HTML::THISDOC{'program_authors'}
2255 -->
2256 <head>
2257 <title>$longtitle</title>
2258
2259 <meta name="description" content="$description">
2260 <meta name="keywords" content="$longtitle">
2261 <meta name="resource-type" content="document">
2262 <meta name="distribution" content="global">
2263 <meta name="Generator" content="$Texi2HTML::THISDOC{program}">
2264 $encoding
2265 $CSS_LINES
2266 <meta http-equiv="Refresh" content="2; url=$Texi2HTML::HREF{'This'}">
2267 $EXTRA_HEAD
2268 </head>
2269
2270 <body $BODYTEXT>
2271 $AFTER_BODY_OPEN
2272 <p>$string</p>
2273 </body>
2274 EOT
2275 }
2276
2277 sub T2H_DEFAULT_node_file_name($$)
2278 {
2279     my $node = shift;
2280     my $type = shift;
2281     return undef if ($node->{'external_node'} or $node->{'index_page'}
2282        or ($type eq 'top' and !$NEW_CROSSREF_STYLE));
2283     my $node_file_base;
2284     if ($type eq 'top' and defined($TOP_NODE_FILE))
2285     {
2286         $node_file_base = $TOP_NODE_FILE;
2287     }
2288     elsif ($NEW_CROSSREF_STYLE)
2289     {
2290         if ($TRANSLITERATE_NODE)
2291         {
2292             $node_file_base = $node->{'cross_manual_file'};
2293         }
2294         else
2295         {
2296             $node_file_base = $node->{'cross_manual_target'};
2297         }
2298     }
2299     else
2300     {
2301          $node_file_base = main::remove_texi($node->{'texi'});
2302          $node_file_base =~ s/[^\w\.\-]/-/g;
2303     }
2304     if (defined($NODE_FILE_EXTENSION) and $NODE_FILE_EXTENSION ne '')
2305     {
2306         return ($node_file_base . ".$NODE_FILE_EXTENSION");
2307     }
2308     return $node_file_base;
2309 }
2310
2311 ########################################################################
2312 # Control of formatting:
2313 # 1.) For some changes, it is often enough to change the value of
2314 #     some global map. It might necessitate building a little
2315 #     function along with the change in hash, if the change is the use
2316 #     of another function (in style_map).
2317 # 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines,
2318 #     give them another name, and assign them to the respective
2319 #     $<fnc> variable (below).
2320
2321
2322 #
2323 # This hash should have keys corresponding with the nonletter command accent
2324 # whose following character is considered to be the argument
2325 # This hash associates an accent macro to the ISO name for the accent if any.
2326 # The customary use of this map is to find the ISO name appearing in html
2327 # entity (like &eacute;) associated with a texinfo accent macro.
2328 #
2329 # The keys of the hash are
2330 # ": umlaut
2331 # ~: tilda accent
2332 # ^: circumflex accent
2333 # `: grave accent
2334 # ': acute accent
2335 # =: macron accent
2336 %accent_map = (
2337           '"',  'uml',
2338           '~',  'tilde',
2339           '^',  'circ',
2340           '`',  'grave',
2341           "'", 'acute',
2342           '=', '',
2343          );
2344
2345 #
2346 # texinfo "simple things" (@foo) to HTML ones
2347 #
2348 %simple_map = (
2349            "*", "<br>",     # HTML+
2350            ' ', '&nbsp;',
2351            "\t", '&nbsp;',
2352            "\n", '&nbsp;',
2353      # "&#173;" or "&shy;" could also be possible for @-, but it seems
2354      # that some browser will consider this as an always visible hyphen mark
2355      # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html)
2356            '-', '',  # hyphenation hint
2357            '|', '',  # used in formatting commands @evenfooting and friends
2358            '/', '',
2359        # spacing commands
2360            ':', '',
2361            '!', '!',
2362            '?', '?',
2363            '.', '.',
2364            '@', '@',
2365            '}', '}',
2366            '{', '{',
2367           );
2368
2369 # this map is used in preformatted text
2370 %simple_map_pre = %simple_map;
2371 $simple_map_pre{'*'} = "\n";
2372
2373 #
2374 # texinfo "things" (@foo{}) to HTML ones
2375 #
2376 %things_map = (
2377                'TeX'          => 'TeX',
2378                'LaTeX'          => 'LaTeX',
2379 # pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing)
2380 #               'br', '<br>',     # paragraph break
2381                'bullet'       => '*',
2382 #               #'copyright' => '(C)',
2383                'copyright'    => '&copy;',
2384                'registeredsymbol'   => '&reg;',
2385                'dots'         => '<small class="dots">...</small>',
2386                'enddots'      => '<small class="enddots">....</small>',
2387                'equiv'        => '==',
2388 # FIXME i18n
2389                'error'        => 'error--&gt;',
2390                'expansion'    => '==&gt;',
2391                'minus'        => '-',
2392                'point'        => '-!-',
2393                'print'        => '-|',
2394                'result'       => '=&gt;',
2395                # set in code using the language
2396                # 'today', &pretty_date,
2397                'today'        => '',
2398                'aa'           => '&aring;',
2399                'AA'           => '&Aring;',
2400                'ae'           => '&aelig;',
2401                'oe'           => '&oelig;', #pertusus: also &#156;. &oelig; not in html 3.2
2402                'AE'           => '&AElig;',
2403                'OE'           => '&OElig;', #pertusus: also &#140;. &OElig; not in html 3.2
2404                'o'            =>  '&oslash;',
2405                'O'            =>  '&Oslash;',
2406                'ss'           => '&szlig;',
2407                'l'            => '&#322;',
2408                'L'            => '&#321;',
2409                'exclamdown'   => '&iexcl;',
2410                'questiondown' => '&iquest;',
2411                'pounds'       => '&pound;',
2412                'ordf'         => '&ordf;',
2413                'ordm'         => '&ordm;',
2414                'comma'        => ',',
2415                'euro'         => '&euro;',
2416                'tie'          => '&nbsp;',
2417              );
2418
2419 # This map is used in preformatted environments
2420 %pre_map = %things_map;
2421 $pre_map{'dots'} = '...';
2422 $pre_map{'enddots'} = '....';
2423 #$pre_map{'br'} = "\n";
2424
2425 # ascii representation of @-commands
2426 %ascii_simple_map = (
2427            "*", "\n",     # HTML+
2428            ' ', ' ',
2429            "\t", "\t",
2430            "\n", "\n",
2431            '-', '',  # hyphenation hint
2432            '|', '',  # used in formatting commands @evenfooting and friends
2433            '/', '',
2434            ':', '',
2435            '!', '!',
2436            '?', '?',
2437            '.', '.',
2438            '@', '@',
2439            '}', '}',
2440            '{', '{',
2441 );
2442
2443 %ascii_things_map = (
2444                'TeX'          => 'TeX',
2445                'LaTeX'          => 'LaTeX',
2446                'bullet'       => '*',
2447                'copyright' => '(C)',
2448                'registeredsymbol'   => '(R)',
2449                'dots'         => '...',
2450                'enddots'      => '....',
2451                'equiv'        => '==',
2452 # FIXME i18n
2453                'error'        => 'error-->',
2454                'expansion'    => '==>',
2455                'minus'        => '-',
2456                'point'        => '-!-',
2457                'print'        => '-|',
2458                'result'       => '=>',
2459                'today'        => '',
2460                'aa'           => 'aa',
2461                'AA'           => 'AA',
2462                'ae'           => 'ae',
2463                'oe'           => 'oe', 
2464                'AE'           => 'AE',
2465                'OE'           => 'OE',
2466                'o'            => '/o',
2467                'O'            => '/O',
2468                'ss'           => 'ss',
2469                'l'            => '/l',
2470                'L'            => '/L',
2471                'exclamdown'   => '?',
2472                'questiondown' => '!',
2473                'pounds'       => '#',
2474                'ordf'         => 'a',
2475                'ordm'         => 'o',
2476                'comma'        => ',',
2477                'euro'         => 'Euro',
2478                'tie'          => ' ',
2479 );
2480
2481 #
2482 # This map is used when texi elements are removed and replaced 
2483 # by simple text
2484 #
2485 %simple_map_texi = (
2486            "*", "",  
2487            " ", " ",
2488            "\t", " ",
2489            "-", "-",  # soft hyphen
2490            "\n", "\n",
2491            "|", "",
2492         # spacing commands
2493            ":", "",
2494            "!", "!",
2495            "?", "?",
2496            ".", ".",
2497            "-", "",
2498            '@', '@',
2499            '}', '}',
2500            '{', '{',
2501           );
2502
2503 # text replacing macros when texi commands are removed and plain text is 
2504 # produced 
2505 %texi_map = (
2506                'TeX', 'TeX',
2507                'LaTeX', 'LaTeX',
2508                'bullet', '*',
2509                'copyright', 'C',
2510                'registeredsymbol', 'R',
2511                'dots', '...',
2512                'enddots', '....',
2513                'equiv', '==',
2514                'error', 'error-->',
2515                'expansion', '==>',
2516                'minus', '-',
2517                'point', '-!-',
2518                'print', '-|',
2519                'result', '=>',
2520                'today'        => '',
2521                'aa', 'aa',
2522                'AA', 'AA',
2523                'ae', 'ae',
2524                'oe', 'oe',
2525                'AE', 'AE',
2526                'OE', 'OE',
2527                'o',  'o',
2528                'O',  'O',
2529                'ss', 'ss',
2530                'l', 'l',
2531                'L', 'L',
2532                'exclamdown', '! upside-down',
2533                #'exclamdown', '&iexcl;',
2534                'questiondown', '? upside-down',
2535                #'questiondown', '&iquest;',
2536                'pounds', 'pound sterling',
2537                #'pounds', '&pound;'
2538                'ordf'         => 'a',
2539                'ordm'         => 'o',
2540                'comma'        => ',',
2541                'euro'         => 'Euro',
2542                'tie'          => ' ',
2543             );
2544
2545 # taken from
2546 #Latin extended additionnal
2547 #http://www.alanwood.net/unicode/latin_extended_additional.html
2548 #C1 Controls and Latin-1 Supplement
2549 #http://www.alanwood.net/unicode/latin_1_supplement.html
2550 #Latin Extended-A
2551 #http://www.alanwood.net/unicode/latin_extended_a.html
2552 #Latin Extended-B
2553 #http://www.alanwood.net/unicode/latin_extended_b.html
2554 #dotless i: 0131
2555
2556 #http://www.alanwood.net/unicode/arrows.html 21**
2557 #http://www.alanwood.net/unicode/general_punctuation.html 20**
2558 #http://www.alanwood.net/unicode/mathematical_operators.html 22**
2559
2560 %unicode_map = (
2561                'bullet'       => '2022',
2562                'copyright'    => '00A9',
2563                'registeredsymbol'   => '00AE',
2564                'dots'         => '2026',
2565                'enddots'      => '',
2566                'equiv'        => '2261',
2567                'error'        => '',
2568                'expansion'    => '2192',
2569                'minus'        => '2212', # in mathematical operators
2570 #               'minus'        => '002D', # in latin1
2571                'point'        => '2605',
2572                'print'        => '22A3',
2573                'result'       => '21D2',
2574                'today'        => '',
2575                'aa'           => '00E5',
2576                'AA'           => '00C5',
2577                'ae'           => '00E6',
2578                'oe'           => '0153',
2579                'AE'           => '00C6',
2580                'OE'           => '0152',
2581                'o'            => '00F8',
2582                'O'            => '00D8',
2583                'ss'           => '00DF',
2584                'l'            => '0142',
2585                'L'            => '0141',
2586                'exclamdown'   => '00A1',
2587                'questiondown' => '00BF',
2588                'pounds'       => '00A3',
2589                'ordf'         => '00AA',
2590                'ordm'         => '00BA',
2591                'comma'        => '002C',
2592                'euro'         => '20AC',
2593                'tie'          => '',
2594 #               'tie'          => '0020', 
2595              );
2596
2597 %transliterate_map = (
2598                '00C5'  => 'AA',
2599                '00E5'  => 'aa',
2600                '00D8'  => 'OE',
2601                '00F8'  => 'oe',
2602                '00E6' => 'ae',
2603                '0153' => 'oe',
2604                '00C6' => 'AE',
2605                '0152' => 'OE',
2606                '00DF' => 'ss',
2607                '0141' => 'L',
2608                '0142' => 'l',
2609                '00D0'  => 'DH',
2610                '0415'  => 'E',
2611                '0435'  => 'e',
2612                '0426'  => 'C',
2613                '042A'  => 'W',
2614                '044A'  => 'w',
2615                '042C'  => 'X',
2616                '044C'  => 'x',
2617                '042E'  => 'yu',
2618                '042F'  => 'YA',
2619                '044F'  => 'ya',
2620                '0433'  => 'g',
2621                '0446'  => 'c',
2622                '04D7'  => 'IO',
2623                '00DD'  => 'Y', # unidecode gets this wrong ?
2624           );
2625
2626 foreach my $symbol(keys(%unicode_map))
2627 {
2628     if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol}))
2629     {
2630          $no_transliterate_map{$unicode_map{$symbol}} = 1;
2631     }
2632 }
2633
2634 %ascii_character_map = (
2635             ' ' => '0020',
2636             '!' => '0021',
2637             '"' => '0022',
2638             '#' => '0023',
2639             '$' => '0024',
2640             '%' => '0025',
2641             '&' => '0026',
2642             "'" => '0027',
2643             '(' => '0028',
2644             ')' => '0029',
2645             '*' => '002A',
2646             '+' => '002B',
2647             ',' => '002C',
2648             '-' => '002D',
2649             '.' => '002E',
2650             '/' => '002F',
2651             ':' => '003A',
2652             ';' => '003B',
2653             '<' => '003C',
2654             '=' => '003D',
2655             '>' => '003E',
2656             '?' => '003F',
2657             '@' => '0040',
2658             '[' => '005B',
2659             '\\' => '005C',
2660             ']' => '005D',
2661             '^' => '005E',
2662             '_' => '005F',
2663             '`' => '0060',
2664             '{' => '007B',
2665             '|' => '007C',
2666             '}' => '007D',
2667             '~' => '007E',
2668 );
2669
2670 %perl_charset_to_html = (
2671               'utf8'       => 'utf-8',
2672               'utf-8-strict'       => 'utf-8',
2673               'ascii'      => 'us-ascii',
2674 );
2675
2676 # symbols used for the commands if $USE_ISO is true.
2677 %iso_symbols = (
2678          'equiv'     => '&equiv;',
2679          'dots'      => '&hellip;',
2680          'bullet'    => '&bull;',
2681          'result'    => '&rArr;',
2682          'expansion' => '&rarr;',
2683          'point'     => '&lowast;',
2684          "'"         => '&rsquo;',
2685          '`'         => '&lsquo;',
2686         );
2687
2688 # not used currently for html, but used in chm.init
2689 %numeric_entity_map = ();
2690
2691 foreach my $symbol (keys(%unicode_map))
2692 {
2693     if ($symbol ne '')
2694     {
2695         $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';';
2696     }
2697 }
2698
2699 # When the value begins with & the function with that name is used to do the
2700 # html. The first argument is the text enclosed within {}, the second is the
2701 # style name (which is also the key of the hash)
2702 #
2703 # Otherwithe the value is the html element used to enclose the text, and if
2704 # there is a " the resulting text is also enclosed within `'
2705 my %old_style_map = (
2706       'acronym',    '',
2707       'asis',       '',
2708       'b',          'b',
2709       'cite',       'cite',
2710       'code',       'code',
2711       'command',    'code',
2712       'ctrl',       '&default_ctrl', 
2713       'dfn',        'em', 
2714       'dmn',        '',   
2715       'email',      '&default_email', 
2716       'emph',       'em',
2717       'env',        'code',
2718       'file',       '"tt', 
2719       'i',          'i',
2720       'kbd',        'kbd',
2721       'key',        'kbd',
2722       'math',       'em',
2723       'option',     '"samp', 
2724       'r',          '',
2725       'samp',       '"samp', 
2726       'sc',         '&default_sc',
2727       'strong',     'strong',
2728       't',          'tt',
2729       'uref',       '&default_uref',
2730       'url',        '&default_url',
2731       'var',        'var',
2732       'verb',       'tt',
2733       'titlefont',  '&default_titlefont',
2734       'w',          '',
2735      );
2736
2737 # default is {'args' => ['normal'], 'attribute' => ''},   
2738 %style_map = (
2739       'asis',       {},
2740       'b',          {'attribute' => 'b'},
2741       'cite',       {'attribute' => 'cite'},
2742       'code',       {'args' => ['code'], 'attribute' => 'code'},
2743       'command',    {'args' => ['code'], 'attribute' => 'code'},
2744       'ctrl',       {'function' => \&t2h_default_ctrl,'type' => 'simple_type'}, 
2745       'dfn',        {'attribute' => 'em'}, 
2746       'dmn',        {},   
2747       'email',      {'args' => ['code', 'normal'], 
2748                        'function' => \&t2h_default_email,
2749                        'type' => 'simple_type'}, 
2750       #'email',      {'args' => ['normal', 'normal'], 
2751       #                 'function' => \&t2h_default_email}, 
2752       'emph',       {'attribute' => 'em'}, 
2753       'env',        {'args' => ['code'], 'attribute' => 'code'},
2754       'file',       {'args' => ['code'], 'attribute' => 'tt', 'quote' => '"'},
2755       'i',          {'attribute' => 'i'},
2756       'slanted',    {'attribute' => 'i'},
2757       'sansserif',  {'attribute' => 'span class="sansserif"'},
2758       'kbd',        {'args' => ['code'], 'attribute' => 'kbd'},
2759       'key',        {'begin' => '&lt;', 'end' => '&gt;'},
2760       'math',       {'attribute' => 'em'},
2761       'option',     {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'},
2762       'r',          {'attribute' => 'span class="roman"'},
2763       'samp',       {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'},
2764 #      'sc',         {'function' => \&t2h_default_sc},
2765       'sc',         {'attribute' => 'small'},
2766       'strong',     {'attribute' => 'strong'},
2767       't',          {'attribute' => 'tt'},
2768       'uref',       {'function' => \&t2h_default_uref, 
2769                       'args' => ['code', 'normal', 'normal'],
2770                       'type' => 'simple_type' },
2771       #'uref',       {'function' => \&t2h_default_uref, 
2772       #                'args' => ['normal', 'normal', 'normal']},
2773       'url',        {'function' => \&t2h_default_uref, 
2774                       'args' => ['code', 'normal', 'normal'],
2775                       'type' => 'simple_type'},
2776       'indicateurl', {'args' => ['code'], 'begin' => '&lt;<code>', 'end' => '</code>&gt;','type' => 'simple_type'},
2777       'var',        {'attribute' => 'var'},
2778       'verb',       {'args' => ['code'], 'attribute' => 'tt'},
2779       'titlefont',  {'function' => \&t2h_default_titlefont, 
2780             'type' => 'simple_type'},
2781       'w',          {'type' => 'simple_type'},
2782      );
2783
2784 %command_type = ();
2785
2786 foreach my $style (keys(%style_map))
2787 {
2788    if (exists($style_map{$style}->{'type'}))
2789    {
2790        $command_type{$style} = $style_map{$style}->{'type'};
2791    }
2792    else
2793    {
2794        $command_type{$style} = 'style';
2795    }
2796 }
2797
2798 %unicode_diacritical = (
2799        'H'          => '030B', 
2800        'ringaccent' => '030A', 
2801        "'"          => '0301',
2802        'v'          => '030C', 
2803        ','          => '0327', 
2804        '^'          => '0302', 
2805        'dotaccent'  => '0307',
2806        '`'          => '0300',
2807        '='          => '0304', 
2808        '~'          => '0303',
2809        '"'          => '0308', 
2810        'udotaccent' => '0323', 
2811        'ubaraccent' => '0332', 
2812        'u'          => '0306',
2813        'tieaccent'  => '0361'
2814 );
2815
2816 %unicode_accents = (
2817     'dotaccent' => { # dot above
2818         'A' => '0226', #C moz-1.2 
2819         'a' => '0227', #c moz-1.2
2820         'B' => '1E02',
2821         'b' => '1E03',
2822         'C' => '010A',
2823         'c' => '010B',
2824         'D' => '1E0A',
2825         'd' => '1E0B',
2826         'E' => '0116',
2827         'e' => '0117',
2828         'F' => '1E1E',
2829         'f' => '1E1F',
2830         'G' => '0120',
2831         'g' => '0121',
2832         'H' => '1E22',
2833         'h' => '1E23',
2834         'i' => '0069',
2835         'I' => '0130',
2836         'N' => '1E44',
2837         'n' => '1E45',
2838         'O' => '022E', #Y moz-1.2
2839         'o' => '022F', #v moz-1.2
2840         'P' => '1E56',
2841         'p' => '1E57',
2842         'R' => '1E58',
2843         'r' => '1E59',
2844         'S' => '1E60',
2845         's' => '1E61',
2846         'T' => '1E6A',
2847         't' => '1E6B',
2848         'W' => '1E86',
2849         'w' => '1E87',
2850         'X' => '1E8A',
2851         'x' => '1E8B',
2852         'Y' => '1E8E',
2853         'y' => '1E8F',
2854         'Z' => '017B',
2855         'z' => '017C',
2856     },
2857     'udotaccent' => { # dot below
2858         'A' => '1EA0',
2859         'a' => '1EA1',
2860         'B' => '1E04',
2861         'b' => '1E05',
2862         'D' => '1E0C',
2863         'd' => '1E0D',
2864         'E' => '1EB8',
2865         'e' => '1EB9',
2866         'H' => '1E24',
2867         'h' => '1E25',
2868         'I' => '1ECA',
2869         'i' => '1ECB',
2870         'K' => '1E32',
2871         'k' => '1E33',
2872         'L' => '1E36',
2873         'l' => '1E37',
2874         'M' => '1E42',
2875         'm' => '1E43',
2876         'N' => '1E46',
2877         'n' => '1E47',
2878         'O' => '1ECC',
2879         'o' => '1ECD',
2880         'R' => '1E5A',
2881         'r' => '1E5B',
2882         'S' => '1E62',
2883         's' => '1E63',
2884         'T' => '1E6C',
2885         't' => '1E6D',
2886         'U' => '1EE4',
2887         'u' => '1EE5',
2888         'V' => '1E7E',
2889         'v' => '1E7F',
2890         'W' => '1E88',
2891         'w' => '1E89',
2892         'Y' => '1EF4',
2893         'y' => '1EF5',
2894         'Z' => '1E92',
2895         'z' => '1E93',
2896     },
2897     'ubaraccent' => { # line below
2898         'B' => '1E06',
2899         'b' => '1E07',
2900         'D' => '1E0E',
2901         'd' => '1E0F',
2902         'h' => '1E96',
2903         'K' => '1E34',
2904         'k' => '1E35',
2905         'L' => '1E3A',
2906         'l' => '1E3B',
2907         'N' => '1E48',
2908         'n' => '1E49',
2909         'R' => '1E5E',
2910         'r' => '1E5F',
2911         'T' => '1E6E',
2912         't' => '1E6F',
2913         'Z' => '1E94',
2914         'z' => '1E95',
2915     },
2916     ',' => { # cedilla
2917         'C' => '00C7',
2918         'c' => '00E7',
2919         'D' => '1E10',
2920         'd' => '1E11',
2921         'E' => '0228', #C moz-1.2
2922         'e' => '0229', #c moz-1.2
2923         'G' => '0122',
2924         'g' => '0123',
2925         'H' => '1E28',
2926         'h' => '1E29',
2927         'K' => '0136',
2928         'k' => '0137',
2929         'L' => '013B',
2930         'l' => '013C',
2931         'N' => '0145',
2932         'n' => '0146',
2933         'R' => '0156',
2934         'r' => '0157',
2935         'S' => '015E',
2936         's' => '015F',
2937         'T' => '0162',
2938         't' => '0163',
2939     },
2940     '=' => { # macron
2941         'A' => '0100',
2942         'a' => '0101',
2943         'E' => '0112',
2944         'e' => '0113',
2945         'I' => '012A',
2946         'i' => '012B',
2947         'G' => '1E20',
2948         'g' => '1E21',
2949         'O' => '014C',
2950         'o' => '014D',
2951         'U' => '016A',
2952         'u' => '016B',
2953         'Y' => '0232', #? moz-1.2
2954         'y' => '0233', #? moz-1.2
2955     },
2956     '"' => { # diaeresis
2957         'A' => '00C4',
2958         'a' => '00E4',
2959         'E' => '00CB',
2960         'e' => '00EB',
2961         'H' => '1E26',
2962         'h' => '1E27',
2963         'I' => '00CF',
2964         'i' => '00EF',
2965         'O' => '00D6',
2966         'o' => '00F6',
2967         't' => '1E97',
2968         'U' => '00DC',
2969         'u' => '00FC',
2970         'W' => '1E84',
2971         'w' => '1E85',
2972         'X' => '1E8C',
2973         'x' => '1E8D',
2974         'y' => '00FF',
2975         'Y' => '0178',
2976     },
2977     'u' => { # breve
2978         'A' => '0102',
2979         'a' => '0103',
2980         'E' => '0114',
2981         'e' => '0115',
2982         'G' => '011E',
2983         'g' => '011F',
2984         'I' => '012C',
2985         'i' => '012D',
2986         'O' => '014E',
2987         'o' => '014F',
2988         'U' => '016C',
2989         'u' => '016D',
2990     },
2991     "'" => { # acute
2992         'A' => '00C1',
2993         'a' => '00E1',
2994         'C' => '0106',
2995         'c' => '0107',
2996         'E' => '00C9',
2997         'e' => '00E9',
2998         'G' => '01F4',
2999         'g' => '01F5',
3000         'I' => '00CD',
3001         'i' => '00ED',
3002         'K' => '1E30',
3003         'k' => '1E31',
3004         'L' => '0139',
3005         'l' => '013A',
3006         'M' => '1E3E',
3007         'm' => '1E3F',
3008         'N' => '0143',
3009         'n' => '0144',
3010         'O' => '00D3',
3011         'o' => '00F3',
3012         'P' => '1E54',
3013         'p' => '1E55',
3014         'R' => '0154',
3015         'r' => '0155',
3016         'S' => '015A',
3017         's' => '015B',
3018         'U' => '00DA',
3019         'u' => '00FA',
3020         'W' => '1E82',
3021         'w' => '1E83',
3022         'Y' => '00DD',
3023         'y' => '00FD',
3024         'Z' => '0179',
3025         'z' => '018A',
3026     },
3027     '~' => { # tilde
3028         'A' => '00C3',
3029         'a' => '00E3',
3030         'E' => '1EBC',
3031         'e' => '1EBD',
3032         'I' => '0128',
3033         'i' => '0129',
3034         'N' => '00D1',
3035         'n' => '00F1',
3036         'O' => '00D5',
3037         'o' => '00F5',
3038         'U' => '0168',
3039         'u' => '0169',
3040         'V' => '1E7C',
3041         'v' => '1E7D',
3042         'Y' => '1EF8',
3043         'y' => '1EF9',
3044     },
3045     '`' => { # grave
3046         'A' => '00C0',
3047         'a' => '00E0',
3048         'E' => '00C8',
3049         'e' => '00E8',
3050         'I' => '00CC',
3051         'i' => '00EC',
3052         'N' => '01F8',
3053         'n' => '01F9',
3054         'O' => '00D2',
3055         'o' => '00F2',
3056         'U' => '00D9',
3057         'u' => '00F9',
3058         'W' => '1E80',
3059         'w' => '1E81',
3060         'Y' => '1EF2',
3061         'y' => '1EF3',
3062     },
3063     '^' => { # circumflex
3064         'A' => '00C2',
3065         'a' => '00E2',
3066         'C' => '0108',
3067         'c' => '0109',
3068         'E' => '00CA',
3069         'e' => '00EA',
3070         'G' => '011C',
3071         'g' => '011D',
3072         'H' => '0124',
3073         'h' => '0125',
3074         'I' => '00CE',
3075         'i' => '00EE',
3076         'J' => '0134',
3077         'j' => '0135',
3078         'O' => '00D4',
3079         'o' => '00F4',
3080         'S' => '015C',
3081         's' => '015D',
3082         'U' => '00DB',
3083         'u' => '00FB',
3084         'W' => '0174',
3085         'w' => '0175',
3086         'Y' => '0176',
3087         'y' => '0177',
3088         'Z' => '1E90',
3089         'z' => '1E91',
3090     },
3091     'ringaccent' => { # ring
3092         'A' => '00C5',
3093         'a' => '00E5',
3094         'U' => '016E',
3095         'u' => '016F',
3096         'w' => '1E98',
3097         'y' => '1E99',
3098     },
3099     'v' => { # caron
3100         'A' => '01CD',
3101         'a' => '01CE',
3102         'C' => '010C',
3103         'c' => '010D',
3104         'D' => '010E',
3105         'd' => '010F',
3106         'E' => '011A',
3107         'e' => '011B',
3108         'G' => '01E6',
3109         'g' => '01E7',
3110         'H' => '021E', #K with moz-1.2
3111         'h' => '021F', #k with moz-1.2
3112         'I' => '01CF',
3113         'i' => '01D0',
3114         'K' => '01E8',
3115         'k' => '01E9',
3116         'L' => '013D', #L' with moz-1.2
3117         'l' => '013E', #l' with moz-1.2
3118         'N' => '0147',
3119         'n' => '0148',
3120         'O' => '01D1',
3121         'o' => '01D2',
3122         'R' => '0158',
3123         'r' => '0159',
3124         'S' => '0160',
3125         's' => '0161',
3126         'T' => '0164',
3127         't' => '0165',
3128         'U' => '01D3',
3129         'u' => '01D4',
3130         'Z' => '017D',
3131         'z' => '017E',
3132     },
3133     'H' => { # double acute
3134         'O' => '0150',
3135         'o' => '0151',
3136         'U' => '0170',
3137         'u' => '0171',
3138     },
3139 );
3140
3141 %transliterate_accent_map = ();
3142 foreach my $command (keys(%unicode_accents))
3143 {
3144     foreach my $letter(keys (%{$unicode_accents{$command}}))
3145     {
3146         $transliterate_accent_map{$unicode_accents{$command}->{$letter}}
3147             = $letter 
3148           unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}}));
3149     }
3150 }
3151
3152 %special_accents = (
3153       'ringaccent' => 'aA',
3154       "'"          => 'aeiouyAEIOUY',
3155       ','          => 'cC',
3156       '^'          => 'aeiouAEIOU',
3157       '`'          => 'aeiouAEIOU',
3158       '~'          => 'nNaoAO',
3159       '"'          => 'aeiouyAEIOU',
3160 );
3161
3162 foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
3163 {
3164      $style_map{$accent_command} = { 'function' => \&t2h_default_accent };
3165      $old_style_map{$accent_command} = '&default_accent';
3166      $style_map_texi{$accent_command} = { 'function' => \&t2h_default_ascii_accent };
3167 }
3168
3169 sub default_accent($$)
3170 {
3171     my $text = shift;
3172     my $accent = shift;
3173     return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
3174     return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
3175     return $text . '&lt;' if ($accent eq 'v');
3176     return "&${text}cedil;" if (($accent eq ',') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
3177     return ascii_accents($text, $accent);
3178 }
3179
3180 sub t2h_default_accent($$)
3181 {
3182     my $accent = shift;
3183     my $args = shift;
3184
3185     my $text = $args->[0];
3186
3187     return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
3188     return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
3189     return $text . '&lt;' if ($accent eq 'v');
3190     return "&${text}cedil;" if (($accent eq ',') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
3191 # FIXME here there could be a conversion to the character in the right 
3192 # encoding, like 
3193 #    if ($USE_UNICODE and defined($OUT_ENCODING) and $OUT_ENCODING ne '' 
3194 #        and exists($unicode_accents{$accent}) and  exists($unicode_accents{$accent}->{$text}))
3195 #    {
3196 #          my $encoded_char =  Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET);
3197 #          return $encoded_char if ($encoded_char ne '');
3198 #    }
3199     if ($USE_NUMERIC_ENTITY)
3200     {
3201         if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text}))
3202         {
3203              return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';');
3204         }
3205     }
3206     return ascii_accents($text, $accent);
3207 }
3208
3209 sub ascii_accents($$)
3210 {
3211     my $text = shift;
3212     my $accent = shift;
3213     return $text if ($accent eq 'dotless');
3214     return $text . $accent if (defined($accent_map{$accent}));
3215     return $text . "''" if ($accent eq 'H');
3216     return $text . '.' if ($accent eq 'dotaccent');
3217     return $text . '*' if ($accent eq 'ringaccent');
3218     return $text . '[' if ($accent eq 'tieaccent');
3219     return $text . '(' if ($accent eq 'u');
3220     return $text . '_' if ($accent eq 'ubaraccent');
3221     return '.' . $text  if ($accent eq 'udotaccent');
3222     return $text . '<' if ($accent eq 'v');
3223     return $text . ',' if ($accent eq ','); 
3224 }
3225
3226 sub default_sc($$)
3227 {
3228     return '<small>' . uc($_[0]) . '</small>';
3229 }
3230
3231 # now unused, upcasing is done in normal_text
3232 sub t2h_default_sc($$$)
3233
3234     shift;
3235     my $args = shift;
3236     return '<small>' . uc($args->[0]) . '</small>';
3237 }
3238
3239 sub default_ctrl($$)
3240 {
3241    return "^$_[0]";
3242 }
3243
3244 sub t2h_default_ctrl($$$)
3245 {
3246     shift;
3247     my $args = shift;
3248    return "^$args->[0]";
3249 }
3250
3251 sub default_sc_pre($$)
3252 {
3253     return uc($_[0]);
3254 }
3255
3256 # now unused, upcasing is done in normal_text
3257 sub t2h_default_sc_pre($$$)
3258 {
3259     shift;
3260     my $args = shift;
3261     return uc($args->[0]);
3262 }
3263
3264 sub default_titlefont($$)
3265 {
3266     return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/);
3267     return '';
3268 }
3269
3270 # Avoid adding h1 if the text is empty
3271 sub t2h_default_titlefont($$$)
3272 {
3273     shift;
3274     my $args = shift;
3275     return "<h1 class=\"titlefont\">$args->[0]</h1>" if ($args->[0] =~ /\S/);
3276     return '';
3277 }
3278
3279 # At some point in time (before 4.7?) according to the texinfo 
3280 # manual, url shouldn't lead to a link but rather be formatted 
3281 # like text. It is now what indicateurl do, url is the same that
3282 # uref with one arg. If we did like makeinfo did it would have been
3283 #sub url($$)
3284 #{
3285 #    return '&lt;<code>' . $_[0] . '</code>&gt;';
3286 #}
3287
3288 # This is unused, t2h_default_uref is used instead
3289 sub t2h_default_url ($$)
3290 {
3291     shift;
3292     my $args = shift;
3293     my $url = shift @$args;
3294     #$url =~ s/\s*$//;
3295     #$url =~ s/^\s*//;
3296     $url = main::normalise_space($url);
3297     return '' unless ($url =~ /\S/);
3298     return &$anchor('', $url, $url);
3299 }
3300
3301 sub default_url ($$)
3302 {
3303     my $url = shift;
3304     my $command = shift;
3305     $url =~ s/\s*$//;
3306     $url =~ s/^\s*//;
3307     return '' unless ($url =~ /\S/);
3308     return &$anchor('', $url, $url);
3309 }
3310
3311 sub default_uref($$)
3312 {
3313     my $arg = shift;
3314     my $command = shift;
3315     my ($url, $text, $replacement);
3316     ($url, $text, $replacement) = split /,\s*/, $arg;
3317     $url =~ s/\s*$//;
3318     $url =~ s/^\s*//;
3319     $text = $replacement if (defined($replacement));
3320     $text = $url unless ($text);
3321     return $text if ($url eq '');
3322     return &$anchor('', $url, $text);
3323 }
3324
3325 sub t2h_default_uref($$)
3326 {
3327     shift;
3328     my $args = shift;
3329     my $url = shift @$args;
3330     my $text = shift @$args;
3331     my $replacement = shift @$args;
3332     #$url =~ s/\s*$//;
3333     #$url =~ s/^\s*//;
3334     $url = main::normalise_space($url);
3335     $replacement = '' if (!defined($replacement));
3336     $replacement = main::normalise_space($replacement);
3337     $text = '' if (!defined($text));
3338     $text = main::normalise_space($text);
3339     $text = $replacement if ($replacement ne '');
3340     $text = $url unless ($text ne '');
3341     return $text if ($url eq '');
3342     return &$anchor('', $url, $text);
3343 }
3344
3345 sub default_email($$)
3346 {
3347     my $arg = shift;
3348     my $command = shift;
3349     my ($mail, $text);
3350     ($mail, $text) = split /,\s*/, $arg;
3351     $mail =~ s/\s*$//;
3352     $mail =~ s/^\s*//;
3353     $text = $mail unless ($text);
3354     return $text if ($mail eq '');
3355     return &$anchor('', "mailto:$mail", $text);
3356 }
3357
3358 sub t2h_default_email($$)
3359 {
3360     my $command = shift;
3361     my $args = shift;
3362     my $mail = shift @$args;
3363     my $text = shift @$args;
3364     $mail = main::normalise_space($mail);
3365     #$mail =~ s/\s*$//;
3366     #$mail =~ s/^\s*//;
3367     $text = $mail unless (defined($text) and ($text ne ''));
3368     $text = main::normalise_space($text);
3369     return $text if ($mail eq '');
3370     return &$anchor('', "mailto:$mail", $text);
3371 }
3372
3373 sub t2h_default_ascii_accent($$$$)
3374 {
3375     my $accent = shift;
3376     my $args = shift;
3377
3378     my $text = $args->[0];
3379     return ascii_accents($text, $accent);
3380 }
3381
3382 sub t2h_default_no_texi_email
3383 {
3384     my $command = shift;
3385     my $args = shift;
3386     my $mail = shift @$args;
3387     my $text = shift @$args;
3388     $mail = main::normalise_space($mail);
3389     #$mail =~ s/\s*$//;
3390     #$mail =~ s/^\s*//;
3391     return $text if (defined($text) and ($text ne ''));
3392     return $mail;
3393 }
3394
3395 sub t2h_default_no_texi_image($$$$)
3396 {
3397     my $command = shift;
3398     my $args = shift;
3399     my $text = $args->[0];
3400     $text = main::normalise_space($text); 
3401     my @args = split (/\s*,\s*/, $text);
3402     return $args[0];
3403 }
3404
3405 sub t2h_default_no_texi_acronym_like($$)
3406 {
3407     my $command = shift;
3408     my $args = shift;
3409     my $acronym_texi = $args->[0];
3410     return (main::remove_texi($acronym_texi)); 
3411 }
3412
3413 sub t2h_remove_command($$$$)
3414 {
3415     return '';
3416 }
3417
3418 # This is used for style in preformatted sections
3419 my %old_style_map_pre = %old_style_map;
3420 $old_style_map_pre{'sc'} = '&default_sc_pre';
3421 $old_style_map_pre{'titlefont'} = '';
3422
3423 foreach my $command (keys(%style_map))
3424 {
3425     $style_map_pre{$command} = {};
3426     $style_map_texi{$command} = {} if (!exists($style_map_texi{$command}));
3427     $style_map_texi{$command}->{'args'} = $style_map{$command}->{'args'}
3428         if (exists($style_map{$command}->{'args'}));
3429  #print STDERR "COMMAND $command";
3430     
3431     foreach my $key (keys(%{$style_map{$command}}))
3432     {
3433         $style_map_pre{$command}->{$key} = $style_map{$command}->{$key};
3434     }
3435 }
3436
3437 #$style_map_pre{'sc'}->{'function'} = \&t2h_default_sc_pre;
3438 $style_map_pre{'sc'} = {};
3439 $style_map_pre{'titlefont'} = {};
3440
3441 #$style_map_texi{'sc'}->{'function'} = \&t2h_default_sc_pre;
3442 $style_map_texi{'sc'} = {};
3443 $style_map_texi{'email'}->{'function'} = \&t2h_default_no_texi_email;
3444
3445 ####### special styles. You shouldn't need to change them
3446 my %special_style = (
3447            #'xref'      => ['keep','normal','normal','keep','normal'],
3448            'xref'         => { 'args' => ['keep','keep','keep','keep','keep'],
3449                'function' => \&main::do_xref },
3450            'ref'         => { 'args' => ['keep','keep','keep','keep','keep'],
3451                'function' => \&main::do_xref },
3452            'pxref'         => { 'args' => ['keep','keep','keep','keep','keep'],
3453                'function' => \&main::do_xref },
3454            'inforef'      => { 'args' => ['keep','keep','keep'], 
3455                'function' => \&main::do_xref },
3456            'image'        => { 'args' => ['keep'], 'function' => \&main::do_image },
3457            'anchor'       => { 'args' => ['keep'], 'function' => \&main::do_anchor_label },
3458            'footnote'     => { 'args' => ['keep'], 'function' => \&main::do_footnote },
3459            'shortcaption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
3460            'caption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
3461            'acronym',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
3462            'abbr',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
3463 );
3464
3465 # @image is replaced by the first arg in strings
3466 $style_map_texi{'image'} = { 'args' => ['keep'],
3467        'function' => \&t2h_default_no_texi_image };
3468
3469 $style_map_texi{'acronym'} = { 'args' => ['keep','keep'],
3470        'function' => \&t2h_default_no_texi_acronym_like };
3471 $style_map_texi{'abbr'} = { 'args' => ['keep','keep'],
3472        'function' => \&t2h_default_no_texi_acronym_like };
3473
3474 foreach my $special (keys(%special_style))
3475 {
3476     $style_map{$special} = $special_style{$special}
3477           unless (defined($style_map{$special}));
3478     $style_map_pre{$special} = $special_style{$special}
3479           unless (defined($style_map_pre{$special}));
3480     $style_map_texi{$special} = { 'args' => ['keep'],
3481         'function' => \&t2h_remove_command }
3482           unless (defined($style_map_texi{$special}));
3483 }
3484 ####### end special styles.
3485
3486
3487 #foreach my $command (keys(%style_map))
3488 #{
3489 #    print STDERR "STYLE_MAP_TEXI $command($style_map_texi{$command}) ";
3490 #    print STDERR "ARGS $style_map_texi{$command}->{'args'} " if (defined($style_map_texi{$command}->{'args'}));
3491 #    print STDERR "FUN $style_map_texi{$command}->{'function'} " if (defined($style_map_texi{$command}->{'function'}));
3492 #    print STDERR "\n";
3493 #}
3494
3495 # uncomment to use the old interface
3496 #%style_map = %old_style_map;
3497 #%style_map_pre = %old_style_map_pre;
3498
3499 %simple_format_simple_map_texi = %simple_map_pre;
3500 %simple_format_texi_map = %pre_map;
3501 %simple_format_style_map_texi = ();
3502
3503 foreach my $command (keys(%style_map_texi))
3504 {
3505     #$simple_format_style_map_texi{$command} = {};
3506     foreach my $key (keys (%{$style_map_texi{$command}}))
3507     {
3508     #print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n";
3509         $simple_format_style_map_texi{$command}->{$key} = 
3510              $style_map_texi{$command}->{$key};
3511     }
3512     $simple_format_style_map_texi{$command} = {} if (!defined($simple_format_style_map_texi{$command}));
3513 }
3514
3515 foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
3516 {
3517 #    $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal'];
3518     $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent;
3519 }
3520
3521 %format_map = (
3522 #       'quotation'   =>  'blockquote',
3523        # lists
3524 #       'itemize'     =>  'ul',
3525        'enumerate'   =>  'ol',
3526        'multitable'  =>  'table',
3527        'table'       =>  'dl compact="compact"',
3528        'vtable'      =>  'dl compact="compact"',
3529        'ftable'      =>  'dl compact="compact"',
3530        'group'       =>  '',
3531        );
3532
3533 %special_list_commands = (
3534        'table'        =>  {},
3535        'vtable'       =>  {},
3536        'ftable'       =>  {},
3537        'itemize'      =>  { 'bullet'  => '' }
3538        );
3539 #
3540 # texinfo format to align attribute of paragraphs
3541 #
3542
3543 %paragraph_style = (
3544       'center'     => 'center',
3545       'flushleft'  => 'left',
3546       'flushright' => 'right',
3547       );
3548       
3549 # an eval of these $complex_format_map->{what}->{'begin'} yields beginning
3550 # an eval of these $complex_format_map->{what}->{'end'} yields end
3551 # $EXAMPLE_INDENT_CELL and SMALL_EXAMPLE_INDENT_CELL can be usefull here
3552 $complex_format_map =
3553 {
3554  'example' =>
3555  {
3556   'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
3557   'end' => q{"</td></tr></table>\n"},
3558  },
3559  'smallexample' =>
3560  {
3561   'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
3562   'end' => q{"</td></tr></table>\n"},
3563  },
3564  'display' =>
3565  {
3566   'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
3567   'end' => q{"</td></tr></table>\n"},
3568  },
3569  'smalldisplay' =>
3570  {
3571   'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
3572   'end' => q{"</td></tr></table>\n"},
3573  }
3574 };
3575
3576 # format shouldn't narrow the margins
3577
3578 $complex_format_map->{'lisp'} =  $complex_format_map->{'example'};
3579 $complex_format_map->{'smalllisp'} = $complex_format_map->{'smallexample'};
3580 $complex_format_map->{'format'} = $complex_format_map->{'display'};
3581 $complex_format_map->{'smallformat'} = $complex_format_map->{'smalldisplay'};
3582
3583 %def_map = (
3584     # basic commands
3585     'deffn', [ 'f', 'category', 'name', 'arg' ],
3586     'defvr', [ 'v', 'category', 'name' ],
3587     'deftypefn', [ 'f', 'category', 'type', 'name', 'arg' ],
3588     'deftypeop', [ 'f', 'category', 'class' , 'type', 'name', 'arg' ],
3589     'deftypevr', [ 'v', 'category', 'type', 'name' ],
3590     'defcv', [ 'v', 'category', 'class' , 'name' ],
3591     'deftypecv', [ 'v', 'category', 'class' , 'type', 'name' ],
3592     'defop', [ 'f', 'category', 'class' , 'name', 'arg' ],
3593     'deftp', [ 't', 'category', 'name', 'arg' ],
3594     # shortcuts
3595     # FIXME i18n
3596     'defun', 'deffn Function',
3597     'defmac', 'deffn Macro',
3598     'defspec', 'deffn {Special Form}',
3599     'defvar', 'defvr Variable',
3600     'defopt', 'defvr {User Option}',
3601     'deftypefun', 'deftypefn {Function}',
3602     'deftypevar', 'deftypevr Variable',
3603     'defivar', 'defcv {Instance Variable}',
3604     'deftypeivar', 'deftypecv {Instance Variable}',
3605     'defmethod', 'defop Method',
3606     'deftypemethod', 'deftypeop Method',
3607          );
3608
3609 # basic x commands
3610 foreach my $key (keys(%def_map))
3611 {
3612     $def_map{$key . 'x'} = $def_map{$key};
3613 }
3614
3615 #
3616 # miscalleneous commands
3617 #
3618 # Depending on the value, the command arg or spaces following the command
3619 #     are handled differently:
3620
3621 # the value is a reference on a hash.
3622 # the hash keys are
3623 #    'arg'  if the value is 'line' then the remaining of the line is the arg
3624 #           if it is a number it is the number of args (separated by spaces)
3625 #    'skip' if the value is 'line' then the remaining of the line is skipped
3626 #           if the value is 'space' space but no newline is skipped
3627 #           if the value is 'whitespace' space is skipped
3628 #           if the value is 'linewhitespace' space is skipped if there are 
3629 #                 only spaces remaining on the line
3630 #           if the value is 'linespace' space but no newline is skipped if 
3631 #                 there are only spaces remaining on the line
3632 #    'texi' if true it is some texinfo code and @value and @macros are expanded
3633 #    'keep' if true the args and the macro are kept, otherwise the macro 
3634 #          args and skipped stuffs are removed
3635 %misc_command = (
3636         # not needed for formatting
3637         'raisesections' => {'skip' => 'line'},  # no arg
3638         'lowersections' => {'skip' => 'line'}, # no arg
3639         'contents' => {}, # no arg
3640         'shortcontents' => {}, # no arg
3641         'summarycontents'=> {}, # no arg
3642         'setcontentsaftertitlepage' => {}, # no arg
3643         'setshortcontentsaftertitlepage' => {}, # no arg
3644         'detailmenu' => {'skip' => 'whitespace'}, # no arg
3645         'end detailmenu' => {'skip' => 'space'}, # no arg
3646         'bye' => {'skip' => 'line'}, # no arg
3647         # comments
3648         'comment' => {'arg' => 'line'},
3649         'c' => {'arg' => 'line'},
3650         # in preamble
3651         'novalidate' => {}, # no arg
3652         'dircategory'=> {'skip' => 'line'}, # line. Position with regard 
3653                          # with direntry is significant
3654         'pagesizes' => {'skip' => 'line', 'arg' => 2}, # can have 2 args 
3655                                  # or one? 200mm,150mm 11.5in
3656         'finalout' => {}, # no arg
3657         'paragraphindent' => {'skip' => 'line', 'arg' => 1}, # arg none asis 
3658                              # or a number and forbids anything else on the line
3659         'firstparagraphindent' => {'skip' => 'line', 'arg' => 1}, # none insert
3660         'frenchspacing' => {'arg' => 1}, # on off
3661         'exampleindent' => {'skip' => 'line', 'arg' => 1}, # asis or a number
3662         'footnotestyle'=> {'skip' => 'line', 'arg' => 1}, # end and separate
3663                                  # and nothing else on the line
3664         'afourpaper' => {'skip' => 'line'}, # no arg
3665         'afourlatex' => {'skip' => 'line'}, # no arg
3666         'afourwide' => {'skip' => 'line'}, # no arg
3667         'headings'=> {'skip' => 'line', 'arg' => 1}, 
3668                     #off on single double singleafter doubleafter
3669                     # interacts with setchapternewpage
3670         'setchapternewpage' => {'skip' => 'line', 'arg' => 1}, # off on odd
3671         'everyheading' => {'arg' => 'line'},
3672         'everyfooting' => {'arg' => 'line'},
3673         'evenheading' => {'arg' => 'line'},
3674         'evenfooting' => {'arg' => 'line'},
3675         'oddheading' => {'arg' => 'line'},
3676         'oddfooting' => {'arg' => 'line'},
3677         'smallbook' => {'skip' => 'line'}, # no arg
3678         'setfilename' => {'arg' => 'line'},
3679         'shorttitle' => {'arg' => 'line', 'texi' => 1},
3680         'shorttitlepage' => {'arg' => 'line', 'texi' => 1},
3681         'settitle' => {'arg' => 'line', 'texi' => 1},
3682         'author' => {'arg' => 'line', 'texi' => 1},
3683         'subtitle' => {'arg' => 'line', 'texi' => 1},
3684         'title' => {'arg' => 'line', 'texi' => 1},
3685         'syncodeindex' => {'skip' => 'linespace', 'arg' => 2}, 
3686                           # args are index identifiers
3687         'synindex' => {'skip' => 'linespace', 'arg' => 2},
3688         'defindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
3689         'defcodeindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
3690         'documentlanguage' => {'skip' => 'whitespace', 'arg' => 1}, 
3691                                                        # language code arg
3692         'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code 
3693                                                         #example distinct
3694         'sp' => {'skip' => 'whitespace', 'arg' => 1}, # no arg 
3695                                     # at the end of line or a numerical arg
3696         # formatting
3697         'page' => {}, # no arg (pagebreak)
3698         'refill' => {}, # no arg (obsolete, to be ignored)
3699         'noindent' => {'skip' => 'whitespace'}, # no arg
3700         'indent' => {'skip' => 'whitespace'},
3701         'need' => {'skip' => 'line', 'arg' => 1}, # one numerical/real arg
3702         'exdent' => {'skip' => 'space'},  
3703         # not valid for info (should be in @iftex)
3704         'vskip' => {'arg' => 'line'}, # arg line in TeX
3705         'cropmarks' => {}, # no arg
3706         # miscalleneous
3707         'verbatiminclude'=> {'skip' => 'line'},
3708         'documentencoding' => {'arg' => 1}, # makeinfo ignore the whole line
3709         # ???
3710         'filbreak' => {},
3711         # obsolete @-commands
3712         'quote-arg' => {},
3713         'allow-recursion' => {},
3714      );
3715 my %misc_command_old = (
3716         # not needed for formatting
3717         'raisesections', 'line',  # no arg
3718         'lowersections', 'line', # no arg
3719         'contents', 1, # no arg
3720         'shortcontents', 1, # no arg
3721         'summarycontents', 1, # no arg
3722         'detailmenu', 'whitespace', # no arg
3723         'end detailmenu', 'space', # no arg
3724         #'end detailmenu', 1, # no arg
3725         'novalidate', 1, # no arg
3726         'bye', 'line', # no arg
3727         # comments
3728         'comment', 'line',
3729         'c', 'line',
3730         # in preamble
3731         'dircategory', 'line', # line. Position with regard with direntry is 
3732                                # significant
3733         'pagesizes', 'line arg2', # can have 2 args 
3734         'finalout', 1, # no arg
3735         'paragraphindent', 'line arg1', # in fact accepts only none asis 
3736                              # or a number and forbids anything else on the line
3737         'firstparagraphindent', 'line arg1', # in fact accepts only none insert
3738         'exampleindent', 'line arg1', # in fact accepts only asis or a number
3739         'footnotestyle', 'line arg1', # in fact accepts only end and separate
3740                                  # and nothing else on the line
3741         'afourpaper', 'line', # no arg
3742         'afourlatex', 'line', # no arg
3743         'afourwide', 'line',  # no arg
3744         'headings', 'line', # one arg, possibilities are 
3745                     #off on single double singleafter doubleafter
3746                     # interacts with setchapternewpage
3747         'setchapternewpage', 'line', # no arg
3748         'everyheading', 'line',
3749         'everyfooting', 'line',
3750         'evenheading', 'line',
3751         'evenfooting', 'line',
3752         'oddheading', 'line',
3753         'oddfooting', 'line',
3754         'smallbook', 'line', # no arg
3755         'setfilename', 'line',
3756         'shorttitle', 'linetexi',
3757         'shorttitlepage', 'linetexi',
3758         'settitle', 'linetexi',
3759         'author', 'linetexi',
3760         'subtitle', 'linetexi',
3761         'title','linetexi',
3762         'syncodeindex','linespace arg2', # args are 
3763         'synindex','linespace arg2',
3764         'defindex', 'line arg1', # one identifier arg
3765         'defcodeindex', 'line arg1', # one identifier arg
3766         'documentlanguage', 'whitespace arg1', # one language code arg
3767         'kbdinputstyle', 'whitespace arg1', # one arg within 
3768                                  #code example distnct
3769         'sp', 'whitespace arg1', # no arg at the en of line or a numerical arg
3770         # formatting
3771         'page', 1, # no arg (pagebreak)
3772         'refill', 1, # no arg (obsolete, to be ignored))
3773         'noindent', 'space', # no arg
3774         'need', 'line arg1', # one numerical/real arg
3775         'exdent', 'space',  
3776         # not valid for info (should be in @iftex)
3777         'vskip', 'line', # arg line in TeX
3778         'cropmarks', 1, # no arg
3779         # miscalleneous
3780         'verbatiminclude', 'line',
3781         'documentencoding', 'arg1',
3782         # ???
3783         'filbreak', 1,
3784      );
3785
3786 %format_in_paragraph = (
3787         'group' => 1,
3788         'html'  => 1,
3789 );
3790 # map mapping css specification to style
3791
3792 %css_map = 
3793      (
3794          'ul.toc'                 => "$TOC_LIST_STYLE",
3795          'pre.menu-comment'       => "$MENU_PRE_STYLE",
3796          'pre.menu-preformatted'  => "$MENU_PRE_STYLE",
3797          'a.summary-letter'       => 'text-decoration: none',
3798          'pre.display'            => 'font-family: serif',
3799          'pre.smalldisplay'       => 'font-family: serif; font-size: smaller',
3800          'pre.smallexample'       => 'font-size: smaller',
3801          'span.sansserif'         => 'font-family:sans-serif; font-weight:normal;',
3802          'span.roman'         => 'font-family:serif; font-weight:normal;'
3803      );
3804
3805 $css_map{'pre.format'} = $css_map{'pre.display'};
3806 $css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'}; 
3807 $css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'};
3808
3809 # The command_handler arrays are for commands formatted externally.
3810 # The function references in @command_handler_init are called
3811 # before the second pass, before the @-commands text collection.
3812 # Those in @command_handler_process are called between the second pass
3813 # and the third pass, after collection of @-commands text and before their
3814 # expansion.
3815 # Those in @command_handler_process are called after the third pass,
3816 # after the document generation.
3817 @command_handler_init = ();
3818 @command_handler_process = ();
3819 @command_handler_finish = ();
3820
3821 # the keys of %command_handler are @-command names and the value
3822 # is a hash reference with the following keys:
3823 # 'init'          function reference used to collect the @-command text
3824 # 'expand'        function reference used when expanding the @-command text
3825 %command_handler = ();
3826
3827 # formatting functions
3828
3829 $anchor            = \&t2h_default_anchor;
3830 $def_item          = \&t2h_default_def_item;
3831 $def               = \&t2h_default_def;
3832 $menu              = \&t2h_default_menu;
3833 $menu_link         = \&t2h_default_menu_link;
3834 $menu_comment      = \&t2h_default_menu_comment;
3835 $menu_description  = \&t2h_default_menu_description;
3836 $simple_menu_link  = \&t2h_default_simple_menu_link;
3837 $external_ref      = \&t2h_default_external_ref;
3838 $external_href     = \&t2h_default_external_href;
3839 $internal_ref      = \&t2h_default_internal_ref;
3840 $table_item        = \&t2h_default_table_item;
3841 $table_line        = \&t2h_default_table_line;
3842 $table_list        = \&t2h_default_table_list;
3843 $row               = \&t2h_default_row;
3844 $cell              = \&t2h_default_cell;
3845 $list_item         = \&t2h_default_list_item;
3846 $comment           = \&t2h_default_comment;
3847 $def_line          = \&t2h_default_def_line;
3848 $def_line_no_texi  = \&t2h_default_def_line_no_texi;
3849 $raw               = \&t2h_default_raw;
3850 $raw_no_texi       = \&t2h_default_raw_no_texi;
3851 $heading           = \&t2h_default_heading;
3852 $paragraph         = \&t2h_default_paragraph;
3853 $preformatted      = \&t2h_default_preformatted;
3854 $foot_line_and_ref = \&t2h_default_foot_line_and_ref;
3855 $foot_section      = \&t2h_default_foot_section;
3856 $image_files       = \&t2h_default_image_files;
3857 $image             = \&t2h_default_image;
3858 $address           = \&t2h_default_address;
3859 $index_entry_label = \&t2h_default_index_entry_label;
3860 $index_summary     = \&t2h_default_index_summary;
3861 $summary_letter    = \&t2h_default_summary_letter;
3862 $index_entry       = \&t2h_default_index_entry;
3863 $index_letter      = \&t2h_default_index_letter;
3864 $print_index       = \&t2h_default_print_index;
3865 $protect_text      = \&t2h_default_protect_text;
3866 $normal_text       = \&t2h_default_normal_text;
3867 $complex_format    = \&t2h_default_complex_format;
3868 $cartouche         = \&t2h_default_cartouche;
3869 $sp                = \&t2h_default_sp;
3870 $definition_category      = \&t2h_default_definition_category;
3871 $copying_comment          = \&t2h_default_copying_comment;
3872 $index_summary_file_entry = \&t2h_default_index_summary_file_entry;
3873 $index_summary_file_end   = \&t2h_default_index_summary_file_end;
3874 $index_summary_file_begin = \&t2h_default_index_summary_file_begin;
3875 $empty_line               = \&t2h_default_empty_line;
3876 $unknown                  = \&t2h_default_unknown;
3877 $unknown_style            = \&t2h_default_unknown_style;
3878 $caption_shortcaption     = \&t2h_caption_shortcaption;
3879 $float                     = \&t2h_default_float;
3880 $listoffloats             = \&t2h_default_listoffloats;
3881 $listoffloats_entry       = \&t2h_default_listoffloats_entry;
3882 $listoffloats_caption     = \&t2h_default_listoffloats_caption;
3883 $listoffloats_float_style = \&t2h_default_listoffloats_float_style;
3884 $listoffloats_style       = \&t2h_default_listoffloats_style;
3885 $acronym_like             = \&t2h_default_acronym_like;
3886 $quotation                = \&t2h_default_quotation;
3887 $quotation_prepend_text   = \&t2h_default_quotation_prepend_text;
3888 $paragraph_style_command  = \&t2h_default_paragraph_style_command;
3889 $heading_texi             = \&t2h_default_heading_texi;
3890 $index_element_heading_texi = \&t2h_default_index_element_heading_texi;
3891
3892 # This function is called whenever a complex format is processed
3893 #
3894 # arguments:
3895 # name of the format
3896 # text appearing inside the format
3897 #
3898 # an eval of $complex_format->{format name}->{'begin'} should lead to the
3899 # beginning of the complex format, an eval of 
3900 # $complex_format->{format name}->{'end'}  should lead to the end of the 
3901 # complex format.
3902 sub t2h_default_complex_format($$)
3903 {
3904     my $name = shift;
3905     my $text = shift;
3906     return '' if ($text eq '');
3907     my $beginning = eval "$complex_format_map->{$name}->{'begin'}";
3908     if ($@ ne '')
3909     {
3910         print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'begin'}: $@";
3911         $beginning = '';
3912
3913     }
3914     my $end = eval "$complex_format_map->{$name}->{'end'}";
3915     if ($@ ne '')
3916     {
3917         print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'end'}: $@";
3918         $end = '';
3919
3920     }
3921     return $beginning . $text . $end;   
3922 }
3923
3924 sub t2h_default_empty_line($$)
3925 {
3926     my $text = shift;
3927     my $state = shift;
3928     #ignore the line if it just follows a deff
3929     return '' if ($state->{'deff_line'});
3930     return $text;
3931 }
3932
3933 sub t2h_default_unknown($$$$)
3934 {
3935     my $macro = shift;
3936     my $line = shift;
3937     my $stack = shift;
3938     my $state = shift;
3939     
3940     my ($result_line, $result, $result_text, $message);
3941     return ($line, 0, undef, undef);
3942 }
3943
3944 sub t2h_default_unknown_style($$$$)
3945 {
3946     my $command = shift;
3947     my $text = shift;
3948     my $state = shift;
3949     
3950     my ($result, $result_text, $message);
3951     return (0, undef, undef);
3952 }
3953
3954 sub t2h_caption_shortcaption($)
3955 {
3956     my $float = shift;
3957     my $caption_lines;
3958     my $shortcaption_lines;
3959     my $style = $float->{'style_texi'};
3960     if (defined($float->{'nr'}))
3961     {
3962         my $nr = $float->{'nr'};
3963         if ($style ne '')
3964         {
3965             $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
3966         }
3967         else 
3968         {
3969             $style = $nr;
3970         }
3971     }
3972     
3973     if (defined($float->{'caption_texi'}))
3974     {
3975         @$caption_lines = @{$float->{'caption_texi'}};
3976         if (defined($style))
3977         {
3978             $caption_lines->[0] = '@strong{' . &$I('%{style}: %{caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] });
3979         }
3980         else
3981         {
3982             $caption_lines->[0] = '@strong{' .  $caption_lines->[0];
3983         }
3984         push @$caption_lines, "}\n";
3985     }
3986     elsif (defined($style))
3987     {
3988         $caption_lines->[0] = '@strong{' . $style . '}' . "\n";
3989     }
3990     if (defined($float->{'shortcaption_texi'}))
3991     {
3992          @$shortcaption_lines = @{$float->{'shortcaption_texi'}};
3993          if (defined($style))
3994          {
3995               $shortcaption_lines->[0] = '@strong{' . &$I('%{style}: %{shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] });
3996          }
3997          else
3998          {
3999               $shortcaption_lines->[0] = '@strong{' .  $shortcaption_lines->[0];
4000          }
4001          push @$shortcaption_lines, "}\n";
4002     }
4003     elsif (defined($style))
4004     {
4005          $shortcaption_lines->[0] = '@strong{' . $style . '}' . "\n";
4006     }
4007     return ($caption_lines, $shortcaption_lines);
4008 }
4009
4010 sub t2h_default_float($$$$$)
4011 {
4012     my $text = shift;
4013     my $float = shift;
4014     my $caption = shift;
4015     my $shortcaption = shift;
4016     
4017     my $label = '';
4018     if (exists($float->{'id'}))
4019     {
4020         $label = &$anchor($float->{'id'});
4021     }
4022     my $caption_text = '';
4023     
4024     if (defined($float->{'caption_texi'}))
4025     {
4026         $caption_text = $caption;
4027     }
4028     elsif (defined($float->{'shortcaption_texi'}))
4029     {
4030         $caption_text = $shortcaption;
4031     }
4032     elsif (defined($caption))
4033     {
4034         $caption_text = $caption;
4035     }
4036     
4037     return '<div class="float">' . "$label\n" . $text . '</div>' . $caption_text;
4038 }
4039
4040 sub t2h_default_listoffloats_style($)
4041 {
4042     my $style_texi = shift;
4043     return ($style_texi);
4044 }
4045
4046 sub t2h_default_listoffloats_float_style($$)
4047 {
4048     my $style_texi = shift;
4049     my $float = shift;
4050     
4051     my $style = $float->{'style_texi'};
4052     if (defined($float->{'nr'}))
4053     {
4054          my $nr = $float->{'nr'};
4055          if ($style ne '')
4056          {
4057               $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
4058          }
4059          else 
4060          {
4061               $style = $nr;
4062          }
4063     }
4064     return $style;
4065 }
4066
4067 sub t2h_default_listoffloats_caption($)
4068 {
4069     my $float = shift;
4070     if (defined($float->{'shortcaption_texi'}))
4071     {
4072          return [ @{$float->{'shortcaption_texi'}} ];
4073     }
4074     elsif (defined($float->{'caption_texi'}))
4075     {
4076          return [ @{$float->{'caption_texi'}} ];
4077     }
4078     return [ ];
4079 }
4080
4081 sub t2h_default_listoffloats_entry($$$$)
4082 {
4083     my $style_texi = shift;
4084     my $float = shift;
4085     my $float_style = shift;
4086     my $caption = shift;
4087     my $href = shift;
4088
4089     return '<dt>' . &$anchor('', $href, $float_style) . '</dt><dd>' . $caption
4090 . '</dd>' . "\n";
4091 }
4092
4093 sub t2h_default_listoffloats($$$)
4094 {
4095     my $style_texi = shift;
4096     my $style = shift;
4097     my $float_entries = shift;
4098
4099     my $result = "<dl class=\"listoffloats\">\n" ;
4100     foreach my $float_entry (@$float_entries)
4101     {
4102          $result .= $float_entry;
4103     }
4104     return $result . "</dl>\n";
4105
4106
4107 # This function is used to protect characters which are special in html 
4108 # in inline text:  &, ", <, and >. 
4109 #
4110 # argument:
4111 # text to be protected
4112 sub t2h_default_protect_text($)
4113 {
4114    my $text = shift;
4115    $text =~ s/&/&amp;/g;
4116    $text =~ s/</&lt;/g;
4117    $text =~ s/>/&gt;/g;
4118    $text =~ s/\"/&quot;/g;
4119    return $text;
4120 }
4121
4122
4123 sub in_small_caps($)
4124 {
4125    my $style_stack = shift;
4126    my $in_sc = 0;
4127    if ($style_stack and scalar(@{$style_stack}))
4128    {
4129        my $level = $#$style_stack;
4130        #print STDERR ":::$level ::@{$style_stack}\n";
4131        while ($level >= 0)
4132        {
4133            if ($style_stack->[$level] eq 'sc')
4134            {
4135                $in_sc = 1;
4136                last;
4137            }
4138            $level--;
4139        }
4140    } 
4141    return $in_sc;
4142 }
4143 #
4144 #
4145 sub t2h_default_normal_text($$$$$)
4146 {
4147    my $text = shift;
4148    my $in_raw_text = shift;
4149    my $in_preformatted = shift;
4150    my $in_code = shift;
4151    my $style_stack = shift;
4152    $text = uc($text) if (in_small_caps($style_stack));
4153    $text = &$protect_text($text) unless($in_raw_text);
4154    if (! $in_code and !$in_preformatted)
4155    { 
4156        if ($USE_ISO and !$in_raw_text)
4157        {
4158            $text =~ s/---/\&mdash\;/g;
4159            $text =~ s/--/\&ndash\;/g;
4160            $text =~ s/``/\&ldquo\;/g;
4161            $text =~ s/''/\&rdquo\;/g;
4162        }
4163        else
4164        {   
4165             if ($in_raw_text) #FIXME really do that ?
4166             {
4167                  $text =~ s/``/"/g;
4168                  $text =~ s/''/"/g;
4169             }
4170             else
4171             {
4172                 $text =~ s/``/&quot;/g;
4173                 $text =~ s/''/&quot;/g;
4174             }
4175             # temporary reuse '' to store --- !....
4176             # FIXME won't '---' be handled wrongly?
4177             # FIXME really do that in raw text?
4178             $text =~ s/---/''/g; 
4179             $text =~ s/--/-/g; 
4180             $text =~ s/''/--/g;
4181        }
4182    }
4183    return $text;
4184 }
4185
4186 # This function produces an anchor 
4187 #
4188 # arguments:
4189 # $name           :   anchor name
4190 # $href           :   anchor href
4191 # text            :   text displayed
4192 # extra_attribs   :   added to anchor attributes list
4193 sub t2h_default_anchor($;$$$)
4194 {
4195     my $name = shift;
4196     my $href = shift;
4197     my $text = shift;
4198     my $attributes = shift;
4199 #print STDERR "!$name!$href!$text!$attributes!\n";
4200     if (!defined($attributes) or ($attributes !~ /\S/))
4201     {
4202         $attributes = '';
4203     }
4204     else 
4205     {
4206         $attributes = ' ' . $attributes;
4207     }
4208     $name = '' if (!defined($name) or ($name !~ /\S/));
4209     $href = '' if (!defined($href) or ($href !~ /\S/));
4210     $text = '' if (!defined($text));
4211     return $text if (($name eq '') and ($href eq ''));
4212     $name = "name=\"$name\"" if ($name ne '');
4213     $href = "href=\"$href\"" if ($href ne '');
4214     $href = ' ' . $href if (($name ne '') and ($href ne ''));
4215 #print STDERR "!!!$name!$href!$text!$attributes!\n";
4216     return "<a ${name}${href}${attributes}>$text</a>";
4217 }
4218
4219 # This function is used to format the text associated with a @deff/@end deff
4220 #
4221 # argument:
4222 # text
4223 #
4224 # $DEF_TABLE should be used to distinguish between @def formatted as table
4225 # and as definition lists.
4226 sub t2h_default_def_item($)
4227 {
4228     my $text = shift;
4229     if ($text =~ /\S/)
4230     {
4231         if (! $DEF_TABLE)
4232         {
4233             return '<dd>' . $text . '</dd>';
4234         }
4235         else
4236         {
4237             return '<tr><td colspan="2">' . $text . '</td></tr>';
4238         }
4239     }
4240     return '';
4241 }
4242
4243 sub t2h_default_definition_category($$$)
4244 {
4245     my $name = shift;
4246     my $class = shift;
4247     my $style = shift;
4248     return ($name) if (!defined($class) or $class =~ /^\s*$/);
4249     if ($style eq 'f')
4250     {
4251         return &$I('%{name} on %{class}', { 'name' => $name, 'class' => $class });
4252     }
4253     elsif ($style eq 'v')
4254     {
4255         return &$I('%{name} of %{class}', { 'name' => $name, 'class' => $class });
4256     }
4257     else
4258     {
4259         return $name;
4260     }
4261 }
4262
4263 # format the container for the @deffn line and text
4264
4265 # argument
4266 # text of the whole @def, line and associated text.
4267 #
4268 # $DEF_TABLE should be used.
4269 sub t2h_default_def($)
4270 {
4271     my $text = shift;
4272     if ($text =~ /\S/)
4273     {
4274         if (! $DEF_TABLE)
4275         {
4276             return "<dl>\n" . $text . "</dl>\n";
4277         }
4278         else
4279         {
4280             return "<table width=\"100%\">\n" . $text . "</table>\n";
4281         }
4282     }
4283     return '';
4284
4285 }
4286
4287 # a whole menu
4288 #
4289 # argument:
4290 # the whole menu text (entries and menu comments)
4291 #
4292 # argument:
4293 # whole menu text.
4294 sub t2h_default_menu($)
4295 {
4296     my $text = shift;
4297     if ($text =~ /\S/)
4298     {
4299         return "<table class=\"menu\" border=\"0\" cellspacing=\"0\">\n" 
4300         . $text . "</table>\n";
4301     }
4302 }
4303
4304 # a simple menu entry ref in case we aren't in a standard menu context
4305 sub t2h_default_simple_menu_link($$$$$$)
4306 {
4307     my $entry = shift;
4308     my $preformatted = shift;
4309     my $href = shift;
4310     my $node = shift;
4311     my $name = shift;
4312     my $ending = shift;
4313     $ending = '' if (!defined($ending));
4314     if (($entry eq '') or $NODE_NAME_IN_MENU or $preformatted)
4315     {
4316         $name .= ':' if ($name ne '');
4317         $entry = "$MENU_SYMBOL$name$node";
4318     }
4319     $entry = &$anchor('', $href, $entry) if ($href);
4320     $entry .= $ending if ($preformatted);
4321     $entry .= '&nbsp;' unless $preformatted;
4322     return $entry;
4323 }
4324
4325 # formats a menu entry link pointing to a node or section 
4326 #
4327 # arguments:
4328 # the entry text
4329 # the state, a hash reference holding informations about the context, with a 
4330 #     usefull entry, 'preformatted', true if we are in a preformatted format
4331 #     (a format keeping space between words). In that case a function
4332 #     of the main program, main::do_preformatted($text, $state) might 
4333 #     be used to format the text with the current format style.
4334 # href is optionnal. It is the reference to the section or the node anchor
4335 #     which should be used to make the link (typically it is the argument 
4336 #     of a href= attribute in a <a> element).
4337 sub t2h_default_menu_link($$$$$$)
4338 {
4339     my $entry = shift;
4340     my $state = shift;
4341     my $href = shift;
4342     my $node = shift;
4343     my $name = shift;
4344     my $ending = shift;
4345 #print STDERR  "MENU_LINK\n";
4346     if (($entry eq '') or $NODE_NAME_IN_MENU or $state->{'preformatted'})
4347     {
4348         $name .= ':' if ($name ne '');
4349         $entry = "$MENU_SYMBOL$name$node";
4350     }
4351     $entry = &$anchor ('', $href, $entry) if (defined($href));
4352     return $entry if ($SIMPLE_MENU); 
4353     if ($state->{'preformatted'})
4354     {
4355         return '<tr><td>' . main::do_preformatted($entry . $ending, $state);
4356     }
4357     return "<tr><td align=\"left\" valign=\"top\">$entry</td><td>&nbsp;&nbsp;</td>";
4358 }
4359
4360 sub simplify_text($)
4361 {
4362     my $text = shift;
4363     $text =~ s/[^\w]//og;
4364     return $text;
4365 }
4366
4367 # formats a menu entry description, ie the text appearing after the node
4368 # specification in a menu entry an spanning until there is another
4369 # menu entry, an empty line or some text at the very beginning of the line
4370 # (we consider that text at the beginning of the line begins a menu comment) 
4371 #
4372 # arguments:
4373 # the description text
4374 # the state. See menu_entry.
4375 # the heading of the element associated with the node.
4376 sub t2h_default_menu_description($$$)
4377 {
4378     my $text = shift;
4379     my $state = shift;
4380     my $element_text = shift;
4381     return $text if ($SIMPLE_MENU); 
4382 #print STDERR  "MENU_DESCRIPTION element_text!$element_text, text!$text\n";
4383     if ($state->{'preformatted'})
4384     {
4385         return main::do_preformatted($text, $state) . '</td></tr>';
4386     }
4387     elsif ($AVOID_MENU_REDUNDANCY)
4388     {
4389         $text = '' if (simplify_text($element_text) eq simplify_text($text));
4390     }
4391     return "<td align=\"left\" valign=\"top\">$text</td></tr>\n";
4392 }
4393
4394 # a menu comment (between menu lines)
4395 # formats the container of a menu comment. A menu comment is any text 
4396 # appearing between menu lines, either separated by an empty line from
4397 # the preceding menu entry, or a text beginning at the first character
4398 # of the line (text not at the very beginning of the line is considered to
4399 # be the continuation of a menu entry description text).
4400 #
4401 # The text itself is considered to be in a preformatted environment
4402 # with name 'menu-commment' and with style $MENU_PRE_STYLE.
4403 #
4404 # argument
4405 # text contained in the menu comment.
4406 sub t2h_default_menu_comment($)
4407 {
4408    my $text = shift;
4409    return $text if ($SIMPLE_MENU); 
4410    if ($text =~ /\S/)
4411    {
4412        return "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">$text</th></tr>";
4413    }
4414    return '';
4415 }
4416
4417 # Construct a href to an external source of information.
4418 # node is the node with texinfo @-commands
4419 # node_id is the node transliterated and transformed as explained in the
4420 #         texinfo manual
4421 # node_xhtml_id is the node transformed such that it is unique and can 
4422 #     be used to make an html cross ref as explained in the texinfo manual
4423 # file is the file in '(file)node'
4424 sub t2h_default_external_href($$$)
4425 {
4426     my $node = shift;
4427     my $node_id = shift;
4428     my $node_xhtml_id = shift;
4429     my $file = shift;
4430     $file = '' if (!defined($file));
4431     my $default_target_split = $EXTERNAL_CROSSREF_SPLIT;
4432     my $target_split;
4433     my $target_mono;
4434     my $href_split;
4435     my $href_mono;
4436     if ($file ne '')
4437     {
4438          if ($NEW_CROSSREF_STYLE)
4439          {
4440              $file =~ s/\.[^\.]*$//;
4441              $file =~ s/^.*\///;
4442              my $href;
4443              if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}))
4444              {
4445                   if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}))
4446                   {
4447                        $target_split = 1;
4448                        $href_split =  $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}->{'href'};
4449                   }
4450                   if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}))
4451                   {
4452                        $target_mono = 1;
4453                        $href_mono =  $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}->{'href'};
4454                   }
4455              }
4456
4457              if ((not $target_mono) and (not $target_split))
4458              { # nothing specified for that manual, use default
4459                   $target_split = $default_target_split;
4460              }
4461              elsif ($target_split and $target_mono)
4462              { # depends on the splitting of the manual
4463                   $target_split = $SPLIT;
4464              }
4465              elsif ($target_mono)
4466              { # only mono specified
4467                   $target_split = 0;
4468              }
4469
4470              if ($target_split)
4471              {
4472                   if (defined($href_split))
4473                   {
4474                        $file = "$href_split";
4475                   }
4476                   elsif (defined($EXTERNAL_DIR))
4477                   {
4478                        $file = "$EXTERNAL_DIR/$file";
4479                   }
4480                   elsif ($SPLIT)
4481                   {
4482                        $file = "../$file";
4483                   }
4484                   $file .= "/";
4485              }
4486              else
4487              {# target not split
4488                   if (defined($href_mono))
4489                   {
4490                        $file = "$href_mono";
4491                   }
4492                   else
4493                   {
4494                        if (defined($EXTERNAL_DIR))
4495                        {
4496                             $file = "$EXTERNAL_DIR/$file";
4497                        }
4498                        elsif ($SPLIT)
4499                        {
4500                            $file = "../$file";
4501                        }
4502                        $file .= "." . $NODE_FILE_EXTENSION;
4503                   }
4504              }
4505          }
4506          else
4507          {
4508              $file .= "/";
4509              if (defined($EXTERNAL_DIR))
4510              {
4511                  $file = $EXTERNAL_DIR . $file;
4512              }
4513              else
4514              {
4515                  $file = '../' . $file;
4516              } 
4517          }
4518     }
4519     else
4520     {
4521         $target_split = $default_target_split;
4522     }
4523     if ($node eq '')
4524     {
4525          if ($NEW_CROSSREF_STYLE)
4526          {
4527              if ($target_split)
4528              {
4529                  return $file . $TOP_NODE_FILE . '.' . $NODE_FILE_EXTENSION . '#Top';
4530                  # or ?
4531                  #return $file . '#Top';
4532              }
4533              else
4534              {
4535                   return $file . '#Top';
4536              }
4537          }
4538          else
4539          {
4540              return $file;
4541          }
4542     }
4543     my $target;
4544     if ($NEW_CROSSREF_STYLE)
4545     {
4546          $node = $node_id;
4547          $target = $node_xhtml_id;
4548     }
4549     else
4550     {
4551          $node = main::remove_texi($node);
4552          $node =~ s/[^\w\.\-]/-/g;
4553     }
4554     my $file_basename = $node;
4555     $file_basename = $TOP_NODE_FILE if ($node =~ /^top$/i);
4556     if ($NEW_CROSSREF_STYLE)
4557     {
4558         if ($target_split)
4559         {
4560             return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target;
4561         }
4562         else
4563         {
4564             return $file . '#' . $target;
4565         }
4566     }
4567     else
4568     {
4569         return $file . $file_basename . ".$NODE_FILE_EXTENSION";
4570     }
4571 }
4572
4573 # format a reference external to the generated manual. This produces a full 
4574 # reference with introductive words and the reference itself.
4575 #
4576 # arguments:
4577 # type of the reference: xref (reference at the beginning of a sentence),
4578 #     pxref (reference in a parenthesis),  
4579 # section in the book. This might be undef.
4580 # book name.
4581 # node and file name formatted according to the convention used in info
4582 #     '(file)node' and no node means the Top node.
4583 # href linking to the html page containing the referenced node. A typical
4584 #     use for this href is a href attribute in an <a> element
4585 # an optionnal cross reference name
4586 sub t2h_default_external_ref($$$$$$)
4587 {
4588     my $type = shift;
4589     my $section = shift;
4590     my $book = shift;
4591     my $file_node = shift;
4592     my $href = shift;
4593     my $cross_ref = shift;
4594
4595     $file_node = "$cross_ref: $file_node" if (($file_node ne '') and ($cross_ref ne ''));
4596     $file_node = &$anchor('', $href, $file_node) if ($file_node ne '');
4597
4598     # Yes, this is ugly, but this helps internationalization
4599     if ($type eq 'pxref')
4600     {
4601          if (($book ne '') and ($file_node ne ''))
4602          {
4603               return &$I('see %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne '');
4604               return &$I('see %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book });
4605          }
4606          elsif ($book ne '')
4607          {
4608               return &$I('see section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4609               return &$I('see @cite{%{book}}', { 'book' => $book });
4610          }
4611          elsif ($file_node ne '')
4612          {
4613               return &$I('see %{node_file_href}', { 'node_file_href' => $file_node });
4614          }
4615     }
4616     if ($type eq 'xref')
4617     {
4618          if (($book ne '') and ($file_node ne ''))
4619          {
4620               return &$I('See %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne '');
4621               return &$I('See %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book });
4622          }
4623          elsif ($book ne '')
4624          {
4625               return &$I('See section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4626               return &$I('See @cite{%{book}}', { 'book' => $book });
4627          }
4628          elsif ($file_node ne '')
4629          {
4630               return &$I('See %{node_file_href}', { 'node_file_href' => $file_node });
4631          }
4632     }
4633     if ($type eq 'ref')
4634     {
4635          if (($book ne '') and ($file_node ne ''))
4636          {
4637               return &$I('%{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne '');
4638               return &$I('%{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book });
4639          }
4640          elsif ($book ne '')
4641          {
4642               return &$I('section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4643               return &$I('@cite{%{book}}', { 'book' => $book });
4644          }
4645          elsif ($file_node ne '')
4646          {
4647               return &$I('%{node_file_href}', { 'node_file_href' => $file_node });
4648          }
4649     }
4650     return '';
4651 }
4652
4653 # format a reference to a node or a section in the generated manual. This 
4654 # produces a full reference with introductive words and the reference itself.
4655 #
4656 # arguments:
4657 # type of the reference: xref (reference at the beginning of a sentence),
4658 #     pxref (reference in a parenthesis),  
4659 # href linking to the html page containing the node or the section. A typical
4660 #     use for this href is a href attribute in an <a> element
4661 # short name for this reference
4662 # name for this reference
4663 # boolean true if the reference is a reference to a section
4664
4665 # $SHORT_REF should be used.
4666 sub t2h_default_internal_ref($$$$$)
4667 {
4668     my $type = shift;
4669     my $href = shift;
4670     my $short_name = shift;
4671     my $name = shift;
4672     my $is_section = shift;
4673
4674     if (! $SHORT_REF)
4675     {
4676         $name = &$anchor('', $href, $name);
4677         if ($type eq 'pxref')
4678         {
4679             return &$I('see section %{reference_name}', { 'reference_name' => $name }) if ($is_section);
4680             return &$I('see %{reference_name}', { 'reference_name' => $name });
4681         }
4682         elsif ($type eq 'xref')
4683         {
4684             return &$I('See section %{reference_name}', { 'reference_name' => $name }) if ($is_section);
4685             return &$I('See %{reference_name}', { 'reference_name' => $name });
4686         }
4687         elsif ($type eq 'ref')
4688         {
4689             return &$I('%{reference_name}', { 'reference_name' => $name });
4690         }
4691     }
4692     else
4693     {
4694         $name = &$anchor('', $href, $short_name);
4695         if ($type eq 'pxref')
4696         {
4697             return &$I('see %{reference_name}', { 'reference_name' => $name });
4698         }
4699         elsif ($type eq 'xref')
4700         {
4701             return &$I('See %{reference_name}', { 'reference_name' => $name });
4702         }
4703         elsif ($type eq 'ref')
4704         {
4705             return &$I('%{reference_name}', { 'reference_name' => $name });
4706         }
4707     }
4708     return '';
4709 }
4710
4711 sub teletyped_in_stack($)
4712 {
4713     my $stack = shift;
4714     foreach my $element(reverse(@$stack))
4715     {
4716         if ($complex_format_map->{$element})
4717         {
4718             if (!$complex_format_map->{$element}->{'pre_style'})
4719             {
4720                 return 1;
4721             }
4722             else
4723             {
4724                 return 0;
4725             }
4726         }
4727     }
4728     return 0;
4729 }
4730
4731 # text after @item in table, vtable and ftable
4732 sub t2h_default_table_item($$$$$$)
4733 {
4734     my $text = shift;
4735     my $index_label = shift;
4736     my $format = shift;
4737     my $command = shift;
4738     my $formatted_command = shift;
4739     my $style_stack = shift;
4740     #print STDERR "-> $format (@$style_stack)\n";
4741     $formatted_command = '' if (!defined($formatted_command) or 
4742           exists($special_list_commands{$format}->{$command}));
4743     if (teletyped_in_stack($style_stack))
4744     {
4745        $text .= '</tt>';
4746        $formatted_command = '<tt>' . $formatted_command;
4747     }
4748     $text .= "\n" . $index_label  if (defined($index_label));
4749     return '<dt>' . $formatted_command . $text . '</dt>' . "\n";
4750 }
4751
4752 # format text on the line following the @item line (in table, vtable and ftable)
4753 sub t2h_default_table_line($)
4754 {
4755     my $text = shift;
4756
4757     if ($text =~ /\S/)
4758     {
4759          return '<dd>' . $text . '</dd>' . "\n";
4760     }
4761     return '';
4762 }
4763
4764 # row in multitable
4765 sub t2h_default_row($$)
4766 {
4767     my $text = shift;
4768     my $macro = shift;
4769
4770     if ($text =~ /\S/)
4771     {
4772          if ($macro eq 'headitem')
4773          {
4774               return '<thead><tr>' . $text . '</tr></thead>' . "\n";
4775          }
4776          return '<tr>' . $text . '</tr>' . "\n";
4777     }
4778     return '';
4779 }
4780
4781 # cell in multitable
4782 sub t2h_default_cell($$)
4783 {
4784     my $text = shift;
4785     my $row_macro = shift;
4786
4787     if ($row_macro eq 'headitem')
4788     {
4789         return '<th>' . $text . '</th>';
4790     }
4791     return '<td>' . $text . '</td>';
4792 }
4793
4794 # format an item in a list
4795 #
4796 # argument:
4797 # text of the item
4798 # format of the list (itemize or enumerate)
4799 # command passed as argument to the format
4800 # formatted_command leading command formatted, if it is a thing command
4801 sub t2h_default_list_item($$$$$$$)
4802 {
4803     my $text = shift;
4804     my $format = shift;
4805     my $command = shift;
4806     my $formatted_command = shift;
4807     my $item_nr = shift;
4808     my $enumerate_style = shift;
4809     my $number = shift;
4810
4811     $formatted_command = '' if (!defined($formatted_command) or 
4812           exists($special_list_commands{$format}->{$command}));
4813     if ($text =~ /\S/)
4814     {
4815         return '<li>' . $formatted_command . $text . '</li>';
4816     }
4817     return '';
4818 }
4819
4820 sub t2h_default_table_list($$$$$$)
4821 {
4822     my $format = shift;
4823     my $text = shift;
4824     my $command = shift;
4825     my $formatted_command = shift;
4826     my $item_nr = shift;
4827     my $enumerate_style = shift;
4828     my $number = shift;
4829     $formatted_command = '' if (!defined($formatted_command) or 
4830           exists($special_list_commands{$format}->{$command}));
4831     if ($format eq 'itemize')
4832     {
4833         return "<ul>\n" . $text . "</ul>\n" if ($command eq 'bullet');
4834         return "<ul$TOC_LIST_ATTRIBUTE>\n" . $text . "</ul>\n";
4835     }
4836 }
4837
4838 # an html comment
4839 sub t2h_default_comment($)
4840 {
4841     my $text = shift;
4842     $text =~ s/--+/-/go;
4843     return '<!-- ' . $text . ' -->' . "\n";
4844 }
4845
4846 sub t2h_collect_styles($)
4847 {
4848     my $stack = shift;
4849     my @result = ();
4850     foreach my $style (reverse(@$stack))
4851     {
4852 #        last unless (defined($command_type{$style}) and $command_type{$style} eq 'style');
4853         push @result, $style if (defined($command_type{$style}) and $command_type{$style} eq 'style');
4854     }
4855     return @result;
4856 }
4857
4858 sub t2h_get_attribute($;$)
4859 {
4860     my $command = shift;
4861     my $map_ref = shift;
4862     $map_ref = \%style_map if (!defined($map_ref));
4863     return '' unless (defined($map_ref->{$command}));
4864     if ((ref($map_ref->{$command}) eq 'HASH') 
4865        and exists($map_ref->{$command}->{'attribute'}))
4866     {
4867         return $map_ref->{$command}->{'attribute'};
4868     }
4869     elsif ($map_ref->{$command} !~ /^&/)
4870     {
4871         my $attribute = $map_ref->{$command};
4872         $attribute =~ s/^\"//;
4873         return $attribute;
4874     }
4875     return '';
4876 }
4877
4878 sub t2h_begin_style($$;$)
4879 {
4880     my $command = shift;
4881     my $text = shift;
4882     my $map_ref = shift;
4883     my $attribute = t2h_get_attribute($command,$map_ref);
4884     $attribute = "<$attribute>" if ($attribute ne '');
4885     return $attribute.$text;
4886 }
4887
4888 sub t2h_end_style($$;$)
4889 {
4890     my $command = shift;
4891     my $text = shift;
4892     my $map_ref = shift;
4893     my $attribute = t2h_get_attribute($command,$map_ref);
4894     if ($attribute =~ /^(\w+)/)
4895     {
4896         $attribute = $1;
4897     }
4898     $attribute = "</$attribute>" if ($attribute ne '');
4899     return $text.$attribute;
4900 }
4901
4902 # a paragraph
4903 # arguments:
4904 # $text of the paragraph
4905 # $align for the alignement
4906 # $indent for the indent style (indent or noindent)
4907 # The following is usefull if the paragraph is in an itemize.
4908 # $paragraph_command is the leading formatting command (like @minus)
4909 # $paragraph_command_formatted is the leading formatting command formatted
4910 # $paragraph_number is a reference on the number of paragraphs appearing
4911 #    in the format. The value should be increased if a paragraph is done
4912 # $format is the format name (@itemize)
4913 sub t2h_default_paragraph($$$$$$$$$$$$)
4914 {
4915     my $text = shift;
4916     my $align = shift;
4917     my $indent = shift;
4918     my $paragraph_command = shift;
4919     my $paragraph_command_formatted = shift;
4920     my $paragraph_number = shift;
4921     my $format = shift;
4922     my $item_nr = shift;
4923     my $enumerate_style = shift;
4924     my $number = shift;
4925     my $command_stack_at_end = shift;
4926     my $command_stack_at_begin = shift;
4927 #print STDERR "format: $format\n" if (defined($format));
4928 #print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n";
4929     $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or 
4930           exists($special_list_commands{$format}->{$paragraph_command}));
4931     return '' if ($text =~ /^\s*$/);
4932     foreach my $style(t2h_collect_styles($command_stack_at_begin))
4933     {
4934        $text = t2h_begin_style($style, $text);
4935     }
4936     foreach my $style(t2h_collect_styles($command_stack_at_end))
4937     {
4938        $text = t2h_end_style($style, $text);
4939     }
4940     if (defined($paragraph_number) and defined($$paragraph_number))
4941     {
4942          $$paragraph_number++;
4943          return $text  if (($format eq 'itemize' or $format eq 'enumerate') and
4944             ($$paragraph_number == 1));
4945     }
4946     my $open = '<p>';
4947     if ($align)
4948     {
4949         $open = "<p align=\"$paragraph_style{$align}\">";
4950     }
4951     return $open.$text.'</p>';
4952 }
4953
4954 # a preformatted region
4955 # arguments:
4956 # $text of the preformatted region
4957 # $pre_style css style
4958 # $class identifier for the preformatted region (example, menu-comment)
4959 # The following is usefull if the preformatted is in an itemize.
4960 # $leading_command is the leading formatting command (like @minus)
4961 # $leading_command_formatted is the leading formatting command formatted
4962 # $preformatted_number is a reference on the number of preformatteds appearing
4963 #    in the format. The value should be increased if a preformatted is done
4964 sub t2h_default_preformatted($$$$$$$$$$$$)
4965 {
4966     my $text = shift;
4967     my $pre_style = shift;
4968     my $class = shift;
4969     my $leading_command = shift;
4970     my $leading_command_formatted = shift;
4971     my $preformatted_number = shift;
4972     my $format = shift;
4973     my $item_nr = shift;
4974     my $enumerate_style = shift;
4975     my $number = shift;
4976     my $command_stack_at_end = shift;
4977     my $command_stack_at_begin = shift;
4978
4979 #print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n";
4980     return '' if ($text eq '');
4981     $leading_command_formatted = '' if (!defined($leading_command_formatted) or 
4982           exists($special_list_commands{$format}->{$leading_command}));
4983     if (defined($preformatted_number) and defined($$preformatted_number))
4984     {
4985         $$preformatted_number++;
4986     }
4987     foreach my $style(t2h_collect_styles($command_stack_at_begin))
4988     {
4989        $text = t2h_begin_style($style, $text, \%style_map_pre);
4990     }
4991     foreach my $style(t2h_collect_styles($command_stack_at_end))
4992     {
4993        $text = t2h_end_style($style, $text, \%style_map_pre);
4994     }
4995     return "<pre class=\"$class\">".$text."</pre>";
4996 }
4997
4998 # This function formats a heading for an element
4999 #
5000 # argument:
5001 # an element. It is a hash reference for a node or a sectionning command.
5002 # The interesting keys are:
5003 # 'text': the heading text
5004 # 'text_nonumber': the heading text without section number
5005 # 'node': true if it is a node
5006 # 'level': level of the element. 0 for @top, 1 for chapter, heading, 
5007 #      appendix..., 2 for section and so on...
5008 # 'tag_level': the sectionning element name, raisesections and lowersections
5009 #      taken into account
5010 sub t2h_default_heading($)
5011 {
5012     my $element = shift;
5013     my $level = 3;
5014     if (!$element->{'node'})
5015     {
5016         $level = $element->{'level'};
5017     }
5018     $level = 1 if ($level == 0);
5019     my $text = $element->{'text'};
5020     return '' if ($text !~ /\S/);
5021     my $class = $element->{'tag_level'};
5022     $class = 'unnumbered' if ($class eq 'top');
5023     if (defined($element->{'tocid'}) and $TOC_LINKS)
5024     {
5025          $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text);
5026     }
5027     my $align = '';
5028     $align = ' align="center"' if ($element->{'tag'} eq 'centerchap');
5029     return "<h$level class=\"$class\"$align> $text </h$level>\n";
5030 }
5031
5032 # formatting of raw regions
5033 # if L2H is true another mechanism is used for tex
5034 sub t2h_default_raw($$)
5035 {
5036     my $style = shift;
5037     my $text = shift;
5038     if ($style eq 'verbatim' or $style eq 'tex')
5039     {
5040         return "<pre class=\"$style\">" . &$protect_text($text) . '</pre>';
5041     }
5042     elsif ($style eq 'html')
5043     {
5044         return $text;
5045     }
5046     else
5047     {
5048         warn "$WARN (bug) unknown style $style\n";
5049         return &$protect_text($text);
5050     }
5051 }
5052
5053 # raw environment when removing texi (in comments) 
5054 sub t2h_default_raw_no_texi($$)
5055 {
5056     my $style = shift;
5057     my $text = shift;
5058     return $text;
5059 }
5060
5061 # This function formats a footnote reference and the footnote text associated
5062 # with a given footnote.
5063 # The footnote reference is the text appearing in the main document pointing
5064 # to the footnote text.
5065 #
5066 # arguments:
5067 # absolute number of the footnote (in the document)
5068 # relative number of the footnote (in the page)
5069 # identifier for the footnote
5070 # identifier for the footnote reference in the main document
5071 # main document file
5072 # footnote text file
5073 # array with the footnote text lines 
5074 # the state. See menu entry.
5075 #
5076 # returns:
5077 # reference on an array containing the footnote text lines which should
5078 #     have been updated
5079 # the text for the reference pointing on the footnote text
5080 sub t2h_default_foot_line_and_ref($$$$$$$)
5081 {
5082     my $number_in_doc = shift;
5083     my $number_in_page = shift;
5084     my $footnote_id = shift;
5085     my $place_id = shift;
5086     my $document_file = shift;
5087     my $footnote_file = shift;
5088     my $lines = shift;
5089     my $state = shift;
5090     
5091     unshift (@$lines, '<h3>' . 
5092           &$anchor($footnote_id, $document_file . "#$place_id",
5093                    "($number_in_doc)")
5094           . "</h3>\n");
5095     return ($lines, &$anchor($place_id,  $footnote_file . "#$footnote_id", 
5096            "($number_in_doc)"));
5097 }
5098
5099 # formats a group of footnotes.
5100 #
5101 # argument:
5102 # array reference on the footnotes texts lines 
5103 #
5104 # returns an array reference on the group of footnotes lines
5105 sub t2h_default_foot_section($)
5106 {
5107     my $lines = shift;
5108     unshift (@$lines, "<div class=\"footnote\">\n" ,"$DEFAULT_RULE\n", "<h3>" . &$I('Footnotes') . "</h3>\n");
5109     push (@$lines, "</div>\n"); 
5110     return $lines; 
5111 }
5112
5113 sub t2h_default_image_files($$)
5114 {
5115     my $base = shift;
5116     my $extension = shift;
5117     my @files = ();
5118     return @files if (!defined($base) or ($base eq ''));
5119     push @files,"$base.$extension" if (defined($extension) and ($extension ne ''));
5120     foreach my $ext (@IMAGE_EXTENSIONS)
5121     {
5122         push @files, "$base.$ext";
5123     }
5124     return @files;
5125 }
5126
5127 # format an image
5128 #
5129 # arguments:
5130 # image file name with path
5131 # image basename
5132 # a boolean true if we are in a preformatted format
5133 # image file name without path
5134 # alt text
5135 # width
5136 # height
5137 # raw alt
5138 # extension
5139 # path to working dir
5140 # path to file relative from working dir
5141 sub t2h_default_image($$$$$$$$$$$)
5142 {
5143     my $file = shift;
5144     my $base = shift;
5145     my $preformatted = shift;
5146     my $file_name = shift;
5147     my $alt = shift;
5148     my $width = shift;
5149     my $height = shift;
5150     my $raw_alt = shift;
5151     my $extension = shift;
5152     my $working_dir = shift;
5153     my $file_path = shift;
5154  
5155     if (!defined($file_path) or $file_path eq '')
5156     {
5157         if (defined($extension) and $extension ne '')
5158         {
5159             $file = "$base.$extension";
5160         }
5161         else
5162         {
5163             $file = "$base.jpg";
5164         }
5165         main::echo_warn ("no image file for $base, (using $file)");
5166     } 
5167     $alt = &$protect_text($base) if (!defined($alt) or ($alt eq ''));
5168     return "[ $alt ]" if ($preformatted);
5169     # it is possible that $file_name is more correct as it allows the user
5170     # to chose the relative path.
5171     $file = &$protect_text($file);
5172     return "<img src=\"$file\" alt=\"$alt\">";
5173 }
5174
5175 # address put in footer describing when was generated and who did the manual
5176 sub t2h_default_address($$)
5177 {
5178     my $user = shift;
5179     my $date = shift;
5180     $user = '' if (!defined($user));
5181     $date = '' if (!defined($date));
5182     if (($user ne '') and ($date ne ''))
5183     {
5184         return &$I('by @emph{%{user}} on @emph{%{date}}', { 'user' => $user,
5185             'date' => $date });
5186     }
5187     elsif ($user ne '')
5188     {
5189         return &$I('by @emph{%{user}}', { 'user' => $user });
5190     }
5191     elsif ($date ne '')
5192     {
5193         return &$I('on @emph{%{date}}', { 'date' => $date });
5194     }
5195     return '';
5196 }
5197
5198 # format a target in the main document for an index entry.
5199 #
5200 # arguments:
5201 # target identifier
5202 # boolean true if in preformatted format
5203 # FIXME document the remaining 
5204 sub t2h_default_index_entry_label($$)
5205 {
5206     my $identifier = shift;
5207     my $preformatted = shift;
5208     
5209     return '' if (!defined($identifier) or ($identifier !~ /\S/));
5210     my $label = &$anchor($identifier);
5211     return $label . "\n" if (!$preformatted);
5212     return $label;
5213 }
5214
5215 # process definition commands line @deffn for example
5216 sub t2h_default_def_line($$$$$)
5217 {
5218    my $category = shift;
5219    my $name = shift;
5220    my $type = shift;
5221    my $arguments = shift;
5222    my $index_label = shift;
5223    $index_label = '' if (!defined($index_label));
5224    $category = '' if (!defined($category) or ($category =~ /^\s*$/));
5225    $name = '' if (!defined($name) or ($name =~ /^\s*$/));
5226    $type = '' if (!defined($type) or $type =~ /^\s*$/);
5227    if (!defined($arguments) or $arguments =~ /^\s*$/)
5228    {
5229        $arguments = '';
5230    }
5231    else
5232    {
5233        chomp ($arguments);
5234        $arguments = '<i>' . $arguments . '</i>';
5235    }
5236    my $type_name = '';
5237    $type_name = " $type" if ($type ne '');
5238    $type_name .= ' <b>' . $name . '</b>' if ($name ne '');
5239    $type_name .= $arguments . "\n";
5240    if (! $DEF_TABLE)
5241    {
5242        return '<dt>'. '<u>' . $category . ':</u>' . $type_name . $index_label . "</dt>\n";
5243    }
5244    else
5245    {
5246        
5247        return "<tr>\n<td align=\"left\">" . $type_name . 
5248        "</td>\n<td align=\"right\">" . $category . $index_label . "</td>\n" . "</tr>\n";
5249    }
5250 }
5251
5252 # process definition commands line @deffn for example while removing texi
5253 # commands
5254 sub t2h_default_def_line_no_texi($$$$$)
5255 {
5256    my $category = shift;
5257    my $name = shift;
5258    my $type = shift;
5259    my $arguments = shift;
5260    $name = '' if (!defined($name) or ($name =~ /^\s*$/));
5261    $type = '' if (!defined($type) or $type =~ /^\s*$/);
5262    if (!defined($arguments) or $arguments =~ /^\s*$/)
5263    {
5264        $arguments = '';
5265    }
5266    my $type_name = '';
5267    $type_name = " $type" if ($type ne '');
5268    $type_name .= ' ' . $name if ($name ne '');
5269    $type_name .= $arguments;
5270    if (! $DEF_TABLE)
5271    {
5272        return $category . ':' . $type_name . "\n";
5273    }
5274    else
5275    {
5276        
5277        return $type_name . "    " . $category . "\n";
5278    }
5279 }
5280
5281 # a cartouche
5282 sub t2h_default_cartouche($$)
5283 {
5284     my $text = shift;
5285
5286     if ($text =~ /\S/)
5287     {
5288         return "<table class=\"cartouche\" border=\"1\"><tr><td>\n" . $text . "</td></tr></table>\n";
5289     }
5290     return '';
5291
5292
5293 # key:          
5294 # origin_href:  
5295 # entry:        
5296 # texi entry: 
5297 # element_href: 
5298 # element_text: 
5299 sub t2h_default_index_summary_file_entry ($$$$$$$$)
5300 {
5301     my $index_name = shift;
5302     my $key = shift;
5303     my $origin_href = shift;
5304     my $entry = shift;
5305     my $texi_entry = shift;
5306     my $element_href = shift;
5307     my $element_text = shift;
5308     my $is_printed = shift;
5309     print IDXFILE "key: $key\n  origin_href: $origin_href\n  entry: $entry\n"
5310       . "  texi_entry: $texi_entry\n"
5311       . "  element_href: $element_href\n  element_text: $element_text\n";
5312 }
5313
5314 sub t2h_default_index_summary_file_begin($$)
5315 {
5316     my $name = shift;
5317     my $is_printed = shift;
5318     open(IDXFILE, ">$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx")
5319        || die "Can't open >$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx for writing: $!\n";
5320 }
5321
5322 sub t2h_default_index_summary_file_end($$)
5323 {
5324     my $name = shift;
5325     my $is_printed = shift;
5326     close (IDXFILE);
5327 }
5328
5329 sub t2h_default_sp($$)
5330 {
5331    my $number = shift;
5332    my $preformatted = shift;
5333    return "<br>\n" x $number if (!$preformatted);
5334    return "\n" x $number;
5335 }
5336
5337 sub t2h_default_acronym_like($$$$$$)
5338 {
5339     my $command = shift;
5340     my $acronym_texi = shift;
5341     my $acronym_text = shift;
5342     my $with_explanation = shift;
5343     my $explanation_lines = shift;
5344     my $explanation_text = shift;
5345     my $explanation_simply_formatted = shift;
5346     
5347     my $attribute = $command;
5348     my $opening = "<$attribute>";
5349     if (defined($explanation_simply_formatted)) 
5350     {
5351         $opening = "<$attribute title=\"$explanation_simply_formatted\">";
5352     }
5353     if ($with_explanation)
5354     {
5355         return &$I('%{acronym_like} (%{explanation})', {'acronym_like' => $opening . $acronym_text . "</$attribute>", 'explanation' => $explanation_text})
5356     }
5357     else
5358     {
5359         return  $opening . $acronym_text . "</$attribute>";
5360     }
5361 }
5362
5363 sub t2h_default_quotation_prepend_text($)
5364 {
5365     my $text = shift;
5366     return undef if (!defined($text) or $text =~ /^$/);
5367 # FIXME if there is a @ protecting the end of line the result is
5368 # @b{some text @:}
5369 # It is likely not to be what was intended
5370     chomp($text);
5371     return &$I('@b{%{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1});
5372 }
5373
5374 sub t2h_default_quotation($$$)
5375 {
5376     my $text = shift;
5377     my $argument_text = shift;
5378     my $argument_text_texi = shift;
5379 #    my $argument_style_texi = shift;
5380 #    my $argument_style_id = shift;
5381 #    if (defined($argument_text))
5382 #    {
5383 #         return '<blockquote>' . &$I('%{style}:%{quotation}',
5384 #          {'style' => $argument_text, 'quotation' => $text}) . '</blockquote>' ;
5385 #    }
5386     return '<blockquote>' . $text . "</blockquote>\n";
5387 }
5388
5389 # format the text within a paragraph style format,
5390 #
5391 # argument:
5392 # format name
5393 # text within the format
5394 sub t2h_default_paragraph_style_command($$)
5395 {
5396     my $format = shift;
5397     my $text = shift;
5398     return $text;
5399 }
5400
5401 # format a whole index
5402 #
5403 # argument:
5404 # index text
5405 # index name
5406 sub t2h_default_print_index($$)
5407 {
5408     my $text = shift;
5409     my $name = shift;
5410     return "<table border=\"0\" class=\"index-$name\">\n" .
5411     "<tr><td></td><th align=\"left\">" . &$I('Index Entry') . "</th><th align=\"left\"> " . &$I('Section') . "</th></tr>\n"
5412     . "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n" . $text .
5413     "</table>\n";
5414 }
5415
5416 # format a letter entry in an index page. The letter entry contains
5417 # the index entries for the words beginning with that letter. It is 
5418 # a target for links pointing from the summary of the index.
5419 #
5420 # arguments:
5421 # the letter
5422 # identifier for the letter entry. This should be used to make the target
5423 #     identifier
5424 # text of the index entries
5425 sub t2h_default_index_letter($$$)
5426 {
5427      my $letter = shift;
5428      my $id = shift;
5429      my $text = shift;
5430      return '<tr><th>' . &$anchor($id,'',&$protect_text($letter)) . 
5431      "</th><td></td><td></td></tr>\n" . $text . 
5432      "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n";
5433 }
5434
5435 # format an index entry (in a letter entry).
5436 #
5437 # arguments:
5438 # href to the main text, linking to the place where the index entry appears
5439 # entry text
5440 # href to the main text, linking to the section or node where the index 
5441 #      entry appears
5442 # section or node heading
5443 sub t2h_default_index_entry($$$$)
5444 {
5445     my $text_href = shift;
5446     my $entry = shift;
5447     my $element_href = shift;
5448     my $element_text = shift;
5449     
5450     return '<tr><td></td><td valign="top">' . &$anchor('', $text_href, $entry)
5451     . '</td><td valign="top">' .  &$anchor('', $element_href, $element_text)
5452     . "</td></tr>\n";
5453 }
5454
5455
5456 sub t2h_default_copying_comment($)
5457 {
5458     my $copying_lines = shift;
5459     my $text = &$comment(main::remove_texi(@$copying_lines));
5460     return $text;
5461 }
5462 # format a letter appearing in a summary for an index. The letter links to
5463 # the place where the index elements beginning with this letter are (called
5464 # a letter entry).
5465 #
5466 # arguments:
5467 # letter
5468 # file where the target letter entry is 
5469 # identifier for the target letter entry
5470 sub t2h_default_summary_letter($$$)
5471 {
5472    my $letter = shift;
5473    my $file = shift;
5474    my $identifier = shift;
5475    return &$anchor('', $file . '#' . $identifier, '<b>' . &$protect_text($letter) . '</b>', 'class="summary-letter"');
5476 }
5477
5478 # format an index summary. This is a list of letters linking to the letter
5479 # entries.
5480 #
5481 # arguments:
5482 # array reference containing the formatted alphabetical letters
5483 # array reference containing the formatted non lphabetical letters
5484 sub t2h_default_index_summary($$)
5485 {
5486     my $alpha = shift;
5487     my $nonalpha = shift;
5488     my $join = '';
5489     my $nonalpha_text = '';
5490     my $alpha_text = '';
5491     $join = " &nbsp; \n<br>\n" if (@$nonalpha and @$alpha);
5492     if (@$nonalpha)
5493     {
5494        $nonalpha_text = join("\n &nbsp; \n", @$nonalpha) . "\n";
5495     }
5496     if (@$alpha)
5497     {
5498        $alpha_text = join("\n &nbsp; \n", @$alpha) . "\n &nbsp; \n";
5499     }
5500     return "<table><tr><th valign=\"top\">" . &$I('Jump to') .": &nbsp; </th><td>" .
5501     $nonalpha_text . $join . $alpha_text . "</td></tr></table>\n";
5502 }
5503
5504 # return the heading with number texinfo text
5505 # also called for nodes.
5506 sub t2h_default_heading_texi($$$)
5507 {
5508     my $tag = shift;
5509     my $texi = shift;
5510     my $number = shift;
5511     $texi =~ s/\s*$//;
5512     $texi =~ s/^\s*//;
5513     return "$number $texi" if ($NUMBER_SECTIONS and defined($number) and ($number !~ /^\s*$/)) ;
5514     return $texi;
5515 }
5516
5517 # return the heading texinfo text for split index sections
5518 sub t2h_default_index_element_heading_texi($$$)
5519 { # FIXME i18n
5520     my $heading_texi = shift;
5521     my $tag = shift;
5522     my $texi = shift;
5523     my $number = shift;
5524     my $first_letter = shift;
5525     my $last_letter = shift;
5526     return "$heading_texi: $first_letter -- $last_letter" if ($last_letter ne $first_letter);
5527     return "$heading_texi: $first_letter";
5528 }
5529
5530 1;
5531
5532 require "$ENV{T2H_HOME}/texi2html.init" 
5533     if ($0 =~ /\.pl$/ &&
5534         -e "$ENV{T2H_HOME}/texi2html.init" && -r "$ENV{T2H_HOME}/texi2html.init");
5535
5536 my $translation_file = 'translations.pl'; # file containing all the translations
5537 my $T2H_OBSOLETE_STRINGS;
5538
5539 # leave this within comments, and keep the require statement
5540 # This way, you can directly run texi2html.pl, 
5541 # if $ENV{T2H_HOME}/translations.pl exists.
5542 #
5543 # @T2H_TRANSLATIONS_FILE@
5544 $LANGUAGES->{'de'} = {
5545                        '  The buttons in the navigation panels have the following meaning:' => '',
5546                        '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
5547                        ' Up ' => '',
5548                        '%{acronym_like} (%{explanation})' => '',
5549                        '%{month}, %{day} %{year}' => '',
5550                        '%{name} of %{class}' => '',
5551                        '%{name} on %{class}' => '',
5552                        '%{node_file_href}' => '',
5553                        '%{node_file_href} @cite{%{book}}' => '',
5554                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5555                        '%{reference_name}' => '',
5556                        '%{style} %{number}' => '',
5557                        '%{style}: %{caption_first_line}' => '',
5558                        '%{style}: %{shortcaption_first_line}' => '',
5559                        '@b{%{quotation_arg}:} ' => '',
5560                        '@cite{%{book}}' => '',
5561                        'About' => '',
5562                        'About (help)' => '',
5563                        'About This Document' => '@"Uber dieses Dokument',
5564                        'April' => 'April',
5565                        'August' => 'August',
5566                        'Back' => '',
5567                        'Beginning of this chapter or previous chapter' => '',
5568                        'Button' => '',
5569                        'Contents' => '',
5570                        'Cover (top) of document' => '',
5571                        'Current Position' => '',
5572                        'Current section' => '',
5573                        'December' => 'Dezember',
5574                        'FastBack' => '',
5575                        'FastForward' => '',
5576                        'February' => 'Februar',
5577                        'First' => '',
5578                        'First section in reading order' => '',
5579                        'Following' => '',
5580                        'Following node' => '',
5581                        'Footnotes' => 'Fu@ss{}noten',
5582                        'Forward' => '',
5583                        'From 1.2.3 go to' => '',
5584                        'Go to' => '',
5585                        'Index' => 'Index',
5586                        'Index Entry' => '',
5587                        'January' => 'Januar',
5588                        'July' => 'Juli',
5589                        'Jump to' => '',
5590                        'June' => 'Juni',
5591                        'Last' => '',
5592                        'Last section in reading order' => '',
5593                        'March' => 'M@"arz',
5594                        'May' => 'Mai',
5595                        'Menu:' => '',
5596                        'Name' => '',
5597                        'Next' => '',
5598                        'Next chapter' => '',
5599                        'Next node' => '',
5600                        'Next section in reading order' => '',
5601                        'Next section on same level' => '',
5602                        'Node following in node reading order' => '',
5603                        'Node up' => '',
5604                        'NodeNext' => '',
5605                        'NodePrev' => '',
5606                        'NodeUp' => '',
5607                        'November' => 'November',
5608                        'October' => 'Oktober',
5609                        'Overview' => '',
5610                        'Overview:' => '',
5611                        'Prev' => '',
5612                        'Previous node' => '',
5613                        'Previous section in reading order' => '',
5614                        'Previous section on same level' => '',
5615                        'Section' => '',
5616                        'Section One' => '',
5617                        'See %{node_file_href}' => '',
5618                        'See %{node_file_href} @cite{%{book}}' => '',
5619                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5620                        'See %{reference_name}' => '',
5621                        'See @cite{%{book}}' => '',
5622                        'See section %{reference_name}' => '',
5623                        'See section `%{section}\' in @cite{%{book}}' => '',
5624                        'September' => 'September',
5625                        'Short Table of Contents' => 'Kurzes Inhaltsverzeichniss',
5626                        'Short table of contents' => '',
5627                        'Subsection One-Four' => '',
5628                        'Subsection One-One' => '',
5629                        'Subsection One-Three' => '',
5630                        'Subsection One-Two' => '',
5631                        'Subsubsection One-Two-Four' => '',
5632                        'Subsubsection One-Two-One' => '',
5633                        'Subsubsection One-Two-Three' => '',
5634                        'Subsubsection One-Two-Two' => '',
5635                        'T2H_today' => '',
5636                        'Table of Contents' => 'Inhaltsverzeichniss',
5637                        'Table of contents' => '',
5638                        'The node you are looking for is at %{href}.' => '',
5639                        'This' => '',
5640                        'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5641                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5642                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
5643                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5644                        'Top' => '',
5645                        'Untitled Document' => '',
5646                        'Up' => '',
5647                        'Up node' => '',
5648                        'Up section' => '',
5649                        'by @emph{%{user}}' => '',
5650                        'by @emph{%{user}} on @emph{%{date}}' => '',
5651                        'current' => '',
5652                        'on @emph{%{date}}' => '',
5653                        'section `%{section}\' in @cite{%{book}}' => '',
5654                        'see %{node_file_href}' => '',
5655                        'see %{node_file_href} @cite{%{book}}' => '',
5656                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5657                        'see %{reference_name}' => '',
5658                        'see @cite{%{book}}' => '',
5659                        'see section %{reference_name}' => '',
5660                        'see section `%{section}\' in @cite{%{book}}' => '',
5661                        'unknown' => ''
5662                      };
5663
5664 $T2H_OBSOLETE_STRINGS->{'de'} = {
5665                                   'See' => 'Siehe',
5666                                   'section' => 'Abschnitt',
5667                                   'see' => 'siehe'
5668                                 };
5669
5670
5671 $LANGUAGES->{'en'} = {
5672                        '  The buttons in the navigation panels have the following meaning:' => '',
5673                        '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
5674                        ' Up ' => '',
5675                        '%{acronym_like} (%{explanation})' => '',
5676                        '%{month}, %{day} %{year}' => '',
5677                        '%{name} of %{class}' => '',
5678                        '%{name} on %{class}' => '',
5679                        '%{node_file_href}' => '',
5680                        '%{node_file_href} @cite{%{book}}' => '',
5681                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5682                        '%{reference_name}' => '',
5683                        '%{style} %{number}' => '',
5684                        '%{style}: %{caption_first_line}' => '',
5685                        '%{style}: %{shortcaption_first_line}' => '',
5686                        '@b{%{quotation_arg}:} ' => '',
5687                        '@cite{%{book}}' => '',
5688                        'About' => '',
5689                        'About (help)' => '',
5690                        'About This Document' => '',
5691                        'April' => '',
5692                        'August' => '',
5693                        'Back' => '',
5694                        'Beginning of this chapter or previous chapter' => '',
5695                        'Button' => '',
5696                        'Contents' => '',
5697                        'Cover (top) of document' => '',
5698                        'Current Position' => '',
5699                        'Current section' => '',
5700                        'December' => '',
5701                        'FastBack' => '',
5702                        'FastForward' => '',
5703                        'February' => '',
5704                        'First' => '',
5705                        'First section in reading order' => '',
5706                        'Following' => '',
5707                        'Following node' => '',
5708                        'Footnotes' => '',
5709                        'Forward' => '',
5710                        'From 1.2.3 go to' => '',
5711                        'Go to' => '',
5712                        'Index' => '',
5713                        'Index Entry' => '',
5714                        'January' => '',
5715                        'July' => '',
5716                        'Jump to' => '',
5717                        'June' => '',
5718                        'Last' => '',
5719                        'Last section in reading order' => '',
5720                        'March' => '',
5721                        'May' => '',
5722                        'Menu:' => '',
5723                        'Name' => '',
5724                        'Next' => '',
5725                        'Next chapter' => '',
5726                        'Next node' => '',
5727                        'Next section in reading order' => '',
5728                        'Next section on same level' => '',
5729                        'Node following in node reading order' => '',
5730                        'Node up' => '',
5731                        'NodeNext' => '',
5732                        'NodePrev' => '',
5733                        'NodeUp' => '',
5734                        'November' => '',
5735                        'October' => '',
5736                        'Overview' => '',
5737                        'Overview:' => '',
5738                        'Prev' => '',
5739                        'Previous node' => '',
5740                        'Previous section in reading order' => '',
5741                        'Previous section on same level' => '',
5742                        'Section' => '',
5743                        'Section One' => '',
5744                        'See %{node_file_href}' => '',
5745                        'See %{node_file_href} @cite{%{book}}' => '',
5746                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5747                        'See %{reference_name}' => '',
5748                        'See @cite{%{book}}' => '',
5749                        'See section %{reference_name}' => '',
5750                        'See section `%{section}\' in @cite{%{book}}' => '',
5751                        'September' => '',
5752                        'Short Table of Contents' => '',
5753                        'Short table of contents' => '',
5754                        'Subsection One-Four' => '',
5755                        'Subsection One-One' => '',
5756                        'Subsection One-Three' => '',
5757                        'Subsection One-Two' => '',
5758                        'Subsubsection One-Two-Four' => '',
5759                        'Subsubsection One-Two-One' => '',
5760                        'Subsubsection One-Two-Three' => '',
5761                        'Subsubsection One-Two-Two' => '',
5762                        'T2H_today' => '%s, %d %d',
5763                        'Table of Contents' => '',
5764                        'Table of contents' => '',
5765                        'The node you are looking for is at %{href}.' => '',
5766                        'This' => '',
5767                        'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5768                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5769                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
5770                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5771                        'Top' => '',
5772                        'Untitled Document' => '',
5773                        'Up' => '',
5774                        'Up node' => '',
5775                        'Up section' => '',
5776                        'by @emph{%{user}}' => '',
5777                        'by @emph{%{user}} on @emph{%{date}}' => '',
5778                        'current' => '',
5779                        'on @emph{%{date}}' => '',
5780                        'section `%{section}\' in @cite{%{book}}' => '',
5781                        'see %{node_file_href}' => '',
5782                        'see %{node_file_href} @cite{%{book}}' => '',
5783                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5784                        'see %{reference_name}' => '',
5785                        'see @cite{%{book}}' => '',
5786                        'see section %{reference_name}' => '',
5787                        'see section `%{section}\' in @cite{%{book}}' => '',
5788                        'unknown' => ''
5789                      };
5790
5791 $T2H_OBSOLETE_STRINGS->{'en'} = {};
5792
5793
5794 $LANGUAGES->{'es'} = {
5795                        '  The buttons in the navigation panels have the following meaning:' => '',
5796                        '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
5797                        ' Up ' => '',
5798                        '%{acronym_like} (%{explanation})' => '',
5799                        '%{month}, %{day} %{year}' => '',
5800                        '%{name} of %{class}' => '',
5801                        '%{name} on %{class}' => '',
5802                        '%{node_file_href}' => '',
5803                        '%{node_file_href} @cite{%{book}}' => '',
5804                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5805                        '%{reference_name}' => '',
5806                        '%{style} %{number}' => '',
5807                        '%{style}: %{caption_first_line}' => '',
5808                        '%{style}: %{shortcaption_first_line}' => '',
5809                        '@b{%{quotation_arg}:} ' => '',
5810                        '@cite{%{book}}' => '',
5811                        'About' => '',
5812                        'About (help)' => '',
5813                        'About This Document' => '',
5814                        'April' => 'abril',
5815                        'August' => 'agosto',
5816                        'Back' => '',
5817                        'Beginning of this chapter or previous chapter' => '',
5818                        'Button' => '',
5819                        'Contents' => '',
5820                        'Cover (top) of document' => '',
5821                        'Current Position' => '',
5822                        'Current section' => '',
5823                        'December' => 'diciembre',
5824                        'FastBack' => '',
5825                        'FastForward' => '',
5826                        'February' => 'febrero',
5827                        'First' => '',
5828                        'First section in reading order' => '',
5829                        'Following' => '',
5830                        'Following node' => '',
5831                        'Footnotes' => '',
5832                        'Forward' => '',
5833                        'From 1.2.3 go to' => '',
5834                        'Go to' => '',
5835                        'Index' => 'Index',
5836                        'Index Entry' => '',
5837                        'January' => 'enero',
5838                        'July' => 'julio',
5839                        'Jump to' => '',
5840                        'June' => 'junio',
5841                        'Last' => '',
5842                        'Last section in reading order' => '',
5843                        'March' => 'marzo',
5844                        'May' => 'mayo',
5845                        'Menu:' => '',
5846                        'Name' => '',
5847                        'Next' => '',
5848                        'Next chapter' => '',
5849                        'Next node' => '',
5850                        'Next section in reading order' => '',
5851                        'Next section on same level' => '',
5852                        'Node following in node reading order' => '',
5853                        'Node up' => '',
5854                        'NodeNext' => '',
5855                        'NodePrev' => '',
5856                        'NodeUp' => '',
5857                        'November' => 'noviembre',
5858                        'October' => 'octubre',
5859                        'Overview' => '',
5860                        'Overview:' => '',
5861                        'Prev' => '',
5862                        'Previous node' => '',
5863                        'Previous section in reading order' => '',
5864                        'Previous section on same level' => '',
5865                        'Section' => '',
5866                        'Section One' => '',
5867                        'See %{node_file_href}' => '',
5868                        'See %{node_file_href} @cite{%{book}}' => '',
5869                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5870                        'See %{reference_name}' => '',
5871                        'See @cite{%{book}}' => '',
5872                        'See section %{reference_name}' => '',
5873                        'See section `%{section}\' in @cite{%{book}}' => '',
5874                        'September' => 'septiembre',
5875                        'Short Table of Contents' => 'Resumen del Contenido',
5876                        'Short table of contents' => '',
5877                        'Subsection One-Four' => '',
5878                        'Subsection One-One' => '',
5879                        'Subsection One-Three' => '',
5880                        'Subsection One-Two' => '',
5881                        'Subsubsection One-Two-Four' => '',
5882                        'Subsubsection One-Two-One' => '',
5883                        'Subsubsection One-Two-Three' => '',
5884                        'Subsubsection One-Two-Two' => '',
5885                        'T2H_today' => '',
5886                        'Table of Contents' => '@\'{@dotless{I}}ndice General',
5887                        'Table of contents' => '',
5888                        'The node you are looking for is at %{href}.' => '',
5889                        'This' => '',
5890                        'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5891                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5892                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
5893                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
5894                        'Top' => '',
5895                        'Untitled Document' => '',
5896                        'Up' => '',
5897                        'Up node' => '',
5898                        'Up section' => '',
5899                        'by @emph{%{user}}' => '',
5900                        'by @emph{%{user}} on @emph{%{date}}' => '',
5901                        'current' => '',
5902                        'on @emph{%{date}}' => '',
5903                        'section `%{section}\' in @cite{%{book}}' => '',
5904                        'see %{node_file_href}' => '',
5905                        'see %{node_file_href} @cite{%{book}}' => '',
5906                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
5907                        'see %{reference_name}' => '',
5908                        'see @cite{%{book}}' => '',
5909                        'see section %{reference_name}' => '',
5910                        'see section `%{section}\' in @cite{%{book}}' => '',
5911                        'unknown' => ''
5912                      };
5913
5914 $T2H_OBSOLETE_STRINGS->{'es'} = {
5915                                   'See' => 'V@\'ease',
5916                                   'section' => 'secci@\'on',
5917                                   'see' => 'v@\'ase'
5918                                 };
5919
5920
5921 $LANGUAGES->{'fr'} = {
5922                        '  The buttons in the navigation panels have the following meaning:' => '  Les boutons de navigation ont la signification suivante :',
5923                        '  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 section un-deux-trois } dans un document dont la structure est :',
5924                        ' Up ' => 'Plus haut',
5925                        '%{acronym_like} (%{explanation})' => '',
5926                        '%{month}, %{day} %{year}' => 'le %{day} %{month} %{year}',
5927                        '%{name} of %{class}' => '%{name} de %{class}',
5928                        '%{name} on %{class}' => '%{name} de %{class}',
5929                        '%{node_file_href}' => '',
5930                        '%{node_file_href} @cite{%{book}}' => '',
5931                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} section `%{section}\' dans @cite{%{book}}',
5932                        '%{reference_name}' => '',
5933                        '%{style} %{number}' => '',
5934                        '%{style}: %{caption_first_line}' => '',
5935                        '%{style}: %{shortcaption_first_line}' => '',
5936                        '@b{%{quotation_arg}:} ' => '',
5937                        '@cite{%{book}}' => '',
5938                        'About' => 'A propos',
5939                        'About (help)' => 'A propos (page d\'aide)',
5940                        'About This Document' => 'A propos de ce document',
5941                        'April' => 'Avril',
5942                        'August' => 'Ao@^ut',
5943                        'Back' => 'Retour',
5944                        'Beginning of this chapter or previous chapter' => 'D@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent',
5945                        'Button' => 'Bouton',
5946                        'Contents' => 'Table des mati@`eres',
5947                        'Cover (top) of document' => 'Couverture (top) du document',
5948                        'Current Position' => 'Position',
5949                        'Current section' => 'Section actuelle',
5950                        'December' => 'D@\'ecembre',
5951                        'FastBack' => 'RetourRapide',
5952                        'FastForward' => 'AvanceRapide',
5953                        'February' => 'F@\'evrier',
5954                        'First' => 'Premier',
5955                        'First section in reading order' => 'Premi@`e section dans l\'ordre de lecture',
5956                        'Following' => 'Suivant',
5957                        'Following node' => 'N@oe{}ud suivant',
5958                        'Footnotes' => 'Notes de bas de page',
5959                        'Forward' => 'Avant',
5960                        'From 1.2.3 go to' => 'Depuis 1.2.3 aller @`a',
5961                        'Go to' => 'Aller @`a',
5962                        'Index' => 'Index',
5963                        'Index Entry' => 'Entr@\'ee d\'index',
5964                        'January' => 'Janvier',
5965                        'July' => 'Juillet',
5966                        'Jump to' => 'Aller @`a',
5967                        'June' => 'Juin',
5968                        'Last' => 'Dernier',
5969                        'Last section in reading order' => 'Derni@`ere section dans l\'ordre de lecture',
5970                        'March' => 'Mars',
5971                        'May' => 'Mai',
5972                        'Menu:' => 'Menu@ :',
5973                        'Name' => 'Nom',
5974                        'Next' => 'Suivant',
5975                        'Next chapter' => 'Chapitre suivant',
5976                        'Next node' => 'N@oe{}ud suivant',
5977                        'Next section in reading order' => 'Section suivante dans l\'ordre de lecture',
5978                        'Next section on same level' => 'Section suivante au m@^eme niveau',
5979                        'Node following in node reading order' => 'N@oe{}ud suivant dans l\'ordre de lecture',
5980                        'Node up' => 'N@oe{}ud au dessus',
5981                        'NodeNext' => 'N@oe{}udSuivant',
5982                        'NodePrev' => 'N@oe{}udPr@\'ec@\'edent',
5983                        'NodeUp' => 'N@oe{}udMonter',
5984                        'November' => 'Novembre',
5985                        'October' => 'Octobre',
5986                        'Overview' => 'Vue d\'ensemble',
5987                        'Overview:' => 'Vue d\'ensemble@ :',
5988                        'Prev' => 'Pr@\'ec@\'edent',
5989                        'Previous node' => 'N@oe{}ud pr@\'ec@\'edent',
5990                        'Previous section in reading order' => 'Section pr@\'ec@\'edente dans l\'ordre de lecture',
5991                        'Previous section on same level' => 'Section pr@\'ec@\'edente au m@^eme niveau',
5992                        'Section' => '',
5993                        'Section One' => 'Section un',
5994                        'See %{node_file_href}' => 'Voir %{node_file_href}',
5995                        'See %{node_file_href} @cite{%{book}}' => 'Voir %{node_file_href} @cite{%{book}}',
5996                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Voir %{node_file_href} section `%{section}\' dans @cite{%{book}}',
5997                        'See %{reference_name}' => 'Voir %{reference_name}',
5998                        'See @cite{%{book}}' => 'Voir @cite{%{book}}',
5999                        'See section %{reference_name}' => 'Voir la section %{reference_name}',
6000                        'See section `%{section}\' in @cite{%{book}}' => 'Voir la section `%{section}\' dans @cite{%{book}}',
6001                        'September' => 'Septembre',
6002                        'Short Table of Contents' => 'R@\'esum@\'e du contenu',
6003                        'Short table of contents' => 'R@\'esum@\'e du contenu',
6004                        'Subsection One-Four' => 'Sous section un-quatre',
6005                        'Subsection One-One' => 'Sous section un-un',
6006                        'Subsection One-Three' => 'Sous section un-trois',
6007                        'Subsection One-Two' => 'Sous section un-deux',
6008                        'Subsubsection One-Two-Four' => 'Sous sous section un-deux-quatre',
6009                        'Subsubsection One-Two-One' => 'Sous sous section un-deux-un',
6010                        'Subsubsection One-Two-Three' => 'Sous sous section un-deux-trois',
6011                        'Subsubsection One-Two-Two' => 'Sous sous section un-deux-deux',
6012                        'T2H_today' => 'le %2$d %1$s %3$d',
6013                        'Table of Contents' => 'Table des mati@`eres',
6014                        'Table of contents' => 'Table des mati@`eres',
6015                        'The node you are looking for is at %{href}.' => 'Le n@oe{}ud que vous recherchez est ici@ : %{href}.',
6016                        'This' => 'Ici',
6017                        '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 par @emph{%{user}} @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.',
6018                        '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}}}.',
6019                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}',
6020                        '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}}}.',
6021                        'Top' => '',
6022                        'Untitled Document' => 'Document sans titre',
6023                        'Up' => 'Monter',
6024                        'Up node' => 'N@oe{}ud au dessus',
6025                        'Up section' => 'Section sup@\'erieure',
6026                        'by @emph{%{user}}' => 'par @emph{%{user}}',
6027                        'by @emph{%{user}} on @emph{%{date}}' => 'par @emph{%{user}} @emph{%{date}}',
6028                        'current' => 'courante',
6029                        'on @emph{%{date}}' => '@emph{%{date}}',
6030                        'section `%{section}\' in @cite{%{book}}' => 'section `%{section}\' dans @cite{%{book}}',
6031                        'see %{node_file_href}' => 'voir %{node_file_href}',
6032                        'see %{node_file_href} @cite{%{book}}' => 'voir %{node_file_href} @cite{%{book}}',
6033                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'voir %{node_file_href} section `%{section}\' dans @cite{%{book}}',
6034                        'see %{reference_name}' => 'voir %{reference_name}',
6035                        'see @cite{%{book}}' => 'voir @cite{%{book}}',
6036                        'see section %{reference_name}' => 'voir la section %{reference_name}',
6037                        'see section `%{section}\' in @cite{%{book}}' => 'voir la section `%{section}\' dans @cite{{book}}',
6038                        'unknown' => 'inconnu'
6039                      };
6040
6041 $T2H_OBSOLETE_STRINGS->{'fr'} = {
6042                                   '  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}.',
6043                                   '  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 :',
6044                                   '%{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => '%{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
6045                                   'See' => 'Voir',
6046                                   'See %{node_file_href} <cite>%{book}</cite>' => 'Voir %{node_file_href} <cite>%{book}</cite>',
6047                                   'See %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'Voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
6048                                   'See <cite>%{book}</cite>' => 'Voir <cite>%{book}</cite>',
6049                                   'See section `%{section}\' in <cite>%{book}</cite>' => 'Voir la section `%{section}\' dans <cite>%{book}</cite>',
6050                                   '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}.',
6051                                   '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}.',
6052                                   '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}.',
6053                                   '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}.',
6054                                   '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}.',
6055                                   '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}.',
6056                                   '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}}}.',
6057                                   'This document was generated using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e en utilisant %{program_homepage_href}.',
6058                                   'about (help)' => '@`a propos (page d\'aide)',
6059                                   'about (this page)' => 'a propos (cette page)',
6060                                   'beginning of this chapter or previous chapter' => 'd@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent',
6061                                   'by <i>%{user}</i>' => 'par <i>%{user}</i>',
6062                                   'by <i>%{user}</i> on <i>%{date}</i>' => 'par <i>%{user}</i> <i>%{date}</i>',
6063                                   'concept index' => 'index',
6064                                   'cover (top) of document' => 'couverture (top) du document',
6065                                   'current section' => 'section actuelle',
6066                                   'first section in reading order' => 'premi@`e section dans l\'ordre de lecture',
6067                                   'following node' => 'node suivant',
6068                                   'index' => 'index',
6069                                   'last section in reading order' => 'derni@`ere section dans l\'ordre de lecture',
6070                                   'next chapter' => 'chapitre suivant',
6071                                   'next node' => 'node suivant',
6072                                   'next section in reading order' => 'section suivante dans l\'ordre de lecture',
6073                                   'next section on same level' => 'section suivante au m@^eme niveau',
6074                                   'node following in node reading order' => 'node suivant dans l\'ordre des nodes',
6075                                   'node up' => 'node au dessus',
6076                                   'on <i>%{date}</i>' => '<i>%{date}</i>',
6077                                   'previous node' => 'node pr@\'ec@\'edent',
6078                                   'previous section in reading order' => 'section pr@\'ec@\'edente dans l\'ordre de lecture',
6079                                   'previous section on same level' => 'section pr@\'ec@\'edente au m@^eme niveau',
6080                                   'section' => 'section',
6081                                   'section `%{section}\' in <cite>%{book}</cite>' => 'section `%{section}\' dans <cite>%{book}</cite>',
6082                                   'see' => 'voir',
6083                                   'see %{node_file_href} <cite>%{book}</cite>' => 'voir %{node_file_href} <cite>%{book}</cite>',
6084                                   'see %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>',
6085                                   'see <cite>%{book}</cite>' => 'voir <cite>%{book}</cite>',
6086                                   'see section `%{section}\' in <cite>%{book}</cite>' => 'voir la section `%{section}\' dans <cite>%{book}</cite>',
6087                                   'short table of contents' => 'table des mati@`eres r@\'esum@\'ee',
6088                                   'table of contents' => 'table des mati@`eres',
6089                                   'up node' => 'node au dessus',
6090                                   'up section' => 'section sup@\'erieure'
6091                                 };
6092
6093
6094 $LANGUAGES->{'ja'} = {
6095                        '  The buttons in the navigation panels have the following meaning:' => 'ナビゲーションパネル中のボタンには以下の意味があります。',
6096                        '  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項}を現在位置に仮定しています。',
6097                        ' Up ' => '上',
6098                        '%{acronym_like} (%{explanation})' => '',
6099                        '%{month}, %{day} %{year}' => '%{year}年%{month}月%{day}日',
6100                        '%{name} of %{class}' => '',
6101                        '%{name} on %{class}' => '',
6102                        '%{node_file_href}' => '',
6103                        '%{node_file_href} @cite{%{book}}' => '',
6104                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6105                        '%{reference_name}' => '',
6106                        '%{style} %{number}' => '',
6107                        '%{style}: %{caption_first_line}' => '',
6108                        '%{style}: %{shortcaption_first_line}' => '',
6109                        '@b{%{quotation_arg}:} ' => '',
6110                        '@cite{%{book}}' => '',
6111                        'About' => '',
6112                        'About (help)' => '',
6113                        'About This Document' => 'この文書について',
6114                        'April' => '4月',
6115                        'August' => '8月',
6116                        'Back' => '',
6117                        'Beginning of this chapter or previous chapter' => '',
6118                        'Button' => 'ボタン',
6119                        'Contents' => '目次',
6120                        'Cover (top) of document' => '',
6121                        'Current Position' => '現在位置',
6122                        'Current section' => '',
6123                        'December' => '12月',
6124                        'FastBack' => '',
6125                        'FastForward' => '',
6126                        'February' => '2月',
6127                        'First' => '',
6128                        'First section in reading order' => '',
6129                        'Following' => '',
6130                        'Following node' => '',
6131                        'Footnotes' => '脚注',
6132                        'Forward' => '',
6133                        'From 1.2.3 go to' => '1.2.3項からの移動先',
6134                        'Go to' => '移動先',
6135                        'Index' => '見出し',
6136                        'Index Entry' => '見出し一覧',
6137                        'January' => '1月',
6138                        'July' => '7月',
6139                        'Jump to' => '移動',
6140                        'June' => '6月',
6141                        'Last' => '',
6142                        'Last section in reading order' => '',
6143                        'March' => '3月',
6144                        'May' => '5月',
6145                        'Menu:' => 'メニュー',
6146                        'Name' => '名称',
6147                        'Next' => '次',
6148                        'Next chapter' => '',
6149                        'Next node' => '',
6150                        'Next section in reading order' => '',
6151                        'Next section on same level' => '',
6152                        'Node following in node reading order' => '',
6153                        'Node up' => '',
6154                        'NodeNext' => '',
6155                        'NodePrev' => '',
6156                        'NodeUp' => '',
6157                        'November' => '11月',
6158                        'October' => '10月',
6159                        'Overview' => '概要',
6160                        'Overview:' => '概要:',
6161                        'Prev' => '前',
6162                        'Previous node' => '',
6163                        'Previous section in reading order' => '',
6164                        'Previous section on same level' => '',
6165                        'Section' => '項',
6166                        'Section One' => '第1項',
6167                        'See %{node_file_href}' => '',
6168                        'See %{node_file_href} @cite{%{book}}' => '',
6169                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6170                        'See %{reference_name}' => '',
6171                        'See @cite{%{book}}' => '',
6172                        'See section %{reference_name}' => '',
6173                        'See section `%{section}\' in @cite{%{book}}' => '',
6174                        'September' => '9月',
6175                        'Short Table of Contents' => '簡略化した目次',
6176                        'Short table of contents' => '',
6177                        'Subsection One-Four' => '第1.4項',
6178                        'Subsection One-One' => '第1.1項',
6179                        'Subsection One-Three' => '第1.3項',
6180                        'Subsection One-Two' => '第1.2項',
6181                        'Subsubsection One-Two-Four' => '第1.2.4項',
6182                        'Subsubsection One-Two-One' => '第1.2.1項',
6183                        'Subsubsection One-Two-Three' => '第1.2.3項',
6184                        'Subsubsection One-Two-Two' => '第1.2.2項',
6185                        'T2H_today' => '%s, %d %d',
6186                        'Table of Contents' => '目次',
6187                        'Table of contents' => '',
6188                        'The node you are looking for is at %{href}.' => '',
6189                        'This' => '',
6190                        '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}}}を用いて生成されました。',
6191                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@emph{%{user}}によって@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
6192                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'この文書は@emph{%{date}}に@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
6193                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。',
6194                        'Top' => '冒頭',
6195                        'Untitled Document' => '無題の文書',
6196                        'Up' => '',
6197                        'Up node' => '',
6198                        'Up section' => '',
6199                        'by @emph{%{user}}' => '@emph{%{user}}',
6200                        'by @emph{%{user}} on @emph{%{date}}' => '@emph{%{user}}, @emph{%{date}',
6201                        'current' => '現在位置',
6202                        'on @emph{%{date}}' => '@emph{%{date}}',
6203                        'section `%{section}\' in @cite{%{book}}' => '@cite{%{book}}の `%{section}\' ',
6204                        'see %{node_file_href}' => '%{node_file_href}参照',
6205                        'see %{node_file_href} @cite{%{book}}' => '%{node_file_href} @cite{%{book}}参照',
6206                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6207                        'see %{reference_name}' => '',
6208                        'see @cite{%{book}}' => '',
6209                        'see section %{reference_name}' => '',
6210                        'see section `%{section}\' in @cite{%{book}}' => '',
6211                        'unknown' => '不明'
6212                      };
6213
6214 $T2H_OBSOLETE_STRINGS->{'ja'} = {
6215                                   'about (help)' => '使用法 (ヘルプ)',
6216                                   'beginning of this chapter or previous chapter' => 'この章または前の章の冒頭',
6217                                   'cover (top) of document' => '文書の表紙 (トップ)',
6218                                   'current section' => '現在の節',
6219                                   'first section in reading order' => '文書順で前の項',
6220                                   'following node' => '次の節',
6221                                   'index' => '見出し',
6222                                   'last section in reading order' => '文書順で最後の項',
6223                                   'next chapter' => '次の章',
6224                                   'next node' => '次の節',
6225                                   'next section in reading order' => '文書順で次の項',
6226                                   'next section on same level' => '同じ階層にある次の項',
6227                                   'node following in node reading order' => '文書順で次の節',
6228                                   'node up' => '上の節へ',
6229                                   'previous node' => '前の節',
6230                                   'previous section in reading order' => '文書順で前の節',
6231                                   'previous section on same level' => '同じ階層にある前の項',
6232                                   'short table of contents' => '簡略化した目次',
6233                                   'table of contents' => '文書の目次',
6234                                   'up node' => '上の節',
6235                                   'up section' => '上の項'
6236                                 };
6237
6238
6239 $LANGUAGES->{'nl'} = {
6240                        '  The buttons in the navigation panels have the following meaning:' => '',
6241                        '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
6242                        ' Up ' => '',
6243                        '%{acronym_like} (%{explanation})' => '',
6244                        '%{month}, %{day} %{year}' => '',
6245                        '%{name} of %{class}' => '',
6246                        '%{name} on %{class}' => '',
6247                        '%{node_file_href}' => '',
6248                        '%{node_file_href} @cite{%{book}}' => '',
6249                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6250                        '%{reference_name}' => '',
6251                        '%{style} %{number}' => '',
6252                        '%{style}: %{caption_first_line}' => '',
6253                        '%{style}: %{shortcaption_first_line}' => '',
6254                        '@b{%{quotation_arg}:} ' => '',
6255                        '@cite{%{book}}' => '',
6256                        'About' => '',
6257                        'About (help)' => '',
6258                        'About This Document' => 'No translation available!',
6259                        'April' => 'April',
6260                        'August' => 'Augustus',
6261                        'Back' => '',
6262                        'Beginning of this chapter or previous chapter' => '',
6263                        'Button' => '',
6264                        'Contents' => '',
6265                        'Cover (top) of document' => '',
6266                        'Current Position' => '',
6267                        'Current section' => '',
6268                        'December' => 'December',
6269                        'FastBack' => '',
6270                        'FastForward' => '',
6271                        'February' => 'Februari',
6272                        'First' => '',
6273                        'First section in reading order' => '',
6274                        'Following' => '',
6275                        'Following node' => '',
6276                        'Footnotes' => 'No translation available!',
6277                        'Forward' => '',
6278                        'From 1.2.3 go to' => '',
6279                        'Go to' => '',
6280                        'Index' => 'Index',
6281                        'Index Entry' => '',
6282                        'January' => 'Januari',
6283                        'July' => 'Juli',
6284                        'Jump to' => '',
6285                        'June' => 'Juni',
6286                        'Last' => '',
6287                        'Last section in reading order' => '',
6288                        'March' => 'Maart',
6289                        'May' => 'Mei',
6290                        'Menu:' => '',
6291                        'Name' => '',
6292                        'Next' => '',
6293                        'Next chapter' => '',
6294                        'Next node' => '',
6295                        'Next section in reading order' => '',
6296                        'Next section on same level' => '',
6297                        'Node following in node reading order' => '',
6298                        'Node up' => '',
6299                        'NodeNext' => '',
6300                        'NodePrev' => '',
6301                        'NodeUp' => '',
6302                        'November' => 'November',
6303                        'October' => 'Oktober',
6304                        'Overview' => '',
6305                        'Overview:' => '',
6306                        'Prev' => '',
6307                        'Previous node' => '',
6308                        'Previous section in reading order' => '',
6309                        'Previous section on same level' => '',
6310                        'Section' => '',
6311                        'Section One' => '',
6312                        'See %{node_file_href}' => '',
6313                        'See %{node_file_href} @cite{%{book}}' => '',
6314                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6315                        'See %{reference_name}' => '',
6316                        'See @cite{%{book}}' => '',
6317                        'See section %{reference_name}' => '',
6318                        'See section `%{section}\' in @cite{%{book}}' => '',
6319                        'September' => 'September',
6320                        'Short Table of Contents' => 'Korte inhoudsopgave',
6321                        'Short table of contents' => '',
6322                        'Subsection One-Four' => '',
6323                        'Subsection One-One' => '',
6324                        'Subsection One-Three' => '',
6325                        'Subsection One-Two' => '',
6326                        'Subsubsection One-Two-Four' => '',
6327                        'Subsubsection One-Two-One' => '',
6328                        'Subsubsection One-Two-Three' => '',
6329                        'Subsubsection One-Two-Two' => '',
6330                        'T2H_today' => '',
6331                        'Table of Contents' => 'Inhoudsopgave',
6332                        'Table of contents' => '',
6333                        'The node you are looking for is at %{href}.' => '',
6334                        'This' => '',
6335                        'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6336                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6337                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
6338                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6339                        'Top' => '',
6340                        'Untitled Document' => '',
6341                        'Up' => '',
6342                        'Up node' => '',
6343                        'Up section' => '',
6344                        'by @emph{%{user}}' => '',
6345                        'by @emph{%{user}} on @emph{%{date}}' => '',
6346                        'current' => '',
6347                        'on @emph{%{date}}' => '',
6348                        'section `%{section}\' in @cite{%{book}}' => '',
6349                        'see %{node_file_href}' => '',
6350                        'see %{node_file_href} @cite{%{book}}' => '',
6351                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6352                        'see %{reference_name}' => '',
6353                        'see @cite{%{book}}' => '',
6354                        'see section %{reference_name}' => '',
6355                        'see section `%{section}\' in @cite{%{book}}' => '',
6356                        'unknown' => ''
6357                      };
6358
6359 $T2H_OBSOLETE_STRINGS->{'nl'} = {
6360                                   'See' => 'Zie',
6361                                   'section' => 'sectie',
6362                                   'see' => 'zie'
6363                                 };
6364
6365
6366 $LANGUAGES->{'no'} = {
6367                        '  The buttons in the navigation panels have the following meaning:' => '',
6368                        '  where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '',
6369                        ' Up ' => '',
6370                        '%{acronym_like} (%{explanation})' => '',
6371                        '%{month}, %{day} %{year}' => '',
6372                        '%{name} of %{class}' => '',
6373                        '%{name} on %{class}' => '',
6374                        '%{node_file_href}' => '',
6375                        '%{node_file_href} @cite{%{book}}' => '',
6376                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6377                        '%{reference_name}' => '',
6378                        '%{style} %{number}' => '',
6379                        '%{style}: %{caption_first_line}' => '',
6380                        '%{style}: %{shortcaption_first_line}' => '',
6381                        '@b{%{quotation_arg}:} ' => '',
6382                        '@cite{%{book}}' => '',
6383                        'About' => '',
6384                        'About (help)' => '',
6385                        'About This Document' => 'No translation available!',
6386                        'April' => 'april',
6387                        'August' => 'august',
6388                        'Back' => '',
6389                        'Beginning of this chapter or previous chapter' => '',
6390                        'Button' => '',
6391                        'Contents' => '',
6392                        'Cover (top) of document' => '',
6393                        'Current Position' => '',
6394                        'Current section' => '',
6395                        'December' => 'desember',
6396                        'FastBack' => '',
6397                        'FastForward' => '',
6398                        'February' => 'februar',
6399                        'First' => '',
6400                        'First section in reading order' => '',
6401                        'Following' => '',
6402                        'Following node' => '',
6403                        'Footnotes' => 'No translation available!',
6404                        'Forward' => '',
6405                        'From 1.2.3 go to' => '',
6406                        'Go to' => '',
6407                        'Index' => 'Indeks',
6408                        'Index Entry' => '',
6409                        'January' => 'januar',
6410                        'July' => 'juli',
6411                        'Jump to' => '',
6412                        'June' => 'juni',
6413                        'Last' => '',
6414                        'Last section in reading order' => '',
6415                        'March' => 'mars',
6416                        'May' => 'mai',
6417                        'Menu:' => '',
6418                        'Name' => '',
6419                        'Next' => '',
6420                        'Next chapter' => '',
6421                        'Next node' => '',
6422                        'Next section in reading order' => '',
6423                        'Next section on same level' => '',
6424                        'Node following in node reading order' => '',
6425                        'Node up' => '',
6426                        'NodeNext' => '',
6427                        'NodePrev' => '',
6428                        'NodeUp' => '',
6429                        'November' => 'november',
6430                        'October' => 'oktober',
6431                        'Overview' => '',
6432                        'Overview:' => '',
6433                        'Prev' => '',
6434                        'Previous node' => '',
6435                        'Previous section in reading order' => '',
6436                        'Previous section on same level' => '',
6437                        'Section' => '',
6438                        'Section One' => '',
6439                        'See %{node_file_href}' => '',
6440                        'See %{node_file_href} @cite{%{book}}' => '',
6441                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6442                        'See %{reference_name}' => '',
6443                        'See @cite{%{book}}' => '',
6444                        'See section %{reference_name}' => '',
6445                        'See section `%{section}\' in @cite{%{book}}' => '',
6446                        'September' => 'september',
6447                        'Short Table of Contents' => 'Kort innholdsfortegnelse',
6448                        'Short table of contents' => '',
6449                        'Subsection One-Four' => '',
6450                        'Subsection One-One' => '',
6451                        'Subsection One-Three' => '',
6452                        'Subsection One-Two' => '',
6453                        'Subsubsection One-Two-Four' => '',
6454                        'Subsubsection One-Two-One' => '',
6455                        'Subsubsection One-Two-Three' => '',
6456                        'Subsubsection One-Two-Two' => '',
6457                        'T2H_today' => '',
6458                        'Table of Contents' => 'Innholdsfortegnelse',
6459                        'Table of contents' => '',
6460                        'The node you are looking for is at %{href}.' => '',
6461                        'This' => '',
6462                        'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6463                        'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6464                        'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '',
6465                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '',
6466                        'Top' => '',
6467                        'Untitled Document' => '',
6468                        'Up' => '',
6469                        'Up node' => '',
6470                        'Up section' => '',
6471                        'by @emph{%{user}}' => '',
6472                        'by @emph{%{user}} on @emph{%{date}}' => '',
6473                        'current' => '',
6474                        'on @emph{%{date}}' => '',
6475                        'section `%{section}\' in @cite{%{book}}' => '',
6476                        'see %{node_file_href}' => '',
6477                        'see %{node_file_href} @cite{%{book}}' => '',
6478                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '',
6479                        'see %{reference_name}' => '',
6480                        'see @cite{%{book}}' => '',
6481                        'see section %{reference_name}' => '',
6482                        'see section `%{section}\' in @cite{%{book}}' => '',
6483                        'unknown' => ''
6484                      };
6485
6486 $T2H_OBSOLETE_STRINGS->{'no'} = {
6487                                   'See' => 'Se',
6488                                   'section' => 'avsnitt',
6489                                   'see' => 'se'
6490                                 };
6491
6492
6493 $LANGUAGES->{'pt'} = {
6494                        '  The buttons in the navigation panels have the following meaning:' => '  Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:',
6495                        '  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:',
6496                        ' Up ' => ' Acima ',
6497                        '%{acronym_like} (%{explanation})' => '',
6498                        '%{month}, %{day} %{year}' => '%{day} de %{month} de %{year}',
6499                        '%{name} of %{class}' => '%{name} da %{class}',
6500                        '%{name} on %{class}' => '%{name} na %{class}',
6501                        '%{node_file_href}' => '',
6502                        '%{node_file_href} @cite{%{book}}' => '',
6503                        '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6504                        '%{reference_name}' => '',
6505                        '%{style} %{number}' => '',
6506                        '%{style}: %{caption_first_line}' => '',
6507                        '%{style}: %{shortcaption_first_line}' => '',
6508                        '@b{%{quotation_arg}:} ' => '',
6509                        '@cite{%{book}}' => '',
6510                        'About' => 'Sobre',
6511                        'About (help)' => 'Sobre (ajuda)',
6512                        'About This Document' => 'Sobre Esse Documento',
6513                        'April' => 'Abril',
6514                        'August' => 'Agosto',
6515                        'Back' => 'Volta',
6516                        'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
6517                        'Button' => 'Bot@~ao',
6518                        'Contents' => 'Conte@\'udo',
6519                        'Cover (top) of document' => 'In@\'icio (topo) do documento',
6520                        'Current Position' => 'Posi@,{c}@~ao Atual',
6521                        'Current section' => 'Se@,{c}@~ao atual',
6522                        'December' => 'Dezembro',
6523                        'FastBack' => 'Voltar R@\'apido',
6524                        'FastForward' => 'Avan@,{c}ar R@\'apido',
6525                        'February' => 'Fevereiro',
6526                        'First' => 'Primeiro',
6527                        'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura',
6528                        'Following' => 'Seguinte',
6529                        'Following node' => 'Nodo seguinte',
6530                        'Footnotes' => 'Notas de Rodap@\'e',
6531                        'Forward' => 'Avan@,{c}ar',
6532                        'From 1.2.3 go to' => 'De 1.2.3 v@\'a para',
6533                        'Go to' => 'V@\'a para',
6534                        'Index' => '@\'Indice',
6535                        'Index Entry' => 'Entrada de @\'Indice',
6536                        'January' => 'Janeiro',
6537                        'July' => 'Julho',
6538                        'Jump to' => 'Pular para',
6539                        'June' => 'Junho',
6540                        'Last' => '@\'Ultimo',
6541                        'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
6542                        'March' => 'Mar@,{c}o',
6543                        'May' => 'Maio',
6544                        'Menu:' => '',
6545                        'Name' => 'Nome',
6546                        'Next' => 'Pr@\'oximo',
6547                        'Next chapter' => 'Pr@\'oximo cap@\'itulo',
6548                        'Next node' => 'Pr@\'oximo nodo',
6549                        'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura',
6550                        'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
6551                        'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos',
6552                        'Node up' => 'Nodo acima',
6553                        'NodeNext' => 'Pr@\'oximo Nodo',
6554                        'NodePrev' => 'Nodo Anterior',
6555                        'NodeUp' => 'Nodo Acima',
6556                        'November' => 'Novembro',
6557                        'October' => 'Outubro',
6558                        'Overview' => 'Vis@~ao geral',
6559                        'Overview:' => 'Vis@~ao geral:',
6560                        'Prev' => 'Pr@\'evio',
6561                        'Previous node' => 'Nodo anterior',
6562                        'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura',
6563                        'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel',
6564                        'Section' => 'Se@,{c}@~ao',
6565                        'Section One' => 'Se@,{c}@~ao Um',
6566                        'See %{node_file_href}' => 'Veja %{node_file_href}',
6567                        'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}',
6568                        'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6569                        'See %{reference_name}' => 'Veja %{reference_name}',
6570                        'See @cite{%{book}}' => 'Veja @cite{%{book}}',
6571                        'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}',
6572                        'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6573                        'September' => 'Setembro',
6574                        'Short Table of Contents' => 'Breve Sum@\'ario',
6575                        'Short table of contents' => 'Breve sum@\'ario',
6576                        'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro',
6577                        'Subsection One-One' => 'Subse@,{c}@~ao Um-Um',
6578                        'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es',
6579                        'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois',
6580                        'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro',
6581                        'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um',
6582                        'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es',
6583                        'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois',
6584                        'T2H_today' => '',
6585                        'Table of Contents' => 'Sum@\'ario',
6586                        'Table of contents' => 'Sum@\'ario',
6587                        'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.',
6588                        'This' => 'Esse',
6589                        '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}}}.',
6590                        '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}}}.',
6591                        '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}}}.',
6592                        'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.',
6593                        'Top' => 'Topo',
6594                        'Untitled Document' => 'Documento Sem Nome',
6595                        'Up' => 'Acima',
6596                        'Up node' => 'Nodo acima',
6597                        'Up section' => 'Se@,{c}@~ao acima',
6598                        'by @emph{%{user}}' => 'por  @emph{%{user}}',
6599                        'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}',
6600                        'current' => 'atual',
6601                        'on @emph{%{date}}' => 'em @emph{%{date}}',
6602                        'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6603                        'see %{node_file_href}' => 'veja %{node_file_href}',
6604                        'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}',
6605                        'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6606                        'see %{reference_name}' => 'veja %{reference_name}',
6607                        'see @cite{%{book}}' => 'veja @cite{%{book}}',
6608                        'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}',
6609                        'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6610                        'unknown' => 'desconhecido'
6611                      };
6612
6613 $T2H_OBSOLETE_STRINGS->{'pt'} = {
6614                                   'See' => 'Veja',
6615                                   'about (help)' => 'sobre (ajuda)',
6616                                   'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
6617                                   'cover (top) of document' => 'in@\'icio (topo) do documento',
6618                                   'current section' => 'se@,{c}@~ao atual',
6619                                   'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura',
6620                                   'following node' => 'nodo seguinte',
6621                                   'index' => '@\'indice',
6622                                   'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura',
6623                                   'next chapter' => 'pr@\'oximo cap@\'itulo',
6624                                   'next node' => 'pr@\'oximo nodo',
6625                                   'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura',
6626                                   'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
6627                                   'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos',
6628                                   'node up' => 'nodo acima',
6629                                   'previous node' => 'nodo anterior',
6630                                   'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura',
6631                                   'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel',
6632                                   'section' => 'Se@,{c}@~ao',
6633                                   'see' => 'veja',
6634                                   'short table of contents' => 'breve sum@\'ario',
6635                                   'table of contents' => 'sum@\'ario',
6636                                   'up node' => 'nodo acima',
6637                                   'up section' => 'se@,{c}@~ao acima'
6638                                 };
6639
6640
6641 $LANGUAGES->{'pt_BR'} = {
6642                           '  The buttons in the navigation panels have the following meaning:' => '  Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:',
6643                           '  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:',
6644                           ' Up ' => ' Acima ',
6645                           '%{acronym_like} (%{explanation})' => '',
6646                           '%{month}, %{day} %{year}' => '%{day} de %{month} de %{year}',
6647                           '%{name} of %{class}' => '%{name} da %{class}',
6648                           '%{name} on %{class}' => '%{name} na %{class}',
6649                           '%{node_file_href}' => '',
6650                           '%{node_file_href} @cite{%{book}}' => '',
6651                           '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6652                           '%{reference_name}' => '',
6653                           '%{style} %{number}' => '',
6654                           '%{style}: %{caption_first_line}' => '',
6655                           '%{style}: %{shortcaption_first_line}' => '',
6656                           '@b{%{quotation_arg}:} ' => '',
6657                           '@cite{%{book}}' => '',
6658                           'About' => 'Sobre',
6659                           'About (help)' => 'Sobre (ajuda)',
6660                           'About This Document' => 'Sobre Esse Documento',
6661                           'April' => 'Abril',
6662                           'August' => 'Agosto',
6663                           'Back' => 'Volta',
6664                           'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
6665                           'Button' => 'Bot@~ao',
6666                           'Contents' => 'Conte@\'udo',
6667                           'Cover (top) of document' => 'In@\'icio (topo) do documento',
6668                           'Current Position' => 'Posi@,{c}@~ao Atual',
6669                           'Current section' => 'Se@,{c}@~ao atual',
6670                           'December' => 'Dezembro',
6671                           'FastBack' => 'Voltar R@\'apido',
6672                           'FastForward' => 'Avan@,{c}ar R@\'apido',
6673                           'February' => 'Fevereiro',
6674                           'First' => 'Primeiro',
6675                           'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura',
6676                           'Following' => 'Seguinte',
6677                           'Following node' => 'Nodo seguinte',
6678                           'Footnotes' => 'Notas de Rodap@\'e',
6679                           'Forward' => 'Avan@,{c}ar',
6680                           'From 1.2.3 go to' => 'De 1.2.3 v@\'a para',
6681                           'Go to' => 'V@\'a para',
6682                           'Index' => '@\'Indice',
6683                           'Index Entry' => 'Entrada de @\'Indice',
6684                           'January' => 'Janeiro',
6685                           'July' => 'Julho',
6686                           'Jump to' => 'Pular para',
6687                           'June' => 'Junho',
6688                           'Last' => '@\'Ultimo',
6689                           'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
6690                           'March' => 'Mar@,{c}o',
6691                           'May' => 'Maio',
6692                           'Menu:' => '',
6693                           'Name' => 'Nome',
6694                           'Next' => 'Pr@\'oximo',
6695                           'Next chapter' => 'Pr@\'oximo cap@\'itulo',
6696                           'Next node' => 'Pr@\'oximo nodo',
6697                           'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura',
6698                           'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
6699                           'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos',
6700                           'Node up' => 'Nodo acima',
6701                           'NodeNext' => 'Pr@\'oximo Nodo',
6702                           'NodePrev' => 'Nodo Anterior',
6703                           'NodeUp' => 'Nodo Acima',
6704                           'November' => 'Novembro',
6705                           'October' => 'Outubro',
6706                           'Overview' => 'Vis@~ao geral',
6707                           'Overview:' => 'Vis@~ao geral:',
6708                           'Prev' => 'Pr@\'evio',
6709                           'Previous node' => 'Nodo anterior',
6710                           'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura',
6711                           'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel',
6712                           'Section' => 'Se@,{c}@~ao',
6713                           'Section One' => 'Se@,{c}@~ao Um',
6714                           'See %{node_file_href}' => 'Veja %{node_file_href}',
6715                           'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}',
6716                           'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6717                           'See %{reference_name}' => 'Veja %{reference_name}',
6718                           'See @cite{%{book}}' => 'Veja @cite{%{book}}',
6719                           'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}',
6720                           'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6721                           'September' => 'Setembro',
6722                           'Short Table of Contents' => 'Breve Sum@\'ario',
6723                           'Short table of contents' => 'Breve sum@\'ario',
6724                           'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro',
6725                           'Subsection One-One' => 'Subse@,{c}@~ao Um-Um',
6726                           'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es',
6727                           'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois',
6728                           'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro',
6729                           'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um',
6730                           'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es',
6731                           'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois',
6732                           'T2H_today' => '',
6733                           'Table of Contents' => 'Sum@\'ario',
6734                           'Table of contents' => 'Sum@\'ario',
6735                           'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.',
6736                           'This' => 'Esse',
6737                           '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}}}.',
6738                           '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}}}.',
6739                           '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}}}.',
6740                           'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.',
6741                           'Top' => 'Topo',
6742                           'Untitled Document' => 'Documento Sem Nome',
6743                           'Up' => 'Acima',
6744                           'Up node' => 'Nodo acima',
6745                           'Up section' => 'Se@,{c}@~ao acima',
6746                           'by @emph{%{user}}' => 'por  @emph{%{user}}',
6747                           'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}',
6748                           'current' => 'atual',
6749                           'on @emph{%{date}}' => 'em @emph{%{date}}',
6750                           'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6751                           'see %{node_file_href}' => 'veja %{node_file_href}',
6752                           'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}',
6753                           'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6754                           'see %{reference_name}' => 'veja %{reference_name}',
6755                           'see @cite{%{book}}' => 'veja @cite{%{book}}',
6756                           'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}',
6757                           'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}',
6758                           'unknown' => 'desconhecido'
6759                         };
6760
6761 $T2H_OBSOLETE_STRINGS->{'pt_BR'} = {
6762                                      'See' => 'Veja',
6763                                      'about (help)' => 'sobre (ajuda)',
6764                                      'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior',
6765                                      'cover (top) of document' => 'in@\'icio (topo) do documento',
6766                                      'current section' => 'se@,{c}@~ao atual',
6767                                      'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura',
6768                                      'following node' => 'nodo seguinte',
6769                                      'index' => '@\'indice',
6770                                      'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura',
6771                                      'next chapter' => 'pr@\'oximo cap@\'itulo',
6772                                      'next node' => 'pr@\'oximo nodo',
6773                                      'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura',
6774                                      'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel',
6775                                      'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos',
6776                                      'node up' => 'nodo acima',
6777                                      'previous node' => 'nodo anterior',
6778                                      'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura',
6779                                      'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel',
6780                                      'section' => 'Se@,{c}@~ao',
6781                                      'see' => 'veja',
6782                                      'short table of contents' => 'breve sum@\'ario',
6783                                      'table of contents' => 'sum@\'ario',
6784                                      'up node' => 'nodo acima',
6785                                      'up section' => 'se@,{c}@~ao acima'
6786                                    };
6787
6788
6789
6790 require "$ENV{T2H_HOME}/$translation_file"
6791     if ($0 =~ /\.pl$/ &&
6792         -e "$ENV{T2H_HOME}/$translation_file" && -r "$ENV{T2H_HOME}/$translation_file");
6793
6794 # set the default 'args' entry to normal for each style hash (and each command
6795 # within)
6796 my $name_index = -1;
6797 my @hash_names = ('style_map', 'style_map_pre', 'style_map_texi', 'simple_format_style_map_texi');
6798 foreach my $hash (\%style_map, \%style_map_pre, \%style_map_texi, \%simple_format_style_map_texi)
6799 {
6800     $name_index++;
6801     my $name = $hash_names[$name_index]; # name associated with hash ref
6802     foreach my $style (keys(%{$hash}))
6803     {
6804         next unless (ref($hash->{$style}) eq 'HASH');
6805         $hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'}));
6806         die "Bug: args not defined, but existing, for $style in $name" if (!defined($hash->{$style}->{'args'}));
6807 #print STDERR "DEFAULT($name, $hash) add normal as arg for $style ($hash->{$style}), $hash->{$style}->{'args'}\n";
6808     }
6809 }
6810
6811 #
6812 # Some functions used to override normal formatting functions in specific 
6813 # cases. The user shouldn't want to change them, but can use them.
6814 #
6815
6816 # used to utf8 encode the result
6817 sub t2h_utf8_accent($$$)
6818 {
6819     my $accent = shift;
6820     my $args = shift;
6821     my $style_stack = shift;
6822   
6823     my $text = $args->[0];
6824     #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n"; 
6825
6826     # special handling of @dotless{i}
6827     if ($accent eq 'dotless')
6828     { 
6829         if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
6830         {
6831              return "\x{0131}";
6832         }
6833         #return "\x{}" if ($text eq 'j'); # not found !
6834         return $text;
6835     }
6836         
6837     # FIXME \x{0131}\x{0308} for @dotless{i} @" doesn't lead to NFC 00ef.
6838     return Unicode::Normalize::NFC($text . chr(hex($unicode_diacritical{$accent}))) 
6839         if (defined($unicode_diacritical{$accent}));
6840     return ascii_accents($text, $accent);
6841 }
6842
6843 sub t2h_utf8_normal_text($$$$$)
6844 {
6845     my $text = shift;
6846     my $in_raw_text = shift;
6847     my $in_preformatted = shift;
6848     my $in_code =shift;
6849     my $style_stack = shift;
6850     $text = &$protect_text($text) unless($in_raw_text);
6851     $text = uc($text) if (in_small_caps($style_stack));
6852
6853     if (!$in_code and !$in_preformatted)
6854     {
6855         $text =~ s/---/\x{2014}/g;
6856         $text =~ s/--/\x{2013}/g;
6857         $text =~ s/``/\x{201C}/g;
6858         $text =~ s/''/\x{201D}/g;
6859     }
6860     return Unicode::Normalize::NFC($text);
6861 }
6862
6863 # these are unlikely to be used by users, as they are essentially
6864 # used to follow the html external refs specification in texinfo
6865 sub t2h_cross_manual_normal_text($$$$$)
6866 {
6867     my $text = shift;
6868     my $in_raw_text = shift;
6869     my $in_preformatted = shift;
6870     my $in_code =shift;
6871     my $style_stack = shift;
6872
6873     $text = uc($text) if (in_small_caps($style_stack));
6874     return $text if ($USE_UNICODE);
6875
6876     # if there is no unicode support, we do all the transformations here
6877     my $result = '';
6878     while ($text ne '')
6879     {
6880         if ($text =~ s/^([A-Za-z0-9]+)//o)
6881         {
6882              $result .= $1;
6883         }
6884         elsif ($text =~ s/^ //o)
6885         {
6886              $result .= '-';
6887         }
6888         elsif ($text =~ s/^(.)//o)
6889         {
6890              if (exists($ascii_character_map{$1}))
6891              {
6892                  $result .= '_' . lc($ascii_character_map{$1});
6893              }
6894              else
6895              { # wild guess that should work for latin1
6896                   $result .= '_' . '00' . lc(sprintf("%02x",ord($1)));
6897              }
6898         }
6899         else
6900         {
6901              print STDERR "Bug: unknown character in cross ref (likely in infinite loop)\n";
6902              sleep 1;
6903         }
6904     }
6905    
6906     return $result;
6907 }
6908
6909 sub t2h_nounicode_cross_manual_accent($$$)
6910 {
6911     my $accent = shift;
6912     my $args = shift;
6913     my $style_stack = shift;
6914                                                                                 
6915     my $text = $args->[0];
6916
6917     if ($accent eq 'dotless')
6918     { 
6919         if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
6920         {
6921              return "_0131";
6922         }
6923         #return "\x{}" if ($text eq 'j'); # not found !
6924         return $text;
6925     }
6926     return '_' . lc($unicode_accents{$accent}->{$text})
6927         if (defined($unicode_accents{$accent}->{$text}));
6928     return ($text . '_' . lc($unicode_diacritical{$accent})) 
6929         if (defined($unicode_diacritical{$accent}));
6930     return ascii_accents($text, $accent);
6931 }
6932
6933 sub t2h_transliterate_cross_manual_accent($$)
6934 {
6935     my $accent = shift;
6936     my $args = shift;
6937                                                                                 
6938     my $text = $args->[0];
6939
6940     if (exists($unicode_accents{$accent}->{$text}) and
6941         exists ($transliterate_map{$unicode_accents{$accent}->{$text}}))
6942     {
6943          return $transliterate_map{$unicode_accents{$accent}->{$text}};
6944     }
6945     return $text;
6946 }
6947
6948
6949 } # end package Texi2HTML::Config
6950
6951 use vars qw(
6952 %value
6953 );
6954
6955 # variables which might be redefined by the user but aren't likely to be  
6956 # they seem to be in the main namespace
6957 use vars qw(
6958 %index_names
6959 %predefined_index
6960 %valid_index
6961 %sec2level
6962 %code_style_map
6963 %region_lines
6964 %forbidden_index_name
6965 );
6966
6967 # Some global variables are set in the script, and used in the subroutines
6968 # they are in the Texi2HTML namespace, thus prefixed with Texi2HTML::.
6969 # see texi2html.init for details.
6970
6971 #+++############################################################################
6972 #                                                                              #
6973 # Initialization                                                               #
6974 # Pasted content of File $(srcdir)/MySimple.pm: Command-line processing        #
6975 #                                                                              #
6976 #---############################################################################
6977
6978 # leave this within comments, and keep the require statement
6979 # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/texi2html.init
6980 # exists.
6981
6982 # @MYSIMPLE@
6983 package Getopt::MySimple;
6984
6985 # Name:
6986 #       Getopt::MySimple.
6987 #
6988 # Documentation:
6989 #       POD-style (incomplete) documentation is in file MySimple.pod
6990 #
6991 # Tabs:
6992 #       4 spaces || die.
6993 #
6994 # Author:
6995 #       Ron Savage      rpsavage@ozemail.com.au.
6996 #       1.00    19-Aug-97       Initial version.
6997 #       1.10    13-Oct-97       Add arrays of switches (eg '=s@').
6998 #       1.20     3-Dec-97       Add 'Help' on a per-switch basis.
6999 #       1.30    11-Dec-97       Change 'Help' to 'verbose'. Make all hash keys lowercase.
7000 #       1.40    10-Nov-98       Change width of help report. Restructure tests.
7001 #               1-Jul-00        Modifications for Texi2html
7002
7003 # --------------------------------------------------------------------------
7004 # Locally modified by obachman (Display type instead of env, order by cmp)
7005 # $Id: MySimple.pm,v 1.5 2006/04/17 23:11:09 pertusus Exp $
7006
7007 # use strict;
7008 # no strict 'refs';
7009
7010 use vars qw(@EXPORT @EXPORT_OK @ISA);
7011 use vars qw($fieldWidth $opt $VERSION);
7012
7013 use Exporter();
7014 use Getopt::Long;
7015
7016 @ISA            = qw(Exporter);
7017 @EXPORT         = qw();
7018 @EXPORT_OK      = qw($opt);     # An alias for $self -> {'opt'}.
7019
7020 # --------------------------------------------------------------------------
7021
7022 $fieldWidth     = 20;
7023 $VERSION        = '1.41';
7024
7025 # --------------------------------------------------------------------------
7026
7027 sub byOrder
7028 {
7029         my($self) = @_;
7030         
7031         return uc($a) cmp (uc($b));
7032 }
7033
7034 # --------------------------------------------------------------------------
7035
7036 sub dumpOptions
7037 {
7038         my($self) = @_;
7039
7040         print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n";
7041
7042         for (sort byOrder keys(%{$self -> {'opt'} }) )
7043         {
7044           print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n";
7045         }
7046
7047         print "\n";
7048
7049 }       # End of dumpOptions.
7050
7051 # --------------------------------------------------------------------------
7052 # Return:
7053 #       0 -> Error.
7054 #       1 -> Ok.
7055
7056 sub getOptions
7057 {
7058         push(@_, 0) if ($#_ == 2);      # Default for $ignoreCase is 0.
7059         push(@_, 1) if ($#_ == 3);      # Default for $helpThenExit is 1.
7060
7061         my($self, $default, $helpText, $versionText, 
7062            $helpThenExit, $versionThenExit, $ignoreCase) = @_;
7063         
7064         $helpThenExit = 1 unless (defined($helpThenExit));
7065         $versionThenExit = 1 unless (defined($versionThenExit));
7066         $ignoreCase = 0 unless (defined($ignoreCase));
7067
7068         $self -> {'default'}            = $default;
7069         $self -> {'helpText'}           = $helpText;
7070         $self -> {'versionText'}        = $versionText;
7071         $Getopt::Long::ignorecase       = $ignoreCase;
7072
7073         unless (defined($self -> {'default'}{'help'}))
7074         {
7075           $self -> {'default'}{'help'} = 
7076           { 
7077            type => ':i', 
7078            default => '',
7079            linkage => sub {$self->helpOptions($_[1]); sleep 5;exit (0) if $helpThenExit;},
7080            verbose => "print help and exit"
7081           };
7082         }
7083
7084         unless (defined($self -> {'default'}{'version'}))
7085         {
7086           $self -> {'default'}{'version'} = 
7087           { 
7088            type => '', 
7089            default => '',
7090            linkage => sub {print $self->{'versionText'};  exit (0) if $versionThenExit;},
7091            verbose => "print version and exit"
7092           };
7093         }
7094
7095         for (keys(%{$self -> {'default'} }) )
7096         {
7097           next unless (ref(${$self -> {'default'} }{$_}) eq 'HASH');
7098           my $type = ${$self -> {'default'} }{$_}{'type'};
7099           push(@{$self -> {'type'} }, "$_$type");
7100           $self->{'opt'}->{$_} =  ${$self -> {'default'} }{$_}{'linkage'}
7101             if ${$self -> {'default'} }{$_}{'linkage'};
7102         }
7103
7104         my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} });
7105
7106         return $result unless $result;
7107
7108         for (keys(%{$self -> {'default'} }) )
7109         {
7110            if (! defined(${$self -> {'opt'} }{$_})) #{
7111             {
7112              ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'};
7113             }
7114         }
7115
7116         $result;
7117 }       # End of getOptions.
7118
7119 # --------------------------------------------------------------------------
7120
7121 sub helpOptions
7122 {
7123         my($self) = shift;
7124         my($noHelp) = shift;
7125         $noHelp = 0 unless $noHelp;
7126         my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth) 
7127           = (10, 5, 9, 78, 4, 11);
7128
7129         print "$self->{'helpText'}" if ($self -> {'helpText'});
7130
7131         print ' Option', ' ' x ($optwidth - length('Option') -1 ),
7132                 'Type', ' ' x ($typewidth - length('Type') + 1),
7133                 'Default', ' ' x ($defaultwidth - length('Default') ),
7134                 "Description\n";
7135
7136         for (sort byOrder keys(%{$self -> {'default'} }) )
7137         {
7138           my($line, $help, $option, $val);
7139           $option = $_;
7140           next if ${$self->{'default'} }{$_}{'noHelp'} && ${$self->{'default'} }{$_}{'noHelp'} > $noHelp;
7141           #$line = " -$_" . ' ' x ($optwidth - (2 + length) ) .
7142           #             "${$self->{'default'} }{$_}{'type'} ".
7143           #             ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
7144                 $line = " --$_" . "${$self->{'default'} }{$_}{'type'}".
7145                         ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) ));
7146
7147                  $val = ${$self->{'default'} }{$_}{'linkage'};
7148                 if ($val)
7149                 {
7150                   if ((ref($val) eq 'SCALAR') and (defined($$val)))
7151                   {
7152                     $val = $$val; 
7153                   }
7154                   else
7155                   {
7156                     $val = '';
7157                   }
7158                 }
7159                 elsif (defined(${$self->{'default'} }{$_}{'default'}))
7160                 {
7161                   $val = ${$self->{'default'} }{$_}{'default'};
7162                 }
7163                 else
7164                 {
7165                   $val = '';
7166                 }
7167                 $line .= "$val  ";
7168                 $line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line));
7169                 
7170                 if (defined(${$self -> {'default'} }{$_}{'verbose'}) &&
7171                   ${$self -> {'default'} }{$_}{'verbose'} ne '')
7172               {
7173                 $help = "${$self->{'default'} }{$_}{'verbose'}";
7174               }
7175               else
7176               {
7177                 $help = ' ';
7178               }
7179               if ((length("$line") + length($help)) < $maxlinewidth)
7180               {
7181                 print $line , $help, "\n";
7182               }
7183               else
7184               {
7185                 print $line, "\n", ' ' x $valind, $help, "\n";
7186               }
7187               for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}}))
7188               {
7189                 print ' ' x ($valind + 2);
7190                 print $val, '  ', ' ' x ($valwidth - length($val) - 2);
7191                 print ${$self->{'default'}}{$option}{'values'}{$val}, "\n";
7192               }
7193         }
7194
7195         print <<EOT;
7196 Note: 'Options' may be abbreviated. 'Type' specifications mean:
7197  <none>| !    no argument: variable is set to 1 on -foo (or, to 0 on -nofoo)
7198     =s | :s   mandatory (or, optional)  string argument
7199     =i | :i   mandatory (or, optional)  integer argument
7200 EOT
7201 }       # End of helpOptions.
7202
7203 #-------------------------------------------------------------------
7204
7205 sub new
7206 {
7207         my($class)                              = @_;
7208         my($self)                               = {};
7209         $self -> {'default'}    = {};
7210         $self -> {'helpText'}   = '';
7211         $self -> {'opt'}                = {};
7212         $opt                                    = $self -> {'opt'};      # An alias for $self -> {'opt'}.
7213         $self -> {'type'}               = ();
7214
7215         return bless $self, $class;
7216
7217 }       # End of new.
7218
7219 # --------------------------------------------------------------------------
7220
7221 1;
7222
7223 # End MySimple.pm
7224
7225 require "$ENV{T2H_HOME}/MySimple.pm"
7226     if ($0 =~ /\.pl$/ &&
7227         -e "$ENV{T2H_HOME}/MySimple.pm" && -r "$ENV{T2H_HOME}/MySimple.pm");
7228
7229 #+++########################################################################
7230 #                                                                          #
7231 # Initialization                                                           #
7232 # Pasted content of File $(srcdir)/T2h_i18n.pm: Internationalisation       #
7233 #                                                                          #
7234 #---########################################################################
7235
7236 # leave this within comments, and keep the require statement
7237 # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_i18n.pm
7238 # exists.
7239
7240 # @T2H_I18N@
7241 #+##############################################################################
7242 #
7243 # T2h_i18n.pm: Internationalization for texi2html
7244 #
7245 #    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
7246 #                             Derek Price <derek@ximbiot.com>,
7247 #                             Adrian Aichner <adrian@xemacs.org>,
7248 #                           & others.
7249 #
7250 #    This program is free software; you can redistribute it and/or modify
7251 #    it under the terms of the GNU General Public License as published by
7252 #    the Free Software Foundation; either version 2 of the License, or
7253 #    (at your option) any later version.
7254 #
7255 #    This program is distributed in the hope that it will be useful,
7256 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
7257 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7258 #    GNU General Public License for more details.
7259 #
7260 #    You should have received a copy of the GNU General Public License
7261 #    along with this program; if not, write to the Free Software
7262 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
7263 #
7264 #-##############################################################################
7265
7266 # This requires perl version 5 or higher
7267 require 5.0;
7268
7269 package Texi2HTML::I18n;
7270
7271 use strict;
7272
7273 use vars qw(
7274 @ISA
7275 @EXPORT
7276 );
7277
7278 use Exporter;
7279 @ISA = qw(Exporter);
7280 @EXPORT = qw(pretty_date);
7281
7282 my $language;
7283 my $i18n_dir = 'i18n'; # name of the directory containing the per language files
7284 #my $translation_file = 'translations.pl'; # file containing all the translations
7285 #my @known_languages = ('de', 'nl', 'es', 'no', 'pt', 'fr'); # The supported
7286                                                # languages
7287
7288 ########################################################################
7289 # Language dependencies:
7290 # To add a new language extend the WORDS hash and create $T2H_<...>_WORDS hash
7291 # To redefine one word, simply do:
7292 # $T2h_i18n::T2H_LANGUAGES->{<language>}->{<word>} = 'whatever' in your personal init file.
7293 #
7294
7295 # Those hashes are obsolete but retained here for reference
7296
7297 my $T2H_WORDS_EN =
7298 {
7299  # titles  of pages
7300  #'Table of Contents'       => 'Table of Contents',
7301  #'Short Table of Contents'  => 'Short Table of Contents',
7302  #'Index'     => 'Index',
7303  #'About This Document'     => 'About This Document',
7304  #'Footnotes' => 'Footnotes',
7305  #'See'             => 'See',
7306  #'see'             => 'see',
7307  #'section'         => 'section',
7308  'About This Document'       => '',
7309  'Table of Contents'         => '',
7310  'Short Table of Contents',  => '',
7311  'Index'                     => '',
7312  'Footnotes'                 => '',
7313  'See'                       => '',
7314  'see'                       => '',
7315  'section'                   => '',
7316  'Top'                       => '',
7317  'Untitled Document'         => '',
7318  # If necessary, we could extend this as follows:
7319  #  # text for buttons
7320  #  'Top_Button' => 'Top',
7321  #  'ToC_Button' => 'Contents',
7322  #  'Overview_Button' => 'Overview',
7323  #  'Index_button' => 'Index',
7324  #  'Back_Button' => 'Back',
7325  #  'FastBack_Button' => 'FastBack',
7326  #  'Prev_Button' => 'Prev',
7327  #  'Up_Button' => 'Up',
7328  #  'Next_Button' => 'Next',
7329  #  'Forward_Button' =>'Forward',
7330  #  'FastWorward_Button' => 'FastForward',
7331  #  'First_Button' => 'First',
7332  #  'Last_Button' => 'Last',
7333  #  'About_Button' => 'About'
7334  'January' => '', 
7335  'February' => '',
7336  'March' => '', 
7337  'April' => '',
7338  'May' => '',
7339  'June' => '',
7340  'July' => '',
7341  'August' => '',
7342  'September' => '',
7343  'October' => '',
7344  'November' => '',
7345  'December' => '', 
7346  'T2H_today' => '%s, %d %d',
7347 };
7348
7349 my $T2H_WORDS_DE =
7350 {
7351  'Table of Contents'       => 'Inhaltsverzeichniss',
7352  'Short Table of Contents'  => 'Kurzes Inhaltsverzeichniss',
7353  'Index'     => 'Index',
7354  'About This Document'     => '&Uuml;ber dieses Dokument',
7355  'Footnotes' => 'Fu&szlig;noten',
7356  'See'             => 'Siehe',
7357  'see'             => 'siehe',
7358  'section'         => 'Abschnitt',
7359  'January' => 'Januar', 
7360  'February' => 'Februar',
7361  'March' => 'M&auml;rz', 
7362  'April' => 'April',
7363  'May' => 'Mai',
7364  'June' => 'Juni',
7365  'July' => 'Juli',
7366  'August' => 'August',
7367  'September' => 'September',
7368  'October' => 'Oktober',
7369  'November' => 'November',
7370  'December' => 'Dezember', 
7371 };
7372
7373 my $T2H_WORDS_NL =
7374 {
7375  'Table of Contents'       => 'Inhoudsopgave',
7376  'Short Table of Contents'  => 'Korte inhoudsopgave',
7377  'Index'     => 'Index',      #Not sure ;-)
7378  'About This Document'     => 'No translation available!', #No translation available!
7379  'Footnotes' => 'No translation available!', #No translation available!
7380  'See'             => 'Zie',
7381  'see'             => 'zie',
7382  'section'         => 'sectie',
7383  'January' => 'Januari', 
7384  'February' => 'Februari',
7385  'March' => 'Maart', 
7386  'April' => 'April',
7387  'May' => 'Mei',
7388  'June' => 'Juni',
7389  'July' => 'Juli',
7390  'August' => 'Augustus',
7391  'September' => 'September',
7392  'October' => 'Oktober',
7393  'November' => 'November',
7394  'December' => 'December', 
7395 };
7396
7397 my $T2H_WORDS_ES =
7398 {
7399  'Table of Contents'       => '&iacute;ndice General',
7400  'Short Table of Contents'  => 'Resumen del Contenido',
7401  'Index'     => 'Index',      #Not sure ;-)
7402  'About This Document'     => 'No translation available!', #No translation available!
7403  'Footnotes' => 'Fu&szlig;noten',
7404  'See'             => 'V&eacute;ase',
7405  'see'             => 'v&eacute;ase',
7406  'section'         => 'secci&oacute;n',
7407  'January' => 'enero', 
7408  'February' => 'febrero',
7409  'March' => 'marzo', 
7410  'April' => 'abril',
7411  'May' => 'mayo',
7412  'June' => 'junio',
7413  'July' => 'julio',
7414  'August' => 'agosto',
7415  'September' => 'septiembre',
7416  'October' => 'octubre',
7417  'November' => 'noviembre',
7418  'December' => 'diciembre', 
7419 };
7420
7421 my $T2H_WORDS_NO =
7422 {
7423  'Table of Contents'       => 'Innholdsfortegnelse',
7424  'Short Table of Contents'  => 'Kort innholdsfortegnelse',
7425  'Index'     => 'Indeks',     #Not sure ;-)
7426  'About This Document'     => 'No translation available!', #No translation available!
7427  'Footnotes' => 'No translation available!',
7428  'See'             => 'Se',
7429  'see'             => 'se',
7430  'section'         => 'avsnitt',
7431  'January' => 'januar', 
7432  'February' => 'februar',
7433  'March' => 'mars', 
7434  'April' => 'april',
7435  'May' => 'mai',
7436  'June' => 'juni',
7437  'July' => 'juli',
7438  'August' => 'august',
7439  'September' => 'september',
7440  'October' => 'oktober',
7441  'November' => 'november',
7442  'December' => 'desember', 
7443 };
7444
7445 my $T2H_WORDS_PT =
7446 {
7447  'Table of Contents'       => 'Sum&aacute;rio',
7448  'Short Table of Contents'  => 'Breve Sum&aacute;rio',
7449  'Index'     => '&Iacute;ndice', #Not sure ;-)
7450  'About This Document'     => 'No translation available!', #No translation available!
7451  'Footnotes' => 'No translation available!',
7452  'See'             => 'Veja',
7453  'see'             => 'veja',
7454  'section'         => 'Se&ccedil;&atilde;o',
7455  'January' => 'Janeiro', 
7456  'February' => 'Fevereiro',
7457  'March' => 'Mar&ccedil;o', 
7458  'April' => 'Abril',
7459  'May' => 'Maio',
7460  'June' => 'Junho',
7461  'July' => 'Julho',
7462  'August' => 'Agosto',
7463  'September' => 'Setembro',
7464  'October' => 'Outubro',
7465  'November' => 'Novembro',
7466  'December' => 'Dezembro', 
7467 };
7468
7469 my $T2H_WORDS_FR =
7470 {
7471  'Table of Contents'       => 'Table des mati&egrave;res',
7472  'Short Table of Contents'  => 'R&eacute;sum&eacute;e du contenu',
7473  'Index'     => 'Index',
7474  'About This Document'     => 'A propos de ce document',
7475  'Footnotes' => 'Notes de bas de page',
7476  'See'             => 'Voir',
7477  'see'             => 'voir',
7478  'section'         => 'section',
7479  'January' => 'Janvier', 
7480  'February' => 'F&eacute;vrier',
7481  'March' => 'Mars', 
7482  'April' => 'Avril',
7483  'May' => 'Mai',
7484  'June' => 'Juin',
7485  'July' => 'Juillet',
7486  'August' => 'Ao&ucirc;t',
7487  'September' => 'Septembre',
7488  'October' => 'Octobre',
7489  'November' => 'Novembre',
7490  'December' => 'D&eacute;cembre', 
7491  'T2H_today' => 'le %2$d %1$s %3$d'
7492 };
7493
7494 #$T2H_LANGUAGES =
7495 #{
7496 # 'en' => $T2H_WORDS_EN,
7497 # 'de' => $T2H_WORDS_DE,
7498 # 'nl' => $T2H_WORDS_NL,
7499 # 'es' => $T2H_WORDS_ES,
7500 # 'no' => $T2H_WORDS_NO,
7501 # 'pt' => $T2H_WORDS_PT,
7502 # 'fr' => $T2H_WORDS_FR,
7503 #};
7504
7505 sub set_language($)
7506 {
7507     my $lang = shift;
7508     if (defined($lang) && exists($Texi2HTML::Config::LANGUAGES->{$lang}) && defined($Texi2HTML::Config::LANGUAGES->{$lang}))
7509     {
7510          $language = $lang;
7511          return 1;
7512     }
7513     else
7514     {
7515          return 0;
7516     }
7517 }
7518
7519
7520 my @MONTH_NAMES =
7521     (
7522      'January', 'February', 'March', 'April', 'May',
7523      'June', 'July', 'August', 'September', 'October',
7524      'November', 'December'
7525     );
7526
7527 my $I = \&get_string;
7528
7529 sub pretty_date($) 
7530 {
7531     my $lang = shift;
7532     my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
7533
7534     ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
7535     $year += ($year < 70) ? 2000 : 1900;
7536     # obachman: Let's do it as the Americans do
7537     #return($MONTH_NAMES->{$lang}[$mon] . ", " . $mday . " " . $year);
7538         #return(sprintf(&$I('T2H_today'), (get_string($MONTH_NAMES[$mon]), $mday, $year)));
7539         return &$I('%{month}, %{day} %{year}', { 'month' => get_string($MONTH_NAMES[$mon]),
7540           'day' => $mday, 'year' => $year });
7541 }
7542
7543 my $error_no_en = 0;
7544 sub get_string($;$$)
7545 {
7546     my $string = shift;
7547     my $arguments = shift;
7548     my $state = shift;
7549     my $T2H_LANGUAGES = $Texi2HTML::Config::LANGUAGES;
7550     if (! exists($T2H_LANGUAGES->{'en'}))
7551     {
7552         unless($error_no_en)
7553         {
7554             print STDERR "i18n: no LANGUAGES->{'en'} hash\n";
7555             $error_no_en = 1;
7556         }
7557     }
7558     else
7559     {
7560         print STDERR "i18n: missing string $string\n" unless (exists ($T2H_LANGUAGES->{'en'}->{$string}));
7561         if (defined ($T2H_LANGUAGES->{$language}->{$string}) and
7562            ($T2H_LANGUAGES->{$language}->{$string} ne ''))
7563         {
7564             $string = $T2H_LANGUAGES->{$language}->{$string};
7565         }
7566         elsif (defined ($T2H_LANGUAGES->{'en'}->{$string}) and
7567             ($T2H_LANGUAGES->{'en'}->{$string} ne ''))
7568         {
7569             $string = $T2H_LANGUAGES->{'en'}->{$string};
7570         }
7571     }
7572     return main::substitute_line($string, $state) unless (defined($arguments) or !keys(%$arguments));
7573     # if there are arguments, we must protect the %{arg} constructs before
7574     # doing substitute_line. So there is a first pass here to change %{arg} 
7575     # to %@{arg@}
7576     my $result = '';
7577     if (!$state->{'keep_texi'})
7578     {
7579         while ($string)
7580         {
7581             if ($string =~ s/^([^%]*)%//)
7582             {
7583                 $result .= $1 if (defined($1));
7584                 $result .= '%';
7585                 if ($string =~ s/^%//)
7586                 {
7587                      $result .= '%';
7588                 }
7589                 elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
7590                 {
7591                      $string =~ s/^\{(\w+)\}//;
7592                      $result .= "\@\{$1\@\}";
7593                 }
7594                 else
7595                 {
7596                      $result .= '%';
7597                 }
7598                 next;
7599             }
7600             else 
7601             {   
7602                 $result .= $string;
7603                 last;
7604             }
7605         }
7606         $string = main::substitute_line($result, $state);
7607     }
7608     # now we substitute the arguments 
7609     $result = '';
7610     while ($string)
7611     {
7612         if ($string =~ s/^([^%]*)%//)
7613         {
7614             $result .= $1 if (defined($1));
7615             if ($string =~ s/^%//)
7616             {
7617                  $result .= '%';
7618             }
7619             elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
7620             {
7621                  $string =~ s/^\{(\w+)\}//;
7622                  $result .= $arguments->{$1};
7623             }
7624             else
7625             {
7626                  $result .= '%';
7627             }
7628             next;
7629         }
7630         else 
7631         {   
7632             $result .= $string;
7633             last;
7634         }
7635     }
7636     return $result;
7637 }
7638
7639 1;
7640 require "$ENV{T2H_HOME}/T2h_i18n.pm"
7641     if ($0 =~ /\.pl$/ &&
7642         -e "$ENV{T2H_HOME}/T2h_i18n.pm" && -r "$ENV{T2H_HOME}/T2h_i18n.pm");
7643
7644
7645 #########################################################################
7646 #
7647 # latex2html stuff
7648 #
7649 #---######################################################################
7650
7651 {
7652 # leave this within comments, and keep the require statement
7653 # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_l2h.pm
7654 # exists.
7655
7656 # @T2H_L2H@
7657 #+##############################################################################
7658 #
7659 # T2h_l2h.pm: interface to LaTeX2HTML
7660 #
7661 #    Copyright (C) 1999-2005  Patrice Dumas <dumas@centre-cired.fr>,
7662 #                             Derek Price <derek@ximbiot.com>,
7663 #                             Adrian Aichner <adrian@xemacs.org>,
7664 #                           & others.
7665 #
7666 #    This program is free software; you can redistribute it and/or modify
7667 #    it under the terms of the GNU General Public License as published by
7668 #    the Free Software Foundation; either version 2 of the License, or
7669 #    (at your option) any later version.
7670 #
7671 #    This program is distributed in the hope that it will be useful,
7672 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
7673 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7674 #    GNU General Public License for more details.
7675 #
7676 #    You should have received a copy of the GNU General Public License
7677 #    along with this program; if not, write to the Free Software
7678 #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
7679 #    02110-1301  USA
7680 #
7681 #-##############################################################################
7682
7683 require 5.0;
7684 use strict;
7685
7686 package Texi2HTML::LaTeX2HTML;
7687 use Cwd;
7688
7689
7690 # latex2html conversions consist of three stages:
7691 # 1) ToLatex: Put "latex" code into a latex file
7692 # 2) ToHtml: Use latex2html to generate corresponding html code and images
7693 # 3) FromHtml: Extract generated code and images from latex2html run
7694 #
7695
7696 # init l2h defaults for files and names
7697
7698 # global variable used for caching
7699 use vars qw(
7700             %l2h_cache
7701            );
7702
7703 my ($l2h_name, $l2h_latex_file, $l2h_cache_file, $l2h_html_file, $l2h_prefix);
7704
7705 # holds the status of latex2html operations. If 0 it means that there was 
7706 # an error
7707 my $status = 0;
7708
7709 my $debug;
7710 my $verbose;
7711 my $docu_rdir;
7712 my $docu_name;
7713 my $docu_ext;
7714 my $ERROR = '***';
7715
7716 ##########################
7717 #
7718 # First stage: Generation of Latex file
7719 # Initialize with: init
7720 # Add content with: to_latex ($text) --> HTML placeholder comment
7721 # Finish with: finish_to_latex
7722 #
7723
7724 my $l2h_latex_preamble = <<EOT;
7725 % This document was automatically generated by the l2h extenstion of texi2html
7726 % DO NOT EDIT !!!
7727 \\documentclass{article}
7728 \\usepackage{html}
7729 \\begin{document}
7730 EOT
7731
7732 my $l2h_latex_closing = <<EOT;
7733 \\end{document}
7734 EOT
7735
7736 my %l2h_to_latex = ();         # associate a latex text with the index in the
7737                                # html result array.
7738 my @l2h_to_latex = ();         # array used to associate the index with 
7739                                # the original latex text.
7740 my $latex_count = 0;           # number of latex texts really stored
7741 my $latex_converted_count = 0; # number of latex texts passed through latex2html
7742 my $to_latex_count = 0;        # total number of latex texts processed
7743 my $cached_count = 0;          # number of cached latex texts
7744 %l2h_cache = ();               # the cache hash. Associate latex text with 
7745                                # html from the previous run
7746 my @l2h_from_html;             # array of resulting html
7747
7748 my %global_count = ();         # associate a command name and the 
7749                                # corresponding counter to the index in the
7750                                # html result array
7751
7752 # set $status to 1, if l2h could be initalized properly, to 0 otherwise
7753 sub init()
7754 {
7755     $docu_name = $Texi2HTML::THISDOC{'file_base_name'};
7756     $docu_rdir = $Texi2HTML::THISDOC{'out_dir'};
7757     $docu_ext = $Texi2HTML::THISDOC{'extension'};
7758     $l2h_name =  "${docu_name}_l2h";
7759     $l2h_latex_file = "$docu_rdir${l2h_name}.tex";
7760     $l2h_cache_file = "${docu_rdir}${docu_name}-l2h_cache.pm";
7761     # destination dir -- generated images are put there, should be the same
7762     # as dir of enclosing html document --
7763     $l2h_html_file = "$docu_rdir${l2h_name}.html";
7764     $l2h_prefix = "${l2h_name}_";
7765     $debug = $Texi2HTML::THISDOC{'debug_l2h'};
7766     $verbose = $Texi2HTML::Config::VERBOSE;
7767
7768     unless ($Texi2HTML::Config::L2H_SKIP)
7769     {
7770         unless (open(L2H_LATEX, ">$l2h_latex_file"))
7771         {
7772             warn "$ERROR l2h: Can't open latex file '$l2h_latex_file' for writing: $!\n";
7773             $status = 0;
7774             return;
7775         }
7776         warn "# l2h: use ${l2h_latex_file} as latex file\n" if ($verbose);
7777         print L2H_LATEX $l2h_latex_preamble;
7778     }
7779     # open the database that holds cached text
7780     init_cache();
7781     $status = 1;
7782 }
7783
7784
7785 # print text (2nd arg) into latex file (if not already there nor in cache)
7786 # which can be later on replaced by the latex2html generated text.
7787
7788 sub to_latex($$$)
7789 {
7790     my $command = shift;
7791     my $text = shift;
7792     my $counter = shift;
7793     if ($command eq 'tex')
7794     {
7795         $text .= ' ';
7796     }
7797     elsif ($command eq 'math') 
7798     {
7799         $text = "\$".$text."\$";
7800     }
7801     $to_latex_count++;
7802     $text =~ s/(\s*)$//;
7803     # try whether we have text already on things to do
7804     my $count = $l2h_to_latex{$text};
7805     unless ($count)
7806     {
7807         $latex_count++;
7808         $count = $latex_count;
7809         # try whether we can get it from cache
7810         my $cached_text = from_cache($text);
7811         if (defined($cached_text))
7812         {
7813              $cached_count++;
7814              # put the cached result in the html result array
7815              $l2h_from_html[$count] = $cached_text;
7816         }
7817         else
7818         {
7819              $latex_converted_count++;
7820              unless ($Texi2HTML::Config::L2H_SKIP)
7821              {
7822                  print L2H_LATEX "\\begin{rawhtml}\n";
7823                  print L2H_LATEX "<!-- l2h_begin $l2h_name $count -->\n";
7824                  print L2H_LATEX "\\end{rawhtml}\n";
7825
7826                  print L2H_LATEX "$text\n";
7827
7828                  print L2H_LATEX "\\begin{rawhtml}\n";
7829                  print L2H_LATEX "<!-- l2h_end $l2h_name $count -->\n";
7830                  print L2H_LATEX "\\end{rawhtml}\n";
7831             }
7832         }
7833         $l2h_to_latex[$count] = $text;
7834         $l2h_to_latex{$text} = $count;
7835     }
7836     $global_count{"${command}_$counter"} = $count; 
7837     return 1;
7838 }
7839
7840 # print closing into latex file and close it
7841 sub finish_to_latex()
7842 {
7843     my $reused = $to_latex_count - $latex_converted_count - $cached_count;
7844     unless ($Texi2HTML::Config::L2H_SKIP)
7845     {
7846         print L2H_LATEX $l2h_latex_closing;
7847         close (L2H_LATEX);
7848     }
7849     warn "# l2h: finished to latex ($cached_count cached, $reused reused, $latex_converted_count to process)\n" if ($verbose);
7850     unless ($latex_count)
7851     {
7852         # no @tex nor @math
7853         finish();
7854         return 0;
7855     }
7856     return 1;
7857 }
7858
7859 ###################################
7860 # Second stage: Use latex2html to generate corresponding html code and images
7861 #
7862 # to_html([$l2h_latex_file, [$l2h_html_dir]]):
7863 #   Call latex2html on $l2h_latex_file
7864 #   Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir
7865 #   Return 1, on success
7866 #          0, otherwise
7867 #
7868 sub to_html()
7869 {
7870     my ($call, $dotbug);
7871     # when there are no tex constructs to convert (happens in case everything
7872     # comes from the cache), there is no latex2html run
7873     if ($Texi2HTML::Config::L2H_SKIP or ($latex_converted_count == 0))
7874     {
7875         warn "# l2h: skipping latex2html run\n" if ($verbose);
7876         return 1;
7877     }
7878     # Check for dot in directory where dvips will work
7879     if ($Texi2HTML::Config::L2H_TMP)
7880     {
7881         if ($Texi2HTML::Config::L2H_TMP =~ /\./)
7882         {
7883             warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
7884             $dotbug = 1;
7885         }
7886     }
7887     else
7888     {
7889         if (cwd() =~ /\./)
7890         {
7891             warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
7892             $dotbug = 1;
7893         }
7894     }
7895     # fix it, if necessary and hope that it works
7896     $Texi2HTML::Config::L2H_TMP = "/tmp" if ($dotbug);
7897
7898     $call = $Texi2HTML::Config::L2H_L2H;
7899     # use init file, if specified
7900     my $init_file = main::locate_init_file($Texi2HTML::Config::L2H_FILE);
7901     $call = $call . " -init_file " . $init_file if ($init_file);
7902     # set output dir
7903     $call .=  ($docu_rdir ? " -dir $docu_rdir" : " -no_subdir");
7904     # use l2h_tmp, if specified
7905     $call .= " -tmp $Texi2HTML::Config::L2H_TMP" if ($Texi2HTML::Config::L2H_TMP);
7906     # use a given html version if specified
7907     $call .= " -html_version $Texi2HTML::Config::L2H_HTML_VERSION" if ($Texi2HTML::Config::L2H_HTML_VERSION);
7908     # options we want to be sure of
7909     $call .= " -address 0 -info 0 -split 0 -no_navigation -no_auto_link";
7910     $call .= " -prefix $l2h_prefix $l2h_latex_file";
7911
7912     warn "# l2h: executing '$call'\n" if ($verbose);
7913     if (system($call))
7914     {
7915         warn "$ERROR l2h: '${call}' did not succeed\n";
7916         return 0;
7917     }
7918     else
7919     {
7920         warn "# l2h: latex2html finished successfully\n" if ($verbose);
7921         return 1;
7922     }
7923 }
7924
7925 ##########################
7926 # Third stage: Extract generated contents from latex2html run
7927 # Initialize with: init_from_html
7928 #   open $l2h_html_file for reading
7929 #   reads in contents into array indexed by numbers
7930 #   return 1,  on success -- 0, otherwise
7931 # Finish with: finish
7932 #   closes $l2h_html_dir/$l2h_name.".$docu_ext"
7933
7934 # the images generated by latex2html have names like ${docu_name}_l2h_img?.png
7935 # they are copied to ${docu_name}_?.png, and html is changed accordingly.
7936 my %l2h_img;            # associate src file to destination file
7937                         # such that files are not copied twice
7938 my $image_count = 1;
7939 sub change_image_file_names($)
7940 {
7941     my $content = shift;
7942     my @images = ($content =~ /SRC="(.*?)"/g);
7943     my ($src, $dest);
7944
7945     for $src (@images)
7946     {
7947         $dest = $l2h_img{$src};
7948         unless ($dest)
7949         {
7950             my $ext = '';
7951             if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
7952             {
7953                 $ext = ".$1";
7954             }
7955             else
7956             {
7957                 warn "$ERROR: L2h image $src has invalid extension\n";
7958                 next;
7959             }
7960             while (-e "$docu_rdir${docu_name}_${image_count}$ext")
7961             {
7962                 $image_count++;
7963             }
7964             $dest = "${docu_name}_${image_count}$ext";
7965 # FIXME this isn't portable. + error condition not checked.
7966             system("cp -f $docu_rdir$src $docu_rdir$dest");
7967             $l2h_img{$src} = $dest;
7968 # FIXME error condition not checked
7969             unlink "$docu_rdir$src" unless ($debug);
7970         }
7971         $content =~ s/SRC="$src"/SRC="$dest"/g;
7972     }
7973     return $content;
7974 }
7975
7976 my $extract_error_count = 0;
7977 my $invalid_counter_count = 0;
7978
7979 sub init_from_html()
7980 {
7981     # when there are no tex constructs to convert (happens in case everything
7982     # comes from the cache), the html file that was generated by previous
7983     # latex2html runs isn't reused.
7984     if ($latex_converted_count == 0)
7985     {
7986         return 1;
7987     }
7988
7989     if (! open(L2H_HTML, "<$l2h_html_file"))
7990     {
7991         warn "$ERROR l2h: Can't open $l2h_html_file for reading\n";
7992         return 0;
7993     }
7994     warn "# l2h: use $l2h_html_file as html file\n" if ($verbose);
7995
7996     my $html_converted_count = 0;   # number of html resulting texts 
7997                                     # retrieved in the file
7998
7999     my ($count, $h_line);
8000     while ($h_line = <L2H_HTML>)
8001     {
8002         if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
8003         {
8004             $count = $1;
8005             my $h_content = '';
8006             my $h_end_found = 0;
8007             while ($h_line = <L2H_HTML>)
8008             {
8009                 if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
8010                 {
8011                     $h_end_found = 1;
8012                     chomp $h_content;
8013                     chomp $h_content;
8014                     $html_converted_count++;
8015                     # transform image file names and copy image files
8016                     $h_content = change_image_file_names($h_content);
8017                     # store result in the html result array
8018                     $l2h_from_html[$count] = $h_content;
8019                     # also add the result in cache hash
8020                     $l2h_cache{$l2h_to_latex[$count]} = $h_content;
8021                     last;
8022                 }
8023                 $h_content = $h_content.$h_line;
8024             }
8025             unless ($h_end_found)
8026             { # couldn't found the closing comment. Certainly  a bug.
8027                 warn "$ERROR l2h(BUG): l2h_end $l2h_name $count not found\n";
8028                 close(L2H_HTML);
8029                 return 0;
8030             }
8031         }
8032     }
8033
8034     # Not the same number of converted elements and retrieved elements
8035     if ($latex_converted_count != $html_converted_count)
8036     {
8037         warn "$ERROR l2h(BUG): waiting for $latex_converted_count elements found $html_converted_count\n";
8038     }
8039
8040     warn "# l2h: Got $html_converted_count of $latex_count html contents\n"
8041         if ($verbose);
8042
8043     close(L2H_HTML);
8044     return 1;
8045 }
8046
8047 my $html_output_count = 0;   # html text outputed in html result file
8048
8049 # called each time a construct handled by latex2html is encountered, should
8050 # output the corresponding html
8051 sub do_tex($$$$)
8052 {
8053     my $style = shift;
8054     my $counter = shift;
8055     my $state = shift;
8056     my $count = $global_count{"${style}_$counter"}; 
8057     ################################## begin debug section (incorrect counts)
8058     if (!defined($count))
8059     {
8060          # counter is undefined
8061          $invalid_counter_count++;
8062          warn "$ERROR l2h(BUG): undefined count for ${style}_$counter\n";
8063          return ("<!-- l2h: ". __LINE__ . " undef count for ${style}_$counter -->")
8064                 if ($debug);
8065          return '';
8066     }
8067     elsif(($count <= 0) or ($count > $latex_count))
8068     {
8069         # counter out of range
8070         $invalid_counter_count++;
8071         warn "$ERROR l2h(BUG): Request of $count content which is out of valide range [0,$latex_count)\n";
8072          return ("<!-- l2h: ". __LINE__ . " out of range count $count -->") 
8073                 if ($debug);
8074          return '';
8075     }
8076     ################################## end debug section (incorrect counts)
8077
8078     # this seems to be a valid counter
8079     my $result = '';
8080     $result = "<!-- l2h_begin $l2h_name $count -->" if ($debug);
8081     if (defined($l2h_from_html[$count]))
8082     {
8083          $html_output_count++;
8084          # maybe we could also have something if simple_format
8085          # with Texi2HTML::Config::protect_text, once simple_format
8086          # may happen for anything else than lines
8087          if ($state->{'remove_texi'})
8088          {# don't protect anything
8089              $result .= $l2h_to_latex[$count];
8090          }
8091          else
8092          { 
8093              $result .= $l2h_from_html[$count];
8094          }
8095     } 
8096     else
8097     {
8098     # if the result is not in @l2h_from_html, there is an error somewhere.
8099         $extract_error_count++;
8100         warn "$ERROR l2h(BUG): can't extract content $count from html\n";
8101         # try simple (ordinary) substitution (without l2h)
8102         $result .= "<!-- l2h: ". __LINE__ . " use texi2html -->" if ($debug);
8103         $result .= main::substitute_text({}, $l2h_to_latex[$count]);
8104     }
8105     $result .= "<!-- l2h_end $l2h_name $count -->" if ($debug);
8106     return $result;
8107 }
8108
8109 # store results in the cache and remove temporary files.
8110 sub finish()
8111 {
8112     return unless($status);
8113     if ($verbose)
8114     {
8115         if ($extract_error_count + $invalid_counter_count)
8116         {
8117             warn "# l2h: finished from html ($extract_error_count extract and $invalid_counter_count invalid counter errors)\n";
8118         }
8119         else
8120         {
8121             warn "# l2h: finished from html (no error)\n";
8122         }
8123         if ($html_output_count != $latex_converted_count)
8124         { # this may happen if @-commands are collected at some places
8125           # but @-command at those places are not expanded later. For 
8126           # example @math on @multitable lines.
8127              warn "# l2h: $html_output_count html outputed for $latex_converted_count converted\n";
8128         }
8129     }
8130     store_cache();
8131     if ($Texi2HTML::Config::L2H_CLEAN)
8132     {
8133         local ($_);
8134         warn "# l2h: removing temporary files generated by l2h extension\n"
8135             if $verbose;
8136         while (<"$docu_rdir$l2h_name"*>)
8137         {
8138 # FIXME error condition not checked
8139             unlink $_;
8140         }
8141     }
8142     warn "# l2h: Finished\n" if $verbose;
8143     return 1;
8144 }
8145
8146 # the driver of end of first pass, second pass and beginning of third pass
8147 #
8148 sub latex2html()
8149 {
8150     return unless($status);
8151     return unless ($status = finish_to_latex());
8152     return unless ($status = to_html());
8153     return unless ($status = init_from_html());
8154 }
8155
8156
8157 ##############################
8158 # stuff for l2h caching
8159 #
8160
8161 # I tried doing this with a dbm data base, but it did not store all
8162 # keys/values. Hence, I did as latex2html does it
8163 sub init_cache
8164 {
8165     if (-r "$l2h_cache_file")
8166     {
8167         my $rdo = do "$l2h_cache_file";
8168         warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
8169             unless ($rdo);
8170     }
8171 }
8172
8173 # store all the text obtained through latex2html
8174 sub store_cache
8175 {
8176     return unless $latex_count;
8177     my ($key, $value);
8178     unless (open(FH, ">$l2h_cache_file"))
8179     { 
8180         warn "$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
8181         return;
8182     }
8183     while (($key, $value) = each %l2h_cache)
8184     {
8185         # escape stuff
8186         $key =~ s|/|\\/|g;
8187         $key =~ s|\\\\/|\\/|g;
8188         # weird, a \ at the end of the key results in an error
8189         # maybe this also broke the dbm database stuff
8190         $key =~ s|\\$|\\\\|;
8191         $value =~ s/\|/\\\|/go;
8192         $value =~ s/\\\\\|/\\\|/go;
8193         $value =~ s|\\\\|\\\\\\\\|g;
8194         print FH "\n\$l2h_cache_key = q/$key/;\n";
8195         print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n";
8196     }
8197     print FH "1;";
8198     close (FH);
8199 }
8200
8201 # return cached html, if it exists for text, and if all pictures
8202 # are there, as well
8203 sub from_cache($)
8204 {
8205     my $text = shift;
8206     my $cached = $l2h_cache{$text};
8207     if (defined($cached))
8208     {
8209         while ($cached =~ m/SRC="(.*?)"/g)
8210         {
8211             unless (-e "$docu_rdir$1")
8212             {
8213                 return undef;
8214             }
8215         }
8216         return $cached;
8217     }
8218     return undef;
8219 }
8220
8221 1;
8222
8223
8224 require "$ENV{T2H_HOME}/T2h_l2h.pm"
8225     if ($0 =~ /\.pl$/ &&
8226         -e "$ENV{T2H_HOME}/T2h_l2h.pm" && -r "$ENV{T2H_HOME}/T2h_l2h.pm");
8227
8228 }
8229
8230 {
8231 package Texi2HTML::LaTeX2HTML::Config;
8232
8233 # latex2html variables
8234 # These variables are not used. They are here for information only, and
8235 # an example of config file for latex2html file is included.
8236 my $ADDRESS;
8237 my $ANTI_ALIAS;
8238 my $ANTI_ALIAS_TEXT;
8239 my $ASCII_MODE;
8240 my $AUTO_LINK;
8241 my $AUTO_PREFIX;
8242 my $CHILDLINE;
8243 my $DEBUG;
8244 my $DESTDIR;
8245 my $ERROR;
8246 my $EXTERNAL_FILE;
8247 my $EXTERNAL_IMAGES;
8248 my $EXTERNAL_UP_LINK;
8249 my $EXTERNAL_UP_TITLE;
8250 my $FIGURE_SCALE_FACTOR;
8251 my $HTML_VERSION;
8252 my $IMAGES_ONLY;
8253 my $INFO;
8254 my $LINE_WIDTH;
8255 my $LOCAL_ICONS;
8256 my $LONG_TITLES;
8257 my $MATH_SCALE_FACTOR;
8258 my $MAX_LINK_DEPTH;
8259 my $MAX_SPLIT_DEPTH;
8260 my $NETSCAPE_HTML;
8261 my $NOLATEX;
8262 my $NO_FOOTNODE;
8263 my $NO_IMAGES;
8264 my $NO_NAVIGATION;
8265 my $NO_SIMPLE_MATH;
8266 my $NO_SUBDIR;
8267 my $PAPERSIZE;
8268 my $PREFIX;
8269 my $PS_IMAGES;
8270 my $REUSE;
8271 my $SCALABLE_FONTS;
8272 my $SHORTEXTN;
8273 my $SHORT_INDEX;
8274 my $SHOW_SECTION_NUMBERS;
8275 my $SPLIT;
8276 my $TEXDEFS;
8277 my $TITLE;
8278 my $TITLES_LANGUAGE;
8279 my $TMP;
8280 my $VERBOSE;
8281 my $WORDS_IN_NAVIGATION_PANEL_TITLES;
8282 my $WORDS_IN_PAGE;
8283
8284 # @T2H_L2H_INIT@
8285
8286 ######################################################################
8287 # from here on, its l2h init stuff
8288 #
8289
8290 ## initialization for latex2html as for Singular manual generation
8291 ## obachman 3/99
8292
8293 #
8294 # Options controlling Titles, File-Names, Tracing and Sectioning
8295 #
8296 $TITLE = '';
8297
8298 $SHORTEXTN = 0;
8299
8300 $LONG_TITLES = 0;
8301
8302 $DESTDIR = '';                  
8303
8304 $NO_SUBDIR = 1;                
8305
8306 $PREFIX = '';                 
8307
8308 $AUTO_PREFIX = 0;            
8309
8310 $AUTO_LINK = 0;
8311
8312 $SPLIT = 0;
8313
8314 $MAX_LINK_DEPTH = 0;
8315
8316 $TMP = '';                     
8317
8318 $DEBUG = 0;
8319
8320 $VERBOSE = 1;
8321
8322 #
8323 # Options controlling Extensions and Special Features
8324 #
8325 #$HTML_VERSION = "3.2";         # set by command line
8326
8327 $TEXDEFS = 1;                   # we absolutely need that
8328
8329 $EXTERNAL_FILE = '';
8330
8331 $SCALABLE_FONTS = 1;
8332
8333 $NO_SIMPLE_MATH = 1;
8334
8335 $LOCAL_ICONS = 1;
8336
8337 $SHORT_INDEX = 0;
8338
8339 $NO_FOOTNODE = 1;
8340
8341 $ADDRESS = '';
8342
8343 $INFO = '';
8344
8345 #
8346 # Switches controlling Image Generation
8347 #
8348 $ASCII_MODE = 0;
8349
8350 $NOLATEX = 0;
8351
8352 $EXTERNAL_IMAGES = 0;
8353
8354 $PS_IMAGES = 0;
8355
8356 $NO_IMAGES = 0;
8357
8358 $IMAGES_ONLY = 0;
8359
8360 $REUSE = 2;
8361
8362 $ANTI_ALIAS = 1;
8363
8364 $ANTI_ALIAS_TEXT = 1;
8365
8366 #
8367 #Switches controlling Navigation Panels
8368 #
8369 $NO_NAVIGATION = 1;
8370 $ADDRESS = '';
8371 $INFO = 0;                      # 0 = do not make a "About this document..." section
8372
8373 #
8374 #Switches for Linking to other documents
8375 #
8376 # currently -- we don't care
8377
8378 $MAX_SPLIT_DEPTH = 0;           # Stop making separate files at this depth
8379
8380 $MAX_LINK_DEPTH = 0;            # Stop showing child nodes at this depth
8381
8382 $NOLATEX = 0;                   # 1 = do not pass unknown environments to Latex
8383
8384 $EXTERNAL_IMAGES = 0;           # 1 = leave the images outside the document
8385
8386 $ASCII_MODE = 0;                # 1 = do not use any icons or internal images
8387
8388 # 1 =  use links to external postscript images rather than inlined bitmap
8389 # images.
8390 $PS_IMAGES = 0;
8391 $SHOW_SECTION_NUMBERS = 0;
8392
8393 ### Other global variables ###############################################
8394 $CHILDLINE = "";
8395
8396 # This is the line width measured in pixels and it is used to right justify
8397 # equations and equation arrays;
8398 $LINE_WIDTH = 500;
8399
8400 # Used in conjunction with AUTO_NAVIGATION
8401 $WORDS_IN_PAGE = 300;
8402
8403 # The value of this variable determines how many words to use in each
8404 # title that is added to the navigation panel (see below)
8405 #
8406 $WORDS_IN_NAVIGATION_PANEL_TITLES = 0;
8407
8408 # This number will determine the size of the equations, special characters,
8409 # and anything which will be converted into an inlined image
8410 # *except* "image generating environments" such as "figure", "table"
8411 # or "minipage".
8412 # Effective values are those greater than 0.
8413 # Sensible values are between 0.1 - 4.
8414 $MATH_SCALE_FACTOR = 1.5;
8415
8416 # This number will determine the size of
8417 # image generating environments such as "figure", "table" or "minipage".
8418 # Effective values are those greater than 0.
8419 # Sensible values are between 0.1 - 4.
8420 $FIGURE_SCALE_FACTOR = 1.6;
8421
8422
8423 #  If both of the following two variables are set then the "Up" button
8424 #  of the navigation panel in the first node/page of a converted document
8425 #  will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set
8426 #  to some text which describes this external link.
8427 $EXTERNAL_UP_LINK = "";
8428 $EXTERNAL_UP_TITLE = "";
8429
8430 # If this is set then the resulting HTML will look marginally better if viewed
8431 # with Netscape.
8432 $NETSCAPE_HTML = 1;
8433
8434 # Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0"
8435 # Paper sizes has no effect other than in the time it takes to create inlined
8436 # images and in whether large images can be created at all ie
8437 #  - larger paper sizes *MAY* help with large image problems
8438 #  - smaller paper sizes are quicker to handle
8439 $PAPERSIZE = "a4";
8440
8441 # Replace "english" with another language in order to tell LaTeX2HTML that you
8442 # want some generated section titles (eg "Table of Contents" or "References")
8443 # to appear in a different language. Currently only "english" and "french"
8444 # is supported but it is very easy to add your own. See the example in the
8445 # file "latex2html.config"
8446 $TITLES_LANGUAGE = "english";
8447
8448 1;                              # This must be the last non-comment line
8449
8450 # End File l2h.init
8451 ######################################################################
8452
8453 }
8454
8455 package main;
8456
8457 #
8458 # pre-defined indices
8459 #
8460
8461 my %index_prefix_to_name = ();
8462
8463 %index_names =
8464 (
8465  'cp' => { 'prefix' => ['cp','c']},
8466  'fn' => { 'prefix' => ['fn', 'f'], code => 1},
8467  'vr' => { 'prefix' => ['vr', 'v'], code => 1},
8468  'ky' => { 'prefix' => ['ky', 'k'], code => 1},
8469  'pg' => { 'prefix' => ['pg', 'p'], code => 1},
8470  'tp' => { 'prefix' => ['tp', 't'], code => 1}
8471 );
8472
8473 foreach my $name(keys(%index_names))
8474 {
8475     foreach my $prefix (@{$index_names{$name}->{'prefix'}})
8476     {
8477         $forbidden_index_name{$prefix} = 1;
8478         $index_prefix_to_name{$prefix} = $name;
8479     }
8480 }
8481
8482 foreach my $other_forbidden_index_name ('info','ps','pdf','htm',
8483    'log','aux','dvi','texi','txi','texinfo','tex','bib')
8484 {
8485     $forbidden_index_name{$other_forbidden_index_name} = 1;
8486 }
8487
8488 # commands with ---, -- '' and `` preserved
8489 # usefull with the old interface
8490
8491 %code_style_map = (
8492            'code'    => 1,
8493            'command' => 1,
8494            'env'     => 1,
8495            'file'    => 1,
8496            'kbd'     => 1,
8497            'option'  => 1,
8498            'samp'    => 1,
8499            'verb'    => 1,
8500 );
8501
8502 my @element_directions = ('Up', 'Forward', 'Back', 'Next', 'Prev', 
8503 'SectionNext', 'SectionPrev', 'SectionUp', 'FastForward', 'FastBack', 
8504 'This', 'NodeUp', 'NodePrev', 'NodeNext', 'Following' );
8505 $::simple_map_ref = \%Texi2HTML::Config::simple_map;
8506 $::simple_map_pre_ref = \%Texi2HTML::Config::simple_map_pre;
8507 $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
8508 $::style_map_ref = \%Texi2HTML::Config::style_map;
8509 $::style_map_pre_ref = \%Texi2HTML::Config::style_map_pre;
8510 $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
8511 $::things_map_ref = \%Texi2HTML::Config::things_map;
8512 $::pre_map_ref = \%Texi2HTML::Config::pre_map;
8513 $::texi_map_ref = \%Texi2HTML::Config::texi_map;
8514
8515 # delete from hash if we are using the new interface
8516 foreach my $code (keys(%code_style_map))
8517 {
8518     delete ($code_style_map{$code}) 
8519        if (ref($::style_map_ref->{$code}) eq 'HASH');
8520 }
8521
8522 # no paragraph in these commands
8523 my %no_paragraph_macro = (
8524            'xref'         => 1,
8525            'ref'          => 1,
8526            'pxref'        => 1,
8527            'inforef'      => 1,
8528            'anchor'       => 1,
8529 );
8530
8531
8532 #
8533 # texinfo section names to level
8534 #
8535 %sec2level = (
8536               'top', 0,
8537               'chapter', 1,
8538               'unnumbered', 1,
8539               'chapheading', 1,
8540               'appendix', 1,
8541               'section', 2,
8542               'unnumberedsec', 2,
8543               'heading', 2,
8544               'appendixsec', 2,
8545               'subsection', 3,
8546               'unnumberedsubsec', 3,
8547               'subheading', 3,
8548               'appendixsubsec', 3,
8549               'subsubsection', 4,
8550               'unnumberedsubsubsec', 4,
8551               'subsubheading', 4,
8552               'appendixsubsubsec', 4,
8553          );
8554
8555 # the reverse mapping. There is an entry for each sectionning command.
8556 # The value is a ref on an array containing at each index the corresponding
8557 # sectionning command name.
8558 my %level2sec;
8559 {
8560     my $sections = [ ];
8561     my $appendices = [ ];
8562     my $unnumbered = [ ];
8563     my $headings = [ ];
8564     foreach my $command (keys (%sec2level))
8565     {
8566         if ($command =~ /^appendix/)
8567         {
8568             $level2sec{$command} = $appendices;
8569         }
8570         elsif ($command =~ /^unnumbered/ or $command eq 'top')
8571         {
8572             $level2sec{$command} = $unnumbered;
8573         }
8574         elsif ($command =~ /section$/ or $command eq 'chapter')
8575         {
8576             $level2sec{$command} = $sections;
8577         }
8578         else
8579         {
8580             $level2sec{$command} = $headings;
8581         }
8582         $level2sec{$command}->[$sec2level{$command}] = $command;
8583     }
8584 }
8585
8586 # this are synonyms
8587 $sec2level{'appendixsection'} = 2;
8588 # sec2level{'majorheading'} is also 1 and not 0
8589 $sec2level{'majorheading'} = 1;
8590 $sec2level{'chapheading'} = 1;
8591 $sec2level{'centerchap'} = 1;
8592
8593 # sction to level hash not taking into account raise and lower sections
8594 my %reference_sec2level = %sec2level;
8595
8596 # regions treated especially. The text for these regions is collected in the
8597 # corresponding array 
8598 %region_lines = (
8599           'titlepage'            => [ ],
8600           'documentdescription'  => [ ],
8601           'copying'              => [ ],
8602 );
8603
8604 # those macros aren't considered as beginning a paragraph
8605 my %no_line_macros = (
8606     'macro' => 1,
8607     'unmacro' => 1,
8608     'rmacro' => 1,
8609     'set' => 1,
8610     'clear' => 1,
8611     'titlefont' => 1,
8612     'include' => 1,
8613     'copying' => 1,
8614     'end copying' => 1,
8615     'tab' => 1,
8616     'item' => 1,
8617     'itemx' => 1,
8618     '*' => 1,
8619     'float' => 1,
8620     'end float' => 1,
8621     'caption' => 1,
8622     'shortcaption' => 1,
8623 );
8624
8625 foreach my $key (keys(%Texi2HTML::Config::misc_command))
8626 {
8627     $no_line_macros{$key} = 1;
8628 }
8629
8630 # a hash associating a format @thing / @end thing with the type of the format
8631 # 'complex_format' 'simple_format' 'deff' 'list' 'menu' 'paragraph_format'
8632 my %format_type = (); 
8633
8634 foreach my $simple_format (keys(%Texi2HTML::Config::format_map))
8635 {
8636    $format_type{$simple_format} = 'simple_format';
8637 }
8638 foreach my $paragraph_style (keys(%Texi2HTML::Config::paragraph_style))
8639 {
8640    $format_type{$paragraph_style} = 'paragraph_format';
8641 }
8642 foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map))
8643 {
8644    $format_type{$complex_format} = 'complex_format';
8645 }
8646 foreach my $table (('table', 'ftable', 'vtable', 'multitable'))
8647 {
8648    $format_type{$table} = 'table';
8649 }
8650 foreach my $def_format (keys(%Texi2HTML::Config::def_map))
8651 {
8652    $format_type{$def_format} = 'deff';
8653 }
8654 $format_type{'itemize'} = 'list';
8655 $format_type{'enumerate'} = 'list';
8656
8657 $format_type{'menu'} = 'menu';
8658
8659 $format_type{'cartouche'} = 'cartouche';
8660
8661 $format_type{'float'} = 'float';
8662
8663 $format_type{'quotation'} = 'quotation';
8664
8665 $format_type{'group'} = 'group';
8666
8667 foreach my $key (keys(%format_type))
8668 {
8669    $no_line_macros{$key} = 1;
8670    $no_line_macros{"end $key"} = 1;
8671 }
8672
8673 foreach my $macro (keys(%Texi2HTML::Config::format_in_paragraph))
8674 {
8675    $no_line_macros{$macro} = 1;
8676    $no_line_macros{"end $macro"} = 1;
8677 }
8678
8679 # fake format at the bottom of the stack
8680 $format_type{'noformat'} = '';
8681
8682 # fake formats are formats used internally within other formats
8683 # we associate them with a real format, for the error messages
8684 my %fake_format = (
8685      'line' => 'table',
8686      'term' => 'table',
8687      'item' => 'list or table',
8688      'row' => 'multitable row',
8689      'cell' => 'multitable cell',
8690      'deff_item' => 'definition command',
8691      'menu_comment' => 'menu',
8692      'menu_description' => 'menu',
8693      'menu_preformatted' => 'menu',
8694   );
8695
8696 foreach my $key (keys(%fake_format))
8697 {
8698     $format_type{$key} = 'fake';
8699 }
8700
8701 # raw formats which are expanded especially
8702 my @raw_regions = ('html', 'verbatim', 'tex', 'xml', 'docbook');
8703
8704 # regions expanded or not depending on the value of this hash
8705 my %text_macros = (
8706      'iftex' => 0, 
8707      'ignore' => 0, 
8708      'menu' => 0, 
8709      'ifplaintext' => 0, 
8710      'ifinfo' => 0,
8711      'ifxml' => 0,
8712      'ifhtml' => 0, 
8713      'ifdocbook' => 0, 
8714      'html' => 0, 
8715      'tex' => 0, 
8716      'xml' => 0,
8717      'titlepage' => 1, 
8718      'documentdescription' => 1, 
8719      'copying' => 1, 
8720      'ifnothtml' => 1, 
8721      'ifnottex' => 1, 
8722      'ifnotplaintext' => 1, 
8723      'ifnotinfo' => 1,
8724      'ifnotxml' => 1,
8725      'ifnotdocbook' => 1, 
8726      'direntry' => 0,
8727      'verbatim' => 'raw', 
8728      'ifclear' => 'value', 
8729      'ifset' => 'value' ,
8730      );
8731     
8732 foreach my $key (keys(%text_macros))
8733 {
8734     unless ($text_macros{$key} eq 'raw')
8735     {
8736         $no_line_macros{$key} = 1;
8737         $no_line_macros{"end $key"} = 1;
8738     }
8739 }
8740
8741 # The css formats are associated with complex format commands, and associated
8742 # with the 'pre_style' key
8743 foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map))
8744 {
8745     next if (defined($Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'}));
8746     $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = '';
8747     $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"}));
8748 }
8749
8750 #+++############################################################################
8751 #                                                                              #
8752 # Argument parsing, initialisation                                             #
8753 #                                                                              #
8754 #---############################################################################
8755
8756 #
8757 # flush stdout and stderr after every write
8758 #
8759 select(STDERR);
8760 $| = 1;
8761 select(STDOUT);
8762 $| = 1;
8763
8764 my $I = \&Texi2HTML::I18n::get_string;
8765
8766 my $T2H_USER; # user running the script
8767 my $documentdescription; # text in @documentdescription 
8768
8769 # shorthand for Texi2HTML::Config::VERBOSE
8770 my $T2H_VERBOSE;
8771 my $T2H_DEBUG;
8772
8773 sub echo_warn($;$);
8774 #print STDERR "" . &$I('test i18n: \' , \a \\ %% %{unknown}a %known % %{known}  \\', { 'known' => 'a known string', 'no' => 'nope'}); exit 0;
8775
8776 # file:        file name to locate. It can be a file path.
8777 # all_files:   if true collect all the files with that name, otherwise stop
8778 #              at first match.
8779 # directories: a reference on a array containing a list of directories to
8780 #              search the file in. default is \@texi2html_config_dirs.
8781 sub locate_init_file($;$$)
8782 {
8783     my $file = shift;
8784     my $all_files = shift;
8785     my $directories = shift;
8786
8787     $directories = \@texi2html_config_dirs if !defined($directories);
8788
8789     if ($file =~ /^\//)
8790     {
8791          return $file if (-e $file and -r $file);
8792     }
8793     else
8794     {
8795          my @files;
8796          foreach my $dir (@$directories)
8797          {
8798               next unless (-d "$dir");
8799               if ($all_files)
8800               {
8801                   push (@files, "$dir/$file") if (-e "$dir/$file" and -r "$dir/$file");
8802               }
8803               else
8804               {
8805                   return "$dir/$file" if (-e "$dir/$file" and -r "$dir/$file");
8806               }
8807          }
8808          return @files if ($all_files);
8809     }
8810     return undef;
8811 }
8812
8813 # called on -init-file
8814 sub load_init_file
8815 {
8816     # First argument is option
8817     shift;
8818     # second argument is value of options
8819     my $init_file = shift;
8820     my $file;
8821     if ($file = locate_init_file($init_file))
8822     {
8823         print STDERR "# reading initialization file from $file\n"
8824             if ($T2H_VERBOSE);
8825         return (Texi2HTML::Config::load($file));
8826     }
8827     else
8828     {
8829         print STDERR "$ERROR Error: can't read init file $init_file\n";
8830         return 0;
8831     }
8832 }
8833
8834 my $cmd_line_lang = 0; # 1 if lang was succesfully set by the command line 
8835                        # in that case @documentlanguage is ignored.
8836 my $lang_set = 0; # 1 if lang was set
8837
8838 #
8839 # called on -lang
8840 sub set_document_language ($;$$)
8841 {
8842     my $lang = shift;
8843     my $from_command_line = shift;
8844     my $line_nr = shift;
8845     my @files = locate_init_file("$i18n_dir/$lang", 1);
8846     foreach  my $file (@files)
8847     {
8848         Texi2HTML::Config::load($file);
8849     }
8850     if (Texi2HTML::I18n::set_language($lang))
8851     {
8852         print STDERR "# using '$lang' as document language\n" if ($T2H_VERBOSE);
8853         $Texi2HTML::Config::LANG = $lang;
8854         $lang_set = 1;
8855         $cmd_line_lang = 1 if ($from_command_line);
8856         if (!$Texi2HTML::Config::TEST)
8857         {
8858             print STDERR "# Setting date in $Texi2HTML::Config::LANG\n" if ($T2H_DEBUG);
8859             $Texi2HTML::THISDOC{'today'} = Texi2HTML::I18n::pretty_date($Texi2HTML::Config::LANG);  # like "20 September 1993";
8860         }
8861         else
8862         {
8863             $Texi2HTML::THISDOC{'today'} = 'a sunny day';
8864         }
8865         $Texi2HTML::THISDOC{'today'} = $Texi2HTML::Config::DATE 
8866             if (defined($Texi2HTML::Config::DATE));
8867         $::things_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
8868         $::pre_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
8869         $::texi_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'};
8870     }
8871     else
8872     {
8873         echo_error ("Language specs for '$lang' do not exists. Reverting to '$Texi2HTML::Config::LANG'", $line_nr);
8874     }
8875 }
8876
8877 # used to manage expanded sections from the command line
8878 sub set_expansion($$)
8879 {
8880     my $region = shift;
8881     my $set = shift;
8882     $set = 1 if (!defined($set));
8883     if ($set)
8884     {
8885          push (@Texi2HTML::Config::EXPAND, $region) unless (grep {$_ eq $region} @Texi2HTML::Config::EXPAND);
8886     }
8887     else
8888     {
8889          @Texi2HTML::Config::EXPAND = grep {$_ ne $region} @Texi2HTML::Config::EXPAND;
8890     }
8891 }
8892
8893
8894 # find the encoding alias.
8895 # with encoding support (USE_UNICODE), may return undef if no alias was found
8896 sub encoding_alias($)
8897 {
8898     my $encoding = shift;
8899     return $encoding if (!defined($encoding) or $encoding eq '');
8900     if ($Texi2HTML::Config::USE_UNICODE)
8901     {
8902          if (! Encode::resolve_alias($encoding))
8903          {
8904               echo_warn("Encoding $encoding unknown");
8905               return undef;
8906          }
8907          print STDERR "# Using encoding " . Encode::resolve_alias($encoding) . "\n"
8908              if ($T2H_VERBOSE);
8909          return Encode::resolve_alias($encoding); 
8910     }
8911     else
8912     {
8913          echo_warn("No alias searched for encoding");
8914          return $encoding;
8915     }
8916 }
8917
8918 # setup hashes used for html manual cross references in texinfo
8919 my %cross_ref_texi_map = %Texi2HTML::Config::texi_map;
8920
8921 $cross_ref_texi_map{'enddots'} = '...';
8922
8923 my %cross_ref_simple_map_texi = %Texi2HTML::Config::simple_map_texi;
8924 my %cross_ref_style_map_texi = ();
8925 my %cross_transliterate_style_map_texi = ();
8926
8927 my %cross_transliterate_texi_map = %cross_ref_texi_map;
8928
8929 foreach my $command (keys(%Texi2HTML::Config::style_map_texi))
8930 {
8931     $cross_ref_style_map_texi{$command} = {}; 
8932     $cross_transliterate_style_map_texi{$command} = {};
8933     foreach my $key (keys (%{$Texi2HTML::Config::style_map_texi{$command}}))
8934     {
8935 #print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n";
8936          $cross_ref_style_map_texi{$command}->{$key} = 
8937               $Texi2HTML::Config::style_map_texi{$command}->{$key};
8938          $cross_transliterate_style_map_texi{$command}->{$key} = 
8939               $Texi2HTML::Config::style_map_texi{$command}->{$key};
8940     }
8941 }
8942
8943 $cross_ref_simple_map_texi{"\n"} = ' ';
8944 $cross_ref_simple_map_texi{"*"} = ' ';
8945
8946 my %nodes = ();             # nodes hash. The key is the texi node name
8947 my %cross_reference_nodes = ();  # normalized node names arrays
8948
8949 # This function is used to construct link names from node names as
8950 # specified for texinfo
8951 sub cross_manual_links()
8952 {
8953     print STDERR "# Doing ".scalar(keys(%nodes))." cross manual links\n" 
8954        if ($T2H_DEBUG);
8955     my $normal_text_kept = $Texi2HTML::Config::normal_text;
8956     $::simple_map_texi_ref = \%cross_ref_simple_map_texi;
8957     $::style_map_texi_ref = \%cross_ref_style_map_texi;
8958     $::texi_map_ref = \%cross_ref_texi_map;
8959     $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text;
8960
8961     foreach my $key (keys(%nodes))
8962     {
8963         my $node = $nodes{$key};
8964         #print STDERR "CROSS_MANUAL:$key,$node\n";
8965         next if ($node->{'index_page'});
8966         if (!defined($node->{'texi'}))
8967         {
8968             ###################### debug section 
8969             foreach my $key (keys(%$node))
8970             {
8971                 #print STDERR "$key:$node->{$key}!!!\n";
8972             }
8973             ###################### end debug section 
8974         }
8975         else 
8976         {
8977             $node->{'cross_manual_target'} = remove_texi($node->{'texi'});
8978             if ($Texi2HTML::Config::USE_UNICODE)
8979             {
8980                 $node->{'cross_manual_target'} = Unicode::Normalize::NFC($node->{'cross_manual_target'});
8981                 if ($Texi2HTML::Config::TRANSLITERATE_NODE and  $Texi2HTML::Config::USE_UNIDECODE)
8982                 {
8983                      $node->{'cross_manual_file'} = 
8984                        unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_target'}));
8985                 }
8986                 $node->{'cross_manual_target'} = 
8987                     unicode_to_protected($node->{'cross_manual_target'});
8988             }
8989 #print STDERR "CROSS_MANUAL_TARGET $node->{'cross_manual_target'}\n";
8990             unless ($node->{'external_node'})
8991             {
8992                 if (exists($cross_reference_nodes{$node->{'cross_manual_target'}}))
8993                 {
8994                     my $other_node_array = $cross_reference_nodes{$node->{'cross_manual_target'}};
8995                     my $node_seen;
8996                     foreach my $other_node (@{$other_node_array})
8997                     {
8998                         $node_seen = $other_node;
8999                         last if ($nodes{$other_node}->{'seen'})
9000                     }
9001                     echo_error("Node equivalent with `$node->{'texi'}' allready used `$node_seen'");
9002                     push @{$other_node_array}, $node->{'texi'};
9003                 }
9004                 else 
9005                 {
9006                     push @{$cross_reference_nodes{$node->{'cross_manual_target'}}}, $node->{'texi'};
9007                 }
9008             }
9009         }
9010     }
9011
9012     
9013     if ($Texi2HTML::Config::TRANSLITERATE_NODE and 
9014          (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
9015     {
9016          $::style_map_texi_ref = \%cross_transliterate_style_map_texi;
9017          $::texi_map_ref = \%cross_transliterate_texi_map;
9018
9019          foreach my $key (keys(%nodes))
9020          {
9021              my $node = $nodes{$key};
9022              next if ($node->{'index_page'});
9023              if (defined($node->{'texi'}))
9024              {
9025                   $node->{'cross_manual_file'} = remove_texi($node->{'texi'});
9026                   $node->{'cross_manual_file'} = unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_file'})) if ($Texi2HTML::Config::USE_UNICODE);
9027              }
9028          }
9029     }
9030
9031     $Texi2HTML::Config::normal_text = $normal_text_kept;
9032     $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
9033     $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
9034     $::texi_map_ref = \%Texi2HTML::Config::texi_map;
9035 }
9036
9037 sub unicode_to_protected($)
9038 {
9039     my $text = shift;
9040     my $result = '';
9041     while ($text ne '')
9042     {
9043         if ($text =~ s/^([A-Za-z0-9]+)//o)
9044         {
9045              $result .= $1;
9046         }
9047         elsif ($text =~ s/^ //o)
9048         {
9049              $result .= '-';
9050         }
9051         elsif ($text =~ s/^(.)//o)
9052         {
9053              if (exists($Texi2HTML::Config::ascii_character_map{$1}))
9054              {
9055                  $result .= '_' . lc($Texi2HTML::Config::ascii_character_map{$1});
9056              }
9057              else
9058              {
9059                  $result .= '_' . lc(sprintf("%04x",ord($1)));
9060              }
9061         }
9062         else
9063         {
9064              print STDERR "Bug: unknown character in a cross ref (likely in infinite loop)\n";
9065              print STDERR "Text: !!$text!!\n";
9066              sleep 1;
9067         }
9068     }
9069     return $result;
9070 }
9071
9072 sub unicode_to_transliterate($)
9073 {
9074     my $text = shift;
9075     my $result = '';
9076     while ($text ne '')
9077     {
9078         if ($text =~ s/^([A-Za-z0-9 ]+)//o)
9079         {
9080              $result .= $1;
9081         }
9082         elsif ($text =~ s/^(.)//o)
9083         {
9084              if (exists($Texi2HTML::Config::ascii_character_map{$1}))
9085              {
9086                  $result .= $1;
9087              }
9088              elsif (exists($Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))}))
9089              {
9090                  $result .= $Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))};
9091              }
9092              elsif (exists($Texi2HTML::Config::unicode_diacritical{uc(sprintf("%04x",ord($1)))}))
9093              {
9094                  $result .= '';
9095              }
9096              else
9097              {
9098                  if ($Texi2HTML::Config::USE_UNIDECODE)
9099                  {
9100                       $result .= unidecode($1);
9101                  }
9102                  else
9103                  {
9104                       $result .= $1;
9105                  }
9106              }
9107         }
9108         else
9109         {
9110              print STDERR "Bug: unknown character in cross ref transliteration (likely in infinite loop)\n";
9111              sleep 1;
9112         }
9113     }
9114     return $result;
9115 }
9116
9117 # This function is used to construct a link name from a node name as
9118 # specified for texinfo
9119 sub cross_manual_line($;$)
9120 {
9121     my $text = shift;
9122     my $transliterate = shift;
9123 #print STDERR "cross_manual_line $text\n";
9124 #print STDERR "remove_texi text ". remove_texi($text)."\n\n\n";
9125     $::simple_map_texi_ref = \%cross_ref_simple_map_texi;
9126     $::style_map_texi_ref = \%cross_ref_style_map_texi;
9127     $::texi_map_ref = \%cross_ref_texi_map;
9128     my $normal_text_kept = $Texi2HTML::Config::normal_text;
9129     $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text;
9130     
9131     my ($cross_ref_target, $cross_ref_file);
9132     if ($Texi2HTML::Config::USE_UNICODE)
9133     {
9134          $cross_ref_target = Unicode::Normalize::NFC(remove_texi($text));
9135          if ($transliterate and $Texi2HTML::Config::USE_UNIDECODE)
9136          {
9137              $cross_ref_file = 
9138                 unicode_to_protected(unicode_to_transliterate($cross_ref_target));
9139          }
9140          $cross_ref_target = unicode_to_protected($cross_ref_target);
9141     }
9142     else
9143     {
9144          $cross_ref_target = remove_texi($text);
9145     }
9146     
9147     if ($transliterate and 
9148          (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
9149     {
9150          $::style_map_texi_ref = \%cross_transliterate_style_map_texi;
9151          $::texi_map_ref = \%cross_transliterate_texi_map;
9152          $cross_ref_file = remove_texi($text);
9153          $cross_ref_file = unicode_to_protected(unicode_to_transliterate($cross_ref_file))
9154                if ($Texi2HTML::Config::USE_UNICODE);
9155     }
9156
9157     $Texi2HTML::Config::normal_text = $normal_text_kept;
9158     $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
9159     $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
9160     $::texi_map_ref = \%Texi2HTML::Config::texi_map;
9161 #print STDERR "\n\ncross_ref $cross_ref\n";
9162     unless ($transliterate)
9163     {
9164         return $cross_ref_target;
9165     }
9166 #    print STDERR "$text|$cross_ref_target|$cross_ref_file\n";
9167     return ($cross_ref_target, $cross_ref_file);
9168 }
9169
9170 # T2H_OPTIONS is a hash whose keys are the (long) names of valid
9171 # command-line options and whose values are a hash with the following keys:
9172 # type    ==> one of !|=i|:i|=s|:s (see GetOpt::Long for more info)
9173 # linkage ==> ref to scalar, array, or subroutine (see GetOpt::Long for more info)
9174 # verbose ==> short description of option (displayed by -h)
9175 # noHelp  ==> if 1 -> for "not so important options": only print description on -h 1
9176 #                2 -> for obsolete options: only print description on -h 2
9177 my $T2H_OPTIONS;
9178 $T2H_OPTIONS -> {'debug'} =
9179 {
9180  type => '=i',
9181  linkage => \$Texi2HTML::Config::DEBUG,
9182  verbose => 'output HTML with debuging information',
9183 };
9184
9185 $T2H_OPTIONS -> {'doctype'} =
9186 {
9187  type => '=s',
9188  linkage => \$Texi2HTML::Config::DOCTYPE,
9189  verbose => 'document type which is output in header of HTML files',
9190  noHelp => 1
9191 };
9192
9193 $T2H_OPTIONS -> {'frameset-doctype'} =
9194 {
9195  type => '=s',
9196  linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
9197  verbose => 'document type for HTML frameset documents',
9198  noHelp => 1
9199 };
9200
9201 $T2H_OPTIONS -> {'test'} =
9202 {
9203  type => '!',
9204  linkage => \$Texi2HTML::Config::TEST,
9205  verbose => 'use predefined information to avoid differences with reference files',
9206  noHelp => 1
9207 };
9208
9209 $T2H_OPTIONS -> {'dump-texi'} =
9210 {
9211  type => '!',
9212  linkage => \$Texi2HTML::Config::DUMP_TEXI,
9213  verbose => 'dump the output of first pass into a file with extension passfirst and exit',
9214  noHelp => 1
9215 };
9216
9217 $T2H_OPTIONS -> {'macro-expand'} =
9218 {
9219  type => '=s',
9220  linkage => \$Texi2HTML::Config::MACRO_EXPAND,
9221  verbose => 'output macro expanded source in <file>',
9222 };
9223
9224 $T2H_OPTIONS -> {'expand'} =
9225 {
9226  type => '=s',
9227  linkage => sub {set_expansion($_[1], 1);},
9228  verbose => 'Expand info|tex|none section of texinfo source',
9229  noHelp => 1,
9230 };
9231
9232 $T2H_OPTIONS -> {'no-expand'} =
9233 {
9234  type => '=s',
9235  linkage => sub {set_expansion ($_[1], 0);},
9236  verbose => 'Don\'t expand the given section of texinfo source',
9237 };
9238
9239 $T2H_OPTIONS -> {'noexpand'} = 
9240 {
9241  type => '=s',
9242  linkage => $T2H_OPTIONS->{'no-expand'}->{'linkage'},
9243  verbose => $T2H_OPTIONS->{'no-expand'}->{'verbose'},
9244  noHelp  => 1,
9245 };
9246
9247 $T2H_OPTIONS -> {'ifhtml'} =
9248 {
9249  type => '!',
9250  linkage => sub { set_expansion('html', $_[1]); },
9251  verbose => "expand ifhtml and html sections",
9252 };
9253
9254 $T2H_OPTIONS -> {'ifinfo'} =
9255 {
9256  type => '!',
9257  linkage => sub { set_expansion('info', $_[1]); },
9258  verbose => "expand ifinfo",
9259 };
9260
9261 $T2H_OPTIONS -> {'ifxml'} =
9262 {
9263  type => '!',
9264  linkage => sub { set_expansion('xml', $_[1]); },
9265  verbose => "expand ifxml and xml sections",
9266 };
9267
9268 $T2H_OPTIONS -> {'ifdocbook'} =
9269 {
9270  type => '!',
9271  linkage => sub { set_expansion('docbook', $_[1]); },
9272  verbose => "expand ifdocbook and docbook sections",
9273 };
9274
9275 $T2H_OPTIONS -> {'iftex'} =
9276 {
9277  type => '!',
9278  linkage => sub { set_expansion('tex', $_[1]); },
9279  verbose => "expand iftex and tex sections",
9280 };
9281
9282 $T2H_OPTIONS -> {'ifplaintext'} =
9283 {
9284  type => '!',
9285  linkage => sub { set_expansion('plaintext', $_[1]); },
9286  verbose => "expand ifplaintext sections",
9287 };
9288
9289 $T2H_OPTIONS -> {'invisible'} =
9290 {
9291  type => '=s',
9292  linkage => \$Texi2HTML::Config::INVISIBLE_MARK,
9293  verbose => 'use text in invisble anchor',
9294  noHelp  => 1,
9295 };
9296
9297 $T2H_OPTIONS -> {'iso'} =
9298 {
9299  type => 'iso',
9300  linkage => \$Texi2HTML::Config::USE_ISO,
9301  verbose => 'if set, ISO8859 characters are used for special symbols (like copyright, etc)',
9302  noHelp => 1,
9303 };
9304
9305 $T2H_OPTIONS -> {'I'} =
9306 {
9307  type => '=s',
9308  linkage => \@Texi2HTML::Config::INCLUDE_DIRS,
9309  verbose => 'append $s to the @include search path',
9310 };
9311
9312 $T2H_OPTIONS -> {'conf-dir'} =
9313 {
9314  type => '=s',
9315  linkage => \@Texi2HTML::Config::CONF_DIRS,
9316  verbose => 'append $s to the init file directories',
9317 };
9318
9319 $T2H_OPTIONS -> {'P'} =
9320 {
9321  type => '=s',
9322  linkage => sub {unshift (@Texi2HTML::Config::PREPEND_DIRS, $_[1]);},
9323  verbose => 'prepend $s to the @include search path',
9324 };
9325
9326 $T2H_OPTIONS -> {'top-file'} =
9327 {
9328  type => '=s',
9329  linkage => \$Texi2HTML::Config::TOP_FILE,
9330  verbose => 'use $s as top file, instead of <docname>.html',
9331 };
9332
9333 $T2H_OPTIONS -> {'toc-file'} =
9334 {
9335  type => '=s',
9336  linkage => \$Texi2HTML::Config::TOC_FILE,
9337  verbose => 'use $s as ToC file, instead of <docname>_toc.html',
9338 };
9339
9340 $T2H_OPTIONS -> {'frames'} =
9341 {
9342  type => '!',
9343  linkage => \$Texi2HTML::Config::FRAMES,
9344  verbose => 'output files which use HTML 4.0 frames (experimental)',
9345  noHelp => 1,
9346 };
9347
9348 $T2H_OPTIONS -> {'menu'} =
9349 {
9350  type => '!',
9351  linkage => \$Texi2HTML::Config::SHOW_MENU,
9352  verbose => 'output Texinfo menus',
9353 };
9354
9355 $T2H_OPTIONS -> {'number'} =
9356 {
9357  type => '!',
9358  linkage => \$Texi2HTML::Config::NUMBER_SECTIONS,
9359  verbose => 'use numbered sections',
9360 };
9361
9362 $T2H_OPTIONS -> {'use-nodes'} =
9363 {
9364  type => '!',
9365  linkage => \$Texi2HTML::Config::USE_NODES,
9366  verbose => 'use nodes for sectionning',
9367 };
9368
9369 $T2H_OPTIONS -> {'node-files'} =
9370 {
9371  type => '!',
9372  linkage => \$Texi2HTML::Config::NODE_FILES,
9373  verbose => 'produce one file per node for cross references'
9374 };
9375
9376 $T2H_OPTIONS -> {'separated-footnotes'} =
9377 {
9378  type => '!',
9379  linkage => \$Texi2HTML::Config::SEPARATED_FOOTNOTES,
9380  verbose => 'footnotes on a separated page',
9381  noHelp => 1,
9382 };
9383
9384 $T2H_OPTIONS -> {'toc-links'} =
9385 {
9386  type => '!',
9387  linkage => \$Texi2HTML::Config::TOC_LINKS,
9388  verbose => 'create links from headings to toc entries'
9389 };
9390
9391 $T2H_OPTIONS -> {'split'} =
9392 {
9393  type => '=s',
9394  linkage => \$Texi2HTML::Config::SPLIT,
9395  verbose => 'split document on section|chapter|node else no splitting',
9396 };
9397
9398 $T2H_OPTIONS -> {'sec-nav'} =
9399 {
9400  type => '!',
9401  linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9402  verbose => 'output navigation panels for each section',
9403 };
9404
9405 $T2H_OPTIONS -> {'subdir'} =
9406 {
9407  type => '=s',
9408  linkage => \$Texi2HTML::Config::SUBDIR,
9409  verbose => 'put files in directory $s, not $cwd',
9410  noHelp => 1,
9411 };
9412
9413 $T2H_OPTIONS -> {'short-ext'} =
9414 {
9415  type => '!',
9416  linkage => \$Texi2HTML::Config::SHORTEXTN,
9417  verbose => 'use "htm" extension for output HTML files',
9418 };
9419
9420 $T2H_OPTIONS -> {'prefix'} =
9421 {
9422  type => '=s',
9423  linkage => \$Texi2HTML::Config::PREFIX,
9424  verbose => 'use as prefix for output files, instead of <docname>',
9425 };
9426
9427 $T2H_OPTIONS -> {'output'} =
9428 {
9429  type => '=s',
9430  linkage => \$Texi2HTML::Config::OUT,
9431  verbose => 'output goes to $s (directory if split)',
9432 };
9433
9434 $T2H_OPTIONS -> {'no-validate'} = 
9435 {
9436  type => '!',
9437  linkage => \$Texi2HTML::Config::NOVALIDATE,
9438  verbose => 'suppress node cross-reference validation',
9439 };
9440
9441 $T2H_OPTIONS -> {'short-ref'} =
9442 {
9443  type => '!',
9444  linkage => \$Texi2HTML::Config::SHORT_REF,
9445  verbose => 'if set, references are without section numbers',
9446 };
9447
9448 $T2H_OPTIONS -> {'idx-sum'} =
9449 {
9450  type => '!',
9451  linkage => \$Texi2HTML::Config::IDX_SUMMARY,
9452  verbose => 'if set, also output index summary',
9453  noHelp  => 1,
9454 };
9455
9456 $T2H_OPTIONS -> {'def-table'} =
9457 {
9458  type => '!',
9459  linkage => \$Texi2HTML::Config::DEF_TABLE,
9460  verbose => 'if set, \@def.. are converted using tables.',
9461  noHelp  => 1,
9462 };
9463
9464 $T2H_OPTIONS -> {'Verbose'} =
9465 {
9466  type => '!',
9467  linkage=> \$Texi2HTML::Config::VERBOSE,
9468  verbose => 'print progress info to stdout',
9469 };
9470
9471 $T2H_OPTIONS -> {'lang'} =
9472 {
9473  type => '=s',
9474  linkage => sub {set_document_language($_[1], 1)},
9475  verbose => 'use $s as document language (ISO 639 encoding)',
9476 };
9477
9478 $T2H_OPTIONS -> {'ignore-preamble-text'} =
9479 {
9480   type => '!',
9481   linkage => \$Texi2HTML::Config::IGNORE_PREAMBLE_TEXT,
9482   verbose => 'if set, ignore the text before @node and sectionning commands',
9483   noHelp => 1,
9484 };
9485
9486 $T2H_OPTIONS -> {'html-xref-prefix'} =
9487 {
9488  type => '=s',
9489  linkage => \$Texi2HTML::Config::EXTERNAL_DIR,
9490  verbose => '$s is the base dir for external manual references',
9491  noHelp => 1,
9492 };
9493
9494 $T2H_OPTIONS -> {'l2h'} =
9495 {
9496  type => '!',
9497  linkage => \$Texi2HTML::Config::L2H,
9498  verbose => 'if set, uses latex2html for @math and @tex',
9499 };
9500
9501 $T2H_OPTIONS -> {'l2h-l2h'} =
9502 {
9503  type => '=s',
9504  linkage => \$Texi2HTML::Config::L2H_L2H,
9505  verbose => 'program to use for latex2html translation',
9506  noHelp => 1,
9507 };
9508
9509 $T2H_OPTIONS -> {'l2h-skip'} =
9510 {
9511  type => '!',
9512  linkage => \$Texi2HTML::Config::L2H_SKIP,
9513  verbose => 'if set, tries to reuse previously latex2html output',
9514  noHelp => 1,
9515 };
9516
9517 $T2H_OPTIONS -> {'l2h-tmp'} =
9518 {
9519  type => '=s',
9520  linkage => \$Texi2HTML::Config::L2H_TMP,
9521  verbose => 'if set, uses $s as temporary latex2html directory',
9522  noHelp => 1,
9523 };
9524
9525 $T2H_OPTIONS -> {'l2h-file'} =
9526 {
9527  type => '=s',
9528  linkage => \$Texi2HTML::Config::L2H_FILE,
9529  verbose => 'if set, uses $s as latex2html init file',
9530  noHelp => 1,
9531 };
9532
9533
9534 $T2H_OPTIONS -> {'l2h-clean'} =
9535 {
9536  type => '!',
9537  linkage => \$Texi2HTML::Config::L2H_CLEAN,
9538  verbose => 'if set, do not keep intermediate latex2html files for later reuse',
9539  noHelp => 1,
9540 };
9541
9542 $T2H_OPTIONS -> {'D'} =
9543 {
9544  type => '=s',
9545  linkage => sub {$value{$_[1]} = 1;},
9546  verbose => 'equivalent to Texinfo "@set $s 1"',
9547  noHelp => 1,
9548 };
9549
9550 $T2H_OPTIONS -> {'U'} =
9551 {
9552  type => '=s',
9553  linkage => sub {delete $value{$_[1]};},
9554  verbose => 'equivalent to Texinfo "@clear $s"',
9555  noHelp => 1,
9556 };
9557
9558 $T2H_OPTIONS -> {'init-file'} =
9559 {
9560  type => '=s',
9561  linkage => \&load_init_file,
9562  verbose => 'load init file $s'
9563 };
9564
9565 $T2H_OPTIONS -> {'css-include'} =
9566 {
9567  type => '=s',
9568  linkage => \@Texi2HTML::Config::CSS_FILES,
9569  verbose => 'use css file $s'
9570 };
9571
9572 ##
9573 ## obsolete cmd line options
9574 ##
9575 my $T2H_OBSOLETE_OPTIONS;
9576
9577 $T2H_OBSOLETE_OPTIONS -> {'out-file'} =
9578 {
9579  type => '=s',
9580  linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
9581  verbose => 'if set, all HTML output goes into file $s, obsoleted by "-output" with different semantics',
9582  noHelp => 2
9583 };
9584
9585 $T2H_OBSOLETE_OPTIONS -> {init_file} =
9586 {
9587  type => '=s',
9588  linkage => \&load_init_file,
9589  verbose => 'obsolete, use "-init-file" instead',
9590  noHelp => 2
9591 };
9592
9593 $T2H_OBSOLETE_OPTIONS -> {l2h_clean} =
9594 {
9595  type => '!',
9596  linkage => \$Texi2HTML::Config::L2H_CLEAN,
9597  verbose => 'obsolete, use "-l2h-clean" instead',
9598  noHelp => 2,
9599 };
9600
9601 $T2H_OBSOLETE_OPTIONS -> {l2h_l2h} =
9602 {
9603  type => '=s',
9604  linkage => \$Texi2HTML::Config::L2H_L2H,
9605  verbose => 'obsolete, use "-l2h-l2h" instead',
9606  noHelp => 2
9607 };
9608
9609 $T2H_OBSOLETE_OPTIONS -> {l2h_skip} =
9610 {
9611  type => '!',
9612  linkage => \$Texi2HTML::Config::L2H_SKIP,
9613  verbose => 'obsolete, use "-l2h-skip" instead',
9614  noHelp => 2
9615 };
9616
9617 $T2H_OBSOLETE_OPTIONS -> {l2h_tmp} =
9618 {
9619  type => '=s',
9620  linkage => \$Texi2HTML::Config::L2H_TMP,
9621  verbose => 'obsolete, use "-l2h-tmp" instead',
9622  noHelp => 2
9623 };
9624
9625 $T2H_OBSOLETE_OPTIONS -> {out_file} =
9626 {
9627  type => '=s',
9628  linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
9629  verbose => 'obsolete, use "-out-file" instead',
9630  noHelp => 2
9631 };
9632
9633 $T2H_OBSOLETE_OPTIONS -> {short_ref} =
9634 {
9635  type => '!',
9636  linkage => \$Texi2HTML::Config::SHORT_REF,
9637  verbose => 'obsolete, use "-short-ref" instead',
9638  noHelp => 2
9639 };
9640
9641 $T2H_OBSOLETE_OPTIONS -> {idx_sum} =
9642 {
9643  type => '!',
9644  linkage => \$Texi2HTML::Config::IDX_SUMMARY,
9645  verbose => 'obsolete, use "-idx-sum" instead',
9646  noHelp  => 2
9647 };
9648
9649 $T2H_OBSOLETE_OPTIONS -> {def_table} =
9650 {
9651  type => '!',
9652  linkage => \$Texi2HTML::Config::DEF_TABLE,
9653  verbose => 'obsolete, use "-def-table" instead',
9654  noHelp  => 2
9655 };
9656
9657 $T2H_OBSOLETE_OPTIONS -> {short_ext} =
9658 {
9659  type => '!',
9660  linkage => \$Texi2HTML::Config::SHORTEXTN,
9661  verbose => 'obsolete, use "-short-ext" instead',
9662  noHelp  => 2
9663 };
9664
9665 $T2H_OBSOLETE_OPTIONS -> {sec_nav} =
9666 {
9667  type => '!',
9668  linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9669  verbose => 'obsolete, use "-sec-nav" instead',
9670  noHelp  => 2
9671 };
9672
9673 $T2H_OBSOLETE_OPTIONS -> {top_file} =
9674 {
9675  type => '=s',
9676  linkage => \$Texi2HTML::Config::TOP_FILE,
9677  verbose => 'obsolete, use "-top-file" instead',
9678  noHelp  => 2
9679 };
9680
9681 $T2H_OBSOLETE_OPTIONS -> {toc_file} =
9682 {
9683  type => '=s',
9684  linkage => \$Texi2HTML::Config::TOC_FILE,
9685  verbose => 'obsolete, use "-toc-file" instead',
9686  noHelp  => 2
9687 };
9688
9689 $T2H_OBSOLETE_OPTIONS -> {glossary} =
9690 {
9691  type => '!',
9692  linkage => \$Texi2HTML::Config::USE_GLOSSARY,
9693  verbose => "this does nothing",
9694  noHelp  => 2,
9695 };
9696
9697 $T2H_OBSOLETE_OPTIONS -> {check} =
9698 {
9699  type => '!',
9700  linkage => sub {exit 0;},
9701  verbose => "exit without doing anything",
9702  noHelp  => 2,
9703 };
9704
9705 $T2H_OBSOLETE_OPTIONS -> {dump_texi} =
9706 {
9707  type => '!',
9708  linkage => \$Texi2HTML::Config::DUMP_TEXI,
9709  verbose => 'obsolete, use "-dump-texi" instead',
9710  noHelp => 1
9711 };
9712
9713 $T2H_OBSOLETE_OPTIONS -> {frameset_doctype} =
9714 {
9715  type => '=s',
9716  linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
9717  verbose => 'obsolete, use "-frameset-doctype" instead',
9718  noHelp => 2
9719 };
9720
9721 $T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} =
9722 {
9723  type => '!',
9724  linkage => sub {$Texi2HTML::Config::SECTION_NAVIGATION = 0;},
9725  verbose => 'obsolete, use -nosec_nav',
9726  noHelp => 2,
9727 };
9728 my $use_acc; # not used
9729 $T2H_OBSOLETE_OPTIONS -> {use_acc} =
9730 {
9731  type => '!',
9732  linkage => \$use_acc,
9733  verbose => 'obsolete, set to true unconditionnaly',
9734  noHelp => 2
9735 };
9736 $T2H_OBSOLETE_OPTIONS -> {expandinfo} =
9737 {
9738  type => '!',
9739  linkage => sub {push @Texi2HTML::Config::EXPAND, 'info';},
9740  verbose => 'obsolete, use "-expand info" instead',
9741  noHelp => 2,
9742 };
9743 $T2H_OBSOLETE_OPTIONS -> {expandtex} =
9744 {
9745  type => '!',
9746  linkage => sub {push @Texi2HTML::Config::EXPAND, 'tex';},
9747  verbose => 'obsolete, use "-expand tex" instead',
9748  noHelp => 2,
9749 };
9750 $T2H_OBSOLETE_OPTIONS -> {monolithic} =
9751 {
9752  type => '!',
9753  linkage => sub {$Texi2HTML::Config::SPLIT = '';},
9754  verbose => 'obsolete, use "-split no" instead',
9755  noHelp => 2
9756 };
9757 $T2H_OBSOLETE_OPTIONS -> {split_node} =
9758 {
9759  type => '!',
9760  linkage => sub{$Texi2HTML::Config::SPLIT = 'section';},
9761  verbose => 'obsolete, use "-split section" instead',
9762  noHelp => 2,
9763 };
9764 $T2H_OBSOLETE_OPTIONS -> {split_chapter} =
9765 {
9766  type => '!',
9767  linkage => sub{$Texi2HTML::Config::SPLIT = 'chapter';},
9768  verbose => 'obsolete, use "-split chapter" instead',
9769  noHelp => 2,
9770 };
9771 $T2H_OBSOLETE_OPTIONS -> {no_verbose} =
9772 {
9773  type => '!',
9774  linkage => sub {$Texi2HTML::Config::VERBOSE = 0;},
9775  verbose => 'obsolete, use -noverbose instead',
9776  noHelp => 2,
9777 };
9778 $T2H_OBSOLETE_OPTIONS -> {output_file} =
9779 {
9780  type => '=s',
9781  linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
9782  verbose => 'obsolete, use --out-file instead',
9783  noHelp => 2
9784 };
9785
9786 $T2H_OBSOLETE_OPTIONS -> {section_navigation} =
9787 {
9788  type => '!',
9789  linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9790  verbose => 'obsolete, use --sec-nav instead',
9791  noHelp => 2,
9792 };
9793
9794 $T2H_OBSOLETE_OPTIONS -> {verbose} =
9795 {
9796  type => '!',
9797  linkage=> \$Texi2HTML::Config::VERBOSE,
9798  verbose => 'obsolete, use -Verbose instead',
9799  noHelp => 2
9800 };
9801
9802 # read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc
9803 # (this is obsolete)
9804 my @rc_files = ();
9805 push @rc_files, "$sysconfdir/texi2htmlrc" if defined($sysconfdir);
9806 push @rc_files, "$ENV{'HOME'}/.texi2htmlrc" if (defined($ENV{HOME}));
9807 foreach my $i (@rc_files)
9808 {
9809     if (-e $i and -r $i)
9810     {
9811         print STDERR "# reading initialization file from $i\n"
9812             if ($T2H_VERBOSE);
9813         print STDERR "Reading config from $i is obsolete, use texi2html/$conf_file_name instead\n";
9814         Texi2HTML::Config::load($i);
9815     }
9816 }
9817
9818 # read initialization files
9819 foreach my $file (locate_init_file($conf_file_name, 1))
9820 {
9821     print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE);
9822     Texi2HTML::Config::load($file);
9823 }
9824
9825 #
9826 # %value hold texinfo variables, see also -D, -U, @set and @clear.
9827 # we predefine html (the output format) and texi2html (the translator)
9828 %value = 
9829       (
9830           'html' => 1,
9831           'texi2html' => $THISVERSION,
9832       );
9833
9834 #+++############################################################################
9835 #                                                                              #
9836 # parse command-line options
9837 #                                                                              #
9838 #---############################################################################
9839
9840
9841 my $T2H_USAGE_TEXT = <<EOT;
9842 Usage: texi2html  [OPTIONS] TEXINFO-FILE
9843 Translates Texinfo source documentation to HTML.
9844 EOT
9845 my $T2H_FAILURE_TEXT = <<EOT;
9846 Try 'texi2html --help' for usage instructions.
9847 EOT
9848
9849 my $options = new Getopt::MySimple;
9850
9851 $T2H_OPTIONS -> {'help'} = 
9852
9853  type => ':i', 
9854  default => '',
9855  linkage => sub {$options->helpOptions($_[1]); 
9856     print "\nSend bugs and suggestions to <texi2html-bug\@nongnu.org>\n";
9857     exit (0);},
9858  verbose => "print help and exit"
9859 };
9860
9861 # this avoids getOptions defining twice 'help' and 'version'.
9862 $T2H_OBSOLETE_OPTIONS -> {'help'} = 0;
9863 $T2H_OBSOLETE_OPTIONS -> {'version'} = 0;
9864
9865 # some older version of GetOpt::Long don't have
9866 # Getopt::Long::Configure("pass_through")
9867 eval {Getopt::Long::Configure("pass_through");};
9868 my $Configure_failed = $@ && <<EOT;
9869 **WARNING: Parsing of obsolete command-line options could have failed.
9870            Consider to use only documented command-line options (run
9871            'texi2html --help 2' for a complete list) or upgrade to perl
9872            version 5.005 or higher.
9873 EOT
9874 if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
9875 {
9876     print STDERR "$Configure_failed" if $Configure_failed;
9877     die $T2H_FAILURE_TEXT;
9878 }
9879 if (@ARGV > 1)
9880 {
9881     eval {Getopt::Long::Configure("no_pass_through");};
9882     if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
9883     {
9884         print STDERR "$Configure_failed" if $Configure_failed;
9885         die $T2H_FAILURE_TEXT;
9886     }
9887 }
9888
9889 #
9890 # read texi2html extensions (if any)
9891 # It is obsolete (obsoleted by -init-file). we keep it for backward
9892 # compatibility.
9893 my $extensions = 'texi2html.ext';  # extensions in working directory
9894 if (-f $extensions)
9895 {
9896     print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
9897     require($extensions);
9898 }
9899 my $progdir;
9900 ($progdir = $0) =~ s/[^\/]+$//;
9901 if ($progdir && ($progdir ne './'))
9902 {
9903     $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
9904     if (-f $extensions)
9905     {
9906         print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
9907         require($extensions);
9908     }
9909 }
9910
9911 # $T2H_DEBUG and $T2H_VERBOSE are shorthands
9912 $T2H_DEBUG = $Texi2HTML::Config::DEBUG;
9913 $T2H_VERBOSE = $Texi2HTML::Config::VERBOSE;
9914
9915 $Texi2HTML::THISDOC{'debug_l2h'} = 0;
9916 $Texi2HTML::THISDOC{'debug_l2h'} = 1 if ($T2H_DEBUG & $DEBUG_L2H);
9917
9918
9919 #+++############################################################################
9920 #                                                                              #
9921 # evaluation of cmd line options
9922 #                                                                              #
9923 #---############################################################################
9924
9925 # Fill in the %style_type hash, a hash associating style @-comand with 
9926 # the type, 'accent', real 'style', simple' style, or 'special'.
9927 # 'simple_style' styles don't extend accross lines.
9928 my %style_type = (); 
9929 my @simple_styles = ('ctrl', 'w', 'url','uref','indicateurl','email',
9930     'titlefont');
9931 foreach my $style (keys(%Texi2HTML::Config::style_map))
9932 {
9933     if (exists $Texi2HTML::Config::command_type{$style})
9934     {
9935         $style_type{$style} = $Texi2HTML::Config::command_type{$style};
9936         next;
9937     }
9938     if (ref($Texi2HTML::Config::style_map{$style} eq 'HASH'))
9939     {
9940         $style_type{$style} = $Texi2HTML::Config::style_map{$style}->{'type'}
9941           if (exists($Texi2HTML::Config::style_map{$style}->{'type'}));
9942     }
9943     else
9944     {
9945         $style_type{$style} = 'simple_style' if (grep {$_ eq $style} @simple_styles);
9946     }
9947     $style_type{$style} = 'style' unless (defined($style_type{$style}));
9948 }
9949 foreach my $accent (keys(%Texi2HTML::Config::unicode_accents), 'tieaccent', 'dotless')
9950 {
9951     if (exists $Texi2HTML::Config::command_type{$accent})
9952     {
9953         $style_type{$accent} = $Texi2HTML::Config::command_type{$accent};
9954         next;
9955     }
9956     $style_type{$accent} = 'accent';
9957 }
9958 #foreach my $simple ('ctrl', 'w', 'url','uref','indicateurl','email')
9959 #{
9960 #    $style_type{$simple} = 'simple_style';
9961 #}
9962 foreach my $special ('footnote', 'ref', 'xref', 'pxref', 'inforef', 'anchor', 'image')
9963 {
9964     if (exists $Texi2HTML::Config::command_type{$special})
9965     {
9966         $style_type{$special} = $Texi2HTML::Config::command_type{$special};
9967         next;
9968     }
9969     $style_type{$special} = 'special';
9970 }
9971
9972 # retro compatibility for $Texi2HTML::Config::EXPAND
9973 push (@Texi2HTML::Config::EXPAND, $Texi2HTML::Config::EXPAND) if ($Texi2HTML::Config::EXPAND);
9974
9975 unshift @texi2html_config_dirs, @Texi2HTML::Config::CONF_DIRS;
9976 # correct %text_macros based on command line and init
9977 # variables
9978 $text_macros{'menu'} = 1 if ($Texi2HTML::Config::SHOW_MENU);
9979
9980 foreach my $expanded (@Texi2HTML::Config::EXPAND)
9981 {
9982     $text_macros{"if$expanded"} = 1 if (exists($text_macros{"if$expanded"}));
9983     next unless (exists($text_macros{$expanded}));
9984     if (grep {$_ eq $expanded} @raw_regions)
9985     {
9986          $text_macros{$expanded} = 'raw'; 
9987     }
9988     else
9989     {
9990          $text_macros{$expanded} = 1; 
9991     }
9992 }
9993
9994 # handle ifnot regions
9995 foreach my $region (keys (%text_macros))
9996 {
9997     next if ($region =~ /^ifnot/);
9998     if ($text_macros{$region} and $region =~ /^if(\w+)$/)
9999     {
10000         $text_macros{"ifnot$1"} = 0;
10001     }
10002 }
10003
10004 if ($T2H_VERBOSE)
10005 {
10006     print STDERR "# Expanded: ";
10007     foreach my $text_macro (keys(%text_macros))
10008     {
10009         print STDERR "$text_macro " if ($text_macros{$text_macro});
10010     }
10011     print STDERR "\n";
10012 }
10013
10014 # This is kept in that file although it is html formatting as it seems to 
10015 # be rather obsolete
10016 $Texi2HTML::Config::INVISIBLE_MARK = '<img src="invisible.xbm" alt="">' if $Texi2HTML::Config::INVISIBLE_MARK eq 'xbm';
10017
10018 $T2H_DEBUG |= $DEBUG_TEXI if ($Texi2HTML::Config::DUMP_TEXI);
10019
10020 # no user provided USE_UNICODE, use configure provided
10021 if (!defined($Texi2HTML::Config::USE_UNICODE))
10022 {
10023     $Texi2HTML::Config::USE_UNICODE = '1';
10024 }
10025
10026 # no user provided nor configured, run time test
10027 if ($Texi2HTML::Config::USE_UNICODE eq '@' .'USE_UNICODE@')
10028 {
10029     $Texi2HTML::Config::USE_UNICODE = 1;
10030     eval {
10031         require Encode;
10032         require Unicode::Normalize; 
10033         Encode->import('encode');
10034     };
10035     $Texi2HTML::Config::USE_UNICODE = 0 if ($@);
10036 }
10037 elsif ($Texi2HTML::Config::USE_UNICODE)
10038 {# user provided or set by configure
10039     require Encode;
10040     require Unicode::Normalize;
10041     Encode->import('encode');
10042 }
10043
10044 # no user provided USE_UNIDECODE, use configure provided
10045 if (!defined($Texi2HTML::Config::USE_UNIDECODE))
10046 {
10047     $Texi2HTML::Config::USE_UNIDECODE = '0';
10048 }
10049
10050 # no user provided nor configured, run time test
10051 if ($Texi2HTML::Config::USE_UNIDECODE eq '@' .'USE_UNIDECODE@')
10052 {
10053     $Texi2HTML::Config::USE_UNIDECODE = 1;
10054     eval {
10055         require Text::Unidecode;
10056         Text::Unidecode->import('unidecode');
10057     };
10058     $Texi2HTML::Config::USE_UNIDECODE = 0 if ($@);
10059 }
10060 elsif ($Texi2HTML::Config::USE_UNIDECODE)
10061 {# user provided or set by configure
10062     require Text::Unidecode;
10063     Text::Unidecode->import('unidecode');
10064 }
10065
10066 print STDERR "# USE_UNICODE $Texi2HTML::Config::USE_UNICODE, USE_UNIDECODE $Texi2HTML::Config::USE_UNIDECODE \n" 
10067   if ($T2H_VERBOSE);
10068
10069 # Construct hashes used for cross references generation
10070 # Do it now as the user may have changed $USE_UNICODE
10071
10072 foreach my $key (keys(%Texi2HTML::Config::unicode_map))
10073 {
10074     if ($Texi2HTML::Config::unicode_map{$key} ne '')
10075     {
10076         if ($Texi2HTML::Config::USE_UNICODE)
10077         {
10078             $cross_ref_texi_map{$key} = chr(hex($Texi2HTML::Config::unicode_map{$key}));
10079             if (($Texi2HTML::Config::TRANSLITERATE_NODE and !$Texi2HTML::Config::USE_UNIDECODE)
10080                 and (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}})))
10081             {
10082                 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
10083                  
10084             }
10085         }
10086         else
10087         {
10088             $cross_ref_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
10089             if ($Texi2HTML::Config::TRANSLITERATE_NODE)
10090             {
10091                 if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}))
10092                 {
10093                     $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
10094                 }
10095                 else
10096                 {
10097                      $cross_transliterate_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
10098                 }
10099             }
10100         }
10101     }
10102 }
10103 if ($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::TRANSLITERATE_NODE
10104      and ! $Texi2HTML::Config::USE_UNIDECODE)
10105 {
10106     foreach my $key (keys (%Texi2HTML::Config::transliterate_accent_map))
10107     {
10108         $Texi2HTML::Config::transliterate_map{$key} = $Texi2HTML::Config::transliterate_accent_map{$key};
10109     }
10110 }
10111
10112 foreach my $key (keys(%cross_ref_style_map_texi))
10113 {
10114     if ($style_type{$key} eq 'accent' 
10115         and (ref($cross_ref_style_map_texi{$key}) eq 'HASH'))
10116     {
10117         if ($Texi2HTML::Config::USE_UNICODE)
10118         {
10119              $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_utf8_accent;
10120         }
10121         else
10122         {
10123              $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_nounicode_cross_manual_accent;
10124         }
10125         if ($Texi2HTML::Config::TRANSLITERATE_NODE and 
10126            !($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::USE_UNIDECODE))
10127         {
10128              $cross_transliterate_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_transliterate_cross_manual_accent;
10129         }
10130     }
10131 }
10132
10133 #
10134 # file name business
10135 #
10136
10137
10138 my $docu_dir;            # directory of the document
10139 my $docu_name;           # basename of the document
10140 my $docu_rdir;           # directory for the output
10141 my $docu_ext = $Texi2HTML::Config::EXTENSION;   # extension
10142 my $docu_toc;            # document's table of contents
10143 my $docu_stoc;           # document's short toc
10144 my $docu_foot;           # document's footnotes
10145 my $docu_about;          # about this document
10146 my $docu_top;            # document top
10147 my $docu_doc;            # document (or document top of split)
10148
10149 die "Need exactly one file to translate\n$T2H_FAILURE_TEXT" unless @ARGV == 1;
10150 my $docu = shift(@ARGV);
10151 if ($docu =~ /(.*\/)/)
10152 {
10153     chop($docu_dir = $1);
10154     $docu_name = $docu;
10155     $docu_name =~ s/.*\///;
10156 }
10157 else
10158 {
10159     $docu_dir = '.';
10160     $docu_name = $docu;
10161 }
10162 unshift(@Texi2HTML::Config::INCLUDE_DIRS, $docu_dir);
10163 unshift(@Texi2HTML::Config::INCLUDE_DIRS, @Texi2HTML::Config::PREPEND_DIRS);
10164 $docu_name =~ s/\.te?x(i|info)?$//;
10165 $docu_name = $Texi2HTML::Config::PREFIX if $Texi2HTML::Config::PREFIX;
10166
10167 # resulting files splitting
10168 if ($Texi2HTML::Config::SPLIT =~ /section/i)
10169 {
10170     $Texi2HTML::Config::SPLIT = 'section';
10171 }
10172 elsif ($Texi2HTML::Config::SPLIT =~ /node/i)
10173 {
10174     $Texi2HTML::Config::SPLIT = 'node';
10175 }
10176 elsif ($Texi2HTML::Config::SPLIT =~ /chapter/i)
10177 {
10178     $Texi2HTML::Config::SPLIT = 'chapter';
10179 }
10180 else
10181 {
10182     $Texi2HTML::Config::SPLIT = '';
10183 }
10184
10185 # Something like backward compatibility
10186 if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SUBDIR)
10187 {
10188     $Texi2HTML::Config::OUT = $Texi2HTML::Config::SUBDIR;
10189 }
10190
10191 # subdir
10192
10193 die "output to STDOUT and split or frames incompatible\n" 
10194     if (($Texi2HTML::Config::SPLIT or $Texi2HTML::Config::FRAMES) and ($Texi2HTML::Config::OUT eq '-'));
10195
10196 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq ''))
10197 {
10198     $Texi2HTML::Config::OUT = $docu_name;
10199 }
10200
10201 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq '.'))
10202 {# This is to avoid trouble with latex2html
10203     $Texi2HTML::Config::OUT = '';
10204 }
10205
10206 $docu_rdir = '';
10207
10208 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne ''))
10209 {
10210     $Texi2HTML::Config::OUT =~ s|/*$||;
10211     $docu_rdir = "$Texi2HTML::Config::OUT/"; 
10212     unless (-d $Texi2HTML::Config::OUT)
10213     {
10214         if ( mkdir($Texi2HTML::Config::OUT, oct(755)))
10215         {
10216             print STDERR "# created directory $Texi2HTML::Config::OUT\n" if ($T2H_VERBOSE);
10217         }
10218         else
10219         {
10220             die "$ERROR can't create directory $Texi2HTML::Config::OUT\n";
10221         }
10222     }
10223     print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
10224 }
10225 elsif (! $Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne ''))
10226 {
10227     if ($Texi2HTML::Config::OUT =~ m|(.*)/|)
10228     {# there is a leading directories
10229         $docu_rdir = "$1/";
10230         unless (-d $docu_rdir)
10231         {
10232             if ( mkdir($docu_rdir, oct(755)))
10233             {
10234                  print STDERR "# created directory $docu_rdir\n" if ($T2H_VERBOSE);
10235             }
10236             else
10237             {
10238                 die "$ERROR can't create directory $docu_rdir\n";
10239             }
10240         }
10241         print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
10242     }
10243     else
10244     {
10245         print STDERR "# putting result files into current directory \n" if ($T2H_VERBOSE);
10246         $docu_rdir = '';
10247     }
10248 }
10249
10250 # We don't use "./" as $docu_rdir when $docu_rdir is the current directory
10251 # because it is problematic for latex2html. To test writability with -w, 
10252 # however we need a real directory.
10253 my $result_rdir = $docu_rdir;
10254 $result_rdir = "." if ($docu_rdir eq '');
10255 unless (-w $result_rdir)
10256 {
10257     $docu_rdir = 'current directory' if ($docu_rdir eq '');
10258     die "$ERROR $docu_rdir not writable\n";
10259 }
10260
10261 # relative path leading to the working directory from the document directory
10262 my $path_to_working_dir = $docu_rdir;
10263 if ($docu_rdir ne '')
10264 {
10265     my $cwd = cwd;
10266     my $docu_path = $docu_rdir;
10267     $docu_path = $cwd . '/' . $docu_path unless ($docu_path =~ /^\//);
10268     my @result = ();
10269     foreach my $element (split /\//, File::Spec->canonpath($docu_path))
10270     {
10271         if ($element eq '')
10272         {
10273             push @result, '';
10274         }
10275         elsif ($element eq '..')
10276         {
10277             if (@result and ($result[-1] eq ''))
10278             {
10279                 print STDERR "Too much .. in absolute file name\n";
10280             }
10281             elsif (@result and ($result[-1] ne '..'))
10282             {
10283                 pop @result;
10284             }
10285             else
10286             {
10287                 push @result, $element;
10288             }
10289         }
10290         else
10291         {
10292             push @result, $element;
10293         }
10294     }
10295     $path_to_working_dir = File::Spec->abs2rel($cwd, join ('/', @result));
10296     $path_to_working_dir =~ s|.*/||;
10297     $path_to_working_dir .= '/' unless($path_to_working_dir eq '');
10298 }
10299
10300 # extension
10301 if ($Texi2HTML::Config::SHORTEXTN)
10302 {
10303     $docu_ext = "htm";
10304 }
10305
10306 $docu_doc = $docu_name . ($docu_ext ? ".$docu_ext" : ""); # document's contents
10307 if ($Texi2HTML::Config::SPLIT)
10308 {
10309     $docu_top   = $Texi2HTML::Config::TOP_FILE || $docu_doc;
10310
10311     if (defined $Texi2HTML::Config::element_file_name)
10312     {
10313         $docu_toc = &$Texi2HTML::Config::element_file_name
10314             (undef, "toc", $docu_name);
10315         $docu_stoc = &$Texi2HTML::Config::element_file_name
10316             (undef, "stoc", $docu_name);
10317         $docu_foot = &$Texi2HTML::Config::element_file_name
10318             (undef, "foot", $docu_name);
10319         $docu_about = &$Texi2HTML::Config::element_file_name
10320             (undef, "about", $docu_name);
10321         # $docu_top may be overwritten later.
10322     }
10323     if (!defined($docu_toc))
10324     {
10325         my $default_toc = "${docu_name}_toc";
10326         $default_toc .= ".$docu_ext" if (defined($docu_ext));
10327         $docu_toc   = $Texi2HTML::Config::TOC_FILE || $default_toc;
10328     }
10329     if (!defined($docu_stoc))
10330     {
10331         $docu_stoc  = "${docu_name}_ovr";
10332         $docu_stoc .= ".$docu_ext" if (defined($docu_ext));
10333     }
10334     if (!defined($docu_foot))
10335     {
10336         $docu_foot  = "${docu_name}_fot";
10337         $docu_foot .= ".$docu_ext" if (defined($docu_ext));
10338     }
10339     if (!defined($docu_about))
10340     {
10341         $docu_about = "${docu_name}_abt";
10342         $docu_about .= ".$docu_ext" if (defined($docu_ext));
10343     }
10344 }
10345 else
10346 {
10347     if ($Texi2HTML::Config::OUT)
10348     {
10349         $docu_doc = $Texi2HTML::Config::OUT;
10350         $docu_doc =~ s|.*/||;
10351     }
10352     if (defined $Texi2HTML::Config::element_file_name)
10353     {
10354         my $docu_name = &$Texi2HTML::Config::element_file_name
10355            (undef, "doc", $docu_name);
10356         $docu_top = $docu_name if (defined($docu_name));
10357     } 
10358     $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc;
10359 }
10360
10361 # Note that file extension has already been added here.
10362
10363 # For use in init files
10364 $Texi2HTML::THISDOC{'filename'}->{'top'} = $docu_top;
10365 $Texi2HTML::THISDOC{'filename'}->{'foot'} = $docu_foot;
10366 $Texi2HTML::THISDOC{'filename'}->{'stoc'} = $docu_stoc;
10367 $Texi2HTML::THISDOC{'filename'}->{'about'} = $docu_about;
10368 $Texi2HTML::THISDOC{'filename'}->{'toc'} = $docu_toc;
10369 $Texi2HTML::THISDOC{'extension'} = $docu_ext;
10370 # FIXME document that
10371 $Texi2HTML::THISDOC{'out_dir'} = $docu_rdir;
10372 $Texi2HTML::THISDOC{'file_base_name'} = $docu_name;
10373
10374
10375 my $docu_doc_file = "$docu_rdir$docu_doc"; 
10376 my $docu_toc_file  = "$docu_rdir$docu_toc";
10377 my $docu_stoc_file = "$docu_rdir$docu_stoc";
10378 my $docu_foot_file = "$docu_rdir$docu_foot";
10379 my $docu_about_file = "$docu_rdir$docu_about";
10380 my $docu_top_file  = "$docu_rdir$docu_top";
10381
10382 my $docu_frame_file =     "$docu_rdir${docu_name}_frame";
10383 $docu_frame_file .= ".$docu_ext" if $docu_ext;
10384 my $docu_toc_frame_file = "$docu_rdir${docu_name}_toc_frame";
10385 $docu_toc_frame_file .= ".$docu_ext" if $docu_ext;
10386
10387 #
10388 # _foo: internal variables to track @foo
10389 #
10390 foreach my $key ('_author', '_title', '_subtitle', '_shorttitlepage',
10391          '_settitle', '_setfilename', '_shorttitle', '_titlefont')
10392 {
10393     $value{$key} = '';            # prevent -w warnings
10394 }
10395 my $index;                         # ref on a hash for the index entries
10396 my %indices = ();                  # hash of indices names containing 
10397                                    #[ $pages, $entries ] (page indices and 
10398                                    # raw index entries)
10399 my @index_labels = ();             # array corresponding with @?index commands
10400                                    # constructed during pass_texi, used to
10401                                    # put labels in pass_text
10402 #
10403 # initial counters
10404 #
10405 my $foot_num = 0;
10406 my $relative_foot_num = 0;
10407 my $idx_num = 0;
10408 my $sec_num = 0;
10409 my $anchor_num = 0;
10410
10411 #
10412 # can I use ISO8859 characters? (HTML+)
10413 #
10414 if ($Texi2HTML::Config::USE_ISO)
10415 {
10416     foreach my $thing (keys(%Texi2HTML::Config::iso_symbols))
10417     {
10418          next unless exists ($::things_map_ref->{$thing});
10419          $::things_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
10420          $::pre_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
10421          $Texi2HTML::Config::simple_format_texi_map{$thing} = $Texi2HTML::Config::iso_symbols{$thing};
10422     }
10423     # we don't override the user defined quote, but beware that this works
10424     # only if the hardcoded defaults, '`' and "'" match with the defaults
10425     # in the default init file
10426     $Texi2HTML::Config::OPEN_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{'`'} 
10427         if (exists($Texi2HTML::Config::iso_symbols{'`'}) and ($Texi2HTML::Config::OPEN_QUOTE_SYMBOL eq '`'));
10428     $Texi2HTML::Config::CLOSE_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{"'"} 
10429        if (exists($Texi2HTML::Config::iso_symbols{"'"}) and ($Texi2HTML::Config::CLOSE_QUOTE_SYMBOL eq "'"));
10430 }
10431
10432
10433
10434 # process a css file
10435 sub process_css_file ($$)
10436 {
10437     my $fh =shift;
10438     my $file = shift;
10439     my $in_rules = 0;
10440     my $in_comment = 0;
10441     my $in_import = 0;
10442     my $in_string = 0;
10443     my $rules = [];
10444     my $imports = [];
10445     while (<$fh>)
10446     {
10447             #print STDERR "Line: $_";
10448         if ($in_rules)
10449         {
10450             push @$rules, $_;
10451             next;
10452         }
10453         my $text = '';
10454         while (1)
10455         { 
10456                 #sleep 1;
10457                 #print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $_";
10458              if ($in_comment)
10459              {
10460                  if (s/^(.*?\*\/)//)
10461                  {
10462                      $text .= $1;
10463                      $in_comment = 0;
10464                  }
10465                  else
10466                  {
10467                      push @$imports, $text . $_;
10468                      last;
10469                  }
10470              }
10471              elsif (!$in_string and s/^\///)
10472              { # what do '\' do here ?
10473                  if (s/^\*//)
10474                  {
10475                      $text .= '/*';
10476                      $in_comment = 1;
10477                  }
10478                  else
10479                  {
10480                      push (@$imports, $text. "\n") if ($text ne '');
10481                      push (@$rules, '/' . $_);
10482                      $in_rules = 1;
10483                      last;
10484                  }
10485              }
10486              elsif (!$in_string and $in_import and s/^([\"\'])//)
10487              { # strings outside of import start rules
10488                  $text .= "$1";
10489                  $in_string = quotemeta("$1");
10490              }
10491              elsif ($in_string and s/^(\\$in_string)//)
10492              {
10493                  $text .= $1;
10494              }
10495              elsif ($in_string and s/^($in_string)//)
10496              {
10497                  $text .= $1;
10498                  $in_string = 0;
10499              }
10500              elsif ((! $in_string and !$in_import) and (s/^([\\]?\@import)$// or s/^([\\]?\@import\s+)//))
10501              {
10502                  $text .= $1;
10503                  $in_import = 1;
10504              }
10505              elsif (!$in_string and $in_import and s/^\;//)
10506              {
10507                  $text .= ';';
10508                  $in_import = 0;
10509              }
10510              elsif (($in_import or $in_string) and s/^(.)//)
10511              {
10512                   $text .= $1;
10513              }
10514              elsif (!$in_import and s/^([^\s])//)
10515              { 
10516                   push (@$imports, $text. "\n") if ($text ne '');
10517                   push (@$rules, $1 . $_);
10518                   $in_rules = 1;
10519                   last;
10520              }
10521              elsif (s/^(\s)//)
10522              {
10523                   $text .= $1;
10524              }
10525              elsif ($_ eq '')
10526              {
10527                   push (@$imports, $text);
10528                   last;
10529              }
10530         } 
10531     }
10532     warn "$WARN string not closed in css file $file\n" if ($in_string);
10533     warn "$WARN comment not closed in css file $file\n" if ($in_comment);
10534     warn "$WARN \@import not finished in css file $file\n"  if ($in_import and !$in_comment and !$in_string);
10535     return ($imports, $rules);
10536 }
10537
10538
10539
10540 # parse texinfo cnf file for external manual specifications. This was
10541 # discussed on texinfo list but not in makeinfo for now. 
10542 my @texinfo_htmlxref_files = locate_init_file ($texinfo_htmlxref, 1, \@texinfo_config_dirs);
10543 foreach my $file (@texinfo_htmlxref_files)
10544 {
10545     print STDERR "html refs config file: $file\n" if ($T2H_DEBUG);    
10546     unless (open (HTMLXREF, $file))
10547     {
10548          warn "Cannot open html refs config file ${file}: $!";
10549          next;
10550     }
10551     while (<HTMLXREF>)
10552     {
10553         my $line = $_;
10554         s/[#]\s.*//;
10555         s/^\s*//;
10556         next if /^\s*$/;
10557         my @htmlxref = split /\s+/;
10558         my $manual = shift @htmlxref;
10559         my $split_or_mono = shift @htmlxref;
10560         if (!defined($split_or_mono) or ($split_or_mono ne 'split' and $split_or_mono ne 'mono'))
10561         {
10562             echo_warn("Bad line in $file: $line");
10563             next;
10564         }
10565         my $href = shift @htmlxref;
10566         next if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}) and exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'}));
10567         
10568         if (defined($href))
10569         {
10570             $href =~ s/\/*$// if ($split_or_mono eq 'split');
10571             $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'} = $href;
10572         }
10573         else
10574         {
10575             $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono} = {};
10576         }
10577     }
10578     close (HTMLXREF);
10579 }
10580
10581 if ($T2H_DEBUG)
10582 {
10583     foreach my $manual (keys(%{$Texi2HTML::THISDOC{'htmlxref'}}))
10584     {
10585          foreach my $split ('split', 'mono')
10586          {
10587               my $href = 'NO';
10588               next unless (exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split}));
10589               $href = $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split}->{'href'} if
10590                   exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split}->{'href'});
10591               print STDERR "$manual: $split, href: $href\n";
10592          }
10593     }
10594 }
10595
10596 print STDERR "# reading from $docu\n" if $T2H_VERBOSE;
10597
10598 #+++###########################################################################
10599 #                                                                             #
10600 # Pass texi: read source, handle variable, ignored text,                      #
10601 #                                                                             #
10602 #---###########################################################################
10603
10604 my @fhs = ();                   # hold the file handles to read
10605 my $input_spool;                # spooled lines to read
10606 my @lines = ();             # whole document
10607 my @lines_numbers = ();     # line number, originating file associated with 
10608                             # whole document 
10609 my $macros;                 # macros. reference on a hash
10610 my %info_enclose;           # macros defined with definfoenclose
10611 my $texi_line_number = { 'file_name' => '', 'line_nr' => 0, 'macro' => '' };
10612 my @floats = ();            # floats list
10613 my %floats = ();            # floats by style
10614
10615 sub initialise_state_texi($)
10616 {
10617     my $state = shift;
10618     $state->{'texi'} = 1;           # for substitute_text and close_stack: 
10619                                     # 1 if pass_texi/scan_texi is to be used
10620     $state->{'macro_inside'} = 0 unless(defined($state->{'macro_inside'}));
10621     $state->{'ifvalue_inside'} = 0 unless(defined($state->{'ifvalue_inside'}));
10622     $state->{'arg_expansion'} = 0 unless(defined($state->{'arg_expansion'}));
10623 }
10624
10625 my @first_lines = ();
10626
10627 sub pass_texi()
10628 {
10629     my $first_lines = 1;        # is it the first lines
10630     my $state = {};
10631                                 # holds the informations about the context
10632                                 # to pass it down to the functions
10633     initialise_state_texi($state);
10634     my @stack;
10635     my $text;
10636  INPUT_LINE: while (defined($_ = next_line($texi_line_number))) 
10637     {
10638         #
10639         # remove the lines preceding \input or an @-command
10640         # 
10641         if ($first_lines)
10642         {
10643             if (/^\\input/)
10644             {
10645                 push @first_lines, $_;
10646                 $first_lines = 0;
10647                 next;
10648             }
10649             if (/^\s*\@/)
10650             {
10651                 $first_lines = 0;
10652             }
10653             else
10654             {
10655                 push @first_lines, $_;
10656                 next;
10657             }
10658         }
10659         #print STDERR "PASS_TEXI($texi_line_number->{'line_nr'})$_";
10660         my $chomped_line = $_;
10661         if (scan_texi ($_, \$text, \@stack, $state, $texi_line_number) and chomp($chomped_line))
10662         {
10663         #print STDERR "==> new page (line_nr $texi_line_number->{'line_nr'},$texi_line_number->{'file_name'},$texi_line_number->{'macro'})\n";
10664             push (@lines_numbers, { 'file_name' => $texi_line_number->{'file_name'},
10665                   'line_nr' => $texi_line_number->{'line_nr'},
10666                   'macro' => $texi_line_number->{'macro'} });
10667         }
10668         #dump_stack (\$text, \@stack, $state);
10669         if ($state->{'bye'})
10670         {
10671             #dump_stack(\$text, \@stack, $state);
10672             # close stack after bye
10673             #print STDERR "close stack after bye\n";
10674             close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number);
10675             #dump_stack(\$text, \@stack, $state);
10676         }
10677         next if (@stack);
10678         $_ = $text;
10679         $text = '';
10680         if (!defined($_))
10681         {# FIXME: remove the error message if it is reported too often
10682             print STDERR "# \$_ undefined after scan_texi. This may be a bug, or not.\n";
10683             print STDERR "# Report (with texinfo file) if you want, otherwise ignore that message.\n";
10684             next unless ($state->{'bye'});
10685         }
10686         push @lines, split_lines($_);
10687         last if ($state->{'bye'});
10688     }
10689     # close stack at the end of pass texi
10690     #print STDERR "close stack at the end of pass texi\n";
10691     close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number);
10692     push @lines, split_lines($text);
10693     print STDERR "# end of pass texi\n" if $T2H_VERBOSE;
10694 }
10695
10696 # return the line after preserving things according to misc_command map.
10697 sub preserve_command($$)
10698 {
10699     my $line = shift;
10700     my $macro = shift;
10701     my $text = '';
10702     my $args = '';
10703     my $skip_spec = '';
10704     my $arg_spec = '';
10705
10706     $skip_spec = $Texi2HTML::Config::misc_command{$macro}->{'skip'}
10707         if (defined($Texi2HTML::Config::misc_command{$macro}->{'skip'}));
10708     $arg_spec = $Texi2HTML::Config::misc_command{$macro}->{'arg'}
10709         if (defined($Texi2HTML::Config::misc_command{$macro}->{'arg'}));
10710
10711     if ($arg_spec eq 'line')
10712     {
10713         $text .= $line;
10714         $args .= $line;
10715         $line = '';
10716     }
10717     elsif ($arg_spec)
10718     {
10719         my $arg_nr = $Texi2HTML::Config::misc_command{$macro}->{'arg'};
10720         while ($arg_nr)
10721         {
10722             $line =~ s/(\s+\S*)//o;
10723             $text .= $1 if defined($1);
10724             $args .= $1 if defined($1);
10725             $arg_nr--;
10726         }
10727     }
10728    
10729     if ($macro eq 'bye')
10730     {
10731         $line = '';
10732         $text = "\n";
10733     }
10734     elsif ($skip_spec eq 'linespace')
10735     {
10736         if ($line =~ /^\s*$/o)
10737         {
10738             $line =~ s/([ \t]*)//o;
10739             $text .= $1;
10740         }
10741     }
10742     elsif ($skip_spec eq 'linewhitespace')
10743     {
10744         if ($line =~ /^\s*$/o)
10745         {
10746             $text .= $line;
10747             $line = '';
10748         }       
10749     }
10750     elsif ($skip_spec eq 'line')
10751     {
10752         $text .= $line;
10753         $line = '';
10754     }
10755     elsif ($skip_spec eq 'whitespace')
10756     {
10757         $line =~ s/(\s*)//o;
10758         $text .=  $1;
10759     }
10760     elsif ($skip_spec eq 'space')
10761     {
10762         $line =~ s/([ \t]*)//o;
10763         $text .= $1;
10764     }
10765     $line = '' if (!defined($line));
10766     return ($line, $text, $args);
10767 }
10768
10769 #+++###########################################################################
10770 #                                                                             #
10771 # Pass structure: parse document structure                                    #
10772 #                                                                             #
10773 #---###########################################################################
10774
10775 # This is a virtual element for things appearing before @node and 
10776 # sectionning commands
10777 my $element_before_anything =
10778
10779     'before_anything' => 1,
10780     'place' => [],
10781     'texi' => 'VIRTUAL ELEMENT BEFORE ANYTHING',
10782 };
10783
10784 # This is a place for index entries, anchors and so on appearing in 
10785 # copying or documentdescription
10786 my $region_place = [];
10787
10788 sub initialise_state_structure($)
10789 {
10790     my $state = shift;
10791     $state->{'structure'} = 1;      # for substitute_text and close_stack: 
10792                                     # 1 if pass_structure/scan_structure is 
10793                                     # to be used
10794     $state->{'menu'} = 0;           # number of opened menus
10795     $state->{'detailmenu'} = 0;     # number of opened detailed menus      
10796     $state->{'sectionning_base'} = 0;         # current base sectionning level
10797     $state->{'table_stack'} = [ "no table" ]; # a stack of opened tables/lists
10798     if (exists($state->{'region_lines'}) and !defined($state->{'region_lines'}))
10799     {
10800         delete ($state->{'region_lines'});
10801         print STDERR "Bug: state->{'region_lines'} exists but undef.\n";
10802     }
10803 }
10804
10805 my @doc_lines = ();         # whole document
10806 my @doc_numbers = ();       # whole document line numbers and file names
10807 my @nodes_list = ();        # nodes in document reading order
10808                             # each member is a reference on a hash
10809 my @sections_list = ();     # sections in reading order
10810                             # each member is a reference on a hash
10811 my @all_elements = ();      # sectionning elements (nodes and sections)
10812                             # in reading order. Each member is a reference
10813                             # on a hash which also appears in %nodes,
10814                             # @sections_list @nodes_list, @elements_list
10815 my @elements_list;          # all the resulting elements in document order
10816 my %sections = ();          # sections hash. The key is the section number
10817                             # headings are there, although they are not elements
10818 my $section_top;            # @top section
10819 my $element_top;            # Top element
10820 my $node_top;               # Top node
10821 my $node_first;             # First node
10822 my $element_index;          # element with first index
10823 my $element_chapter_index;  # chapter with first index
10824 my $element_first;          # first element
10825 my $element_last;           # last element
10826 my %special_commands;       # hash for the commands specially handled 
10827                             # by the user 
10828
10829 # This is a virtual element used to have the right hrefs for index entries
10830 # and anchors in footnotes
10831 my $footnote_element = 
10832
10833     'id' => 'SEC_Foot',
10834     'file' => $docu_foot,
10835     'footnote' => 1,
10836     'element' => 1,
10837     'place' => [],
10838 };
10839
10840 my %content_element =
10841 (
10842     'contents' => { 'id' => 'SEC_Contents', 'contents' => 1, 'texi' => '_contents' },
10843     'shortcontents' => { 'id' => 'SEC_Overview', 'shortcontents' => 1, 'texi' => '_shortcontents' },
10844 );
10845
10846 #my $do_contents;            # do table of contents if true
10847 #my $do_scontents;           # do short table of contents if true
10848 my $novalidate = $Texi2HTML::Config::NOVALIDATE; # @novalidate appeared
10849
10850 sub pass_structure()
10851 {
10852     my $state = {};
10853                                 # holds the informations about the context
10854                                 # to pass it down to the functions
10855     initialise_state_structure($state);
10856     $state->{'element'} = $element_before_anything;
10857     $state->{'place'} = $element_before_anything->{'place'};
10858     my @stack;
10859     my $text;
10860     my $line_nr;
10861
10862     while (@lines)
10863     {
10864         $_ = shift @lines;
10865         my $chomped_line = $_;
10866         if (!chomp($chomped_line) and @lines)
10867         {
10868              $lines[0] = $_ . $lines[0];
10869              next;
10870         }
10871         $line_nr = shift (@lines_numbers);
10872         #print STDERR "PASS_STRUCTURE: $_";
10873         if (!$state->{'raw'} and !$state->{'verb'})
10874         {
10875             my $tag = '';
10876             if (/^\s*\@(\w+)\b/)
10877             {
10878                 $tag = $1;
10879             }
10880
10881             #
10882             # analyze the tag
10883             #
10884             if ($tag and $tag eq 'node' or defined($sec2level{$tag}) or $tag eq 'printindex')
10885             {
10886                 $_ = substitute_texi_line($_); 
10887                 if ($tag eq 'node' or defined($sec2level{$tag}))
10888                 {# in pass structure node shouldn't appear in formats
10889                     close_stack_texi_structure(\$text, \@stack, $state, $line_nr);
10890                     if (exists($state->{'region_lines'}))
10891                     {
10892                         push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($text);
10893                         close_region($state); 
10894                     }
10895                     else
10896                     {
10897                         push @doc_lines, split_lines($text);
10898                     }
10899                     $text = '';
10900                 }
10901                 if ($tag eq 'node')
10902                 {
10903                     my $node_ref;
10904                     my $auto_directions;
10905                     $auto_directions = 1 unless (/,/o);
10906                     my ($node, $node_next, $node_prev, $node_up) = split(/,/, $_);
10907                     $node =~ s/^\@node\s+// if ($node);
10908                     if ($node)
10909                     {
10910                         $node = normalise_space($node);
10911                         if (exists($nodes{$node}) and defined($nodes{$node})
10912                              and $nodes{$node}->{'seen'})
10913                         {
10914                             echo_error ("Duplicate node found: $node", $line_nr);
10915                             next;
10916                         }
10917                         else
10918                         {
10919                             if (exists($nodes{$node}) and defined($nodes{$node}))
10920                             { # node appeared in a menu
10921                                 $node_ref = $nodes{$node};
10922                             }
10923                             else
10924                             {
10925                                 my $first;
10926                                 $first = 1 if (!defined($node_ref));
10927                                 $node_ref = {};
10928                                 $node_first = $node_ref if ($first);
10929                                 $nodes{$node} = $node_ref;
10930                             }
10931                             $node_ref->{'node'} = 1;
10932                             $node_ref->{'tag'} = 'node';
10933                             $node_ref->{'tag_level'} = 'node';
10934                             $node_ref->{'texi'} = $node;
10935                             $node_ref->{'seen'} = 1;
10936                             $node_ref->{'automatic_directions'} = $auto_directions;
10937                             $node_ref->{'place'} = [];
10938                             $node_ref->{'current_place'} = [];
10939                             merge_element_before_anything($node_ref);
10940                             $node_ref->{'index_names'} = [];
10941                             $state->{'place'} = $node_ref->{'current_place'};
10942                             $state->{'element'} = $node_ref;
10943                             $state->{'after_element'} = 1;
10944                             $state->{'node_ref'} = $node_ref;
10945                             # makeinfo treats differently case variants of
10946                             # top in nodes and anchors and in refs commands and 
10947                             # refs from nodes. 
10948                             if ($node =~ /^top$/i)
10949                             {
10950                                 if (!defined($node_top))
10951                                 {
10952                                     $node_top = $node_ref;
10953                                     $node_top->{'texi'} = 'Top';
10954                                     delete $nodes{$node};
10955                                     $nodes{$node_top->{'texi'}} = $node_ref;
10956                                 }
10957                                 else
10958                                 { # All the refs are going to point to the first Top
10959                                     echo_warn ("Top node allready exists", $line_nr);
10960                                     #warn "$WARN Top node allready exists\n";
10961                                 }
10962                             }
10963                             unless (@nodes_list)
10964                             {
10965                                 $node_ref->{'first'} = 1;
10966                             }
10967                             push (@nodes_list, $node_ref);
10968                             push @all_elements, $node_ref;
10969                         }
10970                     }
10971                     else
10972                     {
10973                         echo_error ("Node is undefined: $_ (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)", $line_nr);
10974                         next;
10975                     }
10976
10977                     if ($node_next)
10978                     {
10979                         $node_ref->{'node_next'} = normalise_node($node_next);
10980                     }
10981                     if ($node_prev)
10982                     {
10983                         $node_ref->{'node_prev'} = normalise_node($node_prev);
10984                     }
10985                     if ($node_up)
10986                     { 
10987                         $node_ref->{'node_up'} = normalise_node($node_up);
10988                     }
10989                 }
10990                 elsif (defined($sec2level{$tag}))
10991                 { # section or heading
10992                     if (/^\@$tag\s*(.*)$/)
10993                     {
10994                         my $name = normalise_space($1);
10995                         $name = '' if (!defined($name));
10996                         my $level = $sec2level{$tag};
10997                         $state->{'after_element'} = 1;
10998                         my ($docid, $num);
10999                         if($tag ne 'top')
11000                         {
11001                             $sec_num++;
11002                             $num = $sec_num;
11003                             $docid = "SEC$sec_num";
11004                         }
11005                         else
11006                         {
11007                             $num = 0;
11008                             $docid = "SEC_Top";
11009                         }
11010                         if ($tag !~ /heading/)
11011                         {
11012                             my $section_ref = { 'texi' => $name, 
11013                                'level' => $level,
11014                                'tag' => $tag,
11015                                'sec_num' => $num,
11016                                'section' => 1, 
11017                                'id' => $docid,
11018                                'seen' => 1,
11019                                'index_names' => [],
11020                                'current_place' => [],
11021                                'place' => []
11022                             };
11023              
11024                             if ($tag eq 'top')
11025                             {
11026                                 $section_ref->{'top'} = 1;
11027                                 $section_ref->{'number'} = '';
11028                                 $sections{0} = $section_ref;
11029                                 $section_top = $section_ref;
11030                             }
11031                             $sections{$num} = $section_ref;
11032                             merge_element_before_anything($section_ref);
11033                             if ($state->{'node_ref'} and !exists($state->{'node_ref'}->{'with_section'}))
11034                             {
11035                                 my $node_ref = $state->{'node_ref'};
11036                                 $section_ref->{'node_ref'} = $node_ref;
11037                                 $section_ref->{'titlefont'} = $node_ref->{'titlefont'};
11038                                 $node_ref->{'with_section'} = $section_ref;
11039                                 $node_ref->{'top'} = 1 if ($tag eq 'top');
11040                             }
11041                             if (! $name and $level)
11042                             {
11043                                echo_warn ("$tag without name", $line_nr);
11044                             }
11045                             push @sections_list, $section_ref;
11046                             push @all_elements, $section_ref;
11047                             $state->{'element'} = $section_ref;
11048                             $state->{'place'} = $section_ref->{'current_place'};
11049                             my $node_ref = "NO NODE";
11050                             my $node_texi ='';
11051                             if ($state->{'node_ref'})
11052                             {
11053                                 $node_ref = $state->{'node_ref'};
11054                                 $node_texi = $state->{'node_ref'}->{'texi'};
11055                             }
11056                             print STDERR "# pass_structure node($node_ref)$node_texi, tag \@$tag($level) ref $section_ref, num,id $num,$docid\n   $name\n"
11057                                if $T2H_DEBUG & $DEBUG_ELEMENTS;
11058                         }
11059                         else 
11060                         {
11061                             my $section_ref = { 'texi' => $name, 
11062                                 'level' => $level,
11063                                 'heading' => 1,
11064                                 'tag' => $tag,
11065                                 'tag_level' => $tag,
11066                                 'sec_num' => $sec_num, 
11067                                 'id' => $docid,
11068                                 'number' => '' };
11069                             $state->{'element'} = $section_ref;
11070                             push @{$state->{'place'}}, $section_ref;
11071                             $sections{$sec_num} = $section_ref;
11072                         }
11073                     }
11074                 }
11075                 elsif (/^\@printindex\s+(\w+)/)
11076                 {
11077                     unless (@all_elements)
11078                     {
11079                         echo_warn ("Printindex before document beginning: \@printindex $1", $line_nr);
11080                         next;
11081                     }
11082                     delete $state->{'after_element'};
11083                     # $element_index is the first element with index
11084                     $element_index = $all_elements[-1] unless (defined($element_index));
11085                     # associate the index to the element such that the page
11086                     # number is right
11087                     my $placed_elements = [];
11088                     push @{$all_elements[-1]->{'index_names'}}, { 'name' => $1, 'place' => $placed_elements };
11089                     $state->{'place'} = $placed_elements;
11090                 }
11091                 if (exists($state->{'region_lines'}))
11092                 {
11093                     push @{$region_lines{$state->{'region_lines'}->{'format'}}}, $_;
11094                 }
11095                 else
11096                 {
11097                     push @doc_lines, $_;
11098                     push @doc_numbers, $line_nr;
11099                 }
11100                 next;
11101             }
11102         }
11103         if (scan_structure ($_, \$text, \@stack, $state, $line_nr) and !(exists($state->{'region_lines'})))
11104         {
11105             push (@doc_numbers, $line_nr);
11106         }
11107         next if (@stack);
11108         $_ = $text;
11109         $text = '';
11110         next if (!defined($_));
11111         if ($state->{'region_lines'})
11112         {
11113             push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($_);
11114         }
11115         else
11116         {
11117             push @doc_lines, split_lines($_);
11118         }
11119     }
11120     if (@stack)
11121     {# close stack at the end of pass structure
11122         close_stack_texi_structure(\$text, \@stack, $state, $line_nr);
11123         if ($text)
11124         {
11125             if (exists($state->{'region_lines'}))
11126             {
11127                 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, 
11128                    split_lines($text);
11129             }
11130             else
11131             {
11132                 push @doc_lines, split_lines($text);
11133             }
11134         }
11135     }
11136     echo_warn ("At end of document, $state->{'region_lines'}->{'number'} $state->{'region_lines'}->{'format'} not closed") if (exists($state->{'region_lines'}));
11137     print STDERR "# end of pass structure\n" if $T2H_VERBOSE;
11138 }
11139
11140 # split line at end of line and put each resulting line in an array
11141 # FIXME there must be a more perlish way to do it... Not a big deal 
11142 # as long as it work
11143 sub split_lines($)
11144 {
11145    my $line = shift;
11146    my @result = ();
11147    my $i = 0;
11148    while ($line)
11149    {
11150        $result[$i] = '';
11151        $line =~ s/^(.*)//;
11152        $result[$i] .= $1;
11153        $result[$i] .= "\n" if ($line =~ s/^\n//);
11154        #print STDERR "$i: $result[$i]";
11155        $i++;
11156    }
11157    return @result;
11158 }
11159
11160 # handle misc commands and misc command args
11161 sub misc_command_structure($$$$)
11162 {
11163     my $line = shift;
11164     my $macro = shift;
11165     my $state = shift;
11166     my $line_nr = shift;
11167     my $text;
11168     my $args;
11169
11170     if ($macro eq 'lowersections')
11171     {
11172         my ($sec, $level);
11173         while (($sec, $level) = each %sec2level)
11174         {
11175             $sec2level{$sec} = $level + 1;
11176         }
11177         $state->{'sectionning_base'}--;
11178     }
11179     elsif ($macro eq 'raisesections')
11180     {
11181         my ($sec, $level);
11182         while (($sec, $level) = each %sec2level)
11183         {
11184             $sec2level{$sec} = $level - 1;
11185         }
11186         $state->{'sectionning_base'}++;
11187     }
11188     elsif (($macro eq 'contents') or ($macro eq 'summarycontents') or ($macro eq 'shortcontents'))
11189     {
11190         if ($macro eq 'contents')
11191         {
11192              $Texi2HTML::Config::DO_CONTENTS = 1;
11193         }
11194         else
11195         {
11196              $macro = 'shortcontents';
11197              $Texi2HTML::Config::DO_SCONTENTS = 1;
11198         }
11199         push @{$state->{'place'}}, $content_element{$macro};
11200     }
11201     elsif ($macro eq 'detailmenu')
11202     {
11203         $state->{'detailmenu'}++;
11204     }
11205     elsif ($macro eq 'novalidate')
11206     {
11207         $novalidate = 1;
11208         $Texi2HTML::THISDOC{$macro} = 1; 
11209     }
11210     elsif (grep {$_ eq $macro} ('settitle','setfilename','shortitle','shorttitlepage') 
11211              and ($line =~ /^\s+(.*)$/))
11212     {
11213         $value{"_$macro"} = substitute_texi_line($1);
11214     }
11215     elsif (grep {$_ eq $macro} ('author','subtitle','title')
11216              and ($line =~ /^\s+(.*)$/))
11217     {
11218         $value{"_$macro"} .= substitute_texi_line($1)."\n";
11219         push @{$Texi2HTML::THISDOC{"${macro}s"}}, substitute_texi_line($1);
11220     }
11221     elsif ($macro eq 'synindex' || $macro eq 'syncodeindex')
11222     {
11223         if ($line =~ /^\s+(\w+)\s+(\w+)/)
11224         {
11225             my $index_from = $1;
11226             my $index_to = $2;
11227             echo_error ("unknown from index name $index_from in \@$macro", $line_nr)
11228                 unless $index_names{$index_from};
11229             echo_error ("unknown to index name $index_to in \@$macro", $line_nr)
11230                 unless $index_names{$index_to};
11231             if ($index_names{$index_from} and $index_names{$index_to})
11232             {
11233                 if ($macro eq 'syncodeindex')
11234                 {
11235                     $index_names{$index_to}->{'associated_indices_code'}->{$index_from} = 1;
11236                 }
11237                 else
11238                 {
11239                     $index_names{$index_to}->{'associated_indices'}->{$index_from} = 1;
11240                 }
11241                 push @{$Texi2HTML::THISDOC{$macro}}, [$index_from,$index_to]; 
11242             }
11243         }
11244         else
11245         {
11246             echo_error ("Bad $macro line: $line", $line_nr);
11247         }
11248     }
11249     elsif ($macro eq 'defindex' || $macro eq 'defcodeindex')
11250     {
11251         if ($line =~ /^\s+(\w+)\s*$/)
11252         {
11253             my $name = $1;
11254             if ($forbidden_index_name{$name})
11255             {
11256                 echo_error("Reserved index name $name", $line_nr);
11257             }
11258             else
11259             {
11260                 @{$index_names{$name}->{'prefix'}} = ($name);
11261                 $index_names{$name}->{'code'} = 1 if $macro eq 'defcodeindex';
11262                 $index_prefix_to_name{$name} = $name;
11263                 push @{$Texi2HTML::THISDOC{$macro}}, $name; 
11264             }
11265         }
11266         else
11267         {# makeinfo don't warn and even accepts index with empty name
11268          # and index with numbers only. I reported it on the mailing list
11269          # this should be fixed in future makeinfo versions.
11270             echo_error ("Bad $macro line: $line", $line_nr);
11271         }
11272     }
11273     elsif ($macro eq 'documentlanguage')
11274     {
11275         if ($line =~ /\s+(\w+)/)
11276         {
11277             my $lang = $1;
11278             set_document_language($lang, 0, $line_nr) if (!$cmd_line_lang && $lang);
11279             # warning, this is not the language of the document but the one that
11280             # appear in the texinfo...
11281             $Texi2HTML::THISDOC{$macro} = $lang; 
11282         }
11283     }
11284     elsif ($macro eq 'kbdinputstyle')
11285     {# makeinfo ignores that with --html. I reported it and it should be 
11286      # fixed in future makeinfo releases
11287         if ($line =~ /\s+([a-z]+)/)
11288         {
11289             if ($1 eq 'code')
11290             {
11291                 $::style_map_ref->{'kbd'} = $::style_map_ref->{'code'};
11292                 $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'};
11293                 $Texi2HTML::THISDOC{$macro} = $1;
11294             }
11295             elsif ($1 eq 'example')
11296             {
11297                 $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'};
11298                 $Texi2HTML::THISDOC{$macro} = $1;
11299             }
11300             elsif ($1 ne 'distinct')
11301             {
11302                 echo_error ("Unknown argument for \@$macro: $1", $line_nr);
11303             }
11304         }
11305         else
11306         {
11307             echo_error ("Bad \@$macro", $line_nr);
11308         }
11309     }
11310     elsif ($macro eq 'paragraphindent')
11311     {
11312         if ($line =~ /\s+([0-9]+)/)
11313         {
11314             $Texi2HTML::THISDOC{$macro} = $1;
11315         }
11316         elsif (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(asis)[^\w\-]/))
11317         {
11318             $Texi2HTML::THISDOC{$macro} = $1;
11319         }
11320         else
11321         {
11322             echo_error ("Bad \@$macro", $line_nr);
11323         }
11324     }
11325     elsif ($macro eq 'firstparagraphindent')
11326     {
11327         if (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(insert)[^\w\-]/))
11328         {
11329             $Texi2HTML::THISDOC{$macro} = $1;
11330         }
11331         else
11332         {
11333             echo_error ("Bad \@$macro", $line_nr);
11334         }
11335     }
11336     elsif ($macro eq 'exampleindent')
11337     {
11338         if ($line =~ /^\s+([0-9]+)/)
11339         {
11340             $Texi2HTML::THISDOC{$macro} = $1;
11341         }
11342         elsif ($line =~ /^\s+(asis)[^\w\-]/)
11343         {
11344             $Texi2HTML::THISDOC{$macro} = $1;
11345         }
11346         else
11347         {
11348             echo_error ("Bad \@$macro", $line_nr);
11349         }
11350     }
11351     elsif ($macro eq 'frenchspacing')
11352     {
11353         if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/))
11354         {
11355             $Texi2HTML::THISDOC{$macro} = $1;
11356         }
11357         else
11358         {
11359             echo_error ("Bad \@$macro", $line_nr);
11360         }
11361     }
11362     elsif ($macro eq 'footnotestyle')
11363     {
11364         if (($line =~ /^\s+(end)[^\w\-]/) or ($line =~ /^\s+(separate)[^\w\-]/))
11365         {
11366             $Texi2HTML::THISDOC{$macro} = $1;
11367         }
11368         else
11369         {
11370             echo_error ("Bad \@$macro", $line_nr);
11371         }
11372     }
11373     elsif ($macro eq 'headings')
11374     {
11375         my $valid_arg = 0;
11376         foreach my $possible_arg (('off','on','single','double',
11377                       'singleafter','doubleafter'))
11378         {
11379             if ($line =~ /^\s+($possible_arg)[^\w\-]/)
11380             {   
11381                 $valid_arg = 1;
11382                 $Texi2HTML::THISDOC{$macro} = $possible_arg;
11383                 last;
11384             }
11385         }
11386         unless ($valid_arg)
11387         {
11388             echo_error ("Bad \@$macro", $line_nr);
11389         }
11390     }
11391     elsif ($macro eq 'setchapternewpage')
11392     {
11393         if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/)
11394                 or ($line =~ /^\s+(odd)[^\w\-]/))
11395         {
11396             $Texi2HTML::THISDOC{$macro} = $1;
11397         }
11398         else
11399         {
11400             echo_error ("Bad \@$macro", $line_nr);
11401         }
11402     }
11403     elsif ($macro eq 'setcontentsaftertitlepage' or $macro eq 'setshortcontentsaftertitlepage')
11404     {
11405         $Texi2HTML::THISDOC{$macro} = 1;
11406         my $tag = 'contents';
11407         $tag = 'shortcontents' if ($macro ne 'setcontentsaftertitlepage');
11408         $content_element{$tag}->{'aftertitlepage'} = 1;
11409     }
11410     elsif (grep {$macro eq $_} ('everyheading', 'everyfooting',
11411           'evenheading', 'evenfooting', 'oddheading', 'oddfooting'))
11412     {
11413         my $arg = $line;
11414         $arg =~ s/^\s+//;
11415         $Texi2HTML::THISDOC{$macro} = $arg;
11416     }
11417     elsif ($macro eq 'need')
11418     {
11419         unless (($line =~ /^\s+([0-9]+(\.[0-9]*)?)[^\w\-]/) or 
11420                  ($line =~ /^\s+(\.[0-9]+)[^\w\-]/))
11421         {
11422             echo_warn ("Bad \@$macro", $line_nr);
11423         }
11424     }
11425
11426     ($text, $line, $args) = preserve_command($line, $macro);
11427     return ($text, $line);
11428 }
11429
11430 # return the line after removing things according to misc_command map.
11431 # if the skipped macro has an effect it is done here
11432 # this is used during pass_text
11433 sub misc_command_text($$$$$$)
11434 {
11435     my $line = shift;
11436     my $macro = shift;
11437     my $stack = shift;
11438     my $state = shift;
11439     my $text = shift;
11440     my $line_nr = shift;
11441     my ($skipped, $remaining, $args);
11442     # if it is true the command args are kept so the user can modify how
11443     # they are skipped and handle them as unknown @-commands
11444     my $keep = $Texi2HTML::Config::misc_command{$macro}->{'keep'};
11445
11446     if ($macro eq 'detailmenu')
11447     {
11448         $state->{'detailmenu'}++;
11449     }
11450     elsif ($macro eq 'sp')
11451     {
11452         my $sp_number;
11453         if ($line =~ /^\s+(\d+)\s/)
11454         {
11455             $sp_number = $1;
11456         }
11457         elsif ($line =~ /(\s*)$/)
11458         {
11459             $sp_number = '';
11460         }
11461         else
11462         {
11463             echo_error ("\@$macro needs a numeric arg or no arg", $line_nr);
11464         }
11465         $sp_number = 1 if ($sp_number eq '');
11466         if (!$state->{'remove_texi'})
11467         {
11468             add_prev($text, $stack, &$Texi2HTML::Config::sp($sp_number, $state->{'preformatted'}));
11469         }
11470     }
11471     elsif($macro eq 'verbatiminclude' and !$keep)
11472     {
11473         if ($line =~ /\s+(.+)/)
11474         {
11475             my $arg = $1;
11476             my $file = locate_include_file($arg);
11477             if (defined($file))
11478             {
11479                 if (!open(VERBINCLUDE, $file))
11480                 {
11481                     echo_warn ("Can't read file $file: $!",$line_nr);
11482                 }
11483                 else
11484                 {
11485                     my $verb_text = '';
11486                     while (my $line = <VERBINCLUDE>)
11487                     {
11488                         $verb_text .= $line;
11489                     }
11490                     
11491                     if ($state->{'remove_texi'})
11492                     {
11493                         add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi('verbatim', $verb_text));
11494                     }
11495                     else
11496                     { 
11497                         add_prev($text, $stack, &$Texi2HTML::Config::raw('verbatim', $verb_text));
11498                     }
11499                     close VERBINCLUDE;
11500                 }
11501             }
11502             else
11503             {
11504                 echo_error ("Can't find $arg, skipping", $line_nr);
11505             }
11506         }
11507         else
11508         {
11509             echo_error ("Bad \@$macro line: $_", $line_nr);
11510         }
11511     }
11512     elsif ($macro eq 'indent' or $macro eq 'noindent')
11513     {
11514         $state->{'paragraph_indent'} = $macro;
11515     }
11516     ($remaining, $skipped, $args) = preserve_command($line, $macro);
11517     return ($skipped) if ($keep);
11518     return $remaining if ($remaining ne '');
11519     return undef;
11520 }
11521
11522 # merge the things appearing before the first @node or sectionning command
11523 # (held by element_before_anything) with the current element 
11524 # do that only once.
11525 sub merge_element_before_anything($)
11526 {
11527     my $element = shift;
11528     if (exists($element_before_anything->{'place'}))
11529     {
11530         $element->{'current_place'} = $element_before_anything->{'place'};
11531         delete $element_before_anything->{'place'};
11532         foreach my $placed_thing (@{$element->{'current_place'}})
11533         {
11534             $placed_thing->{'element'} = $element if (exists($placed_thing->{'element'}));
11535         }
11536     }
11537     # this is certainly redundant with the above condition, but cleaner 
11538     # that way
11539     if (exists($element_before_anything->{'titlefont'}))
11540     {
11541         $element->{'titlefont'} = $element_before_anything->{'titlefont'};
11542         delete $element_before_anything->{'titlefont'};
11543     }
11544 }
11545
11546 # find menu_prev, menu_up... for a node in menu
11547 sub menu_entry_texi($$$)
11548 {
11549     my $node = shift;
11550     my $state = shift;
11551     my $line_nr = shift;
11552     my $node_menu_ref = {};
11553     if (exists($nodes{$node}))
11554     {
11555         $node_menu_ref = $nodes{$node};
11556     }
11557     else
11558     {
11559         $nodes{$node} = $node_menu_ref;
11560         $node_menu_ref->{'texi'} = $node;
11561         $node_menu_ref->{'external_node'} = 1 if ($node =~ /\(.+\)/);
11562     }
11563     return if ($state->{'detailmenu'});
11564     if ($state->{'node_ref'})
11565     {
11566         $node_menu_ref->{'menu_up'} = $state->{'node_ref'};
11567         $node_menu_ref->{'menu_up_hash'}->{$state->{'node_ref'}->{'texi'}} = 1;
11568     }
11569     else
11570     {
11571         echo_warn ("menu entry without previous node: $node", $line_nr) unless ($node =~ /\(.+\)/);
11572     }
11573     if ($state->{'prev_menu_node'})
11574     {
11575         $node_menu_ref->{'menu_prev'} = $state->{'prev_menu_node'};
11576         $state->{'prev_menu_node'}->{'menu_next'} = $node_menu_ref;
11577     }
11578     elsif ($state->{'node_ref'})
11579     {
11580         $state->{'node_ref'}->{'menu_child'} = $node_menu_ref;
11581     }
11582     $state->{'prev_menu_node'} = $node_menu_ref;
11583 }
11584
11585 sub equivalent_nodes($)
11586 {
11587     my $name = shift;
11588 #print STDERR "equivalent_nodes $name\n";
11589     my $node = normalise_node($name);
11590     $name = cross_manual_line($node);
11591     my @equivalent_nodes = ();
11592     if (exists($cross_reference_nodes{$name}))
11593     {
11594         @equivalent_nodes = grep {$_ ne $node} @{$cross_reference_nodes{$name}};
11595     }
11596     return @equivalent_nodes;
11597 }
11598
11599 my %files = ();   # keys are files. This is used to avoid reusing an allready
11600                   # used file name
11601 my %empty_indices = (); # value is true for an index name key if the index 
11602                         # is empty
11603 my %printed_indices = (); # value is true for an index name not empty and
11604                           # printed
11605
11606 # find next, prev, up, back, forward, fastback, fastforward
11607 # find element id and file
11608 # split index pages
11609 # associate placed items (items which have links to them) with the right 
11610 # file and id
11611 # associate nodes with sections
11612 sub rearrange_elements()
11613 {
11614     print STDERR "# find sections levels and toplevel\n"
11615         if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11616     
11617     my $toplevel = 4;
11618     # correct level if raisesections or lowersections overflowed
11619     # and find toplevel level
11620     # use %sections to modify also the headings
11621     foreach my $section (values(%sections))
11622     {
11623         my $level = $section->{'level'};
11624         if ($level > $MAX_LEVEL)
11625         {
11626              $section->{'level'} = $MAX_LEVEL;
11627         }
11628         elsif ($level < $MIN_LEVEL and !$section->{'top'})
11629         {
11630              $section->{'level'} = $MIN_LEVEL;
11631         }
11632         else
11633         {
11634              $section->{'level'} = $level;
11635         }
11636         $section->{'toc_level'} = $section->{'level'};
11637         # This is for top
11638         $section->{'toc_level'} = $MIN_LEVEL if ($section->{'level'} < $MIN_LEVEL);
11639         # find the new tag corresponding with the level of the section
11640         if ($section->{'tag'} !~ /heading/ and ($level ne $reference_sec2level{$section->{'tag'}}))
11641         {
11642              $section->{'tag_level'} = $level2sec{$section->{'tag'}}->[$section->{'level'}];
11643         }
11644         else
11645         {
11646              $section->{'tag_level'} = $section->{'tag'};
11647         }
11648         $toplevel = $section->{'level'} if (($section->{'level'} < $toplevel) and ($section->{'level'} > 0 and ($section->{'tag'} !~ /heading/)));
11649         print STDERR "# section level $level: $section->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11650     }
11651     
11652     print STDERR "# find sections structure, construct section numbers (toplevel=$toplevel)\n"
11653         if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11654     my $in_appendix = 0;
11655     # these arrays have an element per sectionning level. 
11656     my @previous_numbers = ();   # holds the number of the previous sections
11657                                  # at the same and upper levels
11658     my @previous_sections = ();  # holds the ref of the previous sections
11659     
11660     foreach my $section (@sections_list)
11661     {
11662         ########################### debug
11663         print STDERR "BUG: node or section_ref defined for section $section->{'texi'}\n"
11664             if (exists($section->{'node'}) or exists($section->{'section_ref'}));
11665         ########################### end debug
11666         next if ($section->{'top'});
11667         print STDERR "Bug level undef for ($section) $section->{'texi'}\n" if (!defined($section->{'level'}));
11668         $section->{'toplevel'} = 1 if ($section->{'level'} == $toplevel);
11669         # undef things under that section level
11670         for (my $level = $section->{'level'} + 1; $level < $MAX_LEVEL + 1 ; $level++)
11671         {
11672             $previous_numbers[$level] = undef;
11673             $previous_sections[$level] = undef;
11674         }
11675         my $number_set;
11676         # find number at the current level
11677         if ($section->{'tag'} =~ /appendix/ and !$in_appendix)
11678         {
11679             $previous_numbers[$toplevel] = 'A';
11680             $in_appendix = 1;
11681             $number_set = 1 if ($section->{'level'} == $toplevel);
11682         }
11683         if (!defined($previous_numbers[$section->{'level'}]) and !$number_set)
11684         {
11685             if ($section->{'tag'} =~ /unnumbered/)
11686             {
11687                  $previous_numbers[$section->{'level'}] = undef;
11688             }
11689             else
11690             {
11691                 $previous_numbers[$section->{'level'}] = 1;
11692             }
11693         }
11694         elsif ($section->{'tag'} !~ /unnumbered/ and !$number_set)
11695         {
11696             $previous_numbers[$section->{'level'}]++;
11697         }
11698         # construct the section number
11699         $section->{'number'} = '';
11700
11701         unless ($section->{'tag'} =~ /unnumbered/)
11702         { 
11703             my $level = $section->{'level'};
11704             while ($level > $toplevel)
11705             {
11706                 my $number = $previous_numbers[$level];
11707                 $number = 0 if (!defined($number));
11708                 if ($section->{'number'})
11709                 {
11710                     $section->{'number'} = "$number.$section->{'number'}";
11711                 }
11712                 else
11713                 {
11714                     $section->{'number'} = $number;
11715                 }    
11716                 $level--;
11717             }
11718             my $toplevel_number = $previous_numbers[$toplevel];
11719             $toplevel_number = 0 if (!defined($toplevel_number));
11720             $section->{'number'} = "$toplevel_number.$section->{'number'}";
11721         }
11722         # find the previous section
11723         if (defined($previous_sections[$section->{'level'}]))
11724         {
11725             my $prev_section = $previous_sections[$section->{'level'}];
11726             $section->{'sectionprev'} = $prev_section;
11727             $prev_section->{'sectionnext'} = $section;
11728         }
11729         # find the up section
11730         if ($section->{'level'} == $toplevel)
11731         {
11732             $section->{'sectionup'} = undef;
11733         }
11734         else
11735         {
11736             my $level = $section->{'level'} - 1;
11737             while (!defined($previous_sections[$level]) and ($level >= 0))
11738             {
11739                  $level--;
11740             }
11741             if ($level >= 0)
11742             {
11743                 $section->{'sectionup'} = $previous_sections[$level];
11744                 # 'child' is the first child
11745                 $section->{'sectionup'}->{'child'} = $section unless ($section->{'sectionprev'});
11746                 push @{$section->{'sectionup'}->{'section_childs'}}, $section;
11747             }
11748             else
11749             {
11750                  $section->{'sectionup'} = undef;
11751             }
11752         }
11753         $previous_sections[$section->{'level'}] = $section;
11754         # This is what is used in the .init file. 
11755         $section->{'up'} = $section->{'sectionup'};
11756         # Not used but documented. 
11757         $section->{'next'} = $section->{'sectionnext'};
11758         $section->{'prev'} = $section->{'sectionprev'};
11759
11760         ############################# debug
11761         my $up = "NO_UP";
11762         $up = $section->{'sectionup'} if (defined($section->{'sectionup'}));
11763         print STDERR "# numbering section ($section->{'level'}): $section->{'number'}: (up: $up) $section->{'texi'}\n"
11764             if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11765         ############################# end debug
11766     }
11767
11768     # at that point there are still some node structures that are not 
11769     # in %nodes, (the external nodes, and unknown nodes in case 
11770     # novalidate is true) so we cannot find the id. The consequence is that
11771     # some node equivalent with another node may not be catched during
11772     # that pass. We mark the nodes that have directions for unreferenced 
11773     # nodes and make a second pass for these nodes afterwards.
11774     my @nodes_with_unknown_directions = ();
11775
11776     my @node_directions = ('node_prev', 'node_next', 'node_up');
11777     # handle nodes 
11778     # the node_prev... are texinfo strings, find the associated node references
11779     print STDERR "# Resolve nodes directions\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11780     foreach my $node (@nodes_list)
11781     {
11782         foreach my $direction (@node_directions)
11783         { 
11784             if (defined($node->{$direction}) and !ref($node->{$direction})
11785                 and ($node->{$direction} ne ''))
11786             {
11787                 if ($nodes{$node->{$direction}} and $nodes{$node->{$direction}}->{'seen'})
11788                 {
11789                      $node->{$direction} = $nodes{$node->{$direction}};
11790                 }
11791                 elsif (($node->{$direction} =~ /^\(.*\)/) or $novalidate)
11792                 { # ref to an external node
11793                     if (exists($nodes{$node->{$direction}}))
11794                     {
11795                         $node->{$direction} = $nodes{$node->{$direction}};
11796                     }
11797                     else
11798                     {
11799                         # FIXME if {'seen'} this is a node appearing in the
11800                         # document and a node like `(file)node'. What to 
11801                         # do then ?
11802                         my $node_ref = { 'texi' => $node->{$direction} };
11803                         $node_ref->{'external_node'} = 1 if ($node->{$direction} =~ /^\(.*\)/);
11804                         $nodes{$node->{$direction}} = $node_ref;
11805                         $node->{$direction} = $node_ref;
11806                     }
11807                 }
11808                 else
11809                 {
11810                      push @nodes_with_unknown_directions, $node;
11811                 }
11812             }
11813         }
11814     }
11815
11816     # Find cross manual links as explained on the texinfo mailing list
11817     # The  specification is such that cross manual links formatting should 
11818     # be insensitive to the manual split
11819     cross_manual_links();    
11820
11821     # Now it is possible to find the unknown directions that are equivalent
11822     # (have same node id) than an existing node
11823     foreach my $node (@nodes_with_unknown_directions)
11824     {
11825         foreach my $direction (@node_directions)
11826         { 
11827             if (defined($node->{$direction}) and !ref($node->{$direction})
11828                 and ($node->{$direction} ne ''))
11829             {
11830                 echo_warn ("$direction `$node->{$direction}' for `$node->{'texi'}' not found");
11831                 my @equivalent_nodes = equivalent_nodes($node->{$direction});
11832                 my $node_seen;
11833                 foreach my $equivalent_node (@equivalent_nodes)
11834                 {
11835                     if ($nodes{$equivalent_node}->{'seen'})
11836                     {
11837                         $node_seen = $equivalent_node;
11838                         last;
11839                     }
11840                 }
11841                 if (defined($node_seen))
11842                 {
11843                     echo_warn (" ---> but equivalent node `$node_seen' found");
11844                     $node->{$direction} = $nodes{$node_seen};
11845                 }
11846                 else
11847                 {
11848                     delete $node->{$direction};
11849                 }
11850             }
11851         }
11852     }
11853
11854     # find section preceding and following top 
11855     my $section_before_top;   # section preceding the top node
11856     my $section_after_top;       # section following the top node
11857     if ($node_top)
11858     {
11859         my $previous_is_top = 0;
11860         foreach my $element (@all_elements)
11861         {
11862             if ($element eq $node_top)
11863             {
11864                 $previous_is_top = 1;
11865                 next;
11866             }
11867             if ($previous_is_top)
11868             {
11869                 if ($element->{'section'})
11870                 {
11871                     $section_after_top = $element;
11872                     last;
11873                 }
11874                 next;
11875             }
11876             $section_before_top = $element if ($element->{'section'});
11877         }
11878     }
11879     print STDERR "# section before Top: $section_before_top->{'texi'}\n" 
11880         if ($section_before_top and ($T2H_DEBUG & $DEBUG_ELEMENTS));
11881     print STDERR "# section after Top: $section_after_top->{'texi'}\n" 
11882          if ($section_after_top and ($T2H_DEBUG & $DEBUG_ELEMENTS));
11883     
11884     print STDERR "# Build the elements list\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11885     if (!$Texi2HTML::Config::USE_NODES)
11886     {
11887         #the only sectionning elements are sections
11888         @elements_list = @sections_list;
11889         # if there is no section we use nodes...
11890         if (!@elements_list)
11891         {
11892             print STDERR "# no section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11893             @elements_list = @all_elements;
11894         }
11895         elsif (!$section_top and $node_top and !$node_top->{'with_section'})
11896         { # special case for the top node if it isn't associated with 
11897           # a section. The top node element is inserted between the 
11898           # $section_before_top and the $section_after_top
11899             print STDERR "# Top not associated with a section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11900             $node_top->{'top_as_section'} = 1;
11901             $node_top->{'section_ref'} = $node_top;
11902             my @old_element_lists = @elements_list;
11903             @elements_list = ();
11904             while (@old_element_lists)
11905             {
11906                 my $section = shift @old_element_lists;
11907                 if ($section_before_top and ($section eq $section_before_top))
11908                 {
11909                     push @elements_list, $section;
11910                     push @elements_list, $node_top;
11911                     last;
11912                 }
11913                 elsif ($section_after_top and ($section eq $section_after_top))
11914                 {
11915                     push @elements_list, $node_top;
11916                     push @elements_list, $section;
11917                     last;
11918                 }
11919                 push @elements_list, $section;
11920             }
11921             push @elements_list, @old_element_lists;
11922         }
11923         
11924         foreach my $element (@elements_list)
11925         {
11926             print STDERR "# new section element $element->{'texi'}\n"
11927                 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11928         }
11929     }
11930     else
11931     {
11932         # elements are sections if possible, and node if no section associated
11933         foreach my $element(@all_elements)
11934         {
11935             if ($element->{'node'})
11936             {
11937                 if (!defined($element->{'with_section'}))
11938                 {
11939                     $element->{'toc_level'} = $MIN_LEVEL if (!defined($element->{'toc_level'}));
11940                     print STDERR "# new node element ($element) $element->{'texi'}\n"
11941                         if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11942                     push @elements_list, $element;
11943                 }
11944             }
11945             else
11946             {
11947                 print STDERR "# new section element ($element) $element->{'texi'}\n"
11948                     if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11949                 push @elements_list, $element;
11950             }
11951         }
11952     }
11953     
11954     # nodes are attached to the section preceding them if not allready 
11955     # associated with a section
11956     # here we don't set @{$element->{'nodes'}} since it may be changed 
11957     # below if split by indices. Therefore we only set 
11958     # @{$element->{'all_elements'}} with all the elements associated
11959     # with an element output, in the right order
11960     print STDERR "# Find the section associated with each node\n"
11961         if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11962     my $current_section = $sections_list[0];
11963     $current_section = $node_top if ($node_top and $node_top->{'top_as_section'} and !$section_before_top);
11964     foreach my $element (@all_elements)
11965     {
11966         if ($element->{'node'} and !$element->{'top_as_section'})
11967         {
11968             if ($element->{'with_section'})
11969             { # the node is associated with a section
11970                 $element->{'section_ref'} = $element->{'with_section'};
11971                 push @{$element->{'section_ref'}->{'all_elements'}}, $element, $element->{'section_ref'};
11972                 # first index is section if the first index is associated with that node
11973                 $element_index = $element->{'section_ref'} if ($element_index and ($element_index eq $element));
11974             }
11975             elsif (defined($current_section))
11976             {# node appearing after a section, but not before another section,
11977              # or appearing before any section
11978                 $element->{'section_ref'} = $current_section;
11979                 $element->{'toc_level'} = $current_section->{'toc_level'};
11980                 push @{$current_section->{'node_childs'}}, $element;
11981                 if ($Texi2HTML::Config::USE_NODES)
11982                 { # the node is an element itself
11983                     push @{$element->{'all_elements'}}, $element;
11984                 }
11985                 else
11986                 {
11987                     push @{$current_section->{'all_elements'}}, $element;
11988                     # first index is section if the first index is associated with that node
11989                     $element_index = $current_section if ($element_index and ($element_index eq $element));
11990                 }
11991             }
11992             else
11993             { # seems like there are only nodes in the documents
11994                 $element->{'toc_level'} = $MIN_LEVEL;
11995                 push @{$element->{'all_elements'}}, $element;
11996             }
11997         }
11998         else
11999         {
12000             $current_section = $element;
12001             if ($element->{'node'})
12002             { # Top node not associated with a section
12003                 $element->{'toc_level'} = $MIN_LEVEL;
12004                 push @{$element->{'section_ref'}->{'all_elements'}}, $element;
12005             }
12006             elsif (!$element->{'node_ref'})
12007             { # a section not preceded by a node
12008                 push @{$element->{'all_elements'}}, $element;
12009             }
12010         }
12011     }
12012
12013     # find first, last and top elements 
12014     $element_first = $elements_list[0];
12015     print STDERR "# element first: $element_first->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 
12016     print STDERR "# top node: $node_top->{'texi'}\n" if (defined($node_top) and
12017         ($T2H_DEBUG & $DEBUG_ELEMENTS));
12018     # element top is the element with @top.
12019     $element_top = $section_top;
12020     # If the top node is associated with a section it is the top_element 
12021     # otherwise element top may be the top node 
12022     $element_top = $node_top if (!defined($element_top) and defined($node_top));
12023     # If there is no @top section no top node the first node is the top element
12024     $element_top = $element_first unless (defined($element_top));
12025     $element_top->{'top'} = 1 if ($element_top->{'node'});
12026     print STDERR "# element top: $element_top->{'texi'}\n" if ($element_top and
12027         ($T2H_DEBUG & $DEBUG_ELEMENTS));
12028
12029     # It is the last element before indices split, which may add new 
12030     # elements
12031     $element_last = $elements_list[-1];
12032     
12033     print STDERR "# Complete nodes next prev and up based on menus and sections\n"
12034         if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12035     # set the default id based on the node number 
12036     my $node_nr = 1;
12037     # find the node* directions
12038     # find the directions corresponding with sections
12039     # and set 'up' for the node
12040     foreach my $node (@nodes_list)
12041     {
12042         # first a warning if the node and the equivalent nodes don't 
12043         # appear in menus
12044         if (!$node->{'first'} and !$node->{'top'} and !$node->{'menu_up'} and ($node->{'texi'} !~ /^top$/i) and $Texi2HTML::Config::SHOW_MENU)
12045         {
12046             my @equivalent_nodes = equivalent_nodes($node->{'texi'});
12047             my $found = 0;
12048             foreach my $equivalent_node (@equivalent_nodes)
12049             {
12050                 if ($nodes{$equivalent_node}->{'first'} or $nodes{$equivalent_node}->{'menu_up'})
12051                 {
12052                    $found = 1;
12053                    last;
12054                 }
12055             }
12056             unless ($found)
12057             {
12058                 warn "$WARN `$node->{'texi'}' doesn't appear in menus\n";
12059             }
12060         }
12061
12062         # use values deduced from menus to complete missing up, next, prev
12063         # or from sectionning commands if automatic sectionning
12064         if ($node->{'node_up'})
12065         {
12066             $node->{'nodeup'} = $node->{'node_up'};
12067         }
12068         elsif ($node->{'automatic_directions'} and $node->{'section_ref'})
12069         {
12070             if (defined($node_top) and ($node eq $node_top))
12071             { # Top node has a special up, which is (dir) by default
12072                 my $top_nodeup = $Texi2HTML::Config::TOP_NODE_UP;
12073                 if (exists($nodes{$top_nodeup}))
12074                 {
12075                     $node->{'nodeup'} = $nodes{$top_nodeup};
12076                 }
12077                 else
12078                 {
12079                     my $node_ref = { 'texi' => $top_nodeup };
12080                     $node_ref->{'external_node'} = 1;
12081                     $nodes{$top_nodeup} = $node_ref;
12082                     $node->{'nodeup'} = $node_ref;
12083                 }
12084             }
12085             elsif (defined($node->{'section_ref'}->{'sectionup'}))
12086             {
12087                 $node->{'nodeup'} = get_node($node->{'section_ref'}->{'sectionup'});
12088             }
12089             elsif ($node->{'section_ref'}->{'toplevel'} and ($node->{'section_ref'} ne $element_top))
12090             {
12091                 $node->{'nodeup'} = get_node($element_top);
12092             }
12093             print STDERR "# Deducing from section node_up $node->{'nodeup'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS and defined($node->{'nodeup'}));
12094         }
12095
12096         if (!$node->{'nodeup'} and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
12097         { # makeinfo don't do that
12098             $node->{'nodeup'} = $node->{'menu_up'};
12099             print STDERR "# Deducing from menu node_up $node->{'menu_up'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12100         }
12101
12102         if ($node->{'nodeup'} and !$node->{'nodeup'}->{'external_node'})
12103         {
12104             # We detect when the up node has no menu entry for that node, as
12105             # there may be infinite loops when finding following node (see below)
12106             unless (defined($node->{'menu_up_hash'}) and ($node->{'menu_up_hash'}->{$node->{'nodeup'}->{'texi'}}))
12107             {
12108                 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);
12109                 push @{$node->{'up_not_in_menu'}}, $node->{'nodeup'}->{'texi'};
12110             }
12111         }
12112
12113         # Find next node
12114         if ($node->{'node_next'})
12115         {
12116             $node->{'nodenext'} = $node->{'node_next'};
12117         }
12118         elsif ($node->{'texi'} eq 'Top')
12119         { # special case as said in the texinfo manual
12120             $node->{'nodenext'} = $node->{'menu_child'} if ($node->{'menu_child'});
12121         }
12122         elsif ($node->{'automatic_directions'})
12123         {
12124             if (defined($node->{'section_ref'}))
12125             {
12126                 my $next;
12127                 my $section = $node->{'section_ref'};
12128                 if (defined($section->{'sectionnext'}))
12129                 {
12130                     $next = get_node($section->{'sectionnext'})
12131                 }
12132                 else 
12133                 {
12134                     while (defined($section->{'sectionup'}) and !defined($section->{'sectionnext'}))
12135                     {
12136                         $section = $section->{'sectionup'};
12137                     }
12138                     if (defined($section->{'sectionnext'}))
12139                     {
12140                         $next = get_node($section->{'sectionnext'});
12141                     }
12142                 }
12143                 $node->{'nodenext'} = $next;
12144             }
12145         }
12146         # next we try menus. makeinfo don't do that
12147         if (!defined($node->{'nodenext'}) and $node->{'menu_next'} 
12148             and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
12149         {
12150             $node->{'nodenext'} = $node->{'menu_next'};
12151         }
12152         # Find prev node
12153         if ($node->{'node_prev'})
12154         {
12155             $node->{'nodeprev'} = $node->{'node_prev'};
12156         }
12157         elsif ($node->{'automatic_directions'})
12158         {
12159             if (defined($node->{'section_ref'}))
12160             {
12161                 my $section = $node->{'section_ref'};
12162                 if (defined($section->{'sectionprev'}))
12163                 {
12164                     $node->{'nodeprev'} = get_node($section->{'sectionprev'});
12165                 }
12166                 elsif (defined($section->{'sectionup'}))
12167                 {
12168                     $node->{'nodeprev'} = get_node($section->{'sectionup'});
12169                 }
12170             }
12171         }
12172         # next we try menus. makeinfo don't do that
12173         if (!defined($node->{'nodeprev'}) and $node->{'menu_prev'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS) 
12174         {
12175             $node->{'nodeprev'} = $node->{'menu_prev'};
12176         }
12177         # the prev node is the parent node
12178         elsif (!defined($node->{'nodeprev'}) and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
12179         {
12180             $node->{'nodeprev'} = $node->{'menu_up'};
12181         }
12182     
12183         # the following node is the node following in node reading order
12184         # it is thus first the child, else the next, else the next following
12185         # the up
12186         if ($node->{'menu_child'})
12187         {
12188             $node->{'following'} = $node->{'menu_child'};
12189         }
12190         elsif ($node->{'automatic_directions'} and defined($node->{'section_ref'}) and defined($node->{'section_ref'}->{'child'}))
12191         {
12192             $node->{'following'} = get_node($node->{'section_ref'}->{'child'});
12193         }
12194         elsif (defined($node->{'nodenext'}))
12195         {
12196             $node->{'following'} = $node->{'nodenext'};
12197         }
12198         else
12199         {
12200             my $up = $node->{'nodeup'};
12201             # in order to avoid infinite recursion in case the up node is the 
12202             # node itself we use the up node as following when there isn't 
12203             # a correct menu structure, here and also below.
12204             $node->{'following'} = $up if (defined($up) and grep {$_ eq $up->{'texi'}} @{$node->{'up_not_in_menu'}});
12205             while ((!defined($node->{'following'})) and (defined($up)))
12206             {
12207                 if (($node_top) and ($up eq $node_top))
12208                 { # if we are at Top, Top is following 
12209                     $node->{'following'} = $node_top;
12210                     $up = undef;
12211                 }
12212                 if (defined($up->{'nodenext'}))
12213                 {
12214                     $node->{'following'} = $up->{'nodenext'};
12215                 }
12216                 elsif (defined($up->{'nodeup'}))
12217                 {
12218                     if (! grep { $_ eq $up->{'nodeup'}->{'texi'} } @{$node->{'up_not_in_menu'}}) 
12219                     { 
12220                         $up = $up->{'nodeup'};
12221                     }
12222                     else
12223                     { # in that case we can go into a infinite loop
12224                         $node->{'following'} = $up->{'nodeup'};
12225                     }
12226                 }
12227                 else
12228                 {
12229                     $up = undef;
12230                 }
12231             }
12232         }
12233
12234         if (defined($node->{'section_ref'}))
12235         {
12236             my $section = $node->{'section_ref'};
12237             foreach my $direction ('sectionnext', 'sectionprev', 'sectionup')
12238             {
12239                 $node->{$direction} = $section->{$direction}
12240                   if (defined($section->{$direction}));
12241             }
12242             # this is a node appearing within a section but not associated
12243             # with that section. We consider that it is below that section.
12244             $node->{'sectionup'} = $section
12245                if (grep {$node eq $_} @{$section->{'node_childs'}});
12246         }
12247         # 'up' is used in .init files. Maybe should go away.
12248         if (defined($node->{'sectionup'}))
12249         {
12250             $node->{'up'} = $node->{'sectionup'};
12251         }
12252         elsif (defined($node->{'nodeup'}) and 
12253              (!$node_top or ($node ne $node_top)))
12254         {
12255             $node->{'up'} = $node->{'nodeup'};
12256         }
12257         # 'next' not used but documented. 
12258         if (defined($node->{'sectionnext'}))
12259         {
12260             $node->{'next'} = $node->{'sectionnext'};
12261         }
12262         if (defined($node->{'sectionprev'}))
12263         {
12264             $node->{'prev'} = $node->{'sectionprev'};
12265         }
12266
12267         # default id for nodes. Should be overriden later.
12268         $node->{'id'} = 'NOD' . $node_nr;
12269         $node_nr++;
12270     }
12271     
12272     print STDERR "# find forward and back\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12273     my $prev;
12274     foreach my $element (@elements_list)
12275     {
12276         $element->{'element'} = 1;
12277         # complete the up for toplevel elements now that element_top is defined
12278         print STDERR "# fwd and back for $element->{'texi'}\n" 
12279             if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12280         # at that point no node may be toplevel, only sections. 
12281         if ($element->{'toplevel'} and ($element ne $element_top))
12282         {
12283             $element->{'sectionup'} = $element_top;
12284             $element->{'up'} = $element_top;
12285         }
12286         if ($prev)
12287         {
12288             $element->{'back'} = $prev;
12289             $prev->{'forward'} = $element;
12290             $prev = $element;
12291         }
12292         else
12293         {
12294             $prev = $element;
12295         }
12296         # If the element is not a node, then all the node directions are copied
12297         # if there is an associated node
12298         if (defined($element->{'node_ref'}))
12299         {
12300             $element->{'nodenext'} = $element->{'node_ref'}->{'nodenext'};
12301             $element->{'nodeprev'} = $element->{'node_ref'}->{'nodeprev'};
12302             $element->{'menu_next'} = $element->{'node_ref'}->{'menu_next'};
12303             $element->{'menu_prev'} = $element->{'node_ref'}->{'menu_prev'};
12304             $element->{'menu_child'} = $element->{'node_ref'}->{'menu_child'};
12305             $element->{'menu_up'} = $element->{'node_ref'}->{'menu_up'};
12306             $element->{'nodeup'} = $element->{'node_ref'}->{'nodeup'};
12307             $element->{'following'} = $element->{'node_ref'}->{'following'};
12308         }
12309         elsif (! $element->{'node'})
12310         { # the section has no node associated. Find the node directions using 
12311           # sections
12312             if (defined($element->{'sectionnext'}))
12313             {
12314                  $element->{'nodenext'} = get_node($element->{'sectionnext'});
12315             }
12316             if (defined($element->{'sectionprev'}))
12317             {
12318                  $element->{'nodeprev'} = get_node($element->{'sectionprev'});
12319             }
12320             if (defined($element->{'up'}))
12321             {
12322                  $element->{'nodeup'} = get_node($element->{'up'});
12323             }
12324             if ($element->{'child'})
12325             {
12326                 $element->{'following'} = get_node($element->{'child'});
12327             }
12328             elsif ($element->{'sectionnext'})
12329             {
12330                 $element->{'following'} = get_node($element->{'sectionnext'});
12331             }
12332             elsif ($element->{'up'})
12333             {
12334                 my $up = $element;
12335                 while ($up->{'up'} and !$element->{'following'})
12336                 {
12337                     print STDERR "# Going up, searching next section from $up->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12338                     $up = $up->{'up'};
12339                     if ($up->{'sectionnext'})
12340                     {
12341                         $element->{'following'} = get_node ($up->{'sectionnext'});
12342                     }
12343                     # avoid infinite loop if the top is up for itself
12344                     last if ($up->{'toplevel'} or $up->{'top'});
12345                 }
12346             }
12347         }
12348     }
12349
12350     my @new_elements = ();
12351     print STDERR "# preparing indices\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12352
12353     while(@elements_list)
12354     {
12355         my $element = shift @elements_list;
12356         # current_element is the last element which can hold text. It is 
12357         # initialized to a fake element
12358         my $current_element = { 'holder' => 1, 'texi' => 'HOLDER', 
12359             'place' => [], 'indices' => [] };
12360         # $back, $forward and $sectionnext are kept because $element
12361         # is in @{$element->{'all_elements'}}, so it is possible that 
12362         # those directions get changed.
12363         # back is set to find back and forward
12364         my $back = $element->{'back'} if defined($element->{'back'});
12365         my $forward = $element->{'forward'};
12366         my $sectionnext = $element->{'sectionnext'};
12367         my $index_num = 0;
12368         my @waiting_elements = (); # elements (nodes) not used for sectionning 
12369                                  # waiting to be associated with an element
12370         foreach my $checked_element(@{$element->{'all_elements'}})
12371         {
12372             if ($checked_element->{'element'})
12373             { # this is the element, we must add it
12374                 push @new_elements, $checked_element;
12375                 if ($current_element->{'holder'})
12376                 { # no previous element added
12377                     push @{$checked_element->{'place'}}, @{$current_element->{'place'}};
12378                     foreach my $index(@{$current_element->{'indices'}})
12379                     {
12380                         push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ;
12381                     }
12382                 }
12383                 else
12384                 {  
12385                     $current_element->{'sectionnext'} = $checked_element;
12386                     $current_element->{'following'} = $checked_element;
12387                     $checked_element->{'sectionprev'} = $current_element;
12388                 }
12389                 $current_element = $checked_element;
12390                 $checked_element->{'back'} = $back;
12391                 $back->{'forward'} = $checked_element if (defined($back));
12392                 $back = $checked_element;
12393                 push @{$checked_element->{'nodes'}}, @waiting_elements;
12394                 @waiting_elements = ();
12395             }
12396             elsif ($current_element->{'holder'})
12397             {
12398                 push @waiting_elements, $checked_element;
12399             }
12400             else
12401             {
12402                 push @{$current_element->{'nodes'}}, $checked_element;
12403                 $checked_element->{'section_ref'} = $current_element;
12404             }
12405             push @{$current_element->{'place'}}, @{$checked_element->{'current_place'}};
12406             foreach my $index (@{$checked_element->{'index_names'}})
12407             {
12408                 print STDERR "# Index in `$checked_element->{'texi'}': $index->{'name'}. Current is `$current_element->{'texi'}'\n"
12409                     if ($T2H_DEBUG & $DEBUG_INDEX);
12410                 my ($pages, $entries) = get_index($index->{'name'});
12411                 if (defined($pages))
12412                 {
12413                     my @pages = @$pages;
12414                     my $first_page = shift @pages;
12415                     ############################## begin debug section
12416                     my $back_texi = 'NO_BACK';
12417                     $back_texi = $back->{'texi'} if (defined($back));
12418                     print STDERR "# Index first page (back `$back_texi', in  `$current_element->{'texi'}')\n" if ($T2H_DEBUG & $DEBUG_INDEX);
12419                     ############################## end debug section
12420                     push @{$current_element->{'indices'}}, [ {'element' => $current_element, 'page' => $first_page, 'name' => $index->{'name'} } ];
12421                     if (@pages)
12422                     {# index is split accross more than one page
12423                         if ($current_element->{'holder'})
12424                         { # the current element isn't an element which is
12425                           # normally outputted. We add a real element. 
12426                           # we are in a node of a section but the element
12427                           # is split by the index, thus we must add 
12428                           # a new element which will contain the text 
12429                           # between the beginning of the element and the index
12430                           # WARNING the added element is like a section, and
12431                           # indeed it is a 'section_ref' and 'sectionup' 
12432                           # for other nodes, it has 'nodes' 
12433                           # (see below and above).
12434                           # But it is also a node. It may have a 'with_section'
12435                           # and have a 'section_ref'
12436                           # it may be considered 'node_ref' for a section.
12437                           # and the Texi2HTML::NODE is relative to this
12438                           # added element.
12439                             
12440                             push @new_elements, $checked_element;
12441                             print STDERR "# Add `$checked_element->{'texi'}' before index page for `$element->{'texi'}'\n" 
12442                                 if ($T2H_DEBUG & $DEBUG_INDEX);
12443                             echo_warn("Add `$checked_element->{'texi'}' for indicing");
12444                             $checked_element->{'element'} = 1;
12445                             $checked_element->{'level'} = $element->{'level'};
12446                             $checked_element->{'toc_level'} = $element->{'toc_level'};
12447                             $checked_element->{'toplevel'} = $element->{'toplevel'};
12448                             if ($element->{'top'})
12449                             {
12450                                 $checked_element->{'toplevel'} = 1; 
12451                                 $checked_element->{'top'} = 1;
12452                             }
12453                             $checked_element->{'up'} = $element->{'up'};
12454                             $checked_element->{'sectionup'} = $element->{'sectionup'};
12455                             $checked_element->{'element_added'} = 1;
12456                             print STDERR "Bug: checked element wasn't seen" if 
12457                                  (!$checked_element->{'seen'});
12458                             $element->{'sectionprev'}->{'sectionnext'} = $checked_element if (exists($element->{'sectionprev'}));
12459                             push @{$checked_element->{'place'}}, @{$current_element->{'place'}};
12460                             foreach my $index(@{$current_element->{'indices'}})
12461                             {
12462                                 push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ;
12463                             }
12464                             foreach my $waiting_element (@waiting_elements)
12465                             {
12466                                  next if ($waiting_element eq $checked_element);
12467                                  $waiting_element->{'section_ref'} = $checked_element;
12468                                  $waiting_element->{'sectionup'} = $checked_element;
12469                                  push @{$checked_element->{'nodes'}}, $waiting_element;
12470                             }
12471                             @waiting_elements = ();
12472                             $checked_element->{'back'} = $back;
12473                             $back->{'forward'} = $checked_element if (defined($back));
12474                             $current_element = $checked_element;
12475                             $back = $checked_element;
12476                         }
12477                         my $index_page;
12478                         while(@pages)
12479                         {
12480                             print STDERR "# New page (back `$back->{'texi'}', current `$current_element->{'texi'}')\n" if ($T2H_DEBUG & $DEBUG_INDEX);
12481                             $index_num++;
12482                             my $page = shift @pages;
12483                             $index_page = { 'index_page' => 1,
12484                              'texi' => "NOT REALLY USED: $current_element->{'texi'}' index $index->{'name'} page $index_num",
12485                              'level' => $element->{'level'},
12486                              'tag' => $element->{'tag'},
12487                              'tag_level' => $element->{'tag_level'},
12488                              'toplevel' => $element->{'toplevel'},
12489                              'top' => $element->{'top'},
12490                              'up' => $element->{'up'},
12491                              'sectionup' => $element->{'sectionup'},
12492                              'back' => $back,
12493                              'prev' => $back,
12494                              'sectionnext' => $sectionnext,
12495                              'following' => $current_element->{'following'},
12496                              'nodeup' => $current_element->{'nodeup'},
12497                              'nodenext' => $current_element->{'nodenext'},
12498                              'nodeprev' => $back,
12499                              'place' => [],
12500                              'seen' => 1,
12501                              'page' => $page
12502                             };
12503                             # the index page is associated with the new element
12504                             # if there is one, the element otherwise
12505                             if ($checked_element->{'element_added'})
12506                             {
12507                                 $index_page->{'original_index_element'} = $checked_element;
12508                             }
12509                             else
12510                             {
12511                                 $index_page->{'original_index_element'} = $element;
12512                             }
12513                             $index_page->{'node'} = 1 if ($element->{'node'});
12514                             while ($nodes{$index_page->{'texi'}})
12515                             {
12516                                 $nodes{$index_page->{'texi'}} .= ' ';
12517                             }
12518                             $nodes{$index_page->{'texi'}} = $index_page;
12519                             push @{$current_element->{'indices'}->[-1]}, {'element' => $index_page, 'page' => $page, 'name' => $index->{'name'} };
12520                             push @new_elements, $index_page;
12521                             $back->{'forward'} = $index_page;
12522                             $back->{'nodenext'} = $index_page;
12523                             $back->{'sectionnext'} = $index_page unless ($back->{'top'});
12524                             $back->{'following'} = $index_page;
12525                             $back = $index_page;
12526                             $index_page->{'toplevel'} = 1 if ($element->{'top'});
12527                         }
12528                         $current_element = $index_page;
12529                     }
12530                 }
12531                 else
12532                 {
12533                     print STDERR "# Empty index: $index->{'name'}\n" 
12534                         if ($T2H_DEBUG & $DEBUG_INDEX);
12535                     $empty_indices{$index->{'name'}} = 1;
12536                 }
12537                 push @{$current_element->{'place'}}, @{$index->{'place'}};
12538             }
12539         }
12540         if ($forward and ($current_element ne $element))
12541         {
12542             $current_element->{'forward'} = $forward;
12543             $forward->{'back'} = $current_element;
12544         }
12545         next if ($current_element eq $element or !$element->{'toplevel'});
12546         # reparent the elements below $element to the last index page
12547         print STDERR "# Reparent for `$element->{'texi'}':\n" if ($T2H_DEBUG & $DEBUG_INDEX);
12548         foreach my $reparented(@{$element->{'section_childs'}},@{$element->{'node_childs'}})
12549         {
12550             $reparented->{'sectionup'} = $current_element;
12551             print STDERR "   reparented: $reparented->{'texi'}\n"
12552                     if ($T2H_DEBUG & $DEBUG_INDEX);
12553         }
12554     }
12555     @elements_list = @new_elements;
12556     
12557     print STDERR "# find fastback and fastforward\n" 
12558        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12559     foreach my $element (@elements_list)
12560     {
12561         my $up = get_top($element);
12562         next unless (defined($up));
12563         $element_chapter_index = $up if ($element_index and ($element_index eq $element));
12564         # fastforward is the next element on same level than the upper parent
12565         # element
12566         $element->{'fastforward'} = $up->{'sectionnext'} if (exists ($up->{'sectionnext'}));
12567         # if the element isn't at the highest level, fastback is the 
12568         # highest parent element
12569         if ($up and ($up ne $element))
12570         {
12571             $element->{'fastback'} = $up;
12572         }
12573         elsif ($element->{'toplevel'})
12574         {
12575             # the element is a top level element, we adjust the next
12576             # toplevel element fastback
12577             $element->{'fastforward'}->{'fastback'} = $element if ($element->{'fastforward'});
12578         }
12579     }
12580     
12581     # set 'reference_element' which is used each time there is a cross ref
12582     # to that node.
12583     # It is the section associated with the node except if USE_NODES
12584     unless ($Texi2HTML::Config::USE_NODES)
12585     {
12586         foreach my $node(@nodes_list)
12587         {
12588             if ($node->{'with_section'})
12589             {
12590                 $node->{'reference_element'} = $node->{'with_section'};
12591             }
12592         }
12593     }
12594
12595     my $index_nr = 0;
12596     # convert directions in direction with first letter in all caps, to be
12597     # consistent with the convention used in the .init file.
12598     # find id for nodes and indices
12599     foreach my $element (@elements_list)
12600     {
12601         $element->{'this'} = $element;
12602         foreach my $direction (@element_directions)
12603         {
12604             my $direction_no_caps = $direction;
12605             $direction_no_caps =~ tr/A-Z/a-z/;
12606             $element->{$direction} = $element->{$direction_no_caps};
12607         }
12608         if ($element->{'index_page'})
12609         {
12610             $element->{'id'} = "INDEX" . $index_nr;
12611             $index_nr++;
12612         }
12613     }
12614
12615     print STDERR "# find float id\n" 
12616        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12617     foreach my $float (@floats)
12618     {
12619         $float->{'style_id'} = cross_manual_line(normalise_space($float->{'style_texi'}));
12620         my $float_style = { };
12621         if (exists($floats{$float->{'style_id'}}))
12622         {
12623             $float_style = $floats{$float->{'style_id'}};
12624         }
12625         else
12626         {
12627             $floats{$float->{'style_id'}} = $float_style;
12628         }
12629         push @{$float_style->{'floats'}}, $float;
12630         $float->{'absolute_nr'} = scalar(@{$float_style->{'floats'}});
12631         my $up = get_top($float->{'element'});
12632         if (defined($up) and (!defined($float_style->{'current_chapter'}) or ($up->{'texi'} ne $float_style->{'current_chapter'})))
12633         {
12634             $float_style->{'current_chapter'} = $up->{'texi'};
12635             $float_style->{'nr_in_chapter'} = 1;
12636         }
12637         else
12638         {
12639             $float_style->{'nr_in_chapter'}++;
12640         }
12641         if (defined($up) and $up->{'number'} ne '')
12642         {
12643             $float->{'chapter_nr'} = $up->{'number'};
12644             $float->{'nr'} = $float->{'chapter_nr'} . $float_style->{'nr_in_chapter'};
12645         }
12646         else
12647         {
12648             $float->{'nr'} = $float->{'absolute_nr'};
12649         }
12650     }
12651     
12652     if ($Texi2HTML::Config::NEW_CROSSREF_STYLE)
12653     { 
12654         foreach my $key (keys(%nodes))
12655         {
12656             my $node = $nodes{$key};
12657             next if ($node->{'external_node'} or $node->{'index_page'});
12658             $node->{'id'} = node_to_id($node->{'cross_manual_target'});
12659         }
12660     }
12661
12662     # Find node file names and file names for nodes considered as elements
12663     my $node_as_top;
12664     if ($node_top)
12665     {
12666         $node_as_top = $node_top;
12667     }
12668     elsif ($element_top->{'node_ref'})
12669     {
12670         $node_as_top = $element_top->{'node_ref'};
12671     }
12672     else
12673     {
12674         $node_as_top = $node_first;
12675     }
12676     if ($node_as_top)
12677     {
12678         my $node_file;
12679         $node_file = &$Texi2HTML::Config::node_file_name($node_as_top,'top');
12680         $node_as_top->{'node_file'} = $node_file if (defined($node_file));
12681     }
12682     foreach my $key (keys(%nodes))
12683     {
12684         my $node = $nodes{$key};
12685         next if (defined($node_as_top) and ($node eq $node_as_top));
12686         my $node_file = &$Texi2HTML::Config::node_file_name($node,'');
12687         $node->{'node_file'} = $node_file if (defined($node_file));
12688     }
12689     
12690     print STDERR "# split and set files\n" 
12691        if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12692     # find document nr and document file for sections and nodes. 
12693     # Split according to Texi2HTML::Config::SPLIT.
12694     # find file and id for placed elements (anchors, index entries, headings)
12695     if ($Texi2HTML::Config::SPLIT)
12696     {
12697         my $cut_section = $toplevel;
12698         my $doc_nr = -1;
12699         if ($Texi2HTML::Config::SPLIT eq 'section')
12700         {
12701             $cut_section = 2 if ($toplevel <= 2);
12702         }
12703         my $previous_file;
12704         foreach my $element (@elements_list)
12705         { 
12706             print STDERR "# Splitting ($Texi2HTML::Config::SPLIT:$cut_section) $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12707             my $new_file = 0;
12708             if (
12709                ($Texi2HTML::Config::SPLIT eq 'node') or
12710                (
12711                  defined($element->{'level'}) and ($element->{'level'} <= $cut_section)
12712                )
12713               )
12714             {
12715                 $new_file = 1;
12716                 $doc_nr++;
12717             }
12718             $doc_nr = 0 if ($doc_nr < 0); # happens if first elements are nodes
12719             $element->{'doc_nr'} = $doc_nr;
12720             my $is_top = '';
12721             $element->{'file'} = "${docu_name}_$doc_nr"
12722                    . ($docu_ext ? ".$docu_ext" : "");
12723             if ($element->{'top'} or (defined($element->{'node_ref'}) and $element->{'node_ref'} eq $element_top))
12724             { # the top elements
12725                 $is_top = "top";
12726                 $element->{'file'} = $docu_top;
12727             }
12728             elsif ($Texi2HTML::Config::NODE_FILES)
12729             {
12730                 if ($new_file)
12731                 {
12732                     my $node = get_node($element) unless(exists($element->{'node_ref'})
12733                         and $element->{'node_ref'}->{'element_added'});
12734                     if ($node and defined($node->{'node_file'}))
12735                     {
12736                         $element->{'file'} = $node->{'node_file'};
12737                     }
12738                     $previous_file = $element->{'file'};
12739                 }
12740                 elsif($previous_file)
12741                 {
12742                     $element->{'file'} = $previous_file;
12743                 }
12744             }
12745             if (defined($Texi2HTML::Config::element_file_name))
12746             {
12747                 my $filename = 
12748                     &$Texi2HTML::Config::element_file_name ($element, $is_top, $docu_name);
12749                 $element->{'file'} = $filename if (defined($filename));
12750             }
12751             print STDERR "# add_file $element->{'file'} for $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12752             add_file($element->{'file'});
12753             foreach my $place(@{$element->{'place'}})
12754             {
12755                 $place->{'file'} = $element->{'file'};
12756                 $place->{'id'} = $element->{'id'} unless defined($place->{'id'});
12757             }
12758             if ($element->{'nodes'})
12759             {
12760                 foreach my $node (@{$element->{'nodes'}})
12761                 {
12762                     $node->{'doc_nr'} = $element->{'doc_nr'};
12763                     $node->{'file'} = $element->{'file'};
12764                 }
12765             }
12766         }
12767     }
12768     else
12769     { # not split
12770         add_file($docu_doc);
12771         foreach my $element(@elements_list)
12772         {
12773             $element->{'file'} = $docu_doc;
12774             $element->{'doc_nr'} = 0;
12775             foreach my $place(@{$element->{'place'}})
12776             {
12777                 $place->{'file'} = $element->{'file'};
12778                 $place->{'id'} = $element->{'id'} unless defined($place->{'id'});
12779             }
12780         }
12781         foreach my $node(@nodes_list)
12782         {
12783             $node->{'file'} = $docu_doc;
12784             $node->{'doc_nr'} = 0;
12785         }
12786     }
12787     # correct the id and file for the things placed in footnotes
12788     foreach my $place(@{$footnote_element->{'place'}})
12789     {
12790         $place->{'file'} = $footnote_element->{'file'};
12791         $place->{'id'} = $footnote_element->{'id'} unless defined($place->{'id'});
12792     }
12793     # if setcontentsaftertitlepage is set, the contents should be associated
12794     # with the titlepage. That's wat is done there.
12795     push @$region_place, $content_element{'contents'} 
12796       if ($Texi2HTML::Config::DO_CONTENTS and $Texi2HTML::THISDOC{'setcontentsaftertitlepage'});
12797     push @$region_place, $content_element{'shortcontents'} 
12798       if ($Texi2HTML::Config::DO_SCONTENTS and $Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'});
12799     # correct the id and file for the things placed in regions (copying...)
12800     foreach my $place(@$region_place)
12801     {
12802 #print STDERR "entry $place->{'entry'} texi $place->{'texi'}\n";
12803         $place->{'file'} = $element_top->{'file'};
12804         $place->{'id'} = $element_top->{'id'} unless defined($place->{'id'});
12805         $place->{'element'} =  $element_top if (exists($place->{'element'}));
12806     }
12807     foreach my $content_type(keys(%content_element))
12808     {
12809         if (!defined($content_element{$content_type}->{'file'}))
12810         {
12811             print STDERR "# No content $content_type\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12812             $content_element{$content_type} = undef;
12813         }
12814     }
12815
12816     ########################### debug prints
12817     foreach my $file (keys(%files))
12818     {
12819         last unless ($T2H_DEBUG & $DEBUG_ELEMENTS);
12820         print STDERR "$file: counter $files{$file}->{'counter'}\n";
12821     }
12822     foreach my $element ((@elements_list, $footnote_element))
12823     {
12824         last unless ($T2H_DEBUG & $DEBUG_ELEMENTS);
12825         my $is_toplevel = 'not toplevel';
12826         $is_toplevel = 'toplevel' if ($element->{'toplevel'});
12827         print STDERR "$element ";
12828         if ($element->{'index_page'})
12829         {
12830             print STDERR "index($element->{'id'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})): $element->{'texi'}\n";
12831         }
12832         elsif ($element->{'node'})
12833         {
12834             print STDERR "node($element->{'id'}, toc_level $element->{'toc_level'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n";
12835             print STDERR "  section_ref: $element->{'section_ref'}->{'texi'}\n" if (defined($element->{'section_ref'}));
12836         }
12837         elsif ($element->{'footnote'})
12838         {
12839             print STDERR "footnotes($element->{'id'}, file $element->{'file'})\n";
12840         }
12841         else 
12842         {
12843             my $number = "UNNUMBERED";
12844             $number = $element->{'number'} if ($element->{'number'});
12845             print STDERR "$number ($element->{'id'}, $is_toplevel, level $element->{'level'}-$element->{'toc_level'}, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n";
12846             print STDERR "  node_ref: $element->{'node_ref'}->{'texi'}\n" if (defined($element->{'node_ref'}));
12847         }
12848
12849         if (!$element->{'footnote'})
12850         {
12851             if (!defined($files{$element->{'file'}}))
12852             {
12853                die "Bug: files{\$element->{'file'}} undef element $element->{'texi'}, file $element->{'file'}.";
12854             }
12855             print STDERR "  file: $element->{'file'} $files{$element->{'file'}}, counter $files{$element->{'file'}}->{'counter'}\n";
12856         }
12857         print STDERR "  TOP($toplevel) " if ($element->{'top'});
12858         print STDERR "  u: $element->{'up'}->{'texi'}\n" if (defined($element->{'up'}));
12859         print STDERR "  ch: $element->{'child'}->{'texi'}\n" if (defined($element->{'child'}));
12860         print STDERR "  fb: $element->{'fastback'}->{'texi'}\n" if (defined($element->{'fastback'}));
12861         print STDERR "  b: $element->{'back'}->{'texi'}\n" if (defined($element->{'back'}));
12862         print STDERR "  p: $element->{'prev'}->{'texi'}\n" if (defined($element->{'prev'}));
12863         print STDERR "  n: $element->{'sectionnext'}->{'texi'}\n" if (defined($element->{'sectionnext'}));
12864         print STDERR "  n_u: $element->{'nodeup'}->{'texi'}\n" if (defined($element->{'nodeup'}));
12865         print STDERR "  f: $element->{'forward'}->{'texi'}\n" if (defined($element->{'forward'}));
12866         print STDERR "  follow: $element->{'following'}->{'texi'}\n" if (defined($element->{'following'}));
12867         print STDERR "  m_p: $element->{'menu_prev'}->{'texi'}\n" if (defined($element->{'menu_prev'}));
12868         print STDERR "  m_n: $element->{'menu_next'}->{'texi'}\n" if (defined($element->{'menu_next'}));
12869         print STDERR "  m_u: $element->{'menu_up'}->{'texi'}\n" if (defined($element->{'menu_up'}));
12870         print STDERR "  m_ch: $element->{'menu_child'}->{'texi'}\n" if (defined($element->{'menu_child'}));
12871         print STDERR "  ff: $element->{'fastforward'}->{'texi'}\n" if (defined($element->{'fastforward'}));
12872         if (defined($element->{'menu_up_hash'}))
12873         {
12874             print STDERR "  parent nodes:\n";
12875             foreach my $menu_up (keys%{$element->{'menu_up_hash'}})
12876             {
12877                 print STDERR "   $menu_up ($element->{'menu_up_hash'}->{$menu_up})\n";
12878             }
12879         }
12880         if (defined($element->{'nodes'}))
12881         {
12882             print STDERR "  nodes: $element->{'nodes'} (@{$element->{'nodes'}})\n";
12883             foreach my $node (@{$element->{'nodes'}})
12884             {
12885                 my $beginning = "   ";
12886                 $beginning = "  *" if ($node->{'with_section'});
12887                 my $file = $node->{'file'};
12888                 $file = "file undef" if (! defined($node->{'file'}));
12889                 print STDERR "${beginning}$node->{'texi'} $file\n";
12890             }
12891         }
12892         print STDERR "  places: $element->{'place'}\n";
12893         foreach my $place(@{$element->{'place'}})
12894         {
12895             if (!$place->{'entry'} and !$place->{'float'} and !$place->{'texi'} and !$place->{'contents'} and !$place->{'shortcontents'})
12896             {
12897                  print STDERR "BUG: unknown placed stuff ========\n";
12898                  foreach my $key (keys(%$place))
12899                  {
12900                       print STDERR "$key: $place->{$key}\n";
12901                  }
12902                  print STDERR "==================================\n";
12903             }
12904             elsif ($place->{'entry'})
12905             {
12906                 print STDERR "    index($place): $place->{'entry'}\n";
12907             }
12908             elsif ($place->{'anchor'})
12909             {
12910                 print STDERR "    anchor: $place->{'texi'}\n";
12911             }
12912             elsif ($place->{'float'})
12913             {
12914                 if (defined($place->{'texi'}))
12915                 {
12916                     print STDERR "    float($place): $place->{'texi'}\n";
12917                 }
12918                 else
12919                 {
12920                     print STDERR "    float($place): NO LABEL\n";
12921                 }
12922             }
12923             elsif ($place->{'contents'})
12924             {
12925                 print STDERR "    contents\n";
12926             }
12927             elsif ($place->{'shortcontents'})
12928             {
12929                 print STDERR "    shortcontents\n";
12930             }
12931             else
12932             {
12933                 print STDERR "    heading: $place->{'texi'}\n";
12934             }
12935         }
12936         if ($element->{'indices'})
12937         {
12938             print STDERR "  indices: $element->{'indices'}\n";
12939             foreach my $index(@{$element->{'indices'}})
12940             {
12941                 print STDERR "    $index: ";
12942                 foreach my $page (@$index)
12943                 {
12944                     print STDERR "'$page->{'element'}->{'texi'}'($page->{'name'}): $page->{'page'} ";
12945                 }
12946                 print STDERR "\n";
12947             }
12948         }
12949     }
12950     ########################### end debug prints
12951 }
12952
12953 sub add_file($)
12954 {
12955     my  $file = shift;
12956     if ($files{$file})
12957     {
12958          $files{$file}->{'counter'}++;
12959     }
12960     else
12961     {
12962          $files{$file} = { 
12963            #'type' => 'section', 
12964            'counter' => 1,
12965            'relative_foot_num' => 1,
12966            'foot_lines' => []
12967          };
12968     }
12969 }
12970
12971 # find parent element which is a top element, or a node within the top section
12972 sub get_top($)
12973 {
12974    my $element = shift;
12975    my $up = $element;
12976    while (!$up->{'toplevel'} and !$up->{'top'})
12977    {
12978        $up = $up->{'sectionup'};
12979        if (!defined($up))
12980        {
12981            # If there is no section, it is normal not to have toplevel element,
12982            # and it is also the case if there is a low level element before
12983            # a top level element
12984            return undef;
12985        }
12986    }
12987    return $up;
12988 }
12989
12990 sub get_node($)
12991 {
12992     my $element = shift;
12993     return undef if (!defined($element));
12994     return $element if ($element->{'node'});
12995     return $element->{'node_ref'} if ($element->{'node_ref'});
12996     return $element;
12997 }
12998 # get the html names from the texi for all elements
12999 sub do_names()
13000 {
13001     print STDERR "# Doing ". scalar(keys(%nodes)) . " nodes, ".
13002         scalar(keys(%sections)) . " sections in ". $#elements_list . 
13003         " elements\n" if ($T2H_DEBUG);
13004     # for nodes and anchors we haven't any state defined
13005     # This seems right, however, as we don't want @refs or @footnotes
13006     # or @anchors within nodes, section commands or anchors.
13007     foreach my $node (keys(%nodes))
13008     {
13009         next if ($nodes{$node}->{'index_page'}); # some nodes are index pages.
13010         my $texi = &$Texi2HTML::Config::heading_texi($nodes{$node}->{'tag'}, 
13011            $nodes{$node}->{'texi'}, undef);
13012         $nodes{$node}->{'text'} = substitute_line ($texi);
13013         $nodes{$node}->{'text_nonumber'} = $nodes{$node}->{'text'};
13014         # backward compatibility
13015         $nodes{$node}->{'name'} = $nodes{$node}->{'text_nonumber'};
13016         $nodes{$node}->{'no_texi'} = remove_texi($texi);
13017         $nodes{$node}->{'simple_format'} = simple_format(undef, $texi);
13018         $nodes{$node}->{'heading_texi'} = $texi;
13019         # FIXME : what to do if $nodes{$node}->{'external_node'} and
13020         # $nodes{$node}->{'seen'}
13021     }
13022     foreach my $number (keys(%sections))
13023     {
13024         my $section = $sections{$number};
13025         #$section->{'name'} = substitute_line($section->{'texi'});
13026         my $texi = &$Texi2HTML::Config::heading_texi($section->{'tag'}, $section->{'texi'}, $section->{'number'});
13027         $section->{'text'} = substitute_line($texi);
13028         $section->{'text_nonumber'} = substitute_line($section->{'texi'});
13029         # backward compatibility
13030         $section->{'name'} = $section->{'text_nonumber'};
13031         $section->{'no_texi'} = remove_texi($texi);
13032         $section->{'simple_format'} = simple_format(undef,$texi);
13033         $section->{'heading_texi'} = $texi;
13034     }
13035     my $tocnr = 1;
13036     foreach my $element (@elements_list)
13037     {
13038         if (!$element->{'top'} and !$element->{'index_page'})
13039         { # for link back to table of contents
13040           # FIXME do it for top too?
13041             $element->{'tocid'} = 'TOC' . $tocnr;
13042             $tocnr++;
13043         }
13044         next if (defined($element->{'text'}));
13045         if ($element->{'index_page'})
13046         {
13047             my $page = $element->{'page'};
13048             my $original_element = $element->{'original_index_element'};
13049             my $texi = &$Texi2HTML::Config::index_element_heading_texi(
13050                  $original_element->{'heading_texi'}, 
13051                  $original_element->{'tag'}, 
13052                  $original_element->{'texi'},
13053                  $original_element->{'number'},
13054                  $page->{'first_letter'}, $page->{'last_letter'});
13055             $element->{'heading_texi'} = $texi;
13056             $element->{'text'} = substitute_line($texi);
13057             $element->{'no_texi'} = remove_texi($texi);
13058             $element->{'simple_format'} = simple_format(undef,$texi);
13059         }
13060     }
13061     print STDERR "# Names done\n" if ($T2H_DEBUG);
13062 }
13063
13064 @{$Texi2HTML::TOC_LINES} = ();            # table of contents
13065 @{$Texi2HTML::OVERVIEW} = ();           # short table of contents
13066
13067
13068
13069 #+++############################################################################
13070 #                                                                              #
13071 # Stuff related to Index generation                                            #
13072 #                                                                              #
13073 #---############################################################################
13074
13075 # called during pass_structure
13076 sub enter_index_entry($$$$$$$)
13077 {
13078     my $prefix = shift;
13079     my $line_nr = shift;
13080     my $key = shift;
13081     my $place = shift;
13082     my $element = shift;
13083     my $use_section_id = shift;
13084     my $command = shift;
13085     unless ($index_prefix_to_name{$prefix})
13086     {
13087         echo_error ("Undefined index command: ${prefix}index", $line_nr);
13088         $key = '';
13089     }
13090     if (!exists($element->{'tag'}) and !$element->{'footnote'})
13091     {
13092         echo_warn ("Index entry before document: \@${prefix}index $key", $line_nr); 
13093     }
13094     $key =~ s/\s+$//;
13095     $key =~ s/^\s*//;
13096     my $entry = $key;
13097     # The $key is mostly usefull for alphabetical sorting
13098     $key = remove_texi($key);
13099     my $id = '';
13100     # don't add a specific index target if after a section or the index
13101     # entry is in @copying or the like
13102     unless ($use_section_id or ($place eq $region_place))
13103     {
13104         $id = 'IDX' . ++$idx_num;
13105     }
13106     my $index_entry = {
13107            'entry'    => $entry,
13108            'element'  => $element,
13109            'prefix'   => $prefix,
13110            'label'    => $id,
13111            'command'  => $command
13112     };
13113             
13114     print STDERR "# enter \@$command ${prefix}index '$key' with id $id ($index_entry)\n"
13115         if ($T2H_DEBUG & $DEBUG_INDEX);
13116     if ($key =~ /^\s*$/)
13117     {
13118         echo_warn("Empty index entry for \@$command",$line_nr);
13119         # don't add the index entry to the list of index entries used for index
13120         # entry formatting,if the index entry appears in a region like copying 
13121         push @index_labels, $index_entry unless ($place eq $region_place);
13122         return;
13123     }
13124     while (exists $index->{$prefix}->{$key})
13125     {
13126         $key .= ' ';
13127     }
13128     $index->{$prefix}->{$key} = $index_entry;
13129     push @$place, $index_entry;
13130     # don't add the index entry to the list of index entries used for index
13131     # entry formatting,if the index entry appears in a region like copying 
13132     push @index_labels, $index_entry unless ($place eq $region_place);
13133 }
13134
13135 # sort according to cmp if both $a and $b are alphabetical or non alphabetical, 
13136 # otherwise the alphabetical is ranked first
13137 sub by_alpha
13138 {
13139     if ($a =~ /^[A-Za-z]/)
13140     {
13141         if ($b =~ /^[A-Za-z]/)
13142         {
13143             return lc($a) cmp lc($b);
13144         }
13145         else
13146         {
13147             return 1;
13148         }
13149     }
13150     elsif ($b =~ /^[A-Za-z]/)
13151     {
13152         return -1;
13153     }
13154     else
13155     {
13156         return lc($a) cmp lc($b);
13157     }
13158 }
13159
13160 # returns an array of index entries pages splitted by letters
13161 # each page has the following members:
13162 # 'first_letter'       first letter on that page
13163 # 'last_letter'        last letter on that page
13164 # 'letters'            ref on an array with all the letters for that page
13165 # 'entries_by_letter'  ref on a hash. Each key is a letter, with value a ref 
13166 #                      on arrays of index entries beginning with this letter
13167 sub get_index_pages($)
13168 {
13169     my $entries = shift;
13170     my (@letters);
13171     my ($entries_by_letter, $pages, $page) = ({}, [], {});
13172     my @keys = sort by_alpha keys %$entries;
13173
13174     # each index entry is placed according to its first letter in
13175     # entries_by_letter
13176     for my $key (@keys)
13177     {
13178         push @{$entries_by_letter->{uc(substr($key,0, 1))}} , $entries->{$key};
13179     }
13180     @letters = sort by_alpha keys %$entries_by_letter;
13181     $Texi2HTML::Config::SPLIT_INDEX = 0 unless $Texi2HTML::Config::SPLIT;
13182
13183     if ($Texi2HTML::Config::SPLIT_INDEX and $Texi2HTML::Config::SPLIT_INDEX =~ /^\d+$/)
13184     {
13185         my $i = 0;
13186         my ($prev_letter);
13187         foreach my $letter (@letters)
13188         {
13189             if ($i > $Texi2HTML::Config::SPLIT_INDEX)
13190             {
13191                 $page->{'last_letter'} = $prev_letter;
13192                 push @$pages, $page;
13193                 $i=0;
13194             }
13195             if ($i == 0)
13196             {
13197                 $page = {};
13198                 $page->{'letters'} = [];
13199                 $page->{'entries_by_letter'} = {};
13200                 $page->{'first_letter'} = $letter;
13201             }
13202             push @{$page->{'letters'}}, $letter;
13203             $page->{'entries_by_letter'}->{$letter} = [@{$entries_by_letter->{$letter}}];
13204             $i += scalar(@{$entries_by_letter->{$letter}});
13205             $prev_letter = $letter;
13206         }
13207         $page->{'last_letter'} = $letters[$#letters];
13208         push @$pages, $page;
13209     }
13210     else
13211     {
13212         warn "$WARN Bad Texi2HTML::Config::SPLIT_INDEX: $Texi2HTML::Config::SPLIT_INDEX\n" if ($Texi2HTML::Config::SPLIT_INDEX);
13213         $page->{'first_letter'} = $letters[0];
13214         $page->{'last_letter'} = $letters[$#letters];
13215         $page->{'letters'} = \@letters;
13216         $page->{'entries_by_letter'} = $entries_by_letter;
13217         push @$pages, $page;
13218         return $pages;
13219     }
13220     return $pages;
13221 }
13222
13223 # return the page and the entries. Cache the result in %indices.
13224 sub get_index($;$)
13225 {
13226     my $index_name = shift;
13227     my $line_nr = shift;
13228
13229     return (@{$indices{$index_name}}) if ($indices{$index_name});
13230
13231     unless (exists($index_names{$index_name}))
13232     {
13233         echo_error ("Bad index name: $index_name", $line_nr);
13234         return;
13235     }
13236     # add the index name itself to the index names searched for index
13237     # prefixes. Only those found associated by synindex or syncodeindex are 
13238     # allready there (unless this code has allready been called).
13239     if ($index_names{$index_name}->{'code'})
13240     {
13241         $index_names{$index_name}->{'associated_indices_code'}->{$index_name} = 1;
13242     }
13243     else
13244     {
13245         $index_names{$index_name}->{'associated_indices'}->{$index_name} = 1;
13246     }
13247
13248     # find all the index names associated with the prefixes and then 
13249     # all the entries associated with each prefix
13250     my $entries = {};
13251     foreach my $associated_indice(keys %{$index_names{$index_name}->{'associated_indices'}})
13252     {
13253         foreach my $prefix(@{$index_names{$associated_indice}->{'prefix'}})
13254         {
13255             foreach my $key (keys %{$index->{$prefix}})
13256             {
13257                 $entries->{$key} = $index->{$prefix}->{$key};
13258             }
13259         }
13260     }
13261
13262     foreach my $associated_indice (keys %{$index_names{$index_name}->{'associated_indices_code'}})
13263     {
13264         unless (exists ($index_names{$index_name}->{'associated_indices'}->{$associated_indice}))
13265         {
13266             foreach my $prefix (@{$index_names{$associated_indice}->{'prefix'}})
13267             {
13268                 foreach my $key (keys (%{$index->{$prefix}}))
13269                 {
13270                     $entries->{$key} = $index->{$prefix}->{$key};
13271                     # use @code for code style index entry
13272                     $entries->{$key}->{'entry'} = "\@code{$entries->{$key}->{entry}}";
13273                 }
13274             }
13275         }
13276     }
13277
13278     return unless %$entries;
13279     my $pages = get_index_pages($entries);
13280     $indices{$index_name} = [ $pages, $entries ];
13281     return ($pages, $entries);
13282 }
13283
13284 my @foot_lines = ();           # footnotes
13285 my $copying_comment = '';      # comment constructed from text between
13286                                # @copying and @end copying with licence
13287 my $to_encoding;               # out file encoding
13288 my %acronyms_like = ();        # acronyms or similar commands associated texts
13289                                # the key are the commands, the values are
13290                                # hash references associating shorthands to
13291                                # texts.
13292
13293 sub initialise_state($)
13294 {
13295     my $state = shift;
13296     $state->{'preformatted'} = 0 unless exists($state->{'preformatted'}); 
13297     $state->{'code_style'} = 0 unless exists($state->{'code_style'}); 
13298     $state->{'keep_texi'} = 0 unless exists($state->{'keep_texi'});
13299     $state->{'keep_nr'} = 0 unless exists($state->{'keep_nr'});
13300     $state->{'detailmenu'} = 0 unless exists($state->{'detailmenu'});     # number of opened detailed menus      
13301     $state->{'table_list_stack'} = [ {'format' => "noformat"} ] unless exists($state->{'table_list_stack'});
13302     $state->{'paragraph_style'} = [ '' ] unless exists($state->{'paragraph_style'}); 
13303     $state->{'preformatted_stack'} = [ '' ] unless exists($state->{'preformatted_stack'}); 
13304     $state->{'menu'} = 0 unless exists($state->{'menu'}); 
13305     $state->{'command_stack'} = [] unless exists($state->{'command_stack'});
13306     $state->{'quotation_stack'} = [] unless exists($state->{'quotation_stack'});
13307     # if there is no $state->{'element'} the first element is used
13308     $state->{'element'} = $elements_list[0] unless (exists($state->{'element'}) and !$state->{'element'}->{'before_anything'});
13309 }
13310
13311 sub pass_text()
13312 {
13313     my %state;
13314     initialise_state(\%state);
13315     my @stack;
13316     my $text;
13317     my $doc_nr;
13318     my $in_doc = 0;
13319     my $element;
13320     my @text =();
13321     my @section_lines = ();
13322     my @head_lines = ();
13323     my $one_section = 1 if (@elements_list == 1);
13324
13325     if (@elements_list == 0)
13326     {
13327         warn "$WARN empty document\n";
13328         exit (0);
13329     }
13330
13331     # We set titlefont only if the titlefont appeared in the top element
13332     if (defined($element_top->{'titlefont'}))
13333     {
13334          $value{'_titlefont'} = $element_top->{'titlefont'};
13335     }
13336     
13337     # prepare %Texi2HTML::THISDOC
13338 #    $Texi2HTML::THISDOC{'settitle_texi'} = $value{'_settitle'};
13339     $Texi2HTML::THISDOC{'fulltitle_texi'} = '';
13340     $Texi2HTML::THISDOC{'title_texi'} = '';
13341     foreach my $possible_fulltitle (('_title', '_settitle', '_shorttitlepage', '_titlefont'))
13342     {
13343         if ($value{$possible_fulltitle} ne '')
13344         {
13345             $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{$possible_fulltitle};
13346             last;
13347         }
13348     }
13349     foreach my $possible_title_texi ($value{'_settitle'}, $Texi2HTML::THISDOC{'fulltitle_texi'})
13350     {
13351         if ($possible_title_texi ne '')
13352         {
13353             $Texi2HTML::THISDOC{'title_texi'} = $possible_title_texi;
13354             last;
13355         }
13356     }
13357 #    $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'};
13358 #    $Texi2HTML::THISDOC{'title_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'};
13359     foreach my $texi_cmd (('shorttitlepage', 'settitle', 'author',
13360            'titlefont', 'subtitle', 'shorttitle'))
13361     {
13362         $Texi2HTML::THISDOC{$texi_cmd . '_texi'} = $value{'_' . $texi_cmd};
13363     }
13364     foreach my $doc_thing (('shorttitlepage', 'settitle', 'author',
13365            'titlefont', 'subtitle', 'shorttitle', 'fulltitle', 'title'))
13366     {
13367         my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'};
13368         $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi);
13369         $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} =
13370            remove_texi($thing_texi);
13371         $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} =
13372            simple_format(undef, $thing_texi);
13373     }
13374
13375     # find Top name
13376     my $element_top_text = '';
13377     my $top_no_texi = '';
13378     my $top_simple_format = '';
13379     my $top_name;
13380     if ($element_top and $element_top->{'text'} and (!$node_top or ($element_top ne $node_top)))
13381     {
13382         $element_top_text = $element_top->{'text'};
13383         $top_no_texi = $element_top->{'no_texi'};
13384         $top_simple_format =  $element_top->{'simple_format'};
13385     }
13386     foreach my $possible_top_name ($Texi2HTML::Config::TOP_HEADING, 
13387          $element_top_text, $Texi2HTML::THISDOC{'title'},
13388          $Texi2HTML::THISDOC{'shorttitle'}, &$I('Top'))
13389     {
13390          if (defined($possible_top_name) and $possible_top_name ne '')
13391          {
13392              $top_name = $possible_top_name;
13393              last;
13394          }
13395     }
13396     foreach my $possible_top_no_texi ($Texi2HTML::Config::TOP_HEADING, 
13397          $top_no_texi, $Texi2HTML::THISDOC{'title_no_texi'},
13398          $Texi2HTML::THISDOC{'shorttitle_no_texi'}, 
13399          &$I('Top',{},{'remove_texi' => 1}))
13400     {
13401          if (defined($possible_top_no_texi) and $possible_top_no_texi ne '')
13402          {
13403              $top_no_texi = $possible_top_no_texi;
13404              last;
13405          }
13406     }
13407      
13408     foreach my $possible_top_simple_format ($top_simple_format,
13409          $Texi2HTML::THISDOC{'title_simple_format'},
13410          $Texi2HTML::THISDOC{'shorttitle_simple_format'},
13411          &$I('Top',{}, {'simple_format' => 1}))
13412     {
13413          if (defined($possible_top_simple_format) and $possible_top_simple_format ne '')
13414          {
13415              $top_simple_format = $possible_top_simple_format;
13416              last;
13417          }
13418     }
13419      
13420      
13421 #    my $top_name = $Texi2HTML::Config::TOP_HEADING || $element_top_text || $Texi2HTML::THISDOC{'title'} || $Texi2HTML::THISDOC{'shorttitle'} || &$I('Top');
13422
13423     if ($Texi2HTML::THISDOC{'fulltitle_texi'} eq '')
13424     {
13425          $Texi2HTML::THISDOC{'fulltitle_texi'} = &$I('Untitled Document',{},
13426            {'keep_texi' => 1});
13427     }
13428     $Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'settitle_texi'};
13429     $Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'fulltitle_texi'} 
13430             if ($Texi2HTML::THISDOC{'title_texi'} eq '');
13431
13432     foreach my $doc_thing (('fulltitle', 'title'))
13433     {
13434         my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'};
13435         $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi);
13436         $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} =
13437            remove_texi($thing_texi);
13438         $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} =
13439            simple_format(undef, $thing_texi);
13440     }
13441
13442     for my $key (keys %Texi2HTML::THISDOC)
13443     {
13444         next if (ref($Texi2HTML::THISDOC{$key}));
13445 print STDERR "!!$key\n" if (!defined($Texi2HTML::THISDOC{$key}));
13446         $Texi2HTML::THISDOC{$key} =~ s/\s*$//;
13447     }
13448     $Texi2HTML::THISDOC{'program'} = $THISPROG;
13449     $Texi2HTML::THISDOC{'program_homepage'} = $T2H_HOMEPAGE;
13450     $Texi2HTML::THISDOC{'program_authors'} = $T2H_AUTHORS;
13451     $Texi2HTML::THISDOC{'user'} = $T2H_USER;
13452     $Texi2HTML::THISDOC{'user'} = $Texi2HTML::Config::USER if (defined($Texi2HTML::Config::USER));
13453 #    $Texi2HTML::THISDOC{'documentdescription'} = $documentdescription;
13454     $Texi2HTML::THISDOC{'copying'} = $copying_comment;
13455     $Texi2HTML::THISDOC{'destination_directory'} = $docu_rdir;
13456     $Texi2HTML::THISDOC{'authors'} = [] if (!defined($Texi2HTML::THISDOC{'authors'}));
13457     $Texi2HTML::THISDOC{'subtitles'} = [] if (!defined($Texi2HTML::THISDOC{'subtitles'}));
13458     $Texi2HTML::THISDOC{'titles'} = [] if (!defined($Texi2HTML::THISDOC{'titles'}));
13459     foreach my $element (('authors', 'subtitles', 'titles'))
13460     {
13461         my $i;
13462         for ($i = 0; $i < $#{$Texi2HTML::THISDOC{$element}} + 1; $i++) 
13463         {
13464             chomp ($Texi2HTML::THISDOC{$element}->[$i]);
13465             $Texi2HTML::THISDOC{$element}->[$i] = substitute_line($Texi2HTML::THISDOC{$element}->[$i]);
13466             #print STDERR "$element:$i: $Texi2HTML::THISDOC{$element}->[$i]\n";
13467         }
13468     }
13469     # prepare TOC, OVERVIEW...
13470     my ($toc_file, $stoc_file, $foot_file, $about_file);
13471     # if not split the references are to the same file
13472     $toc_file = $stoc_file = $foot_file = $about_file = '';
13473     if ($Texi2HTML::Config::SPLIT)
13474     {
13475         $toc_file = $docu_toc;
13476         $stoc_file = $docu_stoc;
13477         if ($Texi2HTML::Config::INLINE_CONTENTS)
13478         {
13479             $toc_file = $content_element{'contents'}->{'file'} if (defined($content_element{'contents'}));
13480             $stoc_file = $content_element{'shortcontents'}->{'file'} if (defined($content_element{'shortcontents'}));
13481         }
13482         $foot_file = $docu_foot;
13483         $about_file = $docu_about;
13484     }
13485     $Texi2HTML::THISDOC{'toc_file'} = $toc_file; 
13486     $Texi2HTML::HREF{'Contents'} = $toc_file.'#'.$content_element{'contents'}->{'id'} if @{$Texi2HTML::TOC_LINES};
13487     $Texi2HTML::HREF{'Overview'} = $stoc_file.'#'.$content_element{'shortcontents'}->{'id'} if @{$Texi2HTML::OVERVIEW};
13488     $Texi2HTML::HREF{'Footnotes'} = $foot_file. '#SEC_Foot';
13489     $Texi2HTML::HREF{'About'} = $about_file . '#SEC_About' unless ($one_section or (not $Texi2HTML::Config::SPLIT and not $Texi2HTML::Config::SECTION_NAVIGATION));
13490     
13491     $Texi2HTML::NAME{'First'} = $element_first->{'text'};
13492     $Texi2HTML::NAME{'Last'} = $element_last->{'text'};
13493     $Texi2HTML::NAME{'About'} = &$I('About This Document');
13494     $Texi2HTML::NAME{'Contents'} = &$I('Table of Contents');
13495     $Texi2HTML::NAME{'Overview'} = &$I('Short Table of Contents');
13496     $Texi2HTML::NAME{'Top'} = $top_name;
13497     $Texi2HTML::NAME{'Footnotes'} = &$I('Footnotes');
13498     $Texi2HTML::NAME{'Index'} = $element_chapter_index->{'text'} if (defined($element_chapter_index));
13499     $Texi2HTML::NAME{'Index'} = $Texi2HTML::Config::INDEX_CHAPTER if ($Texi2HTML::Config::INDEX_CHAPTER ne '');
13500
13501     $Texi2HTML::NO_TEXI{'First'} = $element_first->{'no_texi'};
13502     $Texi2HTML::NO_TEXI{'Last'} = $element_last->{'no_texi'};
13503     $Texi2HTML::NO_TEXI{'About'} = &$I('About This Document', {}, {'remove_texi' => 1} );
13504     $Texi2HTML::NO_TEXI{'Contents'} = &$I('Table of Contents', {}, {'remove_texi' => 1} );
13505     $Texi2HTML::NO_TEXI{'Overview'} = &$I('Short Table of Contents', {}, {'remove_texi' => 1} );
13506     $Texi2HTML::NO_TEXI{'Top'} = $top_no_texi;
13507     $Texi2HTML::NO_TEXI{'Footnotes'} = &$I('Footnotes', {}, {'remove_texi' => 1} );
13508     $Texi2HTML::NO_TEXI{'Index'} = $element_chapter_index->{'no_texi'} if (defined($element_chapter_index));
13509
13510     $Texi2HTML::SIMPLE_TEXT{'First'} = $element_first->{'simple_format'};
13511     $Texi2HTML::SIMPLE_TEXT{'Last'} = $element_last->{'simple_format'};
13512     $Texi2HTML::SIMPLE_TEXT{'About'} = &$I('About This Document', {}, {'simple_format' => 1});
13513     $Texi2HTML::SIMPLE_TEXT{'Contents'} = &$I('Table of Contents',{},  {'simple_format' => 1});
13514     $Texi2HTML::SIMPLE_TEXT{'Overview'} = &$I('Short Table of Contents', {}, {'simple_format' => 1});
13515     $Texi2HTML::SIMPLE_TEXT{'Top'} = $top_simple_format;
13516     $Texi2HTML::SIMPLE_TEXT{'Footnotes'} = &$I('Footnotes', {},{'simple_format' => 1});
13517
13518     $Texi2HTML::SIMPLE_TEXT{'Index'} = $element_chapter_index->{'simple_format'} if (defined($element_chapter_index));
13519     # must be after toc_body, but before titlepage
13520     for my $element_tag ('contents', 'shortcontents')
13521     {
13522         my $toc_lines = &$Texi2HTML::Config::inline_contents(undef, $element_tag, $content_element{$element_tag});
13523         @{$Texi2HTML::THISDOC{'inline_contents'}->{$element_tag}} = @$toc_lines if (defined($toc_lines));
13524     }
13525     $Texi2HTML::TITLEPAGE = '';
13526     $Texi2HTML::TITLEPAGE = substitute_text({}, @{$region_lines{'titlepage'}})
13527         if (@{$region_lines{'titlepage'}});
13528     &$Texi2HTML::Config::titlepage();
13529
13530     &$Texi2HTML::Config::init_out();
13531     $to_encoding = $Texi2HTML::Config::OUT_ENCODING;
13532
13533     ############################################################################
13534     # print frame and frame toc file
13535     #
13536     if ( $Texi2HTML::Config::FRAMES )
13537     {
13538         my $FH = open_out($docu_frame_file);
13539         print STDERR "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
13540         &$Texi2HTML::Config::print_frame($FH, $docu_toc_frame_file, $docu_top_file);
13541         close_out($FH, $docu_frame_file);
13542
13543         $FH = open_out($docu_toc_frame_file);
13544         print STDERR "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE;
13545         &$Texi2HTML::Config::print_toc_frame($FH, $Texi2HTML::OVERVIEW);
13546         close_out($FH, $docu_toc_frame_file);
13547     }
13548
13549     ############################################################################
13550     #
13551     #
13552
13553     my $FH;
13554     my $index_pages;
13555     my $index_pages_nr;
13556     my $index_nr = 0;
13557     my $line_nr;
13558     my $first_section = 0; # 1 if it is the first section of a page
13559     while (@doc_lines)
13560     {
13561         unless ($index_pages)
13562         { # not in a index split over sections
13563             $_ = shift @doc_lines;
13564             my $chomped_line = $_;
13565             if (!chomp($chomped_line) and @doc_lines)
13566             { # if the line has no end of line it is concatenated with the next
13567                  $doc_lines[0] = $_ . $doc_lines[0];
13568                  next;
13569             }
13570             $line_nr = shift (@doc_numbers);
13571             #print STDERR "$line_nr->{'file_name'}($line_nr->{'macro'},$line_nr->{'line_nr'}) $_" if ($line_nr);
13572         }
13573         #print STDERR "PASS_TEXT: $_";
13574         #dump_stack(\$text, \@stack, \%state);
13575         if (!$state{'raw'} and !$state{'verb'})
13576         {
13577             my $tag = '';
13578             $tag = $1 if (/^\@(\w+)/ and !$index_pages);
13579
13580             if (($tag eq 'node') or defined($sec2level{$tag}) or $index_pages)
13581             {
13582                 if (@stack or (defined($text) and $text ne ''))
13583                 {# in pass text node and section shouldn't appear in formats
13584                         #print STDERR "close_stack before \@$tag\n";
13585                         #print STDERR "text!$text%" if (! @stack);
13586                     close_stack(\$text, \@stack, \%state, $line_nr);
13587                     push @section_lines, $text;
13588                     $text = '';
13589                 }
13590                 $sec_num++ if ($sec2level{$tag});
13591                 my $new_element;
13592                 my $current_element;
13593                 if ($tag =~ /heading/)
13594                 {# handle headings, they are not in element lists
13595                     $current_element = $sections{$sec_num};
13596                     #print STDERR "HEADING $_";
13597                     if (! $element)
13598                     {
13599                         $new_element = shift @elements_list;
13600                     }
13601                     else
13602                     {
13603                         push (@section_lines, &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n");
13604                         push @section_lines, &$Texi2HTML::Config::heading($current_element);
13605                         next;
13606                     }
13607                 }
13608                 elsif (!$index_pages)
13609                 {# handle node and structuring elements
13610                     $current_element = shift (@all_elements);
13611                     ########################## begin debug section
13612                     if ($current_element->{'node'})
13613                     {
13614                          print STDERR 'NODE ' . "$current_element->{'texi'}($current_element->{'file'})" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13615                          print STDERR "($current_element->{'section_ref'}->{'texi'})" if ($current_element->{'section_ref'} and ($T2H_DEBUG & $DEBUG_ELEMENTS));
13616                     }
13617                     else
13618                     {
13619                          print STDERR 'SECTION ' . $current_element->{'texi'} if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13620                     }
13621                     print STDERR ": $_" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13622                     ########################## end debug section
13623
13624                     # The element begins a new section if there is no previous
13625                     # or it is an element and not the current one or the 
13626                     # associated section (in case of node) is not the current 
13627                     # one
13628                     if (!$element 
13629                       or ($current_element->{'element'} and ($current_element ne $element))
13630                       or ($current_element->{'section_ref'} and ($current_element->{'section_ref'} ne $element)))
13631                     {
13632                          $new_element = shift @elements_list;
13633                     }
13634                     ########################### begin debug
13635                     my $section_element = $new_element;
13636                     $section_element = $element unless ($section_element);
13637                     if (!$current_element->{'node'} and !$current_element->{'index_page'} and ($section_element ne $current_element))
13638                     {
13639                          print STDERR "NODE: $element->{'texi'}\n" if ($element->{'node'});
13640                          warn "elements_list and all_elements not in sync (elements $section_element->{'texi'}, all $current_element->{'texi'}): $_";
13641                     }
13642                     ########################### end debug
13643                 }
13644                 else
13645                 { # this is a new index section
13646                     $new_element = $index_pages->[$index_pages_nr]->{'element'};
13647                     $current_element = $index_pages->[$index_pages_nr]->{'element'};
13648                     print STDERR "New index page '$new_element->{'texi'}' nr: $index_pages_nr\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13649                     my $list_element = shift @elements_list;
13650                     die "element in index_pages $new_element->{'texi'} and in list $list_element->{'texi'} differs\n" unless ($list_element eq $new_element);
13651                 }
13652                 if ($new_element)
13653                 {
13654                     $index_nr = 0;
13655                     my $old = 'NO_OLD';
13656                     $old = $element->{'texi'} if (defined($element));
13657                     print STDERR "NEW: $new_element->{'texi'}, OLD: $old\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13658                     # print the element that just finished
13659                     $Texi2HTML::THIS_SECTION = \@section_lines;
13660                     $Texi2HTML::THIS_HEADER = \@head_lines;
13661                     if ($element)
13662                     {
13663                         finish_element($FH, $element, $new_element, $first_section);
13664                         $first_section = 0;
13665                         @section_lines = ();
13666                         @head_lines = ();
13667                     }
13668                     else
13669                     {
13670                         print STDERR "# Writing elements:" if ($T2H_VERBOSE);
13671                         if ($Texi2HTML::Config::IGNORE_PREAMBLE_TEXT)
13672                         {
13673                              @section_lines = ();
13674                              @head_lines = ();
13675                         }
13676                         # remove empty line at the beginning of @section_lines
13677                         shift @section_lines while (@section_lines and ($section_lines[0] =~ /^\s*$/));
13678                     }
13679                     # begin new element
13680                     my $previous_file;
13681                     $previous_file = $element->{'file'} if (defined($element));
13682                     $element = $new_element;
13683                     $state{'element'} = $element;
13684                     $Texi2HTML::THIS_ELEMENT = $element;
13685                     #print STDERR "Doing hrefs for $element->{'texi'} First ";
13686                     $Texi2HTML::HREF{'First'} = href($element_first, $element->{'file'});
13687                     #print STDERR "Last ";
13688                     $Texi2HTML::HREF{'Last'} = href($element_last, $element->{'file'});
13689                     #print STDERR "Index ";
13690                     $Texi2HTML::HREF{'Index'} = href($element_chapter_index, $element->{'file'}) if (defined($element_chapter_index));
13691                     #print STDERR "Top ";
13692                     $Texi2HTML::HREF{'Top'} = href($element_top, $element->{'file'});
13693                     if ($Texi2HTML::Config::INLINE_CONTENTS)
13694                     {
13695                         $Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $element->{'file'});
13696                         $Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $element->{'file'});
13697                     }
13698                     foreach my $direction (@element_directions)
13699                     {
13700                         my $elem = $element->{$direction};
13701                         $Texi2HTML::NODE{$direction} = undef;
13702                         $Texi2HTML::HREF{$direction} = undef;
13703                         next unless (defined($elem));
13704                         #print STDERR "$direction ";
13705                         if ($elem->{'node'} or $elem->{'external_node'} or $elem->{'index_page'} or !$elem->{'seen'})
13706                         {
13707                             $Texi2HTML::NODE{$direction} = $elem->{'text'};
13708                         }
13709                         elsif ($elem->{'node_ref'})
13710                         {
13711                             $Texi2HTML::NODE{$direction} = $elem->{'node_ref'}->{'text'};
13712                         }
13713                         if (!$elem->{'seen'})
13714                         {
13715                             $Texi2HTML::HREF{$direction} = do_external_href($elem->{'texi'});
13716                         }
13717                         else
13718                         {
13719                             $Texi2HTML::HREF{$direction} = href($elem, $element->{'file'});
13720                         }
13721                         $Texi2HTML::NAME{$direction} = $elem->{'text'};
13722                         $Texi2HTML::NO_TEXI{$direction} = $elem->{'no_texi'};
13723                         $Texi2HTML::SIMPLE_TEXT{$direction} = $elem->{'simple_format'};
13724                         #print STDERR "$direction ($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";
13725                     }
13726                     #print STDERR "\nDone hrefs for $element->{'texi'}\n";
13727                     $files{$element->{'file'}}->{'counter'}--;
13728                     if (!defined($previous_file) or ($element->{'file'} ne $previous_file))
13729                     {
13730                         my $file = $element->{'file'};
13731                         print STDERR "\n" if ($T2H_VERBOSE and !$T2H_DEBUG);
13732                         print STDERR "# Writing to $docu_rdir$file " if $T2H_VERBOSE;
13733                         my $do_page_head = 0;
13734                         if ($files{$file}->{'filehandle'})
13735                         {
13736                              $FH = $files{$file}->{'filehandle'};
13737                         }
13738                         else
13739                         {
13740                              $FH = open_out("$docu_rdir$file");
13741 #print STDERR "OPEN $docu_rdir$file, $FH". scalar($FH)."\n";
13742                              $files{$file}->{'filehandle'} = $FH;
13743                              $do_page_head = 1;
13744                         }
13745                         if ($element->{'top'})
13746                         {
13747                              &$Texi2HTML::Config::print_Top_header($FH, $do_page_head);
13748                         }
13749                         else
13750                         {
13751                              &$Texi2HTML::Config::print_page_head($FH) if ($do_page_head);
13752                              &$Texi2HTML::Config::print_chapter_header($FH) if $Texi2HTML::Config::SPLIT eq 'chapter';
13753                              &$Texi2HTML::Config::print_section_header($FH) if $Texi2HTML::Config::SPLIT eq 'section';
13754                         }
13755                         $first_section = 1;
13756                     }
13757                     print STDERR "." if ($T2H_VERBOSE);
13758                     print STDERR "\n" if ($T2H_DEBUG);
13759                 }
13760                 my $label = &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n";
13761                 if (@section_lines)
13762                 {
13763                     push (@section_lines, $label);
13764                 }
13765                 else
13766                 {
13767                     push @head_lines, $label;
13768                 }
13769                 if ($index_pages)
13770                 {
13771                     push @section_lines, &$Texi2HTML::Config::heading($element);
13772                     #print STDERR "Do index page $index_pages_nr\n";
13773                     my $page = do_index_page($index_pages, $index_pages_nr);
13774                     push @section_lines, $page;
13775                     if (defined ($index_pages->[$index_pages_nr + 1]))
13776                     {
13777                         $index_pages_nr++;
13778                     }
13779                     else
13780                     {
13781                         $index_pages = undef;
13782                     }
13783                     next;
13784                 }
13785                 push @section_lines, &$Texi2HTML::Config::heading($current_element) if ($current_element->{'element'} and !$current_element->{'top'});
13786                 next;
13787             }
13788             elsif ($tag eq 'printindex')
13789             {
13790                 s/\s+(\w+)\s*//;
13791                 my $name = $1;
13792                 close_paragraph(\$text, \@stack, \%state);
13793                 next if (!$index_names{$name} or $empty_indices{$name});
13794                 $printed_indices{$name} = 1;
13795                 print STDERR "print index $name($index_nr) in `$element->{'texi'}', element->{'indices'}: $element->{'indices'},\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS or $T2H_DEBUG & $DEBUG_INDEX);
13796                 print STDERR "element->{'indices'}->[index_nr]: $element->{'indices'}->[$index_nr] (@{$element->{'indices'}->[$index_nr]})\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS or $T2H_DEBUG & $DEBUG_INDEX);
13797                 $index_pages = $element->{'indices'}->[$index_nr] if (@{$element->{'indices'}->[$index_nr]} > 1);
13798                 $index_pages_nr = 0;
13799                 add_prev(\$text, \@stack, do_index_page($element->{'indices'}->[$index_nr], 0));  
13800                 $index_pages_nr++;
13801                 $index_nr++;
13802                 begin_paragraph (\@stack, \%state) if ($state{'preformatted'});
13803                 next if (@stack);
13804                 push @section_lines, $text;
13805                 $text = '';
13806                 next;
13807             }
13808             elsif (($tag eq 'contents') or ($tag eq 'summarycontents') or ($tag eq 'shortcontents'))
13809             {
13810                 my $element_tag = $tag;
13811                 $element_tag = 'shortcontents' if ($element_tag ne 'contents');
13812                 if ($Texi2HTML::Config::INLINE_CONTENTS and !$content_element{$element_tag}->{'aftertitlepage'})
13813                 {
13814                     if (@stack or (defined($text) and $text ne ''))
13815                     {# in pass text contents  shouldn't appear in formats
13816                         close_stack(\$text, \@stack, \%state, $line_nr);
13817                         push @section_lines, $text;
13818                         $text = '';
13819                     }
13820                     my $toc_lines = &$Texi2HTML::Config::inline_contents($FH, $tag, $content_element{$element_tag});
13821                     push (@section_lines, @$toc_lines) if (defined($toc_lines)) ;
13822                 }
13823                 next;
13824             }
13825         }
13826         scan_line($_, \$text, \@stack, \%state, $line_nr);
13827         #print STDERR "after scan_line: $_";
13828         #dump_stack(\$text, \@stack, \%state);
13829         next if (@stack);
13830         if ($text ne '' )
13831         { 
13832             push @section_lines, $text;
13833             $text = '';
13834         }
13835     }
13836     if (@stack)
13837     {# close stack at the end of pass text
13838         close_stack(\$text, \@stack, \%state, $line_nr);
13839     }
13840     if (defined($text))
13841     {
13842         push @section_lines, $text;
13843     }
13844     print STDERR "\n" if ($T2H_VERBOSE);
13845  
13846     $Texi2HTML::THIS_SECTION = \@section_lines;
13847     # if no sections, then simply print document as is
13848     if ($one_section)
13849     {
13850         if (@foot_lines)
13851         {
13852             &$Texi2HTML::Config::foot_section (\@foot_lines);
13853             push @section_lines, @foot_lines;
13854         }
13855         $Texi2HTML::THIS_HEADER = \@head_lines;
13856         if ($element->{'top'})
13857         {
13858             print STDERR "Bug: `$element->{'texi'}' level undef\n" if (!$element->{'node'} and !defined($element->{'level'}));
13859             $element->{'level'} = 1 if (!defined($element->{'level'}));
13860             $element->{'node'} = 0; # otherwise Texi2HTML::Config::heading may uses the node level
13861             $element->{'text'} = $Texi2HTML::NAME{'Top'};
13862             print STDERR "[Top]" if ($T2H_VERBOSE);
13863             unless ($element->{'titlefont'} or $element->{'index_page'})
13864             {
13865                 unshift @section_lines, &$Texi2HTML::Config::heading($element);
13866             }
13867         }
13868         print STDERR "# Write the section $element->{'texi'}\n" if ($T2H_VERBOSE);
13869         &$Texi2HTML::Config::one_section($FH);
13870         close_out($FH);
13871         return;
13872     }
13873
13874     finish_element ($FH, $element, undef, $first_section);
13875
13876     ############################################################################
13877     # Print ToC, Overview, Footnotes
13878     #
13879     foreach my $direction (@element_directions)
13880     {
13881         $Texi2HTML::HREF{$direction} = undef;
13882         delete $Texi2HTML::HREF{$direction};
13883         # it is better to undef in case the references to these hash entries
13884         # are used, as if deleted, the
13885         # references are still refering to the old, undeleted element
13886         # (we could do both)
13887         $Texi2HTML::NAME{$direction} = undef;
13888         $Texi2HTML::NO_TEXI{$direction} = undef;
13889         $Texi2HTML::SIMPLE_TEXT{$direction} = undef;
13890         $Texi2HTML::NODE{$direction} = undef;
13891
13892         $Texi2HTML::THIS_ELEMENT = undef;
13893     }
13894     if (@foot_lines)
13895     {
13896         print STDERR "# writing Footnotes in $docu_foot_file\n" if $T2H_VERBOSE;
13897         $FH = open_out ($docu_foot_file)
13898             if $Texi2HTML::Config::SPLIT;
13899         $Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{'Footnotes'};
13900         $Texi2HTML::HREF{'Footnotes'} = '#' . $footnote_element->{'id'};
13901         $Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{'Footnotes'};
13902         $Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{'Footnotes'};
13903         $Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{'Footnotes'};
13904         $Texi2HTML::THIS_SECTION = \@foot_lines;
13905         $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor($footnote_element->{'id'}) . "\n" ];
13906         &$Texi2HTML::Config::print_Footnotes($FH);
13907         close_out($FH, $docu_foot_file) 
13908                if ($Texi2HTML::Config::SPLIT);
13909         $Texi2HTML::HREF{'Footnotes'} = $Texi2HTML::HREF{'This'};
13910     }
13911
13912     if (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::Config::INLINE_CONTENTS)
13913     {
13914         print STDERR "# writing Toc in $docu_toc_file\n" if $T2H_VERBOSE;
13915         $FH = open_out ($docu_toc_file)
13916             if $Texi2HTML::Config::SPLIT;
13917         $Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{'Contents'};
13918         $Texi2HTML::HREF{'Contents'} = "#SEC_Contents";
13919         $Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{'Contents'};
13920         $Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{'Contents'};
13921         $Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{'Contents'};
13922         $Texi2HTML::THIS_SECTION = $Texi2HTML::TOC_LINES;
13923         $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_Contents") . "\n" ];
13924         &$Texi2HTML::Config::print_Toc($FH);
13925         close_out($FH, $docu_toc_file) 
13926                if ($Texi2HTML::Config::SPLIT);
13927         $Texi2HTML::HREF{'Contents'} = $Texi2HTML::HREF{'This'};
13928     }
13929
13930     if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::Config::INLINE_CONTENTS)
13931     {
13932         print STDERR "# writing Overview in $docu_stoc_file\n" if $T2H_VERBOSE;
13933         $FH = open_out ($docu_stoc_file)
13934             if $Texi2HTML::Config::SPLIT;
13935         $Texi2HTML::HREF{This} = $Texi2HTML::HREF{Overview};
13936         $Texi2HTML::HREF{Overview} = "#SEC_Overview";
13937         $Texi2HTML::NAME{This} = $Texi2HTML::NAME{Overview};
13938         $Texi2HTML::NO_TEXI{This} = $Texi2HTML::NO_TEXI{Overview};
13939         $Texi2HTML::SIMPLE_TEXT{This} = $Texi2HTML::SIMPLE_TEXT{Overview};
13940         $Texi2HTML::THIS_SECTION = $Texi2HTML::OVERVIEW;
13941         $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_Overview") . "\n" ];
13942         &$Texi2HTML::Config::print_Overview($FH);
13943         close_out($FH,$docu_stoc_file) 
13944                if ($Texi2HTML::Config::SPLIT);
13945         $Texi2HTML::HREF{Overview} = $Texi2HTML::HREF{This};
13946     }
13947     my $about_body;
13948     if ($about_body = &$Texi2HTML::Config::about_body())
13949     {
13950         print STDERR "# writing About in $docu_about_file\n" if $T2H_VERBOSE;
13951         $FH = open_out ($docu_about_file)
13952             if $Texi2HTML::Config::SPLIT;
13953
13954         $Texi2HTML::HREF{This} = $Texi2HTML::HREF{About};
13955         $Texi2HTML::HREF{About} = "#SEC_About";
13956         $Texi2HTML::NAME{This} = $Texi2HTML::NAME{About};
13957         $Texi2HTML::NO_TEXI{This} = $Texi2HTML::NO_TEXI{About};
13958         $Texi2HTML::SIMPLE_TEXT{This} = $Texi2HTML::SIMPLE_TEXT{About};
13959         $Texi2HTML::THIS_SECTION = [$about_body];
13960         $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_About") . "\n" ];
13961         &$Texi2HTML::Config::print_About($FH);
13962         close_out($FH, $docu_stoc_file) 
13963                if ($Texi2HTML::Config::SPLIT);
13964         $Texi2HTML::HREF{About} = $Texi2HTML::HREF{This};
13965     }
13966
13967     unless ($Texi2HTML::Config::SPLIT)
13968     {
13969         &$Texi2HTML::Config::print_page_foot($FH);
13970         close_out ($FH);
13971     }
13972 }
13973
13974 # print section, close file if needed.
13975 sub finish_element($$$$)
13976 {
13977     my $FH = shift;
13978     my $element = shift;
13979     my $new_element = shift;
13980     my $first_section = shift;
13981 #print STDERR "FINISH_ELEMENT($FH)($element->{'texi'})[$element->{'file'}] counter $files{$element->{'file'}}->{'counter'}\n";
13982
13983     # handle foot notes
13984     if ($Texi2HTML::Config::SPLIT and scalar(@foot_lines) 
13985         and !$Texi2HTML::Config::SEPARATED_FOOTNOTES
13986         and  (! $new_element or
13987         ($element and ($new_element->{'file'} ne $element->{'file'})))
13988        )
13989     {
13990         if ($files{$element->{'file'}}->{'counter'})
13991         {# there are other elements in that page we are not on its foot
13992             $files{$element->{'file'}}->{'relative_foot_num'} 
13993                = $relative_foot_num;
13994             push @{$files{$element->{'file'}}->{'foot_lines'}},
13995                 @foot_lines;
13996         }
13997         else
13998         {# we output the footnotes as we are at the file end
13999              unshift @foot_lines, @{$files{$element->{'file'}}->{'foot_lines'}};
14000              &$Texi2HTML::Config::foot_section (\@foot_lines);
14001              push @{$Texi2HTML::THIS_SECTION}, @foot_lines;
14002         }
14003         if ($new_element)
14004         {
14005             $relative_foot_num = 
14006                $files{$new_element->{'file'}}->{'relative_foot_num'};
14007         }
14008         @foot_lines = ();
14009     }
14010     if ($element->{'top'})
14011     {
14012         my $top_file = $docu_top_file;
14013         #print STDERR "TOP $element->{'texi'}, @section_lines\n";
14014         print STDERR "[Top]" if ($T2H_VERBOSE);
14015         $Texi2HTML::HREF{'Top'} = href($element_top, $element->{'file'});
14016         &$Texi2HTML::Config::print_Top($FH, ($element->{'titlefont'} or $element->{'index_page'}));
14017         my $end_page = 0;
14018         if ($Texi2HTML::Config::SPLIT)
14019         {
14020             if (!$files{$element->{'file'}}->{'counter'})
14021             {
14022                 $end_page = 1;
14023             }
14024         }
14025         &$Texi2HTML::Config::print_Top_footer($FH, $end_page);
14026         close_out($FH, $top_file) if ($end_page);
14027     }
14028     else
14029     {
14030         print STDERR "# do element $element->{'texi'}\n"
14031            if ($T2H_DEBUG & $DEBUG_ELEMENTS);
14032         &$Texi2HTML::Config::print_section($FH, $first_section);
14033         if (defined($new_element) and ($new_element->{'file'} ne $element->{'file'}))
14034         {
14035              if (!$files{$element->{'file'}}->{'counter'})
14036              {
14037                  &$Texi2HTML::Config::print_chapter_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'chapter');
14038                  &$Texi2HTML::Config::print_section_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'section');
14039                  #print STDERR "Close file after $element->{'texi'}\n";
14040                  &$Texi2HTML::Config::print_page_foot($FH);
14041                  close_out($FH);
14042              }
14043              else
14044              {
14045                  print STDERR "counter $files{$element->{'file'}}->{'counter'} ne 0, file $element->{'file'}\n" if ($T2H_DEBUG);
14046              }
14047         }
14048         elsif (!defined($new_element))
14049         {
14050             if ($Texi2HTML::Config::SPLIT)
14051             { # end of last splitted section
14052                 &$Texi2HTML::Config::print_chapter_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'chapter');
14053                 &$Texi2HTML::Config::print_section_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'section');
14054                 &$Texi2HTML::Config::print_page_foot($FH);
14055                 close_out($FH);
14056             }
14057             else
14058             {
14059                 &$Texi2HTML::Config::end_section($FH, 1);
14060             }
14061         }
14062         elsif ($new_element->{'top'})
14063         {
14064             &$Texi2HTML::Config::end_section($FH, 1);
14065         }
14066         else
14067         {
14068             &$Texi2HTML::Config::end_section($FH);
14069         }
14070     }
14071 }
14072
14073 # write to files with name the node name for cross manual references.
14074 sub do_node_files()
14075 {
14076     foreach my $key (keys(%nodes))
14077     {
14078         my $node = $nodes{$key};
14079         next unless ($node->{'node_file'});
14080         my $redirection_file = $docu_doc;
14081         $redirection_file = $node->{'file'} if ($Texi2HTML::Config::SPLIT);
14082         if (!$redirection_file)
14083         {
14084              print STDERR "Bug: file for redirection for `$node->{'texi'}' don't exist\n" unless ($novalidate);
14085              next;
14086         }
14087         next if ($redirection_file eq $node->{'node_file'});
14088         my $file = "${docu_rdir}$node->{'node_file'}";
14089         $Texi2HTML::NODE{'This'} = $node->{'text'};
14090         $Texi2HTML::NO_TEXI{'This'} = $node->{'no_texi'};
14091         $Texi2HTML::SIMPLE_TEXT{'This'} = $node->{'simple_format'};
14092         $Texi2HTML::NAME{'This'} = $node->{'text'};
14093         $Texi2HTML::HREF{'This'} = "$node->{'file'}#$node->{'id'}";
14094         my $NODEFILE = open_out ($file);
14095         &$Texi2HTML::Config::print_redirection_page ($NODEFILE);
14096         close $NODEFILE || die "$ERROR: Can't close $file: $!\n";
14097     }
14098 }
14099
14100 #+++############################################################################
14101 #                                                                              #
14102 # Low level functions                                                          #
14103 #                                                                              #
14104 #---############################################################################
14105
14106 sub locate_include_file($)
14107 {
14108     my $file = shift;
14109
14110     # APA: Don't implicitely search ., to conform with the docs!
14111     # return $file if (-e $file && -r $file);
14112     foreach my $dir (@Texi2HTML::Config::INCLUDE_DIRS)
14113     {
14114         return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file");
14115     }
14116     return undef;
14117 }
14118
14119 sub open_file($$)
14120 {
14121     my $name = shift;
14122     my $line_number = shift;
14123     local *FH;
14124     if (open(*FH, "<$name"))
14125     { 
14126         if (defined($Texi2HTML::Config::IN_ENCODING) and $Texi2HTML::Config::USE_UNICODE)
14127         {
14128             binmode(*FH, ":encoding($Texi2HTML::Config::IN_ENCODING)");
14129         }
14130         my $file = { 'fh' => *FH, 
14131            'input_spool' => { 'spool' => [], 
14132                               'macro' => '' },
14133            'name' => $name, 
14134            'line_nr' => 0 };
14135         unshift(@fhs, $file);
14136         $input_spool = $file->{'input_spool'};
14137         $line_number->{'file_name'} = $name;
14138         $line_number->{'line_nr'} = 1;
14139     }
14140     else
14141     {
14142         warn "$ERROR Can't read file $name: $!\n";
14143     }
14144 }
14145
14146 sub open_out($)
14147 {
14148     my $file = shift;
14149     local *FILE;
14150     if ($file eq '-')
14151     {
14152         binmode(STDOUT, ":encoding($to_encoding)") if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE);
14153         return \*STDOUT;
14154     }
14155
14156     unless (open(FILE, ">$file"))
14157     {
14158         die "$ERROR Can't open $file for writing: $!\n";
14159     }
14160     if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE)
14161     {
14162         if ($to_encoding eq 'utf8' or $to_encoding eq 'utf-8-strict')
14163         {
14164             binmode(FILE, ':utf8');
14165         }
14166         else
14167         {
14168             binmode(FILE, ':bytes');
14169         }
14170         binmode(FILE, ":encoding($to_encoding)");
14171     }
14172     return *FILE;
14173 }
14174
14175 # FIXME not used when split 
14176 sub close_out($;$)
14177 {
14178     my $FH = shift;
14179     my $file = shift;
14180     $file = '' if (!defined($file));
14181     return if ($Texi2HTML::Config::OUT eq '');
14182     close ($FH) || die "$ERROR: Error occurred when closing $file: $!\n";
14183 }
14184
14185 sub next_line($)
14186 {
14187     my $line_number = shift;
14188     while (@fhs)
14189     {
14190         my $file = $fhs[0];
14191         $line_number->{'file_name'} = $file->{'name'};
14192         $input_spool = $file->{'input_spool'};
14193         if (@{$input_spool->{'spool'}})
14194         {
14195              $line_number->{'macro'} = $file->{'input_spool'}->{'macro'};
14196              $line_number->{'line_nr'} = $file->{'line_nr'};
14197              my $line = shift(@{$input_spool->{'spool'}});
14198              print STDERR "# unspooling $line" if ($T2H_DEBUG & $DEBUG_MACROS);
14199              return($line);
14200         }
14201         else
14202         {
14203              $file->{'input_spool'}->{'macro'} = '';
14204              $line_number->{'macro'} = '';
14205         }
14206         my $fh = $file->{'fh'};
14207         no strict "refs";
14208         my $line = <$fh>;
14209         use strict "refs";
14210         my $chomped_line = $line;
14211         $file->{'line_nr'}++ if (defined($line) and chomp($chomped_line));
14212         $line_number->{'line_nr'} = $file->{'line_nr'};
14213         return($line) if (defined($line));
14214         no strict "refs";
14215         close($fh);
14216         use strict "refs";
14217         shift(@fhs);
14218     }
14219     return(undef);
14220 }
14221
14222 # echo a warning
14223 sub echo_warn($;$)
14224 {
14225     my $text = shift;
14226     chomp ($text);
14227     my $line_number = shift;
14228     warn "$WARN $text " . format_line_number($line_number) . "\n";
14229 }
14230
14231 sub echo_error($;$)
14232 {
14233     my $text = shift;
14234     chomp ($text);
14235     my $line_number = shift;
14236     warn "$ERROR $text " . format_line_number($line_number) . "\n";
14237 }
14238
14239 sub format_line_number($)
14240 {
14241     my $line_number = shift;
14242     my $macro_text = '';
14243     #$line_number = undef;
14244     return '' unless (defined($line_number));
14245     $macro_text = " in $line_number->{'macro'}" if ($line_number->{'macro'} ne '');
14246     my $file_text = '(';
14247     $file_text = "(in $line_number->{'file_name'} " if ($line_number->{'file_name'} ne $docu);
14248     return "${file_text}l. $line_number->{'line_nr'}" . $macro_text . ')';
14249 }
14250
14251 # to debug, dump the result of pass_texi and pass_structure in a file
14252 sub dump_texi($$;$$)
14253 {
14254     my $lines = shift;
14255     my $pass = shift;
14256     my $numbers = shift;
14257     my $file = shift;
14258     $file = "$docu_rdir$docu_name" . ".pass$pass" if (!defined($file));
14259     unless (open(DMPTEXI, ">$file"))
14260     {
14261          warn "Can't open $file for writing: $!\n";
14262     }
14263     print STDERR "# Dump texi\n" if ($T2H_VERBOSE);
14264     my $index = 0;
14265     foreach my $line (@$lines)
14266     {
14267         my $number_information = '';
14268         my $chomped_line = $line;
14269         $number_information = "$numbers->[$index]->{'file_name'}($numbers->[$index]->{'macro'},$numbers->[$index]->{'line_nr'}) " if (defined($numbers));
14270         print DMPTEXI "${number_information}$line";
14271         $index++ if (chomp($chomped_line));
14272     }
14273     close DMPTEXI;
14274 }
14275  
14276 # return next tag on the line
14277 sub next_tag($)
14278 {
14279     my $line = shift;
14280     # macro_regexp
14281     if ($line =~ /^\s*\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])/o or $line =~ /^\s*\@([a-zA-Z][\w-]*)([\s\{\}\@])/ or $line =~ /^\s*\@([a-zA-Z][\w-]*)$/)
14282     {
14283         return ($1);
14284     }
14285     return '';
14286 }
14287
14288 sub top_stack($)
14289 {
14290     my $stack = shift;
14291     return undef unless(@$stack);
14292     return $stack->[-1];
14293 }
14294
14295 # return the next element with balanced {}
14296 sub next_bracketed($$)
14297 {
14298     my $line = shift;
14299     my $line_nr = shift;
14300     my $opened_braces = 0;
14301     my $result = '';
14302     my $spaces;
14303     if ($line =~ /^(\s*)$/)
14304     {
14305         return ('','',$1);
14306     }
14307     while ($line !~ /^\s*$/)
14308     {
14309 #print STDERR "next_bracketed($opened_braces): $result !!! $line";
14310         if (!$opened_braces)
14311         { # beginning of item
14312             $line =~ s/^(\s*)//;
14313             $spaces = $1;
14314             #if ($line =~ s/^([^\{\}\s]+)//)
14315             if ($line =~ s/^([^\{\}]+?)(\s+)/$2/ or $line =~ s/^([^\{\}]+?)$//)
14316             {
14317                 $result = $1;
14318                 $result =~ s/\s*$//;
14319                 return ($result, $line, $spaces);
14320             }
14321             elsif ($line =~ s/^([^\{\}]+?)([\{\}])/$2/)
14322             {
14323                 $result = $1;
14324             }
14325         }
14326         elsif($line =~ s/^([^\{\}]+)//)
14327         {
14328             $result .= $1;
14329         }
14330         if ($line =~ s/^([\{\}])//)
14331         {
14332             my $brace = $1;
14333             $opened_braces++ if ($brace eq '{');
14334             $opened_braces-- if ($brace eq '}');
14335     
14336             if ($opened_braces < 0)
14337             {
14338                 echo_error("too much '}' in specification", $line_nr);
14339                 $opened_braces = 0;
14340                 next;
14341             }
14342             $result .= $brace;
14343             return ($result, $line, $spaces) if ($opened_braces == 0);
14344         }
14345     }
14346     if ($opened_braces)
14347     {
14348         echo_error("'{' not closed in specification", $line_nr);
14349         return ($result . ( '}' x $opened_braces), '', $spaces);
14350     }
14351     print STDERR "BUG: at the end of next_bracketed\n";
14352     return undef;
14353 }
14354
14355 # do a href using file and id and taking care of ommitting file if it is 
14356 # the same
14357 # element: structuring element to point to
14358 # file: current file
14359 sub href($$)
14360 {
14361     my $element = shift;
14362     my $file = shift;
14363     return '' unless defined($element);
14364     my $href = '';
14365     print STDERR "Bug: $element->{'texi'}, id undef\n" if (!defined($element->{'id'}));
14366     print STDERR "Bug: $element->{'texi'}, file undef\n" if (!defined($element->{'file'}));
14367 #foreach my $key (keys(%{$element}))
14368 #{
14369 #   my $value = 'UNDEF'; $value =  $element->{$key} if defined($element->{$key});
14370 #   print STDERR "$key: $value\n";
14371 #}print STDERR "\n";
14372     $href .= $element->{'file'} if (defined($element->{'file'}) and $file ne $element->{'file'});
14373     $href .= "#$element->{'id'}" if (defined($element->{'id'}));
14374     return $href;
14375 }
14376
14377 sub normalise_space($)
14378 {
14379    return undef unless (defined ($_[0]));
14380    my $text = shift;
14381    $text =~ s/\s+/ /go;
14382    $text =~ s/ $//;
14383    $text =~ s/^ //;
14384    return $text;
14385 }
14386
14387 sub normalise_node($)
14388 {
14389     return undef unless (defined ($_[0]));
14390     my $text = shift;
14391     $text = normalise_space($text);
14392     $text =~ s/^top$/Top/i;
14393     return $text;
14394 }
14395
14396 sub do_anchor_label($$$$)
14397 {
14398     my $command = shift;
14399     #my $anchor = shift;
14400     my $args = shift;
14401     my $anchor = $args->[0];
14402     my $style_stack = shift;
14403     my $state = shift;
14404     my $line_nr = shift;
14405
14406     return '' if ($state->{'multiple_pass'});
14407     $anchor = normalise_node($anchor);
14408     if (!exists($nodes{$anchor}) or !defined($nodes{$anchor}->{'id'}))
14409     {
14410         print STDERR "Bug: unknown anchor `$anchor'\n";
14411     }
14412     return &$Texi2HTML::Config::anchor($nodes{$anchor}->{'id'});
14413 }
14414
14415 sub get_format_command($)
14416 {
14417     my $format = shift;
14418     my $command = '';
14419     my $format_name = '';
14420     my $term = 0;
14421     my $item_nr;
14422     my $paragraph_number;
14423     my $enumerate_type;
14424     my $number;
14425     
14426     $command = $format->{'command'} if (defined($format->{'command'}));
14427     $format_name =  $format->{'format'} if (defined($format->{'format'}));
14428     $term = 1 if ($format->{'term'}); #This should never happen
14429
14430     return ($format_name,$command,\$format->{'paragraph_number'},$term,
14431         $format->{'item_nr'}, $format->{'spec'},  $format->{'number'},
14432         $format->{'stack_at_beginning'});
14433 }
14434
14435 sub do_paragraph($$)
14436 {
14437     my $text = shift;
14438     my $state = shift;
14439     my ($format, $paragraph_command, $paragraph_number, $term, $item_nr, 
14440         $enumerate_type, $number,$stack_at_beginning) 
14441          = get_format_command ($state->{'paragraph_context'});
14442     delete $state->{'paragraph_context'};
14443
14444     my $indent_style = '';
14445     if (exists($state->{'paragraph_indent'}))
14446     {
14447         $indent_style = $state->{'paragraph_indent'};
14448         $state->{'paragraph_indent'} = undef;
14449         delete $state->{'paragraph_indent'};
14450     }
14451     my $paragraph_command_formatted;
14452     $state->{'paragraph_nr'}--;
14453     (print STDERR "Bug text undef in do_paragraph", return '') unless defined($text);
14454     my $align = '';
14455     $align = $state->{'paragraph_style'}->[-1] if ($state->{'paragraph_style'}->[-1]);
14456     
14457     if (exists($::style_map_ref->{$paragraph_command}) and
14458        !exists($Texi2HTML::Config::special_list_commands{$format}->{$paragraph_command}))
14459     { 
14460         if ($format eq 'itemize')
14461         {
14462             chomp ($text);
14463             $text = do_simple($paragraph_command, $text, $state, [$text]);
14464             $text = $text . "\n";
14465         }
14466     }
14467     elsif (exists($::things_map_ref->{$paragraph_command}))
14468     {
14469         $paragraph_command_formatted = do_simple($paragraph_command, '', $state);
14470     }
14471     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);
14472 }
14473
14474 sub do_preformatted($$)
14475 {
14476     my $text = shift;
14477     my $state = shift;
14478     my ($format, $leading_command, $preformatted_number, $term, $item_nr, 
14479         $enumerate_type, $number,$stack_at_beginning) 
14480         = get_format_command($state->{'preformatted_context'});
14481     delete ($state->{'preformatted_context'});
14482     my $leading_command_formatted;
14483     my $pre_style = '';
14484     my $class = '';
14485     $pre_style = $state->{'preformatted_stack'}->[-1]->{'pre_style'} if ($state->{'preformatted_stack'}->[-1]->{'pre_style'});
14486     $class = $state->{'preformatted_stack'}->[-1]->{'class'};
14487     print STDERR "BUG: !state->{'preformatted_stack'}->[-1]->{'class'}\n" unless ($class);
14488     if (exists($::style_map_ref->{$leading_command}) and
14489        !exists($Texi2HTML::Config::special_list_commands{$format}->{$leading_command}) and ($style_type{$leading_command} eq 'style'))
14490     {
14491         $text = do_simple($leading_command, $text, $state,[$text]) if ($format eq 'itemize');
14492     }
14493     elsif (exists($::things_map_ref->{$leading_command}))
14494     {
14495         $leading_command_formatted = do_simple($leading_command, '', $state);
14496     }
14497     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);
14498 }
14499
14500 sub do_external_href($)
14501 {
14502     # node_id is a unique node identifier with only letters, digits, - and _
14503     # node_xhtml_id is almost the same, but xhtml id can only begin with
14504     # letters, so a prefix has to be appended  
14505     my $texi_node = shift;
14506     my $file = '';
14507     my $node_file = '';
14508     my $node_id = '';
14509     my $node_xhtml_id = '';
14510
14511 #print STDERR "do_external_href $texi_node\n";
14512
14513     if ($texi_node =~ s/^\((.+?)\)//)
14514     {
14515          $file = $1;
14516     }
14517     $texi_node = normalise_node($texi_node);
14518     if ($texi_node ne '')
14519     {
14520          if (exists($nodes{$texi_node}) and ($nodes{$texi_node}->{'cross_manual_target'})) 
14521          {
14522                $node_id = $nodes{$texi_node}->{'cross_manual_target'};
14523                if ($Texi2HTML::Config::TRANSLITERATE_NODE)
14524                {
14525                    $node_file = $nodes{$texi_node}->{'cross_manual_file'};
14526                }
14527          }
14528          else 
14529          {
14530               if ($Texi2HTML::Config::TRANSLITERATE_NODE)
14531               {
14532                   ($node_id, $node_file) = cross_manual_line($texi_node,1);
14533               }
14534               else
14535               {
14536                   $node_id = cross_manual_line($texi_node);
14537               }
14538          }
14539          $node_xhtml_id = node_to_id($node_id);
14540          $node_file = $node_id unless ($Texi2HTML::Config::TRANSLITERATE_NODE);
14541     }
14542     return &$Texi2HTML::Config::external_href($texi_node, $node_file, 
14543         $node_xhtml_id, $file);
14544 }
14545
14546 # transform node for cross ref name to id suitable for xhtml: an xhtml id
14547 # must begin with a letter.
14548 sub node_to_id($)
14549 {
14550     my $cross_ref_node_name = shift;
14551     $cross_ref_node_name =~ s/^([0-9_])/g_t$1/;
14552     return $cross_ref_node_name;
14553 }
14554
14555 # return 1 if the following tag shouldn't begin a line
14556 sub no_line($)
14557 {
14558     my $line = shift;
14559     my $next_tag = next_tag($line);
14560     return 1 if (($line =~ /^\s*$/) or $no_line_macros{$next_tag} or 
14561        (($next_tag =~ /^(\w+?)index$/) and ($1 ne 'print')) or 
14562        (($line =~ /^\@end\s+(\w+)/) and  $no_line_macros{"end $1"}));
14563     return 0;
14564 }
14565
14566 sub no_paragraph($$)
14567 {
14568     my $state = shift;
14569     my $line = shift;
14570     return ($state->{'paragraph_context'} or $state->{'preformatted'} or $state->{'remove_texi'} or no_line($line) or $state->{'no_paragraph'});
14571 }
14572
14573 # We restart the preformatted format which was stopped 
14574 # by the format if in preformatted, and start a paragraph
14575 # for the text following the end of the format, if needed
14576 sub begin_paragraph_after_command($$$$)
14577 {
14578     my $state = shift;
14579     my $stack = shift;
14580     my $command = shift;
14581     my $text_following = shift;
14582     
14583     if (($state->{'preformatted'} 
14584            and !$Texi2HTML::Config::format_in_paragraph{$command})
14585         or (!no_paragraph($state,$text_following)))  
14586     {
14587         begin_paragraph($stack, $state); 
14588     }
14589 }
14590
14591 # handle raw formatting, ignored regions...
14592 sub do_text_macro($$$$$)
14593 {
14594     my $type = shift;
14595     my $line = shift;
14596     my $state = shift;
14597     my $stack = shift;
14598     my $line_nr = shift;
14599     my $value;
14600     #print STDERR "do_text_macro $type\n";
14601
14602     if ($text_macros{$type} eq 'raw')
14603     {
14604         $state->{'raw'} = $type;
14605         #print STDERR "RAW\n";
14606         if ($state->{'raw'})
14607         {
14608              push @$stack, { 'style' => $type, 'text' => '' };
14609         }
14610     }
14611     elsif ($text_macros{$type} eq 'value')
14612     {
14613         if (($line =~ s/(\s+)($VARRE)$//) or ($line =~ s/(\s+)($VARRE)(\s)//))
14614         {
14615             $value = $1 . $2;
14616             $value .= $3 if defined($3);
14617             if ($state->{'ignored'})
14618             {
14619                 if ($type eq $state->{'ignored'})
14620                 {
14621                     $state->{'ifvalue_inside'}++;
14622                 }
14623                 # if 'ignored' we don't care about the command as long as
14624                 # the nesting is correct
14625                 return ($line,'');
14626             }
14627             my $open_ifvalue = 0;
14628             if ($type eq 'ifclear')
14629             {
14630                 if (defined($value{$2}))
14631                 {
14632                     $open_ifvalue = 1;
14633                 }
14634                 else
14635                 {
14636                     push @{$state->{'text_macro_stack'}}, $type;
14637                 }
14638             }
14639             elsif ($type eq 'ifset')
14640             {
14641                 unless (defined($value{$2}))
14642                 {
14643                     $open_ifvalue = 1;
14644                 }
14645                 else
14646                 {
14647                     push @{$state->{'text_macro_stack'}}, $type;
14648                 }
14649             }
14650             if ($open_ifvalue)
14651             {
14652                 $state->{'ignored'} = $type;
14653                 $state->{'ifvalue'} = $type;
14654                 $state->{'ifvalue_inside'} = 1;
14655                 # We add at the top of the stack to be able to close all
14656                 # opened comands when closing the ifset/ifclear (and ignore
14657                 # everything that is in those commands)
14658                 push @$stack, { 'style' => 'ifvalue', 'text' => '' };
14659             }
14660             
14661         }
14662         else
14663         { # we accept a lone @ifset or @ifclear if it is inside an 
14664             if ($type eq $state->{'ifvalue'})
14665             {
14666                 $state->{'ifvalue_inside'}++;
14667                 return ($line,'');
14668             }
14669             echo_error ("Bad $type line: $line", $line_nr) unless ($state->{'ignored'});
14670         }
14671     }
14672     elsif (not $text_macros{$type})
14673     { # ignored text
14674         $state->{'ignored'} = $type;
14675         #print STDERR "IGNORED\n";
14676     }
14677     else
14678     {
14679         push @{$state->{'text_macro_stack'}}, $type unless($state->{'ignored'}) ;
14680     }
14681     my $text = "\@$type";
14682     $text .= $value if defined($value); 
14683     return ($line, $text);
14684 }
14685
14686 # do regions handled specially, currently only tex, going through latex2html
14687 sub init_special($$)
14688 {
14689     my $style = shift;
14690     my $text = shift;
14691     if (defined($Texi2HTML::Config::command_handler{$style}) and
14692        defined($Texi2HTML::Config::command_handler{$style}->{'init'}))
14693     {
14694         $special_commands{$style}->{'count'} = 0 if (!defined($special_commands{$style}));
14695         if ($Texi2HTML::Config::command_handler{$style}->{'init'}($style,$text,
14696                $special_commands{$style}->{'count'} +1))
14697         {
14698             $special_commands{$style}->{'count'}++;  
14699             return "\@special_${style}_".$special_commands{$style}->{'count'}."{}";
14700         }
14701         return '';
14702     }
14703 }
14704
14705 sub do_insertcopying($)
14706 {
14707     my $state = shift;
14708     return '' unless @{$region_lines{'copying'}};
14709     my $insert_copying_state = duplicate_state($state);
14710     $insert_copying_state->{'multiple_pass'} = 1;
14711     return substitute_text($insert_copying_state, @{$region_lines{'copying'}});
14712 }
14713
14714 sub get_deff_index($$$)
14715 {
14716     my $tag = shift;
14717     my $line = shift;
14718     my $line_nr = shift;
14719    
14720     $tag =~ s/x$//;
14721     my ($style, $category, $name, $type, $class, $arguments);
14722     ($style, $category, $name, $type, $class, $arguments) = parse_def($tag, $line, $line_nr); 
14723     $name = &$Texi2HTML::Config::definition_category($name, $class, $style);
14724     return ($style, '') if (!defined($name) or ($name =~ /^\s*$/));
14725     return ($style, $name, $arguments);
14726 }
14727
14728 sub parse_def($$$)
14729 {
14730     my $command = shift;
14731     my $line = shift;
14732     my $line_nr = shift;
14733
14734     my $tag = $command;
14735
14736     if (!ref ($Texi2HTML::Config::def_map{$tag}))
14737     {
14738         # substitute shortcuts for definition commands
14739         my $substituted = $Texi2HTML::Config::def_map{$tag};
14740         $substituted =~ s/(\w+)//;
14741         $tag = $1;
14742         $line = $substituted . $line;
14743     }
14744 #print STDERR "PARSE_DEF($command,$tag) $line";
14745     my ($category, $name, $type, $class, $arguments);
14746     my @args = @{$Texi2HTML::Config::def_map{$tag}};
14747     my $style = shift @args;
14748     while (@args)
14749     {
14750         my $arg = shift @args;
14751         if (defined($arg))
14752         {
14753             # backward compatibility, it was possible to have a { in front.
14754             $arg =~  s/^\{//;
14755             my $item;
14756             my $spaces;
14757             ($item, $line,$spaces) = next_bracketed($line, $line_nr);
14758             last if (!defined($item));
14759             $item =~ s/^\{(.*)\}$/$1/ if ($item =~ /^\{/);
14760             if ($arg eq 'category')
14761             {
14762                 $category = $item;
14763             }
14764             elsif ($arg eq 'name')
14765             {
14766                 $name = $item;
14767             }
14768             elsif ($arg eq 'type')
14769             {
14770                 $type = $item;
14771             }
14772             elsif ($arg eq 'class')
14773             {
14774                 $class = $item;
14775             }
14776             elsif ($arg eq 'arg')
14777             { 
14778                 $line = $spaces . $item . $line;
14779             }
14780         }
14781         else
14782         {
14783             last;
14784         }
14785     }
14786 #print STDERR "PARSE_DEF (style $style, category $category, name $name, type $type, class $class, line $line)\n";
14787     return ($style, $category, $name, $type, $class, $line);
14788 }
14789
14790 sub begin_deff_item($$;$)
14791 {
14792     my $stack = shift;
14793     my $state = shift;
14794     my $no_paragraph = shift;
14795     #print STDERR "DEF push deff_item for $state->{'deff'}\n";
14796     push @$stack, { 'format' => 'deff_item', 'text' => '', 'deff_line' => $state->{'deff_line'}};
14797     # there is no paragraph when a new deff just follows the deff we are
14798     # opening
14799     begin_paragraph($stack, $state) 
14800        if ($state->{'preformatted'} and !$no_paragraph);
14801     delete($state->{'deff_line'});
14802     #dump_stack(undef, $stack, $state);
14803 }
14804
14805 sub begin_paragraph($$)
14806 {
14807     my $stack = shift;
14808     my $state = shift;
14809
14810     my $command = 1;
14811     my $top_format = top_format($stack);
14812     if (defined($top_format))
14813     {
14814         $command = $top_format;
14815     }
14816     else
14817     {
14818         $command = { };
14819     }
14820     $command->{'stack_at_beginning'} = [ @{$state->{'command_stack'}} ];
14821     if ($state->{'preformatted'})
14822     {
14823         push @$stack, {'format' => 'preformatted', 'text' => '' };
14824         $state->{'preformatted_context'} = $command;
14825         push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'};
14826         delete $state->{'paragraph_macros'};
14827         return;
14828     }
14829     $state->{'paragraph_context'} = $command;
14830     $state->{'paragraph_nr'}++;
14831     push @$stack, {'format' => 'paragraph', 'text' => '' };
14832     # if there are macros which weren't closed when the previous 
14833     # paragraph was closed we reopen them here
14834     push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'};
14835     delete $state->{'paragraph_macros'};
14836 }
14837
14838 sub parse_format_command($$)
14839 {
14840     my $line = shift;
14841     my $tag = shift;
14842     my $command = 'asis';
14843     # macro_regexp
14844     if (($line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?$/ or $line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?\s/) and ($::things_map_ref->{$1} or defined($::style_map_ref->{$1})))
14845     {
14846         # macro_regexp
14847         $line =~ s/^\s*\@([A-Za-z][\w-]*)(\{\})?\s*//;
14848         $command = $1;
14849     }
14850     return ('', $command) if ($line =~ /^\s*$/);
14851     chomp $line;
14852     $line = substitute_text ({'keep_nr' => 1, 'keep_texi' => 1, 'check_item' => $tag}, $line);
14853     return ($line, $command);
14854 }
14855
14856 sub parse_enumerate($)
14857 {
14858     my $line = shift;
14859     my $spec;
14860     if ($line =~ /^\s*(\w)\b/ and ($1 ne '_'))
14861     {
14862         $spec = $1;
14863         $line =~ s/^\s*(\w)\s*//;
14864     }
14865     return ($line, $spec);
14866 }
14867
14868 sub parse_multitable($$)
14869 {
14870     my $line = shift;
14871     my $line_nr = shift;
14872     # first find the table width
14873     my $table_width = 0;
14874     if ($line =~ s/^\s+\@columnfractions\s+//)
14875     {
14876         my @fractions = split /\s+/, $line;
14877         $table_width = $#fractions + 1;
14878         while (@fractions)
14879         {
14880             my $fraction = shift @fractions;
14881             unless ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/)
14882             { 
14883                 echo_error ("column fraction not a number: $fraction", $line_nr);
14884                 #warn "$ERROR column fraction not a number: $fraction";
14885             }
14886         }
14887     }
14888     else
14889     {
14890         my $element;
14891         my $line_orig = $line;
14892         while ($line !~ /^\s*$/)
14893         {
14894             my $spaces;
14895             ($element, $line, $spaces) = next_bracketed($line, $line_nr);
14896             if ($element =~ /^\{/)
14897             {
14898                 $table_width++; 
14899             }
14900             else
14901             {
14902                 echo_error ("garbage in multitable specification: $element", $line_nr);
14903             }
14904         }
14905     }
14906     return ($table_width);
14907 }
14908
14909 sub end_format($$$$$)
14910 {
14911     my $text = shift;
14912     my $stack = shift;
14913     my $state = shift;
14914     my $format = shift;
14915     my $line_nr = shift;
14916     #print STDERR "END FORMAT $format\n";
14917     #dump_stack($text, $stack, $state);
14918     #sleep 1;
14919     if ($format_type{$format} eq 'menu')
14920     {
14921         $state->{'menu'}--;
14922         close_menu($text, $stack, $state, $line_nr); 
14923     }
14924     if (($format_type{$format} eq 'list') or ($format_type{$format} eq 'table'))
14925     { # those functions return if they detect an inapropriate context
14926         add_item($text, $stack, $state, $line_nr, '', 1); # handle lists
14927         add_term($text, $stack, $state, $line_nr, 1); # handle table
14928         add_line($text, $stack, $state, $line_nr, 1); # handle table
14929         add_row($text, $stack, $state, $line_nr); # handle multitable
14930     }
14931
14932     #print STDERR "END_FORMAT\n";
14933     #dump_stack($text, $stack, $state);
14934
14935     # set to 1 if there is a mismatch between the closed format and format
14936     # opened before
14937     my $format_mismatch = 0;
14938         
14939     my $format_ref = pop @$stack;
14940     
14941     ######################### debug
14942     if (!defined($format_ref->{'text'}))
14943     {
14944         push @$stack, $format_ref;
14945         print STDERR "Bug: text undef in end_format $format\n";
14946         dump_stack($text, $stack, $state);
14947         pop @$stack;
14948     }
14949     ######################### end debug
14950     
14951     if (defined($Texi2HTML::Config::def_map{$format}))
14952     {
14953         close_stack($text, $stack, $state, $line_nr, undef, 'deff_item')
14954            unless ($format_ref->{'format'} eq 'deff_item');
14955         add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'}));
14956         $format_ref = pop @$stack; # pop deff
14957         ######################################### debug
14958         if (!defined($format_ref->{'format'}) or !defined($Texi2HTML::Config::def_map{$format_ref->{'format'}}))
14959         {
14960              print STDERR "Bug: not a def* under deff_item\n";
14961              push (@$stack, $format_ref);
14962              dump_stack($text, $stack, $state);
14963              pop @$stack;  
14964         }
14965         ######################################### end debug
14966         elsif ($format_ref->{'format'} ne $format)
14967         {
14968              $format_mismatch = 1;
14969              echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format", $line_nr);
14970         }
14971         add_prev($text, $stack, &$Texi2HTML::Config::def($format_ref->{'text'}));
14972     }
14973     elsif ($format_type{$format} eq 'cartouche')
14974     {
14975         add_prev($text, $stack, &$Texi2HTML::Config::cartouche($format_ref->{'text'},$state->{'command_stack'}));
14976     }
14977     elsif ($format eq 'float')
14978     {
14979         unless (defined($state->{'float'}))
14980         {
14981             print STDERR "Bug: state->{'float'} not defined in float\n";
14982             next;
14983         }
14984         my ($caption_lines, $shortcaption_lines) = &$Texi2HTML::Config::caption_shortcaption($state->{'float'});
14985         my ($caption_text, $shortcaption_text);
14986         $caption_text = substitute_text(duplicate_state($state), @$caption_lines) if (defined($caption_lines));
14987         $shortcaption_text = substitute_text(duplicate_state($state), @$shortcaption_lines) if (defined($shortcaption_lines));
14988         add_prev($text, $stack, &$Texi2HTML::Config::float($format_ref->{'text'}, $state->{'float'}, $caption_text, $shortcaption_text));
14989         delete $state->{'float'};
14990     }
14991     elsif (exists ($Texi2HTML::Config::complex_format_map->{$format}))
14992     {
14993         $state->{'preformatted'}--;
14994         pop @{$state->{'preformatted_stack'}};
14995         # debug
14996         if (!defined($Texi2HTML::Config::complex_format_map->{$format_ref->{'format'}}->{'begin'}))
14997         {
14998             print STDERR "Bug undef $format_ref->{'format'}" . "->{'begin'} (for $format...)\n";
14999             dump_stack ($text, $stack, $state);
15000         }
15001         #print STDERR "before $format\n";
15002         #dump_stack ($text, $stack, $state);
15003         add_prev($text, $stack, &$Texi2HTML::Config::complex_format($format_ref->{'format'}, $format_ref->{'text'}));
15004         #print STDERR "after $format\n";
15005         #dump_stack ($text, $stack, $state);
15006     }
15007     elsif (($format_type{$format} eq 'table') or ($format_type{$format} eq 'list'))
15008     {
15009             #print STDERR "CLOSE $format ($format_ref->{'format'})\n$format_ref->{'text'}\n";
15010         pop @{$state->{'table_list_stack'}};
15011         #dump_stack($text, $stack, $state); 
15012         if ($format_ref->{'format'} ne $format)
15013         { # for example vtable closing a table. Cannot be known 
15014           # before if in a cell
15015              $format_mismatch = 1;
15016              echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format  ", $line_nr);
15017         }
15018         if ($Texi2HTML::Config::format_map{$format})
15019         { # table or list has a simple format
15020             add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}));
15021         }
15022         else
15023         { # table or list handler defined by the user
15024             add_prev($text, $stack, &$Texi2HTML::Config::table_list($format_ref->{'format'}, $format_ref->{'text'}, $format_ref->{'command'}));
15025         }
15026     } 
15027     elsif ($format_type{$format} eq 'menu')
15028     {
15029     # it should be short-circuited if $Texi2HTML::Config::SIMPLE_MENU
15030         if ($state->{'preformatted'})
15031         {
15032             # end the fake complex format
15033             $state->{'preformatted'}--;
15034             pop @{$state->{'preformatted_stack'}};
15035             pop @$stack;
15036         }
15037         add_prev($text, $stack, &$Texi2HTML::Config::menu($format_ref->{'text'}));
15038     }
15039     elsif ($format eq 'quotation')
15040     {
15041         my $quotation_args = pop @{$state->{'quotation_stack'}};
15042         #add_prev($text, $stack, &$Texi2HTML::Config::quotation($format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'style_texi'}, $quotation_args->{'style_id'}));
15043         add_prev($text, $stack, &$Texi2HTML::Config::quotation($format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'text_texi'}));
15044     }
15045     elsif ($Texi2HTML::Config::paragraph_style{$format})
15046     {
15047         if ($state->{'paragraph_style'}->[-1] eq $format)
15048         {
15049             pop @{$state->{'paragraph_style'}};
15050         }
15051         add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command($format_ref->{'format'},$format_ref->{'text'}));
15052     }
15053     elsif (exists($Texi2HTML::Config::format_map{$format}))
15054     {
15055         add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}));
15056     }
15057     else
15058     {
15059         echo_warn("Unknown format $format", $line_nr);
15060     }
15061     # special case for center as it is at the bottom of the stack
15062     my $removed_from_stack;
15063     if ($format eq 'center')
15064     {
15065         $removed_from_stack = shift @{$state->{'command_stack'}};
15066     }
15067     else
15068     {
15069         $removed_from_stack = pop @{$state->{'command_stack'}};
15070     }
15071     if ($removed_from_stack ne $format and !$format_mismatch)
15072     {
15073         print STDERR "Bug: removed_from_stack $removed_from_stack ne format $format\n";
15074     }
15075 }
15076
15077 sub do_text($;$)
15078 {
15079     my $text = shift;
15080     my $state = shift;
15081     return $text if ($state->{'keep_texi'});
15082     my $remove_texi = 1 if ($state->{'remove_texi'} and !$state->{'simple_format'});
15083     return (&$Texi2HTML::Config::normal_text($text, $remove_texi, $state->{'preformatted'}, $state->{'code_style'},$state->{'command_stack'}));
15084 }
15085
15086 sub end_simple_format($$)
15087 {
15088     my $tag = shift;
15089     my $text = shift;
15090
15091     my $element = $Texi2HTML::Config::format_map{$tag};
15092     return &$Texi2HTML::Config::format($tag, $element, $text);
15093 }
15094
15095 sub close_menu($$$$)
15096 {
15097     my $text = shift;
15098     my $stack = shift;
15099     my $state = shift;
15100     my $line_nr = shift;
15101     if ($state->{'menu_comment'})
15102     {
15103         #print STDERR "close MENU_COMMENT\n";
15104         #dump_stack($text, $stack, $state);
15105         close_stack($text, $stack, $state, $line_nr, undef, 'menu_comment');
15106         # close_paragraph isn't needed in most cases, but a preformatted may 
15107         # appear after close_stack if we closed a format, as formats reopen
15108         # preformatted. However it is empty and close_paragraph will remove it
15109         close_paragraph($text, $stack, $state); 
15110         my $menu_comment = pop @$stack;
15111         if (!$menu_comment->{'format'} or $menu_comment->{'format'} ne 'menu_comment')
15112         {
15113             warn "Bug waiting for menu_comment, got $menu_comment->{'format'}\n"; 
15114             dump_stack($text, $stack, $state);
15115         }
15116         add_prev($text, $stack, &$Texi2HTML::Config::menu_comment($menu_comment->{'text'}));
15117         unless ($Texi2HTML::Config::SIMPLE_MENU)
15118         {
15119             pop @{$state->{'preformatted_stack'}};
15120             $state->{'preformatted'}--;
15121         }
15122         $state->{'menu_comment'}--;
15123     }
15124     if ($state->{'menu_entry'})
15125     {
15126         close_stack($text, $stack,$state, $line_nr, undef, 'menu_description');
15127         my $descr = pop(@$stack);
15128         print STDERR "# close_menu: close description\n" if ($T2H_DEBUG & $DEBUG_MENU);
15129         add_prev($text, $stack, do_menu_description($descr->{'text'}, $state));
15130         delete $state->{'menu_entry'};
15131     }
15132 }
15133
15134 # Format menu link
15135 sub do_menu_link($$;$)
15136 {
15137     my $state = shift;
15138     my $line_nr = shift;
15139     my $simple = shift;
15140     my $menu_entry = $state->{'menu_entry'};
15141     my $file = $state->{'element'}->{'file'};
15142     my $node_name = normalise_node($menu_entry->{'node'});
15143
15144     my $substitution_state = duplicate_state($state);
15145     my $name = substitute_line($menu_entry->{'name'}, $substitution_state);
15146     my $node_formatted = substitute_line($menu_entry->{'node'}, $substitution_state);
15147
15148     my $entry = '';
15149     my $href;
15150     my $element = $nodes{$node_name};
15151
15152     # menu points to an unknown node
15153     if (!$element->{'seen'})
15154     {
15155         if ($menu_entry->{'node'} =~ /^\s*\(.*\)/o or $novalidate)
15156         {
15157             # menu entry points to another info manual or invalid nodes
15158             # and novalidate is set
15159             #$href = $nodes{$node_name}->{'file'};
15160             $href = do_external_href($node_name);
15161         }
15162         else
15163         {
15164             echo_error ("Unknown node in menu entry `$node_name'", $line_nr);
15165             # try to find an equivalent node
15166             my @equivalent_nodes = equivalent_nodes($node_name);
15167             my $node_seen;
15168             foreach my $equivalent_node (@equivalent_nodes)
15169             {
15170                 if ($nodes{$equivalent_node}->{'seen'})
15171                 {
15172                     $node_seen = $equivalent_node;
15173                     last;
15174                 }
15175             }
15176             if (defined($node_seen))
15177             {
15178                 echo_warn (" ---> but equivalent node `$node_seen' found");
15179                 $element = $nodes{$node_seen};
15180             }
15181         }
15182     }
15183
15184     # the original node or an equivalent node was seen
15185     if ($element->{'seen'})
15186     {
15187         if ($element->{'reference_element'})
15188         {
15189             $element = $element->{'reference_element'};
15190         }
15191     
15192         #print STDERR "SUBHREF in menu for `$element->{'texi'}'\n";
15193         $href = href($element, $file);
15194         if (! $element->{'node'})
15195         {
15196             $entry = $element->{'text'}; # this is the section/node name
15197             $entry = "$Texi2HTML::Config::MENU_SYMBOL $entry" if (($entry ne '') and (!defined($element->{'number'}) or ($element->{'number'} =~ /^\s*$/)) and $Texi2HTML::Config::UNNUMBERED_SYMBOL_IN_MENU);
15198         }
15199     }
15200     # save the element used for the href for the description
15201     $menu_entry->{'menu_reference_element'} = $element;
15202
15203     return &$Texi2HTML::Config::menu_link($entry, $substitution_state, $href, $node_formatted, $name, $menu_entry->{'ending'}) unless ($simple);
15204     return &$Texi2HTML::Config::simple_menu_link($entry, $state->{'preformatted'}, $href, $node_formatted, $name, $menu_entry->{'ending'});
15205 }
15206
15207 sub do_menu_description($$)
15208 {
15209     my $descr = shift;
15210     my $state = shift;
15211     my $menu_entry = $state->{'menu_entry'};
15212
15213     my $element = $menu_entry->{'menu_reference_element'};
15214
15215     return &$Texi2HTML::Config::menu_description($descr, duplicate_state($state),$element->{'text_nonumber'});
15216 }
15217
15218 sub do_xref($$$$)
15219 {
15220     my $macro = shift;
15221     my $args = shift;
15222     my $style_stack = shift;
15223     my $state = shift;
15224     my $line_nr = shift;
15225
15226     my $result = '';
15227     my @args = @$args;
15228     #print STDERR "DO_XREF: $macro\n";
15229     my $j = 0;
15230     for ($j = 0; $j <= $#$args; $j++)
15231     {
15232          $args[$j] = normalise_space($args[$j]);
15233     #     print STDERR " ($j)$args[$j]\n";
15234     }
15235     $args[0] = '' if (!defined($args[0]));
15236     my $node_texi = normalise_node($args[0]);
15237     # a ref to a node in an info manual
15238     if ($args[0] =~ s/^\(([^\)]+)\)\s*//)
15239     {
15240         if ($macro eq 'inforef')
15241         {
15242             $args[2] = $1 unless ($args[2]);
15243         }
15244         else
15245         {
15246             $args[3] = $1 unless ($args[3]);
15247         }
15248     }
15249     if (($macro ne 'inforef') and $args[3])
15250     {
15251         $node_texi = "($args[3])" . normalise_node($args[0]);
15252     }
15253
15254     if ($macro eq 'inforef')
15255     {
15256         if ((@args < 1) or ($args[0] eq ''))
15257         {
15258             echo_error ("Need a node name for \@$macro", $line_nr);
15259             return '';
15260         }
15261         if (@args > 3)
15262         {
15263             echo_warn ("Too much arguments for \@$macro", $line_nr);
15264         }
15265         $args[2] = '' if (!defined($args[2]));
15266         $args[1] = '' if (!defined($args[1]));
15267         $node_texi = "($args[2])$args[0]";
15268     }
15269     
15270     my $i;
15271     my $new_state = duplicate_state($state);
15272     $new_state->{'keep_texi'} = 0;
15273     $new_state->{'keep_nr'} = 0;
15274     for ($i = 0; $i < 5; $i++)
15275     {
15276         $args[$i] = substitute_line($args[$i], $new_state);
15277     }
15278     #print STDERR "(@args)\n";
15279     
15280     if (($macro eq 'inforef') or ($args[3] ne '') or ($args[4] ne ''))
15281     {# external ref
15282         if ($macro eq 'inforef')
15283         {
15284             $macro = 'xref';
15285             $args[3] = $args[2];
15286         }
15287         my $href = '';
15288         my $node_file = '';
15289         if ($args[3] ne '')
15290         {
15291             $href = do_external_href($node_texi);
15292             $node_file = "($args[3])$args[0]";
15293         }
15294         my $section = '';
15295         if ($args[4] ne '')
15296         {
15297             $section = $args[0];
15298             if ($args[2] ne '')
15299             {
15300                 $section = $args[2];
15301             }
15302         }
15303         $result = &$Texi2HTML::Config::external_ref($macro, $section, $args[4], $node_file, $href, $args[1]);
15304     }
15305     else
15306     {
15307         my $element = $nodes{$node_texi};
15308         if ($element and $element->{'seen'})
15309         {
15310             if ($element->{'reference_element'})
15311             {
15312                 $element = $element->{'reference_element'};
15313             }
15314             my $file = '';
15315             if (defined($state->{'element'}))
15316             {
15317                 $file = $state->{'element'}->{'file'};
15318             }
15319             else
15320             {
15321                 echo_warn ("\@$macro not in text (in anchor, node, section...)", $line_nr);
15322                 # if Texi2HTML::Config::SPLIT the file is '' which ensures 
15323                 # a href with the file name. if ! Texi2HTML::Config::SPLIT 
15324                 # the 2 file will be the same thus there won't be the file name
15325                 $file = $element->{'file'} unless ($Texi2HTML::Config::SPLIT);
15326             }
15327             #print STDERR "SUBHREF in ref to node `$node_texi': $_";
15328             my $href = href($element, $file);
15329             my $section = $args[2];
15330             $section = $args[1] if ($section eq '');
15331             my $name = $section;
15332             my $short_name = $section;
15333             if ($section eq '')
15334             {
15335                 # FIXME maybe one should use 'text' instead of 'text_nonumber'
15336                 # However the real fix would be to have an internal_ref call
15337                 # with more informations 
15338                 $name = $element->{'text_nonumber'};
15339                 $short_name = $args[0];
15340             }
15341             $result = &$Texi2HTML::Config::internal_ref ($macro, $href, $short_name, $name, $element->{'section'});
15342         }
15343         else
15344         {
15345            if (($node_texi eq '') or !$novalidate)
15346            {
15347                echo_error ("Undefined node `$node_texi' in \@$macro", $line_nr);
15348                my $text = '';
15349                for (my $i = 0; $i < @$args -1; $i++)
15350                {
15351                     $text .= $args->[$i] .',';
15352                }
15353                $text .= $args->[-1];
15354                $result = "\@$macro"."{${text}}";
15355            }
15356            else
15357            {
15358                $result = &$Texi2HTML::Config::external_ref($macro, '', '', $args[0], do_external_href($node_texi), $args[1]);
15359            }
15360         }
15361     }
15362     return $result;
15363 }
15364
15365 sub do_acronym_like($$$$$)
15366 {
15367     my $command = shift;
15368     my $args = shift;
15369     my $acronym_texi = shift @$args;
15370     my $explanation = shift @$args;
15371     my $style_stack = shift;
15372     my $state = shift;
15373     my $line_nr = shift;
15374
15375     my $explanation_lines;
15376     my $explanation_text;
15377     my $explanation_simple_format;
15378
15379     if (defined($explanation))
15380     {
15381         $explanation =~ s/^\s*//;
15382         $explanation =~ s/\s*$//;
15383         $explanation = undef if ($explanation eq '');
15384     }
15385     $acronym_texi =~ s/^\s*//;
15386     $acronym_texi =~ s/\s*$//;
15387     
15388     return '' if ($acronym_texi eq '');
15389     
15390     my $with_explanation = 0;
15391     my $normalized_text =  cross_manual_line(normalise_node($acronym_texi));
15392     if (defined($explanation))
15393     {
15394         $with_explanation = 1;
15395         $acronyms_like{$command}->{$normalized_text} = $explanation;
15396     }
15397     elsif (exists($acronyms_like{$command}->{$normalized_text}))
15398     {
15399         $explanation = $acronyms_like{$command}->{$normalized_text};
15400     }
15401
15402     if (defined($explanation))
15403     {
15404          @$explanation_lines = map {$_ = $_."\n"} split (/\n/, $explanation);
15405          my $text = '';
15406          foreach my $line(@$explanation_lines)
15407          {
15408               $line .= ' ' if (chomp ($line));
15409               $text .= $line
15410          }
15411          $text =~ s/ $//;
15412          my $simple_format_state = duplicate_state($state);
15413          $explanation_simple_format = simple_format($simple_format_state,$text);
15414          $explanation_text = substitute_line($text, duplicate_state($state));
15415     }
15416     return &$Texi2HTML::Config::acronym_like($command, $acronym_texi, substitute_line($acronym_texi, duplicate_state($state)), 
15417        $with_explanation, $explanation_lines, $explanation_text, $explanation_simple_format);
15418 }
15419
15420 sub do_caption_shortcaption($$$$$)
15421 {
15422     my $command = shift;
15423     my $args = shift;
15424     my $text = $args->[0];
15425     my $style_stack = shift;
15426     my $state = shift;
15427     my $line_nr = shift;
15428
15429     if (!exists($state->{'float'}))
15430     {
15431 #dump_stack(\"", [], $state);
15432          echo_error("\@$command outside of float", $line_nr);
15433          return '';
15434     }
15435     my $float = $state->{'float'};
15436     my @texi_lines = map {$_ = $_."\n"} split (/\n/, $text);
15437     $float->{"${command}_texi"} = \@texi_lines;
15438     return '';
15439 }
15440
15441 # function called when a @float is encountered. Don't do any output
15442 # but prepare $state->{'float'}
15443 sub do_float_line($$$$$)
15444 {
15445     my $command = shift;
15446     my $args = shift;
15447     my @args = @$args;
15448     my $style_texi = shift @args;
15449     my $label_texi = shift @args;
15450     my $style_stack = shift;
15451     my $state = shift;
15452     my $line_nr = shift;
15453
15454     $style_texi = undef if (defined($style_texi) and $style_texi=~/^\s*$/);
15455     $label_texi = undef if (defined($label_texi) and $label_texi=~/^\s*$/);
15456     if (defined($label_texi))
15457     { # the float is considered as a node as it may be a target for refs.
15458       # it was entered as a node in the pass_structure and the float
15459       # line was parsed at that time
15460          $state->{'float'} = $nodes{normalise_node($label_texi)};
15461          #print STDERR "float: $state->{'float'}, $state->{'float'}->{'texi'}\n";
15462     }
15463     else 
15464     { # a float without label. It can't be the target for refs.
15465          $state->{'float'} = { 'float' => 1 };
15466          if (defined($style_texi))
15467          {
15468               $state->{'float'}->{'style_texi'} = normalise_space($style_texi);
15469               $state->{'float'}->{'style_id'} = 
15470                   cross_manual_line($state->{'float'}->{'style_texi'});
15471               $state->{'float'}->{'style'} = substitute_line($style_texi);
15472          }
15473          #print STDERR "float: (no label) $state->{'float'}\n";
15474     }
15475     return '';
15476 }
15477
15478 sub do_quotation_line($$$$$)
15479 {
15480     my $command = shift;
15481     my $args = shift;
15482     my @args = @$args;
15483     my $text_texi = shift @args;
15484     my $style_stack = shift;
15485     my $state = shift;
15486     my $line_nr = shift;
15487     my $text;
15488
15489     $text_texi = undef if (defined($text_texi) and $text_texi=~/^\s*$/);
15490     if (defined($text_texi))
15491     {
15492          $text = substitute_line($text_texi, duplicate_state($state));
15493          $text =~ s/\s*$//;
15494     }
15495     my $quotation_args = { 'text' => $text, 'text_texi' => $text_texi };
15496     push @{$state->{'quotation_stack'}}, $quotation_args;
15497     $state->{'prepend_text'} = &$Texi2HTML::Config::quotation_prepend_text($text_texi);
15498     return '';
15499 }
15500
15501 sub do_def_line($$$$$)
15502 {
15503     my $command = shift;
15504     my $args = shift;
15505     my @args = @$args;
15506     my $arguments = shift @args;
15507     my $style_stack = shift;
15508     my $state = shift;
15509     my $line_nr = shift;
15510
15511     $state->{'deff_line'}->{'arguments'} = $arguments;
15512     return '';
15513 }
15514
15515 sub do_footnote($$$$)
15516 {
15517     my $command = shift;
15518     my $args = shift;
15519     my $text = $args->[0];
15520     my $style_stack = shift;
15521     my $state = shift;
15522     my $line_nr = shift;
15523
15524     $text .= "\n";
15525     $foot_num++;
15526     $relative_foot_num++;
15527     my $docid  = "DOCF$foot_num";
15528     my $footid = "FOOT$foot_num";
15529     my $from_file = '';
15530     if ($state->{'element'} and $Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SEPARATED_FOOTNOTES)
15531     { 
15532         $from_file = $state->{'element'}->{'file'};
15533     }
15534     my %state;
15535     initialise_state(\%state); 
15536     if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
15537     {
15538         $state{'element'} = $footnote_element;
15539     }
15540     else
15541     {
15542         $state{'element'} = $state->{'element'};
15543     }
15544     my $file = '';
15545     $file = $docu_foot if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SEPARATED_FOOTNOTES);
15546     
15547     # FIXME use split_lines ? It seems to work like it is now ?
15548     my @lines = substitute_text(\%state, map {$_ = $_."\n"} split (/\n/, $text));
15549     my ($foot_lines, $foot_label) = &$Texi2HTML::Config::foot_line_and_ref ($foot_num,
15550          $relative_foot_num, $footid, $docid, $from_file, $file, \@lines, $state);
15551     push(@foot_lines, @{$foot_lines});
15552     return $foot_label;
15553 }
15554
15555 sub do_image($$$$)
15556 {
15557     # replace images
15558     my $command = shift;
15559     my $args = shift;
15560     my $text = $args->[0];
15561     my $style_stack = shift;
15562     my $state = shift;
15563     my $line_nr = shift;
15564     $text =~ s/\s+/ /gos; # remove useless spaces and newlines
15565     my @args = split (/\s*,\s*/, $text);
15566     my $base = $args[0];
15567     if ($base eq '')
15568     {
15569          echo_error ("no file argument for \@image", $line_nr);
15570          #warn "$ERROR no file argument for \@image\n";
15571          return '';
15572     }
15573     $args[4] = '' if (!defined($args[4]));
15574     $args[3] = '' if (!defined($args[3]));
15575     my $image;
15576     my $file_name;
15577     my @file_names = &$Texi2HTML::Config::image_files($base,$args[4]);
15578 #    $image = locate_include_file("$base.$args[4]") if ($args[4] ne '');
15579     foreach my $file (@file_names)
15580     {
15581          if ($image = locate_include_file($file))
15582          {
15583               $file_name = $file;
15584               last;
15585          }
15586     }
15587     $image = '' if (!defined($image));
15588     
15589     my $alt; 
15590     if ($args[3] =~ /\S/)
15591     {
15592         # makeinfo don't do that. Maybe it should be remove_texi or
15593         # simple_format... The raw alt is also given in argument
15594         $alt = do_text($args[3]);
15595         $alt = $alt if ($alt =~ /\S/);
15596     }
15597     return &$Texi2HTML::Config::image($path_to_working_dir . $image, $base, 
15598         $state->{'preformatted'}, $file_name, $alt, $args[1], $args[2], 
15599         $args[3], $args[4], $path_to_working_dir, $image);
15600 }
15601
15602 sub duplicate_state($)
15603 {
15604     my $state = shift;
15605     my $new_state = { 'element' => $state->{'element'}, 
15606            'preformatted' => $state->{'preformatted'}, 
15607            'code_style' => $state->{'code_style'}, 
15608            'keep_texi' => $state->{'keep_texi'}, 
15609            'keep_nr' => $state->{'keep_nr'}, 
15610            'preformatted_stack' => $state->{'preformatted_stack'},
15611            'multiple_pass' => $state->{'multiple_pass'},
15612 # this is needed for preformatted
15613            'command_stack' => [ @{$state->{'command_stack'}}  ],
15614            'preformatted_context' => 
15615                 {'stack_at_beginning' => [ @{$state->{'command_stack'}}  ] }
15616     };
15617     return $new_state;
15618 }
15619
15620 sub expand_macro($$$$$)
15621 {
15622     my $name = shift;
15623     my $args = shift;
15624     my $end_line = shift;
15625     my $line_nr = shift;
15626     my $state = shift;
15627
15628     # we dont expand macros when in ignored environment.
15629     return if ($state->{'ignored'});
15630     my $index = 0;
15631     foreach my $arg (@$args)
15632     { # expand @macros in arguments. It is complicated because we must be
15633       # carefull not to expand macros in @ignore section or the like, and 
15634       # still keep every single piece of text (including the @ignore macros).
15635         $args->[$index] = substitute_text({'texi' => 1, 'arg_expansion' => 1}, split_lines($arg));
15636         $index++;
15637     }
15638     # retrieve the macro definition
15639     my $macrobody = $macros->{$name}->{'body'};
15640     my $formal_args = $macros->{$name}->{'args'};
15641     my $args_index =  $macros->{$name}->{'args_index'};
15642     my $i;
15643     
15644     die "Bug end_line not defined" if (!defined($end_line));
15645     
15646     for ($i=0; $i<=$#$formal_args; $i++)
15647     {
15648         $args->[$i] = "" unless (defined($args->[$i]));
15649         print STDERR "# arg($i): $args->[$i]\n" if ($T2H_DEBUG & $DEBUG_MACROS);
15650     }
15651     echo_error ("too much arguments for macro $name", $line_nr) if (defined($args->[$i + 1]));
15652     my $result = '';
15653     while ($macrobody)
15654     {
15655         if ($macrobody =~ s/^([^\\]*)\\//o)
15656         {
15657             $result .= $1 if defined($1);
15658             if ($macrobody =~ s/^\\//)
15659             {
15660                 $result .= '\\';
15661             }
15662             elsif ($macrobody =~ s/^(\@end\sr?macro)$// or $macrobody =~ s/^(\@end\sr?macro\s)// or $macrobody =~ s/^(\@r?macro\s+\w+\s*.*)//)
15663             { # \ protect @end macro
15664                 $result .= $1;
15665             }
15666             elsif ($macrobody =~ s/^([^\\]*)\\//)
15667             {
15668                my $arg = $1;
15669                if (defined($args_index->{$arg}))
15670                {
15671                    $result .= $args->[$args_index->{$arg}];
15672                }
15673                else
15674                {
15675                    warn "$ERROR \\ not followed by \\ or an arg but by $arg in macro\n";
15676                    $result .= '\\' . $arg;
15677                }
15678             }
15679             next;
15680         }
15681         $result .= $macrobody;
15682         last;
15683     }
15684     my @result = split(/^/m, $result);
15685     # Add the result of the macro expansion back to the input_spool.
15686     # Set the macro name if in the outer macro
15687     if ($state->{'arg_expansion'})
15688     {
15689         unshift @{$state->{'spool'}}, (@result, $end_line);
15690     }
15691     else
15692     {
15693         unshift @{$input_spool->{'spool'}}, (@result, $end_line);
15694         $input_spool->{'macro'} = $name if ($input_spool->{'macro'} eq '');
15695     }
15696     if ($T2H_DEBUG & $DEBUG_MACROS)
15697     {
15698         print STDERR "# macro expansion result:\n";
15699         #print STDERR "$first_line";
15700         foreach my $line (@result)
15701         {
15702             print STDERR "$line";
15703         }
15704         print STDERR "# macro expansion result end\n";
15705     }
15706 }
15707
15708 sub do_index_summary_file($)
15709 {
15710     my $name = shift;
15711     my ($pages, $entries) = get_index($name);
15712     &$Texi2HTML::Config::index_summary_file_begin ($name, $printed_indices{$name});
15713     print STDERR "# writing $name index summary\n" if $T2H_VERBOSE;
15714
15715     foreach my $key (sort keys %$entries)
15716     {
15717         my $entry = $entries->{$key};
15718         my $indexed_element = $entry->{'element'};
15719         my $entry_element = $indexed_element;
15720         # notice that we use the section associated with a node even when 
15721         # there is no with_section, i.e. when there is another node preceding
15722         # the sectionning command.
15723         # However when it is the Top node, we use the node instead.
15724         # (for the Top node, 'top_as_section' is true)
15725         $entry_element = $entry_element->{'section_ref'} if ($entry_element->{'section_ref'} and !$entry_element->{'top_as_section'});
15726         my $origin_href = $entry->{'file'};
15727    #print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n";
15728         if ($entry->{'label'})
15729         { 
15730              $origin_href .= '#' . $entry->{'label'};
15731         }
15732         else
15733         {
15734             # If the $indexed_element element and the $index entry are on 
15735             # the same
15736             # file the real element is prefered. If they aren't on the same file
15737             # the entry id is choosed as it means that the real element
15738             # and the index entry are separated by a printindex.
15739             print STDERR "id undef ($entry) entry: $entry->{'entry'}, label: $indexed_element->{'text'}\n"  if (!defined($entry->{'id'}));
15740             if ($entry->{'file'} eq $indexed_element->{'file'})
15741             {
15742                 $origin_href .= '#' . $indexed_element->{'id'};
15743             }
15744             else
15745             {
15746                 $origin_href .= '#' . $entry->{'id'} ;
15747             }
15748         }
15749         &$Texi2HTML::Config::index_summary_file_entry ($name,
15750           $key, $origin_href, 
15751           substitute_line($entry->{'entry'}), $entry->{'entry'},
15752           href($entry_element, ''),
15753           $entry_element->{'text'},
15754           $printed_indices{$name});
15755     }
15756     &$Texi2HTML::Config::index_summary_file_end ($name, $printed_indices{$name});
15757 }
15758
15759 sub do_index_page($$;$)
15760 {
15761     my $index_elements = shift;
15762     my $nr = shift;
15763     my $page = shift;
15764     my $index_element = $index_elements->[$nr];
15765     my $summary = do_index_summary($index_element->{'element'}, $index_elements);
15766     my $entries = do_index_entries($index_element->{'element'}, $index_element->{'page'}, $index_element->{'name'});
15767     return $summary . $entries . $summary;
15768 }
15769
15770 sub do_index_summary($$)
15771 {
15772     my $element = shift;
15773     my $index_elements = shift;
15774
15775     my @letters;
15776     my @symbols;
15777
15778     for my $index_element_item (@$index_elements)
15779     {
15780         my $index_element = $index_element_item->{'element'};
15781         my $file = '';
15782         $file .= $index_element->{'file'} if ($index_element->{'file'} ne $element->{'file'});
15783         my $index = 0;
15784         for my $letter (@{$index_element_item->{'page'}->{'letters'}})
15785         {
15786             if ($letter =~ /^[A-Za-z]/)
15787             {
15788                 push @letters, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index");
15789             }
15790             else
15791             {
15792                 push @symbols, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index");
15793             }
15794             $index++;
15795         }
15796     }
15797     return &$Texi2HTML::Config::index_summary(\@letters, \@symbols);
15798 }
15799
15800 sub do_index_entries($$$)
15801 {
15802     my $element = shift;
15803     my $page = shift;
15804     my $name = shift;
15805  
15806     my $letters = '';
15807     my $index = 0;
15808     foreach my $letter (@{$page->{'letters'}})
15809     {
15810        my $entries = '';
15811        foreach my $entry (@{$page->{'entries_by_letter'}->{$letter}})
15812        {
15813            my $indexed_element = $entry->{'element'};
15814            my $entry_element = $indexed_element;
15815            # notice that we use the section associated with a node even when 
15816            # there is no with_section, i.e. when there is another node preceding
15817            # the sectionning command.
15818            # However when it is the Top node, we use the node instead.
15819            # (for the Top node, 'top_as_section' is true)
15820            $entry_element = $entry_element->{'section_ref'} if ($entry_element->{'section_ref'} and !$entry_element->{'top_as_section'});
15821            my $origin_href = '';
15822            $origin_href = $entry->{'file'} if ($Texi2HTML::Config::SPLIT and $entry->{'file'} ne $element->{'file'});
15823            #print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n";
15824            if ($entry->{'label'})
15825            { 
15826                $origin_href .= '#' . $entry->{'label'};
15827            }
15828            else
15829            {
15830                # If the $indexed_element element and the $index entry are 
15831                # in the same file the indexed_element is prefered. If they 
15832                # aren't in the same file the entry id is choosed as it means 
15833                # that the indexed_element element and the index entry are 
15834                # separated by a printindex.
15835                print STDERR "id undef ($entry) entry: $entry->{'entry'}, label: $indexed_element->{'text'}\n"  if (!defined($entry->{'id'}));
15836                if ($entry->{'file'} eq $indexed_element->{'file'})
15837                {
15838                    $origin_href .= '#' . $indexed_element->{'id'};
15839                }
15840                else
15841                {
15842                    $origin_href .= '#' . $entry->{'id'} ;
15843                }
15844            }
15845            #print STDERR "SUBHREF in index entry `$entry->{'entry'}' for `$entry_element->{'texi'}'\n";
15846            $entries .= &$Texi2HTML::Config::index_entry ($origin_href, 
15847                      substitute_line($entry->{'entry'}),
15848                      href($entry_element, $element->{'file'}),
15849                      $entry_element->{'text'});
15850         }
15851         $letters .= &$Texi2HTML::Config::index_letter ($letter, "$element->{'id'}" . "_$index", $entries);
15852         $index++;
15853     }
15854     return &$Texi2HTML::Config::print_index($letters, $name);
15855 }
15856
15857 # remove texi commands, replacing with what seems adequate. see simple_map_texi
15858 # and texi_map.
15859 # Doesn't protect html
15860 sub remove_texi(@)
15861 {
15862     return substitute_text ({ 'remove_texi' => 1}, @_);
15863 }
15864
15865 # Same as remove texi but protect text and use special maps for @-commands
15866 sub simple_format($@)
15867 {
15868     my $state = shift;
15869     $state = {} if (!defined($state));
15870     $state->{'remove_texi'} = 1;
15871     $state->{'simple_format'} = 1;
15872     # WARNING currently it is only used for lines. It may change in the future.
15873     $state->{'no_paragraph'} = 1;
15874     $::simple_map_texi_ref = \%Texi2HTML::Config::simple_format_simple_map_texi;
15875     $::style_map_texi_ref = \%Texi2HTML::Config::simple_format_style_map_texi;
15876     $::texi_map_ref = \%Texi2HTML::Config::simple_format_texi_map;
15877     my $text = substitute_text($state, @_);
15878     $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi;
15879     $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi;
15880     $::texi_map_ref = \%Texi2HTML::Config::texi_map;
15881     return $text;
15882 }
15883
15884 sub enter_table_index_entry($$$$)
15885 {
15886     my $text = shift;
15887     my $stack = shift;
15888     my $state = shift;
15889     my $line_nr = shift;
15890     if ($state->{'item'} and ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/))
15891     {
15892          my $index = $1;
15893          my $macro = $state->{'item'};
15894          delete $state->{'item'};
15895          close_stack($text, $stack, $state, $line_nr, undef, 'index_item');
15896          my $item = pop @$stack;
15897          my $element = $state->{'element'};
15898          $element = $state->{'node_ref'} unless ($element);
15899          enter_index_entry($index, $line_nr, $item->{'text'}, 
15900             $state->{'place'}, $element, 0, $state->{'table_stack'}->[-1]);
15901          add_prev($text, $stack, "\@$macro" . $item->{'text'});
15902     }
15903 }
15904
15905 sub scan_texi($$$$;$)
15906 {
15907     my $line = shift;
15908     my $text = shift;
15909     my $stack = shift;
15910     my $state = shift;
15911     my $line_nr = shift;
15912     
15913     die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
15914     local $_ = $line;
15915
15916     while(1)
15917     {
15918         # scan_texi
15919         #print STDERR "WHILE:$_";
15920         #print STDERR "ARG_EXPANSION: $state->{'arg_expansion'}\n" if ($state->{'arg_expansion'});
15921         #dump_stack($text, $stack, $state);
15922         #print STDERR "ifvalue_inside $state->{'ifvalue_inside'}\n";
15923
15924
15925         # first we handle special cases:
15926         # macro definition: $state->{'macro_inside'}
15927         # macro arguments:  $state->{'macro_name'}
15928         # raw format:       $state->{'raw'}
15929         # @verb:            $state->{'verb'}
15930         # ignored:          $state->{'ignored'}
15931         # and then the remaining text/macros.
15932
15933         # in macro definition
15934         if ($state->{'macro_inside'})
15935         {
15936             if (s/^([^\\\@]*\\)//)
15937             {# protected character or @end macro
15938                  $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
15939                  if (s/^\\//)
15940                  {
15941                       $state->{'macro'}->{'body'} .= '\\' unless ($state->{'ignored'});
15942                       next;
15943                  }
15944                  # I believe it is correct, although makeinfo don't do that.
15945                  elsif (s/^(\@end\sr?macro)$//o or s/^(\@end\sr?macro\s)//o
15946                       or s/^(\@r?macro\s+\w+\s*.*)//o) 
15947                  {
15948                       $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
15949                       next;
15950                  }
15951             }
15952             #if (s/^(.*?)\@end\sr?macro$//o or s/^(.*?)\@end\sr?macro\s+//o)
15953             if (s/^(\@end\sr?macro)$//o or s/^(\@end\sr?macro\s+)//o)
15954             {
15955                  $state->{'macro_inside'}--;
15956                  next if ($state->{'ignored'});
15957                  if ($state->{'macro_inside'})
15958                  {
15959                      $state->{'macro'}->{'body'} .= $1;
15960                      next;
15961                  }
15962                  chomp $state->{'macro'}->{'body'};
15963                  print STDERR "# end macro def. Body:\n$state->{'macro'}->{'body'}"
15964                      if ($T2H_DEBUG & $DEBUG_MACROS);
15965                  delete $state->{'macro'};
15966                  return if (/^\s*$/);
15967                  next;
15968             }
15969             elsif(/^(\@r?macro\s+\w+\s*.*)/)
15970             {
15971                  $state->{'macro'}->{'body'} .= $_ unless ($state->{'ignored'});
15972                  $state->{'macro_inside'}++;
15973                  return;
15974             }
15975             elsif (s/^\@(.)//)
15976             {
15977                  $state->{'macro'}->{'body'} .= '@' . $1 unless ($state->{'ignored'});
15978                  next;
15979             }
15980             elsif (s/^\@//)
15981             {
15982                  $state->{'macro'}->{'body'} .= '@' unless ($state->{'ignored'});
15983                  next;
15984             }
15985             else
15986             {
15987                  s/([^\@\\]*)//;
15988                  if ($state->{'ignored'})
15989                  {
15990                      return if (/^$/);
15991                      next;
15992                  }
15993                  $state->{'macro'}->{'body'} .= $1 if (defined($1));
15994                  if (/^$/)
15995                  {
15996                       $state->{'macro'}->{'body'} .= $_;
15997                       return;
15998                  }
15999                  next;
16000             }
16001         }
16002         # in macro arguments parsing/expansion. Here \ { } and , if this is a
16003         # multi args macro have a signification, the remaining is passed 
16004         # unmodified
16005         if (defined($state->{'macro_name'}))
16006         {
16007             my $special_chars = quotemeta ('\{}');
16008             my $multi_args = 0;
16009             my $formal_args = $macros->{$state->{'macro_name'}}->{'args'};
16010             $multi_args = 1 if ($#$formal_args >= 1);
16011             $special_chars .= quotemeta(',') if ($multi_args);
16012             if ($state->{'macro_args'}->[-1] eq '')
16013             {# remove space at the very beginning
16014                 s/^\s*//o;
16015             }
16016             if (s/^([^$special_chars]*)([$special_chars])//)
16017             {
16018                 $state->{'macro_args'}->[-1] .= $1 if defined($1);
16019                 # \ protects any character in macro arguments
16020                 if ($2 eq '\\')
16021                 {
16022                     print STDERR "# macro call: protected char\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16023                     if (s/^(.)//)
16024                     {
16025                         $state->{'macro_args'}->[-1] .= $1;
16026                     }
16027                     else
16028                     {
16029                         $state->{'macro_args'}->[-1] .= '\\';
16030                     }
16031                 }
16032                 elsif ($2 eq ',')
16033                 { # in texinfo 4.8.90 a comma in braces is protected
16034                     if ($state->{'macro_depth'} > 1)
16035                     {
16036                         $state->{'macro_args'}->[-1] .= ',';
16037                     }
16038                     else
16039                     { # separate args
16040                         print STDERR "# macro call: new arg\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16041                         s/^\s*//o;
16042                         push @{$state->{'macro_args'}}, '';
16043                     }
16044                 }
16045                 elsif ($2 eq '}')
16046                 { # balanced } ends the macro call, otherwise it is in the arg
16047                     $state->{'macro_depth'}--;
16048                     if ($state->{'macro_depth'} == 0)
16049                     { 
16050                         print STDERR "# expanding macro $state->{'macro_name'}\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16051                         $_ = expand_macro($state->{'macro_name'}, $state->{'macro_args'}, $_, $line_nr, $state);
16052                         delete $state->{'macro_name'};
16053                         delete $state->{'macro_depth'};
16054                         delete $state->{'macro_args'};
16055                         return;
16056                     }
16057                     else
16058                     {
16059                         print STDERR "# macro call: closing }\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16060                         add_text('}', \$state->{'macro_args'}->[-1]);
16061                     }
16062                 }
16063                 elsif ($2 eq '{')
16064                 {
16065                     print STDERR "# macro call: opening {\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16066                     $state->{'macro_depth'}++;
16067                     add_text('{', \$state->{'macro_args'}->[-1]);
16068                 }
16069                 next;
16070             }
16071             print STDERR "# macro call: end of line\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16072             $state->{'macro_args'}->[-1] .= $_;
16073             return;
16074         }
16075         # in a raw format, verbatim, tex or html
16076         if ($state->{'raw'}) 
16077         {
16078             my $tag = $state->{'raw'};
16079
16080             # debugging
16081             if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
16082             {
16083                 print STDERR "Bug: raw or special: $tag but not on top of stack\n";
16084                 print STDERR "line: $_";
16085                 dump_stack($text, $stack, $state);
16086                 exit 1;
16087             }
16088             
16089             if (s/^(.*?)(\@end\s$tag)$// or s/^(.*?)(\@end\s$tag\s)//)
16090             {# we add it even if 'ignored', it'll be discarded when there is
16091              # the @end
16092                 add_prev ($text, $stack, $1);
16093                 my $end = $2;
16094                 my $style = pop @$stack;
16095                 if ($style->{'text'} !~ /^\s*$/ or $state->{'arg_expansion'})
16096                 # FIXME if 'arg_expansion' and also 'ignored' is true, 
16097                 # theoretically we should keep
16098                 # what is in the raw format however
16099                 # it will be removed later anyway 
16100                 {# ARG_EXPANSION
16101                     my $after_macro = '';
16102                     $after_macro = ' ' unless (/^\s*$/);
16103                     add_prev ($text, $stack, $style->{'text'} . $end . $after_macro) unless ($state->{'ignored'});
16104                     delete $state->{'raw'};
16105                 }
16106                 next;
16107             }
16108             else
16109             {# we add it even if 'ignored', it'll be discarded when there is 
16110              # the @end
16111                  add_prev ($text, $stack, $_);
16112                  last;
16113             }
16114         }
16115
16116         # in a @verb{ .. } macro
16117         if (defined($state->{'verb'}))
16118         {
16119             #dump_stack($text, $stack, $state);
16120             my $char = quotemeta($state->{'verb'});
16121             #print STDERR "VERB $char\n";
16122             if (s/^(.*?)$char\}/\}/)
16123             {# we add it even if 'ignored', it'll be discarded when closing
16124                  add_prev($text, $stack, $1 . $state->{'verb'});
16125                  $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
16126                  delete $state->{'verb'};
16127                  next;
16128             }
16129             else
16130             {# we add it even if 'ignored', it'll be discarded when closing
16131                  add_prev($text, $stack, $_);
16132                  last;
16133             }
16134         }
16135         # In ignored region
16136         if ($state->{'ignored'})
16137         {
16138             #print STDERR "IGNORED(ifvalue($state->{'ifvalue_inside'})): $state->{'ignored'}\n";
16139             if (/^.*?\@end(\s+)([a-zA-Z]\w+)/)
16140             {
16141                 if ($2 eq $state->{'ignored'})
16142                 {
16143                     s/^(.*?\@end)(\s+)([a-zA-Z]\w+)//; 
16144                     my $end_ignore = $1.$2.$3;
16145                     if (($state->{'ifvalue_inside'}) and $state->{'ignored'} eq $state->{'ifvalue'})
16146                     {
16147                          if ($state->{'ifvalue_inside'} == 1)
16148                          {# closing still opened @-commands with braces
16149                              pop (@$stack) while (@$stack and $stack->[-1]->{'style'} ne 'ifvalue')
16150                          }
16151                          pop (@$stack);
16152                          $state->{'ifvalue_inside'}--;
16153                     }
16154                     $state->{'ignored'} = undef;
16155                     delete $state->{'ignored'};
16156                     # We are stil in the ignored ifset or ifclear section
16157                     $state->{'ignored'} = $state->{'ifvalue'} if ($state->{'ifvalue_inside'});
16158                     #dump_stack($text, $stack, $state);
16159                     # MACRO_ARG => keep ignored text
16160                     if ($state->{'arg_expansion'})
16161                     {# this may not be very usefull as it'll be remove later
16162                         add_prev ($text, $stack, $end_ignore);
16163                         next;
16164                     }
16165                     return if /^\s*$/o;
16166                     next;
16167                 }
16168             }
16169             add_prev ($text, $stack, $_) if ($state->{'arg_expansion'});
16170             # we could theoretically continue for ignored commands other
16171             # than ifset or ifclear, however it isn't usefull.
16172             return unless ($state->{'ifvalue_inside'} and ($state->{'ignored'} eq $state->{'ifvalue'}));
16173         }
16174
16175         
16176         # an @end tag
16177         # macro_regexp
16178         if (s/^([^{}@]*)\@end(\s+)([a-zA-Z][\w-]*)//)
16179         {
16180             my $leading_text = $1;
16181             my $space = $2;
16182             my $end_tag = $3;
16183             # when 'ignored' we don't open environments that aren't associated
16184             # with ignored regions, so we don't need to close them.
16185             next if ($state->{'ignored'});# ARG_EXPANSION
16186             add_prev($text, $stack, $leading_text);
16187             if (defined($state->{'text_macro_stack'})
16188                and @{$state->{'text_macro_stack'}}
16189                and ($end_tag eq $state->{'text_macro_stack'}->[-1]))
16190             {
16191                 pop @{$state->{'text_macro_stack'}};
16192                 # we keep menu and titlepage for the following pass
16193                 if ((($end_tag eq 'menu') and $text_macros{'menu'}) or ($region_lines{$end_tag}) or $state->{'arg_expansion'})
16194                 {
16195                      add_prev($text, $stack, "\@end${space}$end_tag");
16196                 }
16197                 else
16198                 {
16199                     #print STDERR "End $end_tag\n";
16200                     #dump_stack($text, $stack, $state);
16201                     return if (/^\s*$/);
16202                 }
16203             }
16204             elsif ($text_macros{$end_tag})
16205             {
16206                 echo_error ("\@end $end_tag without corresponding element", $line_nr);
16207             }
16208             else
16209             {# ARG_EXPANSION
16210                 add_prev($text, $stack, "\@end${space}$end_tag");
16211             }
16212             next;
16213         }
16214         # macro_regexp
16215         elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
16216         {# ARG_EXPANSION
16217             add_prev($text, $stack, $1) unless $state->{'ignored'};
16218             my $macro = $2;
16219             #print STDERR "MACRO $macro\n";
16220             # handle skipped @-commands
16221             $state->{'bye'} = 1 if ($macro eq 'bye' and !$state->{'ignored'} and !$state->{'arg_expansion'});
16222             if (defined($Texi2HTML::Config::misc_command{$macro}) and 
16223                  !$Texi2HTML::Config::misc_command{$macro}->{'texi'}
16224                  and $macro ne 'documentencoding')
16225             {# ARG_EXPANSION
16226                  my ($line, $args);
16227                  ($_, $line, $args) = preserve_command($_, $macro);
16228                  add_prev ($text, $stack, "\@$macro" . $line) unless $state->{'ignored'}; 
16229             }
16230             # pertusus: it seems that value substitution are performed after
16231             # macro argument expansions: if we have 
16232             # @set comma ,
16233             # and a call to a macro @macro {arg1 @value{comma} arg2}
16234             # the macro arg is arg1 , arg2 and the comma don't separate
16235             # args. Likewise it seems that the @value are not expanded
16236             # in macro definitions
16237
16238             # track variables
16239             elsif($macro eq 'set' or $macro eq 'clear')
16240             {
16241                 if ($macro eq 'set')
16242                 {
16243                     if (s/^(\s+)($VARRE)(\s+)(.*)$//o)
16244                     {
16245                         if ($state->{'arg_expansion'})
16246                         {
16247                             my $line = "\@$macro" . $1.$2.$3;
16248                             $line .= $4 if (defined($4));
16249                             add_prev($text, $stack, $line); 
16250                             next;
16251                         }
16252                         next if $state->{'ignored'};
16253                         $value{$2} = $4;
16254                     }
16255                     else
16256                     {
16257                         echo_warn ("Missing argument for \@$macro", $line_nr);
16258                     }
16259                 }
16260                 elsif ($macro eq 'clear')
16261                 {
16262                     if (s/^(\s+)($VARRE)//o)
16263                     {
16264                         if ($state->{'arg_expansion'})
16265                         {
16266                             add_prev($text, $stack, "\@$macro" . $1 . $2);
16267                             next; 
16268                         }
16269                         next if $state->{'ignored'};
16270                         delete $value{$2};
16271                     }
16272                     else
16273                     {
16274                         echo_warn ("Missing argument for \@$macro", $line_nr);
16275                     }
16276                 }
16277                 return if (/^\s*$/);
16278             }
16279             elsif ($macro =~ /^r?macro$/)
16280             { #FIXME what to do if 'arg_expansion' is true (ie within another
16281               # macro call arguments?
16282                 if (/^\s+(\w[\w-]*)\s*(.*)/)
16283                 {
16284                     my $name = $1;
16285                     unless ($state->{'ignored'})
16286                     {
16287                          if (exists($macros->{$name}))
16288                          {
16289                              echo_warn ("macro `$name' allready defined " . 
16290                                  format_line_number($macros->{$name}->{'line_nr'}) . " redefined", $line_nr);
16291                          }
16292                          
16293                     }
16294                     $state->{'macro_inside'} = 1;
16295                     next if ($state->{'ignored'});
16296                     # if in 'arg_expansion' we really want to take into account
16297                     # that we are in an ignored ifclear.
16298                     my @args = ();
16299                     @args = split(/\s*,\s*/ , $1)
16300                        if ($2 =~ /^\s*{\s*(.*?)\s*}\s*/);
16301                     # keep the context information of the definition
16302                     $macros->{$name}->{'line_nr'} = { 'file_name' => $line_nr->{'file_name'}, 
16303                          'line_nr' => $line_nr->{'line_nr'}, 'macro' => $line_nr->{'macro'} } if (defined($line_nr));
16304                     $macros->{$name}->{'args'} = \@args;
16305                     my $arg_index = 0;
16306                     my $debug_msg = '';
16307                     foreach my $arg (@args)
16308                     { # when expanding macros, the argument index is retrieved
16309                       # with args_index
16310                         $macros->{$name}->{'args_index'}->{$arg} = $arg_index;
16311                         $debug_msg .= "$arg($arg_index) ";
16312                         $arg_index++;
16313                     }
16314                     $macros->{$name}->{'body'} = '';
16315                     $state->{'macro'} = $macros->{$name};
16316                     print STDERR "# macro def $name: $debug_msg\n"
16317                          if ($T2H_DEBUG & $DEBUG_MACROS);
16318                 }
16319                 else
16320                 {# it means we have a macro without a name
16321                     echo_error ("Macro definition without macro name $_", $line_nr)
16322                         unless ($state->{'ignored'});
16323                 }
16324                 return;
16325             }
16326             elsif (defined($text_macros{$macro}))
16327             {
16328                 my $tag;
16329                 ($_, $tag) = do_text_macro($macro, $_, $state, $stack, $line_nr); 
16330                 # if it is a raw formatting command or a menu command
16331                 # we must keep it for later, unless we are in an 'ignored'.
16332                 # if in 'arg_expansion' we keep everything.
16333                 my $macro_kept;
16334                 if ((($state->{'raw'} or (($macro eq 'menu') and $text_macros{'menu'}) or (exists($region_lines{$macro}))) and !$state->{'ignored'}) or $state->{'arg_expansion'})
16335                 {
16336                     add_prev($text, $stack, $tag);
16337                     $macro_kept = 1;
16338                 }
16339                 #dump_stack ($text, $stack, $state);
16340                 next if $macro_kept;
16341                 return if (/^\s*$/);
16342             }
16343             elsif ($macro eq 'documentencoding')
16344             {
16345                 my $spaces = '';
16346                 my $encoding = '';
16347                 if (s/(\s+)([0-9\w\-]+)//)
16348                 {
16349                     $spaces = $1;
16350                     $encoding = $2;
16351                     next if ($state->{'ignored'});
16352                     if (!$state->{'arg_expansion'} and !$state->{'ignored'})
16353                     {
16354                         $Texi2HTML::Config::DOCUMENT_ENCODING = $encoding;
16355                         my $from_encoding = encoding_alias($encoding);
16356                         $Texi2HTML::Config::IN_ENCODING = $from_encoding if
16357                             defined($from_encoding);
16358                         if (defined($from_encoding) and $Texi2HTML::Config::USE_UNICODE)
16359                         {
16360                             foreach my $file (@fhs)
16361                             {
16362                                 binmode($file->{'fh'}, ":encoding($from_encoding)");
16363                             }
16364                         }
16365                     }
16366                 }# ARG_EXPANSION
16367                 add_prev($text, $stack, "\@$macro" . $spaces . $encoding) unless ($state->{'ignored'});
16368             }
16369             elsif ($macro eq 'definfoenclose')
16370             {
16371                 # FIXME if 'ignored' or 'arg_expansion' maybe we could parse
16372                 # the args anyway and don't take away the whole line?
16373
16374                 # as in the makeinfo doc 'definfoenclose' may override
16375                 # texinfo @-commands like @i. It is what we do here.
16376                 if ($state->{'arg_expansion'})
16377                 {
16378                     add_prev($text, $stack, "\@$macro" . $_);
16379                     return;
16380                 }
16381                 return if ($state->{'ignored'});
16382                 if (s/^\s+([a-z]+)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//)
16383                 {
16384                     $info_enclose{$1} = [ $2, $3 ];
16385                 }
16386                 else
16387                 {
16388                     echo_error("Bad \@$macro", $line_nr);
16389                 }
16390                 return if (/^\s*$/);
16391                 s/^\s*//;
16392             }
16393             elsif ($macro eq 'include')
16394             {
16395                 if ($state->{'arg_expansion'})
16396                 {
16397                     add_prev($text, $stack, "\@$macro" . $_);
16398                     return;
16399                 }
16400                 return if ($state->{'ignored'});
16401                 #if (s/^\s+([\/\w.+-]+)//o)
16402                 if (s/^(\s+)(.*)//o)
16403                 {
16404                     my $file_name = $2;
16405                     $file_name =~ s/\s*$//;
16406                     my $file = locate_include_file($file_name);
16407                     if (defined($file))
16408                     {
16409                         open_file($file, $line_nr);
16410                         print STDERR "# including $file\n" if $T2H_VERBOSE;
16411                     }
16412                     else
16413                     {
16414                         echo_error ("Can't find $file_name, skipping", $line_nr);
16415                     }
16416                 }
16417                 else
16418                 {
16419                     echo_error ("Bad include line: $_", $line_nr);
16420                     return;
16421                 } 
16422                 return;
16423             }
16424             elsif ($macro eq 'value')
16425             {
16426                 if (s/^{($VARRE)}//)
16427                 {
16428                     my $value = $1;
16429                     if ($state->{'arg_expansion'})
16430                     {
16431                         add_prev($text, $stack, "\@$macro" .'{'. $value .'}');
16432                         next;
16433                     }
16434                     next if ($state->{'ignored'});
16435                     my $expansion = "No value for $value";
16436                     $expansion = $value{$value} if (defined($value{$value}));
16437                     $_ = $expansion . $_;
16438                 }
16439                 else
16440                 {
16441                     if ($state->{'arg_expansion'})
16442                     {
16443                         add_prev($text, $stack, "\@$macro");
16444                         next;
16445                     }
16446                     next if ($state->{'ignored'});
16447                     echo_error ("bad \@value macro", $line_nr);
16448                 }
16449             }
16450             elsif ($macro eq 'unmacro')
16451             { #FIXME with 'arg_expansion' should it be passed unmodified ?
16452                 if ($state->{'ignored'})
16453                 {
16454                     s/^\s+(\w+)//;
16455                 }
16456                 else
16457                 {
16458                     delete $macros->{$1} if (s/^\s+(\w+)//);
16459                 }
16460                 return if (/^\s*$/);
16461                 s/^\s*//;
16462             }
16463             elsif (exists($macros->{$macro}))
16464             {# it must be before the handling of {, otherwise it is considered
16465              # to be regular texinfo @-command. Maybe it could be placed higher
16466              # if we want user defined macros to override texinfo @-commands
16467
16468              # in 'ignored' we parse macro defined args anyway as it removes 
16469              # some text, but we don't expand the macro
16470
16471                 my $ref = $macros->{$macro}->{'args'};
16472                 # we remove any space/new line before the argument
16473                 if (s/^\s*{\s*//)
16474                 { # the macro has args
16475                     $state->{'macro_args'} = [ "" ];
16476                     $state->{'macro_name'} = $macro;
16477                     $state->{'macro_depth'} = 1;
16478                 }
16479                 elsif (($#$ref >= 1) or ($#$ref <0))
16480                 { # no brace -> no arg
16481                     $_ = expand_macro ($macro, [], $_, $line_nr, $state);
16482                     return;
16483                 }
16484                 else
16485                 { # macro with one arg on the line
16486                     chomp $_;
16487                     $_ = expand_macro ($macro, [$_], "\n", $line_nr, $state);
16488                     return;
16489                 }
16490             }
16491             elsif ($macro eq ',')
16492             {# the @, causes problems when `,' separates things (in @node, @ref)
16493                 $_ = "\@m_cedilla" . $_;
16494             } # handling of @, must be done before handling of {
16495             elsif (s/^{//)
16496             {# we add nested commands in a stack. verb is also on the stack
16497              # but handled specifically.
16498              # we add it the comands even in 'ignored' as their result is 
16499              # discarded when the closing brace appear, or the ifset or 
16500              # iclear is closed.
16501                 if ($macro eq 'verb')
16502                 {
16503                     if (/^$/)
16504                     {
16505                         echo_error ("without associated character", $line_nr);
16506                         #warn "$ERROR verb at end of line";
16507                     }
16508                     else
16509                     {
16510                         s/^(.)//;
16511                         $state->{'verb'} = $1;
16512                     }
16513                 }
16514                 push (@$stack, { 'style' => $macro, 'text' => '' });
16515             }
16516             else
16517             {
16518                 add_prev($text, $stack, "\@$macro") unless($state->{'ignored'});
16519             }
16520             next;
16521         }
16522         #elsif(s/^([^{}@]*)\@(.)//o)
16523         elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
16524         {# ARG_EXPANSION
16525             # No need to warn here for @ followed by a character that
16526             # is not in any @-command and it is done later
16527             add_prev($text, $stack, $1 . "\@$2") unless($state->{'ignored'});
16528             next;
16529         }
16530         elsif (s/^([^{}]*)([{}])//o)
16531         {
16532          # in ignored section we cannot be sure that there is an @-command
16533          # allready opened so we must discard the text.
16534          # ARG_EXPANSION
16535             add_prev($text, $stack, $1) unless($state->{'ignored'});
16536             if ($2 eq '{')
16537             {
16538               # this empty style is for a lone brace.
16539               # we add it even in 'ignored' as it is discarded when the closing
16540               # brace appear, or the ifset or iclear is closed.
16541                 push @$stack, { 'style' => '', 'text' => '' };
16542             }
16543             else
16544             {
16545                 if (@$stack)
16546                 {
16547                     my $style = pop @$stack;
16548                     my $result;
16549                     if (($style->{'style'} ne '') and exists($info_enclose{$style->{'style'}}) and !$state->{'arg_expansion'})
16550                     {
16551                         $result = $info_enclose{$style->{'style'}}->[0] . $style->{'text'} . $info_enclose{$style->{'style'}}->[1];      
16552                     }              
16553                     elsif ($style->{'style'} ne '')
16554                     {
16555                         $result = '@' . $style->{'style'} . '{' . $style->{'text'} . '}';
16556                     }
16557                     else
16558                     {
16559                         $result = '{' . $style->{'text'};
16560                         # don't close { if we are closing stack as we are not 
16561                         # sure this is a { ... } construct. i.e. we are
16562                         # not sure that the user properly closed the matching
16563                         # brace, so we don't close it ourselves
16564                         $result .= '}' unless ($state->{'close_stack'} or $state->{'arg_expansion'});
16565                     }
16566                     if ($state->{'ignored'})
16567                     {# ARG_EXPANSION
16568                         print STDERR "# Popped `$style->{'style'}' in ifset/ifclear\n" if ($T2H_DEBUG);
16569                         next;
16570                     }
16571                     add_prev ($text, $stack, $result);
16572                     #print STDERR "MACRO end $style->{'style'} remaining: $_";
16573                     next;
16574                 }
16575                 else
16576                 {# ARG_EXPANSION
16577                     # we warn in the last pass that there is a } without open
16578                     add_prev ($text, $stack, '}') unless($state->{'ignored'});
16579                 }
16580             }
16581         }
16582         else
16583         {# ARG_EXPANSION
16584             #print STDERR "END_LINE $_";
16585             add_prev($text, $stack, $_) unless($state->{'ignored'});
16586             last;
16587         }
16588     }
16589     return undef if ($state->{'ignored'});
16590     return 1;
16591 }
16592
16593 sub close_structure_command($$$$)
16594 {
16595     my $cmd_ref = shift;
16596     my $state = shift;
16597     my $unclosed_commands = shift;
16598     my $line_nr = shift;
16599     my $result;
16600     
16601     if ($cmd_ref->{'style'} eq 'anchor')
16602     {
16603         my $anchor = $cmd_ref->{'text'};
16604         $anchor = normalise_node($anchor);
16605         if ($nodes{$anchor})
16606         {
16607             echo_error ("Duplicate node for anchor found: $anchor", $line_nr);
16608             return '';
16609         }
16610         $anchor_num++;
16611         $nodes{$anchor} = { 'anchor' => 1, 'seen' => 1, 'texi' => $anchor, 'id' => 'ANC' . $anchor_num};
16612         push @{$state->{'place'}}, $nodes{$anchor};
16613     }
16614     elsif ($cmd_ref->{'style'} eq 'footnote')
16615     {
16616         if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
16617         {
16618             $state->{'element'} = $state->{'footnote_element'};
16619             $state->{'place'} = $state->{'footnote_place'};
16620         }
16621     }
16622     elsif ($cmd_ref->{'style'} eq 'caption' or $cmd_ref->{'style'}
16623        eq 'shortcaption' and $state->{'float'})
16624     {
16625         my @texi_lines = map {$_ = $_."\n"} split (/\n/, $cmd_ref->{'text'});
16626         $state->{'float'}->{$cmd_ref->{'style'} . "_texi"} = \@texi_lines;
16627     }
16628     if (($cmd_ref->{'style'} eq 'titlefont') and ($cmd_ref->{'text'} =~ /\S/))
16629     {
16630         $state->{'element'}->{'titlefont'} = $cmd_ref->{'text'} unless ((exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} eq 'titlepage')) or defined($state->{'element'}->{'titlefont'})) ;
16631     }
16632     if (defined($Texi2HTML::Config::command_handler{$cmd_ref->{'style'}}))
16633     {
16634         $result = init_special($cmd_ref->{'style'},$cmd_ref->{'text'});
16635         if ($unclosed_commands)
16636         {
16637             $result .= "\n"; # the end of line is eaten by init_special
16638             echo_error("Closing specially handled \@-command $cmd_ref->{'style'}",$line_nr);
16639         }
16640     }
16641     elsif ($cmd_ref->{'style'})
16642     {
16643         $result = '@' . $cmd_ref->{'style'} . '{' . $cmd_ref->{'text'};
16644         $result .= '}' unless ($unclosed_commands);
16645     }
16646     else
16647     {
16648         $result = '{' . $cmd_ref->{'text'};
16649         # don't close { if we are closing stack as we are not
16650         # sure this is a licit { ... } construct.
16651         $result .= '}' unless ($unclosed_commands);
16652     }
16653     return $result;
16654 }
16655
16656 sub scan_structure($$$$;$)
16657 {
16658     my $line = shift;
16659     my $text = shift;
16660     my $stack = shift;
16661     my $state = shift;
16662     my $line_nr = shift;
16663
16664     die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
16665     local $_ = $line;
16666     #print STDERR "SCAN_STRUCTURE: $line";
16667     #dump_stack ($text, $stack, $state); 
16668     if (!$state->{'raw'} and (!exists($state->{'region_lines'})))
16669     { 
16670         if (!$state->{'verb'} and $state->{'menu'} and /^\*/o)
16671         {
16672         # new menu entry
16673             delete ($state->{'after_element'});
16674             my $menu_line = $_;
16675             my $node;
16676             if (/^\*\s+($NODERE)::/)
16677             {
16678                 $node = $1;
16679             }
16680             elsif (/^\*\s+([^:]+):\s*([^\t,\.\n]+)[\t,\.\n]/)
16681             {
16682                 #$name = $1;
16683                 $node = $2;
16684             }
16685             if ($node)
16686             {
16687                 menu_entry_texi(normalise_node($node), $state, $line_nr);
16688             }
16689         }
16690         unless (no_line($_))
16691         {
16692             delete $state->{'after_element'};
16693         }
16694     }
16695
16696     while(1)
16697     {
16698         # scan structure
16699         #print STDERR "WHILE (s):$_";
16700         #dump_stack($text, $stack, $state);
16701
16702         # as texinfo 4.5
16703         # verbatim might begin at another position than beginning
16704         # of line, and end verbatim might too. To end a verbatim section
16705         # @end verbatim must have exactly one space between end and verbatim
16706         # things following end verbatim are not ignored.
16707         #
16708         # html might begin at another position than beginning
16709         # of line, but @end html must begin the line, and have
16710         # exactly one space. Things following end html are ignored.
16711         # tex and ignore works like html
16712         #
16713         # ifnothtml might begin at another position than beginning
16714         # of line, and @end  ifnothtml might too, there might be more
16715         # than one space between @end and ifnothtml but nothing more on 
16716         # the line.
16717         # @end itemize, @end ftable works like @end ifnothtml.
16718         # except that @item on the same line than @end vtable doesn't work
16719         # 
16720         # text right after the itemize before an item is displayed.
16721         # @item might be somewhere in a line. 
16722         # strangely @item on the same line than @end vtable doesn't work
16723         # there should be nothing else than a command following @itemize...
16724         #
16725         # see more examples in formatting directory
16726
16727         if ($state->{'raw'}) 
16728         {
16729             my $tag = $state->{'raw'};
16730             ################# debug 
16731             if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
16732             {
16733                 print STDERR "Bug: raw or special: $tag but not on top of stack\n";
16734                 print STDERR "line: $_";
16735                 dump_stack($text, $stack, $state);
16736                 exit 1;
16737             }
16738             ################# end debug 
16739             if (s/^(.*?)\@end\s$tag$// or s/^(.*?)\@end\s$tag\s//)
16740             {
16741                 add_prev ($text, $stack, $1);
16742                 delete $state->{'raw'};
16743                 my $style = pop @$stack;
16744                 if (defined($Texi2HTML::Config::command_handler{$tag})) 
16745                 { # replace the special region by what init_special give
16746                     if ($style->{'text'} !~ /^\s*$/)
16747                     {
16748                         add_prev ($text, $stack, init_special($style->{'style'}, $style->{'text'}));
16749                     }
16750                     
16751                 }
16752                 else
16753                 {
16754                     my $after_macro = '';
16755                     $after_macro = ' ' unless (/^\s*$/);
16756                     add_prev ($text, $stack, $style->{'text'} . "\@end $tag" . $after_macro);
16757                 }
16758                 unless (no_line($_))
16759                 {
16760                     delete ($state->{'after_element'});
16761                 }
16762                 next;
16763             }
16764             else
16765             {
16766                 add_prev ($text, $stack, $_);
16767                 return if (defined($Texi2HTML::Config::command_handler{$tag})); 
16768                 last;
16769             }
16770         }
16771         
16772         if (defined($state->{'verb'}))
16773         {
16774             my $char = quotemeta($state->{'verb'});
16775             if (s/^(.*?)$char\}/\}/)
16776             {
16777                 add_prev($text, $stack, $1 . $state->{'verb'});
16778                 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
16779                 delete $state->{'verb'};
16780                 next;
16781             }
16782             else
16783             {
16784                 add_prev($text, $stack, $_);
16785                 last;
16786             }
16787         }
16788         
16789         unless (no_line($_))
16790         {
16791             delete $state->{'after_element'};
16792         }
16793         # macro_regexp
16794         if (s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
16795         {
16796             add_prev($text, $stack, $1);
16797             my $end_tag = $2;
16798             #print STDERR "END STRUCTURE $end_tag\n";
16799             $state->{'detailmenu'}-- if ($end_tag eq 'detailmenu' and $state->{'detailmenu'});
16800             if (defined($state->{'text_macro_stack'}) 
16801                and @{$state->{'text_macro_stack'}} 
16802                and ($end_tag eq $state->{'text_macro_stack'}->[-1]))
16803             {
16804                 pop @{$state->{'text_macro_stack'}};
16805                 if (exists($region_lines{$end_tag}))
16806                 { # end a region_line macro, like documentdescription, copying
16807                      print STDERR "Bug: end_tag $end_tag ne $state->{'region_lines'}->{'format'}" 
16808                          if ( $end_tag ne $state->{'region_lines'}->{'format'});
16809                      $state->{'region_lines'}->{'number'}--;
16810                      if ($state->{'region_lines'}->{'number'} == 0)
16811                      { 
16812                          close_region($state);
16813                      }
16814                      #dump_stack($text, $stack, $state); 
16815                 }
16816                 if ($end_tag eq 'menu')
16817                 {
16818                     add_prev($text, $stack, "\@end $end_tag");
16819                     $state->{'menu'}--;
16820                 }
16821                 else
16822                 {
16823                         #print STDERR "End $end_tag\n";
16824                         #dump_stack($text, $stack, $state);
16825                     return if (/^\s*$/);
16826                 }
16827             }
16828             elsif ($text_macros{$end_tag})
16829             {
16830                 echo_error ("\@end $end_tag without corresponding element", $line_nr);
16831                 #dump_stack($text, $stack, $state);
16832             }
16833             else
16834             {
16835                 if ($end_tag eq 'float' and $state->{'float'})
16836                 {
16837                     delete $state->{'float'};
16838                 }
16839                 elsif ($end_tag eq $state->{'table_stack'}->[-1])
16840                 {
16841                     enter_table_index_entry($text, $stack, $state, $line_nr);
16842                     pop @{$state->{'table_stack'}};
16843                 }
16844                 #add end tag
16845                 add_prev($text, $stack, "\@end $end_tag");
16846             }
16847             next;
16848         }
16849         #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
16850         # macro_regexp
16851         elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
16852         {
16853             add_prev($text, $stack, $1);
16854             my $macro = $2;
16855             #print STDERR "MACRO $macro\n";
16856             if (defined($Texi2HTML::Config::misc_command{$macro}))
16857             {
16858                  my $line;
16859                  ($_, $line) = misc_command_structure($_, $macro, $state, 
16860                        $line_nr);
16861                  add_prev ($text, $stack, "\@$macro".$line); 
16862                  next;
16863             }
16864
16865             if ($macro =~ /^(\w+?)index/ and ($1 ne 'print') and ($1 ne 'syncode') and ($1 ne 'syn') and ($1 ne 'def') and ($1 ne 'defcode'))
16866             {
16867                 my $index_prefix = $1;
16868                 my $key = $_;
16869                 $key =~ s/^\s*//;
16870                 $_ = substitute_texi_line($_);
16871                 enter_index_entry($index_prefix, $line_nr, $key, $state->{'place'}, $state->{'element'}, $state->{'after_element'}, $macro);
16872                 add_prev ($text, $stack, "\@$macro" .  $_);
16873                 last;
16874             }
16875             elsif (defined($text_macros{$macro}))
16876             {
16877                 #print STDERR "TEXT_MACRO: $macro\n";
16878                 if ($text_macros{$macro} eq 'raw')
16879                 {
16880                     $state->{'raw'} = $macro;
16881                     #print STDERR "RAW\n";
16882                 }
16883                 elsif ($format_type{$macro} and $format_type{$macro} eq 'menu')
16884                 {
16885                     $state->{'menu'}++;
16886                     delete ($state->{'prev_menu_node'});
16887                     push @{$state->{'text_macro_stack'}}, $macro;
16888                     #print STDERR "MENU (text_macro_stack: @{$state->{'text_macro_stack'}})\n";
16889                 }
16890                 elsif (exists($region_lines{$macro}))
16891                 {
16892                     if (exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} ne $macro))
16893                     {
16894                         echo_error("\@$macro not allowed within $state->{'region_lines'}->{'format'}", $line_nr);
16895                         next;
16896                     }
16897                     if (!exists($state->{'region_lines'}))
16898                     {
16899                         $state->{'region_lines'}->{'format'} = $macro;
16900                         $state->{'region_lines'}->{'number'} = 1;
16901                         $state->{'region_lines'}->{'after_element'} = 1 if ($state->{'after_element'});
16902                         $state->{'region_lines'}->{'kept_place'} = $state->{'place'};
16903                         $state->{'place'} = $region_place;
16904                     }
16905                     else
16906                     {
16907                         $state->{'region_lines'}->{'number'}++;
16908                     }
16909                     push @{$state->{'text_macro_stack'}}, $macro;
16910                 }
16911                 # if it is a raw formatting command or a menu command
16912                 # we must keep it for later
16913                 my $macro_kept; 
16914                 if (($state->{'raw'} and (!defined($Texi2HTML::Config::command_handler{$macro}))) or ($macro eq 'menu'))
16915                 {
16916                     add_prev($text, $stack, "\@$macro");
16917                     $macro_kept = 1;
16918                 }
16919                 if ($state->{'raw'})
16920                 {
16921                     push @$stack, { 'style' => $macro, 'text' => '' };
16922                 }
16923                 next if $macro_kept;
16924                 #dump_stack ($text, $stack, $state);
16925                 return if (/^\s*$/);
16926             }
16927             elsif ($macro eq 'float')
16928             { 
16929                 my ($style_texi, $label_texi) = split(/,/, $_);
16930                 $style_texi = normalise_space($style_texi);
16931                 $label_texi = undef if (defined($label_texi) and ($label_texi =~ /^\s*$/));
16932                 if (defined($label_texi))
16933                 { # The float may be a target for refs if it has a label
16934                     $label_texi = normalise_node($label_texi);
16935                     if (exists($nodes{$label_texi}) and defined($nodes{$label_texi})
16936                          and $nodes{$label_texi}->{'seen'})
16937                     {
16938                         echo_error ("Duplicate label found: $label_texi", $line_nr);
16939                         while ($_ =~ /,/)
16940                         {
16941                             $_ =~ s/,.*$//;
16942                         }
16943                     }
16944                     else
16945                     {
16946                         my $float = { };
16947                         if (exists($nodes{$label_texi}) and defined($nodes{$label_texi}))
16948                         { # float appeared in a menu
16949                             $float = $nodes{$label_texi};
16950                         }
16951                         else
16952                         {
16953                             $nodes{$label_texi} = $float;
16954                         }
16955                         $float->{'float'} = 1;
16956                         $float->{'tag'} = 'float';
16957                         $float->{'texi'} = $label_texi;
16958                         $float->{'seen'} = 1;
16959                         $float->{'id'} = $label_texi;
16960 #print STDERR "FLOAT: $float $float->{'texi'}, place $state->{'place'}\n";
16961                         push @{$state->{'place'}}, $float;
16962                         $float->{'element'} = $state->{'element'};
16963                         $state->{'float'} = $float;
16964                         $float->{'style_texi'} = $style_texi;
16965                         push @floats, $float;
16966                     }
16967                 }
16968                 add_prev($text, $stack, "\@$macro" . $_);
16969                 last;
16970             }
16971             elsif (defined($Texi2HTML::Config::def_map{$macro}))
16972             {
16973                 #We must enter the index entries
16974                 my ($prefix, $entry, $argument) = get_deff_index($macro, $_, $line_nr);
16975                 # use deffn instead of deffnx for @-command record 
16976                 # associated with index entry
16977                 my $idx_macro = $macro;
16978                 $idx_macro =~ s/x$//;
16979                 enter_index_entry($prefix, $line_nr, $entry, $state->{'place'},
16980                    $state->{'element'}, 0, $idx_macro) if ($prefix);
16981                 s/(.*)//;
16982                 add_prev($text, $stack, "\@$macro" . $1);
16983                 # the text is discarded but we must handle correctly bad
16984                 # texinfo with 2 @def-like commands on the same line
16985                 substitute_text({'structure' => 1, 'place' => $state->{'place'} },($argument));
16986             }
16987             elsif ($macro =~ /^itemx?$/)
16988             {
16989                 enter_table_index_entry($text, $stack, $state, $line_nr);
16990                 if ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/)
16991                 {
16992                     $state->{'item'} = $macro;
16993                     push @$stack, { 'format' => 'index_item', 'text' => "" };
16994                 }
16995                 else
16996                 {
16997                     add_prev($text, $stack, "\@$macro");
16998                 }
16999             }
17000             elsif ($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'list'))
17001             { # We must enter the index entries of (v|f)table thus we track
17002               # in which table we are
17003                 push @{$state->{'table_stack'}}, $macro;
17004                 add_prev($text, $stack, "\@$macro");
17005             }
17006             elsif (s/^{//)
17007             {
17008                 if ($macro eq 'verb')
17009                 {
17010                     if (/^$/)
17011                     {
17012                         # We allready warned in pass texi
17013                         #warn "$ERROR verb at end of line";
17014                     }
17015                     else
17016                     {
17017                         s/^(.)//;
17018                         $state->{'verb'} = $1;
17019                     }
17020                 }
17021                 elsif ($macro eq 'footnote' and $Texi2HTML::Config::SEPARATED_FOOTNOTES)
17022                 {
17023                     $state->{'footnote_element'} = $state->{'element'};
17024                     $state->{'footnote_place'} = $state->{'place'};
17025                     $state->{'element'} = $footnote_element;
17026                     $state->{'place'} = $footnote_element->{'place'};
17027                 }
17028                 push (@$stack, { 'style' => $macro, 'text' => '' });
17029             }
17030             else
17031             {
17032                 add_prev($text, $stack, "\@$macro");
17033             }
17034             next;
17035         }
17036         #elsif(s/^([^{}@]*)\@(.)//o)
17037         elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
17038         {
17039             add_prev($text, $stack, $1 . "\@$2");
17040             next;
17041         }
17042         elsif (s/^([^{}]*)([{}])//o)
17043         {
17044             add_prev($text, $stack, $1);
17045             if ($2 eq '{')
17046             {
17047                 push @$stack, { 'style' => '', 'text' => '' };
17048             }
17049             else
17050             {
17051                 if (@$stack)
17052                 {
17053                     my $style = pop @$stack;
17054                     my $result;
17055                     add_prev ($text, $stack, close_structure_command($style,
17056                          $state, 0, $line_nr));
17057                     next;
17058                 }
17059                 else
17060                 {
17061                     # We warn in the last pass
17062                     #warn "$ERROR '}' without opening '{' line: $line";
17063                     #echo_error ("'}' without opening '{' line: $line", $line_nr);
17064                     add_prev ($text, $stack, '}');
17065                 }
17066             }
17067         }
17068         else
17069         {
17070             #print STDERR "END_LINE $_";
17071             add_prev($text, $stack, $_);
17072             enter_table_index_entry($text, $stack, $state, $line_nr);
17073             last;
17074         }
17075     }
17076     return 1;
17077 }
17078
17079 sub scan_line($$$$;$)
17080 {
17081     my $line = shift;
17082     my $text = shift;
17083     my $stack = shift;
17084     my $state = shift;
17085     my $line_nr = shift;
17086
17087     die "stack not an array ref"  unless (ref($stack) eq "ARRAY");
17088     local $_ = $line;
17089     #print STDERR "SCAN_LINE (@{$state->{'command_stack'}}): $line";
17090     #dump_stack($text, $stack,  $state );
17091     my $new_menu_entry; # true if there is a new menu entry
17092     my $menu_description_in_format; # true if we are in a menu description 
17093                                 # but in another format section (@table....)
17094     if (defined($state->{'prepend_text'}))
17095     {
17096         $_ = $state->{'prepend_text'} . $_;
17097         $state->{'prepend_text'} = undef;
17098         delete $state->{'prepend_text'};
17099     }
17100
17101     unless ($state->{'end_of_line_protected'} and $state->{'deff_line'})
17102     { # end of lines are really protected only for @def*
17103         if (!$state->{'raw'} and !$state->{'verb'} and $state->{'menu'})
17104         { # new menu entry
17105             my ($node, $name, $ending);
17106             if (s/^\*(\s+$NODERE)(::)//o)
17107             {
17108                 $node = $1;
17109                 $ending = $2;
17110             }
17111             elsif (s/^\*(\s+[^:]+):(\s*[^\t,\.\n]+)([\t,\.\n])//o)
17112             {
17113                 $name = $1;
17114                 $node = $2;
17115                 $ending = $3;
17116             }
17117             if ($node)
17118             {
17119                 my $top_stack = top_stack($stack);
17120                 if ($top_stack and $top_stack->{'format'} and 
17121                     (
17122                      ($top_stack->{'format'} eq 'menu_description') or
17123                      ($top_stack->{'format'} eq 'menu') or
17124                      (($top_stack->{'format'} eq 'preformatted') and (stack_order($stack, 'preformatted', 'menu_comment'))) or
17125                      ($top_stack->{'format'} eq 'menu_preformatted') or
17126                      ($top_stack->{'format'} eq 'menu_comment')
17127                     )
17128                    )
17129                 { # we are in a normal menu state.
17130                     close_menu($text, $stack, $state, $line_nr);
17131                     $new_menu_entry = 1;
17132                     $state->{'menu_entry'} = { 'name' => $name, 'node' => $node,
17133                        'ending' => $ending };
17134                     add_prev ($text, $stack, do_menu_link($state, $line_nr));
17135                     print STDERR "# New menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU);
17136                     push @$stack, {'format' => 'menu_description', 'text' => ''};
17137                 }
17138                 else
17139                 { # we are within a macro or a format. In that case we use
17140                   # a simplified formatting of menu which should be right whatever
17141                   # the context
17142                     my $menu_entry = $state->{'menu_entry'};
17143                     $state->{'menu_entry'} = { 'name' => $name, 'node' => $node,
17144                        'ending' => $ending };
17145                     add_prev ($text, $stack, do_menu_link($state, $line_nr, 1));
17146                     $state->{'menu_entry'} = $menu_entry;
17147                 }
17148             }
17149         }
17150         # we're in a menu entry description
17151         if ($state->{'menu_entry'} and !$new_menu_entry)
17152         {
17153             my $top_stack = top_stack($stack);
17154             if (/^\s+\S.*$/ or (!$top_stack->{'format'} or ($top_stack->{'format'} ne 'menu_description')))
17155             { # description continues
17156                 $menu_description_in_format = 1 if ($top_stack->{'format'} and ($top_stack->{'format'} ne 'menu_description'));
17157                 print STDERR "# Description continues\n" if ($T2H_DEBUG & $DEBUG_MENU);
17158             }
17159             else
17160             { # enter menu comment after menu entry
17161                 ################################ begin debug
17162                 if (!$top_stack->{'format'} or ($top_stack->{'format'} ne 'menu_description'))
17163                 {
17164                     print STDERR "Bug: begin menu comment but previous isn't menu_description\n";
17165                     dump_stack ($text, $stack, $state);
17166                 }
17167                 print STDERR "# Menu comment begins\n" if ($T2H_DEBUG & $DEBUG_MENU);
17168                 ################################ end debug
17169                 my $descr = pop(@$stack);
17170             
17171                 add_prev ($text, $stack, do_menu_description($descr->{'text'}, $state));
17172                 delete $state->{'menu_entry'};
17173                 unless (/^\s*\@end\s+menu\b/)
17174                 {
17175                     $state->{'menu_comment'}++;
17176                     push @$stack, {'format' => 'menu_comment', 'text' => ''};
17177                     unless ($Texi2HTML::Config::SIMPLE_MENU)
17178                     {
17179                         push @{$state->{'preformatted_stack'}}, {'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE, 'class' => 'menu-comment' };
17180                         $state->{'preformatted'}++;
17181                         begin_paragraph($stack, $state);
17182                     }
17183                 }
17184             }
17185         }
17186         if (($state->{'menu_entry'} and !$menu_description_in_format) or $state->{'raw'} or $state->{'preformatted'}  or $state->{'no_paragraph'} or $state->{'keep_texi'} or $state->{'remove_texi'})
17187         { # empty lines are left unmodified
17188             if (/^\s*$/)
17189             {
17190                 add_prev($text, $stack, $_);
17191                 return;
17192             }
17193             elsif (!$state->{'raw'})
17194             {
17195                 my $next_tag = next_tag($_);
17196                 if ($state->{'deff_line'} and !defined($Texi2HTML::Config::def_map{$next_tag}))
17197                 {
17198                     begin_deff_item($stack, $state);
17199                 }
17200             }
17201         }
17202         else
17203         {
17204             if (/^\s*$/)
17205             {
17206                 if ($state->{'paragraph_context'})
17207                 { # An empty line ends a paragraph
17208                     close_paragraph($text, $stack, $state, $line_nr);
17209                 }
17210                 add_prev($text, $stack, &$Texi2HTML::Config::empty_line($_,$state));
17211                 return 1;
17212            }
17213            else
17214            {
17215                #print STDERR "a line not empty and not in no paragraph format\n";
17216                 my $next_tag = next_tag($_);
17217                 if ($state->{'deff_line'} and !defined($Texi2HTML::Config::def_map{$next_tag}))
17218                 { # finish opening the deff, as this is not a deff tag, it can't be 
17219                   # a deff macro with x
17220                     begin_deff_item($stack, $state);
17221                 }
17222                 if (!no_paragraph($state,$_))
17223                 { # open a paragraph, unless the line begins with a macro that
17224                   # shouldn't trigger a paragraph opening
17225                     begin_paragraph($stack, $state);
17226                 }
17227             }
17228         }
17229     }
17230     delete $state->{'end_of_line_protected'} 
17231        if ($state->{'end_of_line_protected'});
17232
17233     while(1)
17234     {
17235         # scan_line
17236         #print STDERR "WHILE (l): $_|";
17237         #dump_stack($text, $stack, $state);
17238         # we're in a raw format (html, tex if !L2H, verbatim)
17239         if (defined($state->{'raw'})) 
17240         {
17241             (dump_stack($text, $stack, $state), die "Bug for raw ($state->{'raw'})") if (! @$stack or ! ($stack->[-1]->{'style'} eq $state->{'raw'}));
17242             if (s/^(.*?)\@end\s$state->{'raw'}$// or s/^(.*?)\@end\s$state->{'raw'}\s+//)
17243             # don't protect html, it is done by Texi2HTML::Config::raw if needed
17244             {
17245                 print STDERR "# end raw $state->{'raw'}\n" if ($T2H_DEBUG & $DEBUG_FORMATS);
17246                 add_prev ($text, $stack, $1);
17247                 my $style = pop @$stack;
17248                 if ($style->{'text'} !~ /^\s*$/)
17249                 {
17250                     if ($state->{'keep_texi'})
17251                     {
17252                         add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}");
17253                     }
17254                     elsif ($state->{'remove_texi'})
17255                     {
17256                         add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi($style->{'style'}, $style->{'text'}));
17257                     }
17258                     else
17259                     { 
17260                         add_prev($text, $stack, &$Texi2HTML::Config::raw($style->{'style'}, $style->{'text'}));
17261                     }
17262                 }
17263                 if (!$state->{'keep_texi'} and !$state->{'remove_texi'})
17264                 {
17265                     # reopen preformatted if it was interrupted by the raw format
17266                     # if raw format is html the preformatted wasn't interrupted
17267                     begin_paragraph($stack, $state) if ($state->{'preformatted'} and (!$Texi2HTML::Config::format_in_paragraph{$state->{'raw'}})); 
17268                     delete $state->{'raw'};
17269                     return if (/^\s*$/);
17270                 }
17271                 delete $state->{'raw'};
17272                 next;
17273             }
17274             else
17275             {
17276                 print STDERR "#within raw $state->{'raw'}:$_" if ($T2H_DEBUG & $DEBUG_FORMATS);
17277                 add_prev ($text, $stack, $_);
17278                 last;
17279             }
17280         }
17281
17282         # we are within a @verb
17283         if (defined($state->{'verb'}))
17284         {
17285             my $char = quotemeta($state->{'verb'});
17286             if (s/^(.*?)$char\}/\}/)
17287             {
17288                  if ($state->{'keep_texi'})
17289                  {
17290                      add_prev($text, $stack, $1 . $state->{'verb'});
17291                      $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
17292                  }
17293                  elsif ($state->{'remove_texi'})
17294                  {
17295                      add_prev($text, $stack, $1);
17296                  }
17297                  else
17298                  {
17299                      add_prev($text, $stack, do_text($1, $state));
17300                  }
17301                  delete $state->{'verb'};
17302                  next;
17303             }
17304             else
17305             {
17306                  add_prev($text, $stack, $_);
17307                  last;
17308             }
17309         }
17310
17311         # a special case for @ followed by an end of line in deff
17312         # FIXME this is similar with makeinfo, but shouldn't that
17313         # be done for @floats and @quotations too? and @item, @center?
17314         # this piece of code is required, to avoid the 'cmd_line' to be 
17315         # closed below 
17316         if ($state->{'end_of_line_protected'} and $state->{'deff_line'})
17317         { 
17318             print STDERR "Bug: 'end_of_line_protected' with text following: $_\n" 
17319                 unless /^$/;
17320             return;
17321         }
17322
17323         # We handle now the end tags 
17324         # macro_regexp
17325         if ($state->{'keep_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
17326         {
17327             my $end_tag = $2;
17328             add_prev($text, $stack, $1 . "\@end $end_tag");
17329             next;
17330         }
17331         # macro_regexp
17332         elsif ($state->{'remove_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
17333         {
17334             add_prev($text, $stack, $1);
17335             next;
17336         }
17337         # macro_regexp
17338         if (s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)\s//o or s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)$//o)
17339         {
17340             add_prev($text, $stack, do_text($1, $state));
17341             my $end_tag = $2;
17342             #print STDERR "END_MACRO $end_tag\n";
17343             #dump_stack ($text, $stack, $state);
17344             
17345             # First we test if the stack is not empty.
17346             # Then we test if the end tag is a format tag.
17347             # We then close paragraphs and preformatted at top of the stack.
17348             # We handle the end tag (even when it was not the tag which appears
17349             # on the top of the stack; in that case we close anything 
17350             # until that element)
17351             $state->{'detailmenu'}-- if ($end_tag eq 'detailmenu' and $state->{'detailmenu'});
17352             # FIXME handle below (look for misc_command) to let the user 
17353             # keep that end tag. On the other hand it is only used for 
17354             # end detailmenu, so maybe it should just go and detailmenu
17355             # could be handled like a normal format. Last there could be 
17356             # something similar than what is done for other misc_commands.
17357             next if (defined($Texi2HTML::Config::misc_command{"end $end_tag"}));
17358             my $top_stack = top_stack($stack);
17359             if (!$top_stack)
17360             {
17361                 echo_error ("\@end $end_tag without corresponding opening", $line_nr);
17362                 add_prev($text, $stack, "\@end $end_tag");
17363                 next;
17364             }
17365
17366             if (!$format_type{$end_tag})
17367             {
17368                 echo_warn ("Unknown \@end $end_tag", $line_nr);
17369                 #warn "$ERROR Unknown \@end $end_tag\n";
17370                 add_prev($text, $stack, "\@end $end_tag");
17371                 next;
17372             }
17373             unless ($Texi2HTML::Config::format_in_paragraph{$end_tag})
17374             { # If the $end_tag is wrong we may be keeping paragraph 
17375               # for a format with paragraphs on the stack
17376                 close_paragraph($text, $stack, $state, $line_nr); 
17377             }
17378
17379             $top_stack = top_stack($stack);
17380             if (!$top_stack or (!defined($top_stack->{'format'})))
17381             {
17382                 echo_error ("\@end $end_tag without corresponding opening element", $line_nr);
17383                 add_prev($text, $stack, "\@end $end_tag");
17384                 dump_stack ($text, $stack, $state) if ($T2H_DEBUG);
17385                 next;
17386             }
17387             # Warn if the format on top of stack is not compatible with the 
17388             # end tag, and find the end tag.
17389             unless (
17390                 ($top_stack->{'format'} eq $end_tag)
17391                 or
17392                 ( 
17393                  ($format_type{$end_tag} eq 'menu') and
17394                  (
17395                   ($top_stack->{'format'} eq 'menu_preformatted') or
17396                   ($top_stack->{'format'} eq 'menu_comment') or
17397                   ($top_stack->{'format'} eq 'menu_description')
17398                  )
17399                 ) or
17400                 ( 
17401                  ($end_tag eq 'multitable') and 
17402                  (
17403                   ($top_stack->{'format'} eq 'cell') or
17404                   ($top_stack->{'format'} eq 'null')
17405                  )
17406                 ) or
17407                 ( 
17408                  ($format_type{$end_tag} eq 'list' ) and 
17409                  ($top_stack->{'format'} eq 'item')
17410                 ) or
17411                 (
17412                  (
17413                   ($format_type{$end_tag} eq 'table') and 
17414                   ($end_tag ne 'multitable')
17415                  ) and 
17416                  (
17417                    ($top_stack->{'format'} eq 'term') or
17418                    ($top_stack->{'format'} eq 'line') 
17419                  )
17420                 ) or
17421                 (
17422                  (defined($Texi2HTML::Config::def_map{$end_tag})) and 
17423                  ($top_stack->{'format'} eq 'deff_item')
17424                 ) or
17425                 (
17426                  ($end_tag eq 'row') and 
17427                  ($top_stack->{'format'} eq 'cell')
17428                 )
17429                )
17430             {
17431                 # this is not the right format. We try to close other
17432                 # formats to find the format we are searching for.
17433                 # First we close paragraphs, as with a wrong $end_format
17434                 # they may not be closed properly.
17435                 close_paragraph($text, $stack, $state, $line_nr);
17436                 $top_stack = top_stack($stack);
17437                 if (!$top_stack or (!defined($top_stack->{'format'})))
17438                 {
17439                     echo_error ("\@end $end_tag without corresponding opening element", $line_nr);
17440                     add_prev($text, $stack, "\@end $end_tag");
17441                     dump_stack ($text, $stack, $state) if ($T2H_DEBUG);
17442                     next;
17443                 }
17444                 my $waited_format = $top_stack->{'format'};
17445                 $waited_format = $fake_format{$top_stack->{'format'}} if ($format_type{$top_stack->{'format'}} eq 'fake');
17446                 echo_error ("waiting for end of $waited_format, found \@end $end_tag", $line_nr);
17447                 close_stack($text, $stack, $state, $line_nr, undef, $end_tag);
17448                 # an empty preformatted may appear when closing things as
17449                 # when closed, formats reopen the preformatted environment
17450                 # in case there is some text following, but we know it isn't 
17451                 # the case here, thus we can close paragraphs.
17452                 close_paragraph($text, $stack, $state);
17453                 my $new_top_stack = top_stack($stack);
17454                 next unless ($new_top_stack and defined($new_top_stack->{'format'}) and (($new_top_stack->{'format'} eq $end_tag) 
17455                    or (($format_type{$new_top_stack->{'format'}} eq 'fake') and ($fake_format{$new_top_stack->{'format'}} eq $format_type{$end_tag}))));
17456             }
17457             # We should now be able to handle the format
17458             if (defined($format_type{$end_tag}) and $format_type{$end_tag} ne 'fake')
17459             {
17460                 end_format($text, $stack, $state, $end_tag, $line_nr);
17461                 begin_paragraph_after_command($state,$stack,$end_tag,$_);
17462             }
17463             else 
17464             { # this is a fake format, ie a format used internally, inside
17465               # a real format. We do nothing, hoping the real format will
17466               # get closed, closing the fake internal formats
17467               #print STDERR "FAKE \@end $end_tag\n";
17468             }
17469             next;
17470         }
17471         # This is a macro
17472         #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
17473         # macro_regexp
17474         elsif (s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@,]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{},@]*)\@([a-zA-Z][\w-]*)$//o)
17475         {
17476             add_prev($text, $stack, do_text($1, $state));
17477             my $macro = $2;
17478             #print STDERR "MACRO $macro\n";
17479             #print STDERR "LINE $_";
17480             #dump_stack ($text, $stack, $state);
17481             # This is a macro added by close_stack to mark paragraph end
17482             if ($macro eq 'end_paragraph')
17483             {
17484                 s/^\{\}//;
17485                 my $top_stack = top_stack($stack);
17486                 #################################### debug
17487                 if (!$top_stack or !$top_stack->{'format'} 
17488                     or ($top_stack->{'format'} ne 'paragraph'))
17489                 {
17490                     print STDERR "Bug: end_paragraph but no paragraph to end\n";
17491                     dump_stack ($text, $stack, $state);
17492                     next;
17493                 }
17494                 #################################### end debug
17495                 s/^\s//;
17496                 my $paragraph = pop @$stack;
17497                 add_prev ($text, $stack, do_paragraph($paragraph->{'text'}, $state));
17498                 next;
17499             }
17500             # Handle macro added by close_stack to mark preformatted region end
17501             elsif ($macro eq 'end_preformatted')
17502             {
17503                 #print STDERR "END_PREFORMATTED\n";
17504                 s/^\{\}//;
17505                 my $top_stack = top_stack($stack);
17506                 #################################### debug
17507                 if (!$top_stack or !$top_stack->{'format'} 
17508                     or ($top_stack->{'format'} ne 'preformatted'))
17509                 {
17510                     print STDERR "Bug: end_preformatted but no preformatted to end\n";
17511                     dump_stack ($text, $stack, $state);
17512                     next;
17513                 }
17514                 #################################### end debug
17515                 my $paragraph = pop @$stack;
17516                 s/^\s//;
17517                 add_prev ($text, $stack, do_preformatted($paragraph->{'text'}, $state));
17518                 next;
17519             }
17520             if (defined($Texi2HTML::Config::misc_command{$macro}))
17521             {
17522                 # The strange condition associated with 'keep_texi' is 
17523                 # there because for an argument appearing on an @itemize 
17524                 # line (we're in 'check_item'), meant to be prepended to an 
17525                 # @item we don't want to keep @c or @comment as otherwise it 
17526                 # eats the @item line. Other commands could do that too but 
17527                 # then the user deserves what he gets.
17528                 if ($state->{'keep_texi'} and 
17529                            (!$state->{'check_item'} or ($macro ne 'c' and $macro ne 'comment'))) 
17530                 {
17531                     my ($line, $args);
17532                     ($_, $line, $args) = preserve_command($_, $macro);
17533                     add_prev($text, $stack, "\@$macro". $line);
17534                     next;
17535                 }
17536
17537                 # Handle the misc command
17538                 $_ = misc_command_text($_, $macro, $stack, $state, $text, $line_nr);
17539                 return unless (defined($_));
17540                 unless ($Texi2HTML::Config::misc_command{$macro}->{'keep'})
17541                 {
17542                      begin_paragraph($stack, $state) if 
17543                        (!no_paragraph($state,$_));
17544                      next;
17545                 }
17546             }
17547             if ($macro eq 'listoffloats')
17548             {
17549                 if ($state->{'keep_texi'})
17550                 {
17551                     if (s/(.*)//o)
17552                     {
17553                         add_prev($text, $stack, "\@$macro" . $1);
17554                     }
17555                     next;
17556                 }
17557                 return undef if ($state->{'remove_texi'});
17558                 
17559                 if (s/^(\s+)(.*)//o)
17560                 {
17561                     my $arg = $2;
17562                     my $style_id = cross_manual_line(normalise_space($arg));
17563                     my $style = substitute_line (&$Texi2HTML::Config::listoffloats_style($arg));
17564                     if (exists ($floats{$style_id}))
17565                     {
17566                          close_paragraph($text, $stack, $state, $line_nr);
17567                          my @listoffloats_entries = ();
17568                          foreach my $float (@{$floats{$style_id}->{'floats'}})
17569                          {
17570                               my $float_style = substitute_line(&$Texi2HTML::Config::listoffloats_float_style($arg, $float));
17571                               my $caption_lines = &$Texi2HTML::Config::listoffloats_caption($float);
17572                               # we set 'multiple_pass' such that index entries
17573                               # and anchors are not handled one more time;
17574                               # the caption has allready been formatted, 
17575                               # and these have been handled at the right place
17576                               my $caption = substitute_text({ 'multiple_pass' => 1 }, @$caption_lines);
17577                               push @listoffloats_entries, &$Texi2HTML::Config::listoffloats_entry($arg, $float, $float_style, $caption, href($float, $state->{'element'}->{'file'}));
17578                          }
17579                          add_prev($text, $stack, &$Texi2HTML::Config::listoffloats($arg, $style, \@listoffloats_entries));
17580                     }
17581                     else
17582                     {
17583                          echo_warn ("Unknown float style $arg", $line_nr); 
17584                     }
17585                 }
17586                 else
17587                 {
17588                     echo_error ("Bad \@$macro line: $_", $line_nr);
17589                 } 
17590                 return undef;
17591             }
17592             # This is a @macroname{...} construct. We add it on top of stack
17593             # It will be handled when we encounter the '}'
17594             # There is a special case for def macros as @deffn{def} is licit
17595             if (!$Texi2HTML::Config::def_map{$macro} and s/^{//)
17596             {
17597                 if ($macro eq 'verb')
17598                 {
17599                     if (/^$/)
17600                     {
17601                         # Allready warned 
17602                         #warn "$ERROR verb at end of line";
17603                     }
17604                     else
17605                     {
17606                         s/^(.)//;
17607                         $state->{'verb'} = $1;
17608                     }
17609                 } 
17610                 elsif ($macro eq 'm_cedilla' and !$state->{'keep_texi'})
17611                 {
17612                     $macro = ',';
17613                 }
17614                 # currently if remove_texi and anchor/ref/footnote
17615                 # the text within the command is ignored
17616                 # see t2h_remove_command in texi2html.init
17617                 push (@$stack, { 'style' => $macro, 'text' => '', 'arg_nr' => 0 });
17618                 $state->{'no_paragraph'}++ if ($no_paragraph_macro{$macro});
17619                 open_arg($macro, 0, $state);
17620                 if (defined($style_type{$macro}) and (($style_type{$macro} eq 'style') or ($style_type{$macro} eq 'accent')))
17621                 {
17622                      push (@{$state->{'command_stack'}}, $macro);
17623                      #print STDERR "# Stacked $macro (@{$state->{'command_stack'}})\n" if ($T2H_DEBUG); 
17624                 }
17625                 next;
17626             }
17627
17628             # special case if we are checking itemize line. In that case
17629             # we want to make sure that there is no @item on the @itemize
17630             # line, otherwise it will be added on the front of another @item,
17631             # leading to an infinite loop...
17632
17633             if ($state->{'check_item'} and ($macro =~ /^itemx?$/ or $macro eq 'headitem'))
17634             {
17635                 echo_error("\@$macro on \@$state->{'check_item'} line", $line_nr);
17636                 next;
17637             }
17638
17639             # if we're keeping texi unmodified we can do it now
17640             if ($state->{'keep_texi'})
17641             {
17642                 # We treat specially formats accepting {} on command line
17643                 if ($macro eq 'multitable' or defined($Texi2HTML::Config::def_map{$macro}))
17644                 {
17645                     add_prev($text, $stack, "\@$macro" . $_);
17646                     $_ = '';
17647                     next;
17648                 }
17649                 # @ at the end of line may protect the end of line even when
17650                 # keeping texi
17651                 if ($macro eq "\n")
17652                 {
17653                      $state->{'end_of_line_protected'} = 1;
17654                      #print STDERR "PROTECTING END OF LINE\n";
17655                 }
17656
17657                 add_prev($text, $stack, "\@$macro");
17658                 if ($text_macros{$macro} and $text_macros{$macro} eq 'raw')
17659                 {
17660                     $state->{'raw'} = $macro;
17661                     push (@$stack, {'style' => $macro, 'text' => ''});
17662                 }
17663                 next;
17664             }
17665
17666             # If we are removing texi, the following macros are not removed 
17667             # as is but modified. So they are collected first, as if we were
17668             # in normal text
17669
17670             # a raw macro beginning
17671             if ($text_macros{$macro} and $text_macros{$macro} eq 'raw')
17672             {
17673                 if (!$Texi2HTML::Config::format_in_paragraph{$macro})
17674                 { # close paragraph before verbatim (and tex if !L2H)
17675                     close_paragraph($text, $stack, $state, $line_nr);
17676                 }
17677                 $state->{'raw'} = $macro;
17678                 push (@$stack, {'style' => $macro, 'text' => ''});
17679                 return if (/^\s*$/);
17680                 next;
17681             }
17682             my $simple_macro = 1;
17683             # An accent macro
17684             if (exists($Texi2HTML::Config::accent_map{$macro}))
17685             {
17686                 push (@{$state->{'command_stack'}}, $macro);
17687                 if (s/^(\S)//o)
17688                 {
17689                     add_prev($text, $stack, do_simple($macro, $1, $state, [ $1 ], $line_nr));
17690                 }
17691                 else
17692                 { # The accent is at end of line
17693                     add_prev($text, $stack, do_text($macro, $state));
17694                 }
17695                 pop @{$state->{'command_stack'}};
17696             }
17697             # an @-command which should be like @command{}. We handle it...
17698             elsif ($::things_map_ref->{$macro})
17699             {
17700                 echo_warn ("$macro requires {}", $line_nr);
17701                 add_prev($text, $stack, do_simple($macro, '', $state));
17702             }
17703             # an @-command like @command
17704             elsif (defined($::simple_map_ref->{$macro}))
17705             {
17706                 add_prev($text, $stack, do_simple($macro, '', $state));
17707             }
17708             else
17709             {
17710                  $simple_macro = 0;
17711             }
17712             if ($simple_macro)
17713             {# if the macro didn't triggered a paragraph start it might now
17714                 begin_paragraph($stack, $state) if 
17715                    ($no_line_macros{$macro} and !no_paragraph($state,$_));
17716                 next;
17717             }
17718             # the following macros are modified or ignored if we are 
17719             # removing texi, and they are not handled like macros in text
17720             if ($state->{'remove_texi'})
17721             {
17722                  # handle specially some macros
17723                  if ((($macro =~ /^(\w+?)index$/) and ($1 ne 'print')) or 
17724                       ($macro eq 'itemize') or ($macro =~ /^(|v|f)table$/)
17725                       or ($macro eq 'multitable') or ($macro eq 'quotation'))
17726                  {
17727                       return;
17728                  }
17729                  elsif ($macro eq 'enumerate')
17730                  {
17731                       my $spec;
17732                       ($_, $spec) = parse_enumerate ($_);
17733                       return if (/^\s*$/);
17734                       next;
17735                  }
17736                  elsif (defined($Texi2HTML::Config::def_map{$macro}))
17737                  {
17738                      my ($style, $category, $name, $type, $class, $arguments);
17739                      ($style, $category, $name, $type, $class, $arguments) = parse_def($macro, $_, $line_nr); 
17740                      # FIXME -- --- ''... lead to simple text in texi2html
17741                      # while they are kept as is in html coments by makeinfo
17742                      $category = remove_texi($category) if (defined($category));
17743                      $name = remove_texi($name) if (defined($name));
17744                      $type = remove_texi($type) if (defined($type));
17745                      $class = remove_texi($class) if (defined($class));
17746                      $arguments = remove_texi($arguments) if (defined($arguments));
17747                      chomp($arguments);
17748                      add_prev($text, $stack, &$Texi2HTML::Config::def_line_no_texi($category, $name, $type, $arguments));
17749                      return;
17750                 }
17751
17752                 # ignore other macros
17753                 next;
17754             }
17755
17756             # handle the other macros, in the context of some normal text
17757             if (($macro =~ /^(\w+?)index$/) and ($1 ne 'print'))
17758             {
17759                 add_prev($text, $stack, do_index_entry_label($macro,$state,$line_nr));
17760                 return;
17761             }
17762             if ($macro eq 'insertcopying')
17763             {
17764                 close_paragraph($text, $stack, $state, $line_nr);
17765                 add_prev($text, $stack, do_insertcopying($state));
17766                 # reopen a preformatted format if it was interrupted by the macro
17767                 begin_paragraph ($stack, $state) if ($state->{'preformatted'});
17768                 return;
17769             }
17770             if ($macro =~ /^itemx?$/o or ($macro eq 'headitem'))
17771             {
17772                     #print STDERR "ITEM: $_";
17773                     #dump_stack($text, $stack, $state);
17774                 abort_empty_preformatted($stack, $state);
17775                 # FIXME let the user be able not to close the paragraph
17776                 close_paragraph($text, $stack, $state, $line_nr);
17777                 # these functions return the format if in the right context
17778                 my $format;
17779                 if ($format = add_item($text, $stack, $state, $line_nr, $_))
17780                 { # handle lists
17781                 }
17782                 elsif ($format = add_term($text, $stack, $state, $line_nr))
17783                 {# handle table @item line
17784                 }
17785                 elsif ($format = add_line($text, $stack, $state, $line_nr)) 
17786                 {# handle table text
17787                 }
17788                 if ($format)
17789                 {
17790                     if (defined($format->{'prepended'}))
17791                     { 
17792                         $_ = $format->{'prepended'} . ' ' . $_ if ($format->{'prepended'} ne '');
17793                     }
17794                     if (defined($format->{'command'}))
17795                     { 
17796                          open_arg($format->{'command'},0, $state);
17797                     }
17798                     next;
17799                 }
17800                 $format = add_row ($text, $stack, $state, $line_nr); # handle multitable
17801                 unless ($format)
17802                 {
17803                     echo_warn ("\@$macro outside of table or list", $line_nr);
17804                     next;
17805                 }
17806                 push @$stack, {'format' => 'row', 'text' => '', 'item_cmd' => $macro };
17807                 if ($format->{'max_columns'})
17808                 {
17809                     push @$stack, {'format' => 'cell', 'text' => ''};
17810                     $format->{'cell'} = 1;
17811                     
17812                     begin_paragraph_after_command($state,$stack,$macro,$_);
17813                 }
17814                 else
17815                 {
17816                     echo_warn ("\@$macro in empty multitable", $line_nr);
17817                 }
17818                 next;
17819             }
17820             if ($macro eq 'tab')
17821             {
17822                 abort_empty_preformatted($stack, $state);
17823                 # FIXME let the user be able not to close the paragraph
17824                 close_paragraph($text, $stack, $state, $line_nr);
17825                 my $format = add_cell ($text, $stack, $state);
17826                 #print STDERR "tab, $format->{'cell'}, max $format->{'max_columns'}\n";
17827                 if (!$format)
17828                 {
17829                     echo_warn ("\@$macro outside of multitable", $line_nr);
17830                 }
17831                 elsif (!$format->{'max_columns'})
17832                 {
17833                     echo_warn ("\@$macro in empty multitable", $line_nr);
17834                     push @$stack, {'format' => 'null', 'text' => ''};
17835                     next;
17836                 }
17837                 elsif ($format->{'cell'} > $format->{'max_columns'})
17838                 {
17839                     echo_warn ("too much \@$macro (multitable has only $format->{'max_columns'} column(s))", $line_nr);
17840                     push @$stack, {'format' => 'null', 'text' => ''};
17841                     next;
17842                 }
17843                 else
17844                 {
17845                     push @$stack, {'format' => 'cell', 'text' => ''};
17846                 }
17847                 begin_paragraph_after_command($state,$stack,$macro,$_);
17848                 next;
17849             }
17850             # Macro opening a format (table, list, deff, example...)
17851             if ($format_type{$macro} and ($format_type{$macro} ne 'fake'))
17852             {
17853                 unless ($Texi2HTML::Config::format_in_paragraph{$macro})
17854                 {
17855                     close_paragraph($text, $stack, $state, $line_nr);
17856                 }
17857                 push (@{$state->{'command_stack'}}, $macro);
17858                 if ($format_type{$macro} eq 'menu')
17859                 {
17860                     close_menu($text, $stack, $state, $line_nr);
17861                     $state->{'menu'}++;
17862                 }
17863                 # A deff like macro
17864                 if (defined($Texi2HTML::Config::def_map{$macro}))
17865                 {
17866                     my $top_format = top_format($stack);
17867                     if (defined($top_format) and ("$top_format->{'format'}x" eq $macro))
17868                     {
17869                       # the @DEFx macro has been put at the top of the 
17870                       # command_stack, although there is no real format opening
17871                          pop @{$state->{'command_stack'}};
17872                          $macro =~ s/x$//o;
17873                          if (!$state->{'deff_line'})
17874                          {# DEFx macro within a DEF paragraph
17875                               close_stack($text, $stack, $state, $line_nr, undef, 'deff_item');
17876                               my $format_ref = pop @$stack;
17877                               add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'}));
17878                          }
17879                          #print STDERR "DEFx $macro\n";
17880                     }
17881                     else
17882                     {
17883                          # The previous @def command isn't the same @def
17884                          # command. We begin the item for the previous @def
17885                          # command and immediately open the new one.
17886                          begin_deff_item($stack, $state, 1) if ($state->{'deff_line'});
17887                          $macro =~ s/x$//o;
17888                          # we remove what is on the stack and put it back,
17889                          # to make sure that it is the form without x.
17890                          pop @{$state->{'command_stack'}};
17891                          push @{$state->{'command_stack'}}, $macro;
17892                          #print STDERR "DEF begin $macro\n";
17893                          push @$stack, { 'format' => $macro, 'text' => '' };
17894                     }
17895                     #print STDERR "BEGIN_DEFF $macro\n";
17896                     #dump_stack ($text, $stack, $state);
17897                     $state->{'deff_line'}->{'command'} = $macro;
17898                     my ($style, $category, $name, $type, $class, $arguments);
17899                     ($style, $category, $name, $type, $class, $_) = parse_def($macro, $_, $line_nr); 
17900                     #print STDERR "AFTER parse_def $_";
17901                     # duplicate_state?
17902                     $state->{'deff_line'}->{'style'} = $style;
17903                     $state->{'deff_line'}->{'category'} = substitute_line($category) if (defined($category));
17904                     $state->{'deff_line'}->{'category'} = '' if (!defined($category));
17905                     # FIXME -- --- ''... are transformed to entities by 
17906                     # makeinfo. It may be wrong.
17907                     $state->{'deff_line'}->{'name'} = substitute_line($name) if (defined($name));
17908                     $state->{'deff_line'}->{'name'} = '' if (!defined($name));
17909                     $state->{'deff_line'}->{'type'} = substitute_line($type) if (defined($type));
17910                     $state->{'deff_line'}->{'class'} = substitute_line($class) if (defined($class));
17911                     # the remaining of the line (the argument)
17912                     #print STDERR "DEFF: open_cmd_line do_def_line $_";
17913                     open_cmd_line($stack, $state, ['keep'], \&do_def_line);
17914                     next;
17915                 }
17916                 elsif (exists ($Texi2HTML::Config::complex_format_map->{$macro}))
17917                 { # handle menu if SIMPLE_MENU. see texi2html.init
17918                     $state->{'preformatted'}++;
17919                     my $complex_format =  $Texi2HTML::Config::complex_format_map->{$macro};
17920                     my $format = { 'format' => $macro, 'text' => '', 'pre_style' => $complex_format->{'pre_style'} };
17921                     my $class = $macro;
17922                     $class = $complex_format->{'class'} if (defined($complex_format->{'class'}));
17923                     push @{$state->{'preformatted_stack'}}, {'pre_style' =>$complex_format->{'pre_style'}, 'class' => $class };
17924                     push @$stack, $format;
17925                     unless ($Texi2HTML::Config::format_in_paragraph{$macro})
17926                     {
17927                         begin_paragraph($stack, $state);
17928                     }
17929                 }
17930                 elsif ($Texi2HTML::Config::paragraph_style{$macro})
17931                 {
17932                     push (@$stack, { 'format' => $macro, 'text' => '' });
17933                     begin_paragraph_after_command($state,$stack,$macro,$_);
17934                     push @{$state->{'paragraph_style'}}, $macro;
17935                     if ($macro eq 'center')
17936                     {
17937                         # @center may be in a weird state with regard with
17938                         # nesting, so we put it on the bottom of the stack
17939                         pop @{$state->{'command_stack'}};
17940                         unshift @{$state->{'command_stack'}}, $macro;
17941                         # for similar reasons, we may have a bad stack nesting
17942                         # which results in } after a closing. For example
17943                         # @center @samp{something @center end of samp}
17944                         # results to samp being kept in the 'command_stack'
17945
17946                         # we keep the end of line for @center, to
17947                         # avoid the return in case there is only spaces
17948                         # which occurs for all the format commmands followed by 
17949                         # spaces only
17950                         next;
17951                     }
17952                 }
17953                 elsif ($format_type{$macro} eq 'menu')
17954                 {
17955                     # if $Texi2HTML::Config::SIMPLE_MENU we won't get there
17956                     # as the menu is a complex format in that case, so it 
17957                     # is handled above
17958                     push @$stack, { 'format' => $macro, 'text' => '' };
17959                     if ($state->{'preformatted'})
17960                     {
17961                     # Start a fake complex format in order to have a given pre style
17962                         $state->{'preformatted'}++;
17963                         push @$stack, { 'format' => 'menu_preformatted', 'text' => '', 'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE };
17964                         push @{$state->{'preformatted_stack'}}, {'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE, 'class' => 'menu-preformatted' };
17965                     }
17966                 }
17967                 elsif (($format_type{$macro} eq 'list') or ($format_type{$macro} eq 'table'))
17968                 {
17969                     my $format;
17970                     #print STDERR "LIST_TABLE $macro\n";
17971                     #dump_stack($text, $stack, $state);
17972                     if (($macro eq 'itemize') or ($macro =~ /^(|v|f)table$/))
17973                     {
17974                         my $command;
17975                         my $prepended;
17976                         ($prepended, $command) = parse_format_command($_,$macro);
17977                         $format = { 'format' => $macro, 'text' => '', 'command' => $command, 'prepended' => $prepended, 'term' => 0 };
17978                         $_ = '';
17979                     }
17980                     elsif ($macro eq 'enumerate')
17981                     {
17982                         my $spec;
17983                         ($_, $spec) = parse_enumerate ($_);
17984                         $spec = 1 if (!defined($spec)); 
17985                         $format = { 'format' => $macro, 'text' => '', 'spec' => $spec, 'item_nr' => 0 };
17986                     }
17987                     elsif ($macro eq 'multitable')
17988                     {
17989                         my $max_columns = parse_multitable ($_, $line_nr);
17990                         if (!$max_columns)
17991                         {
17992                             echo_warn ("empty multitable", $line_nr);
17993                             $max_columns = 0;
17994                         }
17995                         $format = { 'format' => $macro, 'text' => '', 'max_columns' => $max_columns, 'cell' => 1 };
17996                     }
17997                     $format->{'first'} = 1;
17998                     $format->{'paragraph_number'} = 0;
17999                     push @$stack, $format;
18000                     push @{$state->{'table_list_stack'}}, $format;
18001                     if ($macro =~ /^(|v|f)table$/)
18002                     {
18003                         push @$stack, { 'format' => 'line', 'text' => ''};
18004                     }
18005                     elsif ($macro eq 'multitable')
18006                     {
18007                         if ($format->{'max_columns'})
18008                         {
18009                             push @$stack, { 'format' => 'row', 'text' => '', 'item_cmd' => $macro };
18010                             push @$stack, { 'format' => 'cell', 'text' => ''};
18011                         }
18012                         else 
18013                         {
18014                             # multitable without row... We use the special null
18015                             # format which content is ignored
18016                             push @$stack, { 'format' => 'null', 'text' => ''};
18017                             push @$stack, { 'format' => 'null', 'text' => ''};
18018                         }
18019                     }
18020                     if ($format_type{$macro} eq 'list')
18021                     {
18022                         push @$stack, { 'format' => 'item', 'text' => ''};
18023                     }
18024                     begin_paragraph_after_command($state,$stack,$macro,$_)
18025                        if ($macro ne 'multitable');
18026                     return if ($format_type{$macro} eq 'table' or $macro eq 'itemize');
18027                 }
18028                 elsif ($macro eq 'float' or $macro eq 'quotation')
18029                 {
18030                     push @$stack, {'format' => $macro, 'text' => '' };
18031                     if ($macro eq 'float')
18032                     {
18033                          open_cmd_line($stack, $state, ['keep','keep'], \&do_float_line);
18034                     }
18035                     elsif ($macro eq 'quotation')
18036                     {
18037                          open_cmd_line($stack, $state, ['keep'], \&do_quotation_line);
18038                     }
18039                     #dump_stack($text, $stack, $state);
18040                     next;
18041                 }
18042                 # keep this one at the end as there are some other formats
18043                 # which are also in format_map
18044                 elsif (defined($Texi2HTML::Config::format_map{$macro}) or ($format_type{$macro} eq 'cartouche'))
18045                 {
18046                     push @$stack, { 'format' => $macro, 'text' => '' };
18047                     begin_paragraph_after_command($state,$stack,$macro,$_);
18048                 }
18049                 return if (/^\s*$/);
18050                 next;
18051             }
18052             $_ = do_unknown ($macro, $_, $text, $stack, $state, $line_nr);
18053             next;
18054         }
18055         elsif(s/^([^{}@,]*)\@([^\s\}\{\@]*)//o)
18056         { # A macro with a character which shouldn't appear in macro name
18057             add_prev($text, $stack, do_text($1, $state));
18058             $_ = do_unknown ($2, $_, $text, $stack, $state, $line_nr);
18059             next;
18060         }
18061         elsif (s/^([^{},]*)([{}])//o or (@$stack and 
18062              defined($stack->[-1]->{'style'}) and
18063              ($stack->[-1]->{'style'} eq 'cmd_line') and /^([^{},]*)$/o))
18064         {
18065             my $leading_text = $1;
18066             my $brace = $2;
18067             add_prev($text, $stack, do_text($leading_text, $state));
18068             if (defined($brace) and ($brace eq '{'))
18069             {
18070                 add_prev($text, $stack, do_text('{',$state));
18071                 unless ($state->{'keep_texi'} or $state->{'remove_texi'})
18072                 {
18073                     echo_error ("'{' without macro. Before: $_", $line_nr);
18074                 }
18075             }
18076             elsif (defined($brace) and ($brace eq '}') and 
18077                     (!@$stack or (!defined($stack->[-1]->{'style'}))
18078             # a non empty stack, but with 'cmd_line' as first item on the stack
18079             # is like an empty stack
18080                        or ($stack->[-1]->{'style'} eq 'cmd_line')))
18081             {
18082                 if ($state->{'keep_texi'})
18083                 {
18084                     add_prev($text, $stack, '}');
18085                 }
18086                 else
18087                 {
18088                     echo_error("'}' without opening '{' before: $_", $line_nr);
18089                 }
18090             }
18091             else
18092             { # A @-command{ ...} is closed
18093                 my $style = pop @$stack;
18094                 my $command = $style->{'style'};
18095                 my $result;
18096                 if (ref($::style_map_ref->{$command}) eq 'HASH')
18097                 {
18098                     push (@{$style->{'args'}}, $style->{'text'});
18099                     $style->{'fulltext'} .= $style->{'text'};
18100                     #my $number = 0;
18101                     #foreach my $arg(@{$style->{'args'}})
18102                     #{
18103                          #print STDERR "  $number: $arg\n";
18104                     #     $number++;
18105                     #}
18106                     $style->{'text'} = $style->{'fulltext'};
18107                     $state->{'keep_texi'} = 0 if (
18108                         ($::style_map_ref->{$command}->{'args'}->[$style->{'arg_nr'}] eq 'keep') 
18109                         and ($state->{'keep_nr'} == 1));
18110                 }
18111                 $state->{'no_paragraph'}-- if ($no_paragraph_macro{$command});
18112                 if ($command)
18113                 {
18114                     $style->{'no_close'} = 1 if ($state->{'no_close'});
18115                     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')))
18116                     {
18117                         my $style_command = pop @{$state->{'command_stack'}};
18118                         if ($style_command ne $command)
18119                         {
18120                             print STDERR "Bug: $style_command on 'command_stack', not $command\n";
18121                             push @$stack, $style;
18122                             push @{$state->{'command_stack'}}, $style_command;
18123                             print STDERR "Stacks before pop top:\n";
18124                             dump_stack($text, $stack, $state);
18125                             pop @$stack;
18126                         }
18127                     }
18128                     if ($state->{'keep_texi'})
18129                     { # don't expand @-commands in anchor, refs...
18130                         close_arg ($command, $style->{'arg_nr'}, $state);
18131                         $result = '@' . $command . '{' . $style->{'text'} . '}';
18132                     }
18133                     else
18134                     {
18135                         $result = do_simple($command, $style->{'text'}, $state, $style->{'args'}, $line_nr, $style->{'no_open'}, $style->{'no_close'});
18136                         if ($state->{'code_style'} < 0)
18137                         {
18138                             echo_error ("Bug: negative code_style: $state->{'code_style'}, line:$_", $line_nr);
18139                         }
18140                     }
18141                 }
18142                 else
18143                 {
18144                     print STDERR "Bug: empty style in pass_text\n";
18145                 }
18146                 add_prev($text, $stack, $result);
18147                 if ($command eq 'cmd_line')
18148                 {
18149                     if ($state->{'deff_line'})
18150                     {
18151 #print STDERR "DO DEFF $state->{'deff_line'}->{'command'} $state->{'deff_line'}->{'arguments'}\n";
18152                          my $command = $state->{'deff_line'}->{'command'};
18153                          my $def_style = $state->{'deff_line'}->{'style'};
18154                          my $category = $state->{'deff_line'}->{'category'};
18155                          my $class = $state->{'deff_line'}->{'class'};
18156                          my $type = $state->{'deff_line'}->{'type'};
18157                          my $name = $state->{'deff_line'}->{'name'};
18158                          #my $arguments = $state->{'deff'}->{'arguments'};
18159                          my $arguments; 
18160                          $arguments = substitute_line($state->{'deff_line'}->{'arguments'}) if (defined($state->{'deff_line'}->{'arguments'}));
18161
18162                          $category = &$Texi2HTML::Config::definition_category($category, $class, $def_style);
18163                          my $index_label = do_index_entry_label($command, $state,$line_nr);
18164                          add_prev($text, $stack, &$Texi2HTML::Config::def_line($category, $name, $type, $arguments, $index_label));
18165                     }
18166                     elsif ($state->{'preformatted'})
18167                     { # inconditionally begin a preformatted section for 
18168                       # non @def* commands (currently @float and @quotation)
18169                       # for @def* it is done in begin_deff_item
18170                         begin_paragraph($stack, $state);
18171                     }
18172                     $state->{'no_paragraph'}--;
18173                     return;
18174                 }
18175             }
18176         }
18177         elsif (s/^([^,]*)[,]//o)
18178         {
18179              add_prev($text, $stack, do_text($1, $state));
18180              if (@$stack and defined($stack->[-1]->{'style'})
18181                   and (ref($::style_map_ref->{$stack->[-1]->{'style'}}) eq 'HASH'))
18182              {
18183                   my $macro = $stack->[-1]->{'style'};
18184                   my $style_args = $::style_map_ref->{$macro}->{'args'};
18185                   if (defined($style_args->[$stack->[-1]->{'arg_nr'} + 1]))
18186                   {
18187                        push (@{$stack->[-1]->{'args'}}, $stack->[-1]->{'text'});
18188                        $stack->[-1]->{'fulltext'} .= $stack->[-1]->{'text'} . do_text(',', $state);
18189                        $stack->[-1]->{'text'} = '';
18190                        close_arg ($macro, $stack->[-1]->{'arg_nr'}, $state);
18191                        $stack->[-1]->{'arg_nr'}++;
18192                        open_arg ($macro, $stack->[-1]->{'arg_nr'}, $state);
18193                        next;
18194                   }
18195              }
18196              add_prev($text, $stack, do_text(',', $state));
18197         }
18198         else
18199         { # no macro nor '}', but normal text
18200             add_prev($text, $stack, do_text($_, $state));
18201             #print STDERR "END LINE:$_!!!\n";
18202             #dump_stack($text, $stack, $state);
18203             
18204             # @item line is closed by end of line
18205             add_term($text, $stack, $state, $line_nr);
18206
18207             # @center is closed at the end of line. When a @-command which 
18208             # keeps the texi as is happens on the @center line, the @center
18209             # is closed at the end of line appearing after the @-command
18210             # closing (for example @ref, @footnote).
18211
18212             # when 'closing_center' is true we don't retry to close 
18213             # the @center line.
18214             if ($state->{'paragraph_style'}->[-1] eq 'center' 
18215                and !$state->{'closing_center'} and !$state->{'keep_texi'})
18216             {
18217                 $state->{'closing_center'} = 1;
18218                 unless ($Texi2HTML::Config::format_in_paragraph{'center'})
18219                 {
18220                     close_paragraph($text, $stack, $state, $line_nr); 
18221                 }
18222                 close_stack($text, $stack, $state, $line_nr, undef, 'center');
18223                 delete $state->{'closing_center'};
18224                 my $center = pop @$stack;
18225                 add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command('center',$center->{'text'}));
18226                 my $top_paragraph_style = pop @{$state->{'paragraph_style'}};
18227                 # center is at the bottom of the comand_stack because it 
18228                 # may be nested in many way
18229                 my $bottom_command_stack = shift @{$state->{'command_stack'}};
18230                 print STDERR "Bug: closing center, top_paragraph_style: $top_paragraph_style, bottom_command_stack: $bottom_command_stack.\n"
18231                    if ($bottom_command_stack ne 'center' or $top_paragraph_style ne 'center');
18232                 $_ = '';
18233                 next;
18234             }
18235             last;
18236         }
18237     }
18238     return 1;
18239 }
18240
18241 sub open_arg($$$)
18242 {
18243     my $macro = shift;
18244     my $arg_nr = shift;
18245     my $state = shift;
18246     if (ref($::style_map_ref->{$macro}) eq 'HASH')
18247     {
18248          my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
18249          if ($arg eq 'code' and !$state->{'keep_texi'})
18250          {
18251              $state->{'code_style'}++;
18252          }
18253          elsif ($arg eq 'keep')
18254          {
18255              $state->{'keep_nr'}++;
18256              $state->{'keep_texi'} = 1;
18257          }
18258     }
18259     elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
18260     {
18261          $state->{'code_style'}++;
18262     }
18263 }
18264
18265 sub close_arg($$$)
18266 {
18267     my $macro = shift;
18268     my $arg_nr = shift;
18269     my $state = shift;
18270     if (ref($::style_map_ref->{$macro}) eq 'HASH')
18271     {
18272          my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
18273          if ($arg eq 'code' and !$state->{'keep_texi'})
18274          {
18275              $state->{'code_style'}--;
18276          }
18277          elsif ($arg eq 'keep')
18278          {
18279              $state->{'keep_nr'}--;
18280              $state->{'keep_texi'} = 0 if ($state->{'keep_nr'} == 0);
18281          }
18282 #print STDERR "c $arg_nr $macro $arg $state->{'code_style'}\n";
18283     }
18284     elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
18285     {
18286          $state->{'code_style'}--;
18287     }
18288 }
18289
18290 # add a special style on the top of the stack. This is used for commands
18291 # that extend until the end of the line
18292 sub open_cmd_line($$$$)
18293 {
18294     my $stack = shift;
18295     my $state = shift;
18296     my $args = shift;
18297     my $function = shift;
18298     push @$stack, {'style' => 'cmd_line', 'text' => '', 'arg_nr' => 0};
18299     foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi)
18300     {
18301          $hash->{'cmd_line'}->{'args'} = $args;
18302          $hash->{'cmd_line'}->{'function'} = $function;
18303     }
18304     $state->{'no_paragraph'}++;
18305     open_arg ('cmd_line', 0, $state);
18306 }
18307
18308 # finish @item line in @*table
18309 sub add_term($$$$;$)
18310 {
18311     my $text = shift;
18312     my $stack = shift;
18313     my $state = shift;
18314     my $line_nr = shift;
18315     my $end = shift;
18316     return unless (exists ($state->{'table_list_stack'}));
18317     my $format = $state->{'table_list_stack'}->[-1];
18318     return unless (($format_type{$format->{'format'}} eq 'table') and ($format->{'format'} ne 'multitable' ) and $format->{'term'});
18319     #print STDERR "ADD_TERM\n";
18320     # we set 'term' = 0 early such that if we encounter an end of line
18321     # during close_stack we don't try to do the term once more
18322     $state->{'table_list_stack'}->[-1]->{'term'} = 0;
18323     # it is the first paragraph for the term.
18324     $format->{'paragraph_number'} = 0;
18325
18326     #dump_stack($text, $stack, $state);
18327     close_stack($text, $stack, $state, $line_nr, undef, 'term');
18328     my $term = pop @$stack;
18329     my $command_formatted;
18330     chomp ($term->{'text'});
18331     if (exists($::style_map_ref->{$format->{'command'}}) and 
18332        !exists($Texi2HTML::Config::special_list_commands{$format->{'format'}}->{$format->{'command'}}) and ($style_type{$format->{'command'}} eq 'style'))
18333     {
18334          my $leading_spaces = '';
18335          my $trailing_spaces = '';
18336          $term->{'text'}  =~ s/^(\s*)//o;
18337          $leading_spaces = $1 if (defined($1));
18338          $term->{'text'}  =~ s/(\s*)$//o;
18339          $trailing_spaces = $1 if (defined($1));
18340          $term->{'text'} = do_simple($format->{'command'}, $term->{'text'}, $state, [$term->{'text'}]); 
18341          $term->{'text'} = $leading_spaces. $term->{'text'} .$trailing_spaces;
18342     }
18343     elsif (exists($::things_map_ref->{$format->{'command'}}))
18344     {
18345         $command_formatted = do_simple($format->{'command'}, '', $state);
18346     }
18347     my $index_label;
18348     if ($format->{'format'} =~ /^(f|v)/o)
18349     {
18350         $index_label = do_index_entry_label($format->{'format'}, $state,$line_nr);
18351         print STDERR "Bug: no index entry for $text" unless defined($index_label);
18352     }
18353     add_prev($text, $stack, &$Texi2HTML::Config::table_item($term->{'text'}, $index_label,$format->{'format'},$format->{'command'}, $command_formatted,$state->{'command_stack'}));
18354     unless ($end)
18355     {
18356         push (@$stack, { 'format' => 'line', 'text' => '' });
18357         begin_paragraph($stack, $state) if ($state->{'preformatted'});
18358     }
18359     return $format;
18360 }
18361
18362 sub add_row($$$$)
18363 {
18364     my $text = shift;
18365     my $stack = shift;
18366     my $state = shift;
18367     my $line_nr = shift;
18368     my $format = $state->{'table_list_stack'}->[-1];
18369     return unless ($format->{'format'} eq 'multitable');
18370     if ($format->{'cell'} > $format->{'max_columns'})
18371     {
18372         close_stack($text, $stack, $state, $line_nr, undef, 'null');
18373         pop @$stack;
18374     }
18375     unless ($format->{'max_columns'})
18376     { # empty multitable
18377         pop @$stack; # pop 'row'
18378         return $format;
18379     }
18380     if ($format->{'first'})
18381     { # first row
18382         $format->{'first'} = 0;
18383         #dump_stack($text, $stack, $state);
18384         #if ($stack->[-1]->{'format'} and ($stack->[-1]->{'format'} eq 'paragraph') and ($stack->[-1]->{'text'} =~ /^\s*$/) and ($format->{'cell'} == 1))
18385         if ($stack->[-1]->{'format'} and ($stack->[-1]->{'format'} eq 'cell') and ($stack->[-1]->{'text'} =~ /^\s*$/) and ($format->{'cell'} == 1))
18386         {
18387             pop @$stack;
18388             pop @$stack;
18389             #pop @$stack;
18390             return $format;
18391         }
18392     }
18393     add_cell($text, $stack, $state);
18394     my $row = pop @$stack;    
18395     add_prev($text, $stack, &$Texi2HTML::Config::row($row->{'text'}, $row->{'item_cmd'}));
18396     return $format;
18397 }
18398
18399 sub add_cell($$$$)
18400 {
18401     my $text = shift;
18402     my $stack = shift;
18403     my $state = shift;
18404     my $line_nr = shift;
18405     my $format = $state->{'table_list_stack'}->[-1];
18406     return unless ($format->{'format'} eq 'multitable');
18407     if ($format->{'cell'} <= $format->{'max_columns'})
18408     {
18409         close_stack($text, $stack, $state, $line_nr, undef, 'cell');
18410         my $cell = pop @$stack;
18411         my $row = top_stack($stack);
18412         print STDERR "Bug: top_stack of cell not a row\n" if (!defined($row) or !defined($row->{'format'}) or ($row->{'format'} ne 'row'));
18413         add_prev($text, $stack, &$Texi2HTML::Config::cell($cell->{'text'}, $row->{'item_cmd'}));
18414         $format->{'cell'}++;
18415     }
18416     return $format;
18417 }
18418
18419 sub add_line($$$$;$)
18420 {
18421     my $text = shift;
18422     my $stack = shift;
18423     my $state = shift;
18424     my $line_nr = shift;
18425     my $end = shift;
18426     my $format = $state->{'table_list_stack'}->[-1]; 
18427     return unless ($format_type{$format->{'format'}} eq 'table' and ($format->{'format'} ne 'multitable') and ($format->{'term'} == 0));
18428     #print STDERR "ADD_LINE\n";
18429     #dump_stack($text, $stack, $state);
18430     # as in pre the end of line are kept, we must explicitely abort empty
18431     # preformatted, close_stack doesn't abort the empty preformatted regions.
18432     abort_empty_preformatted($stack, $state) if ($format->{'first'});
18433     close_stack($text, $stack, $state, $line_nr, undef, 'line');
18434     my $line = pop @$stack;
18435     $format->{'paragraph_number'} = 0;
18436     my $first = 0;
18437     $first = 1 if ($format->{'first'});
18438     if ($first)
18439     {
18440         $format->{'first'} = 0;
18441         # we must have <dd> or <dt> following <dl> thus we do a 
18442         # &$Texi2HTML::Config::table_line here too, although it could have
18443         # been a normal paragraph.
18444         add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'})) if ($line->{'text'} =~ /\S/o);
18445     }
18446     else
18447     {
18448         add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}));
18449     }
18450     unless($end)
18451     {
18452         push (@$stack, { 'format' => 'term', 'text' => '' });
18453     }
18454     $format->{'term'} = 1;
18455     return $format;
18456 }
18457
18458 # finish @enumerate or @itemize @item
18459 sub add_item($$$$;$)
18460 {
18461     my $text = shift;
18462     my $stack = shift;
18463     my $state = shift;
18464     my $line_nr = shift;
18465     my $line = shift;
18466     my $end = shift;
18467     my $format = $state->{'table_list_stack'}->[-1];
18468     return unless ($format_type{$format->{'format'}} eq 'list');
18469     #print STDERR "ADD_ITEM: \n";
18470     # as in pre the end of line are kept, we must explicitely abort empty
18471     # preformatted, close_stack doesn't do that.
18472     abort_empty_preformatted($stack, $state) if ($format->{'first'});
18473     close_stack($text, $stack, $state, $line_nr, undef, 'item');
18474     $format->{'paragraph_number'} = 0;
18475     if ($format->{'format'} eq 'enumerate')
18476     {
18477         $format->{'number'} = '';
18478         my $spec = $format->{'spec'};
18479         $format->{'item_nr'}++;
18480         if ($spec =~ /^[0-9]$/)
18481         {
18482             $format->{'number'} = $spec + $format->{'item_nr'} - 1;
18483         }
18484         else
18485         {
18486             my $base_letter = ord('a');
18487             $base_letter = ord('A') if (ucfirst($spec) eq $spec);
18488
18489             my @letter_ords = decompose(ord($spec) - $base_letter + $format->{'item_nr'} - 1, 26);
18490             foreach my $ord (@letter_ords)
18491             {# WARNING we go directly to 'ba' after 'z', and not 'aa'
18492              #because 'ba' is 1,0 and 'aa' is 0,0.
18493                 $format->{'number'} = chr($base_letter + $ord) . $format->{'number'};
18494             }
18495         }
18496     }
18497     
18498     #dump_stack ($text, $stack, $state);
18499     my $item = pop @$stack;
18500     # the element following ol or ul must be li. Thus even though there
18501     # is no @item we put a normal item.
18502
18503     # don't do an item if it is the first and it is empty
18504     if (!$format->{'first'} or ($item->{'text'} =~ /\S/o))
18505     {
18506         my $formatted_command;
18507         if (defined($format->{'command'}) and exists($::things_map_ref->{$format->{'command'}}))
18508         {
18509             $formatted_command = do_simple($format->{'command'}, '', $state);
18510         }
18511         #chomp($item->{'text'});
18512         add_prev($text, $stack, &$Texi2HTML::Config::list_item($item->{'text'},$format->{'format'},$format->{'command'}, $formatted_command, $format->{'item_nr'}, $format->{'spec'}, $format->{'number'}));
18513     } 
18514     if ($format->{'first'})
18515     {
18516         $format->{'first'} = 0;
18517     }
18518
18519     # Now prepare the new item
18520     unless($end)
18521     {
18522         push (@$stack, { 'format' => 'item', 'text' => '' });
18523         begin_paragraph($stack, $state) unless (!$state->{'preformatted'} and no_line($line));
18524     }
18525     return $format;
18526 }
18527
18528 # format ``simple'' macros, that is macros without arg or style macros
18529 sub do_simple($$$;$$$$)
18530 {
18531     my $macro = shift;
18532     my $text = shift;
18533     my $state = shift;
18534     my $args = shift;
18535     my $line_nr = shift;
18536     my $no_open = shift;
18537     my $no_close = shift;
18538     
18539     my $arg_nr = 0;
18540     $arg_nr = @$args - 1 if (defined($args));
18541     
18542 #print STDERR "DO_SIMPLE $macro $arg_nr $args @$args\n" if (defined($args));
18543     if (defined($::simple_map_ref->{$macro}))
18544     {
18545         # \n may in certain circumstances, protect end of lines
18546         if ($macro eq "\n")
18547         {
18548             $state->{'end_of_line_protected'} = 1;
18549             #print STDERR "PROTECTING END OF LINE\n";
18550         }
18551         if ($state->{'keep_texi'})
18552         {
18553             return "\@$macro";
18554         }
18555         elsif ($state->{'remove_texi'})
18556         {
18557 #print STDERR "DO_SIMPLE remove_texi $macro\n";
18558             return  $::simple_map_texi_ref->{$macro};
18559         }
18560         elsif ($state->{'preformatted'})
18561         {
18562             return $::simple_map_pre_ref->{$macro};
18563         }
18564         else
18565         {
18566             return $::simple_map_ref->{$macro};
18567         }
18568     }
18569     if (defined($::things_map_ref->{$macro}))
18570     {
18571         my $result;
18572         if ($state->{'keep_texi'})
18573         {
18574             $result = "\@$macro" . '{}';
18575         }
18576         elsif ($state->{'remove_texi'})
18577         {
18578             $result =  $::texi_map_ref->{$macro};
18579 #print STDERR "DO_SIMPLE remove_texi texi_map $macro\n";
18580         }
18581         elsif ($state->{'preformatted'})
18582         {
18583             $result = $::pre_map_ref->{$macro};
18584         }
18585         else 
18586         {
18587             $result = $::things_map_ref->{$macro};
18588         }
18589         return $result . $text;
18590     }
18591     elsif (defined($::style_map_ref->{$macro}))
18592     {
18593         if ($state->{'keep_texi'})
18594         {
18595             return "\@$macro" . '{' . $text . '}';
18596         }
18597         else 
18598         {
18599             my $style;
18600             my $result;
18601             if ($state->{'remove_texi'})
18602             {
18603 #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;
18604                 $style = $::style_map_texi_ref->{$macro};
18605             }
18606             elsif ($state->{'preformatted'})
18607             {
18608                 $style = $::style_map_pre_ref->{$macro};
18609             }
18610             else
18611             {
18612                 $style = $::style_map_ref->{$macro};
18613             }
18614             if (defined($style))
18615             {                           # known style
18616                 $result = &$Texi2HTML::Config::style($style, $macro, $text, $args, $no_close, $no_open, $line_nr, $state, $state->{'command_stack'});
18617             }
18618             if (!$no_close)
18619             { 
18620                 close_arg($macro,$arg_nr, $state);
18621             }
18622             return $result;
18623         }
18624     }
18625     elsif ($macro =~ /^special_(\w+)_(\d+)$/o)
18626     {
18627         my $style = $1;
18628         my $count = $2;
18629         print STDERR "Bug? text in \@$macro not empty.\n" if ($text ne '');  
18630         if ($state->{'keep_texi'})
18631         {# text should be empty
18632             return "\@$macro" . '{' . $text . '}';
18633         }
18634         if (defined($Texi2HTML::Config::command_handler{$style}) and
18635           defined($Texi2HTML::Config::command_handler{$style}->{'expand'}))
18636         {
18637             my $struct_count = 1+ $special_commands{$style}->{'max'} - $special_commands{$style}->{'count'};
18638             if (($count != $struct_count) and $T2H_DEBUG)
18639             {
18640                 print STDERR "count $count in \@special $style and structure $struct_count differ\n";
18641             }
18642             $special_commands{$style}->{'count'}--;  
18643         }
18644         my $result = $Texi2HTML::Config::command_handler{$style}->{'expand'}
18645               ($style,$count,$state,$text);
18646         $result = '' if (!defined($result));
18647         return $result;
18648     }
18649     # Unknown macro
18650     my $result = '';
18651     my ($done, $result_text, $message) = &$Texi2HTML::Config::unknown_style($macro, $text,$state);
18652     if ($done)
18653     {
18654         echo_warn($message, $line_nr) if (defined($message));
18655         if (defined($result_text))
18656         {
18657             $result = $result_text;
18658         }
18659     }
18660     else 
18661     { 
18662         unless ($no_open)
18663         { # we warn only if no_open is true, i.e. it is the first time we 
18664           # close the macro for a multiline macro
18665             echo_warn ("Unknown command with braces `\@$macro'", $line_nr);
18666             $result = do_text("\@$macro") . "{";
18667         }
18668         $result .= $text;
18669         $result .= '}' unless ($no_close);
18670     }
18671     return $result;
18672 }
18673
18674 sub do_unknown($$$$$$)
18675 {
18676     my $macro = shift;
18677     my $line = shift;
18678     my $text = shift;
18679     my $stack = shift;
18680     my $state = shift;
18681     my $line_nr = shift;
18682     #print STDERR "do_unknown: $macro ::: $line"; 
18683     my ($result_line, $result, $result_text, $message) = &$Texi2HTML::Config::unknown($macro, $line,$stack,$state);
18684     if ($result)
18685     {
18686          add_prev ($text, $stack, $result_text) if (defined($result_text));
18687          echo_warn($message, $line_nr) if (defined($message));
18688          return $result_line;
18689     }
18690     else
18691     {
18692          echo_warn ("Unknown command `\@$macro' (left as is)", $line_nr);
18693          add_prev ($text, $stack, do_text("\@$macro"));
18694          return $line;
18695     }
18696 }
18697
18698 # used only during @macro processing
18699 sub add_text($@)
18700 {
18701     my $string = shift;
18702
18703     return if (!defined($string));
18704     foreach my $scalar_ref (@_)
18705     {
18706         next unless defined($scalar_ref);
18707         if (!defined($$scalar_ref))
18708         {
18709             $$scalar_ref = $string;
18710         }
18711         else
18712         {
18713             $$scalar_ref .= $string;
18714         }
18715         return;
18716     }
18717 }
18718
18719 sub add_prev ($$$)
18720 {
18721     my $text = shift;
18722     my $stack = shift;
18723     my $string = shift;
18724
18725     unless (defined($text) and ref($text) eq "SCALAR")
18726     {
18727        die "text not a SCALAR ref: " . ref($text) . "";
18728     }
18729     #if (!defined($stack) or (ref($stack) ne "ARRAY"))
18730     #{
18731     #    $string = $stack;
18732     #    $stack = [];
18733     #}
18734     
18735     return if (!defined($string));
18736     if (@$stack)
18737     {
18738         $stack->[-1]->{'text'} .= $string;
18739         return;
18740     }
18741
18742     if (!defined($$text))
18743     {
18744          $$text = $string;
18745     }
18746     else
18747     {
18748          $$text .= $string;
18749     }
18750 }
18751
18752 sub close_stack_texi_structure($$$$)
18753 {
18754     my $text = shift;
18755     my $stack = shift;
18756     my $state = shift;
18757     my $line_nr = shift;
18758
18759     return undef unless (@$stack or $state->{'raw'} or $state->{'macro'} or $state->{'macro_name'} or $state->{'ignored'});
18760
18761     #print STDERR "close_stack_texi_structure\n";
18762     #dump_stack ($text, $stack, $state);
18763     my $stack_level = $#$stack + 1;
18764     my $string = '';
18765     
18766     if ($state->{'ignored'})
18767     {
18768         $string .= "\@end $state->{'ignored'} ";
18769         echo_warn ("closing $state->{'ignored'}", $line_nr); 
18770     }
18771     if ($state->{'texi'})
18772     {
18773         if ($state->{'macro'})
18774         {
18775             $string .= "\@end macro ";
18776             echo_warn ("closing macro", $line_nr); 
18777         }
18778         elsif ($state->{'macro_name'})
18779         {
18780             $string .= ('}' x $state->{'macro_depth'}) . " ";
18781             echo_warn ("closing $state->{'macro_name'} ($state->{'macro_depth'} braces missing)", $line_nr); 
18782         }
18783         elsif ($state->{'verb'})
18784         {
18785             echo_warn ("closing \@verb", $line_nr); 
18786             $string .= $state->{'verb'} . '}';
18787         }
18788         elsif ($state->{'raw'})
18789         {
18790             echo_warn ("closing \@$state->{'raw'} raw format", $line_nr);
18791             $string .= "\@end $state->{'raw'} ";
18792         }
18793         if ($string ne '')
18794         {
18795             #print STDERR "close_stack scan_texi ($string)\n";
18796             scan_texi ($string, $text, $stack, $state, $line_nr);
18797             $string = '';
18798         }
18799     }
18800     elsif ($state->{'verb'})
18801     {
18802         $string .= $state->{'verb'};
18803     }
18804
18805     while ($stack_level--)
18806     {
18807         my $stack_text = $stack->[$stack_level]->{'text'};
18808         $stack_text = '' if (!defined($stack_text));
18809         if ($stack->[$stack_level]->{'format'})
18810         {
18811             my $format = $stack->[$stack_level]->{'format'};
18812             if ($format eq 'index_item')
18813             {
18814                 enter_table_index_entry($text, $stack, $state, $line_nr);
18815                 next;
18816             }
18817             elsif (!defined($format_type{$format}) or ($format_type{$format} ne 'fake'))
18818             {
18819                 $stack_text = "\@$format\n" . $stack_text;
18820             }
18821         }
18822         elsif (defined($stack->[$stack_level]->{'style'}))
18823         {
18824             if ($state->{'structure'})
18825             {
18826                 $stack_text = close_structure_command($stack->[$stack_level],
18827                    $state,1,$line_nr)
18828             }
18829             else
18830             {
18831                 my $style = $stack->[$stack_level]->{'style'};
18832                 if ($style ne '')
18833                 {
18834                     $stack_text = "\@$style\{" . $stack_text;
18835                 }
18836                 else
18837                 {# this is a lone opened brace. We readd it there.
18838                     $stack_text = "\{" . $stack_text;
18839                 }
18840             }
18841         }
18842         pop @$stack;
18843         add_prev($text, $stack, $stack_text);
18844     }
18845     $stack = [ ];
18846
18847     $state->{'close_stack'} = 1;
18848     if ($string ne '')
18849     {
18850         if ($state->{'texi'})
18851         {
18852             #print STDERR "scan_texi in close_stack ($string)\n";
18853             scan_texi($string, $text, $stack, $state, $line_nr);
18854         }
18855         elsif ($state->{'structure'})
18856         {
18857             #print STDERR "scan_structure in close_stack ($string)\n";
18858             scan_structure($string, $text, $stack, $state, $line_nr);
18859         }
18860     }
18861     delete $state->{'close_stack'};
18862 }
18863
18864 # close region like @insertcopying, titlepage...
18865 # restore $state->{'after_element'} and delete the structure
18866 sub close_region($)
18867 {
18868     my $state = shift;
18869     $state->{'after_element'} = 1;
18870     delete $state->{'after_element'} unless 
18871           ($state->{'region_lines'}->{'after_element'});
18872     $state->{'place'} = $state->{'region_lines'}->{'kept_place'};
18873     delete $state->{'region_lines'}->{'number'};
18874     delete $state->{'region_lines'}->{'format'};
18875     delete $state->{'region_lines'}->{'after_element'};
18876     delete $state->{'region_lines'}->{'kept_place'};
18877     delete $state->{'region_lines'};
18878 }
18879
18880 # close the stack, closing macros and formats left open.
18881 # the precise behavior of the function depends on $close_paragraph:
18882 #  undef   -> close everything
18883 #  defined -> remove empty paragraphs, close until the first format or 
18884 #          paragraph. don't close styles, duplicate stack of styles not closed
18885
18886 # if a $format is given the stack is closed according to $close_paragraph but
18887 # if $format is encountered the closing stops
18888
18889 sub close_stack($$$$;$$)
18890 {
18891     my $text = shift;
18892     my $stack = shift;
18893     my $state = shift;
18894     my $line_nr = shift;
18895     my $close_paragraph = shift;
18896     my $format = shift;
18897     my $new_stack;
18898     
18899     #print STDERR "sub_close_stack\n";
18900     return $new_stack unless (@$stack);
18901     
18902     my $stack_level = $#$stack + 1;
18903     my $string = '';
18904     my $verb = '';
18905     
18906     if ($state->{'verb'})
18907     {
18908         $string .= $state->{'verb'};
18909         $verb = $state->{'verb'};
18910     }
18911
18912     #debugging
18913     #my $print_format = 'NO FORMAT';
18914     #$print_format = $format if ($format);
18915     #my $print_close_paragraph = 'close everything';
18916     #$print_close_paragraph = 'close paragraph without duplicating' if (defined($close_paragraph));
18917     #$print_close_paragraph = $close_paragraph if ($close_paragraph);
18918     #print STDERR "Close_stack: format $print_format, close_paragraph: $print_close_paragraph\n";
18919     
18920     while ($stack_level--)
18921     {
18922         if ($stack->[$stack_level]->{'format'})
18923         {
18924             my $stack_format = $stack->[$stack_level]->{'format'};
18925             last if (defined($close_paragraph) or (defined($format) and $stack_format eq $format));
18926             # We silently close paragraphs, preformatted sections and fake formats
18927             if ($stack_format eq 'paragraph')
18928             {
18929                 $string .= "\@end_paragraph{}";
18930             }
18931             elsif ($stack_format eq 'preformatted')
18932             {
18933                 $string .= "\@end_preformatted{}";
18934             }
18935             else
18936             {
18937                 if ($fake_format{$stack_format})
18938                 {
18939                     warn "# Closing a fake format `$stack_format'\n" if ($T2H_VERBOSE);
18940                 }
18941                 elsif ($stack_format ne 'center')
18942                 { # we don't warn, but add an @end center
18943                     echo_warn ("closing `$stack_format'", $line_nr); 
18944                     #dump_stack ($text, $stack, $state);
18945                 }
18946                 $string .= "\@end $stack_format ";
18947             }
18948         }
18949         else
18950         {
18951             my $style =  $stack->[$stack_level]->{'style'};
18952             # FIXME images, footnotes, xrefs, anchors with $close_paragraphs?
18953             # seems that it is not possible, as it is triggered by 
18954             # close_paragraph which shouldn't be called with keep_texi
18955             # and when the arguments are expanded, there is a 
18956             # substitute_line or similar with a new stack.
18957             if ($close_paragraph)
18958             { #duplicate the stack
18959               # the !exists($style_type{$style}) condition catches the unknown 
18960               # @-commands: by default they are considered as style commands
18961                 if ((exists($style_type{$style}) and ($style_type{$style} eq 'style')) or (!exists($style_type{$style})))
18962                 {
18963                     push @$new_stack, { 'style' => $style, 'text' => '', 'no_open' => 1, 'arg_nr' => 0 };
18964                     $string .= '}';
18965                 }
18966                 elsif (($style_type{$style} eq 'simple_style') or ($style_type{$style} eq 'accent'))
18967                 {
18968                     $string .= '}';
18969                 }
18970                 else
18971                 {
18972                     print STDERR "$style while closing paragraph\n";
18973                 }
18974             }
18975             else
18976             {
18977                 dump_stack ($text, $stack, $state) if (!defined($style)); # bug
18978                 $string .= '}';
18979                 echo_warn ("closing \@-command $style", $line_nr) if ($style); 
18980             }
18981         }
18982     }
18983     $state->{'no_close'} = 1 if ($close_paragraph);
18984     $state->{'close_stack'} = 1;
18985     if ($string ne '')
18986     {
18987             #print STDERR "scan_line in CLOSE_STACK ($string)\n";
18988             #dump_stack ($text, $stack, $state);
18989          scan_line($string, $text, $stack, $state, $line_nr);
18990     }
18991     delete $state->{'no_close'};
18992     delete $state->{'close_stack'};
18993     $state->{'verb'} = $verb if (($verb ne '') and $close_paragraph);
18994     # cancel paragraph states and command_stack
18995     # FIXME this seems to be unusefull, see formatting/center.texi
18996     unless (defined($close_paragraph) or defined($format))
18997     {
18998         $state->{'paragraph_style'} = [ '' ];
18999         $state->{'command_stack'} = [ '' ]; 
19000     }
19001     return $new_stack;
19002 }
19003
19004 # given a stack and a list of formats, return true if the stack contains 
19005 # these formats, first on top
19006 sub stack_order($@)
19007 {
19008     my $stack = shift;
19009     my $stack_level = $#$stack + 1;
19010     while (@_)
19011     {
19012         my $format = shift;
19013         while ($stack_level--)
19014         {
19015             if ($stack->[$stack_level]->{'format'})
19016             {
19017                 if ($stack->[$stack_level]->{'format'} eq $format)
19018                 {
19019                     $format = undef;
19020                     last;
19021                 }
19022                 else
19023                 {
19024                     return 0;
19025                 }
19026             }
19027         }
19028         return 0 if ($format);
19029     }
19030     return 1;
19031 }       
19032
19033 sub top_format($)
19034 {
19035     my $stack = shift;
19036     my $stack_level = $#$stack + 1;
19037     while ($stack_level--)
19038     {
19039         if ($stack->[$stack_level]->{'format'} and !$fake_format{$stack->[$stack_level]->{'format'}})
19040         {
19041              return $stack->[$stack_level];
19042         }
19043     }
19044     return undef;
19045 }
19046
19047 sub close_paragraph($$$;$)
19048 {
19049     my $text = shift;
19050     my $stack = shift;
19051     my $state = shift;
19052     my $line_nr = shift;
19053     #my $macro = shift;
19054     #print STDERR "CLOSE_PARAGRAPH\n";
19055     #dump_stack($text, $stack, $state);
19056     my $new_stack = close_stack($text, $stack, $state, $line_nr, 1);
19057     my $top_stack = top_stack($stack);
19058     if ($top_stack and !defined($top_stack->{'format'}))
19059     { #debug
19060          print STDERR "Bug: no format on top stack\n";
19061          dump_stack($text, $stack, $state);
19062     }
19063     if ($top_stack and ($top_stack->{'format'} eq 'paragraph'))
19064     {
19065         my $paragraph = pop @$stack;
19066         add_prev($text, $stack, do_paragraph($paragraph->{'text'}, $state));
19067         $state->{'paragraph_macros'} = $new_stack;
19068         return 1;
19069     }
19070     elsif ($top_stack and ($top_stack->{'format'} eq 'preformatted'))
19071     {
19072         my $paragraph = pop @$stack;
19073         add_prev($text, $stack, do_preformatted($paragraph->{'text'}, $state));
19074         $state->{'paragraph_macros'} = $new_stack;
19075         return 1;
19076     }
19077     return;
19078 }
19079
19080 sub abort_empty_preformatted($$)
19081 {
19082     my $stack = shift;
19083     my $state = shift;
19084     if (@$stack and $stack->[-1]->{'format'} 
19085        and ($stack->[-1]->{'format'} eq 'preformatted')
19086        and ($stack->[-1]->{'text'} !~ /\S/))
19087     {
19088         pop @$stack;
19089     }
19090 }
19091
19092 # for debugging
19093 sub dump_stack($$$)
19094 {
19095     my $text = shift;
19096     my $stack = shift;
19097     my $state = shift;
19098
19099     if (defined($$text))
19100     {
19101         print STDERR "text: $$text\n";
19102     }
19103     else
19104     {
19105         print STDERR "text: UNDEF\n";
19106     }
19107     my $in_remove = 0;
19108     my $in_simple_format = 0;
19109     my $in_keep = 0;
19110     $in_keep = 1 if ($state->{'keep_texi'});
19111     if (!$in_keep)
19112     {
19113         $in_simple_format = 1 if ($state->{'simple_format'});
19114         $in_remove = 1 if ($state->{'remove_texi'}  and !$in_simple_format);
19115     }
19116     print STDERR "state(k${in_keep}s${in_simple_format}r${in_remove}): ";
19117     foreach my $key (keys(%$state))
19118     {
19119         my $value = 'UNDEF';
19120         $value = $state->{$key} if (defined($state->{$key}));
19121         print STDERR "$key: $value " if (!ref($value));
19122     }
19123     print STDERR "\n";
19124     my $stack_level = $#$stack + 1;
19125     while ($stack_level--)
19126     {
19127         print STDERR " $stack_level-> ";
19128         foreach my $key (keys(%{$stack->[$stack_level]}))
19129         {
19130             my $value = 'UNDEF';
19131             $value = $stack->[$stack_level]->{$key} if 
19132                 (defined($stack->[$stack_level]->{$key}));
19133             print STDERR "$key: $value ";
19134         }
19135         print STDERR "\n";
19136     }
19137     if (defined($state->{'table_list_stack'}))
19138     {
19139         print STDERR "table_list_stack: ";
19140         foreach my $format (@{$state->{'table_list_stack'}})
19141         {
19142             print STDERR "$format->{'format'} ";
19143         }
19144         print STDERR "\n";
19145     }
19146     if (defined($state->{'command_stack'})) 
19147     {
19148         print STDERR "command_stack: ";
19149         foreach my $style (@{$state->{'command_stack'}})
19150         {
19151             print STDERR "($style) ";
19152         }
19153         print STDERR "\n";
19154     }
19155     if (defined($state->{'region_lines'}))
19156     {
19157         print STDERR "region_lines($state->{'region_lines'}->{'number'}): $state->{'region_lines'}->{'format'}\n";
19158     }
19159     if (defined($state->{'text_macro_stack'}) and @{$state->{'text_macro_stack'}})
19160     {
19161         print STDERR "text_macro_stack: (@{$state->{'text_macro_stack'}})\n";
19162     }
19163 }
19164
19165 # for debugging 
19166 sub print_elements($)
19167 {
19168     my $elements = shift;
19169     foreach my $elem(@$elements)
19170     {
19171         if ($elem->{'node'})
19172         {
19173             print STDERR "node-> $elem ";
19174         }
19175         else
19176         {
19177             print STDERR "chap=> $elem ";
19178         }
19179         foreach my $key (keys(%$elem))
19180         {
19181             my $value = "UNDEF";
19182             $value = $elem->{$key} if (defined($elem->{$key}));
19183             print STDERR "$key: $value ";
19184         }
19185         print STDERR "\n";
19186     }
19187 }
19188
19189 sub substitute_line($;$)
19190 {
19191     my $line = shift;
19192     my $state = shift;
19193     $state = {} if (!defined($state));
19194     $state->{'no_paragraph'} = 1;
19195     # this is usefull when called from &$I
19196     return simple_format($state, $line) if ($state->{'simple_format'});
19197     return substitute_text($state, $line);
19198 }
19199
19200 sub substitute_text($@)
19201 {
19202     my $state = shift;
19203     my @stack = ();
19204     my $text = '';
19205     my $result = '';
19206     if ($state->{'structure'})
19207     {
19208         initialise_state_structure($state);
19209     }
19210     elsif ($state->{'texi'})
19211     {
19212         initialise_state_texi($state);
19213     }
19214     else
19215     {
19216         initialise_state($state);
19217     }
19218     $state->{'spool'} = [];
19219     #print STDERR "SUBST_TEXT begin\n";
19220     
19221     while (@_ or @{$state->{'spool'}})
19222     {
19223         my $line;
19224         if (@{$state->{'spool'}})
19225         {
19226              $line = shift @{$state->{'spool'}};
19227         }
19228         else
19229         {
19230             $line = shift @_;
19231         }
19232         next unless (defined($line));
19233         if ($state->{'structure'})
19234         {
19235             scan_structure ($line, \$text, \@stack, $state);
19236         }
19237         elsif ($state->{'texi'})
19238         {
19239             scan_texi ($line, \$text, \@stack, $state);
19240         }
19241         else
19242         {
19243             scan_line($line, \$text, \@stack, $state);
19244         }
19245         next if (@stack);
19246         $result .= $text;
19247         $text = '';
19248     }
19249     # FIXME could we have the line number ?
19250     # close stack in substitute_text
19251     if ($state->{'texi'} or $state->{'structure'})
19252     {
19253          close_stack_texi_structure(\$text, \@stack, $state, undef);
19254     }
19255     else
19256     {
19257          close_stack(\$text, \@stack, $state, undef);
19258     }
19259     #print STDERR "SUBST_TEXT end\n";
19260     return $result . $text;
19261 }
19262
19263 # this function does the second pass formatting. It is not obvious that 
19264 # it is usefull as in that pass the collected things 
19265 sub substitute_texi_line($)
19266 {
19267     my $text = shift;  
19268     return $text if $text =~ /^\s*$/;
19269     #print STDERR "substitute_texi_line $text\n";
19270     my @text = substitute_text({'structure' => 1}, $text);
19271     my @result = ();
19272     while (@text)
19273     {
19274         push @result,  split (/\n/, shift (@text));
19275     }
19276     return '' unless (@result);
19277     my $result = shift @result;
19278     return $result . "\n" unless (@result);
19279     foreach my $line (@result)
19280     {
19281         chomp $line;
19282         $result .= ' ' . $line;
19283     }
19284     return $result . "\n";
19285 }
19286
19287 sub print_lines($;$)
19288 {
19289     my ($fh, $lines) = @_;
19290     $lines = $Texi2HTML::THIS_SECTION unless $lines;
19291     my @cnt;
19292     my $cnt;
19293     for my $line (@$lines)
19294     {
19295         print $fh $line;
19296         if (defined($Texi2HTML::Config::WORDS_IN_PAGE) and ($Texi2HTML::Config::SPLIT eq 'node'))
19297         {
19298             @cnt = split(/\W*\s+\W*/, $line);
19299             $cnt += scalar(@cnt);
19300         }
19301     }
19302     return $cnt;
19303 }
19304
19305 sub do_index_entry_label($$$)
19306 {
19307     my $command = shift;
19308     my $state = shift;
19309     my $line_nr = shift;
19310     return '' if ($state->{'multiple_pass'});
19311     my $entry = shift @index_labels;
19312     if (!defined($entry))
19313     {
19314         echo_warn ("Not enough index entries !", $line_nr);
19315         return '';
19316     }
19317     if ($command ne $entry->{'command'})
19318     {
19319         # happens with bad texinfo with a line like
19320         # @deffn func aaaa args  @defvr c--ategory d--efvr_name
19321         echo_warn ("Waiting for index cmd \@$entry->{'command'}, got \@$command", $line_nr);
19322     }
19323     
19324     print STDERR "[(index $command) $entry->{'entry'} $entry->{'label'}]\n"
19325         if ($T2H_DEBUG & $DEBUG_INDEX);
19326     return &$Texi2HTML::Config::index_entry_label ($entry->{'label'}, $state->{'preformatted'}, substitute_line($entry->{'entry'}), 
19327       $index_prefix_to_name{$prefix},
19328        $command); 
19329 }
19330
19331 # decompose a decimal number on a given base. The algorithm looks like
19332 # the division with growing powers (division suivant les puissances
19333 # croissantes) ?
19334 sub decompose($$)
19335 {  
19336     my $number = shift;
19337     my $base = shift;
19338     my @result = ();
19339
19340     return (0) if ($number == 0);
19341     my $power = 1;
19342     my $remaining = $number;
19343
19344     while ($remaining)
19345     {
19346          my $factor = $remaining % ($base ** $power);
19347          $remaining -= $factor;
19348          push (@result, $factor / ($base ** ($power - 1)));
19349          $power++;
19350     }
19351     return @result;
19352 }
19353
19354 # main processing is called here
19355 set_document_language('en') unless ($lang_set);
19356 # APA: There's got to be a better way:
19357 $T2H_USER = &$I('unknown');
19358
19359 if ($Texi2HTML::Config::TEST)
19360 {
19361     # to generate files similar to reference ones to be able to check for
19362     # real changes we use these dummy values if -test is given
19363     $T2H_USER = 'a tester';
19364     $THISPROG = 'texi2html';
19365     setlocale( LC_ALL, "C" );
19366
19367 else
19368
19369     # the eval prevents this from breaking on system which do not have
19370     # a proper getpwuid implemented
19371     eval { ($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//;}; # Who am i
19372     # APA: Provide Windows NT workaround until getpwuid gets
19373     # implemented there.
19374     $T2H_USER = $ENV{'USERNAME'} unless defined $T2H_USER;
19375 }
19376     
19377 open_file($docu, $texi_line_number);
19378 #Texi2HTML::LaTeX2HTML::init() if ($Texi2HTML::Config::L2H);
19379 if ($Texi2HTML::Config::L2H)
19380 {
19381    push @Texi2HTML::Config::command_handler_init, \&Texi2HTML::LaTeX2HTML::init;
19382    push @Texi2HTML::Config::command_handler_process, \&Texi2HTML::LaTeX2HTML::latex2html;
19383    push @Texi2HTML::Config::command_handler_finish, \&Texi2HTML::LaTeX2HTML::finish;
19384    $Texi2HTML::Config::command_handler{'math'} = 
19385      { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, 
19386        'expand' => \&Texi2HTML::LaTeX2HTML::do_tex
19387      };
19388    $Texi2HTML::Config::command_handler{'tex'} = 
19389      { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, 
19390        'expand' => \&Texi2HTML::LaTeX2HTML::do_tex
19391      };
19392 }
19393 foreach my $handler(@Texi2HTML::Config::command_handler_init)
19394 {
19395     &$handler;
19396 }
19397
19398 my @css_import_lines;
19399 my @css_rule_lines;
19400
19401 # process css files
19402 foreach my $file (@Texi2HTML::Config::CSS_FILES)
19403 {
19404     my $css_file_fh;
19405     my $css_file;
19406     if ($file eq '-')
19407     {
19408         $css_file_fh = \*STDIN;
19409         $css_file = '-';
19410     }
19411     else
19412     {
19413          $css_file = locate_init_file ($file);
19414          unless (defined($css_file))
19415          {
19416              warn "css file $file not found\n";
19417              next;
19418          }
19419          unless (open (CSSFILE, "$css_file"))
19420          {
19421              warn "Cannot open ${css_file}: $!";
19422              next;
19423         }
19424         $css_file_fh = \*CSSFILE;
19425     }
19426     my ($import_lines, $rules_lines);
19427     ($import_lines, $rules_lines) = process_css_file ($css_file_fh, $css_file);
19428     push @css_import_lines, @$import_lines;
19429     push @css_rule_lines, @$rules_lines;
19430 }
19431
19432 $Texi2HTML::THISDOC{'css_import_lines'} = \@css_import_lines;
19433 $Texi2HTML::THISDOC{'css_lines'} = \@css_rule_lines;
19434
19435 if ($T2H_DEBUG & $DEBUG_USER)
19436 {
19437     if (@css_import_lines)
19438     {
19439         print STDERR "# css import lines\n";
19440         foreach my $line (@css_import_lines)
19441         {
19442             print STDERR "$line";
19443         }
19444     }
19445     if (@css_rule_lines)
19446     {
19447         print STDERR "# css rule lines\n";
19448         foreach my $line (@css_rule_lines)
19449         {
19450             print STDERR "$line";
19451         }
19452     }
19453 }
19454
19455 pass_texi();
19456 dump_texi(\@lines, 'texi', \@lines_numbers) if ($T2H_DEBUG & $DEBUG_TEXI);
19457 if (defined($Texi2HTML::Config::MACRO_EXPAND))
19458 {
19459     my @texi_lines = (@first_lines, @lines);
19460     dump_texi(\@texi_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND);
19461 }
19462 pass_structure();
19463 if ($T2H_DEBUG & $DEBUG_TEXI)
19464 {
19465     dump_texi(\@doc_lines, 'first', \@doc_numbers);
19466     if (defined($Texi2HTML::Config::MACRO_EXPAND and $Texi2HTML::Config::DUMP_TEXI))
19467     {
19468         unshift (@doc_lines, @first_lines);
19469         push (@doc_lines, "\@bye\n");
19470         dump_texi(\@doc_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND . ".first");
19471     }
19472 }
19473 exit(0) if ($Texi2HTML::Config::DUMP_TEXI or defined($Texi2HTML::Config::MACRO_EXPAND));
19474
19475 foreach my $style (keys(%special_commands))
19476 {
19477   $special_commands{$style}->{'max'} = $special_commands{$style}->{'count'};
19478 }
19479
19480 rearrange_elements();
19481 do_names();
19482
19483 #Texi2HTML::LaTeX2HTML::latex2html();
19484 foreach my $handler(@Texi2HTML::Config::command_handler_process)
19485 {
19486     &$handler;
19487 }
19488
19489 if (@{$region_lines{'documentdescription'}} and (!defined($Texi2HTML::Config::DOCUMENT_DESCRIPTION)))
19490 {
19491     my $documentdescription = remove_texi(@{$region_lines{'documentdescription'}}); 
19492     my @documentdescription = split (/\n/, $documentdescription);
19493     $Texi2HTML::Config::DOCUMENT_DESCRIPTION = shift @documentdescription;
19494     chomp $Texi2HTML::Config::DOCUMENT_DESCRIPTION;
19495     foreach my $line (@documentdescription)
19496     {
19497         chomp $line;
19498         $Texi2HTML::Config::DOCUMENT_DESCRIPTION .= ' ' . $line;
19499     }
19500 }
19501 # do copyright notice inserted in comment at the beginning of the files
19502 if (@{$region_lines{'copying'}})
19503 {
19504     $copying_comment = &$Texi2HTML::Config::copying_comment($region_lines{'copying'});
19505 }
19506 &$Texi2HTML::Config::toc_body(\@elements_list);
19507 $sec_num = 0;
19508
19509
19510 &$Texi2HTML::Config::css_lines(\@css_import_lines, \@css_rule_lines);
19511
19512 pass_text();
19513 print STDERR "BUG: " . scalar(@index_labels) . " index entries pending\n" 
19514    if (scalar(@index_labels));
19515 foreach my $special (keys(%special_commands))
19516 {
19517     my $count = $special_commands{$special}->{'count'};
19518     if (($count != 0) and $T2H_VERBOSE)
19519     {
19520          echo_warn ("$count special \@$special were not processed.\n");
19521     }
19522 }
19523 if ($Texi2HTML::Config::IDX_SUMMARY)
19524 {
19525     foreach my $entry (keys(%index_names))
19526     {
19527          do_index_summary_file($entry) unless ($empty_indices{$entry});
19528     }
19529 }
19530 do_node_files() if ($Texi2HTML::Config::NODE_FILES);
19531 #l2h_FinishFromHtml() if ($Texi2HTML::Config::L2H);
19532 #l2h_Finish() if($Texi2HTML::Config::L2H);
19533 #Texi2HTML::LaTeX2HTML::finish();
19534 foreach my $handler(@Texi2HTML::Config::command_handler_finish)
19535 {
19536     &$handler;
19537 }
19538 &$Texi2HTML::Config::finish_out();
19539 print STDERR "# that's all folks\n" if $T2H_VERBOSE;
19540
19541 exit(0);
19542
19543
19544 ##############################################################################
19545
19546 # These next few lines are legal in both Perl and nroff.
19547
19548 .00 ;                           # finish .ig
19549
19550 'di                     \" finish diversion--previous line must be blank
19551 .nr nl 0-1              \" fake up transition to first page again
19552 .nr % 0                 \" start at page 1
19553 '; __END__ ############# From here on it's a standard manual page ############
19554     .so ${prefix}/man/man1/texi2html.1