1 #! /usr/bin/perl -- # perl
4 #+##############################################################################
6 # texi2html: Program to transform Texinfo documents to HTML
8 # Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>,
9 # Derek Price <derek@ximbiot.com>,
10 # Adrian Aichner <adrian@xemacs.org>,
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.
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.
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
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'.
32 # for POSIX::setlocale and File::Spec
34 # Perl pragma to restrict unsafe constructs
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
40 # used to find a relative path back to the current working directory
45 # larry.jones@sdrc.com (Larry Jones)
46 # this pragma is not present in perl5.004_02:
48 # Perl pragma to control optional warnings
51 #++##########################################################################
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,
59 #--##########################################################################
62 # $Id: texi2html.pl,v 1.182 2007/05/07 22:56:02 pertusus Exp $
65 my $T2H_HOMEPAGE = "http://www.nongnu.org/texi2html/";
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>
73 Maintained by: Many creative people.
74 Send bugs and suggestions to <texi2html-bug\@nongnu.org>
77 # Version: set in configure.in
78 my $THISVERSION = '1.78a';
79 my $THISPROG = "texi2html $THISVERSION"; # program name and version
81 #+++########################################################################
83 # Paths and file names #
85 #---########################################################################
87 # set by configure, prefix for the sysconfdir and so on
88 my $prefix = '/usr/local';
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@')
98 $sysconfdir = eval '"${prefix}/etc"';
102 $sysconfdir = "/usr/local/etc";
105 if ('${prefix}/share' ne '@' . 'datadir@')
107 $pkgdatadir = eval '"${prefix}/share/texi2html"';
108 $datadir = eval '"${prefix}/share"';
112 $pkgdatadir = "/usr/local/share/texi2html";
113 $datadir = "/usr/local/share";
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';
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));
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));
133 #+++########################################################################
137 #---########################################################################
142 my $DEBUG_MACROS = 8;
143 my $DEBUG_FORMATS = 16;
144 my $DEBUG_ELEMENTS = 32;
148 my $ERROR = "***"; # prefix for errors
149 my $WARN = "**"; # prefix for warnings
151 my $VARRE = '[\w\-]+'; # RE for a variable name
152 my $NODERE = '[^:]+'; # RE for node names
157 #+++###########################################################################
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 #
164 #---###########################################################################
167 package Texi2HTML::Config;
173 eval { require($file) ;};
176 print STDERR "error loading $file: $@\n";
182 # customization options variables
215 $AVOID_MENU_REDUNDANCY
238 $IGNORE_PREAMBLE_TEXT
243 # customization variables
244 # ENCODING is deprecated
256 $SMALL_EXAMPLE_INDENT_CELL
265 $HREF_DIR_INSTEAD_FILE
270 $VERTICAL_HEAD_NAVIGATION
273 $UNNUMBERED_SYMBOL_IN_MENU
300 @SECTION_FOOTER_BUTTONS
305 # customization variables which may be guessed in the script
310 $DOCUMENT_DESCRIPTION
311 $EXTERNAL_CROSSREF_SPLIT
320 # customizable subroutines references
335 $print_section_header
336 $print_section_footer
337 $print_chapter_header
338 $print_chapter_footer
341 $print_head_navigation
342 $print_foot_navigation
351 $print_redirection_page
403 $index_summary_file_entry
404 $index_summary_file_end
405 $index_summary_file_begin
413 $caption_shortcaption
416 $listoffloats_caption
417 $listoffloats_float_style
421 $quotation_prepend_text
422 $paragraph_style_command
424 $index_element_heading_texi
430 # hash which entries might be redefined by the user
442 %simple_format_simple_map_texi
443 %simple_format_style_map_texi
444 %simple_format_texi_map
453 %transliterate_accent_map
454 %no_transliterate_map
459 %perl_charset_to_html
464 %special_list_commands
468 @command_handler_init
469 @command_handler_process
470 @command_handler_finish
474 # needed in this namespace for translations
475 $I = \&Texi2HTML::I18n::get_string;
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).
484 $toc_body = \&T2H_GPL_toc_body;
485 $style = \&T2H_GPL_style;
486 $format = \&T2H_GPL_format;
488 sub T2H_GPL_toc_body($)
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)
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)
502 while ($level > $current_level)
505 my $ln = "\n$ind<ul${ul_style}>\n";
506 $ind = ' ' x $current_level;
507 push(@{$Texi2HTML::TOC_LINES}, $ln);
510 elsif ($level < $current_level)
512 while ($level < $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");
524 push(@{$Texi2HTML::TOC_LINES}, "</li>\n");
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);
534 while (0 < $current_level)
537 my $ind = ' ' x $current_level;
538 push(@{$Texi2HTML::TOC_LINES}, "</li>\n$ind</ul>\n");
540 @{$Texi2HTML::TOC_LINES} = () unless ($DO_CONTENTS);
541 if (@{$Texi2HTML::TOC_LINES})
543 unshift @{$Texi2HTML::TOC_LINES}, $BEFORE_TOC_LINES;
544 push @{$Texi2HTML::TOC_LINES}, $AFTER_TOC_LINES;
546 @{$Texi2HTML::OVERVIEW} = () unless ($DO_SCONTENTS or $FRAMES);
547 if (@{$Texi2HTML::OVERVIEW})
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;
556 sub T2H_GPL_style($$$$$$$$$)
562 my $no_close = shift;
566 my $style_stack = shift;
569 my $use_attribute = 0;
570 my $use_begin_end = 0;
571 if (ref($style) eq 'HASH')
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'}))
578 $style = $style->{'attribute'};
582 elsif (defined($style->{'function'}))
584 $text = &{$style->{'function'}}($command, $args, $style_stack, $state, $line_nr);
589 if ($style =~ s/^\"//)
593 if ($style =~ s/^\&//)
595 $style = 'Texi2HTML::Config::' . $style;
596 eval "\$text = &$style(\$text, \$command, \$style_stack)";
608 my $attribute_text = '';
609 if ($style =~ /^(\w+)(\s+.*)/)
612 $attribute_text = $2;
614 # $text = "<${style}$attribute_text>$text</$style>" ;
615 $text = "<${style}$attribute_text>" . "$text" if (!$no_open);
616 $text .= "</$style>" if (!$no_close);
619 $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
620 $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
623 if (ref($style) eq 'HASH')
625 if (defined($style->{'begin'}) and !$no_open)
627 $text = $style->{'begin'} . $text;
629 if (defined($style->{'end'}) and !$no_close)
631 $text = $text . $style->{'end'};
634 if ($do_quotes and !$use_attribute)
636 $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open);
637 $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close);
642 sub T2H_GPL_format($$$)
647 return '' if (!defined($element) or ($text !~ /\S/));
648 return $text if ($element eq '');
649 my $attribute_text = '';
650 if ($element =~ /^(\w+)(\s+.*)/)
653 $attribute_text = $2;
655 return "<${element}$attribute_text>\n" . $text. "</$element>\n";
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.
664 ######################################################################
665 # File: texi2html.init
667 # Default values for command-line arguments and for various customizable
668 # procedures are set in this file.
670 # A copy of this file is pasted into the beginning of texi2html by
671 # running './configure'.
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>
677 # $Id: texi2html.init,v 1.116 2007/05/07 22:56:02 pertusus Exp $
679 ######################################################################
680 # The following variables can also be set by command-line options
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.
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.
695 # The integer value specifies what kind of debugging output is generated.
699 # The value is the 'SystemLiteral' which identifies the canonical DTD
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">';
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">';
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.
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.
725 # the @EXPAND array contains the expanded section names.
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 = ' ';
736 # if this value is true, ISO8859 characters are used for special symbols
737 # (like copyright, etc).
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 = (".");
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.
755 # append to the files searched for init files.
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".
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.
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.
778 # if the value is true the Texinfo menus are shown.
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;
787 # if this is set the nodes are used as sectionning elements.
788 # Otherwise the nodes are incorporated in sections.
792 # if this is set one file per node is generated, which can be a target for
793 # cross manual references.
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
806 # -sec-nav|-nosec-nav
807 # if this is set then navigation panels are printed at the beginning of each
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.
812 # If the document is split at sections this is ignored.
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;
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;
825 # if this is set, links from headings to toc entries are created.
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.
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.
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.
845 # If this is set a monolithic document is outputted into $filename.
849 # suppress node cross-reference validation
853 # if this is set cross-references are given without section numbers.
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).
863 # If this is set a table construction for @def.... instead of definition
865 # (New Option: 27.07.2000 Karl Heinz Marbaise)
869 # if this is set chatter about what we are doing.
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'
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
880 # Default's to 'en' if not set or no @documentlanguage is specified.
883 # -ignore-preamble-text
884 # If this is set the text before @node and sectionning commands is ignored.
885 $IGNORE_PREAMBLE_TEXT = 0;
888 # base directory for external manuals.
889 #$EXTERNAL_DIR = '../';
890 $EXTERNAL_DIR = undef;
893 # if this is set, latex2html is used for generation of math content.
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.
904 ######################
905 # The following options are only relevant if $L2H is set
908 # name/location of latex2html program
909 $L2H_L2H = "latex2html";
912 # If this is set the actual call to latex2html is skipped. The previously
913 # generated content is reused, instead.
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.
923 # If set, l2h uses the file as latex2html init file
924 $L2H_FILE = 'l2h.init';
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_).
931 ##############################################################################
933 # The following can only be set in the init file
935 ##############################################################################
937 # If true do table of contents even if there is no @content
940 # If true do short table of contents even if there is no @shortcontent
943 # if set, output the contents where the command is located
944 $INLINE_CONTENTS = 1;
946 # if this variable is true, numeric entities are used when there is no
947 # corresponding textual entity.
948 $USE_NUMERIC_ENTITY = 1;
950 # if set, then use node names in menu entries, instead of section names
951 $NODE_NAME_IN_MENU = 0;
953 # new style for crossrefs
954 $NEW_CROSSREF_STYLE = 1;
956 # transliterate node names for external refs (and internal if NODE_FILES)
957 $TRANSLITERATE_NODE = 1;
959 # if set and menu entry equals menu description, then do not print
961 # Likewise, if node name equals entry name, do not print entry name.
962 $AVOID_MENU_REDUNDANCY = 1;
964 # if set, center @image by default
965 # otherwise, do not center by default
966 # Deprecated and not used anymore
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> </td>';
973 # same as above, only for @small
974 $SMALL_EXAMPLE_INDENT_CELL = '<td> </td>';
976 # font size for @small
977 $SMALL_FONT_SIZE = '-1';
980 $SMALL_RULE = '<hr size="1">';
981 $DEFAULT_RULE = '<hr>';
982 $MIDDLE_RULE = '<hr size="2">';
983 $BIG_RULE = '<hr size="6">';
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)
990 # if set, use this chapter for 'Index' button, else
991 # use first chapter with @printindex
994 # if set and $SPLIT is set, then split index pages at the next letter
995 # after they have more than that many entries
998 # symbol put at the beginning of nodes entry in menu (and optionnaly of
999 # unnumbered in menus, see next variable)
1000 $MENU_SYMBOL = '•';
1001 #$MENU_SYMBOL = '*';
1005 $OPEN_QUOTE_SYMBOL = "\`";
1006 $CLOSE_QUOTE_SYMBOL = "'";
1008 # if true put a $MENU_SYMBOL before unnumbered in menus
1009 $UNNUMBERED_SYMBOL_IN_MENU = 0;
1011 # extension for nodes files when NODE_FILES is true
1012 $NODE_FILE_EXTENSION = "html";
1015 $EXTENSION = "html";
1017 # file name used for Top node when NODE_FILES is true
1018 $TOP_NODE_FILE = "index";
1020 # node name used for Top node when automatic node directions are used
1021 $TOP_NODE_UP = '(dir)';
1023 # this controls the pre style for menus
1024 $MENU_PRE_STYLE = 'font-family: serif';
1026 # This controls the ul style for toc
1027 $TOC_LIST_STYLE = 'list-style: none';
1028 $TOC_LIST_ATTRIBUTE = ' class="toc"';
1030 # These lines are inserted before and after the shortcontents
1031 $BEFORE_OVERVIEW = "<div class=\"shortcontents\">\n";
1032 $AFTER_OVERVIEW = "</div>\n";
1034 # These lines are inserted before and after the contents
1035 $BEFORE_TOC_LINES = "<div class=\"contents\">\n";
1036 $AFTER_TOC_LINES = "</div>\n";
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 = '';
1043 # text inserted after <body ...>
1044 $AFTER_BODY_OPEN = '';
1046 # text inserted before </body>, this will be automatically inside <p></p>
1047 $PRE_BODY_CLOSE = '';
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.
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;
1059 # if this is set a vertical navigation panel is used.
1060 $VERTICAL_HEAD_NAVIGATION = 0;
1062 # html version for latex2html
1063 $L2H_HTML_VERSION = "4.0";
1065 # use the information given by menus to complete the node directions
1066 $USE_MENU_DIRECTIONS = 1;
1068 # specify in this array which "buttons" should appear in which order
1069 # in the navigation panel for sections; use ' ' for empty buttons (space)
1072 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1074 'Top', 'Contents', 'Index', 'About',
1077 # buttons for misc stuff
1078 @MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About');
1080 # buttons for chapter file footers
1081 # (and headers but only if SECTION_NAVIGATION is false)
1084 'FastBack', 'FastForward', ' ',
1086 'Top', 'Contents', 'Index', 'About',
1089 # buttons for section file footers
1090 @SECTION_FOOTER_BUTTONS =
1092 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1095 @NODE_FOOTER_BUTTONS =
1097 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward',
1099 'Top', 'Contents', 'Index', 'About',
1100 # 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward'
1105 # insert here name of icon images for buttons
1106 # Icons are used, if $ICONS and resp. value are set
1131 # insert here name of icon images for these, if button is inactive
1155 @IMAGE_EXTENSIONS = ('png','jpg','jpeg','gif');
1157 $init_out = \&t2h_default_init_out;
1158 $finish_out = \&t2h_default_finish_out;
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()
1164 # Names of text as alternative for icons
1165 # FIXME maybe get those in simple_format?
1169 'Contents', &$I('Contents'),
1170 'Overview', &$I('Overview'),
1171 'Index', &$I('Index'),
1173 'This', &$I('current'),
1175 'FastBack', ' << ',
1176 'Prev', &$I('Prev'),
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', ' > ',
1184 'FastForward', ' >> ',
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'),
1216 'Contents', &$I('Contents'),
1217 'Overview', &$I('Overview'),
1218 'Index', &$I('Index'),
1220 'This', &$I('This'),
1221 'Back', &$I('Back'),
1222 'FastBack', &$I('FastBack'),
1223 'Prev', &$I('Prev'),
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'),
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))
1243 $EXTERNAL_CROSSREF_SPLIT = 1;
1247 $EXTERNAL_CROSSREF_SPLIT = 0;
1251 $ENCODING_NAME = $ENCODING if (!defined($ENCODING_NAME) and
1252 defined($ENCODING));
1254 if (!defined($OUT_ENCODING) and (defined($ENCODING_NAME)))
1256 $OUT_ENCODING = main::encoding_alias ($ENCODING_NAME);
1257 $OUT_ENCODING = $ENCODING_NAME if (!defined($OUT_ENCODING));
1259 if (!defined($OUT_ENCODING) and (defined($IN_ENCODING)))
1261 $OUT_ENCODING = $IN_ENCODING;
1263 if (!defined($OUT_ENCODING) and (defined($DOCUMENT_ENCODING)))
1265 $OUT_ENCODING = main::encoding_alias ($DOCUMENT_ENCODING);
1266 $OUT_ENCODING = $DOCUMENT_ENCODING if (!defined($OUT_ENCODING));
1269 if (!defined($ENCODING_NAME))
1271 if (defined($OUT_ENCODING) and defined($perl_charset_to_html{$OUT_ENCODING}))
1273 $ENCODING_NAME = $perl_charset_to_html{$OUT_ENCODING};
1275 elsif (defined($IN_ENCODING) and defined($perl_charset_to_html{$IN_ENCODING}))
1277 $ENCODING_NAME = $perl_charset_to_html{$IN_ENCODING};
1279 elsif (defined($DOCUMENT_ENCODING) and defined($perl_charset_to_html{$DOCUMENT_ENCODING}))
1281 $ENCODING_NAME = $perl_charset_to_html{$DOCUMENT_ENCODING};
1283 elsif (defined($OUT_ENCODING))
1285 $ENCODING_NAME = $OUT_ENCODING;
1287 elsif (defined($IN_ENCODING))
1289 $ENCODING_NAME = $IN_ENCODING;
1291 elsif (defined($DOCUMENT_ENCODING))
1293 $ENCODING_NAME = $DOCUMENT_ENCODING;
1295 elsif (defined($perl_charset_to_html{$DEFAULT_ENCODING}))
1297 $ENCODING_NAME = $perl_charset_to_html{$DEFAULT_ENCODING};
1301 $ENCODING_NAME = 'us-ascii';
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);
1312 if ($SIMPLE_MENU and !defined($complex_format_map->{'menu'}))
1314 $complex_format_map->{'menu'} = { 'begin' => q{''} , 'end' => q{''},
1315 'pre_style' => "$MENU_PRE_STYLE", 'class' => 'menu-preformatted' };
1318 return $OUT_ENCODING;
1321 sub t2h_default_finish_out()
1325 #######################################################################
1327 # Values guessed if not set here, set in init_out
1329 #######################################################################
1333 # default used in init_out for the setting of the ENCODING_NAME variable
1334 $DEFAULT_ENCODING = 'utf8';
1336 # In file encoding. The @documentencoding overrides that variable.
1337 $DOCUMENT_ENCODING = undef;
1339 # In file encoding, understandable by perl. Set according to DOCUMENT_ENCODING
1340 $IN_ENCODING = undef;
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;
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;
1350 # if undef set to @documentdescription. If there is no @documentdescription,
1352 $DOCUMENT_DESCRIPTION = undef;
1354 # if undef set 1 if SPLIT, to 0 otherwise
1355 $EXTERNAL_CROSSREF_SPLIT = undef;
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
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
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
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
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
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
1426 # $Texi2HTML::THIS_ELEMENT holds the element reference.
1429 # There are the following subs which control the layout:
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;
1464 ########################################################################
1465 # Layout for html for every sections
1467 sub T2H_DEFAULT_print_section
1470 my $first_in_page = shift;
1471 my $previous_is_top = shift;
1472 my $buttons = \@SECTION_BUTTONS;
1474 if ($first_in_page and $SECTION_NAVIGATION)
1476 &$print_head_navigation($fh, $buttons);
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);
1483 my $nw = main::print_lines($fh);
1485 and (($SPLIT eq 'node') && $SECTION_NAVIGATION))
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));
1494 sub T2H_DEFAULT_one_section($)
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);
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
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($$)
1516 my $do_page_head = shift;
1517 &$print_page_head($fh) if ($do_page_head);
1519 sub T2H_DEFAULT_print_Top_footer($$)
1522 my $end_page = shift;
1523 my $buttons = \@MISC_BUTTONS;
1524 &$print_foot_navigation($fh);
1525 print $fh "$SMALL_RULE\n";
1528 &$print_navigation($fh, $buttons);
1529 &$print_page_foot($fh);
1532 sub T2H_DEFAULT_print_Top($$)
1535 my $has_top_heading = shift;
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);
1543 if (@$Texi2HTML::THIS_SECTION)
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);
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'})
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";
1562 elsif (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::THISDOC{'setcontentsaftertitlepage'})
1564 print $fh '<h1> ' . $Texi2HTML::NAME{'Contents'} . "</h1>\n";
1565 my $nw = main::print_lines($fh, $Texi2HTML::TOC_LINES);
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
1577 return &$print_misc(@_);
1579 sub T2H_DEFAULT_print_Overview
1581 return &$print_misc(@_);
1583 sub T2H_DEFAULT_print_Footnotes
1585 return &$print_misc(@_);
1587 sub T2H_DEFAULT_print_About
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);
1594 sub T2H_DEFAULT_print_misc_header
1597 my $buttons = shift;
1598 &$print_page_head($fh) if $SPLIT;
1599 &$print_head_navigation($fh, $buttons) if ($SPLIT or $SECTION_NAVIGATION);
1602 sub T2H_DEFAULT_print_misc_footer
1605 my $buttons = shift;
1607 &$print_foot_navigation($fh, $buttons);
1608 print $fh "$SMALL_RULE\n";
1611 &$print_navigation($fh, $buttons);# if ($SPLIT ne 'node');
1612 &$print_page_foot($fh);
1616 sub T2H_DEFAULT_print_misc
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);
1625 ##################################################################
1626 # section_footer is only called if SPLIT eq 'section'
1627 # section_footer: after print_section of last section, before print_page_foot
1630 sub T2H_DEFAULT_print_section_footer
1633 my $buttons = \@SECTION_FOOTER_BUTTONS;
1634 &$end_section ($fh, 1);
1635 &$print_navigation($fh, $buttons);
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
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
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.
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";
1661 sub T2H_DEFAULT_print_chapter_footer
1664 my $buttons = \@CHAPTER_BUTTONS;
1665 &$print_foot_navigation($fh);
1666 print $fh "$BIG_RULE\n";
1667 &$print_navigation($fh, $buttons);
1670 sub T2H_DEFAULT_print_section_header
1672 # nothing to do there, by default
1673 if (! $SECTION_NAVIGATION)
1674 { # in this case print_navigation is called here.
1676 my $buttons = \@SECTION_BUTTONS;
1677 &$print_head_navigation($fh, $buttons);
1681 ###################################################################
1682 # Layout of standard header and footer
1685 sub T2H_DEFAULT_print_page_head($)
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 '');
1695 $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING_NAME\">" if (defined($ENCODING_NAME) and ($ENCODING_NAME ne ''));
1699 $Texi2HTML::THISDOC{'copying'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program} -->
1701 $Texi2HTML::THISDOC{program_authors}
1704 <title>$longtitle</title>
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}">
1721 sub program_string()
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 ''))
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'} });
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'} });
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'} });
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'} });
1747 sub T2H_DEFAULT_end_section($$)
1750 my $end_foot_navigation = shift;
1751 &$print_foot_navigation($fh) if ($end_foot_navigation);
1752 print $fh "$BIG_RULE\n";
1755 sub T2H_DEFAULT_print_page_foot($)
1758 my $program_string = program_string();
1772 ###################################################################
1773 # Layout of navigation panel
1775 sub T2H_DEFAULT_print_head_navigation($$)
1778 my $buttons = shift;
1779 if ($VERTICAL_HEAD_NAVIGATION)
1782 <table border="0" cellpadding="0" cellspacing="0">
1787 main::print_lines($fh, $Texi2HTML::THIS_HEADER);
1788 &$print_navigation($fh, $buttons, $VERTICAL_HEAD_NAVIGATION);
1789 if ($VERTICAL_HEAD_NAVIGATION)
1796 elsif (defined $SPLIT
1797 and ($SPLIT eq 'node'))
1799 print $fh "$SMALL_RULE\n";
1803 sub T2H_DEFAULT_print_foot_navigation
1806 if ($VERTICAL_HEAD_NAVIGATION)
1816 ######################################################################
1819 # how to create IMG tag
1820 sub T2H_DEFAULT_button_icon_img
1825 return '' if (!defined($icon));
1826 $button = "" if (!defined ($button));
1827 $name = '' if (!defined($name));
1833 $alt = "$button: $name";
1844 return qq{<img src="$icon" border="0" alt="$alt" align="middle">};
1847 sub T2H_DEFAULT_print_navigation
1850 my $buttons = shift;
1851 my $vertical = shift;
1853 print $fh '<table cellpadding="', $spacing, '" cellspacing="', $spacing,
1854 "\" border=\"0\">\n";
1856 print $fh "<tr>" unless $vertical;
1857 for my $button (@$buttons)
1859 print $fh qq{<tr valign="top" align="left">\n} if $vertical;
1860 print $fh qq{<td valign="middle" align="left">};
1862 if (ref($button) eq 'CODE')
1864 &$button($fh, $vertical);
1866 elsif (ref($button) eq 'SCALAR')
1868 print $fh "$$button" if defined($$button);
1870 elsif (ref($button) eq 'ARRAY')
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))
1878 if ($Texi2HTML::HREF{$button_href})
1882 $Texi2HTML::HREF{$button_href},
1893 elsif ($button eq ' ')
1894 { # handle space button
1896 ($ICONS && $ACTIVE_ICONS{' '}) ?
1897 &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) :
1898 $NAVIGATION_TEXT{' '};
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})
1909 $Texi2HTML::HREF{$button},
1910 &$button_icon_img($BUTTONS_NAME{$button},
1911 $ACTIVE_ICONS{$button},
1912 $Texi2HTML::SIMPLE_TEXT{$button}),
1921 $Texi2HTML::HREF{$button},
1922 $NAVIGATION_TEXT{$button},
1929 { # button is passive
1931 $ICONS && $PASSIVE_ICONS{$button} ?
1932 &$button_icon_img($BUTTONS_NAME{$button},
1933 $PASSIVE_ICONS{$button},
1934 $Texi2HTML::SIMPLE_TEXT{$button}) :
1936 "[" . $NAVIGATION_TEXT{$button} . "]";
1938 print $fh "</td>\n";
1939 print $fh "</tr>\n" if $vertical;
1941 print $fh "</tr>" unless $vertical;
1942 print $fh "</table>\n";
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 ?
1950 sub T2H_DEFAULT_print_frame
1953 my $toc_file = shift;
1954 my $main_file = shift;
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">
1967 sub T2H_DEFAULT_print_toc_frame
1970 my $stoc_lines = shift;
1971 &$print_page_head($fh);
1975 print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines;
1976 print $fh "</body></html>\n";
1979 # This subroutine is intended to fill @Texi2HTML::TOC_LINES and
1980 # @Texi2HTML::OVERVIEW with the table of contents and short table of
1984 # ref on an array containing all the elements
1986 # each element is a reference on a hash. The following keys might be of
1988 # 'top': true if this is the top element
1989 # 'index_page': true if the element is an index page added because of index
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
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
2001 # Relevant configuration variables are:
2003 # $TOC_LIST_ATTRIBUTE: usefull in case a list is used
2004 # $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames.
2012 sub T2H_DEFAULT_toc_body($)
2016 sub T2H_DEFAULT_inline_contents($$$)
2019 my $command = shift;
2020 my $element = shift;
2026 if ($command eq 'contents')
2028 $name = $Texi2HTML::NAME{'Contents'};
2029 $lines = $Texi2HTML::TOC_LINES;
2033 $name = $Texi2HTML::NAME{'Overview'};
2034 $lines = $Texi2HTML::OVERVIEW;
2038 $result = [ "".&$anchor($element->{'id'})."\n",
2039 "<h1>$name</h1>\n" ];
2040 push @$result, @$lines;
2046 sub T2H_DEFAULT_css_lines ($$)
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)))
2055 next unless ($css_map{$css_rule});
2056 $CSS_LINES .= "$css_rule {$css_map{$css_rule}}\n";
2058 $CSS_LINES .= join('',@$rule_lines) . "\n" if (@$rule_lines);
2059 $CSS_LINES .= "-->\n</style>\n";
2062 ######################################################################
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.
2071 return ' ' . program_string() . "\n";
2074 # If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>.
2080 'Contents', ' ',
2081 'Overview', ' ',
2082 'Index', ' ',
2090 'NodeNext', '1.2.4',
2091 'NodePrev', '1.2.2',
2092 'Following', '1.2.4',
2095 'About', ' ',
2100 sub T2H_DEFAULT_about_body
2102 my $about = "<p>\n";
2103 if (ref($PRE_ABOUT) eq 'CODE')
2105 $about .= &$PRE_ABOUT();
2109 $about .= $PRE_ABOUT;
2115 $about .= &$I(' The buttons in the navigation panels have the following meaning:') . "\n";
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";
2126 for my $button (@SECTION_BUTTONS)
2128 next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY';
2129 $about .= " <tr>\n <td align=\"center\">";
2131 ($ICONS && $ACTIVE_ICONS{$button} ?
2132 &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) :
2133 ' [' . $NAVIGATION_TEXT{$button} . '] ');
2134 $about .= "</td>\n";
2136 <td align="center">$BUTTONS_NAME{$button}</td>
2137 <td>$BUTTONS_GOTO{$button}</td>
2138 <td>$BUTTONS_EXAMPLE{$button}</td>
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";
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:
2158 $about .= ' <li> 1. ' . &$I('Section One') . "\n" .
2160 ' <li>1.1 ' . &$I('Subsection One-One') . "\n";
2167 $about .= ' <li>1.2 ' . &$I('Subsection One-Two') . "\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') . " \n"
2173 ' <strong><== ' . &$I('Current Position') . " </strong></li>\n" .
2174 ' <li>1.2.4 ' . &$I('Subsubsection One-Two-Four') . "</li>\n" .
2177 ' <li>1.3 ' . &$I('Subsection One-Three') . "\n";
2184 $about .= ' <li>1.4 ' . &$I('Subsection One-Four') . "</li>\n";
2194 sub T2H_DEFAULT_titlepage()
2197 if (@{$Texi2HTML::THISDOC{'titles'}}
2198 or @{$Texi2HTML::THISDOC{'subtitles'}}
2199 or @{$Texi2HTML::THISDOC{'authors'}})
2201 $result = "<div align=\"center\">\n";
2202 foreach my $title (@{$Texi2HTML::THISDOC{'titles'}})
2204 $result .= '<h1>' . $title . "</h1>\n";
2206 foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}})
2208 $result .= '<h2>' . $subtitle . "</h2>\n";
2210 foreach my $author (@{$Texi2HTML::THISDOC{'authors'}})
2212 $result .= '<strong> ' . $author . " </strong><br>\n";
2214 $result .= "</div>\n$DEFAULT_RULE\n";
2217 $Texi2HTML::TITLEPAGE = $result . $Texi2HTML::TITLEPAGE;
2219 if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
2221 foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
2223 $Texi2HTML::TITLEPAGE .= $line;
2225 $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
2227 if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
2229 foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
2231 $Texi2HTML::TITLEPAGE .= $line;
2233 $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
2237 # FIXME Honor DOCUMENT_DESCRIPTION?
2238 sub T2H_DEFAULT_print_redirection_page($)
2241 my $longtitle = "$Texi2HTML::THISDOC{'title_simple_format'}";
2242 $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if exists $Texi2HTML::SIMPLE_TEXT{'This'};
2243 my $description = $longtitle;
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 });
2252 <!-- Created on $Texi2HTML::THISDOC{'today'} by $Texi2HTML::THISDOC{'program'} -->
2254 $Texi2HTML::THISDOC{'program_authors'}
2257 <title>$longtitle</title>
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}">
2266 <meta http-equiv="Refresh" content="2; url=$Texi2HTML::HREF{'This'}">
2277 sub T2H_DEFAULT_node_file_name($$)
2281 return undef if ($node->{'external_node'} or $node->{'index_page'}
2282 or ($type eq 'top' and !$NEW_CROSSREF_STYLE));
2284 if ($type eq 'top' and defined($TOP_NODE_FILE))
2286 $node_file_base = $TOP_NODE_FILE;
2288 elsif ($NEW_CROSSREF_STYLE)
2290 if ($TRANSLITERATE_NODE)
2292 $node_file_base = $node->{'cross_manual_file'};
2296 $node_file_base = $node->{'cross_manual_target'};
2301 $node_file_base = main::remove_texi($node->{'texi'});
2302 $node_file_base =~ s/[^\w\.\-]/-/g;
2304 if (defined($NODE_FILE_EXTENSION) and $NODE_FILE_EXTENSION ne '')
2306 return ($node_file_base . ".$NODE_FILE_EXTENSION");
2308 return $node_file_base;
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).
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 é) associated with a texinfo accent macro.
2329 # The keys of the hash are
2332 # ^: circumflex accent
2346 # texinfo "simple things" (@foo) to HTML ones
2349 "*", "<br>", # HTML+
2353 # "­" or "­" 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
2369 # this map is used in preformatted text
2370 %simple_map_pre = %simple_map;
2371 $simple_map_pre{'*'} = "\n";
2374 # texinfo "things" (@foo{}) to HTML ones
2379 # pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing)
2380 # 'br', '<br>', # paragraph break
2382 # #'copyright' => '(C)',
2383 'copyright' => '©',
2384 'registeredsymbol' => '®',
2385 'dots' => '<small class="dots">...</small>',
2386 'enddots' => '<small class="enddots">....</small>',
2389 'error' => 'error-->',
2390 'expansion' => '==>',
2394 'result' => '=>',
2395 # set in code using the language
2396 # 'today', &pretty_date,
2401 'oe' => 'œ', #pertusus: also œ. œ not in html 3.2
2403 'OE' => 'Œ', #pertusus: also Œ. Œ not in html 3.2
2409 'exclamdown' => '¡',
2410 'questiondown' => '¿',
2411 'pounds' => '£',
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";
2425 # ascii representation of @-commands
2426 %ascii_simple_map = (
2431 '-', '', # hyphenation hint
2432 '|', '', # used in formatting commands @evenfooting and friends
2443 %ascii_things_map = (
2447 'copyright' => '(C)',
2448 'registeredsymbol' => '(R)',
2450 'enddots' => '....',
2453 'error' => 'error-->',
2454 'expansion' => '==>',
2471 'exclamdown' => '?',
2472 'questiondown' => '!',
2482 # This map is used when texi elements are removed and replaced
2485 %simple_map_texi = (
2489 "-", "-", # soft hyphen
2503 # text replacing macros when texi commands are removed and plain text is
2510 'registeredsymbol', 'R',
2514 'error', 'error-->',
2532 'exclamdown', '! upside-down',
2533 #'exclamdown', '¡',
2534 'questiondown', '? upside-down',
2535 #'questiondown', '¿',
2536 'pounds', 'pound sterling',
2537 #'pounds', '£'
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
2551 #http://www.alanwood.net/unicode/latin_extended_a.html
2553 #http://www.alanwood.net/unicode/latin_extended_b.html
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**
2562 'copyright' => '00A9',
2563 'registeredsymbol' => '00AE',
2568 'expansion' => '2192',
2569 'minus' => '2212', # in mathematical operators
2570 # 'minus' => '002D', # in latin1
2586 'exclamdown' => '00A1',
2587 'questiondown' => '00BF',
2597 %transliterate_map = (
2623 '00DD' => 'Y', # unidecode gets this wrong ?
2626 foreach my $symbol(keys(%unicode_map))
2628 if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol}))
2630 $no_transliterate_map{$unicode_map{$symbol}} = 1;
2634 %ascii_character_map = (
2670 %perl_charset_to_html = (
2672 'utf-8-strict' => 'utf-8',
2673 'ascii' => 'us-ascii',
2676 # symbols used for the commands if $USE_ISO is true.
2678 'equiv' => '≡',
2679 'dots' => '…',
2680 'bullet' => '•',
2681 'result' => '⇒',
2682 'expansion' => '→',
2683 'point' => '∗',
2688 # not used currently for html, but used in chm.init
2689 %numeric_entity_map = ();
2691 foreach my $symbol (keys(%unicode_map))
2695 $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';';
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)
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 = (
2712 'ctrl', '&default_ctrl',
2715 'email', '&default_email',
2726 'sc', '&default_sc',
2729 'uref', '&default_uref',
2730 'url', '&default_url',
2733 'titlefont', '&default_titlefont',
2737 # default is {'args' => ['normal'], 'attribute' => ''},
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'},
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' => '<', 'end' => '>'},
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' => '<<code>', 'end' => '</code>>','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'},
2786 foreach my $style (keys(%style_map))
2788 if (exists($style_map{$style}->{'type'}))
2790 $command_type{$style} = $style_map{$style}->{'type'};
2794 $command_type{$style} = 'style';
2798 %unicode_diacritical = (
2800 'ringaccent' => '030A',
2805 'dotaccent' => '0307',
2810 'udotaccent' => '0323',
2811 'ubaraccent' => '0332',
2813 'tieaccent' => '0361'
2816 %unicode_accents = (
2817 'dotaccent' => { # dot above
2818 'A' => '0226', #C moz-1.2
2819 'a' => '0227', #c moz-1.2
2838 'O' => '022E', #Y moz-1.2
2839 'o' => '022F', #v moz-1.2
2857 'udotaccent' => { # dot below
2897 'ubaraccent' => { # line below
2921 'E' => '0228', #C moz-1.2
2922 'e' => '0229', #c moz-1.2
2953 'Y' => '0232', #? moz-1.2
2954 'y' => '0233', #? moz-1.2
2956 '"' => { # diaeresis
3063 '^' => { # circumflex
3091 'ringaccent' => { # ring
3110 'H' => '021E', #K with moz-1.2
3111 'h' => '021F', #k with moz-1.2
3116 'L' => '013D', #L' with moz-1.2
3117 'l' => '013E', #l' with moz-1.2
3133 'H' => { # double acute
3141 %transliterate_accent_map = ();
3142 foreach my $command (keys(%unicode_accents))
3144 foreach my $letter(keys (%{$unicode_accents{$command}}))
3146 $transliterate_accent_map{$unicode_accents{$command}->{$letter}}
3148 unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}}));
3152 %special_accents = (
3153 'ringaccent' => 'aA',
3154 "'" => 'aeiouyAEIOUY',
3156 '^' => 'aeiouAEIOU',
3157 '`' => 'aeiouAEIOU',
3159 '"' => 'aeiouyAEIOU',
3162 foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
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 };
3169 sub default_accent($$)
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 . '<' 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);
3180 sub t2h_default_accent($$)
3185 my $text = $args->[0];
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 . '<' 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
3193 # if ($USE_UNICODE and defined($OUT_ENCODING) and $OUT_ENCODING ne ''
3194 # and exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text}))
3196 # my $encoded_char = Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET);
3197 # return $encoded_char if ($encoded_char ne '');
3199 if ($USE_NUMERIC_ENTITY)
3201 if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text}))
3203 return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';');
3206 return ascii_accents($text, $accent);
3209 sub ascii_accents($$)
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 ',');
3228 return '<small>' . uc($_[0]) . '</small>';
3231 # now unused, upcasing is done in normal_text
3232 sub t2h_default_sc($$$)
3236 return '<small>' . uc($args->[0]) . '</small>';
3239 sub default_ctrl($$)
3244 sub t2h_default_ctrl($$$)
3248 return "^$args->[0]";
3251 sub default_sc_pre($$)
3256 # now unused, upcasing is done in normal_text
3257 sub t2h_default_sc_pre($$$)
3261 return uc($args->[0]);
3264 sub default_titlefont($$)
3266 return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/);
3270 # Avoid adding h1 if the text is empty
3271 sub t2h_default_titlefont($$$)
3275 return "<h1 class=\"titlefont\">$args->[0]</h1>" if ($args->[0] =~ /\S/);
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
3285 # return '<<code>' . $_[0] . '</code>>';
3288 # This is unused, t2h_default_uref is used instead
3289 sub t2h_default_url ($$)
3293 my $url = shift @$args;
3296 $url = main::normalise_space($url);
3297 return '' unless ($url =~ /\S/);
3298 return &$anchor('', $url, $url);
3301 sub default_url ($$)
3304 my $command = shift;
3307 return '' unless ($url =~ /\S/);
3308 return &$anchor('', $url, $url);
3311 sub default_uref($$)
3314 my $command = shift;
3315 my ($url, $text, $replacement);
3316 ($url, $text, $replacement) = split /,\s*/, $arg;
3319 $text = $replacement if (defined($replacement));
3320 $text = $url unless ($text);
3321 return $text if ($url eq '');
3322 return &$anchor('', $url, $text);
3325 sub t2h_default_uref($$)
3329 my $url = shift @$args;
3330 my $text = shift @$args;
3331 my $replacement = shift @$args;
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);
3345 sub default_email($$)
3348 my $command = shift;
3350 ($mail, $text) = split /,\s*/, $arg;
3353 $text = $mail unless ($text);
3354 return $text if ($mail eq '');
3355 return &$anchor('', "mailto:$mail", $text);
3358 sub t2h_default_email($$)
3360 my $command = shift;
3362 my $mail = shift @$args;
3363 my $text = shift @$args;
3364 $mail = main::normalise_space($mail);
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);
3373 sub t2h_default_ascii_accent($$$$)
3378 my $text = $args->[0];
3379 return ascii_accents($text, $accent);
3382 sub t2h_default_no_texi_email
3384 my $command = shift;
3386 my $mail = shift @$args;
3387 my $text = shift @$args;
3388 $mail = main::normalise_space($mail);
3391 return $text if (defined($text) and ($text ne ''));
3395 sub t2h_default_no_texi_image($$$$)
3397 my $command = shift;
3399 my $text = $args->[0];
3400 $text = main::normalise_space($text);
3401 my @args = split (/\s*,\s*/, $text);
3405 sub t2h_default_no_texi_acronym_like($$)
3407 my $command = shift;
3409 my $acronym_texi = $args->[0];
3410 return (main::remove_texi($acronym_texi));
3413 sub t2h_remove_command($$$$)
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'} = '';
3423 foreach my $command (keys(%style_map))
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";
3431 foreach my $key (keys(%{$style_map{$command}}))
3433 $style_map_pre{$command}->{$key} = $style_map{$command}->{$key};
3437 #$style_map_pre{'sc'}->{'function'} = \&t2h_default_sc_pre;
3438 $style_map_pre{'sc'} = {};
3439 $style_map_pre{'titlefont'} = {};
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;
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},
3465 # @image is replaced by the first arg in strings
3466 $style_map_texi{'image'} = { 'args' => ['keep'],
3467 'function' => \&t2h_default_no_texi_image };
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 };
3474 foreach my $special (keys(%special_style))
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}));
3484 ####### end special styles.
3487 #foreach my $command (keys(%style_map))
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";
3495 # uncomment to use the old interface
3496 #%style_map = %old_style_map;
3497 #%style_map_pre = %old_style_map_pre;
3499 %simple_format_simple_map_texi = %simple_map_pre;
3500 %simple_format_texi_map = %pre_map;
3501 %simple_format_style_map_texi = ();
3503 foreach my $command (keys(%style_map_texi))
3505 #$simple_format_style_map_texi{$command} = {};
3506 foreach my $key (keys (%{$style_map_texi{$command}}))
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};
3512 $simple_format_style_map_texi{$command} = {} if (!defined($simple_format_style_map_texi{$command}));
3515 foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
3517 # $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal'];
3518 $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent;
3522 # 'quotation' => 'blockquote',
3524 # 'itemize' => 'ul',
3525 'enumerate' => 'ol',
3526 'multitable' => 'table',
3527 'table' => 'dl compact="compact"',
3528 'vtable' => 'dl compact="compact"',
3529 'ftable' => 'dl compact="compact"',
3533 %special_list_commands = (
3537 'itemize' => { 'bullet' => '' }
3540 # texinfo format to align attribute of paragraphs
3543 %paragraph_style = (
3544 'center' => 'center',
3545 'flushleft' => 'left',
3546 'flushright' => 'right',
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 =
3556 'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
3557 'end' => q{"</td></tr></table>\n"},
3561 'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
3562 'end' => q{"</td></tr></table>\n"},
3566 'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"},
3567 'end' => q{"</td></tr></table>\n"},
3571 'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"},
3572 'end' => q{"</td></tr></table>\n"},
3576 # format shouldn't narrow the margins
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'};
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' ],
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',
3610 foreach my $key (keys(%def_map))
3612 $def_map{$key . 'x'} = $def_map{$key};
3616 # miscalleneous commands
3618 # Depending on the value, the command arg or spaces following the command
3619 # are handled differently:
3621 # the value is a reference on a hash.
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
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
3648 'comment' => {'arg' => 'line'},
3649 'c' => {'arg' => 'line'},
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},
3692 'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code
3694 'sp' => {'skip' => 'whitespace', 'arg' => 1}, # no arg
3695 # at the end of line or a numerical arg
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
3707 'verbatiminclude'=> {'skip' => 'line'},
3708 'documentencoding' => {'arg' => 1}, # makeinfo ignore the whole line
3711 # obsolete @-commands
3713 'allow-recursion' => {},
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
3731 'dircategory', 'line', # line. Position with regard with direntry is
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',
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
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
3776 # not valid for info (should be in @iftex)
3777 'vskip', 'line', # arg line in TeX
3778 'cropmarks', 1, # no arg
3780 'verbatiminclude', 'line',
3781 'documentencoding', 'arg1',
3786 %format_in_paragraph = (
3790 # map mapping css specification to style
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;'
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'};
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
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 = ();
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 = ();
3827 # formatting functions
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;
3892 # This function is called whenever a complex format is processed
3895 # name of the format
3896 # text appearing inside the format
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
3902 sub t2h_default_complex_format($$)
3906 return '' if ($text eq '');
3907 my $beginning = eval "$complex_format_map->{$name}->{'begin'}";
3910 print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'begin'}: $@";
3914 my $end = eval "$complex_format_map->{$name}->{'end'}";
3917 print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'end'}: $@";
3921 return $beginning . $text . $end;
3924 sub t2h_default_empty_line($$)
3928 #ignore the line if it just follows a deff
3929 return '' if ($state->{'deff_line'});
3933 sub t2h_default_unknown($$$$)
3940 my ($result_line, $result, $result_text, $message);
3941 return ($line, 0, undef, undef);
3944 sub t2h_default_unknown_style($$$$)
3946 my $command = shift;
3950 my ($result, $result_text, $message);
3951 return (0, undef, undef);
3954 sub t2h_caption_shortcaption($)
3958 my $shortcaption_lines;
3959 my $style = $float->{'style_texi'};
3960 if (defined($float->{'nr'}))
3962 my $nr = $float->{'nr'};
3965 $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
3973 if (defined($float->{'caption_texi'}))
3975 @$caption_lines = @{$float->{'caption_texi'}};
3976 if (defined($style))
3978 $caption_lines->[0] = '@strong{' . &$I('%{style}: %{caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] });
3982 $caption_lines->[0] = '@strong{' . $caption_lines->[0];
3984 push @$caption_lines, "}\n";
3986 elsif (defined($style))
3988 $caption_lines->[0] = '@strong{' . $style . '}' . "\n";
3990 if (defined($float->{'shortcaption_texi'}))
3992 @$shortcaption_lines = @{$float->{'shortcaption_texi'}};
3993 if (defined($style))
3995 $shortcaption_lines->[0] = '@strong{' . &$I('%{style}: %{shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] });
3999 $shortcaption_lines->[0] = '@strong{' . $shortcaption_lines->[0];
4001 push @$shortcaption_lines, "}\n";
4003 elsif (defined($style))
4005 $shortcaption_lines->[0] = '@strong{' . $style . '}' . "\n";
4007 return ($caption_lines, $shortcaption_lines);
4010 sub t2h_default_float($$$$$)
4014 my $caption = shift;
4015 my $shortcaption = shift;
4018 if (exists($float->{'id'}))
4020 $label = &$anchor($float->{'id'});
4022 my $caption_text = '';
4024 if (defined($float->{'caption_texi'}))
4026 $caption_text = $caption;
4028 elsif (defined($float->{'shortcaption_texi'}))
4030 $caption_text = $shortcaption;
4032 elsif (defined($caption))
4034 $caption_text = $caption;
4037 return '<div class="float">' . "$label\n" . $text . '</div>' . $caption_text;
4040 sub t2h_default_listoffloats_style($)
4042 my $style_texi = shift;
4043 return ($style_texi);
4046 sub t2h_default_listoffloats_float_style($$)
4048 my $style_texi = shift;
4051 my $style = $float->{'style_texi'};
4052 if (defined($float->{'nr'}))
4054 my $nr = $float->{'nr'};
4057 $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr});
4067 sub t2h_default_listoffloats_caption($)
4070 if (defined($float->{'shortcaption_texi'}))
4072 return [ @{$float->{'shortcaption_texi'}} ];
4074 elsif (defined($float->{'caption_texi'}))
4076 return [ @{$float->{'caption_texi'}} ];
4081 sub t2h_default_listoffloats_entry($$$$)
4083 my $style_texi = shift;
4085 my $float_style = shift;
4086 my $caption = shift;
4089 return '<dt>' . &$anchor('', $href, $float_style) . '</dt><dd>' . $caption
4093 sub t2h_default_listoffloats($$$)
4095 my $style_texi = shift;
4097 my $float_entries = shift;
4099 my $result = "<dl class=\"listoffloats\">\n" ;
4100 foreach my $float_entry (@$float_entries)
4102 $result .= $float_entry;
4104 return $result . "</dl>\n";
4107 # This function is used to protect characters which are special in html
4108 # in inline text: &, ", <, and >.
4111 # text to be protected
4112 sub t2h_default_protect_text($)
4115 $text =~ s/&/&/g;
4116 $text =~ s/</</g;
4117 $text =~ s/>/>/g;
4118 $text =~ s/\"/"/g;
4123 sub in_small_caps($)
4125 my $style_stack = shift;
4127 if ($style_stack and scalar(@{$style_stack}))
4129 my $level = $#$style_stack;
4130 #print STDERR ":::$level ::@{$style_stack}\n";
4133 if ($style_stack->[$level] eq 'sc')
4145 sub t2h_default_normal_text($$$$$)
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)
4156 if ($USE_ISO and !$in_raw_text)
4158 $text =~ s/---/\&mdash\;/g;
4159 $text =~ s/--/\&ndash\;/g;
4160 $text =~ s/``/\&ldquo\;/g;
4161 $text =~ s/''/\&rdquo\;/g;
4165 if ($in_raw_text) #FIXME really do that ?
4172 $text =~ s/``/"/g;
4173 $text =~ s/''/"/g;
4175 # temporary reuse '' to store --- !....
4176 # FIXME won't '---' be handled wrongly?
4177 # FIXME really do that in raw text?
4178 $text =~ s/---/''/g;
4186 # This function produces an anchor
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($;$$$)
4198 my $attributes = shift;
4199 #print STDERR "!$name!$href!$text!$attributes!\n";
4200 if (!defined($attributes) or ($attributes !~ /\S/))
4206 $attributes = ' ' . $attributes;
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>";
4219 # This function is used to format the text associated with a @deff/@end deff
4224 # $DEF_TABLE should be used to distinguish between @def formatted as table
4225 # and as definition lists.
4226 sub t2h_default_def_item($)
4233 return '<dd>' . $text . '</dd>';
4237 return '<tr><td colspan="2">' . $text . '</td></tr>';
4243 sub t2h_default_definition_category($$$)
4248 return ($name) if (!defined($class) or $class =~ /^\s*$/);
4251 return &$I('%{name} on %{class}', { 'name' => $name, 'class' => $class });
4253 elsif ($style eq 'v')
4255 return &$I('%{name} of %{class}', { 'name' => $name, 'class' => $class });
4263 # format the container for the @deffn line and text
4266 # text of the whole @def, line and associated text.
4268 # $DEF_TABLE should be used.
4269 sub t2h_default_def($)
4276 return "<dl>\n" . $text . "</dl>\n";
4280 return "<table width=\"100%\">\n" . $text . "</table>\n";
4290 # the whole menu text (entries and menu comments)
4294 sub t2h_default_menu($)
4299 return "<table class=\"menu\" border=\"0\" cellspacing=\"0\">\n"
4300 . $text . "</table>\n";
4304 # a simple menu entry ref in case we aren't in a standard menu context
4305 sub t2h_default_simple_menu_link($$$$$$)
4308 my $preformatted = shift;
4313 $ending = '' if (!defined($ending));
4314 if (($entry eq '') or $NODE_NAME_IN_MENU or $preformatted)
4316 $name .= ':' if ($name ne '');
4317 $entry = "$MENU_SYMBOL$name$node";
4319 $entry = &$anchor('', $href, $entry) if ($href);
4320 $entry .= $ending if ($preformatted);
4321 $entry .= ' ' unless $preformatted;
4325 # formats a menu entry link pointing to a node or section
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($$$$$$)
4345 #print STDERR "MENU_LINK\n";
4346 if (($entry eq '') or $NODE_NAME_IN_MENU or $state->{'preformatted'})
4348 $name .= ':' if ($name ne '');
4349 $entry = "$MENU_SYMBOL$name$node";
4351 $entry = &$anchor ('', $href, $entry) if (defined($href));
4352 return $entry if ($SIMPLE_MENU);
4353 if ($state->{'preformatted'})
4355 return '<tr><td>' . main::do_preformatted($entry . $ending, $state);
4357 return "<tr><td align=\"left\" valign=\"top\">$entry</td><td> </td>";
4360 sub simplify_text($)
4363 $text =~ s/[^\w]//og;
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)
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($$$)
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'})
4385 return main::do_preformatted($text, $state) . '</td></tr>';
4387 elsif ($AVOID_MENU_REDUNDANCY)
4389 $text = '' if (simplify_text($element_text) eq simplify_text($text));
4391 return "<td align=\"left\" valign=\"top\">$text</td></tr>\n";
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).
4401 # The text itself is considered to be in a preformatted environment
4402 # with name 'menu-commment' and with style $MENU_PRE_STYLE.
4405 # text contained in the menu comment.
4406 sub t2h_default_menu_comment($)
4409 return $text if ($SIMPLE_MENU);
4412 return "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">$text</th></tr>";
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
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($$$)
4427 my $node_id = shift;
4428 my $node_xhtml_id = shift;
4430 $file = '' if (!defined($file));
4431 my $default_target_split = $EXTERNAL_CROSSREF_SPLIT;
4438 if ($NEW_CROSSREF_STYLE)
4440 $file =~ s/\.[^\.]*$//;
4443 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}))
4445 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}))
4448 $href_split = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}->{'href'};
4450 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}))
4453 $href_mono = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}->{'href'};
4457 if ((not $target_mono) and (not $target_split))
4458 { # nothing specified for that manual, use default
4459 $target_split = $default_target_split;
4461 elsif ($target_split and $target_mono)
4462 { # depends on the splitting of the manual
4463 $target_split = $SPLIT;
4465 elsif ($target_mono)
4466 { # only mono specified
4472 if (defined($href_split))
4474 $file = "$href_split";
4476 elsif (defined($EXTERNAL_DIR))
4478 $file = "$EXTERNAL_DIR/$file";
4488 if (defined($href_mono))
4490 $file = "$href_mono";
4494 if (defined($EXTERNAL_DIR))
4496 $file = "$EXTERNAL_DIR/$file";
4502 $file .= "." . $NODE_FILE_EXTENSION;
4509 if (defined($EXTERNAL_DIR))
4511 $file = $EXTERNAL_DIR . $file;
4515 $file = '../' . $file;
4521 $target_split = $default_target_split;
4525 if ($NEW_CROSSREF_STYLE)
4529 return $file . $TOP_NODE_FILE . '.' . $NODE_FILE_EXTENSION . '#Top';
4531 #return $file . '#Top';
4535 return $file . '#Top';
4544 if ($NEW_CROSSREF_STYLE)
4547 $target = $node_xhtml_id;
4551 $node = main::remove_texi($node);
4552 $node =~ s/[^\w\.\-]/-/g;
4554 my $file_basename = $node;
4555 $file_basename = $TOP_NODE_FILE if ($node =~ /^top$/i);
4556 if ($NEW_CROSSREF_STYLE)
4560 return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target;
4564 return $file . '#' . $target;
4569 return $file . $file_basename . ".$NODE_FILE_EXTENSION";
4573 # format a reference external to the generated manual. This produces a full
4574 # reference with introductive words and the reference itself.
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.
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($$$$$$)
4589 my $section = shift;
4591 my $file_node = shift;
4593 my $cross_ref = shift;
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 '');
4598 # Yes, this is ugly, but this helps internationalization
4599 if ($type eq 'pxref')
4601 if (($book ne '') and ($file_node ne ''))
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 });
4608 return &$I('see section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4609 return &$I('see @cite{%{book}}', { 'book' => $book });
4611 elsif ($file_node ne '')
4613 return &$I('see %{node_file_href}', { 'node_file_href' => $file_node });
4616 if ($type eq 'xref')
4618 if (($book ne '') and ($file_node ne ''))
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 });
4625 return &$I('See section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4626 return &$I('See @cite{%{book}}', { 'book' => $book });
4628 elsif ($file_node ne '')
4630 return &$I('See %{node_file_href}', { 'node_file_href' => $file_node });
4635 if (($book ne '') and ($file_node ne ''))
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 });
4642 return &$I('section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne '');
4643 return &$I('@cite{%{book}}', { 'book' => $book });
4645 elsif ($file_node ne '')
4647 return &$I('%{node_file_href}', { 'node_file_href' => $file_node });
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.
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
4665 # $SHORT_REF should be used.
4666 sub t2h_default_internal_ref($$$$$)
4670 my $short_name = shift;
4672 my $is_section = shift;
4676 $name = &$anchor('', $href, $name);
4677 if ($type eq 'pxref')
4679 return &$I('see section %{reference_name}', { 'reference_name' => $name }) if ($is_section);
4680 return &$I('see %{reference_name}', { 'reference_name' => $name });
4682 elsif ($type eq 'xref')
4684 return &$I('See section %{reference_name}', { 'reference_name' => $name }) if ($is_section);
4685 return &$I('See %{reference_name}', { 'reference_name' => $name });
4687 elsif ($type eq 'ref')
4689 return &$I('%{reference_name}', { 'reference_name' => $name });
4694 $name = &$anchor('', $href, $short_name);
4695 if ($type eq 'pxref')
4697 return &$I('see %{reference_name}', { 'reference_name' => $name });
4699 elsif ($type eq 'xref')
4701 return &$I('See %{reference_name}', { 'reference_name' => $name });
4703 elsif ($type eq 'ref')
4705 return &$I('%{reference_name}', { 'reference_name' => $name });
4711 sub teletyped_in_stack($)
4714 foreach my $element(reverse(@$stack))
4716 if ($complex_format_map->{$element})
4718 if (!$complex_format_map->{$element}->{'pre_style'})
4731 # text after @item in table, vtable and ftable
4732 sub t2h_default_table_item($$$$$$)
4735 my $index_label = 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))
4746 $formatted_command = '<tt>' . $formatted_command;
4748 $text .= "\n" . $index_label if (defined($index_label));
4749 return '<dt>' . $formatted_command . $text . '</dt>' . "\n";
4752 # format text on the line following the @item line (in table, vtable and ftable)
4753 sub t2h_default_table_line($)
4759 return '<dd>' . $text . '</dd>' . "\n";
4765 sub t2h_default_row($$)
4772 if ($macro eq 'headitem')
4774 return '<thead><tr>' . $text . '</tr></thead>' . "\n";
4776 return '<tr>' . $text . '</tr>' . "\n";
4781 # cell in multitable
4782 sub t2h_default_cell($$)
4785 my $row_macro = shift;
4787 if ($row_macro eq 'headitem')
4789 return '<th>' . $text . '</th>';
4791 return '<td>' . $text . '</td>';
4794 # format an item in a list
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($$$$$$$)
4805 my $command = shift;
4806 my $formatted_command = shift;
4807 my $item_nr = shift;
4808 my $enumerate_style = shift;
4811 $formatted_command = '' if (!defined($formatted_command) or
4812 exists($special_list_commands{$format}->{$command}));
4815 return '<li>' . $formatted_command . $text . '</li>';
4820 sub t2h_default_table_list($$$$$$)
4824 my $command = shift;
4825 my $formatted_command = shift;
4826 my $item_nr = shift;
4827 my $enumerate_style = shift;
4829 $formatted_command = '' if (!defined($formatted_command) or
4830 exists($special_list_commands{$format}->{$command}));
4831 if ($format eq 'itemize')
4833 return "<ul>\n" . $text . "</ul>\n" if ($command eq 'bullet');
4834 return "<ul$TOC_LIST_ATTRIBUTE>\n" . $text . "</ul>\n";
4839 sub t2h_default_comment($)
4842 $text =~ s/--+/-/go;
4843 return '<!-- ' . $text . ' -->' . "\n";
4846 sub t2h_collect_styles($)
4850 foreach my $style (reverse(@$stack))
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');
4858 sub t2h_get_attribute($;$)
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'}))
4867 return $map_ref->{$command}->{'attribute'};
4869 elsif ($map_ref->{$command} !~ /^&/)
4871 my $attribute = $map_ref->{$command};
4872 $attribute =~ s/^\"//;
4878 sub t2h_begin_style($$;$)
4880 my $command = 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;
4888 sub t2h_end_style($$;$)
4890 my $command = shift;
4892 my $map_ref = shift;
4893 my $attribute = t2h_get_attribute($command,$map_ref);
4894 if ($attribute =~ /^(\w+)/)
4898 $attribute = "</$attribute>" if ($attribute ne '');
4899 return $text.$attribute;
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($$$$$$$$$$$$)
4918 my $paragraph_command = shift;
4919 my $paragraph_command_formatted = shift;
4920 my $paragraph_number = shift;
4922 my $item_nr = shift;
4923 my $enumerate_style = 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))
4934 $text = t2h_begin_style($style, $text);
4936 foreach my $style(t2h_collect_styles($command_stack_at_end))
4938 $text = t2h_end_style($style, $text);
4940 if (defined($paragraph_number) and defined($$paragraph_number))
4942 $$paragraph_number++;
4943 return $text if (($format eq 'itemize' or $format eq 'enumerate') and
4944 ($$paragraph_number == 1));
4949 $open = "<p align=\"$paragraph_style{$align}\">";
4951 return $open.$text.'</p>';
4954 # a preformatted region
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($$$$$$$$$$$$)
4967 my $pre_style = shift;
4969 my $leading_command = shift;
4970 my $leading_command_formatted = shift;
4971 my $preformatted_number = shift;
4973 my $item_nr = shift;
4974 my $enumerate_style = shift;
4976 my $command_stack_at_end = shift;
4977 my $command_stack_at_begin = shift;
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))
4985 $$preformatted_number++;
4987 foreach my $style(t2h_collect_styles($command_stack_at_begin))
4989 $text = t2h_begin_style($style, $text, \%style_map_pre);
4991 foreach my $style(t2h_collect_styles($command_stack_at_end))
4993 $text = t2h_end_style($style, $text, \%style_map_pre);
4995 return "<pre class=\"$class\">".$text."</pre>";
4998 # This function formats a heading for an element
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($)
5012 my $element = shift;
5014 if (!$element->{'node'})
5016 $level = $element->{'level'};
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)
5025 $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text);
5028 $align = ' align="center"' if ($element->{'tag'} eq 'centerchap');
5029 return "<h$level class=\"$class\"$align> $text </h$level>\n";
5032 # formatting of raw regions
5033 # if L2H is true another mechanism is used for tex
5034 sub t2h_default_raw($$)
5038 if ($style eq 'verbatim' or $style eq 'tex')
5040 return "<pre class=\"$style\">" . &$protect_text($text) . '</pre>';
5042 elsif ($style eq 'html')
5048 warn "$WARN (bug) unknown style $style\n";
5049 return &$protect_text($text);
5053 # raw environment when removing texi (in comments)
5054 sub t2h_default_raw_no_texi($$)
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.
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.
5077 # reference on an array containing the footnote text lines which should
5079 # the text for the reference pointing on the footnote text
5080 sub t2h_default_foot_line_and_ref($$$$$$$)
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;
5091 unshift (@$lines, '<h3>' .
5092 &$anchor($footnote_id, $document_file . "#$place_id",
5095 return ($lines, &$anchor($place_id, $footnote_file . "#$footnote_id",
5096 "($number_in_doc)"));
5099 # formats a group of footnotes.
5102 # array reference on the footnotes texts lines
5104 # returns an array reference on the group of footnotes lines
5105 sub t2h_default_foot_section($)
5108 unshift (@$lines, "<div class=\"footnote\">\n" ,"$DEFAULT_RULE\n", "<h3>" . &$I('Footnotes') . "</h3>\n");
5109 push (@$lines, "</div>\n");
5113 sub t2h_default_image_files($$)
5116 my $extension = shift;
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)
5122 push @files, "$base.$ext";
5130 # image file name with path
5132 # a boolean true if we are in a preformatted format
5133 # image file name without path
5139 # path to working dir
5140 # path to file relative from working dir
5141 sub t2h_default_image($$$$$$$$$$$)
5145 my $preformatted = shift;
5146 my $file_name = shift;
5150 my $raw_alt = shift;
5151 my $extension = shift;
5152 my $working_dir = shift;
5153 my $file_path = shift;
5155 if (!defined($file_path) or $file_path eq '')
5157 if (defined($extension) and $extension ne '')
5159 $file = "$base.$extension";
5163 $file = "$base.jpg";
5165 main::echo_warn ("no image file for $base, (using $file)");
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\">";
5175 # address put in footer describing when was generated and who did the manual
5176 sub t2h_default_address($$)
5180 $user = '' if (!defined($user));
5181 $date = '' if (!defined($date));
5182 if (($user ne '') and ($date ne ''))
5184 return &$I('by @emph{%{user}} on @emph{%{date}}', { 'user' => $user,
5189 return &$I('by @emph{%{user}}', { 'user' => $user });
5193 return &$I('on @emph{%{date}}', { 'date' => $date });
5198 # format a target in the main document for an index entry.
5202 # boolean true if in preformatted format
5203 # FIXME document the remaining
5204 sub t2h_default_index_entry_label($$)
5206 my $identifier = shift;
5207 my $preformatted = shift;
5209 return '' if (!defined($identifier) or ($identifier !~ /\S/));
5210 my $label = &$anchor($identifier);
5211 return $label . "\n" if (!$preformatted);
5215 # process definition commands line @deffn for example
5216 sub t2h_default_def_line($$$$$)
5218 my $category = 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*$/)
5234 $arguments = '<i>' . $arguments . '</i>';
5237 $type_name = " $type" if ($type ne '');
5238 $type_name .= ' <b>' . $name . '</b>' if ($name ne '');
5239 $type_name .= $arguments . "\n";
5242 return '<dt>'. '<u>' . $category . ':</u>' . $type_name . $index_label . "</dt>\n";
5247 return "<tr>\n<td align=\"left\">" . $type_name .
5248 "</td>\n<td align=\"right\">" . $category . $index_label . "</td>\n" . "</tr>\n";
5252 # process definition commands line @deffn for example while removing texi
5254 sub t2h_default_def_line_no_texi($$$$$)
5256 my $category = 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*$/)
5267 $type_name = " $type" if ($type ne '');
5268 $type_name .= ' ' . $name if ($name ne '');
5269 $type_name .= $arguments;
5272 return $category . ':' . $type_name . "\n";
5277 return $type_name . " " . $category . "\n";
5282 sub t2h_default_cartouche($$)
5288 return "<table class=\"cartouche\" border=\"1\"><tr><td>\n" . $text . "</td></tr></table>\n";
5299 sub t2h_default_index_summary_file_entry ($$$$$$$$)
5301 my $index_name = shift;
5303 my $origin_href = 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";
5314 sub t2h_default_index_summary_file_begin($$)
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";
5322 sub t2h_default_index_summary_file_end($$)
5325 my $is_printed = shift;
5329 sub t2h_default_sp($$)
5332 my $preformatted = shift;
5333 return "<br>\n" x $number if (!$preformatted);
5334 return "\n" x $number;
5337 sub t2h_default_acronym_like($$$$$$)
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;
5347 my $attribute = $command;
5348 my $opening = "<$attribute>";
5349 if (defined($explanation_simply_formatted))
5351 $opening = "<$attribute title=\"$explanation_simply_formatted\">";
5353 if ($with_explanation)
5355 return &$I('%{acronym_like} (%{explanation})', {'acronym_like' => $opening . $acronym_text . "</$attribute>", 'explanation' => $explanation_text})
5359 return $opening . $acronym_text . "</$attribute>";
5363 sub t2h_default_quotation_prepend_text($)
5366 return undef if (!defined($text) or $text =~ /^$/);
5367 # FIXME if there is a @ protecting the end of line the result is
5369 # It is likely not to be what was intended
5371 return &$I('@b{%{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1});
5374 sub t2h_default_quotation($$$)
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))
5383 # return '<blockquote>' . &$I('%{style}:%{quotation}',
5384 # {'style' => $argument_text, 'quotation' => $text}) . '</blockquote>' ;
5386 return '<blockquote>' . $text . "</blockquote>\n";
5389 # format the text within a paragraph style format,
5393 # text within the format
5394 sub t2h_default_paragraph_style_command($$)
5401 # format a whole index
5406 sub t2h_default_print_index($$)
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 .
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.
5422 # identifier for the letter entry. This should be used to make the target
5424 # text of the index entries
5425 sub t2h_default_index_letter($$$)
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";
5435 # format an index entry (in a letter entry).
5438 # href to the main text, linking to the place where the index entry appears
5440 # href to the main text, linking to the section or node where the index
5442 # section or node heading
5443 sub t2h_default_index_entry($$$$)
5445 my $text_href = shift;
5447 my $element_href = shift;
5448 my $element_text = shift;
5450 return '<tr><td></td><td valign="top">' . &$anchor('', $text_href, $entry)
5451 . '</td><td valign="top">' . &$anchor('', $element_href, $element_text)
5456 sub t2h_default_copying_comment($)
5458 my $copying_lines = shift;
5459 my $text = &$comment(main::remove_texi(@$copying_lines));
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
5468 # file where the target letter entry is
5469 # identifier for the target letter entry
5470 sub t2h_default_summary_letter($$$)
5474 my $identifier = shift;
5475 return &$anchor('', $file . '#' . $identifier, '<b>' . &$protect_text($letter) . '</b>', 'class="summary-letter"');
5478 # format an index summary. This is a list of letters linking to the letter
5482 # array reference containing the formatted alphabetical letters
5483 # array reference containing the formatted non lphabetical letters
5484 sub t2h_default_index_summary($$)
5487 my $nonalpha = shift;
5489 my $nonalpha_text = '';
5490 my $alpha_text = '';
5491 $join = " \n<br>\n" if (@$nonalpha and @$alpha);
5494 $nonalpha_text = join("\n \n", @$nonalpha) . "\n";
5498 $alpha_text = join("\n \n", @$alpha) . "\n \n";
5500 return "<table><tr><th valign=\"top\">" . &$I('Jump to') .": </th><td>" .
5501 $nonalpha_text . $join . $alpha_text . "</td></tr></table>\n";
5504 # return the heading with number texinfo text
5505 # also called for nodes.
5506 sub t2h_default_heading_texi($$$)
5513 return "$number $texi" if ($NUMBER_SECTIONS and defined($number) and ($number !~ /^\s*$/)) ;
5517 # return the heading texinfo text for split index sections
5518 sub t2h_default_index_element_heading_texi($$$)
5520 my $heading_texi = 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";
5532 require "$ENV{T2H_HOME}/texi2html.init"
5533 if ($0 =~ /\.pl$/ &&
5534 -e "$ENV{T2H_HOME}/texi2html.init" && -r "$ENV{T2H_HOME}/texi2html.init");
5536 my $translation_file = 'translations.pl'; # file containing all the translations
5537 my $T2H_OBSOLETE_STRINGS;
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.
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:' => '',
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}}' => '',
5562 'About (help)' => '',
5563 'About This Document' => '@"Uber dieses Dokument',
5565 'August' => 'August',
5567 'Beginning of this chapter or previous chapter' => '',
5570 'Cover (top) of document' => '',
5571 'Current Position' => '',
5572 'Current section' => '',
5573 'December' => 'Dezember',
5575 'FastForward' => '',
5576 'February' => 'Februar',
5578 'First section in reading order' => '',
5580 'Following node' => '',
5581 'Footnotes' => 'Fu@ss{}noten',
5583 'From 1.2.3 go to' => '',
5586 'Index Entry' => '',
5587 'January' => 'Januar',
5592 'Last section in reading order' => '',
5593 'March' => 'M@"arz',
5598 'Next chapter' => '',
5600 'Next section in reading order' => '',
5601 'Next section on same level' => '',
5602 'Node following in node reading order' => '',
5607 'November' => 'November',
5608 'October' => 'Oktober',
5612 'Previous node' => '',
5613 'Previous section in reading order' => '',
5614 'Previous section on same level' => '',
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' => '',
5636 'Table of Contents' => 'Inhaltsverzeichniss',
5637 'Table of contents' => '',
5638 'The node you are looking for is at %{href}.' => '',
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}}}.' => '',
5645 'Untitled Document' => '',
5649 'by @emph{%{user}}' => '',
5650 'by @emph{%{user}} on @emph{%{date}}' => '',
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}}' => '',
5664 $T2H_OBSOLETE_STRINGS->{'de'} = {
5666 'section' => 'Abschnitt',
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:' => '',
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}}' => '',
5689 'About (help)' => '',
5690 'About This Document' => '',
5694 'Beginning of this chapter or previous chapter' => '',
5697 'Cover (top) of document' => '',
5698 'Current Position' => '',
5699 'Current section' => '',
5702 'FastForward' => '',
5705 'First section in reading order' => '',
5707 'Following node' => '',
5710 'From 1.2.3 go to' => '',
5713 'Index Entry' => '',
5719 'Last section in reading order' => '',
5725 'Next chapter' => '',
5727 'Next section in reading order' => '',
5728 'Next section on same level' => '',
5729 'Node following in node reading order' => '',
5739 'Previous node' => '',
5740 'Previous section in reading order' => '',
5741 'Previous section on same level' => '',
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}}' => '',
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}.' => '',
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}}}.' => '',
5772 'Untitled Document' => '',
5776 'by @emph{%{user}}' => '',
5777 'by @emph{%{user}} on @emph{%{date}}' => '',
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}}' => '',
5791 $T2H_OBSOLETE_STRINGS->{'en'} = {};
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:' => '',
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}}' => '',
5812 'About (help)' => '',
5813 'About This Document' => '',
5815 'August' => 'agosto',
5817 'Beginning of this chapter or previous chapter' => '',
5820 'Cover (top) of document' => '',
5821 'Current Position' => '',
5822 'Current section' => '',
5823 'December' => 'diciembre',
5825 'FastForward' => '',
5826 'February' => 'febrero',
5828 'First section in reading order' => '',
5830 'Following node' => '',
5833 'From 1.2.3 go to' => '',
5836 'Index Entry' => '',
5837 'January' => 'enero',
5842 'Last section in reading order' => '',
5848 'Next chapter' => '',
5850 'Next section in reading order' => '',
5851 'Next section on same level' => '',
5852 'Node following in node reading order' => '',
5857 'November' => 'noviembre',
5858 'October' => 'octubre',
5862 'Previous node' => '',
5863 'Previous section in reading order' => '',
5864 'Previous section on same level' => '',
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' => '',
5886 'Table of Contents' => '@\'{@dotless{I}}ndice General',
5887 'Table of contents' => '',
5888 'The node you are looking for is at %{href}.' => '',
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}}}.' => '',
5895 'Untitled Document' => '',
5899 'by @emph{%{user}}' => '',
5900 'by @emph{%{user}} on @emph{%{date}}' => '',
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}}' => '',
5914 $T2H_OBSOLETE_STRINGS->{'es'} = {
5915 'See' => 'V@\'ease',
5916 'section' => 'secci@\'on',
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',
5942 'August' => 'Ao@^ut',
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',
5963 'Index Entry' => 'Entr@\'ee d\'index',
5964 'January' => 'Janvier',
5965 'July' => 'Juillet',
5966 'Jump to' => 'Aller @`a',
5968 'Last' => 'Dernier',
5969 'Last section in reading order' => 'Derni@`ere section dans l\'ordre de lecture',
5972 'Menu:' => 'Menu@ :',
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',
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}.',
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}}}.',
6022 'Untitled Document' => 'Document sans titre',
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'
6041 $T2H_OBSOLETE_STRINGS->{'fr'} = {
6042 ' This document was generated %{who_and_when_generated} using %{program_homepage_href}.' => ' Ce document a été généré %{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 à <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>',
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 été généré 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 été généré 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 été généré <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',
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>',
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'
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項}を現在位置に仮定しています。',
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}}' => '',
6112 'About (help)' => '',
6113 'About This Document' => 'この文書について',
6117 'Beginning of this chapter or previous chapter' => '',
6120 'Cover (top) of document' => '',
6121 'Current Position' => '現在位置',
6122 'Current section' => '',
6123 'December' => '12月',
6125 'FastForward' => '',
6128 'First section in reading order' => '',
6130 'Following node' => '',
6131 'Footnotes' => '脚注',
6133 'From 1.2.3 go to' => '1.2.3項からの移動先',
6136 'Index Entry' => '見出し一覧',
6142 'Last section in reading order' => '',
6148 'Next chapter' => '',
6150 'Next section in reading order' => '',
6151 'Next section on same level' => '',
6152 'Node following in node reading order' => '',
6157 'November' => '11月',
6160 'Overview:' => '概要:',
6162 'Previous node' => '',
6163 'Previous section in reading order' => '',
6164 'Previous section on same level' => '',
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}.' => '',
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}}}を用いて生成されました。',
6195 'Untitled Document' => '無題の文書',
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}}' => '',
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' => '次の節',
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' => '文書の目次',
6235 'up section' => '上の項'
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:' => '',
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}}' => '',
6257 'About (help)' => '',
6258 'About This Document' => 'No translation available!',
6260 'August' => 'Augustus',
6262 'Beginning of this chapter or previous chapter' => '',
6265 'Cover (top) of document' => '',
6266 'Current Position' => '',
6267 'Current section' => '',
6268 'December' => 'December',
6270 'FastForward' => '',
6271 'February' => 'Februari',
6273 'First section in reading order' => '',
6275 'Following node' => '',
6276 'Footnotes' => 'No translation available!',
6278 'From 1.2.3 go to' => '',
6281 'Index Entry' => '',
6282 'January' => 'Januari',
6287 'Last section in reading order' => '',
6293 'Next chapter' => '',
6295 'Next section in reading order' => '',
6296 'Next section on same level' => '',
6297 'Node following in node reading order' => '',
6302 'November' => 'November',
6303 'October' => 'Oktober',
6307 'Previous node' => '',
6308 'Previous section in reading order' => '',
6309 'Previous section on same level' => '',
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' => '',
6331 'Table of Contents' => 'Inhoudsopgave',
6332 'Table of contents' => '',
6333 'The node you are looking for is at %{href}.' => '',
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}}}.' => '',
6340 'Untitled Document' => '',
6344 'by @emph{%{user}}' => '',
6345 'by @emph{%{user}} on @emph{%{date}}' => '',
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}}' => '',
6359 $T2H_OBSOLETE_STRINGS->{'nl'} = {
6361 'section' => 'sectie',
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:' => '',
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}}' => '',
6384 'About (help)' => '',
6385 'About This Document' => 'No translation available!',
6387 'August' => 'august',
6389 'Beginning of this chapter or previous chapter' => '',
6392 'Cover (top) of document' => '',
6393 'Current Position' => '',
6394 'Current section' => '',
6395 'December' => 'desember',
6397 'FastForward' => '',
6398 'February' => 'februar',
6400 'First section in reading order' => '',
6402 'Following node' => '',
6403 'Footnotes' => 'No translation available!',
6405 'From 1.2.3 go to' => '',
6407 'Index' => 'Indeks',
6408 'Index Entry' => '',
6409 'January' => 'januar',
6414 'Last section in reading order' => '',
6420 'Next chapter' => '',
6422 'Next section in reading order' => '',
6423 'Next section on same level' => '',
6424 'Node following in node reading order' => '',
6429 'November' => 'november',
6430 'October' => 'oktober',
6434 'Previous node' => '',
6435 'Previous section in reading order' => '',
6436 'Previous section on same level' => '',
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' => '',
6458 'Table of Contents' => 'Innholdsfortegnelse',
6459 'Table of contents' => '',
6460 'The node you are looking for is at %{href}.' => '',
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}}}.' => '',
6467 'Untitled Document' => '',
6471 'by @emph{%{user}}' => '',
6472 'by @emph{%{user}} on @emph{%{date}}' => '',
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}}' => '',
6486 $T2H_OBSOLETE_STRINGS->{'no'} = {
6488 'section' => 'avsnitt',
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}}' => '',
6511 'About (help)' => 'Sobre (ajuda)',
6512 'About This Document' => 'Sobre Esse Documento',
6514 'August' => 'Agosto',
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',
6538 'Jump to' => 'Pular para',
6540 'Last' => '@\'Ultimo',
6541 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
6542 'March' => 'Mar@,{c}o',
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',
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}.',
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}}}.',
6594 'Untitled Document' => 'Documento Sem Nome',
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'
6613 $T2H_OBSOLETE_STRINGS->{'pt'} = {
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',
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'
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}}' => '',
6659 'About (help)' => 'Sobre (ajuda)',
6660 'About This Document' => 'Sobre Esse Documento',
6662 'August' => 'Agosto',
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',
6686 'Jump to' => 'Pular para',
6688 'Last' => '@\'Ultimo',
6689 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura',
6690 'March' => 'Mar@,{c}o',
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',
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}.',
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}}}.',
6742 'Untitled Document' => 'Documento Sem Nome',
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'
6761 $T2H_OBSOLETE_STRINGS->{'pt_BR'} = {
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',
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'
6790 require "$ENV{T2H_HOME}/$translation_file"
6791 if ($0 =~ /\.pl$/ &&
6792 -e "$ENV{T2H_HOME}/$translation_file" && -r "$ENV{T2H_HOME}/$translation_file");
6794 # set the default 'args' entry to normal for each style hash (and each command
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)
6801 my $name = $hash_names[$name_index]; # name associated with hash ref
6802 foreach my $style (keys(%{$hash}))
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";
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.
6816 # used to utf8 encode the result
6817 sub t2h_utf8_accent($$$)
6821 my $style_stack = shift;
6823 my $text = $args->[0];
6824 #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n";
6826 # special handling of @dotless{i}
6827 if ($accent eq 'dotless')
6829 if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
6833 #return "\x{}" if ($text eq 'j'); # not found !
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);
6843 sub t2h_utf8_normal_text($$$$$)
6846 my $in_raw_text = shift;
6847 my $in_preformatted = 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));
6853 if (!$in_code and !$in_preformatted)
6855 $text =~ s/---/\x{2014}/g;
6856 $text =~ s/--/\x{2013}/g;
6857 $text =~ s/``/\x{201C}/g;
6858 $text =~ s/''/\x{201D}/g;
6860 return Unicode::Normalize::NFC($text);
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($$$$$)
6868 my $in_raw_text = shift;
6869 my $in_preformatted = shift;
6871 my $style_stack = shift;
6873 $text = uc($text) if (in_small_caps($style_stack));
6874 return $text if ($USE_UNICODE);
6876 # if there is no unicode support, we do all the transformations here
6880 if ($text =~ s/^([A-Za-z0-9]+)//o)
6884 elsif ($text =~ s/^ //o)
6888 elsif ($text =~ s/^(.)//o)
6890 if (exists($ascii_character_map{$1}))
6892 $result .= '_' . lc($ascii_character_map{$1});
6895 { # wild guess that should work for latin1
6896 $result .= '_' . '00' . lc(sprintf("%02x",ord($1)));
6901 print STDERR "Bug: unknown character in cross ref (likely in infinite loop)\n";
6909 sub t2h_nounicode_cross_manual_accent($$$)
6913 my $style_stack = shift;
6915 my $text = $args->[0];
6917 if ($accent eq 'dotless')
6919 if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
6923 #return "\x{}" if ($text eq 'j'); # not found !
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);
6933 sub t2h_transliterate_cross_manual_accent($$)
6938 my $text = $args->[0];
6940 if (exists($unicode_accents{$accent}->{$text}) and
6941 exists ($transliterate_map{$unicode_accents{$accent}->{$text}}))
6943 return $transliterate_map{$unicode_accents{$accent}->{$text}};
6949 } # end package Texi2HTML::Config
6955 # variables which might be redefined by the user but aren't likely to be
6956 # they seem to be in the main namespace
6964 %forbidden_index_name
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.
6971 #+++############################################################################
6974 # Pasted content of File $(srcdir)/MySimple.pm: Command-line processing #
6976 #---############################################################################
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
6983 package Getopt::MySimple;
6989 # POD-style (incomplete) documentation is in file MySimple.pod
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
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 $
7010 use vars qw(@EXPORT @EXPORT_OK @ISA);
7011 use vars qw($fieldWidth $opt $VERSION);
7016 @ISA = qw(Exporter);
7018 @EXPORT_OK = qw($opt); # An alias for $self -> {'opt'}.
7020 # --------------------------------------------------------------------------
7025 # --------------------------------------------------------------------------
7031 return uc($a) cmp (uc($b));
7034 # --------------------------------------------------------------------------
7040 print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n";
7042 for (sort byOrder keys(%{$self -> {'opt'} }) )
7044 print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n";
7049 } # End of dumpOptions.
7051 # --------------------------------------------------------------------------
7058 push(@_, 0) if ($#_ == 2); # Default for $ignoreCase is 0.
7059 push(@_, 1) if ($#_ == 3); # Default for $helpThenExit is 1.
7061 my($self, $default, $helpText, $versionText,
7062 $helpThenExit, $versionThenExit, $ignoreCase) = @_;
7064 $helpThenExit = 1 unless (defined($helpThenExit));
7065 $versionThenExit = 1 unless (defined($versionThenExit));
7066 $ignoreCase = 0 unless (defined($ignoreCase));
7068 $self -> {'default'} = $default;
7069 $self -> {'helpText'} = $helpText;
7070 $self -> {'versionText'} = $versionText;
7071 $Getopt::Long::ignorecase = $ignoreCase;
7073 unless (defined($self -> {'default'}{'help'}))
7075 $self -> {'default'}{'help'} =
7079 linkage => sub {$self->helpOptions($_[1]); sleep 5;exit (0) if $helpThenExit;},
7080 verbose => "print help and exit"
7084 unless (defined($self -> {'default'}{'version'}))
7086 $self -> {'default'}{'version'} =
7090 linkage => sub {print $self->{'versionText'}; exit (0) if $versionThenExit;},
7091 verbose => "print version and exit"
7095 for (keys(%{$self -> {'default'} }) )
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'};
7104 my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} });
7106 return $result unless $result;
7108 for (keys(%{$self -> {'default'} }) )
7110 if (! defined(${$self -> {'opt'} }{$_})) #{
7112 ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'};
7117 } # End of getOptions.
7119 # --------------------------------------------------------------------------
7124 my($noHelp) = shift;
7125 $noHelp = 0 unless $noHelp;
7126 my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth)
7127 = (10, 5, 9, 78, 4, 11);
7129 print "$self->{'helpText'}" if ($self -> {'helpText'});
7131 print ' Option', ' ' x ($optwidth - length('Option') -1 ),
7132 'Type', ' ' x ($typewidth - length('Type') + 1),
7133 'Default', ' ' x ($defaultwidth - length('Default') ),
7136 for (sort byOrder keys(%{$self -> {'default'} }) )
7138 my($line, $help, $option, $val);
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'}) ));
7147 $val = ${$self->{'default'} }{$_}{'linkage'};
7150 if ((ref($val) eq 'SCALAR') and (defined($$val)))
7159 elsif (defined(${$self->{'default'} }{$_}{'default'}))
7161 $val = ${$self->{'default'} }{$_}{'default'};
7168 $line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line));
7170 if (defined(${$self -> {'default'} }{$_}{'verbose'}) &&
7171 ${$self -> {'default'} }{$_}{'verbose'} ne '')
7173 $help = "${$self->{'default'} }{$_}{'verbose'}";
7179 if ((length("$line") + length($help)) < $maxlinewidth)
7181 print $line , $help, "\n";
7185 print $line, "\n", ' ' x $valind, $help, "\n";
7187 for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}}))
7189 print ' ' x ($valind + 2);
7190 print $val, ' ', ' ' x ($valwidth - length($val) - 2);
7191 print ${$self->{'default'}}{$option}{'values'}{$val}, "\n";
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
7201 } # End of helpOptions.
7203 #-------------------------------------------------------------------
7209 $self -> {'default'} = {};
7210 $self -> {'helpText'} = '';
7211 $self -> {'opt'} = {};
7212 $opt = $self -> {'opt'}; # An alias for $self -> {'opt'}.
7213 $self -> {'type'} = ();
7215 return bless $self, $class;
7219 # --------------------------------------------------------------------------
7225 require "$ENV{T2H_HOME}/MySimple.pm"
7226 if ($0 =~ /\.pl$/ &&
7227 -e "$ENV{T2H_HOME}/MySimple.pm" && -r "$ENV{T2H_HOME}/MySimple.pm");
7229 #+++########################################################################
7232 # Pasted content of File $(srcdir)/T2h_i18n.pm: Internationalisation #
7234 #---########################################################################
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
7241 #+##############################################################################
7243 # T2h_i18n.pm: Internationalization for texi2html
7245 # Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>,
7246 # Derek Price <derek@ximbiot.com>,
7247 # Adrian Aichner <adrian@xemacs.org>,
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.
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.
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
7264 #-##############################################################################
7266 # This requires perl version 5 or higher
7269 package Texi2HTML::I18n;
7279 @ISA = qw(Exporter);
7280 @EXPORT = qw(pretty_date);
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
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.
7295 # Those hashes are obsolete but retained here for reference
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',
7307 #'section' => 'section',
7308 'About This Document' => '',
7309 'Table of Contents' => '',
7310 'Short Table of Contents', => '',
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'
7346 'T2H_today' => '%s, %d %d',
7351 'Table of Contents' => 'Inhaltsverzeichniss',
7352 'Short Table of Contents' => 'Kurzes Inhaltsverzeichniss',
7354 'About This Document' => 'Über dieses Dokument',
7355 'Footnotes' => 'Fußnoten',
7358 'section' => 'Abschnitt',
7359 'January' => 'Januar',
7360 'February' => 'Februar',
7361 'March' => 'März',
7366 'August' => 'August',
7367 'September' => 'September',
7368 'October' => 'Oktober',
7369 'November' => 'November',
7370 'December' => 'Dezember',
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!
7382 'section' => 'sectie',
7383 'January' => 'Januari',
7384 'February' => 'Februari',
7390 'August' => 'Augustus',
7391 'September' => 'September',
7392 'October' => 'Oktober',
7393 'November' => 'November',
7394 'December' => 'December',
7399 'Table of Contents' => 'í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ßnoten',
7404 'See' => 'Véase',
7405 'see' => 'véase',
7406 'section' => 'sección',
7407 'January' => 'enero',
7408 'February' => 'febrero',
7414 'August' => 'agosto',
7415 'September' => 'septiembre',
7416 'October' => 'octubre',
7417 'November' => 'noviembre',
7418 'December' => 'diciembre',
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!',
7430 'section' => 'avsnitt',
7431 'January' => 'januar',
7432 'February' => 'februar',
7438 'August' => 'august',
7439 'September' => 'september',
7440 'October' => 'oktober',
7441 'November' => 'november',
7442 'December' => 'desember',
7447 'Table of Contents' => 'Sumário',
7448 'Short Table of Contents' => 'Breve Sumário',
7449 'Index' => 'Índice', #Not sure ;-)
7450 'About This Document' => 'No translation available!', #No translation available!
7451 'Footnotes' => 'No translation available!',
7454 'section' => 'Seção',
7455 'January' => 'Janeiro',
7456 'February' => 'Fevereiro',
7457 'March' => 'Março',
7462 'August' => 'Agosto',
7463 'September' => 'Setembro',
7464 'October' => 'Outubro',
7465 'November' => 'Novembro',
7466 'December' => 'Dezembro',
7471 'Table of Contents' => 'Table des matières',
7472 'Short Table of Contents' => 'Résumée du contenu',
7474 'About This Document' => 'A propos de ce document',
7475 'Footnotes' => 'Notes de bas de page',
7478 'section' => 'section',
7479 'January' => 'Janvier',
7480 'February' => 'Février',
7485 'July' => 'Juillet',
7486 'August' => 'Août',
7487 'September' => 'Septembre',
7488 'October' => 'Octobre',
7489 'November' => 'Novembre',
7490 'December' => 'Décembre',
7491 'T2H_today' => 'le %2$d %1$s %3$d'
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,
7508 if (defined($lang) && exists($Texi2HTML::Config::LANGUAGES->{$lang}) && defined($Texi2HTML::Config::LANGUAGES->{$lang}))
7522 'January', 'February', 'March', 'April', 'May',
7523 'June', 'July', 'August', 'September', 'October',
7524 'November', 'December'
7527 my $I = \&get_string;
7532 my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
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 });
7543 my $error_no_en = 0;
7544 sub get_string($;$$)
7547 my $arguments = shift;
7549 my $T2H_LANGUAGES = $Texi2HTML::Config::LANGUAGES;
7550 if (! exists($T2H_LANGUAGES->{'en'}))
7552 unless($error_no_en)
7554 print STDERR "i18n: no LANGUAGES->{'en'} hash\n";
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 ''))
7564 $string = $T2H_LANGUAGES->{$language}->{$string};
7566 elsif (defined ($T2H_LANGUAGES->{'en'}->{$string}) and
7567 ($T2H_LANGUAGES->{'en'}->{$string} ne ''))
7569 $string = $T2H_LANGUAGES->{'en'}->{$string};
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}
7577 if (!$state->{'keep_texi'})
7581 if ($string =~ s/^([^%]*)%//)
7583 $result .= $1 if (defined($1));
7585 if ($string =~ s/^%//)
7589 elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
7591 $string =~ s/^\{(\w+)\}//;
7592 $result .= "\@\{$1\@\}";
7606 $string = main::substitute_line($result, $state);
7608 # now we substitute the arguments
7612 if ($string =~ s/^([^%]*)%//)
7614 $result .= $1 if (defined($1));
7615 if ($string =~ s/^%//)
7619 elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1}))
7621 $string =~ s/^\{(\w+)\}//;
7622 $result .= $arguments->{$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");
7645 #########################################################################
7649 #---######################################################################
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
7657 #+##############################################################################
7659 # T2h_l2h.pm: interface to LaTeX2HTML
7661 # Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>,
7662 # Derek Price <derek@ximbiot.com>,
7663 # Adrian Aichner <adrian@xemacs.org>,
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.
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.
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
7681 #-##############################################################################
7686 package Texi2HTML::LaTeX2HTML;
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
7696 # init l2h defaults for files and names
7698 # global variable used for caching
7703 my ($l2h_name, $l2h_latex_file, $l2h_cache_file, $l2h_html_file, $l2h_prefix);
7705 # holds the status of latex2html operations. If 0 it means that there was
7716 ##########################
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
7724 my $l2h_latex_preamble = <<EOT;
7725 % This document was automatically generated by the l2h extenstion of texi2html
7727 \\documentclass{article}
7732 my $l2h_latex_closing = <<EOT;
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
7748 my %global_count = (); # associate a command name and the
7749 # corresponding counter to the index in the
7752 # set $status to 1, if l2h could be initalized properly, to 0 otherwise
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;
7768 unless ($Texi2HTML::Config::L2H_SKIP)
7770 unless (open(L2H_LATEX, ">$l2h_latex_file"))
7772 warn "$ERROR l2h: Can't open latex file '$l2h_latex_file' for writing: $!\n";
7776 warn "# l2h: use ${l2h_latex_file} as latex file\n" if ($verbose);
7777 print L2H_LATEX $l2h_latex_preamble;
7779 # open the database that holds cached text
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.
7790 my $command = shift;
7792 my $counter = shift;
7793 if ($command eq 'tex')
7797 elsif ($command eq 'math')
7799 $text = "\$".$text."\$";
7802 $text =~ s/(\s*)$//;
7803 # try whether we have text already on things to do
7804 my $count = $l2h_to_latex{$text};
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))
7814 # put the cached result in the html result array
7815 $l2h_from_html[$count] = $cached_text;
7819 $latex_converted_count++;
7820 unless ($Texi2HTML::Config::L2H_SKIP)
7822 print L2H_LATEX "\\begin{rawhtml}\n";
7823 print L2H_LATEX "<!-- l2h_begin $l2h_name $count -->\n";
7824 print L2H_LATEX "\\end{rawhtml}\n";
7826 print L2H_LATEX "$text\n";
7828 print L2H_LATEX "\\begin{rawhtml}\n";
7829 print L2H_LATEX "<!-- l2h_end $l2h_name $count -->\n";
7830 print L2H_LATEX "\\end{rawhtml}\n";
7833 $l2h_to_latex[$count] = $text;
7834 $l2h_to_latex{$text} = $count;
7836 $global_count{"${command}_$counter"} = $count;
7840 # print closing into latex file and close it
7841 sub finish_to_latex()
7843 my $reused = $to_latex_count - $latex_converted_count - $cached_count;
7844 unless ($Texi2HTML::Config::L2H_SKIP)
7846 print L2H_LATEX $l2h_latex_closing;
7849 warn "# l2h: finished to latex ($cached_count cached, $reused reused, $latex_converted_count to process)\n" if ($verbose);
7850 unless ($latex_count)
7859 ###################################
7860 # Second stage: Use latex2html to generate corresponding html code and images
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
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))
7875 warn "# l2h: skipping latex2html run\n" if ($verbose);
7878 # Check for dot in directory where dvips will work
7879 if ($Texi2HTML::Config::L2H_TMP)
7881 if ($Texi2HTML::Config::L2H_TMP =~ /\./)
7883 warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n";
7891 warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n";
7895 # fix it, if necessary and hope that it works
7896 $Texi2HTML::Config::L2H_TMP = "/tmp" if ($dotbug);
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);
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";
7912 warn "# l2h: executing '$call'\n" if ($verbose);
7915 warn "$ERROR l2h: '${call}' did not succeed\n";
7920 warn "# l2h: latex2html finished successfully\n" if ($verbose);
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"
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($)
7941 my $content = shift;
7942 my @images = ($content =~ /SRC="(.*?)"/g);
7947 $dest = $l2h_img{$src};
7951 if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext)
7957 warn "$ERROR: L2h image $src has invalid extension\n";
7960 while (-e "$docu_rdir${docu_name}_${image_count}$ext")
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);
7971 $content =~ s/SRC="$src"/SRC="$dest"/g;
7976 my $extract_error_count = 0;
7977 my $invalid_counter_count = 0;
7979 sub init_from_html()
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)
7989 if (! open(L2H_HTML, "<$l2h_html_file"))
7991 warn "$ERROR l2h: Can't open $l2h_html_file for reading\n";
7994 warn "# l2h: use $l2h_html_file as html file\n" if ($verbose);
7996 my $html_converted_count = 0; # number of html resulting texts
7997 # retrieved in the file
7999 my ($count, $h_line);
8000 while ($h_line = <L2H_HTML>)
8002 if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/)
8006 my $h_end_found = 0;
8007 while ($h_line = <L2H_HTML>)
8009 if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/)
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;
8023 $h_content = $h_content.$h_line;
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";
8034 # Not the same number of converted elements and retrieved elements
8035 if ($latex_converted_count != $html_converted_count)
8037 warn "$ERROR l2h(BUG): waiting for $latex_converted_count elements found $html_converted_count\n";
8040 warn "# l2h: Got $html_converted_count of $latex_count html contents\n"
8047 my $html_output_count = 0; # html text outputed in html result file
8049 # called each time a construct handled by latex2html is encountered, should
8050 # output the corresponding html
8054 my $counter = shift;
8056 my $count = $global_count{"${style}_$counter"};
8057 ################################## begin debug section (incorrect counts)
8058 if (!defined($count))
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 -->")
8067 elsif(($count <= 0) or ($count > $latex_count))
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 -->")
8076 ################################## end debug section (incorrect counts)
8078 # this seems to be a valid counter
8080 $result = "<!-- l2h_begin $l2h_name $count -->" if ($debug);
8081 if (defined($l2h_from_html[$count]))
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];
8093 $result .= $l2h_from_html[$count];
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]);
8105 $result .= "<!-- l2h_end $l2h_name $count -->" if ($debug);
8109 # store results in the cache and remove temporary files.
8112 return unless($status);
8115 if ($extract_error_count + $invalid_counter_count)
8117 warn "# l2h: finished from html ($extract_error_count extract and $invalid_counter_count invalid counter errors)\n";
8121 warn "# l2h: finished from html (no error)\n";
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";
8131 if ($Texi2HTML::Config::L2H_CLEAN)
8134 warn "# l2h: removing temporary files generated by l2h extension\n"
8136 while (<"$docu_rdir$l2h_name"*>)
8138 # FIXME error condition not checked
8142 warn "# l2h: Finished\n" if $verbose;
8146 # the driver of end of first pass, second pass and beginning of third pass
8150 return unless($status);
8151 return unless ($status = finish_to_latex());
8152 return unless ($status = to_html());
8153 return unless ($status = init_from_html());
8157 ##############################
8158 # stuff for l2h caching
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
8165 if (-r "$l2h_cache_file")
8167 my $rdo = do "$l2h_cache_file";
8168 warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n")
8173 # store all the text obtained through latex2html
8176 return unless $latex_count;
8178 unless (open(FH, ">$l2h_cache_file"))
8180 warn "$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n";
8183 while (($key, $value) = each %l2h_cache)
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";
8201 # return cached html, if it exists for text, and if all pictures
8202 # are there, as well
8206 my $cached = $l2h_cache{$text};
8207 if (defined($cached))
8209 while ($cached =~ m/SRC="(.*?)"/g)
8211 unless (-e "$docu_rdir$1")
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");
8231 package Texi2HTML::LaTeX2HTML::Config;
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.
8238 my $ANTI_ALIAS_TEXT;
8247 my $EXTERNAL_IMAGES;
8248 my $EXTERNAL_UP_LINK;
8249 my $EXTERNAL_UP_TITLE;
8250 my $FIGURE_SCALE_FACTOR;
8257 my $MATH_SCALE_FACTOR;
8259 my $MAX_SPLIT_DEPTH;
8274 my $SHOW_SECTION_NUMBERS;
8278 my $TITLES_LANGUAGE;
8281 my $WORDS_IN_NAVIGATION_PANEL_TITLES;
8286 ######################################################################
8287 # from here on, its l2h init stuff
8290 ## initialization for latex2html as for Singular manual generation
8294 # Options controlling Titles, File-Names, Tracing and Sectioning
8314 $MAX_LINK_DEPTH = 0;
8323 # Options controlling Extensions and Special Features
8325 #$HTML_VERSION = "3.2"; # set by command line
8327 $TEXDEFS = 1; # we absolutely need that
8329 $EXTERNAL_FILE = '';
8331 $SCALABLE_FONTS = 1;
8333 $NO_SIMPLE_MATH = 1;
8346 # Switches controlling Image Generation
8352 $EXTERNAL_IMAGES = 0;
8364 $ANTI_ALIAS_TEXT = 1;
8367 #Switches controlling Navigation Panels
8371 $INFO = 0; # 0 = do not make a "About this document..." section
8374 #Switches for Linking to other documents
8376 # currently -- we don't care
8378 $MAX_SPLIT_DEPTH = 0; # Stop making separate files at this depth
8380 $MAX_LINK_DEPTH = 0; # Stop showing child nodes at this depth
8382 $NOLATEX = 0; # 1 = do not pass unknown environments to Latex
8384 $EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document
8386 $ASCII_MODE = 0; # 1 = do not use any icons or internal images
8388 # 1 = use links to external postscript images rather than inlined bitmap
8391 $SHOW_SECTION_NUMBERS = 0;
8393 ### Other global variables ###############################################
8396 # This is the line width measured in pixels and it is used to right justify
8397 # equations and equation arrays;
8400 # Used in conjunction with AUTO_NAVIGATION
8401 $WORDS_IN_PAGE = 300;
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)
8406 $WORDS_IN_NAVIGATION_PANEL_TITLES = 0;
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"
8412 # Effective values are those greater than 0.
8413 # Sensible values are between 0.1 - 4.
8414 $MATH_SCALE_FACTOR = 1.5;
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;
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 = "";
8430 # If this is set then the resulting HTML will look marginally better if viewed
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
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";
8448 1; # This must be the last non-comment line
8451 ######################################################################
8458 # pre-defined indices
8461 my %index_prefix_to_name = ();
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}
8473 foreach my $name(keys(%index_names))
8475 foreach my $prefix (@{$index_names{$name}->{'prefix'}})
8477 $forbidden_index_name{$prefix} = 1;
8478 $index_prefix_to_name{$prefix} = $name;
8482 foreach my $other_forbidden_index_name ('info','ps','pdf','htm',
8483 'log','aux','dvi','texi','txi','texinfo','tex','bib')
8485 $forbidden_index_name{$other_forbidden_index_name} = 1;
8488 # commands with ---, -- '' and `` preserved
8489 # usefull with the old interface
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;
8515 # delete from hash if we are using the new interface
8516 foreach my $code (keys(%code_style_map))
8518 delete ($code_style_map{$code})
8519 if (ref($::style_map_ref->{$code}) eq 'HASH');
8522 # no paragraph in these commands
8523 my %no_paragraph_macro = (
8533 # texinfo section names to level
8546 'unnumberedsubsec', 3,
8548 'appendixsubsec', 3,
8550 'unnumberedsubsubsec', 4,
8552 'appendixsubsubsec', 4,
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.
8561 my $appendices = [ ];
8562 my $unnumbered = [ ];
8564 foreach my $command (keys (%sec2level))
8566 if ($command =~ /^appendix/)
8568 $level2sec{$command} = $appendices;
8570 elsif ($command =~ /^unnumbered/ or $command eq 'top')
8572 $level2sec{$command} = $unnumbered;
8574 elsif ($command =~ /section$/ or $command eq 'chapter')
8576 $level2sec{$command} = $sections;
8580 $level2sec{$command} = $headings;
8582 $level2sec{$command}->[$sec2level{$command}] = $command;
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;
8593 # sction to level hash not taking into account raise and lower sections
8594 my %reference_sec2level = %sec2level;
8596 # regions treated especially. The text for these regions is collected in the
8597 # corresponding array
8600 'documentdescription' => [ ],
8604 # those macros aren't considered as beginning a paragraph
8605 my %no_line_macros = (
8622 'shortcaption' => 1,
8625 foreach my $key (keys(%Texi2HTML::Config::misc_command))
8627 $no_line_macros{$key} = 1;
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 = ();
8634 foreach my $simple_format (keys(%Texi2HTML::Config::format_map))
8636 $format_type{$simple_format} = 'simple_format';
8638 foreach my $paragraph_style (keys(%Texi2HTML::Config::paragraph_style))
8640 $format_type{$paragraph_style} = 'paragraph_format';
8642 foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map))
8644 $format_type{$complex_format} = 'complex_format';
8646 foreach my $table (('table', 'ftable', 'vtable', 'multitable'))
8648 $format_type{$table} = 'table';
8650 foreach my $def_format (keys(%Texi2HTML::Config::def_map))
8652 $format_type{$def_format} = 'deff';
8654 $format_type{'itemize'} = 'list';
8655 $format_type{'enumerate'} = 'list';
8657 $format_type{'menu'} = 'menu';
8659 $format_type{'cartouche'} = 'cartouche';
8661 $format_type{'float'} = 'float';
8663 $format_type{'quotation'} = 'quotation';
8665 $format_type{'group'} = 'group';
8667 foreach my $key (keys(%format_type))
8669 $no_line_macros{$key} = 1;
8670 $no_line_macros{"end $key"} = 1;
8673 foreach my $macro (keys(%Texi2HTML::Config::format_in_paragraph))
8675 $no_line_macros{$macro} = 1;
8676 $no_line_macros{"end $macro"} = 1;
8679 # fake format at the bottom of the stack
8680 $format_type{'noformat'} = '';
8682 # fake formats are formats used internally within other formats
8683 # we associate them with a real format, for the error messages
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',
8696 foreach my $key (keys(%fake_format))
8698 $format_type{$key} = 'fake';
8701 # raw formats which are expanded especially
8702 my @raw_regions = ('html', 'verbatim', 'tex', 'xml', 'docbook');
8704 # regions expanded or not depending on the value of this hash
8718 'documentdescription' => 1,
8722 'ifnotplaintext' => 1,
8725 'ifnotdocbook' => 1,
8727 'verbatim' => 'raw',
8728 'ifclear' => 'value',
8729 'ifset' => 'value' ,
8732 foreach my $key (keys(%text_macros))
8734 unless ($text_macros{$key} eq 'raw')
8736 $no_line_macros{$key} = 1;
8737 $no_line_macros{"end $key"} = 1;
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))
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"}));
8750 #+++############################################################################
8752 # Argument parsing, initialisation #
8754 #---############################################################################
8757 # flush stdout and stderr after every write
8764 my $I = \&Texi2HTML::I18n::get_string;
8766 my $T2H_USER; # user running the script
8767 my $documentdescription; # text in @documentdescription
8769 # shorthand for Texi2HTML::Config::VERBOSE
8774 #print STDERR "" . &$I('test i18n: \' , \a \\ %% %{unknown}a %known % %{known} \\', { 'known' => 'a known string', 'no' => 'nope'}); exit 0;
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
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($;$$)
8784 my $all_files = shift;
8785 my $directories = shift;
8787 $directories = \@texi2html_config_dirs if !defined($directories);
8791 return $file if (-e $file and -r $file);
8796 foreach my $dir (@$directories)
8798 next unless (-d "$dir");
8801 push (@files, "$dir/$file") if (-e "$dir/$file" and -r "$dir/$file");
8805 return "$dir/$file" if (-e "$dir/$file" and -r "$dir/$file");
8808 return @files if ($all_files);
8813 # called on -init-file
8816 # First argument is option
8818 # second argument is value of options
8819 my $init_file = shift;
8821 if ($file = locate_init_file($init_file))
8823 print STDERR "# reading initialization file from $file\n"
8825 return (Texi2HTML::Config::load($file));
8829 print STDERR "$ERROR Error: can't read init file $init_file\n";
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
8840 sub set_document_language ($;$$)
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)
8848 Texi2HTML::Config::load($file);
8850 if (Texi2HTML::I18n::set_language($lang))
8852 print STDERR "# using '$lang' as document language\n" if ($T2H_VERBOSE);
8853 $Texi2HTML::Config::LANG = $lang;
8855 $cmd_line_lang = 1 if ($from_command_line);
8856 if (!$Texi2HTML::Config::TEST)
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";
8863 $Texi2HTML::THISDOC{'today'} = 'a sunny day';
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'};
8873 echo_error ("Language specs for '$lang' do not exists. Reverting to '$Texi2HTML::Config::LANG'", $line_nr);
8877 # used to manage expanded sections from the command line
8878 sub set_expansion($$)
8882 $set = 1 if (!defined($set));
8885 push (@Texi2HTML::Config::EXPAND, $region) unless (grep {$_ eq $region} @Texi2HTML::Config::EXPAND);
8889 @Texi2HTML::Config::EXPAND = grep {$_ ne $region} @Texi2HTML::Config::EXPAND;
8894 # find the encoding alias.
8895 # with encoding support (USE_UNICODE), may return undef if no alias was found
8896 sub encoding_alias($)
8898 my $encoding = shift;
8899 return $encoding if (!defined($encoding) or $encoding eq '');
8900 if ($Texi2HTML::Config::USE_UNICODE)
8902 if (! Encode::resolve_alias($encoding))
8904 echo_warn("Encoding $encoding unknown");
8907 print STDERR "# Using encoding " . Encode::resolve_alias($encoding) . "\n"
8909 return Encode::resolve_alias($encoding);
8913 echo_warn("No alias searched for encoding");
8918 # setup hashes used for html manual cross references in texinfo
8919 my %cross_ref_texi_map = %Texi2HTML::Config::texi_map;
8921 $cross_ref_texi_map{'enddots'} = '...';
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 = ();
8927 my %cross_transliterate_texi_map = %cross_ref_texi_map;
8929 foreach my $command (keys(%Texi2HTML::Config::style_map_texi))
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}}))
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};
8943 $cross_ref_simple_map_texi{"\n"} = ' ';
8944 $cross_ref_simple_map_texi{"*"} = ' ';
8946 my %nodes = (); # nodes hash. The key is the texi node name
8947 my %cross_reference_nodes = (); # normalized node names arrays
8949 # This function is used to construct link names from node names as
8950 # specified for texinfo
8951 sub cross_manual_links()
8953 print STDERR "# Doing ".scalar(keys(%nodes))." cross manual links\n"
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;
8961 foreach my $key (keys(%nodes))
8963 my $node = $nodes{$key};
8964 #print STDERR "CROSS_MANUAL:$key,$node\n";
8965 next if ($node->{'index_page'});
8966 if (!defined($node->{'texi'}))
8968 ###################### debug section
8969 foreach my $key (keys(%$node))
8971 #print STDERR "$key:$node->{$key}!!!\n";
8973 ###################### end debug section
8977 $node->{'cross_manual_target'} = remove_texi($node->{'texi'});
8978 if ($Texi2HTML::Config::USE_UNICODE)
8980 $node->{'cross_manual_target'} = Unicode::Normalize::NFC($node->{'cross_manual_target'});
8981 if ($Texi2HTML::Config::TRANSLITERATE_NODE and $Texi2HTML::Config::USE_UNIDECODE)
8983 $node->{'cross_manual_file'} =
8984 unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_target'}));
8986 $node->{'cross_manual_target'} =
8987 unicode_to_protected($node->{'cross_manual_target'});
8989 #print STDERR "CROSS_MANUAL_TARGET $node->{'cross_manual_target'}\n";
8990 unless ($node->{'external_node'})
8992 if (exists($cross_reference_nodes{$node->{'cross_manual_target'}}))
8994 my $other_node_array = $cross_reference_nodes{$node->{'cross_manual_target'}};
8996 foreach my $other_node (@{$other_node_array})
8998 $node_seen = $other_node;
8999 last if ($nodes{$other_node}->{'seen'})
9001 echo_error("Node equivalent with `$node->{'texi'}' allready used `$node_seen'");
9002 push @{$other_node_array}, $node->{'texi'};
9006 push @{$cross_reference_nodes{$node->{'cross_manual_target'}}}, $node->{'texi'};
9013 if ($Texi2HTML::Config::TRANSLITERATE_NODE and
9014 (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
9016 $::style_map_texi_ref = \%cross_transliterate_style_map_texi;
9017 $::texi_map_ref = \%cross_transliterate_texi_map;
9019 foreach my $key (keys(%nodes))
9021 my $node = $nodes{$key};
9022 next if ($node->{'index_page'});
9023 if (defined($node->{'texi'}))
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);
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;
9037 sub unicode_to_protected($)
9043 if ($text =~ s/^([A-Za-z0-9]+)//o)
9047 elsif ($text =~ s/^ //o)
9051 elsif ($text =~ s/^(.)//o)
9053 if (exists($Texi2HTML::Config::ascii_character_map{$1}))
9055 $result .= '_' . lc($Texi2HTML::Config::ascii_character_map{$1});
9059 $result .= '_' . lc(sprintf("%04x",ord($1)));
9064 print STDERR "Bug: unknown character in a cross ref (likely in infinite loop)\n";
9065 print STDERR "Text: !!$text!!\n";
9072 sub unicode_to_transliterate($)
9078 if ($text =~ s/^([A-Za-z0-9 ]+)//o)
9082 elsif ($text =~ s/^(.)//o)
9084 if (exists($Texi2HTML::Config::ascii_character_map{$1}))
9088 elsif (exists($Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))}))
9090 $result .= $Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))};
9092 elsif (exists($Texi2HTML::Config::unicode_diacritical{uc(sprintf("%04x",ord($1)))}))
9098 if ($Texi2HTML::Config::USE_UNIDECODE)
9100 $result .= unidecode($1);
9110 print STDERR "Bug: unknown character in cross ref transliteration (likely in infinite loop)\n";
9117 # This function is used to construct a link name from a node name as
9118 # specified for texinfo
9119 sub cross_manual_line($;$)
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;
9131 my ($cross_ref_target, $cross_ref_file);
9132 if ($Texi2HTML::Config::USE_UNICODE)
9134 $cross_ref_target = Unicode::Normalize::NFC(remove_texi($text));
9135 if ($transliterate and $Texi2HTML::Config::USE_UNIDECODE)
9138 unicode_to_protected(unicode_to_transliterate($cross_ref_target));
9140 $cross_ref_target = unicode_to_protected($cross_ref_target);
9144 $cross_ref_target = remove_texi($text);
9147 if ($transliterate and
9148 (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE))
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);
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)
9164 return $cross_ref_target;
9166 # print STDERR "$text|$cross_ref_target|$cross_ref_file\n";
9167 return ($cross_ref_target, $cross_ref_file);
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
9178 $T2H_OPTIONS -> {'debug'} =
9181 linkage => \$Texi2HTML::Config::DEBUG,
9182 verbose => 'output HTML with debuging information',
9185 $T2H_OPTIONS -> {'doctype'} =
9188 linkage => \$Texi2HTML::Config::DOCTYPE,
9189 verbose => 'document type which is output in header of HTML files',
9193 $T2H_OPTIONS -> {'frameset-doctype'} =
9196 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
9197 verbose => 'document type for HTML frameset documents',
9201 $T2H_OPTIONS -> {'test'} =
9204 linkage => \$Texi2HTML::Config::TEST,
9205 verbose => 'use predefined information to avoid differences with reference files',
9209 $T2H_OPTIONS -> {'dump-texi'} =
9212 linkage => \$Texi2HTML::Config::DUMP_TEXI,
9213 verbose => 'dump the output of first pass into a file with extension passfirst and exit',
9217 $T2H_OPTIONS -> {'macro-expand'} =
9220 linkage => \$Texi2HTML::Config::MACRO_EXPAND,
9221 verbose => 'output macro expanded source in <file>',
9224 $T2H_OPTIONS -> {'expand'} =
9227 linkage => sub {set_expansion($_[1], 1);},
9228 verbose => 'Expand info|tex|none section of texinfo source',
9232 $T2H_OPTIONS -> {'no-expand'} =
9235 linkage => sub {set_expansion ($_[1], 0);},
9236 verbose => 'Don\'t expand the given section of texinfo source',
9239 $T2H_OPTIONS -> {'noexpand'} =
9242 linkage => $T2H_OPTIONS->{'no-expand'}->{'linkage'},
9243 verbose => $T2H_OPTIONS->{'no-expand'}->{'verbose'},
9247 $T2H_OPTIONS -> {'ifhtml'} =
9250 linkage => sub { set_expansion('html', $_[1]); },
9251 verbose => "expand ifhtml and html sections",
9254 $T2H_OPTIONS -> {'ifinfo'} =
9257 linkage => sub { set_expansion('info', $_[1]); },
9258 verbose => "expand ifinfo",
9261 $T2H_OPTIONS -> {'ifxml'} =
9264 linkage => sub { set_expansion('xml', $_[1]); },
9265 verbose => "expand ifxml and xml sections",
9268 $T2H_OPTIONS -> {'ifdocbook'} =
9271 linkage => sub { set_expansion('docbook', $_[1]); },
9272 verbose => "expand ifdocbook and docbook sections",
9275 $T2H_OPTIONS -> {'iftex'} =
9278 linkage => sub { set_expansion('tex', $_[1]); },
9279 verbose => "expand iftex and tex sections",
9282 $T2H_OPTIONS -> {'ifplaintext'} =
9285 linkage => sub { set_expansion('plaintext', $_[1]); },
9286 verbose => "expand ifplaintext sections",
9289 $T2H_OPTIONS -> {'invisible'} =
9292 linkage => \$Texi2HTML::Config::INVISIBLE_MARK,
9293 verbose => 'use text in invisble anchor',
9297 $T2H_OPTIONS -> {'iso'} =
9300 linkage => \$Texi2HTML::Config::USE_ISO,
9301 verbose => 'if set, ISO8859 characters are used for special symbols (like copyright, etc)',
9305 $T2H_OPTIONS -> {'I'} =
9308 linkage => \@Texi2HTML::Config::INCLUDE_DIRS,
9309 verbose => 'append $s to the @include search path',
9312 $T2H_OPTIONS -> {'conf-dir'} =
9315 linkage => \@Texi2HTML::Config::CONF_DIRS,
9316 verbose => 'append $s to the init file directories',
9319 $T2H_OPTIONS -> {'P'} =
9322 linkage => sub {unshift (@Texi2HTML::Config::PREPEND_DIRS, $_[1]);},
9323 verbose => 'prepend $s to the @include search path',
9326 $T2H_OPTIONS -> {'top-file'} =
9329 linkage => \$Texi2HTML::Config::TOP_FILE,
9330 verbose => 'use $s as top file, instead of <docname>.html',
9333 $T2H_OPTIONS -> {'toc-file'} =
9336 linkage => \$Texi2HTML::Config::TOC_FILE,
9337 verbose => 'use $s as ToC file, instead of <docname>_toc.html',
9340 $T2H_OPTIONS -> {'frames'} =
9343 linkage => \$Texi2HTML::Config::FRAMES,
9344 verbose => 'output files which use HTML 4.0 frames (experimental)',
9348 $T2H_OPTIONS -> {'menu'} =
9351 linkage => \$Texi2HTML::Config::SHOW_MENU,
9352 verbose => 'output Texinfo menus',
9355 $T2H_OPTIONS -> {'number'} =
9358 linkage => \$Texi2HTML::Config::NUMBER_SECTIONS,
9359 verbose => 'use numbered sections',
9362 $T2H_OPTIONS -> {'use-nodes'} =
9365 linkage => \$Texi2HTML::Config::USE_NODES,
9366 verbose => 'use nodes for sectionning',
9369 $T2H_OPTIONS -> {'node-files'} =
9372 linkage => \$Texi2HTML::Config::NODE_FILES,
9373 verbose => 'produce one file per node for cross references'
9376 $T2H_OPTIONS -> {'separated-footnotes'} =
9379 linkage => \$Texi2HTML::Config::SEPARATED_FOOTNOTES,
9380 verbose => 'footnotes on a separated page',
9384 $T2H_OPTIONS -> {'toc-links'} =
9387 linkage => \$Texi2HTML::Config::TOC_LINKS,
9388 verbose => 'create links from headings to toc entries'
9391 $T2H_OPTIONS -> {'split'} =
9394 linkage => \$Texi2HTML::Config::SPLIT,
9395 verbose => 'split document on section|chapter|node else no splitting',
9398 $T2H_OPTIONS -> {'sec-nav'} =
9401 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9402 verbose => 'output navigation panels for each section',
9405 $T2H_OPTIONS -> {'subdir'} =
9408 linkage => \$Texi2HTML::Config::SUBDIR,
9409 verbose => 'put files in directory $s, not $cwd',
9413 $T2H_OPTIONS -> {'short-ext'} =
9416 linkage => \$Texi2HTML::Config::SHORTEXTN,
9417 verbose => 'use "htm" extension for output HTML files',
9420 $T2H_OPTIONS -> {'prefix'} =
9423 linkage => \$Texi2HTML::Config::PREFIX,
9424 verbose => 'use as prefix for output files, instead of <docname>',
9427 $T2H_OPTIONS -> {'output'} =
9430 linkage => \$Texi2HTML::Config::OUT,
9431 verbose => 'output goes to $s (directory if split)',
9434 $T2H_OPTIONS -> {'no-validate'} =
9437 linkage => \$Texi2HTML::Config::NOVALIDATE,
9438 verbose => 'suppress node cross-reference validation',
9441 $T2H_OPTIONS -> {'short-ref'} =
9444 linkage => \$Texi2HTML::Config::SHORT_REF,
9445 verbose => 'if set, references are without section numbers',
9448 $T2H_OPTIONS -> {'idx-sum'} =
9451 linkage => \$Texi2HTML::Config::IDX_SUMMARY,
9452 verbose => 'if set, also output index summary',
9456 $T2H_OPTIONS -> {'def-table'} =
9459 linkage => \$Texi2HTML::Config::DEF_TABLE,
9460 verbose => 'if set, \@def.. are converted using tables.',
9464 $T2H_OPTIONS -> {'Verbose'} =
9467 linkage=> \$Texi2HTML::Config::VERBOSE,
9468 verbose => 'print progress info to stdout',
9471 $T2H_OPTIONS -> {'lang'} =
9474 linkage => sub {set_document_language($_[1], 1)},
9475 verbose => 'use $s as document language (ISO 639 encoding)',
9478 $T2H_OPTIONS -> {'ignore-preamble-text'} =
9481 linkage => \$Texi2HTML::Config::IGNORE_PREAMBLE_TEXT,
9482 verbose => 'if set, ignore the text before @node and sectionning commands',
9486 $T2H_OPTIONS -> {'html-xref-prefix'} =
9489 linkage => \$Texi2HTML::Config::EXTERNAL_DIR,
9490 verbose => '$s is the base dir for external manual references',
9494 $T2H_OPTIONS -> {'l2h'} =
9497 linkage => \$Texi2HTML::Config::L2H,
9498 verbose => 'if set, uses latex2html for @math and @tex',
9501 $T2H_OPTIONS -> {'l2h-l2h'} =
9504 linkage => \$Texi2HTML::Config::L2H_L2H,
9505 verbose => 'program to use for latex2html translation',
9509 $T2H_OPTIONS -> {'l2h-skip'} =
9512 linkage => \$Texi2HTML::Config::L2H_SKIP,
9513 verbose => 'if set, tries to reuse previously latex2html output',
9517 $T2H_OPTIONS -> {'l2h-tmp'} =
9520 linkage => \$Texi2HTML::Config::L2H_TMP,
9521 verbose => 'if set, uses $s as temporary latex2html directory',
9525 $T2H_OPTIONS -> {'l2h-file'} =
9528 linkage => \$Texi2HTML::Config::L2H_FILE,
9529 verbose => 'if set, uses $s as latex2html init file',
9534 $T2H_OPTIONS -> {'l2h-clean'} =
9537 linkage => \$Texi2HTML::Config::L2H_CLEAN,
9538 verbose => 'if set, do not keep intermediate latex2html files for later reuse',
9542 $T2H_OPTIONS -> {'D'} =
9545 linkage => sub {$value{$_[1]} = 1;},
9546 verbose => 'equivalent to Texinfo "@set $s 1"',
9550 $T2H_OPTIONS -> {'U'} =
9553 linkage => sub {delete $value{$_[1]};},
9554 verbose => 'equivalent to Texinfo "@clear $s"',
9558 $T2H_OPTIONS -> {'init-file'} =
9561 linkage => \&load_init_file,
9562 verbose => 'load init file $s'
9565 $T2H_OPTIONS -> {'css-include'} =
9568 linkage => \@Texi2HTML::Config::CSS_FILES,
9569 verbose => 'use css file $s'
9573 ## obsolete cmd line options
9575 my $T2H_OBSOLETE_OPTIONS;
9577 $T2H_OBSOLETE_OPTIONS -> {'out-file'} =
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',
9585 $T2H_OBSOLETE_OPTIONS -> {init_file} =
9588 linkage => \&load_init_file,
9589 verbose => 'obsolete, use "-init-file" instead',
9593 $T2H_OBSOLETE_OPTIONS -> {l2h_clean} =
9596 linkage => \$Texi2HTML::Config::L2H_CLEAN,
9597 verbose => 'obsolete, use "-l2h-clean" instead',
9601 $T2H_OBSOLETE_OPTIONS -> {l2h_l2h} =
9604 linkage => \$Texi2HTML::Config::L2H_L2H,
9605 verbose => 'obsolete, use "-l2h-l2h" instead',
9609 $T2H_OBSOLETE_OPTIONS -> {l2h_skip} =
9612 linkage => \$Texi2HTML::Config::L2H_SKIP,
9613 verbose => 'obsolete, use "-l2h-skip" instead',
9617 $T2H_OBSOLETE_OPTIONS -> {l2h_tmp} =
9620 linkage => \$Texi2HTML::Config::L2H_TMP,
9621 verbose => 'obsolete, use "-l2h-tmp" instead',
9625 $T2H_OBSOLETE_OPTIONS -> {out_file} =
9628 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
9629 verbose => 'obsolete, use "-out-file" instead',
9633 $T2H_OBSOLETE_OPTIONS -> {short_ref} =
9636 linkage => \$Texi2HTML::Config::SHORT_REF,
9637 verbose => 'obsolete, use "-short-ref" instead',
9641 $T2H_OBSOLETE_OPTIONS -> {idx_sum} =
9644 linkage => \$Texi2HTML::Config::IDX_SUMMARY,
9645 verbose => 'obsolete, use "-idx-sum" instead',
9649 $T2H_OBSOLETE_OPTIONS -> {def_table} =
9652 linkage => \$Texi2HTML::Config::DEF_TABLE,
9653 verbose => 'obsolete, use "-def-table" instead',
9657 $T2H_OBSOLETE_OPTIONS -> {short_ext} =
9660 linkage => \$Texi2HTML::Config::SHORTEXTN,
9661 verbose => 'obsolete, use "-short-ext" instead',
9665 $T2H_OBSOLETE_OPTIONS -> {sec_nav} =
9668 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9669 verbose => 'obsolete, use "-sec-nav" instead',
9673 $T2H_OBSOLETE_OPTIONS -> {top_file} =
9676 linkage => \$Texi2HTML::Config::TOP_FILE,
9677 verbose => 'obsolete, use "-top-file" instead',
9681 $T2H_OBSOLETE_OPTIONS -> {toc_file} =
9684 linkage => \$Texi2HTML::Config::TOC_FILE,
9685 verbose => 'obsolete, use "-toc-file" instead',
9689 $T2H_OBSOLETE_OPTIONS -> {glossary} =
9692 linkage => \$Texi2HTML::Config::USE_GLOSSARY,
9693 verbose => "this does nothing",
9697 $T2H_OBSOLETE_OPTIONS -> {check} =
9700 linkage => sub {exit 0;},
9701 verbose => "exit without doing anything",
9705 $T2H_OBSOLETE_OPTIONS -> {dump_texi} =
9708 linkage => \$Texi2HTML::Config::DUMP_TEXI,
9709 verbose => 'obsolete, use "-dump-texi" instead',
9713 $T2H_OBSOLETE_OPTIONS -> {frameset_doctype} =
9716 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE,
9717 verbose => 'obsolete, use "-frameset-doctype" instead',
9721 $T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} =
9724 linkage => sub {$Texi2HTML::Config::SECTION_NAVIGATION = 0;},
9725 verbose => 'obsolete, use -nosec_nav',
9728 my $use_acc; # not used
9729 $T2H_OBSOLETE_OPTIONS -> {use_acc} =
9732 linkage => \$use_acc,
9733 verbose => 'obsolete, set to true unconditionnaly',
9736 $T2H_OBSOLETE_OPTIONS -> {expandinfo} =
9739 linkage => sub {push @Texi2HTML::Config::EXPAND, 'info';},
9740 verbose => 'obsolete, use "-expand info" instead',
9743 $T2H_OBSOLETE_OPTIONS -> {expandtex} =
9746 linkage => sub {push @Texi2HTML::Config::EXPAND, 'tex';},
9747 verbose => 'obsolete, use "-expand tex" instead',
9750 $T2H_OBSOLETE_OPTIONS -> {monolithic} =
9753 linkage => sub {$Texi2HTML::Config::SPLIT = '';},
9754 verbose => 'obsolete, use "-split no" instead',
9757 $T2H_OBSOLETE_OPTIONS -> {split_node} =
9760 linkage => sub{$Texi2HTML::Config::SPLIT = 'section';},
9761 verbose => 'obsolete, use "-split section" instead',
9764 $T2H_OBSOLETE_OPTIONS -> {split_chapter} =
9767 linkage => sub{$Texi2HTML::Config::SPLIT = 'chapter';},
9768 verbose => 'obsolete, use "-split chapter" instead',
9771 $T2H_OBSOLETE_OPTIONS -> {no_verbose} =
9774 linkage => sub {$Texi2HTML::Config::VERBOSE = 0;},
9775 verbose => 'obsolete, use -noverbose instead',
9778 $T2H_OBSOLETE_OPTIONS -> {output_file} =
9781 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';},
9782 verbose => 'obsolete, use --out-file instead',
9786 $T2H_OBSOLETE_OPTIONS -> {section_navigation} =
9789 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION,
9790 verbose => 'obsolete, use --sec-nav instead',
9794 $T2H_OBSOLETE_OPTIONS -> {verbose} =
9797 linkage=> \$Texi2HTML::Config::VERBOSE,
9798 verbose => 'obsolete, use -Verbose instead',
9802 # read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc
9803 # (this is obsolete)
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)
9809 if (-e $i and -r $i)
9811 print STDERR "# reading initialization file from $i\n"
9813 print STDERR "Reading config from $i is obsolete, use texi2html/$conf_file_name instead\n";
9814 Texi2HTML::Config::load($i);
9818 # read initialization files
9819 foreach my $file (locate_init_file($conf_file_name, 1))
9821 print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE);
9822 Texi2HTML::Config::load($file);
9826 # %value hold texinfo variables, see also -D, -U, @set and @clear.
9827 # we predefine html (the output format) and texi2html (the translator)
9831 'texi2html' => $THISVERSION,
9834 #+++############################################################################
9836 # parse command-line options
9838 #---############################################################################
9841 my $T2H_USAGE_TEXT = <<EOT;
9842 Usage: texi2html [OPTIONS] TEXINFO-FILE
9843 Translates Texinfo source documentation to HTML.
9845 my $T2H_FAILURE_TEXT = <<EOT;
9846 Try 'texi2html --help' for usage instructions.
9849 my $options = new Getopt::MySimple;
9851 $T2H_OPTIONS -> {'help'} =
9855 linkage => sub {$options->helpOptions($_[1]);
9856 print "\nSend bugs and suggestions to <texi2html-bug\@nongnu.org>\n";
9858 verbose => "print help and exit"
9861 # this avoids getOptions defining twice 'help' and 'version'.
9862 $T2H_OBSOLETE_OPTIONS -> {'help'} = 0;
9863 $T2H_OBSOLETE_OPTIONS -> {'version'} = 0;
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.
9874 if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
9876 print STDERR "$Configure_failed" if $Configure_failed;
9877 die $T2H_FAILURE_TEXT;
9881 eval {Getopt::Long::Configure("no_pass_through");};
9882 if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n"))
9884 print STDERR "$Configure_failed" if $Configure_failed;
9885 die $T2H_FAILURE_TEXT;
9890 # read texi2html extensions (if any)
9891 # It is obsolete (obsoleted by -init-file). we keep it for backward
9893 my $extensions = 'texi2html.ext'; # extensions in working directory
9896 print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
9897 require($extensions);
9900 ($progdir = $0) =~ s/[^\/]+$//;
9901 if ($progdir && ($progdir ne './'))
9903 $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
9906 print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE;
9907 require($extensions);
9911 # $T2H_DEBUG and $T2H_VERBOSE are shorthands
9912 $T2H_DEBUG = $Texi2HTML::Config::DEBUG;
9913 $T2H_VERBOSE = $Texi2HTML::Config::VERBOSE;
9915 $Texi2HTML::THISDOC{'debug_l2h'} = 0;
9916 $Texi2HTML::THISDOC{'debug_l2h'} = 1 if ($T2H_DEBUG & $DEBUG_L2H);
9919 #+++############################################################################
9921 # evaluation of cmd line options
9923 #---############################################################################
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',
9931 foreach my $style (keys(%Texi2HTML::Config::style_map))
9933 if (exists $Texi2HTML::Config::command_type{$style})
9935 $style_type{$style} = $Texi2HTML::Config::command_type{$style};
9938 if (ref($Texi2HTML::Config::style_map{$style} eq 'HASH'))
9940 $style_type{$style} = $Texi2HTML::Config::style_map{$style}->{'type'}
9941 if (exists($Texi2HTML::Config::style_map{$style}->{'type'}));
9945 $style_type{$style} = 'simple_style' if (grep {$_ eq $style} @simple_styles);
9947 $style_type{$style} = 'style' unless (defined($style_type{$style}));
9949 foreach my $accent (keys(%Texi2HTML::Config::unicode_accents), 'tieaccent', 'dotless')
9951 if (exists $Texi2HTML::Config::command_type{$accent})
9953 $style_type{$accent} = $Texi2HTML::Config::command_type{$accent};
9956 $style_type{$accent} = 'accent';
9958 #foreach my $simple ('ctrl', 'w', 'url','uref','indicateurl','email')
9960 # $style_type{$simple} = 'simple_style';
9962 foreach my $special ('footnote', 'ref', 'xref', 'pxref', 'inforef', 'anchor', 'image')
9964 if (exists $Texi2HTML::Config::command_type{$special})
9966 $style_type{$special} = $Texi2HTML::Config::command_type{$special};
9969 $style_type{$special} = 'special';
9972 # retro compatibility for $Texi2HTML::Config::EXPAND
9973 push (@Texi2HTML::Config::EXPAND, $Texi2HTML::Config::EXPAND) if ($Texi2HTML::Config::EXPAND);
9975 unshift @texi2html_config_dirs, @Texi2HTML::Config::CONF_DIRS;
9976 # correct %text_macros based on command line and init
9978 $text_macros{'menu'} = 1 if ($Texi2HTML::Config::SHOW_MENU);
9980 foreach my $expanded (@Texi2HTML::Config::EXPAND)
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)
9986 $text_macros{$expanded} = 'raw';
9990 $text_macros{$expanded} = 1;
9994 # handle ifnot regions
9995 foreach my $region (keys (%text_macros))
9997 next if ($region =~ /^ifnot/);
9998 if ($text_macros{$region} and $region =~ /^if(\w+)$/)
10000 $text_macros{"ifnot$1"} = 0;
10006 print STDERR "# Expanded: ";
10007 foreach my $text_macro (keys(%text_macros))
10009 print STDERR "$text_macro " if ($text_macros{$text_macro});
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';
10018 $T2H_DEBUG |= $DEBUG_TEXI if ($Texi2HTML::Config::DUMP_TEXI);
10020 # no user provided USE_UNICODE, use configure provided
10021 if (!defined($Texi2HTML::Config::USE_UNICODE))
10023 $Texi2HTML::Config::USE_UNICODE = '1';
10026 # no user provided nor configured, run time test
10027 if ($Texi2HTML::Config::USE_UNICODE eq '@' .'USE_UNICODE@')
10029 $Texi2HTML::Config::USE_UNICODE = 1;
10032 require Unicode::Normalize;
10033 Encode->import('encode');
10035 $Texi2HTML::Config::USE_UNICODE = 0 if ($@);
10037 elsif ($Texi2HTML::Config::USE_UNICODE)
10038 {# user provided or set by configure
10040 require Unicode::Normalize;
10041 Encode->import('encode');
10044 # no user provided USE_UNIDECODE, use configure provided
10045 if (!defined($Texi2HTML::Config::USE_UNIDECODE))
10047 $Texi2HTML::Config::USE_UNIDECODE = '0';
10050 # no user provided nor configured, run time test
10051 if ($Texi2HTML::Config::USE_UNIDECODE eq '@' .'USE_UNIDECODE@')
10053 $Texi2HTML::Config::USE_UNIDECODE = 1;
10055 require Text::Unidecode;
10056 Text::Unidecode->import('unidecode');
10058 $Texi2HTML::Config::USE_UNIDECODE = 0 if ($@);
10060 elsif ($Texi2HTML::Config::USE_UNIDECODE)
10061 {# user provided or set by configure
10062 require Text::Unidecode;
10063 Text::Unidecode->import('unidecode');
10066 print STDERR "# USE_UNICODE $Texi2HTML::Config::USE_UNICODE, USE_UNIDECODE $Texi2HTML::Config::USE_UNIDECODE \n"
10069 # Construct hashes used for cross references generation
10070 # Do it now as the user may have changed $USE_UNICODE
10072 foreach my $key (keys(%Texi2HTML::Config::unicode_map))
10074 if ($Texi2HTML::Config::unicode_map{$key} ne '')
10076 if ($Texi2HTML::Config::USE_UNICODE)
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}})))
10082 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
10088 $cross_ref_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
10089 if ($Texi2HTML::Config::TRANSLITERATE_NODE)
10091 if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}))
10093 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}};
10097 $cross_transliterate_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key});
10103 if ($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::TRANSLITERATE_NODE
10104 and ! $Texi2HTML::Config::USE_UNIDECODE)
10106 foreach my $key (keys (%Texi2HTML::Config::transliterate_accent_map))
10108 $Texi2HTML::Config::transliterate_map{$key} = $Texi2HTML::Config::transliterate_accent_map{$key};
10112 foreach my $key (keys(%cross_ref_style_map_texi))
10114 if ($style_type{$key} eq 'accent'
10115 and (ref($cross_ref_style_map_texi{$key}) eq 'HASH'))
10117 if ($Texi2HTML::Config::USE_UNICODE)
10119 $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_utf8_accent;
10123 $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_nounicode_cross_manual_accent;
10125 if ($Texi2HTML::Config::TRANSLITERATE_NODE and
10126 !($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::USE_UNIDECODE))
10128 $cross_transliterate_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_transliterate_cross_manual_accent;
10134 # file name business
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)
10149 die "Need exactly one file to translate\n$T2H_FAILURE_TEXT" unless @ARGV == 1;
10150 my $docu = shift(@ARGV);
10151 if ($docu =~ /(.*\/)/)
10153 chop($docu_dir = $1);
10154 $docu_name = $docu;
10155 $docu_name =~ s/.*\///;
10160 $docu_name = $docu;
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;
10167 # resulting files splitting
10168 if ($Texi2HTML::Config::SPLIT =~ /section/i)
10170 $Texi2HTML::Config::SPLIT = 'section';
10172 elsif ($Texi2HTML::Config::SPLIT =~ /node/i)
10174 $Texi2HTML::Config::SPLIT = 'node';
10176 elsif ($Texi2HTML::Config::SPLIT =~ /chapter/i)
10178 $Texi2HTML::Config::SPLIT = 'chapter';
10182 $Texi2HTML::Config::SPLIT = '';
10185 # Something like backward compatibility
10186 if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SUBDIR)
10188 $Texi2HTML::Config::OUT = $Texi2HTML::Config::SUBDIR;
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 '-'));
10196 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq ''))
10198 $Texi2HTML::Config::OUT = $docu_name;
10201 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq '.'))
10202 {# This is to avoid trouble with latex2html
10203 $Texi2HTML::Config::OUT = '';
10208 if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne ''))
10210 $Texi2HTML::Config::OUT =~ s|/*$||;
10211 $docu_rdir = "$Texi2HTML::Config::OUT/";
10212 unless (-d $Texi2HTML::Config::OUT)
10214 if ( mkdir($Texi2HTML::Config::OUT, oct(755)))
10216 print STDERR "# created directory $Texi2HTML::Config::OUT\n" if ($T2H_VERBOSE);
10220 die "$ERROR can't create directory $Texi2HTML::Config::OUT\n";
10223 print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
10225 elsif (! $Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne ''))
10227 if ($Texi2HTML::Config::OUT =~ m|(.*)/|)
10228 {# there is a leading directories
10229 $docu_rdir = "$1/";
10230 unless (-d $docu_rdir)
10232 if ( mkdir($docu_rdir, oct(755)))
10234 print STDERR "# created directory $docu_rdir\n" if ($T2H_VERBOSE);
10238 die "$ERROR can't create directory $docu_rdir\n";
10241 print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE);
10245 print STDERR "# putting result files into current directory \n" if ($T2H_VERBOSE);
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)
10257 $docu_rdir = 'current directory' if ($docu_rdir eq '');
10258 die "$ERROR $docu_rdir not writable\n";
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 '')
10266 my $docu_path = $docu_rdir;
10267 $docu_path = $cwd . '/' . $docu_path unless ($docu_path =~ /^\//);
10269 foreach my $element (split /\//, File::Spec->canonpath($docu_path))
10271 if ($element eq '')
10275 elsif ($element eq '..')
10277 if (@result and ($result[-1] eq ''))
10279 print STDERR "Too much .. in absolute file name\n";
10281 elsif (@result and ($result[-1] ne '..'))
10287 push @result, $element;
10292 push @result, $element;
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 '');
10301 if ($Texi2HTML::Config::SHORTEXTN)
10306 $docu_doc = $docu_name . ($docu_ext ? ".$docu_ext" : ""); # document's contents
10307 if ($Texi2HTML::Config::SPLIT)
10309 $docu_top = $Texi2HTML::Config::TOP_FILE || $docu_doc;
10311 if (defined $Texi2HTML::Config::element_file_name)
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.
10323 if (!defined($docu_toc))
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;
10329 if (!defined($docu_stoc))
10331 $docu_stoc = "${docu_name}_ovr";
10332 $docu_stoc .= ".$docu_ext" if (defined($docu_ext));
10334 if (!defined($docu_foot))
10336 $docu_foot = "${docu_name}_fot";
10337 $docu_foot .= ".$docu_ext" if (defined($docu_ext));
10339 if (!defined($docu_about))
10341 $docu_about = "${docu_name}_abt";
10342 $docu_about .= ".$docu_ext" if (defined($docu_ext));
10347 if ($Texi2HTML::Config::OUT)
10349 $docu_doc = $Texi2HTML::Config::OUT;
10350 $docu_doc =~ s|.*/||;
10352 if (defined $Texi2HTML::Config::element_file_name)
10354 my $docu_name = &$Texi2HTML::Config::element_file_name
10355 (undef, "doc", $docu_name);
10356 $docu_top = $docu_name if (defined($docu_name));
10358 $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc;
10361 # Note that file extension has already been added here.
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;
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";
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;
10388 # _foo: internal variables to track @foo
10390 foreach my $key ('_author', '_title', '_subtitle', '_shorttitlepage',
10391 '_settitle', '_setfilename', '_shorttitle', '_titlefont')
10393 $value{$key} = ''; # prevent -w warnings
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
10406 my $relative_foot_num = 0;
10409 my $anchor_num = 0;
10412 # can I use ISO8859 characters? (HTML+)
10414 if ($Texi2HTML::Config::USE_ISO)
10416 foreach my $thing (keys(%Texi2HTML::Config::iso_symbols))
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};
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 "'"));
10434 # process a css file
10435 sub process_css_file ($$)
10440 my $in_comment = 0;
10447 #print STDERR "Line: $_";
10457 #print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $_";
10460 if (s/^(.*?\*\/)//)
10467 push @$imports, $text . $_;
10471 elsif (!$in_string and s/^\///)
10472 { # what do '\' do here ?
10480 push (@$imports, $text. "\n") if ($text ne '');
10481 push (@$rules, '/' . $_);
10486 elsif (!$in_string and $in_import and s/^([\"\'])//)
10487 { # strings outside of import start rules
10489 $in_string = quotemeta("$1");
10491 elsif ($in_string and s/^(\\$in_string)//)
10495 elsif ($in_string and s/^($in_string)//)
10500 elsif ((! $in_string and !$in_import) and (s/^([\\]?\@import)$// or s/^([\\]?\@import\s+)//))
10505 elsif (!$in_string and $in_import and s/^\;//)
10510 elsif (($in_import or $in_string) and s/^(.)//)
10514 elsif (!$in_import and s/^([^\s])//)
10516 push (@$imports, $text. "\n") if ($text ne '');
10517 push (@$rules, $1 . $_);
10527 push (@$imports, $text);
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);
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)
10545 print STDERR "html refs config file: $file\n" if ($T2H_DEBUG);
10546 unless (open (HTMLXREF, $file))
10548 warn "Cannot open html refs config file ${file}: $!";
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'))
10562 echo_warn("Bad line in $file: $line");
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'}));
10568 if (defined($href))
10570 $href =~ s/\/*$// if ($split_or_mono eq 'split');
10571 $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'} = $href;
10575 $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono} = {};
10583 foreach my $manual (keys(%{$Texi2HTML::THISDOC{'htmlxref'}}))
10585 foreach my $split ('split', 'mono')
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";
10596 print STDERR "# reading from $docu\n" if $T2H_VERBOSE;
10598 #+++###########################################################################
10600 # Pass texi: read source, handle variable, ignored text, #
10602 #---###########################################################################
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
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
10615 sub initialise_state_texi($)
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'}));
10625 my @first_lines = ();
10629 my $first_lines = 1; # is it the first lines
10631 # holds the informations about the context
10632 # to pass it down to the functions
10633 initialise_state_texi($state);
10636 INPUT_LINE: while (defined($_ = next_line($texi_line_number)))
10639 # remove the lines preceding \input or an @-command
10645 push @first_lines, $_;
10655 push @first_lines, $_;
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))
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'} });
10668 #dump_stack (\$text, \@stack, $state);
10669 if ($state->{'bye'})
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);
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'});
10686 push @lines, split_lines($_);
10687 last if ($state->{'bye'});
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;
10696 # return the line after preserving things according to misc_command map.
10697 sub preserve_command($$)
10703 my $skip_spec = '';
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'}));
10711 if ($arg_spec eq 'line')
10719 my $arg_nr = $Texi2HTML::Config::misc_command{$macro}->{'arg'};
10722 $line =~ s/(\s+\S*)//o;
10723 $text .= $1 if defined($1);
10724 $args .= $1 if defined($1);
10729 if ($macro eq 'bye')
10734 elsif ($skip_spec eq 'linespace')
10736 if ($line =~ /^\s*$/o)
10738 $line =~ s/([ \t]*)//o;
10742 elsif ($skip_spec eq 'linewhitespace')
10744 if ($line =~ /^\s*$/o)
10750 elsif ($skip_spec eq 'line')
10755 elsif ($skip_spec eq 'whitespace')
10757 $line =~ s/(\s*)//o;
10760 elsif ($skip_spec eq 'space')
10762 $line =~ s/([ \t]*)//o;
10765 $line = '' if (!defined($line));
10766 return ($line, $text, $args);
10769 #+++###########################################################################
10771 # Pass structure: parse document structure #
10773 #---###########################################################################
10775 # This is a virtual element for things appearing before @node and
10776 # sectionning commands
10777 my $element_before_anything =
10779 'before_anything' => 1,
10781 'texi' => 'VIRTUAL ELEMENT BEFORE ANYTHING',
10784 # This is a place for index entries, anchors and so on appearing in
10785 # copying or documentdescription
10786 my $region_place = [];
10788 sub initialise_state_structure($)
10791 $state->{'structure'} = 1; # for substitute_text and close_stack:
10792 # 1 if pass_structure/scan_structure is
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'}))
10800 delete ($state->{'region_lines'});
10801 print STDERR "Bug: state->{'region_lines'} exists but undef.\n";
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
10829 # This is a virtual element used to have the right hrefs for index entries
10830 # and anchors in footnotes
10831 my $footnote_element =
10833 'id' => 'SEC_Foot',
10834 'file' => $docu_foot,
10840 my %content_element =
10842 'contents' => { 'id' => 'SEC_Contents', 'contents' => 1, 'texi' => '_contents' },
10843 'shortcontents' => { 'id' => 'SEC_Overview', 'shortcontents' => 1, 'texi' => '_shortcontents' },
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
10850 sub pass_structure()
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'};
10865 my $chomped_line = $_;
10866 if (!chomp($chomped_line) and @lines)
10868 $lines[0] = $_ . $lines[0];
10871 $line_nr = shift (@lines_numbers);
10872 #print STDERR "PASS_STRUCTURE: $_";
10873 if (!$state->{'raw'} and !$state->{'verb'})
10876 if (/^\s*\@(\w+)\b/)
10884 if ($tag and $tag eq 'node' or defined($sec2level{$tag}) or $tag eq 'printindex')
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'}))
10892 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($text);
10893 close_region($state);
10897 push @doc_lines, split_lines($text);
10901 if ($tag eq 'node')
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);
10910 $node = normalise_space($node);
10911 if (exists($nodes{$node}) and defined($nodes{$node})
10912 and $nodes{$node}->{'seen'})
10914 echo_error ("Duplicate node found: $node", $line_nr);
10919 if (exists($nodes{$node}) and defined($nodes{$node}))
10920 { # node appeared in a menu
10921 $node_ref = $nodes{$node};
10926 $first = 1 if (!defined($node_ref));
10928 $node_first = $node_ref if ($first);
10929 $nodes{$node} = $node_ref;
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
10948 if ($node =~ /^top$/i)
10950 if (!defined($node_top))
10952 $node_top = $node_ref;
10953 $node_top->{'texi'} = 'Top';
10954 delete $nodes{$node};
10955 $nodes{$node_top->{'texi'}} = $node_ref;
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";
10963 unless (@nodes_list)
10965 $node_ref->{'first'} = 1;
10967 push (@nodes_list, $node_ref);
10968 push @all_elements, $node_ref;
10973 echo_error ("Node is undefined: $_ (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)", $line_nr);
10979 $node_ref->{'node_next'} = normalise_node($node_next);
10983 $node_ref->{'node_prev'} = normalise_node($node_prev);
10987 $node_ref->{'node_up'} = normalise_node($node_up);
10990 elsif (defined($sec2level{$tag}))
10991 { # section or heading
10992 if (/^\@$tag\s*(.*)$/)
10994 my $name = normalise_space($1);
10995 $name = '' if (!defined($name));
10996 my $level = $sec2level{$tag};
10997 $state->{'after_element'} = 1;
11003 $docid = "SEC$sec_num";
11008 $docid = "SEC_Top";
11010 if ($tag !~ /heading/)
11012 my $section_ref = { 'texi' => $name,
11019 'index_names' => [],
11020 'current_place' => [],
11026 $section_ref->{'top'} = 1;
11027 $section_ref->{'number'} = '';
11028 $sections{0} = $section_ref;
11029 $section_top = $section_ref;
11031 $sections{$num} = $section_ref;
11032 merge_element_before_anything($section_ref);
11033 if ($state->{'node_ref'} and !exists($state->{'node_ref'}->{'with_section'}))
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');
11041 if (! $name and $level)
11043 echo_warn ("$tag without name", $line_nr);
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";
11051 if ($state->{'node_ref'})
11053 $node_ref = $state->{'node_ref'};
11054 $node_texi = $state->{'node_ref'}->{'texi'};
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;
11061 my $section_ref = { 'texi' => $name,
11065 'tag_level' => $tag,
11066 'sec_num' => $sec_num,
11069 $state->{'element'} = $section_ref;
11070 push @{$state->{'place'}}, $section_ref;
11071 $sections{$sec_num} = $section_ref;
11075 elsif (/^\@printindex\s+(\w+)/)
11077 unless (@all_elements)
11079 echo_warn ("Printindex before document beginning: \@printindex $1", $line_nr);
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
11087 my $placed_elements = [];
11088 push @{$all_elements[-1]->{'index_names'}}, { 'name' => $1, 'place' => $placed_elements };
11089 $state->{'place'} = $placed_elements;
11091 if (exists($state->{'region_lines'}))
11093 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, $_;
11097 push @doc_lines, $_;
11098 push @doc_numbers, $line_nr;
11103 if (scan_structure ($_, \$text, \@stack, $state, $line_nr) and !(exists($state->{'region_lines'})))
11105 push (@doc_numbers, $line_nr);
11110 next if (!defined($_));
11111 if ($state->{'region_lines'})
11113 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($_);
11117 push @doc_lines, split_lines($_);
11121 {# close stack at the end of pass structure
11122 close_stack_texi_structure(\$text, \@stack, $state, $line_nr);
11125 if (exists($state->{'region_lines'}))
11127 push @{$region_lines{$state->{'region_lines'}->{'format'}}},
11128 split_lines($text);
11132 push @doc_lines, split_lines($text);
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;
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
11151 $line =~ s/^(.*)//;
11153 $result[$i] .= "\n" if ($line =~ s/^\n//);
11154 #print STDERR "$i: $result[$i]";
11160 # handle misc commands and misc command args
11161 sub misc_command_structure($$$$)
11166 my $line_nr = shift;
11170 if ($macro eq 'lowersections')
11173 while (($sec, $level) = each %sec2level)
11175 $sec2level{$sec} = $level + 1;
11177 $state->{'sectionning_base'}--;
11179 elsif ($macro eq 'raisesections')
11182 while (($sec, $level) = each %sec2level)
11184 $sec2level{$sec} = $level - 1;
11186 $state->{'sectionning_base'}++;
11188 elsif (($macro eq 'contents') or ($macro eq 'summarycontents') or ($macro eq 'shortcontents'))
11190 if ($macro eq 'contents')
11192 $Texi2HTML::Config::DO_CONTENTS = 1;
11196 $macro = 'shortcontents';
11197 $Texi2HTML::Config::DO_SCONTENTS = 1;
11199 push @{$state->{'place'}}, $content_element{$macro};
11201 elsif ($macro eq 'detailmenu')
11203 $state->{'detailmenu'}++;
11205 elsif ($macro eq 'novalidate')
11208 $Texi2HTML::THISDOC{$macro} = 1;
11210 elsif (grep {$_ eq $macro} ('settitle','setfilename','shortitle','shorttitlepage')
11211 and ($line =~ /^\s+(.*)$/))
11213 $value{"_$macro"} = substitute_texi_line($1);
11215 elsif (grep {$_ eq $macro} ('author','subtitle','title')
11216 and ($line =~ /^\s+(.*)$/))
11218 $value{"_$macro"} .= substitute_texi_line($1)."\n";
11219 push @{$Texi2HTML::THISDOC{"${macro}s"}}, substitute_texi_line($1);
11221 elsif ($macro eq 'synindex' || $macro eq 'syncodeindex')
11223 if ($line =~ /^\s+(\w+)\s+(\w+)/)
11225 my $index_from = $1;
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})
11233 if ($macro eq 'syncodeindex')
11235 $index_names{$index_to}->{'associated_indices_code'}->{$index_from} = 1;
11239 $index_names{$index_to}->{'associated_indices'}->{$index_from} = 1;
11241 push @{$Texi2HTML::THISDOC{$macro}}, [$index_from,$index_to];
11246 echo_error ("Bad $macro line: $line", $line_nr);
11249 elsif ($macro eq 'defindex' || $macro eq 'defcodeindex')
11251 if ($line =~ /^\s+(\w+)\s*$/)
11254 if ($forbidden_index_name{$name})
11256 echo_error("Reserved index name $name", $line_nr);
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;
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);
11273 elsif ($macro eq 'documentlanguage')
11275 if ($line =~ /\s+(\w+)/)
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;
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]+)/)
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;
11295 elsif ($1 eq 'example')
11297 $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'};
11298 $Texi2HTML::THISDOC{$macro} = $1;
11300 elsif ($1 ne 'distinct')
11302 echo_error ("Unknown argument for \@$macro: $1", $line_nr);
11307 echo_error ("Bad \@$macro", $line_nr);
11310 elsif ($macro eq 'paragraphindent')
11312 if ($line =~ /\s+([0-9]+)/)
11314 $Texi2HTML::THISDOC{$macro} = $1;
11316 elsif (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(asis)[^\w\-]/))
11318 $Texi2HTML::THISDOC{$macro} = $1;
11322 echo_error ("Bad \@$macro", $line_nr);
11325 elsif ($macro eq 'firstparagraphindent')
11327 if (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(insert)[^\w\-]/))
11329 $Texi2HTML::THISDOC{$macro} = $1;
11333 echo_error ("Bad \@$macro", $line_nr);
11336 elsif ($macro eq 'exampleindent')
11338 if ($line =~ /^\s+([0-9]+)/)
11340 $Texi2HTML::THISDOC{$macro} = $1;
11342 elsif ($line =~ /^\s+(asis)[^\w\-]/)
11344 $Texi2HTML::THISDOC{$macro} = $1;
11348 echo_error ("Bad \@$macro", $line_nr);
11351 elsif ($macro eq 'frenchspacing')
11353 if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/))
11355 $Texi2HTML::THISDOC{$macro} = $1;
11359 echo_error ("Bad \@$macro", $line_nr);
11362 elsif ($macro eq 'footnotestyle')
11364 if (($line =~ /^\s+(end)[^\w\-]/) or ($line =~ /^\s+(separate)[^\w\-]/))
11366 $Texi2HTML::THISDOC{$macro} = $1;
11370 echo_error ("Bad \@$macro", $line_nr);
11373 elsif ($macro eq 'headings')
11376 foreach my $possible_arg (('off','on','single','double',
11377 'singleafter','doubleafter'))
11379 if ($line =~ /^\s+($possible_arg)[^\w\-]/)
11382 $Texi2HTML::THISDOC{$macro} = $possible_arg;
11386 unless ($valid_arg)
11388 echo_error ("Bad \@$macro", $line_nr);
11391 elsif ($macro eq 'setchapternewpage')
11393 if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/)
11394 or ($line =~ /^\s+(odd)[^\w\-]/))
11396 $Texi2HTML::THISDOC{$macro} = $1;
11400 echo_error ("Bad \@$macro", $line_nr);
11403 elsif ($macro eq 'setcontentsaftertitlepage' or $macro eq 'setshortcontentsaftertitlepage')
11405 $Texi2HTML::THISDOC{$macro} = 1;
11406 my $tag = 'contents';
11407 $tag = 'shortcontents' if ($macro ne 'setcontentsaftertitlepage');
11408 $content_element{$tag}->{'aftertitlepage'} = 1;
11410 elsif (grep {$macro eq $_} ('everyheading', 'everyfooting',
11411 'evenheading', 'evenfooting', 'oddheading', 'oddfooting'))
11415 $Texi2HTML::THISDOC{$macro} = $arg;
11417 elsif ($macro eq 'need')
11419 unless (($line =~ /^\s+([0-9]+(\.[0-9]*)?)[^\w\-]/) or
11420 ($line =~ /^\s+(\.[0-9]+)[^\w\-]/))
11422 echo_warn ("Bad \@$macro", $line_nr);
11426 ($text, $line, $args) = preserve_command($line, $macro);
11427 return ($text, $line);
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($$$$$$)
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'};
11446 if ($macro eq 'detailmenu')
11448 $state->{'detailmenu'}++;
11450 elsif ($macro eq 'sp')
11453 if ($line =~ /^\s+(\d+)\s/)
11457 elsif ($line =~ /(\s*)$/)
11463 echo_error ("\@$macro needs a numeric arg or no arg", $line_nr);
11465 $sp_number = 1 if ($sp_number eq '');
11466 if (!$state->{'remove_texi'})
11468 add_prev($text, $stack, &$Texi2HTML::Config::sp($sp_number, $state->{'preformatted'}));
11471 elsif($macro eq 'verbatiminclude' and !$keep)
11473 if ($line =~ /\s+(.+)/)
11476 my $file = locate_include_file($arg);
11477 if (defined($file))
11479 if (!open(VERBINCLUDE, $file))
11481 echo_warn ("Can't read file $file: $!",$line_nr);
11485 my $verb_text = '';
11486 while (my $line = <VERBINCLUDE>)
11488 $verb_text .= $line;
11491 if ($state->{'remove_texi'})
11493 add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi('verbatim', $verb_text));
11497 add_prev($text, $stack, &$Texi2HTML::Config::raw('verbatim', $verb_text));
11504 echo_error ("Can't find $arg, skipping", $line_nr);
11509 echo_error ("Bad \@$macro line: $_", $line_nr);
11512 elsif ($macro eq 'indent' or $macro eq 'noindent')
11514 $state->{'paragraph_indent'} = $macro;
11516 ($remaining, $skipped, $args) = preserve_command($line, $macro);
11517 return ($skipped) if ($keep);
11518 return $remaining if ($remaining ne '');
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($)
11527 my $element = shift;
11528 if (exists($element_before_anything->{'place'}))
11530 $element->{'current_place'} = $element_before_anything->{'place'};
11531 delete $element_before_anything->{'place'};
11532 foreach my $placed_thing (@{$element->{'current_place'}})
11534 $placed_thing->{'element'} = $element if (exists($placed_thing->{'element'}));
11537 # this is certainly redundant with the above condition, but cleaner
11539 if (exists($element_before_anything->{'titlefont'}))
11541 $element->{'titlefont'} = $element_before_anything->{'titlefont'};
11542 delete $element_before_anything->{'titlefont'};
11546 # find menu_prev, menu_up... for a node in menu
11547 sub menu_entry_texi($$$)
11551 my $line_nr = shift;
11552 my $node_menu_ref = {};
11553 if (exists($nodes{$node}))
11555 $node_menu_ref = $nodes{$node};
11559 $nodes{$node} = $node_menu_ref;
11560 $node_menu_ref->{'texi'} = $node;
11561 $node_menu_ref->{'external_node'} = 1 if ($node =~ /\(.+\)/);
11563 return if ($state->{'detailmenu'});
11564 if ($state->{'node_ref'})
11566 $node_menu_ref->{'menu_up'} = $state->{'node_ref'};
11567 $node_menu_ref->{'menu_up_hash'}->{$state->{'node_ref'}->{'texi'}} = 1;
11571 echo_warn ("menu entry without previous node: $node", $line_nr) unless ($node =~ /\(.+\)/);
11573 if ($state->{'prev_menu_node'})
11575 $node_menu_ref->{'menu_prev'} = $state->{'prev_menu_node'};
11576 $state->{'prev_menu_node'}->{'menu_next'} = $node_menu_ref;
11578 elsif ($state->{'node_ref'})
11580 $state->{'node_ref'}->{'menu_child'} = $node_menu_ref;
11582 $state->{'prev_menu_node'} = $node_menu_ref;
11585 sub equivalent_nodes($)
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}))
11594 @equivalent_nodes = grep {$_ ne $node} @{$cross_reference_nodes{$name}};
11596 return @equivalent_nodes;
11599 my %files = (); # keys are files. This is used to avoid reusing an allready
11601 my %empty_indices = (); # value is true for an index name key if the index
11603 my %printed_indices = (); # value is true for an index name not empty and
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
11611 # associate nodes with sections
11612 sub rearrange_elements()
11614 print STDERR "# find sections levels and toplevel\n"
11615 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
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))
11623 my $level = $section->{'level'};
11624 if ($level > $MAX_LEVEL)
11626 $section->{'level'} = $MAX_LEVEL;
11628 elsif ($level < $MIN_LEVEL and !$section->{'top'})
11630 $section->{'level'} = $MIN_LEVEL;
11634 $section->{'level'} = $level;
11636 $section->{'toc_level'} = $section->{'level'};
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'}}))
11642 $section->{'tag_level'} = $level2sec{$section->{'tag'}}->[$section->{'level'}];
11646 $section->{'tag_level'} = $section->{'tag'};
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);
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
11660 foreach my $section (@sections_list)
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++)
11672 $previous_numbers[$level] = undef;
11673 $previous_sections[$level] = undef;
11676 # find number at the current level
11677 if ($section->{'tag'} =~ /appendix/ and !$in_appendix)
11679 $previous_numbers[$toplevel] = 'A';
11681 $number_set = 1 if ($section->{'level'} == $toplevel);
11683 if (!defined($previous_numbers[$section->{'level'}]) and !$number_set)
11685 if ($section->{'tag'} =~ /unnumbered/)
11687 $previous_numbers[$section->{'level'}] = undef;
11691 $previous_numbers[$section->{'level'}] = 1;
11694 elsif ($section->{'tag'} !~ /unnumbered/ and !$number_set)
11696 $previous_numbers[$section->{'level'}]++;
11698 # construct the section number
11699 $section->{'number'} = '';
11701 unless ($section->{'tag'} =~ /unnumbered/)
11703 my $level = $section->{'level'};
11704 while ($level > $toplevel)
11706 my $number = $previous_numbers[$level];
11707 $number = 0 if (!defined($number));
11708 if ($section->{'number'})
11710 $section->{'number'} = "$number.$section->{'number'}";
11714 $section->{'number'} = $number;
11718 my $toplevel_number = $previous_numbers[$toplevel];
11719 $toplevel_number = 0 if (!defined($toplevel_number));
11720 $section->{'number'} = "$toplevel_number.$section->{'number'}";
11722 # find the previous section
11723 if (defined($previous_sections[$section->{'level'}]))
11725 my $prev_section = $previous_sections[$section->{'level'}];
11726 $section->{'sectionprev'} = $prev_section;
11727 $prev_section->{'sectionnext'} = $section;
11729 # find the up section
11730 if ($section->{'level'} == $toplevel)
11732 $section->{'sectionup'} = undef;
11736 my $level = $section->{'level'} - 1;
11737 while (!defined($previous_sections[$level]) and ($level >= 0))
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;
11750 $section->{'sectionup'} = undef;
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'};
11760 ############################# debug
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
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 = ();
11776 my @node_directions = ('node_prev', 'node_next', 'node_up');
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)
11782 foreach my $direction (@node_directions)
11784 if (defined($node->{$direction}) and !ref($node->{$direction})
11785 and ($node->{$direction} ne ''))
11787 if ($nodes{$node->{$direction}} and $nodes{$node->{$direction}}->{'seen'})
11789 $node->{$direction} = $nodes{$node->{$direction}};
11791 elsif (($node->{$direction} =~ /^\(.*\)/) or $novalidate)
11792 { # ref to an external node
11793 if (exists($nodes{$node->{$direction}}))
11795 $node->{$direction} = $nodes{$node->{$direction}};
11799 # FIXME if {'seen'} this is a node appearing in the
11800 # document and a node like `(file)node'. What to
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;
11810 push @nodes_with_unknown_directions, $node;
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();
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)
11825 foreach my $direction (@node_directions)
11827 if (defined($node->{$direction}) and !ref($node->{$direction})
11828 and ($node->{$direction} ne ''))
11830 echo_warn ("$direction `$node->{$direction}' for `$node->{'texi'}' not found");
11831 my @equivalent_nodes = equivalent_nodes($node->{$direction});
11833 foreach my $equivalent_node (@equivalent_nodes)
11835 if ($nodes{$equivalent_node}->{'seen'})
11837 $node_seen = $equivalent_node;
11841 if (defined($node_seen))
11843 echo_warn (" ---> but equivalent node `$node_seen' found");
11844 $node->{$direction} = $nodes{$node_seen};
11848 delete $node->{$direction};
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
11859 my $previous_is_top = 0;
11860 foreach my $element (@all_elements)
11862 if ($element eq $node_top)
11864 $previous_is_top = 1;
11867 if ($previous_is_top)
11869 if ($element->{'section'})
11871 $section_after_top = $element;
11876 $section_before_top = $element if ($element->{'section'});
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));
11884 print STDERR "# Build the elements list\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11885 if (!$Texi2HTML::Config::USE_NODES)
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)
11892 print STDERR "# no section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11893 @elements_list = @all_elements;
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)
11906 my $section = shift @old_element_lists;
11907 if ($section_before_top and ($section eq $section_before_top))
11909 push @elements_list, $section;
11910 push @elements_list, $node_top;
11913 elsif ($section_after_top and ($section eq $section_after_top))
11915 push @elements_list, $node_top;
11916 push @elements_list, $section;
11919 push @elements_list, $section;
11921 push @elements_list, @old_element_lists;
11924 foreach my $element (@elements_list)
11926 print STDERR "# new section element $element->{'texi'}\n"
11927 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11932 # elements are sections if possible, and node if no section associated
11933 foreach my $element(@all_elements)
11935 if ($element->{'node'})
11937 if (!defined($element->{'with_section'}))
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;
11947 print STDERR "# new section element ($element) $element->{'texi'}\n"
11948 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
11949 push @elements_list, $element;
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)
11966 if ($element->{'node'} and !$element->{'top_as_section'})
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));
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;
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));
11993 { # seems like there are only nodes in the documents
11994 $element->{'toc_level'} = $MIN_LEVEL;
11995 push @{$element->{'all_elements'}}, $element;
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;
12006 elsif (!$element->{'node_ref'})
12007 { # a section not preceded by a node
12008 push @{$element->{'all_elements'}}, $element;
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));
12029 # It is the last element before indices split, which may add new
12031 $element_last = $elements_list[-1];
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
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)
12042 # first a warning if the node and the equivalent nodes don't
12044 if (!$node->{'first'} and !$node->{'top'} and !$node->{'menu_up'} and ($node->{'texi'} !~ /^top$/i) and $Texi2HTML::Config::SHOW_MENU)
12046 my @equivalent_nodes = equivalent_nodes($node->{'texi'});
12048 foreach my $equivalent_node (@equivalent_nodes)
12050 if ($nodes{$equivalent_node}->{'first'} or $nodes{$equivalent_node}->{'menu_up'})
12058 warn "$WARN `$node->{'texi'}' doesn't appear in menus\n";
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'})
12066 $node->{'nodeup'} = $node->{'node_up'};
12068 elsif ($node->{'automatic_directions'} and $node->{'section_ref'})
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}))
12075 $node->{'nodeup'} = $nodes{$top_nodeup};
12079 my $node_ref = { 'texi' => $top_nodeup };
12080 $node_ref->{'external_node'} = 1;
12081 $nodes{$top_nodeup} = $node_ref;
12082 $node->{'nodeup'} = $node_ref;
12085 elsif (defined($node->{'section_ref'}->{'sectionup'}))
12087 $node->{'nodeup'} = get_node($node->{'section_ref'}->{'sectionup'});
12089 elsif ($node->{'section_ref'}->{'toplevel'} and ($node->{'section_ref'} ne $element_top))
12091 $node->{'nodeup'} = get_node($element_top);
12093 print STDERR "# Deducing from section node_up $node->{'nodeup'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS and defined($node->{'nodeup'}));
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);
12102 if ($node->{'nodeup'} and !$node->{'nodeup'}->{'external_node'})
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'}}))
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'};
12114 if ($node->{'node_next'})
12116 $node->{'nodenext'} = $node->{'node_next'};
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'});
12122 elsif ($node->{'automatic_directions'})
12124 if (defined($node->{'section_ref'}))
12127 my $section = $node->{'section_ref'};
12128 if (defined($section->{'sectionnext'}))
12130 $next = get_node($section->{'sectionnext'})
12134 while (defined($section->{'sectionup'}) and !defined($section->{'sectionnext'}))
12136 $section = $section->{'sectionup'};
12138 if (defined($section->{'sectionnext'}))
12140 $next = get_node($section->{'sectionnext'});
12143 $node->{'nodenext'} = $next;
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)
12150 $node->{'nodenext'} = $node->{'menu_next'};
12153 if ($node->{'node_prev'})
12155 $node->{'nodeprev'} = $node->{'node_prev'};
12157 elsif ($node->{'automatic_directions'})
12159 if (defined($node->{'section_ref'}))
12161 my $section = $node->{'section_ref'};
12162 if (defined($section->{'sectionprev'}))
12164 $node->{'nodeprev'} = get_node($section->{'sectionprev'});
12166 elsif (defined($section->{'sectionup'}))
12168 $node->{'nodeprev'} = get_node($section->{'sectionup'});
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)
12175 $node->{'nodeprev'} = $node->{'menu_prev'};
12177 # the prev node is the parent node
12178 elsif (!defined($node->{'nodeprev'}) and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS)
12180 $node->{'nodeprev'} = $node->{'menu_up'};
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
12186 if ($node->{'menu_child'})
12188 $node->{'following'} = $node->{'menu_child'};
12190 elsif ($node->{'automatic_directions'} and defined($node->{'section_ref'}) and defined($node->{'section_ref'}->{'child'}))
12192 $node->{'following'} = get_node($node->{'section_ref'}->{'child'});
12194 elsif (defined($node->{'nodenext'}))
12196 $node->{'following'} = $node->{'nodenext'};
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)))
12207 if (($node_top) and ($up eq $node_top))
12208 { # if we are at Top, Top is following
12209 $node->{'following'} = $node_top;
12212 if (defined($up->{'nodenext'}))
12214 $node->{'following'} = $up->{'nodenext'};
12216 elsif (defined($up->{'nodeup'}))
12218 if (! grep { $_ eq $up->{'nodeup'}->{'texi'} } @{$node->{'up_not_in_menu'}})
12220 $up = $up->{'nodeup'};
12223 { # in that case we can go into a infinite loop
12224 $node->{'following'} = $up->{'nodeup'};
12234 if (defined($node->{'section_ref'}))
12236 my $section = $node->{'section_ref'};
12237 foreach my $direction ('sectionnext', 'sectionprev', 'sectionup')
12239 $node->{$direction} = $section->{$direction}
12240 if (defined($section->{$direction}));
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'}});
12247 # 'up' is used in .init files. Maybe should go away.
12248 if (defined($node->{'sectionup'}))
12250 $node->{'up'} = $node->{'sectionup'};
12252 elsif (defined($node->{'nodeup'}) and
12253 (!$node_top or ($node ne $node_top)))
12255 $node->{'up'} = $node->{'nodeup'};
12257 # 'next' not used but documented.
12258 if (defined($node->{'sectionnext'}))
12260 $node->{'next'} = $node->{'sectionnext'};
12262 if (defined($node->{'sectionprev'}))
12264 $node->{'prev'} = $node->{'sectionprev'};
12267 # default id for nodes. Should be overriden later.
12268 $node->{'id'} = 'NOD' . $node_nr;
12272 print STDERR "# find forward and back\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12274 foreach my $element (@elements_list)
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))
12283 $element->{'sectionup'} = $element_top;
12284 $element->{'up'} = $element_top;
12288 $element->{'back'} = $prev;
12289 $prev->{'forward'} = $element;
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'}))
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'};
12309 elsif (! $element->{'node'})
12310 { # the section has no node associated. Find the node directions using
12312 if (defined($element->{'sectionnext'}))
12314 $element->{'nodenext'} = get_node($element->{'sectionnext'});
12316 if (defined($element->{'sectionprev'}))
12318 $element->{'nodeprev'} = get_node($element->{'sectionprev'});
12320 if (defined($element->{'up'}))
12322 $element->{'nodeup'} = get_node($element->{'up'});
12324 if ($element->{'child'})
12326 $element->{'following'} = get_node($element->{'child'});
12328 elsif ($element->{'sectionnext'})
12330 $element->{'following'} = get_node($element->{'sectionnext'});
12332 elsif ($element->{'up'})
12335 while ($up->{'up'} and !$element->{'following'})
12337 print STDERR "# Going up, searching next section from $up->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12339 if ($up->{'sectionnext'})
12341 $element->{'following'} = get_node ($up->{'sectionnext'});
12343 # avoid infinite loop if the top is up for itself
12344 last if ($up->{'toplevel'} or $up->{'top'});
12350 my @new_elements = ();
12351 print STDERR "# preparing indices\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12353 while(@elements_list)
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'};
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'}})
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'}})
12380 push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ;
12385 $current_element->{'sectionnext'} = $checked_element;
12386 $current_element->{'following'} = $checked_element;
12387 $checked_element->{'sectionprev'} = $current_element;
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 = ();
12396 elsif ($current_element->{'holder'})
12398 push @waiting_elements, $checked_element;
12402 push @{$current_element->{'nodes'}}, $checked_element;
12403 $checked_element->{'section_ref'} = $current_element;
12405 push @{$current_element->{'place'}}, @{$checked_element->{'current_place'}};
12406 foreach my $index (@{$checked_element->{'index_names'}})
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))
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'} } ];
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
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'})
12450 $checked_element->{'toplevel'} = 1;
12451 $checked_element->{'top'} = 1;
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'}})
12462 push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ;
12464 foreach my $waiting_element (@waiting_elements)
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;
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;
12480 print STDERR "# New page (back `$back->{'texi'}', current `$current_element->{'texi'}')\n" if ($T2H_DEBUG & $DEBUG_INDEX);
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'},
12494 'sectionnext' => $sectionnext,
12495 'following' => $current_element->{'following'},
12496 'nodeup' => $current_element->{'nodeup'},
12497 'nodenext' => $current_element->{'nodenext'},
12498 'nodeprev' => $back,
12503 # the index page is associated with the new element
12504 # if there is one, the element otherwise
12505 if ($checked_element->{'element_added'})
12507 $index_page->{'original_index_element'} = $checked_element;
12511 $index_page->{'original_index_element'} = $element;
12513 $index_page->{'node'} = 1 if ($element->{'node'});
12514 while ($nodes{$index_page->{'texi'}})
12516 $nodes{$index_page->{'texi'}} .= ' ';
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'});
12528 $current_element = $index_page;
12533 print STDERR "# Empty index: $index->{'name'}\n"
12534 if ($T2H_DEBUG & $DEBUG_INDEX);
12535 $empty_indices{$index->{'name'}} = 1;
12537 push @{$current_element->{'place'}}, @{$index->{'place'}};
12540 if ($forward and ($current_element ne $element))
12542 $current_element->{'forward'} = $forward;
12543 $forward->{'back'} = $current_element;
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'}})
12550 $reparented->{'sectionup'} = $current_element;
12551 print STDERR " reparented: $reparented->{'texi'}\n"
12552 if ($T2H_DEBUG & $DEBUG_INDEX);
12555 @elements_list = @new_elements;
12557 print STDERR "# find fastback and fastforward\n"
12558 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12559 foreach my $element (@elements_list)
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
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))
12571 $element->{'fastback'} = $up;
12573 elsif ($element->{'toplevel'})
12575 # the element is a top level element, we adjust the next
12576 # toplevel element fastback
12577 $element->{'fastforward'}->{'fastback'} = $element if ($element->{'fastforward'});
12581 # set 'reference_element' which is used each time there is a cross ref
12583 # It is the section associated with the node except if USE_NODES
12584 unless ($Texi2HTML::Config::USE_NODES)
12586 foreach my $node(@nodes_list)
12588 if ($node->{'with_section'})
12590 $node->{'reference_element'} = $node->{'with_section'};
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)
12601 $element->{'this'} = $element;
12602 foreach my $direction (@element_directions)
12604 my $direction_no_caps = $direction;
12605 $direction_no_caps =~ tr/A-Z/a-z/;
12606 $element->{$direction} = $element->{$direction_no_caps};
12608 if ($element->{'index_page'})
12610 $element->{'id'} = "INDEX" . $index_nr;
12615 print STDERR "# find float id\n"
12616 if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12617 foreach my $float (@floats)
12619 $float->{'style_id'} = cross_manual_line(normalise_space($float->{'style_texi'}));
12620 my $float_style = { };
12621 if (exists($floats{$float->{'style_id'}}))
12623 $float_style = $floats{$float->{'style_id'}};
12627 $floats{$float->{'style_id'}} = $float_style;
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'})))
12634 $float_style->{'current_chapter'} = $up->{'texi'};
12635 $float_style->{'nr_in_chapter'} = 1;
12639 $float_style->{'nr_in_chapter'}++;
12641 if (defined($up) and $up->{'number'} ne '')
12643 $float->{'chapter_nr'} = $up->{'number'};
12644 $float->{'nr'} = $float->{'chapter_nr'} . $float_style->{'nr_in_chapter'};
12648 $float->{'nr'} = $float->{'absolute_nr'};
12652 if ($Texi2HTML::Config::NEW_CROSSREF_STYLE)
12654 foreach my $key (keys(%nodes))
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'});
12662 # Find node file names and file names for nodes considered as elements
12666 $node_as_top = $node_top;
12668 elsif ($element_top->{'node_ref'})
12670 $node_as_top = $element_top->{'node_ref'};
12674 $node_as_top = $node_first;
12679 $node_file = &$Texi2HTML::Config::node_file_name($node_as_top,'top');
12680 $node_as_top->{'node_file'} = $node_file if (defined($node_file));
12682 foreach my $key (keys(%nodes))
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));
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)
12697 my $cut_section = $toplevel;
12699 if ($Texi2HTML::Config::SPLIT eq 'section')
12701 $cut_section = 2 if ($toplevel <= 2);
12704 foreach my $element (@elements_list)
12706 print STDERR "# Splitting ($Texi2HTML::Config::SPLIT:$cut_section) $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12709 ($Texi2HTML::Config::SPLIT eq 'node') or
12711 defined($element->{'level'}) and ($element->{'level'} <= $cut_section)
12718 $doc_nr = 0 if ($doc_nr < 0); # happens if first elements are nodes
12719 $element->{'doc_nr'} = $doc_nr;
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
12726 $element->{'file'} = $docu_top;
12728 elsif ($Texi2HTML::Config::NODE_FILES)
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'}))
12736 $element->{'file'} = $node->{'node_file'};
12738 $previous_file = $element->{'file'};
12740 elsif($previous_file)
12742 $element->{'file'} = $previous_file;
12745 if (defined($Texi2HTML::Config::element_file_name))
12748 &$Texi2HTML::Config::element_file_name ($element, $is_top, $docu_name);
12749 $element->{'file'} = $filename if (defined($filename));
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'}})
12755 $place->{'file'} = $element->{'file'};
12756 $place->{'id'} = $element->{'id'} unless defined($place->{'id'});
12758 if ($element->{'nodes'})
12760 foreach my $node (@{$element->{'nodes'}})
12762 $node->{'doc_nr'} = $element->{'doc_nr'};
12763 $node->{'file'} = $element->{'file'};
12770 add_file($docu_doc);
12771 foreach my $element(@elements_list)
12773 $element->{'file'} = $docu_doc;
12774 $element->{'doc_nr'} = 0;
12775 foreach my $place(@{$element->{'place'}})
12777 $place->{'file'} = $element->{'file'};
12778 $place->{'id'} = $element->{'id'} unless defined($place->{'id'});
12781 foreach my $node(@nodes_list)
12783 $node->{'file'} = $docu_doc;
12784 $node->{'doc_nr'} = 0;
12787 # correct the id and file for the things placed in footnotes
12788 foreach my $place(@{$footnote_element->{'place'}})
12790 $place->{'file'} = $footnote_element->{'file'};
12791 $place->{'id'} = $footnote_element->{'id'} unless defined($place->{'id'});
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)
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'}));
12807 foreach my $content_type(keys(%content_element))
12809 if (!defined($content_element{$content_type}->{'file'}))
12811 print STDERR "# No content $content_type\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
12812 $content_element{$content_type} = undef;
12816 ########################### debug prints
12817 foreach my $file (keys(%files))
12819 last unless ($T2H_DEBUG & $DEBUG_ELEMENTS);
12820 print STDERR "$file: counter $files{$file}->{'counter'}\n";
12822 foreach my $element ((@elements_list, $footnote_element))
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'})
12830 print STDERR "index($element->{'id'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})): $element->{'texi'}\n";
12832 elsif ($element->{'node'})
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'}));
12837 elsif ($element->{'footnote'})
12839 print STDERR "footnotes($element->{'id'}, file $element->{'file'})\n";
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'}));
12849 if (!$element->{'footnote'})
12851 if (!defined($files{$element->{'file'}}))
12853 die "Bug: files{\$element->{'file'}} undef element $element->{'texi'}, file $element->{'file'}.";
12855 print STDERR " file: $element->{'file'} $files{$element->{'file'}}, counter $files{$element->{'file'}}->{'counter'}\n";
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'}))
12874 print STDERR " parent nodes:\n";
12875 foreach my $menu_up (keys%{$element->{'menu_up_hash'}})
12877 print STDERR " $menu_up ($element->{'menu_up_hash'}->{$menu_up})\n";
12880 if (defined($element->{'nodes'}))
12882 print STDERR " nodes: $element->{'nodes'} (@{$element->{'nodes'}})\n";
12883 foreach my $node (@{$element->{'nodes'}})
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";
12892 print STDERR " places: $element->{'place'}\n";
12893 foreach my $place(@{$element->{'place'}})
12895 if (!$place->{'entry'} and !$place->{'float'} and !$place->{'texi'} and !$place->{'contents'} and !$place->{'shortcontents'})
12897 print STDERR "BUG: unknown placed stuff ========\n";
12898 foreach my $key (keys(%$place))
12900 print STDERR "$key: $place->{$key}\n";
12902 print STDERR "==================================\n";
12904 elsif ($place->{'entry'})
12906 print STDERR " index($place): $place->{'entry'}\n";
12908 elsif ($place->{'anchor'})
12910 print STDERR " anchor: $place->{'texi'}\n";
12912 elsif ($place->{'float'})
12914 if (defined($place->{'texi'}))
12916 print STDERR " float($place): $place->{'texi'}\n";
12920 print STDERR " float($place): NO LABEL\n";
12923 elsif ($place->{'contents'})
12925 print STDERR " contents\n";
12927 elsif ($place->{'shortcontents'})
12929 print STDERR " shortcontents\n";
12933 print STDERR " heading: $place->{'texi'}\n";
12936 if ($element->{'indices'})
12938 print STDERR " indices: $element->{'indices'}\n";
12939 foreach my $index(@{$element->{'indices'}})
12941 print STDERR " $index: ";
12942 foreach my $page (@$index)
12944 print STDERR "'$page->{'element'}->{'texi'}'($page->{'name'}): $page->{'page'} ";
12950 ########################### end debug prints
12958 $files{$file}->{'counter'}++;
12963 #'type' => 'section',
12965 'relative_foot_num' => 1,
12971 # find parent element which is a top element, or a node within the top section
12974 my $element = shift;
12976 while (!$up->{'toplevel'} and !$up->{'top'})
12978 $up = $up->{'sectionup'};
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
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'});
12998 # get the html names from the texi for all elements
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))
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'}
13022 foreach my $number (keys(%sections))
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;
13036 foreach my $element (@elements_list)
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;
13044 next if (defined($element->{'text'}));
13045 if ($element->{'index_page'})
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);
13061 print STDERR "# Names done\n" if ($T2H_DEBUG);
13064 @{$Texi2HTML::TOC_LINES} = (); # table of contents
13065 @{$Texi2HTML::OVERVIEW} = (); # short table of contents
13069 #+++############################################################################
13071 # Stuff related to Index generation #
13073 #---############################################################################
13075 # called during pass_structure
13076 sub enter_index_entry($$$$$$$)
13078 my $prefix = shift;
13079 my $line_nr = shift;
13082 my $element = shift;
13083 my $use_section_id = shift;
13084 my $command = shift;
13085 unless ($index_prefix_to_name{$prefix})
13087 echo_error ("Undefined index command: ${prefix}index", $line_nr);
13090 if (!exists($element->{'tag'}) and !$element->{'footnote'})
13092 echo_warn ("Index entry before document: \@${prefix}index $key", $line_nr);
13097 # The $key is mostly usefull for alphabetical sorting
13098 $key = remove_texi($key);
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))
13104 $id = 'IDX' . ++$idx_num;
13106 my $index_entry = {
13108 'element' => $element,
13109 'prefix' => $prefix,
13111 'command' => $command
13114 print STDERR "# enter \@$command ${prefix}index '$key' with id $id ($index_entry)\n"
13115 if ($T2H_DEBUG & $DEBUG_INDEX);
13116 if ($key =~ /^\s*$/)
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);
13124 while (exists $index->{$prefix}->{$key})
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);
13135 # sort according to cmp if both $a and $b are alphabetical or non alphabetical,
13136 # otherwise the alphabetical is ranked first
13139 if ($a =~ /^[A-Za-z]/)
13141 if ($b =~ /^[A-Za-z]/)
13143 return lc($a) cmp lc($b);
13150 elsif ($b =~ /^[A-Za-z]/)
13156 return lc($a) cmp lc($b);
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($)
13169 my $entries = shift;
13171 my ($entries_by_letter, $pages, $page) = ({}, [], {});
13172 my @keys = sort by_alpha keys %$entries;
13174 # each index entry is placed according to its first letter in
13175 # entries_by_letter
13176 for my $key (@keys)
13178 push @{$entries_by_letter->{uc(substr($key,0, 1))}} , $entries->{$key};
13180 @letters = sort by_alpha keys %$entries_by_letter;
13181 $Texi2HTML::Config::SPLIT_INDEX = 0 unless $Texi2HTML::Config::SPLIT;
13183 if ($Texi2HTML::Config::SPLIT_INDEX and $Texi2HTML::Config::SPLIT_INDEX =~ /^\d+$/)
13187 foreach my $letter (@letters)
13189 if ($i > $Texi2HTML::Config::SPLIT_INDEX)
13191 $page->{'last_letter'} = $prev_letter;
13192 push @$pages, $page;
13198 $page->{'letters'} = [];
13199 $page->{'entries_by_letter'} = {};
13200 $page->{'first_letter'} = $letter;
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;
13207 $page->{'last_letter'} = $letters[$#letters];
13208 push @$pages, $page;
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;
13223 # return the page and the entries. Cache the result in %indices.
13226 my $index_name = shift;
13227 my $line_nr = shift;
13229 return (@{$indices{$index_name}}) if ($indices{$index_name});
13231 unless (exists($index_names{$index_name}))
13233 echo_error ("Bad index name: $index_name", $line_nr);
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'})
13241 $index_names{$index_name}->{'associated_indices_code'}->{$index_name} = 1;
13245 $index_names{$index_name}->{'associated_indices'}->{$index_name} = 1;
13248 # find all the index names associated with the prefixes and then
13249 # all the entries associated with each prefix
13251 foreach my $associated_indice(keys %{$index_names{$index_name}->{'associated_indices'}})
13253 foreach my $prefix(@{$index_names{$associated_indice}->{'prefix'}})
13255 foreach my $key (keys %{$index->{$prefix}})
13257 $entries->{$key} = $index->{$prefix}->{$key};
13262 foreach my $associated_indice (keys %{$index_names{$index_name}->{'associated_indices_code'}})
13264 unless (exists ($index_names{$index_name}->{'associated_indices'}->{$associated_indice}))
13266 foreach my $prefix (@{$index_names{$associated_indice}->{'prefix'}})
13268 foreach my $key (keys (%{$index->{$prefix}}))
13270 $entries->{$key} = $index->{$prefix}->{$key};
13271 # use @code for code style index entry
13272 $entries->{$key}->{'entry'} = "\@code{$entries->{$key}->{entry}}";
13278 return unless %$entries;
13279 my $pages = get_index_pages($entries);
13280 $indices{$index_name} = [ $pages, $entries ];
13281 return ($pages, $entries);
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
13293 sub initialise_state($)
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'});
13314 initialise_state(\%state);
13321 my @section_lines = ();
13322 my @head_lines = ();
13323 my $one_section = 1 if (@elements_list == 1);
13325 if (@elements_list == 0)
13327 warn "$WARN empty document\n";
13331 # We set titlefont only if the titlefont appeared in the top element
13332 if (defined($element_top->{'titlefont'}))
13334 $value{'_titlefont'} = $element_top->{'titlefont'};
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'))
13343 if ($value{$possible_fulltitle} ne '')
13345 $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{$possible_fulltitle};
13349 foreach my $possible_title_texi ($value{'_settitle'}, $Texi2HTML::THISDOC{'fulltitle_texi'})
13351 if ($possible_title_texi ne '')
13353 $Texi2HTML::THISDOC{'title_texi'} = $possible_title_texi;
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'))
13362 $Texi2HTML::THISDOC{$texi_cmd . '_texi'} = $value{'_' . $texi_cmd};
13364 foreach my $doc_thing (('shorttitlepage', 'settitle', 'author',
13365 'titlefont', 'subtitle', 'shorttitle', 'fulltitle', 'title'))
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);
13376 my $element_top_text = '';
13377 my $top_no_texi = '';
13378 my $top_simple_format = '';
13380 if ($element_top and $element_top->{'text'} and (!$node_top or ($element_top ne $node_top)))
13382 $element_top_text = $element_top->{'text'};
13383 $top_no_texi = $element_top->{'no_texi'};
13384 $top_simple_format = $element_top->{'simple_format'};
13386 foreach my $possible_top_name ($Texi2HTML::Config::TOP_HEADING,
13387 $element_top_text, $Texi2HTML::THISDOC{'title'},
13388 $Texi2HTML::THISDOC{'shorttitle'}, &$I('Top'))
13390 if (defined($possible_top_name) and $possible_top_name ne '')
13392 $top_name = $possible_top_name;
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}))
13401 if (defined($possible_top_no_texi) and $possible_top_no_texi ne '')
13403 $top_no_texi = $possible_top_no_texi;
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}))
13413 if (defined($possible_top_simple_format) and $possible_top_simple_format ne '')
13415 $top_simple_format = $possible_top_simple_format;
13421 # my $top_name = $Texi2HTML::Config::TOP_HEADING || $element_top_text || $Texi2HTML::THISDOC{'title'} || $Texi2HTML::THISDOC{'shorttitle'} || &$I('Top');
13423 if ($Texi2HTML::THISDOC{'fulltitle_texi'} eq '')
13425 $Texi2HTML::THISDOC{'fulltitle_texi'} = &$I('Untitled Document',{},
13426 {'keep_texi' => 1});
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 '');
13432 foreach my $doc_thing (('fulltitle', 'title'))
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);
13442 for my $key (keys %Texi2HTML::THISDOC)
13444 next if (ref($Texi2HTML::THISDOC{$key}));
13445 print STDERR "!!$key\n" if (!defined($Texi2HTML::THISDOC{$key}));
13446 $Texi2HTML::THISDOC{$key} =~ s/\s*$//;
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'))
13462 for ($i = 0; $i < $#{$Texi2HTML::THISDOC{$element}} + 1; $i++)
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";
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)
13475 $toc_file = $docu_toc;
13476 $stoc_file = $docu_stoc;
13477 if ($Texi2HTML::Config::INLINE_CONTENTS)
13479 $toc_file = $content_element{'contents'}->{'file'} if (defined($content_element{'contents'}));
13480 $stoc_file = $content_element{'shortcontents'}->{'file'} if (defined($content_element{'shortcontents'}));
13482 $foot_file = $docu_foot;
13483 $about_file = $docu_about;
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));
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 '');
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));
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});
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')
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));
13525 $Texi2HTML::TITLEPAGE = '';
13526 $Texi2HTML::TITLEPAGE = substitute_text({}, @{$region_lines{'titlepage'}})
13527 if (@{$region_lines{'titlepage'}});
13528 &$Texi2HTML::Config::titlepage();
13530 &$Texi2HTML::Config::init_out();
13531 $to_encoding = $Texi2HTML::Config::OUT_ENCODING;
13533 ############################################################################
13534 # print frame and frame toc file
13536 if ( $Texi2HTML::Config::FRAMES )
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);
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);
13549 ############################################################################
13555 my $index_pages_nr;
13558 my $first_section = 0; # 1 if it is the first section of a page
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];
13570 $line_nr = shift (@doc_numbers);
13571 #print STDERR "$line_nr->{'file_name'}($line_nr->{'macro'},$line_nr->{'line_nr'}) $_" if ($line_nr);
13573 #print STDERR "PASS_TEXT: $_";
13574 #dump_stack(\$text, \@stack, \%state);
13575 if (!$state{'raw'} and !$state{'verb'})
13578 $tag = $1 if (/^\@(\w+)/ and !$index_pages);
13580 if (($tag eq 'node') or defined($sec2level{$tag}) or $index_pages)
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;
13590 $sec_num++ if ($sec2level{$tag});
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 $_";
13599 $new_element = shift @elements_list;
13603 push (@section_lines, &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n");
13604 push @section_lines, &$Texi2HTML::Config::heading($current_element);
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'})
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));
13619 print STDERR 'SECTION ' . $current_element->{'texi'} if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13621 print STDERR ": $_" if ($T2H_DEBUG & $DEBUG_ELEMENTS);
13622 ########################## end debug section
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
13629 or ($current_element->{'element'} and ($current_element ne $element))
13630 or ($current_element->{'section_ref'} and ($current_element->{'section_ref'} ne $element)))
13632 $new_element = shift @elements_list;
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))
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'}): $_";
13642 ########################### end debug
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);
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;
13663 finish_element($FH, $element, $new_element, $first_section);
13664 $first_section = 0;
13665 @section_lines = ();
13670 print STDERR "# Writing elements:" if ($T2H_VERBOSE);
13671 if ($Texi2HTML::Config::IGNORE_PREAMBLE_TEXT)
13673 @section_lines = ();
13676 # remove empty line at the beginning of @section_lines
13677 shift @section_lines while (@section_lines and ($section_lines[0] =~ /^\s*$/));
13679 # begin new element
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)
13695 $Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $element->{'file'});
13696 $Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $element->{'file'});
13698 foreach my $direction (@element_directions)
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'})
13707 $Texi2HTML::NODE{$direction} = $elem->{'text'};
13709 elsif ($elem->{'node_ref'})
13711 $Texi2HTML::NODE{$direction} = $elem->{'node_ref'}->{'text'};
13713 if (!$elem->{'seen'})
13715 $Texi2HTML::HREF{$direction} = do_external_href($elem->{'texi'});
13719 $Texi2HTML::HREF{$direction} = href($elem, $element->{'file'});
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";
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))
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'})
13736 $FH = $files{$file}->{'filehandle'};
13740 $FH = open_out("$docu_rdir$file");
13741 #print STDERR "OPEN $docu_rdir$file, $FH". scalar($FH)."\n";
13742 $files{$file}->{'filehandle'} = $FH;
13745 if ($element->{'top'})
13747 &$Texi2HTML::Config::print_Top_header($FH, $do_page_head);
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';
13755 $first_section = 1;
13757 print STDERR "." if ($T2H_VERBOSE);
13758 print STDERR "\n" if ($T2H_DEBUG);
13760 my $label = &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n";
13761 if (@section_lines)
13763 push (@section_lines, $label);
13767 push @head_lines, $label;
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]))
13781 $index_pages = undef;
13785 push @section_lines, &$Texi2HTML::Config::heading($current_element) if ($current_element->{'element'} and !$current_element->{'top'});
13788 elsif ($tag eq 'printindex')
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));
13802 begin_paragraph (\@stack, \%state) if ($state{'preformatted'});
13804 push @section_lines, $text;
13808 elsif (($tag eq 'contents') or ($tag eq 'summarycontents') or ($tag eq 'shortcontents'))
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'})
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;
13820 my $toc_lines = &$Texi2HTML::Config::inline_contents($FH, $tag, $content_element{$element_tag});
13821 push (@section_lines, @$toc_lines) if (defined($toc_lines)) ;
13826 scan_line($_, \$text, \@stack, \%state, $line_nr);
13827 #print STDERR "after scan_line: $_";
13828 #dump_stack(\$text, \@stack, \%state);
13832 push @section_lines, $text;
13837 {# close stack at the end of pass text
13838 close_stack(\$text, \@stack, \%state, $line_nr);
13840 if (defined($text))
13842 push @section_lines, $text;
13844 print STDERR "\n" if ($T2H_VERBOSE);
13846 $Texi2HTML::THIS_SECTION = \@section_lines;
13847 # if no sections, then simply print document as is
13852 &$Texi2HTML::Config::foot_section (\@foot_lines);
13853 push @section_lines, @foot_lines;
13855 $Texi2HTML::THIS_HEADER = \@head_lines;
13856 if ($element->{'top'})
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'})
13865 unshift @section_lines, &$Texi2HTML::Config::heading($element);
13868 print STDERR "# Write the section $element->{'texi'}\n" if ($T2H_VERBOSE);
13869 &$Texi2HTML::Config::one_section($FH);
13874 finish_element ($FH, $element, undef, $first_section);
13876 ############################################################################
13877 # Print ToC, Overview, Footnotes
13879 foreach my $direction (@element_directions)
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;
13892 $Texi2HTML::THIS_ELEMENT = undef;
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'};
13912 if (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::Config::INLINE_CONTENTS)
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'};
13930 if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::Config::INLINE_CONTENTS)
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};
13948 if ($about_body = &$Texi2HTML::Config::about_body())
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;
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};
13967 unless ($Texi2HTML::Config::SPLIT)
13969 &$Texi2HTML::Config::print_page_foot($FH);
13974 # print section, close file if needed.
13975 sub finish_element($$$$)
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";
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'})))
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'}},
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;
14005 $relative_foot_num =
14006 $files{$new_element->{'file'}}->{'relative_foot_num'};
14010 if ($element->{'top'})
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'}));
14018 if ($Texi2HTML::Config::SPLIT)
14020 if (!$files{$element->{'file'}}->{'counter'})
14025 &$Texi2HTML::Config::print_Top_footer($FH, $end_page);
14026 close_out($FH, $top_file) if ($end_page);
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'}))
14035 if (!$files{$element->{'file'}}->{'counter'})
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);
14045 print STDERR "counter $files{$element->{'file'}}->{'counter'} ne 0, file $element->{'file'}\n" if ($T2H_DEBUG);
14048 elsif (!defined($new_element))
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);
14059 &$Texi2HTML::Config::end_section($FH, 1);
14062 elsif ($new_element->{'top'})
14064 &$Texi2HTML::Config::end_section($FH, 1);
14068 &$Texi2HTML::Config::end_section($FH);
14073 # write to files with name the node name for cross manual references.
14074 sub do_node_files()
14076 foreach my $key (keys(%nodes))
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)
14084 print STDERR "Bug: file for redirection for `$node->{'texi'}' don't exist\n" unless ($novalidate);
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";
14100 #+++############################################################################
14102 # Low level functions #
14104 #---############################################################################
14106 sub locate_include_file($)
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)
14114 return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file");
14122 my $line_number = shift;
14124 if (open(*FH, "<$name"))
14126 if (defined($Texi2HTML::Config::IN_ENCODING) and $Texi2HTML::Config::USE_UNICODE)
14128 binmode(*FH, ":encoding($Texi2HTML::Config::IN_ENCODING)");
14130 my $file = { 'fh' => *FH,
14131 'input_spool' => { 'spool' => [],
14135 unshift(@fhs, $file);
14136 $input_spool = $file->{'input_spool'};
14137 $line_number->{'file_name'} = $name;
14138 $line_number->{'line_nr'} = 1;
14142 warn "$ERROR Can't read file $name: $!\n";
14152 binmode(STDOUT, ":encoding($to_encoding)") if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE);
14156 unless (open(FILE, ">$file"))
14158 die "$ERROR Can't open $file for writing: $!\n";
14160 if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE)
14162 if ($to_encoding eq 'utf8' or $to_encoding eq 'utf-8-strict')
14164 binmode(FILE, ':utf8');
14168 binmode(FILE, ':bytes');
14170 binmode(FILE, ":encoding($to_encoding)");
14175 # FIXME not used when split
14180 $file = '' if (!defined($file));
14181 return if ($Texi2HTML::Config::OUT eq '');
14182 close ($FH) || die "$ERROR: Error occurred when closing $file: $!\n";
14187 my $line_number = shift;
14190 my $file = $fhs[0];
14191 $line_number->{'file_name'} = $file->{'name'};
14192 $input_spool = $file->{'input_spool'};
14193 if (@{$input_spool->{'spool'}})
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);
14203 $file->{'input_spool'}->{'macro'} = '';
14204 $line_number->{'macro'} = '';
14206 my $fh = $file->{'fh'};
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));
14227 my $line_number = shift;
14228 warn "$WARN $text " . format_line_number($line_number) . "\n";
14231 sub echo_error($;$)
14235 my $line_number = shift;
14236 warn "$ERROR $text " . format_line_number($line_number) . "\n";
14239 sub format_line_number($)
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 . ')';
14251 # to debug, dump the result of pass_texi and pass_structure in a file
14252 sub dump_texi($$;$$)
14256 my $numbers = shift;
14258 $file = "$docu_rdir$docu_name" . ".pass$pass" if (!defined($file));
14259 unless (open(DMPTEXI, ">$file"))
14261 warn "Can't open $file for writing: $!\n";
14263 print STDERR "# Dump texi\n" if ($T2H_VERBOSE);
14265 foreach my $line (@$lines)
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));
14276 # return next tag on the line
14281 if ($line =~ /^\s*\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])/o or $line =~ /^\s*\@([a-zA-Z][\w-]*)([\s\{\}\@])/ or $line =~ /^\s*\@([a-zA-Z][\w-]*)$/)
14291 return undef unless(@$stack);
14292 return $stack->[-1];
14295 # return the next element with balanced {}
14296 sub next_bracketed($$)
14299 my $line_nr = shift;
14300 my $opened_braces = 0;
14303 if ($line =~ /^(\s*)$/)
14307 while ($line !~ /^\s*$/)
14309 #print STDERR "next_bracketed($opened_braces): $result !!! $line";
14310 if (!$opened_braces)
14311 { # beginning of item
14312 $line =~ s/^(\s*)//;
14314 #if ($line =~ s/^([^\{\}\s]+)//)
14315 if ($line =~ s/^([^\{\}]+?)(\s+)/$2/ or $line =~ s/^([^\{\}]+?)$//)
14318 $result =~ s/\s*$//;
14319 return ($result, $line, $spaces);
14321 elsif ($line =~ s/^([^\{\}]+?)([\{\}])/$2/)
14326 elsif($line =~ s/^([^\{\}]+)//)
14330 if ($line =~ s/^([\{\}])//)
14333 $opened_braces++ if ($brace eq '{');
14334 $opened_braces-- if ($brace eq '}');
14336 if ($opened_braces < 0)
14338 echo_error("too much '}' in specification", $line_nr);
14339 $opened_braces = 0;
14343 return ($result, $line, $spaces) if ($opened_braces == 0);
14346 if ($opened_braces)
14348 echo_error("'{' not closed in specification", $line_nr);
14349 return ($result . ( '}' x $opened_braces), '', $spaces);
14351 print STDERR "BUG: at the end of next_bracketed\n";
14355 # do a href using file and id and taking care of ommitting file if it is
14357 # element: structuring element to point to
14358 # file: current file
14361 my $element = shift;
14363 return '' unless defined($element);
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}))
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'}));
14377 sub normalise_space($)
14379 return undef unless (defined ($_[0]));
14381 $text =~ s/\s+/ /go;
14387 sub normalise_node($)
14389 return undef unless (defined ($_[0]));
14391 $text = normalise_space($text);
14392 $text =~ s/^top$/Top/i;
14396 sub do_anchor_label($$$$)
14398 my $command = shift;
14399 #my $anchor = shift;
14401 my $anchor = $args->[0];
14402 my $style_stack = shift;
14404 my $line_nr = shift;
14406 return '' if ($state->{'multiple_pass'});
14407 $anchor = normalise_node($anchor);
14408 if (!exists($nodes{$anchor}) or !defined($nodes{$anchor}->{'id'}))
14410 print STDERR "Bug: unknown anchor `$anchor'\n";
14412 return &$Texi2HTML::Config::anchor($nodes{$anchor}->{'id'});
14415 sub get_format_command($)
14417 my $format = shift;
14419 my $format_name = '';
14422 my $paragraph_number;
14423 my $enumerate_type;
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
14430 return ($format_name,$command,\$format->{'paragraph_number'},$term,
14431 $format->{'item_nr'}, $format->{'spec'}, $format->{'number'},
14432 $format->{'stack_at_beginning'});
14435 sub do_paragraph($$)
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'};
14444 my $indent_style = '';
14445 if (exists($state->{'paragraph_indent'}))
14447 $indent_style = $state->{'paragraph_indent'};
14448 $state->{'paragraph_indent'} = undef;
14449 delete $state->{'paragraph_indent'};
14451 my $paragraph_command_formatted;
14452 $state->{'paragraph_nr'}--;
14453 (print STDERR "Bug text undef in do_paragraph", return '') unless defined($text);
14455 $align = $state->{'paragraph_style'}->[-1] if ($state->{'paragraph_style'}->[-1]);
14457 if (exists($::style_map_ref->{$paragraph_command}) and
14458 !exists($Texi2HTML::Config::special_list_commands{$format}->{$paragraph_command}))
14460 if ($format eq 'itemize')
14463 $text = do_simple($paragraph_command, $text, $state, [$text]);
14464 $text = $text . "\n";
14467 elsif (exists($::things_map_ref->{$paragraph_command}))
14469 $paragraph_command_formatted = do_simple($paragraph_command, '', $state);
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);
14474 sub do_preformatted($$)
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 = '';
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'))
14491 $text = do_simple($leading_command, $text, $state,[$text]) if ($format eq 'itemize');
14493 elsif (exists($::things_map_ref->{$leading_command}))
14495 $leading_command_formatted = do_simple($leading_command, '', $state);
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);
14500 sub do_external_href($)
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;
14507 my $node_file = '';
14509 my $node_xhtml_id = '';
14511 #print STDERR "do_external_href $texi_node\n";
14513 if ($texi_node =~ s/^\((.+?)\)//)
14517 $texi_node = normalise_node($texi_node);
14518 if ($texi_node ne '')
14520 if (exists($nodes{$texi_node}) and ($nodes{$texi_node}->{'cross_manual_target'}))
14522 $node_id = $nodes{$texi_node}->{'cross_manual_target'};
14523 if ($Texi2HTML::Config::TRANSLITERATE_NODE)
14525 $node_file = $nodes{$texi_node}->{'cross_manual_file'};
14530 if ($Texi2HTML::Config::TRANSLITERATE_NODE)
14532 ($node_id, $node_file) = cross_manual_line($texi_node,1);
14536 $node_id = cross_manual_line($texi_node);
14539 $node_xhtml_id = node_to_id($node_id);
14540 $node_file = $node_id unless ($Texi2HTML::Config::TRANSLITERATE_NODE);
14542 return &$Texi2HTML::Config::external_href($texi_node, $node_file,
14543 $node_xhtml_id, $file);
14546 # transform node for cross ref name to id suitable for xhtml: an xhtml id
14547 # must begin with a letter.
14550 my $cross_ref_node_name = shift;
14551 $cross_ref_node_name =~ s/^([0-9_])/g_t$1/;
14552 return $cross_ref_node_name;
14555 # return 1 if the following tag shouldn't begin a line
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"}));
14566 sub no_paragraph($$)
14570 return ($state->{'paragraph_context'} or $state->{'preformatted'} or $state->{'remove_texi'} or no_line($line) or $state->{'no_paragraph'});
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($$$$)
14580 my $command = shift;
14581 my $text_following = shift;
14583 if (($state->{'preformatted'}
14584 and !$Texi2HTML::Config::format_in_paragraph{$command})
14585 or (!no_paragraph($state,$text_following)))
14587 begin_paragraph($stack, $state);
14591 # handle raw formatting, ignored regions...
14592 sub do_text_macro($$$$$)
14598 my $line_nr = shift;
14600 #print STDERR "do_text_macro $type\n";
14602 if ($text_macros{$type} eq 'raw')
14604 $state->{'raw'} = $type;
14605 #print STDERR "RAW\n";
14606 if ($state->{'raw'})
14608 push @$stack, { 'style' => $type, 'text' => '' };
14611 elsif ($text_macros{$type} eq 'value')
14613 if (($line =~ s/(\s+)($VARRE)$//) or ($line =~ s/(\s+)($VARRE)(\s)//))
14616 $value .= $3 if defined($3);
14617 if ($state->{'ignored'})
14619 if ($type eq $state->{'ignored'})
14621 $state->{'ifvalue_inside'}++;
14623 # if 'ignored' we don't care about the command as long as
14624 # the nesting is correct
14627 my $open_ifvalue = 0;
14628 if ($type eq 'ifclear')
14630 if (defined($value{$2}))
14636 push @{$state->{'text_macro_stack'}}, $type;
14639 elsif ($type eq 'ifset')
14641 unless (defined($value{$2}))
14647 push @{$state->{'text_macro_stack'}}, $type;
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' => '' };
14663 { # we accept a lone @ifset or @ifclear if it is inside an
14664 if ($type eq $state->{'ifvalue'})
14666 $state->{'ifvalue_inside'}++;
14669 echo_error ("Bad $type line: $line", $line_nr) unless ($state->{'ignored'});
14672 elsif (not $text_macros{$type})
14674 $state->{'ignored'} = $type;
14675 #print STDERR "IGNORED\n";
14679 push @{$state->{'text_macro_stack'}}, $type unless($state->{'ignored'}) ;
14681 my $text = "\@$type";
14682 $text .= $value if defined($value);
14683 return ($line, $text);
14686 # do regions handled specially, currently only tex, going through latex2html
14687 sub init_special($$)
14691 if (defined($Texi2HTML::Config::command_handler{$style}) and
14692 defined($Texi2HTML::Config::command_handler{$style}->{'init'}))
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))
14698 $special_commands{$style}->{'count'}++;
14699 return "\@special_${style}_".$special_commands{$style}->{'count'}."{}";
14705 sub do_insertcopying($)
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'}});
14714 sub get_deff_index($$$)
14718 my $line_nr = shift;
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);
14730 my $command = shift;
14732 my $line_nr = shift;
14734 my $tag = $command;
14736 if (!ref ($Texi2HTML::Config::def_map{$tag}))
14738 # substitute shortcuts for definition commands
14739 my $substituted = $Texi2HTML::Config::def_map{$tag};
14740 $substituted =~ s/(\w+)//;
14742 $line = $substituted . $line;
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;
14750 my $arg = shift @args;
14753 # backward compatibility, it was possible to have a { in front.
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')
14764 elsif ($arg eq 'name')
14768 elsif ($arg eq 'type')
14772 elsif ($arg eq 'class')
14776 elsif ($arg eq 'arg')
14778 $line = $spaces . $item . $line;
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);
14790 sub begin_deff_item($$;$)
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
14799 begin_paragraph($stack, $state)
14800 if ($state->{'preformatted'} and !$no_paragraph);
14801 delete($state->{'deff_line'});
14802 #dump_stack(undef, $stack, $state);
14805 sub begin_paragraph($$)
14811 my $top_format = top_format($stack);
14812 if (defined($top_format))
14814 $command = $top_format;
14820 $command->{'stack_at_beginning'} = [ @{$state->{'command_stack'}} ];
14821 if ($state->{'preformatted'})
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'};
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'};
14838 sub parse_format_command($$)
14842 my $command = 'asis';
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})))
14847 $line =~ s/^\s*\@([A-Za-z][\w-]*)(\{\})?\s*//;
14850 return ('', $command) if ($line =~ /^\s*$/);
14852 $line = substitute_text ({'keep_nr' => 1, 'keep_texi' => 1, 'check_item' => $tag}, $line);
14853 return ($line, $command);
14856 sub parse_enumerate($)
14860 if ($line =~ /^\s*(\w)\b/ and ($1 ne '_'))
14863 $line =~ s/^\s*(\w)\s*//;
14865 return ($line, $spec);
14868 sub parse_multitable($$)
14871 my $line_nr = shift;
14872 # first find the table width
14873 my $table_width = 0;
14874 if ($line =~ s/^\s+\@columnfractions\s+//)
14876 my @fractions = split /\s+/, $line;
14877 $table_width = $#fractions + 1;
14880 my $fraction = shift @fractions;
14881 unless ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/)
14883 echo_error ("column fraction not a number: $fraction", $line_nr);
14884 #warn "$ERROR column fraction not a number: $fraction";
14891 my $line_orig = $line;
14892 while ($line !~ /^\s*$/)
14895 ($element, $line, $spaces) = next_bracketed($line, $line_nr);
14896 if ($element =~ /^\{/)
14902 echo_error ("garbage in multitable specification: $element", $line_nr);
14906 return ($table_width);
14909 sub end_format($$$$$)
14914 my $format = shift;
14915 my $line_nr = shift;
14916 #print STDERR "END FORMAT $format\n";
14917 #dump_stack($text, $stack, $state);
14919 if ($format_type{$format} eq 'menu')
14921 $state->{'menu'}--;
14922 close_menu($text, $stack, $state, $line_nr);
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
14932 #print STDERR "END_FORMAT\n";
14933 #dump_stack($text, $stack, $state);
14935 # set to 1 if there is a mismatch between the closed format and format
14937 my $format_mismatch = 0;
14939 my $format_ref = pop @$stack;
14941 ######################### debug
14942 if (!defined($format_ref->{'text'}))
14944 push @$stack, $format_ref;
14945 print STDERR "Bug: text undef in end_format $format\n";
14946 dump_stack($text, $stack, $state);
14949 ######################### end debug
14951 if (defined($Texi2HTML::Config::def_map{$format}))
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'}}))
14960 print STDERR "Bug: not a def* under deff_item\n";
14961 push (@$stack, $format_ref);
14962 dump_stack($text, $stack, $state);
14965 ######################################### end debug
14966 elsif ($format_ref->{'format'} ne $format)
14968 $format_mismatch = 1;
14969 echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format", $line_nr);
14971 add_prev($text, $stack, &$Texi2HTML::Config::def($format_ref->{'text'}));
14973 elsif ($format_type{$format} eq 'cartouche')
14975 add_prev($text, $stack, &$Texi2HTML::Config::cartouche($format_ref->{'text'},$state->{'command_stack'}));
14977 elsif ($format eq 'float')
14979 unless (defined($state->{'float'}))
14981 print STDERR "Bug: state->{'float'} not defined in float\n";
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'};
14991 elsif (exists ($Texi2HTML::Config::complex_format_map->{$format}))
14993 $state->{'preformatted'}--;
14994 pop @{$state->{'preformatted_stack'}};
14996 if (!defined($Texi2HTML::Config::complex_format_map->{$format_ref->{'format'}}->{'begin'}))
14998 print STDERR "Bug undef $format_ref->{'format'}" . "->{'begin'} (for $format...)\n";
14999 dump_stack ($text, $stack, $state);
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);
15007 elsif (($format_type{$format} eq 'table') or ($format_type{$format} eq 'list'))
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);
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'}));
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'}));
15027 elsif ($format_type{$format} eq 'menu')
15029 # it should be short-circuited if $Texi2HTML::Config::SIMPLE_MENU
15030 if ($state->{'preformatted'})
15032 # end the fake complex format
15033 $state->{'preformatted'}--;
15034 pop @{$state->{'preformatted_stack'}};
15037 add_prev($text, $stack, &$Texi2HTML::Config::menu($format_ref->{'text'}));
15039 elsif ($format eq 'quotation')
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'}));
15045 elsif ($Texi2HTML::Config::paragraph_style{$format})
15047 if ($state->{'paragraph_style'}->[-1] eq $format)
15049 pop @{$state->{'paragraph_style'}};
15051 add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command($format_ref->{'format'},$format_ref->{'text'}));
15053 elsif (exists($Texi2HTML::Config::format_map{$format}))
15055 add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}));
15059 echo_warn("Unknown format $format", $line_nr);
15061 # special case for center as it is at the bottom of the stack
15062 my $removed_from_stack;
15063 if ($format eq 'center')
15065 $removed_from_stack = shift @{$state->{'command_stack'}};
15069 $removed_from_stack = pop @{$state->{'command_stack'}};
15071 if ($removed_from_stack ne $format and !$format_mismatch)
15073 print STDERR "Bug: removed_from_stack $removed_from_stack ne format $format\n";
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'}));
15086 sub end_simple_format($$)
15091 my $element = $Texi2HTML::Config::format_map{$tag};
15092 return &$Texi2HTML::Config::format($tag, $element, $text);
15095 sub close_menu($$$$)
15100 my $line_nr = shift;
15101 if ($state->{'menu_comment'})
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')
15113 warn "Bug waiting for menu_comment, got $menu_comment->{'format'}\n";
15114 dump_stack($text, $stack, $state);
15116 add_prev($text, $stack, &$Texi2HTML::Config::menu_comment($menu_comment->{'text'}));
15117 unless ($Texi2HTML::Config::SIMPLE_MENU)
15119 pop @{$state->{'preformatted_stack'}};
15120 $state->{'preformatted'}--;
15122 $state->{'menu_comment'}--;
15124 if ($state->{'menu_entry'})
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'};
15135 sub do_menu_link($$;$)
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'});
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);
15150 my $element = $nodes{$node_name};
15152 # menu points to an unknown node
15153 if (!$element->{'seen'})
15155 if ($menu_entry->{'node'} =~ /^\s*\(.*\)/o or $novalidate)
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);
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);
15168 foreach my $equivalent_node (@equivalent_nodes)
15170 if ($nodes{$equivalent_node}->{'seen'})
15172 $node_seen = $equivalent_node;
15176 if (defined($node_seen))
15178 echo_warn (" ---> but equivalent node `$node_seen' found");
15179 $element = $nodes{$node_seen};
15184 # the original node or an equivalent node was seen
15185 if ($element->{'seen'})
15187 if ($element->{'reference_element'})
15189 $element = $element->{'reference_element'};
15192 #print STDERR "SUBHREF in menu for `$element->{'texi'}'\n";
15193 $href = href($element, $file);
15194 if (! $element->{'node'})
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);
15200 # save the element used for the href for the description
15201 $menu_entry->{'menu_reference_element'} = $element;
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'});
15207 sub do_menu_description($$)
15211 my $menu_entry = $state->{'menu_entry'};
15213 my $element = $menu_entry->{'menu_reference_element'};
15215 return &$Texi2HTML::Config::menu_description($descr, duplicate_state($state),$element->{'text_nonumber'});
15222 my $style_stack = shift;
15224 my $line_nr = shift;
15228 #print STDERR "DO_XREF: $macro\n";
15230 for ($j = 0; $j <= $#$args; $j++)
15232 $args[$j] = normalise_space($args[$j]);
15233 # print STDERR " ($j)$args[$j]\n";
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*//)
15240 if ($macro eq 'inforef')
15242 $args[2] = $1 unless ($args[2]);
15246 $args[3] = $1 unless ($args[3]);
15249 if (($macro ne 'inforef') and $args[3])
15251 $node_texi = "($args[3])" . normalise_node($args[0]);
15254 if ($macro eq 'inforef')
15256 if ((@args < 1) or ($args[0] eq ''))
15258 echo_error ("Need a node name for \@$macro", $line_nr);
15263 echo_warn ("Too much arguments for \@$macro", $line_nr);
15265 $args[2] = '' if (!defined($args[2]));
15266 $args[1] = '' if (!defined($args[1]));
15267 $node_texi = "($args[2])$args[0]";
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++)
15276 $args[$i] = substitute_line($args[$i], $new_state);
15278 #print STDERR "(@args)\n";
15280 if (($macro eq 'inforef') or ($args[3] ne '') or ($args[4] ne ''))
15282 if ($macro eq 'inforef')
15285 $args[3] = $args[2];
15288 my $node_file = '';
15289 if ($args[3] ne '')
15291 $href = do_external_href($node_texi);
15292 $node_file = "($args[3])$args[0]";
15295 if ($args[4] ne '')
15297 $section = $args[0];
15298 if ($args[2] ne '')
15300 $section = $args[2];
15303 $result = &$Texi2HTML::Config::external_ref($macro, $section, $args[4], $node_file, $href, $args[1]);
15307 my $element = $nodes{$node_texi};
15308 if ($element and $element->{'seen'})
15310 if ($element->{'reference_element'})
15312 $element = $element->{'reference_element'};
15315 if (defined($state->{'element'}))
15317 $file = $state->{'element'}->{'file'};
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);
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 '')
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];
15341 $result = &$Texi2HTML::Config::internal_ref ($macro, $href, $short_name, $name, $element->{'section'});
15345 if (($node_texi eq '') or !$novalidate)
15347 echo_error ("Undefined node `$node_texi' in \@$macro", $line_nr);
15349 for (my $i = 0; $i < @$args -1; $i++)
15351 $text .= $args->[$i] .',';
15353 $text .= $args->[-1];
15354 $result = "\@$macro"."{${text}}";
15358 $result = &$Texi2HTML::Config::external_ref($macro, '', '', $args[0], do_external_href($node_texi), $args[1]);
15365 sub do_acronym_like($$$$$)
15367 my $command = shift;
15369 my $acronym_texi = shift @$args;
15370 my $explanation = shift @$args;
15371 my $style_stack = shift;
15373 my $line_nr = shift;
15375 my $explanation_lines;
15376 my $explanation_text;
15377 my $explanation_simple_format;
15379 if (defined($explanation))
15381 $explanation =~ s/^\s*//;
15382 $explanation =~ s/\s*$//;
15383 $explanation = undef if ($explanation eq '');
15385 $acronym_texi =~ s/^\s*//;
15386 $acronym_texi =~ s/\s*$//;
15388 return '' if ($acronym_texi eq '');
15390 my $with_explanation = 0;
15391 my $normalized_text = cross_manual_line(normalise_node($acronym_texi));
15392 if (defined($explanation))
15394 $with_explanation = 1;
15395 $acronyms_like{$command}->{$normalized_text} = $explanation;
15397 elsif (exists($acronyms_like{$command}->{$normalized_text}))
15399 $explanation = $acronyms_like{$command}->{$normalized_text};
15402 if (defined($explanation))
15404 @$explanation_lines = map {$_ = $_."\n"} split (/\n/, $explanation);
15406 foreach my $line(@$explanation_lines)
15408 $line .= ' ' if (chomp ($line));
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));
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);
15420 sub do_caption_shortcaption($$$$$)
15422 my $command = shift;
15424 my $text = $args->[0];
15425 my $style_stack = shift;
15427 my $line_nr = shift;
15429 if (!exists($state->{'float'}))
15431 #dump_stack(\"", [], $state);
15432 echo_error("\@$command outside of float", $line_nr);
15435 my $float = $state->{'float'};
15436 my @texi_lines = map {$_ = $_."\n"} split (/\n/, $text);
15437 $float->{"${command}_texi"} = \@texi_lines;
15441 # function called when a @float is encountered. Don't do any output
15442 # but prepare $state->{'float'}
15443 sub do_float_line($$$$$)
15445 my $command = shift;
15448 my $style_texi = shift @args;
15449 my $label_texi = shift @args;
15450 my $style_stack = shift;
15452 my $line_nr = shift;
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";
15464 { # a float without label. It can't be the target for refs.
15465 $state->{'float'} = { 'float' => 1 };
15466 if (defined($style_texi))
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);
15473 #print STDERR "float: (no label) $state->{'float'}\n";
15478 sub do_quotation_line($$$$$)
15480 my $command = shift;
15483 my $text_texi = shift @args;
15484 my $style_stack = shift;
15486 my $line_nr = shift;
15489 $text_texi = undef if (defined($text_texi) and $text_texi=~/^\s*$/);
15490 if (defined($text_texi))
15492 $text = substitute_line($text_texi, duplicate_state($state));
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);
15501 sub do_def_line($$$$$)
15503 my $command = shift;
15506 my $arguments = shift @args;
15507 my $style_stack = shift;
15509 my $line_nr = shift;
15511 $state->{'deff_line'}->{'arguments'} = $arguments;
15515 sub do_footnote($$$$)
15517 my $command = shift;
15519 my $text = $args->[0];
15520 my $style_stack = shift;
15522 my $line_nr = shift;
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)
15532 $from_file = $state->{'element'}->{'file'};
15535 initialise_state(\%state);
15536 if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
15538 $state{'element'} = $footnote_element;
15542 $state{'element'} = $state->{'element'};
15545 $file = $docu_foot if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SEPARATED_FOOTNOTES);
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;
15558 my $command = shift;
15560 my $text = $args->[0];
15561 my $style_stack = 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];
15569 echo_error ("no file argument for \@image", $line_nr);
15570 #warn "$ERROR no file argument for \@image\n";
15573 $args[4] = '' if (!defined($args[4]));
15574 $args[3] = '' if (!defined($args[3]));
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)
15581 if ($image = locate_include_file($file))
15583 $file_name = $file;
15587 $image = '' if (!defined($image));
15590 if ($args[3] =~ /\S/)
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/);
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);
15602 sub duplicate_state($)
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'}} ] }
15620 sub expand_macro($$$$$)
15624 my $end_line = shift;
15625 my $line_nr = shift;
15628 # we dont expand macros when in ignored environment.
15629 return if ($state->{'ignored'});
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));
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'};
15644 die "Bug end_line not defined" if (!defined($end_line));
15646 for ($i=0; $i<=$#$formal_args; $i++)
15648 $args->[$i] = "" unless (defined($args->[$i]));
15649 print STDERR "# arg($i): $args->[$i]\n" if ($T2H_DEBUG & $DEBUG_MACROS);
15651 echo_error ("too much arguments for macro $name", $line_nr) if (defined($args->[$i + 1]));
15655 if ($macrobody =~ s/^([^\\]*)\\//o)
15657 $result .= $1 if defined($1);
15658 if ($macrobody =~ s/^\\//)
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
15666 elsif ($macrobody =~ s/^([^\\]*)\\//)
15669 if (defined($args_index->{$arg}))
15671 $result .= $args->[$args_index->{$arg}];
15675 warn "$ERROR \\ not followed by \\ or an arg but by $arg in macro\n";
15676 $result .= '\\' . $arg;
15681 $result .= $macrobody;
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'})
15689 unshift @{$state->{'spool'}}, (@result, $end_line);
15693 unshift @{$input_spool->{'spool'}}, (@result, $end_line);
15694 $input_spool->{'macro'} = $name if ($input_spool->{'macro'} eq '');
15696 if ($T2H_DEBUG & $DEBUG_MACROS)
15698 print STDERR "# macro expansion result:\n";
15699 #print STDERR "$first_line";
15700 foreach my $line (@result)
15702 print STDERR "$line";
15704 print STDERR "# macro expansion result end\n";
15708 sub do_index_summary_file($)
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;
15715 foreach my $key (sort keys %$entries)
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'})
15730 $origin_href .= '#' . $entry->{'label'};
15734 # If the $indexed_element element and the $index entry are on
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'})
15742 $origin_href .= '#' . $indexed_element->{'id'};
15746 $origin_href .= '#' . $entry->{'id'} ;
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});
15756 &$Texi2HTML::Config::index_summary_file_end ($name, $printed_indices{$name});
15759 sub do_index_page($$;$)
15761 my $index_elements = 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;
15770 sub do_index_summary($$)
15772 my $element = shift;
15773 my $index_elements = shift;
15778 for my $index_element_item (@$index_elements)
15780 my $index_element = $index_element_item->{'element'};
15782 $file .= $index_element->{'file'} if ($index_element->{'file'} ne $element->{'file'});
15784 for my $letter (@{$index_element_item->{'page'}->{'letters'}})
15786 if ($letter =~ /^[A-Za-z]/)
15788 push @letters, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index");
15792 push @symbols, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index");
15797 return &$Texi2HTML::Config::index_summary(\@letters, \@symbols);
15800 sub do_index_entries($$$)
15802 my $element = shift;
15808 foreach my $letter (@{$page->{'letters'}})
15811 foreach my $entry (@{$page->{'entries_by_letter'}->{$letter}})
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'})
15826 $origin_href .= '#' . $entry->{'label'};
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'})
15838 $origin_href .= '#' . $indexed_element->{'id'};
15842 $origin_href .= '#' . $entry->{'id'} ;
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'});
15851 $letters .= &$Texi2HTML::Config::index_letter ($letter, "$element->{'id'}" . "_$index", $entries);
15854 return &$Texi2HTML::Config::print_index($letters, $name);
15857 # remove texi commands, replacing with what seems adequate. see simple_map_texi
15859 # Doesn't protect html
15862 return substitute_text ({ 'remove_texi' => 1}, @_);
15865 # Same as remove texi but protect text and use special maps for @-commands
15866 sub simple_format($@)
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;
15884 sub enter_table_index_entry($$$$)
15889 my $line_nr = shift;
15890 if ($state->{'item'} and ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/))
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'});
15905 sub scan_texi($$$$;$)
15911 my $line_nr = shift;
15913 die "stack not an array ref" unless (ref($stack) eq "ARRAY");
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";
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.
15933 # in macro definition
15934 if ($state->{'macro_inside'})
15936 if (s/^([^\\\@]*\\)//)
15937 {# protected character or @end macro
15938 $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
15941 $state->{'macro'}->{'body'} .= '\\' unless ($state->{'ignored'});
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)
15948 $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'});
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)
15955 $state->{'macro_inside'}--;
15956 next if ($state->{'ignored'});
15957 if ($state->{'macro_inside'})
15959 $state->{'macro'}->{'body'} .= $1;
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*$/);
15969 elsif(/^(\@r?macro\s+\w+\s*.*)/)
15971 $state->{'macro'}->{'body'} .= $_ unless ($state->{'ignored'});
15972 $state->{'macro_inside'}++;
15977 $state->{'macro'}->{'body'} .= '@' . $1 unless ($state->{'ignored'});
15982 $state->{'macro'}->{'body'} .= '@' unless ($state->{'ignored'});
15988 if ($state->{'ignored'})
15993 $state->{'macro'}->{'body'} .= $1 if (defined($1));
15996 $state->{'macro'}->{'body'} .= $_;
16002 # in macro arguments parsing/expansion. Here \ { } and , if this is a
16003 # multi args macro have a signification, the remaining is passed
16005 if (defined($state->{'macro_name'}))
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
16016 if (s/^([^$special_chars]*)([$special_chars])//)
16018 $state->{'macro_args'}->[-1] .= $1 if defined($1);
16019 # \ protects any character in macro arguments
16022 print STDERR "# macro call: protected char\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16025 $state->{'macro_args'}->[-1] .= $1;
16029 $state->{'macro_args'}->[-1] .= '\\';
16033 { # in texinfo 4.8.90 a comma in braces is protected
16034 if ($state->{'macro_depth'} > 1)
16036 $state->{'macro_args'}->[-1] .= ',';
16040 print STDERR "# macro call: new arg\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16042 push @{$state->{'macro_args'}}, '';
16046 { # balanced } ends the macro call, otherwise it is in the arg
16047 $state->{'macro_depth'}--;
16048 if ($state->{'macro_depth'} == 0)
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'};
16059 print STDERR "# macro call: closing }\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16060 add_text('}', \$state->{'macro_args'}->[-1]);
16065 print STDERR "# macro call: opening {\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16066 $state->{'macro_depth'}++;
16067 add_text('{', \$state->{'macro_args'}->[-1]);
16071 print STDERR "# macro call: end of line\n" if ($T2H_DEBUG & $DEBUG_MACROS);
16072 $state->{'macro_args'}->[-1] .= $_;
16075 # in a raw format, verbatim, tex or html
16076 if ($state->{'raw'})
16078 my $tag = $state->{'raw'};
16081 if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
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);
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
16092 add_prev ($text, $stack, $1);
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
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'};
16109 {# we add it even if 'ignored', it'll be discarded when there is
16111 add_prev ($text, $stack, $_);
16116 # in a @verb{ .. } macro
16117 if (defined($state->{'verb'}))
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'};
16130 {# we add it even if 'ignored', it'll be discarded when closing
16131 add_prev($text, $stack, $_);
16135 # In ignored region
16136 if ($state->{'ignored'})
16138 #print STDERR "IGNORED(ifvalue($state->{'ifvalue_inside'})): $state->{'ignored'}\n";
16139 if (/^.*?\@end(\s+)([a-zA-Z]\w+)/)
16141 if ($2 eq $state->{'ignored'})
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'})
16147 if ($state->{'ifvalue_inside'} == 1)
16148 {# closing still opened @-commands with braces
16149 pop (@$stack) while (@$stack and $stack->[-1]->{'style'} ne 'ifvalue')
16152 $state->{'ifvalue_inside'}--;
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);
16165 return if /^\s*$/o;
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'}));
16178 if (s/^([^{}@]*)\@end(\s+)([a-zA-Z][\w-]*)//)
16180 my $leading_text = $1;
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]))
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'})
16195 add_prev($text, $stack, "\@end${space}$end_tag");
16199 #print STDERR "End $end_tag\n";
16200 #dump_stack($text, $stack, $state);
16201 return if (/^\s*$/);
16204 elsif ($text_macros{$end_tag})
16206 echo_error ("\@end $end_tag without corresponding element", $line_nr);
16210 add_prev($text, $stack, "\@end${space}$end_tag");
16215 elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
16217 add_prev($text, $stack, $1) unless $state->{'ignored'};
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')
16227 ($_, $line, $args) = preserve_command($_, $macro);
16228 add_prev ($text, $stack, "\@$macro" . $line) unless $state->{'ignored'};
16230 # pertusus: it seems that value substitution are performed after
16231 # macro argument expansions: if we have
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
16239 elsif($macro eq 'set' or $macro eq 'clear')
16241 if ($macro eq 'set')
16243 if (s/^(\s+)($VARRE)(\s+)(.*)$//o)
16245 if ($state->{'arg_expansion'})
16247 my $line = "\@$macro" . $1.$2.$3;
16248 $line .= $4 if (defined($4));
16249 add_prev($text, $stack, $line);
16252 next if $state->{'ignored'};
16257 echo_warn ("Missing argument for \@$macro", $line_nr);
16260 elsif ($macro eq 'clear')
16262 if (s/^(\s+)($VARRE)//o)
16264 if ($state->{'arg_expansion'})
16266 add_prev($text, $stack, "\@$macro" . $1 . $2);
16269 next if $state->{'ignored'};
16274 echo_warn ("Missing argument for \@$macro", $line_nr);
16277 return if (/^\s*$/);
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*(.*)/)
16285 unless ($state->{'ignored'})
16287 if (exists($macros->{$name}))
16289 echo_warn ("macro `$name' allready defined " .
16290 format_line_number($macros->{$name}->{'line_nr'}) . " redefined", $line_nr);
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.
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;
16306 my $debug_msg = '';
16307 foreach my $arg (@args)
16308 { # when expanding macros, the argument index is retrieved
16310 $macros->{$name}->{'args_index'}->{$arg} = $arg_index;
16311 $debug_msg .= "$arg($arg_index) ";
16314 $macros->{$name}->{'body'} = '';
16315 $state->{'macro'} = $macros->{$name};
16316 print STDERR "# macro def $name: $debug_msg\n"
16317 if ($T2H_DEBUG & $DEBUG_MACROS);
16320 {# it means we have a macro without a name
16321 echo_error ("Macro definition without macro name $_", $line_nr)
16322 unless ($state->{'ignored'});
16326 elsif (defined($text_macros{$macro}))
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.
16334 if ((($state->{'raw'} or (($macro eq 'menu') and $text_macros{'menu'}) or (exists($region_lines{$macro}))) and !$state->{'ignored'}) or $state->{'arg_expansion'})
16336 add_prev($text, $stack, $tag);
16339 #dump_stack ($text, $stack, $state);
16340 next if $macro_kept;
16341 return if (/^\s*$/);
16343 elsif ($macro eq 'documentencoding')
16347 if (s/(\s+)([0-9\w\-]+)//)
16351 next if ($state->{'ignored'});
16352 if (!$state->{'arg_expansion'} and !$state->{'ignored'})
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)
16360 foreach my $file (@fhs)
16362 binmode($file->{'fh'}, ":encoding($from_encoding)");
16367 add_prev($text, $stack, "\@$macro" . $spaces . $encoding) unless ($state->{'ignored'});
16369 elsif ($macro eq 'definfoenclose')
16371 # FIXME if 'ignored' or 'arg_expansion' maybe we could parse
16372 # the args anyway and don't take away the whole line?
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'})
16378 add_prev($text, $stack, "\@$macro" . $_);
16381 return if ($state->{'ignored'});
16382 if (s/^\s+([a-z]+)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//)
16384 $info_enclose{$1} = [ $2, $3 ];
16388 echo_error("Bad \@$macro", $line_nr);
16390 return if (/^\s*$/);
16393 elsif ($macro eq 'include')
16395 if ($state->{'arg_expansion'})
16397 add_prev($text, $stack, "\@$macro" . $_);
16400 return if ($state->{'ignored'});
16401 #if (s/^\s+([\/\w.+-]+)//o)
16402 if (s/^(\s+)(.*)//o)
16404 my $file_name = $2;
16405 $file_name =~ s/\s*$//;
16406 my $file = locate_include_file($file_name);
16407 if (defined($file))
16409 open_file($file, $line_nr);
16410 print STDERR "# including $file\n" if $T2H_VERBOSE;
16414 echo_error ("Can't find $file_name, skipping", $line_nr);
16419 echo_error ("Bad include line: $_", $line_nr);
16424 elsif ($macro eq 'value')
16426 if (s/^{($VARRE)}//)
16429 if ($state->{'arg_expansion'})
16431 add_prev($text, $stack, "\@$macro" .'{'. $value .'}');
16434 next if ($state->{'ignored'});
16435 my $expansion = "No value for $value";
16436 $expansion = $value{$value} if (defined($value{$value}));
16437 $_ = $expansion . $_;
16441 if ($state->{'arg_expansion'})
16443 add_prev($text, $stack, "\@$macro");
16446 next if ($state->{'ignored'});
16447 echo_error ("bad \@value macro", $line_nr);
16450 elsif ($macro eq 'unmacro')
16451 { #FIXME with 'arg_expansion' should it be passed unmodified ?
16452 if ($state->{'ignored'})
16458 delete $macros->{$1} if (s/^\s+(\w+)//);
16460 return if (/^\s*$/);
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
16468 # in 'ignored' we parse macro defined args anyway as it removes
16469 # some text, but we don't expand the macro
16471 my $ref = $macros->{$macro}->{'args'};
16472 # we remove any space/new line before the argument
16474 { # the macro has args
16475 $state->{'macro_args'} = [ "" ];
16476 $state->{'macro_name'} = $macro;
16477 $state->{'macro_depth'} = 1;
16479 elsif (($#$ref >= 1) or ($#$ref <0))
16480 { # no brace -> no arg
16481 $_ = expand_macro ($macro, [], $_, $line_nr, $state);
16485 { # macro with one arg on the line
16487 $_ = expand_macro ($macro, [$_], "\n", $line_nr, $state);
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 {
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')
16505 echo_error ("without associated character", $line_nr);
16506 #warn "$ERROR verb at end of line";
16511 $state->{'verb'} = $1;
16514 push (@$stack, { 'style' => $macro, 'text' => '' });
16518 add_prev($text, $stack, "\@$macro") unless($state->{'ignored'});
16522 #elsif(s/^([^{}@]*)\@(.)//o)
16523 elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
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'});
16530 elsif (s/^([^{}]*)([{}])//o)
16532 # in ignored section we cannot be sure that there is an @-command
16533 # allready opened so we must discard the text.
16535 add_prev($text, $stack, $1) unless($state->{'ignored'});
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' => '' };
16547 my $style = pop @$stack;
16549 if (($style->{'style'} ne '') and exists($info_enclose{$style->{'style'}}) and !$state->{'arg_expansion'})
16551 $result = $info_enclose{$style->{'style'}}->[0] . $style->{'text'} . $info_enclose{$style->{'style'}}->[1];
16553 elsif ($style->{'style'} ne '')
16555 $result = '@' . $style->{'style'} . '{' . $style->{'text'} . '}';
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'});
16566 if ($state->{'ignored'})
16568 print STDERR "# Popped `$style->{'style'}' in ifset/ifclear\n" if ($T2H_DEBUG);
16571 add_prev ($text, $stack, $result);
16572 #print STDERR "MACRO end $style->{'style'} remaining: $_";
16577 # we warn in the last pass that there is a } without open
16578 add_prev ($text, $stack, '}') unless($state->{'ignored'});
16584 #print STDERR "END_LINE $_";
16585 add_prev($text, $stack, $_) unless($state->{'ignored'});
16589 return undef if ($state->{'ignored'});
16593 sub close_structure_command($$$$)
16595 my $cmd_ref = shift;
16597 my $unclosed_commands = shift;
16598 my $line_nr = shift;
16601 if ($cmd_ref->{'style'} eq 'anchor')
16603 my $anchor = $cmd_ref->{'text'};
16604 $anchor = normalise_node($anchor);
16605 if ($nodes{$anchor})
16607 echo_error ("Duplicate node for anchor found: $anchor", $line_nr);
16611 $nodes{$anchor} = { 'anchor' => 1, 'seen' => 1, 'texi' => $anchor, 'id' => 'ANC' . $anchor_num};
16612 push @{$state->{'place'}}, $nodes{$anchor};
16614 elsif ($cmd_ref->{'style'} eq 'footnote')
16616 if ($Texi2HTML::Config::SEPARATED_FOOTNOTES)
16618 $state->{'element'} = $state->{'footnote_element'};
16619 $state->{'place'} = $state->{'footnote_place'};
16622 elsif ($cmd_ref->{'style'} eq 'caption' or $cmd_ref->{'style'}
16623 eq 'shortcaption' and $state->{'float'})
16625 my @texi_lines = map {$_ = $_."\n"} split (/\n/, $cmd_ref->{'text'});
16626 $state->{'float'}->{$cmd_ref->{'style'} . "_texi"} = \@texi_lines;
16628 if (($cmd_ref->{'style'} eq 'titlefont') and ($cmd_ref->{'text'} =~ /\S/))
16630 $state->{'element'}->{'titlefont'} = $cmd_ref->{'text'} unless ((exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} eq 'titlepage')) or defined($state->{'element'}->{'titlefont'})) ;
16632 if (defined($Texi2HTML::Config::command_handler{$cmd_ref->{'style'}}))
16634 $result = init_special($cmd_ref->{'style'},$cmd_ref->{'text'});
16635 if ($unclosed_commands)
16637 $result .= "\n"; # the end of line is eaten by init_special
16638 echo_error("Closing specially handled \@-command $cmd_ref->{'style'}",$line_nr);
16641 elsif ($cmd_ref->{'style'})
16643 $result = '@' . $cmd_ref->{'style'} . '{' . $cmd_ref->{'text'};
16644 $result .= '}' unless ($unclosed_commands);
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);
16656 sub scan_structure($$$$;$)
16662 my $line_nr = shift;
16664 die "stack not an array ref" unless (ref($stack) eq "ARRAY");
16666 #print STDERR "SCAN_STRUCTURE: $line";
16667 #dump_stack ($text, $stack, $state);
16668 if (!$state->{'raw'} and (!exists($state->{'region_lines'})))
16670 if (!$state->{'verb'} and $state->{'menu'} and /^\*/o)
16673 delete ($state->{'after_element'});
16674 my $menu_line = $_;
16676 if (/^\*\s+($NODERE)::/)
16680 elsif (/^\*\s+([^:]+):\s*([^\t,\.\n]+)[\t,\.\n]/)
16687 menu_entry_texi(normalise_node($node), $state, $line_nr);
16690 unless (no_line($_))
16692 delete $state->{'after_element'};
16699 #print STDERR "WHILE (s):$_";
16700 #dump_stack($text, $stack, $state);
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.
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
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
16717 # @end itemize, @end ftable works like @end ifnothtml.
16718 # except that @item on the same line than @end vtable doesn't work
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...
16725 # see more examples in formatting directory
16727 if ($state->{'raw'})
16729 my $tag = $state->{'raw'};
16730 ################# debug
16731 if (! @$stack or ($stack->[-1]->{'style'} ne $tag))
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);
16738 ################# end debug
16739 if (s/^(.*?)\@end\s$tag$// or s/^(.*?)\@end\s$tag\s//)
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*$/)
16748 add_prev ($text, $stack, init_special($style->{'style'}, $style->{'text'}));
16754 my $after_macro = '';
16755 $after_macro = ' ' unless (/^\s*$/);
16756 add_prev ($text, $stack, $style->{'text'} . "\@end $tag" . $after_macro);
16758 unless (no_line($_))
16760 delete ($state->{'after_element'});
16766 add_prev ($text, $stack, $_);
16767 return if (defined($Texi2HTML::Config::command_handler{$tag}));
16772 if (defined($state->{'verb'}))
16774 my $char = quotemeta($state->{'verb'});
16775 if (s/^(.*?)$char\}/\}/)
16777 add_prev($text, $stack, $1 . $state->{'verb'});
16778 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
16779 delete $state->{'verb'};
16784 add_prev($text, $stack, $_);
16789 unless (no_line($_))
16791 delete $state->{'after_element'};
16794 if (s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
16796 add_prev($text, $stack, $1);
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]))
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)
16812 close_region($state);
16814 #dump_stack($text, $stack, $state);
16816 if ($end_tag eq 'menu')
16818 add_prev($text, $stack, "\@end $end_tag");
16819 $state->{'menu'}--;
16823 #print STDERR "End $end_tag\n";
16824 #dump_stack($text, $stack, $state);
16825 return if (/^\s*$/);
16828 elsif ($text_macros{$end_tag})
16830 echo_error ("\@end $end_tag without corresponding element", $line_nr);
16831 #dump_stack($text, $stack, $state);
16835 if ($end_tag eq 'float' and $state->{'float'})
16837 delete $state->{'float'};
16839 elsif ($end_tag eq $state->{'table_stack'}->[-1])
16841 enter_table_index_entry($text, $stack, $state, $line_nr);
16842 pop @{$state->{'table_stack'}};
16845 add_prev($text, $stack, "\@end $end_tag");
16849 #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
16851 elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o)
16853 add_prev($text, $stack, $1);
16855 #print STDERR "MACRO $macro\n";
16856 if (defined($Texi2HTML::Config::misc_command{$macro}))
16859 ($_, $line) = misc_command_structure($_, $macro, $state,
16861 add_prev ($text, $stack, "\@$macro".$line);
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'))
16867 my $index_prefix = $1;
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" . $_);
16875 elsif (defined($text_macros{$macro}))
16877 #print STDERR "TEXT_MACRO: $macro\n";
16878 if ($text_macros{$macro} eq 'raw')
16880 $state->{'raw'} = $macro;
16881 #print STDERR "RAW\n";
16883 elsif ($format_type{$macro} and $format_type{$macro} eq 'menu')
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";
16890 elsif (exists($region_lines{$macro}))
16892 if (exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} ne $macro))
16894 echo_error("\@$macro not allowed within $state->{'region_lines'}->{'format'}", $line_nr);
16897 if (!exists($state->{'region_lines'}))
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;
16907 $state->{'region_lines'}->{'number'}++;
16909 push @{$state->{'text_macro_stack'}}, $macro;
16911 # if it is a raw formatting command or a menu command
16912 # we must keep it for later
16914 if (($state->{'raw'} and (!defined($Texi2HTML::Config::command_handler{$macro}))) or ($macro eq 'menu'))
16916 add_prev($text, $stack, "\@$macro");
16919 if ($state->{'raw'})
16921 push @$stack, { 'style' => $macro, 'text' => '' };
16923 next if $macro_kept;
16924 #dump_stack ($text, $stack, $state);
16925 return if (/^\s*$/);
16927 elsif ($macro eq 'float')
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'})
16938 echo_error ("Duplicate label found: $label_texi", $line_nr);
16947 if (exists($nodes{$label_texi}) and defined($nodes{$label_texi}))
16948 { # float appeared in a menu
16949 $float = $nodes{$label_texi};
16953 $nodes{$label_texi} = $float;
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;
16968 add_prev($text, $stack, "\@$macro" . $_);
16971 elsif (defined($Texi2HTML::Config::def_map{$macro}))
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);
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));
16987 elsif ($macro =~ /^itemx?$/)
16989 enter_table_index_entry($text, $stack, $state, $line_nr);
16990 if ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/)
16992 $state->{'item'} = $macro;
16993 push @$stack, { 'format' => 'index_item', 'text' => "" };
16997 add_prev($text, $stack, "\@$macro");
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");
17008 if ($macro eq 'verb')
17012 # We allready warned in pass texi
17013 #warn "$ERROR verb at end of line";
17018 $state->{'verb'} = $1;
17021 elsif ($macro eq 'footnote' and $Texi2HTML::Config::SEPARATED_FOOTNOTES)
17023 $state->{'footnote_element'} = $state->{'element'};
17024 $state->{'footnote_place'} = $state->{'place'};
17025 $state->{'element'} = $footnote_element;
17026 $state->{'place'} = $footnote_element->{'place'};
17028 push (@$stack, { 'style' => $macro, 'text' => '' });
17032 add_prev($text, $stack, "\@$macro");
17036 #elsif(s/^([^{}@]*)\@(.)//o)
17037 elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o)
17039 add_prev($text, $stack, $1 . "\@$2");
17042 elsif (s/^([^{}]*)([{}])//o)
17044 add_prev($text, $stack, $1);
17047 push @$stack, { 'style' => '', 'text' => '' };
17053 my $style = pop @$stack;
17055 add_prev ($text, $stack, close_structure_command($style,
17056 $state, 0, $line_nr));
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, '}');
17070 #print STDERR "END_LINE $_";
17071 add_prev($text, $stack, $_);
17072 enter_table_index_entry($text, $stack, $state, $line_nr);
17079 sub scan_line($$$$;$)
17085 my $line_nr = shift;
17087 die "stack not an array ref" unless (ref($stack) eq "ARRAY");
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'}))
17096 $_ = $state->{'prepend_text'} . $_;
17097 $state->{'prepend_text'} = undef;
17098 delete $state->{'prepend_text'};
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'})
17105 my ($node, $name, $ending);
17106 if (s/^\*(\s+$NODERE)(::)//o)
17111 elsif (s/^\*(\s+[^:]+):(\s*[^\t,\.\n]+)([\t,\.\n])//o)
17119 my $top_stack = top_stack($stack);
17120 if ($top_stack and $top_stack->{'format'} and
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')
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' => ''};
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
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;
17150 # we're in a menu entry description
17151 if ($state->{'menu_entry'} and !$new_menu_entry)
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);
17160 { # enter menu comment after menu entry
17161 ################################ begin debug
17162 if (!$top_stack->{'format'} or ($top_stack->{'format'} ne 'menu_description'))
17164 print STDERR "Bug: begin menu comment but previous isn't menu_description\n";
17165 dump_stack ($text, $stack, $state);
17167 print STDERR "# Menu comment begins\n" if ($T2H_DEBUG & $DEBUG_MENU);
17168 ################################ end debug
17169 my $descr = pop(@$stack);
17171 add_prev ($text, $stack, do_menu_description($descr->{'text'}, $state));
17172 delete $state->{'menu_entry'};
17173 unless (/^\s*\@end\s+menu\b/)
17175 $state->{'menu_comment'}++;
17176 push @$stack, {'format' => 'menu_comment', 'text' => ''};
17177 unless ($Texi2HTML::Config::SIMPLE_MENU)
17179 push @{$state->{'preformatted_stack'}}, {'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE, 'class' => 'menu-comment' };
17180 $state->{'preformatted'}++;
17181 begin_paragraph($stack, $state);
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
17190 add_prev($text, $stack, $_);
17193 elsif (!$state->{'raw'})
17195 my $next_tag = next_tag($_);
17196 if ($state->{'deff_line'} and !defined($Texi2HTML::Config::def_map{$next_tag}))
17198 begin_deff_item($stack, $state);
17206 if ($state->{'paragraph_context'})
17207 { # An empty line ends a paragraph
17208 close_paragraph($text, $stack, $state, $line_nr);
17210 add_prev($text, $stack, &$Texi2HTML::Config::empty_line($_,$state));
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);
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);
17230 delete $state->{'end_of_line_protected'}
17231 if ($state->{'end_of_line_protected'});
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'}))
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
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*$/)
17250 if ($state->{'keep_texi'})
17252 add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}");
17254 elsif ($state->{'remove_texi'})
17256 add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi($style->{'style'}, $style->{'text'}));
17260 add_prev($text, $stack, &$Texi2HTML::Config::raw($style->{'style'}, $style->{'text'}));
17263 if (!$state->{'keep_texi'} and !$state->{'remove_texi'})
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*$/);
17271 delete $state->{'raw'};
17276 print STDERR "#within raw $state->{'raw'}:$_" if ($T2H_DEBUG & $DEBUG_FORMATS);
17277 add_prev ($text, $stack, $_);
17282 # we are within a @verb
17283 if (defined($state->{'verb'}))
17285 my $char = quotemeta($state->{'verb'});
17286 if (s/^(.*?)$char\}/\}/)
17288 if ($state->{'keep_texi'})
17290 add_prev($text, $stack, $1 . $state->{'verb'});
17291 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'};
17293 elsif ($state->{'remove_texi'})
17295 add_prev($text, $stack, $1);
17299 add_prev($text, $stack, do_text($1, $state));
17301 delete $state->{'verb'};
17306 add_prev($text, $stack, $_);
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
17316 if ($state->{'end_of_line_protected'} and $state->{'deff_line'})
17318 print STDERR "Bug: 'end_of_line_protected' with text following: $_\n"
17323 # We handle now the end tags
17325 if ($state->{'keep_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
17328 add_prev($text, $stack, $1 . "\@end $end_tag");
17332 elsif ($state->{'remove_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//)
17334 add_prev($text, $stack, $1);
17338 if (s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)\s//o or s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)$//o)
17340 add_prev($text, $stack, do_text($1, $state));
17342 #print STDERR "END_MACRO $end_tag\n";
17343 #dump_stack ($text, $stack, $state);
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);
17361 echo_error ("\@end $end_tag without corresponding opening", $line_nr);
17362 add_prev($text, $stack, "\@end $end_tag");
17366 if (!$format_type{$end_tag})
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");
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);
17379 $top_stack = top_stack($stack);
17380 if (!$top_stack or (!defined($top_stack->{'format'})))
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);
17387 # Warn if the format on top of stack is not compatible with the
17388 # end tag, and find the end tag.
17390 ($top_stack->{'format'} eq $end_tag)
17393 ($format_type{$end_tag} eq 'menu') and
17395 ($top_stack->{'format'} eq 'menu_preformatted') or
17396 ($top_stack->{'format'} eq 'menu_comment') or
17397 ($top_stack->{'format'} eq 'menu_description')
17401 ($end_tag eq 'multitable') and
17403 ($top_stack->{'format'} eq 'cell') or
17404 ($top_stack->{'format'} eq 'null')
17408 ($format_type{$end_tag} eq 'list' ) and
17409 ($top_stack->{'format'} eq 'item')
17413 ($format_type{$end_tag} eq 'table') and
17414 ($end_tag ne 'multitable')
17417 ($top_stack->{'format'} eq 'term') or
17418 ($top_stack->{'format'} eq 'line')
17422 (defined($Texi2HTML::Config::def_map{$end_tag})) and
17423 ($top_stack->{'format'} eq 'deff_item')
17426 ($end_tag eq 'row') and
17427 ($top_stack->{'format'} eq 'cell')
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'})))
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);
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}))));
17457 # We should now be able to handle the format
17458 if (defined($format_type{$end_tag}) and $format_type{$end_tag} ne 'fake')
17460 end_format($text, $stack, $state, $end_tag, $line_nr);
17461 begin_paragraph_after_command($state,$stack,$end_tag,$_);
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";
17472 #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o)
17474 elsif (s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@,]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{},@]*)\@([a-zA-Z][\w-]*)$//o)
17476 add_prev($text, $stack, do_text($1, $state));
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')
17485 my $top_stack = top_stack($stack);
17486 #################################### debug
17487 if (!$top_stack or !$top_stack->{'format'}
17488 or ($top_stack->{'format'} ne 'paragraph'))
17490 print STDERR "Bug: end_paragraph but no paragraph to end\n";
17491 dump_stack ($text, $stack, $state);
17494 #################################### end debug
17496 my $paragraph = pop @$stack;
17497 add_prev ($text, $stack, do_paragraph($paragraph->{'text'}, $state));
17500 # Handle macro added by close_stack to mark preformatted region end
17501 elsif ($macro eq 'end_preformatted')
17503 #print STDERR "END_PREFORMATTED\n";
17505 my $top_stack = top_stack($stack);
17506 #################################### debug
17507 if (!$top_stack or !$top_stack->{'format'}
17508 or ($top_stack->{'format'} ne 'preformatted'))
17510 print STDERR "Bug: end_preformatted but no preformatted to end\n";
17511 dump_stack ($text, $stack, $state);
17514 #################################### end debug
17515 my $paragraph = pop @$stack;
17517 add_prev ($text, $stack, do_preformatted($paragraph->{'text'}, $state));
17520 if (defined($Texi2HTML::Config::misc_command{$macro}))
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')))
17532 ($_, $line, $args) = preserve_command($_, $macro);
17533 add_prev($text, $stack, "\@$macro". $line);
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'})
17542 begin_paragraph($stack, $state) if
17543 (!no_paragraph($state,$_));
17547 if ($macro eq 'listoffloats')
17549 if ($state->{'keep_texi'})
17553 add_prev($text, $stack, "\@$macro" . $1);
17557 return undef if ($state->{'remove_texi'});
17559 if (s/^(\s+)(.*)//o)
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}))
17566 close_paragraph($text, $stack, $state, $line_nr);
17567 my @listoffloats_entries = ();
17568 foreach my $float (@{$floats{$style_id}->{'floats'}})
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'}));
17579 add_prev($text, $stack, &$Texi2HTML::Config::listoffloats($arg, $style, \@listoffloats_entries));
17583 echo_warn ("Unknown float style $arg", $line_nr);
17588 echo_error ("Bad \@$macro line: $_", $line_nr);
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/^{//)
17597 if ($macro eq 'verb')
17602 #warn "$ERROR verb at end of line";
17607 $state->{'verb'} = $1;
17610 elsif ($macro eq 'm_cedilla' and !$state->{'keep_texi'})
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')))
17622 push (@{$state->{'command_stack'}}, $macro);
17623 #print STDERR "# Stacked $macro (@{$state->{'command_stack'}})\n" if ($T2H_DEBUG);
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...
17633 if ($state->{'check_item'} and ($macro =~ /^itemx?$/ or $macro eq 'headitem'))
17635 echo_error("\@$macro on \@$state->{'check_item'} line", $line_nr);
17639 # if we're keeping texi unmodified we can do it now
17640 if ($state->{'keep_texi'})
17642 # We treat specially formats accepting {} on command line
17643 if ($macro eq 'multitable' or defined($Texi2HTML::Config::def_map{$macro}))
17645 add_prev($text, $stack, "\@$macro" . $_);
17649 # @ at the end of line may protect the end of line even when
17651 if ($macro eq "\n")
17653 $state->{'end_of_line_protected'} = 1;
17654 #print STDERR "PROTECTING END OF LINE\n";
17657 add_prev($text, $stack, "\@$macro");
17658 if ($text_macros{$macro} and $text_macros{$macro} eq 'raw')
17660 $state->{'raw'} = $macro;
17661 push (@$stack, {'style' => $macro, 'text' => ''});
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
17670 # a raw macro beginning
17671 if ($text_macros{$macro} and $text_macros{$macro} eq 'raw')
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);
17677 $state->{'raw'} = $macro;
17678 push (@$stack, {'style' => $macro, 'text' => ''});
17679 return if (/^\s*$/);
17682 my $simple_macro = 1;
17684 if (exists($Texi2HTML::Config::accent_map{$macro}))
17686 push (@{$state->{'command_stack'}}, $macro);
17689 add_prev($text, $stack, do_simple($macro, $1, $state, [ $1 ], $line_nr));
17692 { # The accent is at end of line
17693 add_prev($text, $stack, do_text($macro, $state));
17695 pop @{$state->{'command_stack'}};
17697 # an @-command which should be like @command{}. We handle it...
17698 elsif ($::things_map_ref->{$macro})
17700 echo_warn ("$macro requires {}", $line_nr);
17701 add_prev($text, $stack, do_simple($macro, '', $state));
17703 # an @-command like @command
17704 elsif (defined($::simple_map_ref->{$macro}))
17706 add_prev($text, $stack, do_simple($macro, '', $state));
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,$_));
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'})
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'))
17729 elsif ($macro eq 'enumerate')
17732 ($_, $spec) = parse_enumerate ($_);
17733 return if (/^\s*$/);
17736 elsif (defined($Texi2HTML::Config::def_map{$macro}))
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));
17748 add_prev($text, $stack, &$Texi2HTML::Config::def_line_no_texi($category, $name, $type, $arguments));
17752 # ignore other macros
17756 # handle the other macros, in the context of some normal text
17757 if (($macro =~ /^(\w+?)index$/) and ($1 ne 'print'))
17759 add_prev($text, $stack, do_index_entry_label($macro,$state,$line_nr));
17762 if ($macro eq 'insertcopying')
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'});
17770 if ($macro =~ /^itemx?$/o or ($macro eq 'headitem'))
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
17779 if ($format = add_item($text, $stack, $state, $line_nr, $_))
17782 elsif ($format = add_term($text, $stack, $state, $line_nr))
17783 {# handle table @item line
17785 elsif ($format = add_line($text, $stack, $state, $line_nr))
17786 {# handle table text
17790 if (defined($format->{'prepended'}))
17792 $_ = $format->{'prepended'} . ' ' . $_ if ($format->{'prepended'} ne '');
17794 if (defined($format->{'command'}))
17796 open_arg($format->{'command'},0, $state);
17800 $format = add_row ($text, $stack, $state, $line_nr); # handle multitable
17803 echo_warn ("\@$macro outside of table or list", $line_nr);
17806 push @$stack, {'format' => 'row', 'text' => '', 'item_cmd' => $macro };
17807 if ($format->{'max_columns'})
17809 push @$stack, {'format' => 'cell', 'text' => ''};
17810 $format->{'cell'} = 1;
17812 begin_paragraph_after_command($state,$stack,$macro,$_);
17816 echo_warn ("\@$macro in empty multitable", $line_nr);
17820 if ($macro eq 'tab')
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";
17829 echo_warn ("\@$macro outside of multitable", $line_nr);
17831 elsif (!$format->{'max_columns'})
17833 echo_warn ("\@$macro in empty multitable", $line_nr);
17834 push @$stack, {'format' => 'null', 'text' => ''};
17837 elsif ($format->{'cell'} > $format->{'max_columns'})
17839 echo_warn ("too much \@$macro (multitable has only $format->{'max_columns'} column(s))", $line_nr);
17840 push @$stack, {'format' => 'null', 'text' => ''};
17845 push @$stack, {'format' => 'cell', 'text' => ''};
17847 begin_paragraph_after_command($state,$stack,$macro,$_);
17850 # Macro opening a format (table, list, deff, example...)
17851 if ($format_type{$macro} and ($format_type{$macro} ne 'fake'))
17853 unless ($Texi2HTML::Config::format_in_paragraph{$macro})
17855 close_paragraph($text, $stack, $state, $line_nr);
17857 push (@{$state->{'command_stack'}}, $macro);
17858 if ($format_type{$macro} eq 'menu')
17860 close_menu($text, $stack, $state, $line_nr);
17861 $state->{'menu'}++;
17863 # A deff like macro
17864 if (defined($Texi2HTML::Config::def_map{$macro}))
17866 my $top_format = top_format($stack);
17867 if (defined($top_format) and ("$top_format->{'format'}x" eq $macro))
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'}};
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'}));
17879 #print STDERR "DEFx $macro\n";
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'});
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' => '' };
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 $_";
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);
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})
17927 begin_paragraph($stack, $state);
17930 elsif ($Texi2HTML::Config::paragraph_style{$macro})
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')
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'
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
17953 elsif ($format_type{$macro} eq 'menu')
17955 # if $Texi2HTML::Config::SIMPLE_MENU we won't get there
17956 # as the menu is a complex format in that case, so it
17958 push @$stack, { 'format' => $macro, 'text' => '' };
17959 if ($state->{'preformatted'})
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' };
17967 elsif (($format_type{$macro} eq 'list') or ($format_type{$macro} eq 'table'))
17970 #print STDERR "LIST_TABLE $macro\n";
17971 #dump_stack($text, $stack, $state);
17972 if (($macro eq 'itemize') or ($macro =~ /^(|v|f)table$/))
17976 ($prepended, $command) = parse_format_command($_,$macro);
17977 $format = { 'format' => $macro, 'text' => '', 'command' => $command, 'prepended' => $prepended, 'term' => 0 };
17980 elsif ($macro eq 'enumerate')
17983 ($_, $spec) = parse_enumerate ($_);
17984 $spec = 1 if (!defined($spec));
17985 $format = { 'format' => $macro, 'text' => '', 'spec' => $spec, 'item_nr' => 0 };
17987 elsif ($macro eq 'multitable')
17989 my $max_columns = parse_multitable ($_, $line_nr);
17992 echo_warn ("empty multitable", $line_nr);
17995 $format = { 'format' => $macro, 'text' => '', 'max_columns' => $max_columns, 'cell' => 1 };
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$/)
18003 push @$stack, { 'format' => 'line', 'text' => ''};
18005 elsif ($macro eq 'multitable')
18007 if ($format->{'max_columns'})
18009 push @$stack, { 'format' => 'row', 'text' => '', 'item_cmd' => $macro };
18010 push @$stack, { 'format' => 'cell', 'text' => ''};
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' => ''};
18020 if ($format_type{$macro} eq 'list')
18022 push @$stack, { 'format' => 'item', 'text' => ''};
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');
18028 elsif ($macro eq 'float' or $macro eq 'quotation')
18030 push @$stack, {'format' => $macro, 'text' => '' };
18031 if ($macro eq 'float')
18033 open_cmd_line($stack, $state, ['keep','keep'], \&do_float_line);
18035 elsif ($macro eq 'quotation')
18037 open_cmd_line($stack, $state, ['keep'], \&do_quotation_line);
18039 #dump_stack($text, $stack, $state);
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'))
18046 push @$stack, { 'format' => $macro, 'text' => '' };
18047 begin_paragraph_after_command($state,$stack,$macro,$_);
18049 return if (/^\s*$/);
18052 $_ = do_unknown ($macro, $_, $text, $stack, $state, $line_nr);
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);
18061 elsif (s/^([^{},]*)([{}])//o or (@$stack and
18062 defined($stack->[-1]->{'style'}) and
18063 ($stack->[-1]->{'style'} eq 'cmd_line') and /^([^{},]*)$/o))
18065 my $leading_text = $1;
18067 add_prev($text, $stack, do_text($leading_text, $state));
18068 if (defined($brace) and ($brace eq '{'))
18070 add_prev($text, $stack, do_text('{',$state));
18071 unless ($state->{'keep_texi'} or $state->{'remove_texi'})
18073 echo_error ("'{' without macro. Before: $_", $line_nr);
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')))
18082 if ($state->{'keep_texi'})
18084 add_prev($text, $stack, '}');
18088 echo_error("'}' without opening '{' before: $_", $line_nr);
18092 { # A @-command{ ...} is closed
18093 my $style = pop @$stack;
18094 my $command = $style->{'style'};
18096 if (ref($::style_map_ref->{$command}) eq 'HASH')
18098 push (@{$style->{'args'}}, $style->{'text'});
18099 $style->{'fulltext'} .= $style->{'text'};
18101 #foreach my $arg(@{$style->{'args'}})
18103 #print STDERR " $number: $arg\n";
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));
18111 $state->{'no_paragraph'}-- if ($no_paragraph_macro{$command});
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')))
18117 my $style_command = pop @{$state->{'command_stack'}};
18118 if ($style_command ne $command)
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);
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'} . '}';
18135 $result = do_simple($command, $style->{'text'}, $state, $style->{'args'}, $line_nr, $style->{'no_open'}, $style->{'no_close'});
18136 if ($state->{'code_style'} < 0)
18138 echo_error ("Bug: negative code_style: $state->{'code_style'}, line:$_", $line_nr);
18144 print STDERR "Bug: empty style in pass_text\n";
18146 add_prev($text, $stack, $result);
18147 if ($command eq 'cmd_line')
18149 if ($state->{'deff_line'})
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'};
18160 $arguments = substitute_line($state->{'deff_line'}->{'arguments'}) if (defined($state->{'deff_line'}->{'arguments'}));
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));
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);
18172 $state->{'no_paragraph'}--;
18177 elsif (s/^([^,]*)[,]//o)
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'))
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]))
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);
18196 add_prev($text, $stack, do_text(',', $state));
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);
18204 # @item line is closed by end of line
18205 add_term($text, $stack, $state, $line_nr);
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).
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'})
18217 $state->{'closing_center'} = 1;
18218 unless ($Texi2HTML::Config::format_in_paragraph{'center'})
18220 close_paragraph($text, $stack, $state, $line_nr);
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');
18244 my $arg_nr = shift;
18246 if (ref($::style_map_ref->{$macro}) eq 'HASH')
18248 my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
18249 if ($arg eq 'code' and !$state->{'keep_texi'})
18251 $state->{'code_style'}++;
18253 elsif ($arg eq 'keep')
18255 $state->{'keep_nr'}++;
18256 $state->{'keep_texi'} = 1;
18259 elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
18261 $state->{'code_style'}++;
18268 my $arg_nr = shift;
18270 if (ref($::style_map_ref->{$macro}) eq 'HASH')
18272 my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr];
18273 if ($arg eq 'code' and !$state->{'keep_texi'})
18275 $state->{'code_style'}--;
18277 elsif ($arg eq 'keep')
18279 $state->{'keep_nr'}--;
18280 $state->{'keep_texi'} = 0 if ($state->{'keep_nr'} == 0);
18282 #print STDERR "c $arg_nr $macro $arg $state->{'code_style'}\n";
18284 elsif ($code_style_map{$macro} and !$state->{'keep_texi'})
18286 $state->{'code_style'}--;
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($$$$)
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)
18301 $hash->{'cmd_line'}->{'args'} = $args;
18302 $hash->{'cmd_line'}->{'function'} = $function;
18304 $state->{'no_paragraph'}++;
18305 open_arg ('cmd_line', 0, $state);
18308 # finish @item line in @*table
18309 sub add_term($$$$;$)
18314 my $line_nr = 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;
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'))
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;
18343 elsif (exists($::things_map_ref->{$format->{'command'}}))
18345 $command_formatted = do_simple($format->{'command'}, '', $state);
18348 if ($format->{'format'} =~ /^(f|v)/o)
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);
18353 add_prev($text, $stack, &$Texi2HTML::Config::table_item($term->{'text'}, $index_label,$format->{'format'},$format->{'command'}, $command_formatted,$state->{'command_stack'}));
18356 push (@$stack, { 'format' => 'line', 'text' => '' });
18357 begin_paragraph($stack, $state) if ($state->{'preformatted'});
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'})
18372 close_stack($text, $stack, $state, $line_nr, undef, 'null');
18375 unless ($format->{'max_columns'})
18376 { # empty multitable
18377 pop @$stack; # pop 'row'
18380 if ($format->{'first'})
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))
18393 add_cell($text, $stack, $state);
18394 my $row = pop @$stack;
18395 add_prev($text, $stack, &$Texi2HTML::Config::row($row->{'text'}, $row->{'item_cmd'}));
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'})
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'}++;
18419 sub add_line($$$$;$)
18424 my $line_nr = 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;
18437 $first = 1 if ($format->{'first'});
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);
18448 add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}));
18452 push (@$stack, { 'format' => 'term', 'text' => '' });
18454 $format->{'term'} = 1;
18458 # finish @enumerate or @itemize @item
18459 sub add_item($$$$;$)
18464 my $line_nr = 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')
18477 $format->{'number'} = '';
18478 my $spec = $format->{'spec'};
18479 $format->{'item_nr'}++;
18480 if ($spec =~ /^[0-9]$/)
18482 $format->{'number'} = $spec + $format->{'item_nr'} - 1;
18486 my $base_letter = ord('a');
18487 $base_letter = ord('A') if (ucfirst($spec) eq $spec);
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'};
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.
18503 # don't do an item if it is the first and it is empty
18504 if (!$format->{'first'} or ($item->{'text'} =~ /\S/o))
18506 my $formatted_command;
18507 if (defined($format->{'command'}) and exists($::things_map_ref->{$format->{'command'}}))
18509 $formatted_command = do_simple($format->{'command'}, '', $state);
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'}));
18514 if ($format->{'first'})
18516 $format->{'first'} = 0;
18519 # Now prepare the new item
18522 push (@$stack, { 'format' => 'item', 'text' => '' });
18523 begin_paragraph($stack, $state) unless (!$state->{'preformatted'} and no_line($line));
18528 # format ``simple'' macros, that is macros without arg or style macros
18529 sub do_simple($$$;$$$$)
18535 my $line_nr = shift;
18536 my $no_open = shift;
18537 my $no_close = shift;
18540 $arg_nr = @$args - 1 if (defined($args));
18542 #print STDERR "DO_SIMPLE $macro $arg_nr $args @$args\n" if (defined($args));
18543 if (defined($::simple_map_ref->{$macro}))
18545 # \n may in certain circumstances, protect end of lines
18546 if ($macro eq "\n")
18548 $state->{'end_of_line_protected'} = 1;
18549 #print STDERR "PROTECTING END OF LINE\n";
18551 if ($state->{'keep_texi'})
18555 elsif ($state->{'remove_texi'})
18557 #print STDERR "DO_SIMPLE remove_texi $macro\n";
18558 return $::simple_map_texi_ref->{$macro};
18560 elsif ($state->{'preformatted'})
18562 return $::simple_map_pre_ref->{$macro};
18566 return $::simple_map_ref->{$macro};
18569 if (defined($::things_map_ref->{$macro}))
18572 if ($state->{'keep_texi'})
18574 $result = "\@$macro" . '{}';
18576 elsif ($state->{'remove_texi'})
18578 $result = $::texi_map_ref->{$macro};
18579 #print STDERR "DO_SIMPLE remove_texi texi_map $macro\n";
18581 elsif ($state->{'preformatted'})
18583 $result = $::pre_map_ref->{$macro};
18587 $result = $::things_map_ref->{$macro};
18589 return $result . $text;
18591 elsif (defined($::style_map_ref->{$macro}))
18593 if ($state->{'keep_texi'})
18595 return "\@$macro" . '{' . $text . '}';
18601 if ($state->{'remove_texi'})
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};
18606 elsif ($state->{'preformatted'})
18608 $style = $::style_map_pre_ref->{$macro};
18612 $style = $::style_map_ref->{$macro};
18614 if (defined($style))
18616 $result = &$Texi2HTML::Config::style($style, $macro, $text, $args, $no_close, $no_open, $line_nr, $state, $state->{'command_stack'});
18620 close_arg($macro,$arg_nr, $state);
18625 elsif ($macro =~ /^special_(\w+)_(\d+)$/o)
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 . '}';
18634 if (defined($Texi2HTML::Config::command_handler{$style}) and
18635 defined($Texi2HTML::Config::command_handler{$style}->{'expand'}))
18637 my $struct_count = 1+ $special_commands{$style}->{'max'} - $special_commands{$style}->{'count'};
18638 if (($count != $struct_count) and $T2H_DEBUG)
18640 print STDERR "count $count in \@special $style and structure $struct_count differ\n";
18642 $special_commands{$style}->{'count'}--;
18644 my $result = $Texi2HTML::Config::command_handler{$style}->{'expand'}
18645 ($style,$count,$state,$text);
18646 $result = '' if (!defined($result));
18651 my ($done, $result_text, $message) = &$Texi2HTML::Config::unknown_style($macro, $text,$state);
18654 echo_warn($message, $line_nr) if (defined($message));
18655 if (defined($result_text))
18657 $result = $result_text;
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") . "{";
18669 $result .= '}' unless ($no_close);
18674 sub do_unknown($$$$$$)
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);
18686 add_prev ($text, $stack, $result_text) if (defined($result_text));
18687 echo_warn($message, $line_nr) if (defined($message));
18688 return $result_line;
18692 echo_warn ("Unknown command `\@$macro' (left as is)", $line_nr);
18693 add_prev ($text, $stack, do_text("\@$macro"));
18698 # used only during @macro processing
18701 my $string = shift;
18703 return if (!defined($string));
18704 foreach my $scalar_ref (@_)
18706 next unless defined($scalar_ref);
18707 if (!defined($$scalar_ref))
18709 $$scalar_ref = $string;
18713 $$scalar_ref .= $string;
18723 my $string = shift;
18725 unless (defined($text) and ref($text) eq "SCALAR")
18727 die "text not a SCALAR ref: " . ref($text) . "";
18729 #if (!defined($stack) or (ref($stack) ne "ARRAY"))
18731 # $string = $stack;
18735 return if (!defined($string));
18738 $stack->[-1]->{'text'} .= $string;
18742 if (!defined($$text))
18752 sub close_stack_texi_structure($$$$)
18757 my $line_nr = shift;
18759 return undef unless (@$stack or $state->{'raw'} or $state->{'macro'} or $state->{'macro_name'} or $state->{'ignored'});
18761 #print STDERR "close_stack_texi_structure\n";
18762 #dump_stack ($text, $stack, $state);
18763 my $stack_level = $#$stack + 1;
18766 if ($state->{'ignored'})
18768 $string .= "\@end $state->{'ignored'} ";
18769 echo_warn ("closing $state->{'ignored'}", $line_nr);
18771 if ($state->{'texi'})
18773 if ($state->{'macro'})
18775 $string .= "\@end macro ";
18776 echo_warn ("closing macro", $line_nr);
18778 elsif ($state->{'macro_name'})
18780 $string .= ('}' x $state->{'macro_depth'}) . " ";
18781 echo_warn ("closing $state->{'macro_name'} ($state->{'macro_depth'} braces missing)", $line_nr);
18783 elsif ($state->{'verb'})
18785 echo_warn ("closing \@verb", $line_nr);
18786 $string .= $state->{'verb'} . '}';
18788 elsif ($state->{'raw'})
18790 echo_warn ("closing \@$state->{'raw'} raw format", $line_nr);
18791 $string .= "\@end $state->{'raw'} ";
18795 #print STDERR "close_stack scan_texi ($string)\n";
18796 scan_texi ($string, $text, $stack, $state, $line_nr);
18800 elsif ($state->{'verb'})
18802 $string .= $state->{'verb'};
18805 while ($stack_level--)
18807 my $stack_text = $stack->[$stack_level]->{'text'};
18808 $stack_text = '' if (!defined($stack_text));
18809 if ($stack->[$stack_level]->{'format'})
18811 my $format = $stack->[$stack_level]->{'format'};
18812 if ($format eq 'index_item')
18814 enter_table_index_entry($text, $stack, $state, $line_nr);
18817 elsif (!defined($format_type{$format}) or ($format_type{$format} ne 'fake'))
18819 $stack_text = "\@$format\n" . $stack_text;
18822 elsif (defined($stack->[$stack_level]->{'style'}))
18824 if ($state->{'structure'})
18826 $stack_text = close_structure_command($stack->[$stack_level],
18831 my $style = $stack->[$stack_level]->{'style'};
18834 $stack_text = "\@$style\{" . $stack_text;
18837 {# this is a lone opened brace. We readd it there.
18838 $stack_text = "\{" . $stack_text;
18843 add_prev($text, $stack, $stack_text);
18847 $state->{'close_stack'} = 1;
18850 if ($state->{'texi'})
18852 #print STDERR "scan_texi in close_stack ($string)\n";
18853 scan_texi($string, $text, $stack, $state, $line_nr);
18855 elsif ($state->{'structure'})
18857 #print STDERR "scan_structure in close_stack ($string)\n";
18858 scan_structure($string, $text, $stack, $state, $line_nr);
18861 delete $state->{'close_stack'};
18864 # close region like @insertcopying, titlepage...
18865 # restore $state->{'after_element'} and delete the structure
18866 sub close_region($)
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'};
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
18886 # if a $format is given the stack is closed according to $close_paragraph but
18887 # if $format is encountered the closing stops
18889 sub close_stack($$$$;$$)
18894 my $line_nr = shift;
18895 my $close_paragraph = shift;
18896 my $format = shift;
18899 #print STDERR "sub_close_stack\n";
18900 return $new_stack unless (@$stack);
18902 my $stack_level = $#$stack + 1;
18906 if ($state->{'verb'})
18908 $string .= $state->{'verb'};
18909 $verb = $state->{'verb'};
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";
18920 while ($stack_level--)
18922 if ($stack->[$stack_level]->{'format'})
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')
18929 $string .= "\@end_paragraph{}";
18931 elsif ($stack_format eq 'preformatted')
18933 $string .= "\@end_preformatted{}";
18937 if ($fake_format{$stack_format})
18939 warn "# Closing a fake format `$stack_format'\n" if ($T2H_VERBOSE);
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);
18946 $string .= "\@end $stack_format ";
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})))
18963 push @$new_stack, { 'style' => $style, 'text' => '', 'no_open' => 1, 'arg_nr' => 0 };
18966 elsif (($style_type{$style} eq 'simple_style') or ($style_type{$style} eq 'accent'))
18972 print STDERR "$style while closing paragraph\n";
18977 dump_stack ($text, $stack, $state) if (!defined($style)); # bug
18979 echo_warn ("closing \@-command $style", $line_nr) if ($style);
18983 $state->{'no_close'} = 1 if ($close_paragraph);
18984 $state->{'close_stack'} = 1;
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);
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))
18998 $state->{'paragraph_style'} = [ '' ];
18999 $state->{'command_stack'} = [ '' ];
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($@)
19009 my $stack_level = $#$stack + 1;
19012 my $format = shift;
19013 while ($stack_level--)
19015 if ($stack->[$stack_level]->{'format'})
19017 if ($stack->[$stack_level]->{'format'} eq $format)
19028 return 0 if ($format);
19036 my $stack_level = $#$stack + 1;
19037 while ($stack_level--)
19039 if ($stack->[$stack_level]->{'format'} and !$fake_format{$stack->[$stack_level]->{'format'}})
19041 return $stack->[$stack_level];
19047 sub close_paragraph($$$;$)
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'}))
19060 print STDERR "Bug: no format on top stack\n";
19061 dump_stack($text, $stack, $state);
19063 if ($top_stack and ($top_stack->{'format'} eq 'paragraph'))
19065 my $paragraph = pop @$stack;
19066 add_prev($text, $stack, do_paragraph($paragraph->{'text'}, $state));
19067 $state->{'paragraph_macros'} = $new_stack;
19070 elsif ($top_stack and ($top_stack->{'format'} eq 'preformatted'))
19072 my $paragraph = pop @$stack;
19073 add_prev($text, $stack, do_preformatted($paragraph->{'text'}, $state));
19074 $state->{'paragraph_macros'} = $new_stack;
19080 sub abort_empty_preformatted($$)
19084 if (@$stack and $stack->[-1]->{'format'}
19085 and ($stack->[-1]->{'format'} eq 'preformatted')
19086 and ($stack->[-1]->{'text'} !~ /\S/))
19093 sub dump_stack($$$)
19099 if (defined($$text))
19101 print STDERR "text: $$text\n";
19105 print STDERR "text: UNDEF\n";
19108 my $in_simple_format = 0;
19110 $in_keep = 1 if ($state->{'keep_texi'});
19113 $in_simple_format = 1 if ($state->{'simple_format'});
19114 $in_remove = 1 if ($state->{'remove_texi'} and !$in_simple_format);
19116 print STDERR "state(k${in_keep}s${in_simple_format}r${in_remove}): ";
19117 foreach my $key (keys(%$state))
19119 my $value = 'UNDEF';
19120 $value = $state->{$key} if (defined($state->{$key}));
19121 print STDERR "$key: $value " if (!ref($value));
19124 my $stack_level = $#$stack + 1;
19125 while ($stack_level--)
19127 print STDERR " $stack_level-> ";
19128 foreach my $key (keys(%{$stack->[$stack_level]}))
19130 my $value = 'UNDEF';
19131 $value = $stack->[$stack_level]->{$key} if
19132 (defined($stack->[$stack_level]->{$key}));
19133 print STDERR "$key: $value ";
19137 if (defined($state->{'table_list_stack'}))
19139 print STDERR "table_list_stack: ";
19140 foreach my $format (@{$state->{'table_list_stack'}})
19142 print STDERR "$format->{'format'} ";
19146 if (defined($state->{'command_stack'}))
19148 print STDERR "command_stack: ";
19149 foreach my $style (@{$state->{'command_stack'}})
19151 print STDERR "($style) ";
19155 if (defined($state->{'region_lines'}))
19157 print STDERR "region_lines($state->{'region_lines'}->{'number'}): $state->{'region_lines'}->{'format'}\n";
19159 if (defined($state->{'text_macro_stack'}) and @{$state->{'text_macro_stack'}})
19161 print STDERR "text_macro_stack: (@{$state->{'text_macro_stack'}})\n";
19166 sub print_elements($)
19168 my $elements = shift;
19169 foreach my $elem(@$elements)
19171 if ($elem->{'node'})
19173 print STDERR "node-> $elem ";
19177 print STDERR "chap=> $elem ";
19179 foreach my $key (keys(%$elem))
19181 my $value = "UNDEF";
19182 $value = $elem->{$key} if (defined($elem->{$key}));
19183 print STDERR "$key: $value ";
19189 sub substitute_line($;$)
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);
19200 sub substitute_text($@)
19206 if ($state->{'structure'})
19208 initialise_state_structure($state);
19210 elsif ($state->{'texi'})
19212 initialise_state_texi($state);
19216 initialise_state($state);
19218 $state->{'spool'} = [];
19219 #print STDERR "SUBST_TEXT begin\n";
19221 while (@_ or @{$state->{'spool'}})
19224 if (@{$state->{'spool'}})
19226 $line = shift @{$state->{'spool'}};
19232 next unless (defined($line));
19233 if ($state->{'structure'})
19235 scan_structure ($line, \$text, \@stack, $state);
19237 elsif ($state->{'texi'})
19239 scan_texi ($line, \$text, \@stack, $state);
19243 scan_line($line, \$text, \@stack, $state);
19249 # FIXME could we have the line number ?
19250 # close stack in substitute_text
19251 if ($state->{'texi'} or $state->{'structure'})
19253 close_stack_texi_structure(\$text, \@stack, $state, undef);
19257 close_stack(\$text, \@stack, $state, undef);
19259 #print STDERR "SUBST_TEXT end\n";
19260 return $result . $text;
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($)
19268 return $text if $text =~ /^\s*$/;
19269 #print STDERR "substitute_texi_line $text\n";
19270 my @text = substitute_text({'structure' => 1}, $text);
19274 push @result, split (/\n/, shift (@text));
19276 return '' unless (@result);
19277 my $result = shift @result;
19278 return $result . "\n" unless (@result);
19279 foreach my $line (@result)
19282 $result .= ' ' . $line;
19284 return $result . "\n";
19287 sub print_lines($;$)
19289 my ($fh, $lines) = @_;
19290 $lines = $Texi2HTML::THIS_SECTION unless $lines;
19293 for my $line (@$lines)
19296 if (defined($Texi2HTML::Config::WORDS_IN_PAGE) and ($Texi2HTML::Config::SPLIT eq 'node'))
19298 @cnt = split(/\W*\s+\W*/, $line);
19299 $cnt += scalar(@cnt);
19305 sub do_index_entry_label($$$)
19307 my $command = shift;
19309 my $line_nr = shift;
19310 return '' if ($state->{'multiple_pass'});
19311 my $entry = shift @index_labels;
19312 if (!defined($entry))
19314 echo_warn ("Not enough index entries !", $line_nr);
19317 if ($command ne $entry->{'command'})
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);
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},
19331 # decompose a decimal number on a given base. The algorithm looks like
19332 # the division with growing powers (division suivant les puissances
19336 my $number = shift;
19340 return (0) if ($number == 0);
19342 my $remaining = $number;
19346 my $factor = $remaining % ($base ** $power);
19347 $remaining -= $factor;
19348 push (@result, $factor / ($base ** ($power - 1)));
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');
19359 if ($Texi2HTML::Config::TEST)
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" );
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;
19377 open_file($docu, $texi_line_number);
19378 #Texi2HTML::LaTeX2HTML::init() if ($Texi2HTML::Config::L2H);
19379 if ($Texi2HTML::Config::L2H)
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
19388 $Texi2HTML::Config::command_handler{'tex'} =
19389 { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex,
19390 'expand' => \&Texi2HTML::LaTeX2HTML::do_tex
19393 foreach my $handler(@Texi2HTML::Config::command_handler_init)
19398 my @css_import_lines;
19399 my @css_rule_lines;
19401 # process css files
19402 foreach my $file (@Texi2HTML::Config::CSS_FILES)
19408 $css_file_fh = \*STDIN;
19413 $css_file = locate_init_file ($file);
19414 unless (defined($css_file))
19416 warn "css file $file not found\n";
19419 unless (open (CSSFILE, "$css_file"))
19421 warn "Cannot open ${css_file}: $!";
19424 $css_file_fh = \*CSSFILE;
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;
19432 $Texi2HTML::THISDOC{'css_import_lines'} = \@css_import_lines;
19433 $Texi2HTML::THISDOC{'css_lines'} = \@css_rule_lines;
19435 if ($T2H_DEBUG & $DEBUG_USER)
19437 if (@css_import_lines)
19439 print STDERR "# css import lines\n";
19440 foreach my $line (@css_import_lines)
19442 print STDERR "$line";
19445 if (@css_rule_lines)
19447 print STDERR "# css rule lines\n";
19448 foreach my $line (@css_rule_lines)
19450 print STDERR "$line";
19456 dump_texi(\@lines, 'texi', \@lines_numbers) if ($T2H_DEBUG & $DEBUG_TEXI);
19457 if (defined($Texi2HTML::Config::MACRO_EXPAND))
19459 my @texi_lines = (@first_lines, @lines);
19460 dump_texi(\@texi_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND);
19463 if ($T2H_DEBUG & $DEBUG_TEXI)
19465 dump_texi(\@doc_lines, 'first', \@doc_numbers);
19466 if (defined($Texi2HTML::Config::MACRO_EXPAND and $Texi2HTML::Config::DUMP_TEXI))
19468 unshift (@doc_lines, @first_lines);
19469 push (@doc_lines, "\@bye\n");
19470 dump_texi(\@doc_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND . ".first");
19473 exit(0) if ($Texi2HTML::Config::DUMP_TEXI or defined($Texi2HTML::Config::MACRO_EXPAND));
19475 foreach my $style (keys(%special_commands))
19477 $special_commands{$style}->{'max'} = $special_commands{$style}->{'count'};
19480 rearrange_elements();
19483 #Texi2HTML::LaTeX2HTML::latex2html();
19484 foreach my $handler(@Texi2HTML::Config::command_handler_process)
19489 if (@{$region_lines{'documentdescription'}} and (!defined($Texi2HTML::Config::DOCUMENT_DESCRIPTION)))
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)
19498 $Texi2HTML::Config::DOCUMENT_DESCRIPTION .= ' ' . $line;
19501 # do copyright notice inserted in comment at the beginning of the files
19502 if (@{$region_lines{'copying'}})
19504 $copying_comment = &$Texi2HTML::Config::copying_comment($region_lines{'copying'});
19506 &$Texi2HTML::Config::toc_body(\@elements_list);
19510 &$Texi2HTML::Config::css_lines(\@css_import_lines, \@css_rule_lines);
19513 print STDERR "BUG: " . scalar(@index_labels) . " index entries pending\n"
19514 if (scalar(@index_labels));
19515 foreach my $special (keys(%special_commands))
19517 my $count = $special_commands{$special}->{'count'};
19518 if (($count != 0) and $T2H_VERBOSE)
19520 echo_warn ("$count special \@$special were not processed.\n");
19523 if ($Texi2HTML::Config::IDX_SUMMARY)
19525 foreach my $entry (keys(%index_names))
19527 do_index_summary_file($entry) unless ($empty_indices{$entry});
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)
19538 &$Texi2HTML::Config::finish_out();
19539 print STDERR "# that's all folks\n" if $T2H_VERBOSE;
19544 ##############################################################################
19546 # These next few lines are legal in both Perl and nroff.
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