#! /usr/local/bin/perl -- # perl 'di '; 'ig 00 '; # texi2html: generated by addformats.sh from texi2html.temp and formats/html.init formats/info.init formats/docbook.init formats/xml.init formats/plaintext.init # texi2html.temp: generated by buildt2h.sh from texi2html_configured.pl and MySimple.pm T2h_i18n.pm texi2html.init translations.pl examples/l2h.init T2h_l2h.pm documentlanguages.pl #+############################################################################## # # texi2html: Program to transform Texinfo documents to HTML # # Copyright (C) 1999-2010 Patrice Dumas , # Derek Price , # Adrian Aichner , # & others. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # # Some error messages come from texinfo (makeinfo), so copyright holder # is the FSF or the individual who wrote them. All come from before the # switch of texinfo to GPLv3+. # #-############################################################################## # The man page for this program is included at the end of this file and can be # viewed using the command 'nroff -man texi2html'. # for POSIX::setlocale and File::Spec require 5.00405; # Perl pragma to restrict unsafe constructs use strict; # used in case of tests, to revert to "C" locale. use POSIX qw(setlocale LC_ALL LC_CTYPE); # used to obtain the name of the current working directory use Cwd; # Used to find the parent directory of this script. use File::Basename; # used to find a relative path back to the current working directory use File::Spec; # to determine the path separator and null file use Config; #use encoding::warnings; # for translations #use encoding 'utf8'; #use utf8; # # According to # larry.jones@sdrc.com (Larry Jones) # this pragma is not present in perl5.004_02: # # Perl pragma to control optional warnings # use warnings; # determine the path separators my $path_separator = $Config{'path_sep'}; $path_separator = ':' if (!defined($path_separator)); my $quoted_path_separator = quotemeta($path_separator); #++########################################################################## # # NOTE FOR DEBUGGING THIS SCRIPT: # You can run 'perl -x texi2html.pl' directly, provided you have the script # in the same directory with, or the environment variable T2H_HOME set to # the directory containing, the texi2html.init, T2h_i18n.pm, translations.pl, # l2h.init, & T2h_l2h.pm files. Ditto makeinfo.pl, if you make it a # symlink to texi2html.pl. # #--########################################################################## my $T2H_HOME = defined $ENV{T2H_HOME} ? $ENV{T2H_HOME} : dirname $0; if ($0 =~ /\.pl$/) { # Issue a warning in debugging mode if $T2H_HOME is set but isn't # accessible. if (!-e $T2H_HOME) { warn "T2H_HOME ($T2H_HOME) does not exist."; } elsif (!-d $T2H_HOME) { warn "T2H_HOME ($T2H_HOME) is not a directory."; } elsif (!-x $T2H_HOME) { warn "T2H_HOME ($T2H_HOME) is not accessible."; } } # CVS version: # $Id: texi2html.pl,v 1.393 2010/06/30 22:01:27 pertusus Exp $ # FIXME. Change for texinfo, and also simplify. # Homepage: my $T2H_HOMEPAGE = "http://www.nongnu.org/texi2html/"; # Authors (appears in comments): my $T2H_AUTHORS = < (original author) Karl Berry Olaf Bachmann and many others. Maintained by: Many creative people. Send bugs and suggestions to EOT # Version: set in configure.in my $THISVERSION = '5.0'; my $THISPROG = "texi2html $THISVERSION"; # program name and version #+++######################################################################## # # # Paths and file names # # # #---######################################################################## # set by configure, prefix for the sysconfdir and so on my $prefix = '/usr/local'; my $datarootdir;# = '${prefix}/share'; my $sysconfdir; my $pkgdatadir; my $datadir; # We need to eval as $prefix has to be expanded. However when we haven't # run configure @sysconfdir will be expanded as an array, thus we verify # whether configure was run or not if ('${prefix}/etc' ne '@' . 'sysconfdir@') { $sysconfdir = eval '"${prefix}/etc"'; } else { $sysconfdir = "/usr/local/etc"; } if ('${prefix}/share' ne '@' . 'datarootdir@') { $datarootdir = eval '"${prefix}/share"'; } else { $datarootdir = "/usr/local/share"; } if ('${datarootdir}' ne '@' . 'datadir@') { $pkgdatadir = eval '"${datarootdir}/texi2html"'; $datadir = eval '"${datarootdir}"'; } else { $pkgdatadir = "/usr/local/share/texi2html"; $datadir = "/usr/local/share"; } my $target_prefix = "t_h"; #+++######################################################################## # # # Constants # # # #---######################################################################## my $DEBUG_MENU = 1; my $DEBUG_INDEX = 2; my $DEBUG_TEXI = 4; my $DEBUG_MACROS = 8; my $DEBUG_FORMATS = 16; my $DEBUG_ELEMENTS = 32; my $DEBUG_USER = 64; my $DEBUG_L2H = 128; my $VARRE = '[\w\-]+'; # RE for a variable name my $MAX_LEVEL = 4; my $MIN_LEVEL = 1; #+++######################################################################## # # # Command name and default format # # # #---######################################################################## my $real_command_name = $0; $real_command_name =~ s/.*\///; $real_command_name =~ s/\.pl$//; my %command_format = ( 'texi2html' => 'html', 'makeinfo' => 'info', 'texi2any' => 'raw-text', ); # Config files my $i18n_dir = 'i18n'; # name of the directory containing the per language files my $conf_file_name = 'Config' ; my $texinfo_htmlxref = 'htmlxref.cnf'; # directories for texinfo configuration files my @texinfo_config_dirs = ('./.texinfo'); push @texinfo_config_dirs, "$ENV{'HOME'}/.texinfo" if (defined($ENV{'HOME'})); push @texinfo_config_dirs, "$sysconfdir/texinfo" if (defined($sysconfdir)); push @texinfo_config_dirs, "$datadir/texinfo" if (defined($datadir)); my @program_config_dirs; my @program_init_dirs; # program name dependent initializations: config directories and default # format. sub set_config_init_dirs_output($) { my $program_name = shift; if (!defined($command_format{$program_name})) { # user can make any link to set $0, or use --program with an unknown name. # In that case the default is to use texi2any $program_name = 'texi2any'; } my $default_output_format = $command_format{$program_name}; # directories for config files @program_config_dirs = ('./'); push @program_config_dirs, "$ENV{'HOME'}/.$program_name/" if (defined($ENV{'HOME'})); push @program_config_dirs, "$sysconfdir/$program_name/" if (defined($sysconfdir)); push @program_config_dirs, "$datadir/$program_name" if (defined($datadir)); # directories for init files @program_init_dirs = @program_config_dirs; # common directories for all command names foreach my $texinfo_config_dir (@texinfo_config_dirs) { push @program_init_dirs, "${texinfo_config_dir}/init/"; } $Texi2HTML::Config::DEFAULT_OUTPUT_FORMAT = $default_output_format; $Texi2HTML::Config::COMMAND_NAME = $program_name; Texi2HTML::Config::t2h_default_load_format($default_output_format, 0); } #+++########################################################################### # # # Initialization # # Some declarations, some functions that are GPL and therefore cannot be in # # texi2html.init, some functions that are not to be customized. # # Pasted content of File $(srcdir)/texi2html.init: Default initializations # # # #---########################################################################### { package Texi2HTML::Config; use Config; # customization options variables use vars qw( $DEBUG $PREFIX $VERBOSE $SUBDIR $IDX_SUMMARY $SPLIT $SPLIT_SIZE $SHORT_REF @EXPAND $TOP $DOCTYPE $FRAMESET_DOCTYPE $ERROR_LIMIT $CHECK $TEST $DUMP_TEXI $MACRO_EXPAND $CAPTION_STYLE $USE_ISO $TOP_FILE $TOC_FILE $FRAMES $SHOW_MENU $SHOW_TITLE $NUMBER_SECTIONS $NUMBER_FOOTNOTES $USE_NODES $USE_SECTIONS $USE_NODE_TARGET $USE_UNICODE $USE_UNIDECODE $TRANSLITERATE_FILE_NAMES $NODE_FILES $NODE_FILENAMES $NODE_NAME_IN_MENU $NODE_NAME_IN_INDEX $AVOID_MENU_REDUNDANCY $HEADERS $NO_WARN $FORCE $MONOLITHIC $SHORTEXTN $EXTENSION $OUT $NOVALIDATE $DEF_TABLE $DOCUMENTLANGUAGE $CONTENTS $SHORTCONTENTS $FOOTNOTESTYLE $FILLCOLUMN $SETCONTENTSAFTERTITLEPAGE $SETSHORTCONTENTSAFTERTITLEPAGE $KBDINPUTSTYLE $FRENCHSPACING $ALLOWCODEBREAKS $SETFILENAME $TOC_LINKS $L2H $L2H_L2H $L2H_SKIP $L2H_TMP $L2H_CLEAN $L2H_FILE $L2H_HTML_VERSION $EXTERNAL_DIR @INCLUDE_DIRS @PREPEND_DIRS @CONF_DIRS $IGNORE_PREAMBLE_TEXT @CSS_FILES @CSS_REFS $INLINE_CONTENTS $INLINE_INSERTCOPYING $PARAGRAPHINDENT $FIRSTPARAGRAPHINDENT $ENABLE_ENCODING $INTERNAL_LINKS $DEFAULT_OUTPUT_FORMAT $OUTPUT_FORMAT $COMMAND_NAME @COMMANDS ); # customization variables use vars qw( $ENCODING_NAME $DOCUMENT_ENCODING $OUT_ENCODING $IN_ENCODING $DEFAULT_ENCODING $MENU_PRE_STYLE $MENU_PRE_COMPLEX_FORMAT $EXAMPLE_INDENT_CELL $SMALL_EXAMPLE_INDENT_CELL $SMALL_FONT_SIZE $SMALL_RULE $DEFAULT_RULE $MIDDLE_RULE $BIG_RULE $TOP_HEADING $INDEX_CHAPTER $SPLIT_INDEX $USE_MENU_DIRECTIONS $USE_UP_FOR_ADJACENT_NODES $AFTER_BODY_OPEN $PRE_BODY_CLOSE $EXTRA_HEAD $VERTICAL_HEAD_NAVIGATION $WORDS_IN_PAGE $ICONS $UNNUMBERED_SYMBOL_IN_MENU $SIMPLE_MENU $MENU_SYMBOL $MENU_ENTRY_COLON $INDEX_ENTRY_COLON $USE_ACCESSKEY $USE_REL_REV $USE_LINKS $OPEN_QUOTE_SYMBOL $CLOSE_QUOTE_SYMBOL $NO_NUMBER_FOOTNOTE_SYMBOL $NO_BULLET_LIST_STYLE $NO_BULLET_LIST_ATTRIBUTE $NO_BULLET_LIST_CLASS $TOP_NODE_FILE $TOP_NODE_FILE_TARGET $TOP_NODE_UP $NODE_FILE_EXTENSION $STDIN_DOCU_NAME $STDOUT_DOCU_NAME $BEFORE_OVERVIEW $AFTER_OVERVIEW $BEFORE_TOC_LINES $AFTER_TOC_LINES $NEW_CROSSREF_STYLE $TOP_HEADING_AT_BEGINNING $USE_NUMERIC_ENTITY $USE_SETFILENAME $USE_SETFILENAME_EXTENSION $SEPARATE_DESCRIPTION $IGNORE_BEFORE_SETFILENAME $OVERVIEW_LINK_TO_TOC $COMPLETE_IMAGE_PATHS $DATE %ACTIVE_ICONS %NAVIGATION_TEXT %PASSIVE_ICONS %BUTTONS_NAME %BUTTONS_GOTO %BUTTONS_EXAMPLE %BUTTONS_ACCESSKEY %BUTTONS_REL %BUTTONS_TEXT @T2H_FORMAT_EXPAND @CHAPTER_BUTTONS @MISC_BUTTONS @SECTION_BUTTONS @SECTION_FOOTER_BUTTONS @NODE_FOOTER_BUTTONS @TOP_BUTTONS @LINKS_BUTTONS @IMAGE_EXTENSIONS @INPUT_FILE_SUFFIXES $ENABLE_ENCODING_USE_ENTITY $PROGRAM_NAME_IN_FOOTER $HEADER_IN_TABLE $DATE_IN_HEADER $COMPLEX_FORMAT_IN_TABLE $USE_TITLEPAGE_FOR_TITLE $INLINE_CSS_STYLE $NO_CSS $I18N_PERL_HASH $USE_NLS ); # customization variables which may be guessed in the script #our $ADDRESS; use vars qw( $BODYTEXT $CSS_LINES $DOCUMENT_DESCRIPTION $EXTERNAL_CROSSREF_SPLIT ); # I18n use vars qw( $I $LANGUAGES ); # customizable subroutines references use vars qw( $print_section $one_section $end_section $print_Top_header $print_Top_footer $print_Top $print_Toc $print_Overview $print_Footnotes $print_About $print_misc_header $print_misc_footer $print_misc $print_section_header $print_section_footer $print_chapter_header $print_chapter_footer $print_element_header $print_page_head $print_page_foot $print_head_navigation $print_foot_navigation $print_title $button_icon_img $button_formatting $print_navigation $about_body $print_frame $print_toc_frame $toc_body $contents $internal_links $shortcontents $titlepage $insertcopying $css_lines $print_redirection_page $translate_names $init_out $finish_out $node_file_name $element_file_name $node_target_name $element_target_name $placed_target_file_name $inline_contents $program_string $preserve_misc_command $misc_command_line $misc_command_line_texi $protect_text $anchor $anchor_label $element_label $misc_element_label $def_item $def $menu $menu_command $menu_link $menu_description $menu_comment $simple_menu_link $ref_beginning $info_ref $book_ref $external_href $external_ref $internal_ref $table_item $table_line $row $cell $list_item $comment $def_line $def_line_no_texi $heading_no_texi $raw $raw_no_texi $heading $element_heading $heading_text $heading_text_preformatted $paragraph $preformatted $empty_preformatted $foot_line_and_ref $foot_section $image $image_files $index_entry_label $index_entry $index_entry_command $index_letter $print_index $printindex $index_summary $summary_letter $complex_format $cartouche $sp $definition_category $definition_index_entry $table_list $copying_comment $documentdescription $index_summary_file_entry $index_summary_file_end $index_summary_file_begin $style $line_command $format $normal_text $empty_line $unknown $unknown_style $float $caption_shortcaption $caption_shortcaption_command $listoffloats $listoffloats_entry $listoffloats_caption $listoffloats_float_style $listoffloats_style $acronym_like $quotation $quotation_prepend_text $paragraph_style_command $heading_texi $index_element_heading_texi $format_list_item_texi $begin_format_texi $begin_style_texi $begin_paragraph_texi $tab_item_texi $footnote_texi $colon_command $simple_command $thing_command $begin_special_region $end_special_region $PRE_ABOUT $AFTER_ABOUT ); # hash which entries might be redefined by the user use vars qw( $complex_format_map %complex_format_map %accent_map %def_map %format_map %simple_map %simple_map_pre %simple_map_texi %simple_map_math %style_map %style_map_pre %style_map_math %style_map_texi %simple_format_simple_map_texi %simple_format_style_map_texi %simple_format_texi_map %line_command_map %command_type %paragraph_style %stop_paragraph_command %format_code_style %region_formats_kept %texi_formats_map %things_map %pre_map %math_map %texi_map %sorting_things_map %unicode_map %unicode_diacritical %transliterate_map %transliterate_accent_map %no_transliterate_map %ascii_character_map %default_simple_map %default_things_map %default_texi_map %default_style_map %default_style_map_pre %default_style_map_texi %default_simple_format_style_map_texi %numeric_entity_map %perl_charset_to_html %misc_pages_targets %misc_command %no_paragraph_commands %css_map %format_in_paragraph %special_list_commands %accent_letters %unicode_accents %special_accents %inter_item_commands $def_always_delimiters $def_in_type_delimiters $def_argument_separator_delimiters %colon_command_punctuation_characters $punctuation_characters $after_punctuation_characters @command_handler_setup @command_handler_init @command_handler_names @command_handler_process @command_handler_output @command_handler_finish %command_handler %special_style %null_device_file %language_codes %region_codes %deprecated_commands %output_format_names %canonical_texinfo_encodings @text_substitutions_normal @text_substitutions_texi @text_substitutions_simple_format @text_substitutions_pre %htmlxref_entries ); # deprecated use vars qw( $address %iso_symbols %simple_map_pre_math %simple_map_texi_math $ENCODING $CENTER_IMAGE $HREF_DIR_INSTEAD_FILE $EXPAND $USE_GLOSSARY $INVISIBLE_MARK ); # subject to change use vars qw( %makeinfo_encoding_to_map %makeinfo_unicode_to_eight_bit %eight_bit_to_unicode %t2h_encoding_aliases ); # FIXME i18n ? %output_format_names = ( 'info' => 'Info', 'html' => 'HTML', 'docbook' => 'Docbook XML', 'xml' => 'Texinfo XML', 'plaintext' => 'plain text', 'raw-text' => 'raw text', ); sub load($) { my $file = shift; # If required like other init files, the functions would be redefined # and the format dependent stuff wouldn't be loaded. Having the # formats loaded could be worked around, for example there could be # a variable that, and if the variable is defined a function reference # should be called right after the require. There is no real # workaround for having the function redefined, though. foreach my $output_format (keys(%output_format_names)) { if ($file =~ /\/$output_format\.init$/) { t2h_default_load_format($output_format, 1); return 1; } } eval { require($file) ;}; if ($@ ne '') { print STDERR "error loading $file: $@\n"; return 0; } return 1; } sub set_conf($$;$) { my $name = shift; my $value = shift; my $not_global = shift; unless ($not_global) { if (defined($value)) { $Texi2HTML::GLOBAL{$name} = $value; } else { delete $Texi2HTML::GLOBAL{$name}; } return 1; } return 0 if (defined($Texi2HTML::GLOBAL{$name})); if (defined($value)) { $Texi2HTML::THISDOC{$name} = $value; } else { delete $Texi2HTML::THISDOC{$name}; } return 1; } my %config_map = ( 'paragraphindent' => \$PARAGRAPHINDENT, 'firstparagraphindent' => \$FIRSTPARAGRAPHINDENT, 'footnotestyle' => \$FOOTNOTESTYLE, 'fillcolumn' => \$FILLCOLUMN, 'documentlanguage' => \$DOCUMENTLANGUAGE, 'novalidate' => \$NOVALIDATE, 'SPLIT' => \$SPLIT, 'SPLIT_SIZE' => \$SPLIT_SIZE, 'contents' => \$CONTENTS, 'shortcontents' => \$SHORTCONTENTS, 'doctype' => \$DOCTYPE, 'headers' => \$HEADERS, 'DOCUMENT_ENCODING' => \$DOCUMENT_ENCODING, 'IN_ENCODING' => \$IN_ENCODING, 'setcontentsaftertitlepage' => \$SETCONTENTSAFTERTITLEPAGE, 'setshortcontentsaftertitlepage' => \$SETSHORTCONTENTSAFTERTITLEPAGE, 'kbdinputstyle' => \$KBDINPUTSTYLE, 'frenchspacing' => \$FRENCHSPACING, 'allowcodebreaks' => \$ALLOWCODEBREAKS, 'setfilename' => \$SETFILENAME, 'use_nls' => \$USE_NLS, ); sub get_conf($) { my $name = shift; return $Texi2HTML::THISDOC{$name} if (defined($Texi2HTML::THISDOC{$name})); return $Texi2HTML::GLOBAL{$name} if (defined($Texi2HTML::GLOBAL{$name})); return ${$config_map{$name}} if (defined($config_map{$name})); # there is no default value for many @-commmands, like headings.... #print STDERR "Unknown conf string: $name\n"; } # manage expanded sections sub set_expansion($$) { my $region = shift; my $set = shift; $set = 1 if (!defined($set)); if ($set) { push (@EXPAND, $region) unless (grep {$_ eq $region} @EXPAND); } else { @EXPAND = grep {$_ ne $region} @EXPAND; @T2H_FORMAT_EXPAND = grep {$_ ne $region} @T2H_FORMAT_EXPAND; } } # needed in this namespace for translations $I = \&Texi2HTML::I18n::get_string; sub gdt($;$$) { return &main::gdt(@_); } sub __($) { return &main::__(@_); } sub __p($$) { return &main::__p(@_); } sub N__($) { return $_[0]; } # # Function refs covered by the GPL as part of the texi2html.pl original # code. As such they cannot appear in texi2html.init which is public # domain (at least the things coded by me, and, if I'm not wrong also the # things coded by Olaf -- Pat). # sub HTML_DEFAULT_shortcontents($$) { my $elements_list = shift; my $stoc_file = shift; return unless (Texi2HTML::Config::get_conf('shortcontents') or $FRAMES); my $ul_class = ''; $ul_class = $NO_BULLET_LIST_CLASS if ($NUMBER_SECTIONS); my @result = (); foreach my $element (@$elements_list) { next if ($element->{'tag'} eq 'top' or $element->{'toc_level'} != 1); my $dest_for_stoc = $element->{'file'}; my $dest_target_for_stoc = $element->{'target'}; if ($Texi2HTML::Config::OVERVIEW_LINK_TO_TOC) { $dest_for_stoc = $Texi2HTML::THISDOC{'toc_file'}; $dest_target_for_stoc = $element->{'tocid'}; } $dest_for_stoc = '' if ($dest_for_stoc eq $stoc_file); my $text = $element->{'text'}; my $stoc_entry = "
  • " . &$anchor ($element->{'stocid'}, "$dest_for_stoc#$dest_target_for_stoc",$text); push(@result, $stoc_entry. "
  • \n"); } if (@result) { unshift @result, html_default_attribute_class('ul', $ul_class) .">\n"; push @result, "\n"; unshift @result, $BEFORE_OVERVIEW; push @result, $AFTER_OVERVIEW; } return \@result; } sub HTML_DEFAULT_contents($$) { my $elements_list = shift; my $toc_file = shift; return unless (Texi2HTML::Config::get_conf('contents')); my $current_level = 0; my $ul_class = ''; $ul_class = $NO_BULLET_LIST_CLASS if ($NUMBER_SECTIONS); my @result = (); foreach my $element (@$elements_list) { next if ($element->{'tag'} eq 'top'); my $ind = ' ' x $current_level; my $level = $element->{'toc_level'}; print STDERR "Bug no toc_level for ($element) $element->{'texi'}\n" if (!defined ($level)); if ($level > $current_level) { while ($level > $current_level) { $current_level++; my $ln = "\n$ind".html_default_attribute_class('ul', $ul_class).">\n"; $ind = ' ' x $current_level; push(@result, $ln); } } elsif ($level < $current_level) { while ($level < $current_level) { $current_level--; $ind = ' ' x $current_level; my $line = "\n$ind"; $line .= "" if ($level == $current_level); push(@result, "$line\n"); } } else { push(@result, "\n"); } my $dest_for_toc = $element->{'file'}; my $dest_for_stoc = $element->{'file'}; my $dest_target_for_stoc = $element->{'target'}; $dest_for_toc = '' if ($dest_for_toc eq $toc_file); my $text = $element->{'text'}; my $toc_entry = "
  • " . &$anchor ($element->{'tocid'}, "$dest_for_toc#$element->{'target'}",$text); push (@result, $ind . $toc_entry); } while (0 < $current_level) { $current_level--; my $ind = ' ' x $current_level; push(@result, "
  • \n$ind\n"); } if (@result) { unshift @result, $BEFORE_TOC_LINES; push @result, $AFTER_TOC_LINES; } return \@result; } #$toc_body = \&T2H_GPL_toc_body; #$style = \&T2H_GPL_style; #$format = \&T2H_GPL_format; #$printindex = \&t2h_GPL_default_printindex; #$summary_letter = \&t2h_default_summary_letter; sub T2H_GPL_style($$$$$$$$$$) { # known style my $style = shift; my $command = shift; my $text = shift; my $args = shift; my $no_close = shift; my $no_open = shift; my $line_nr = shift; my $state = shift; my $style_stack = shift; my $kept_line_nrs = shift; my $do_quotes = 0; my $use_attribute = 0; my $use_begin_end = 0; my $inline_attribute = 0; if (ref($style) eq 'HASH') { #print STDERR "GPL_STYLE $command ($style)\n"; #print STDERR " @$args\n"; if (ref($style->{'args'}) ne 'ARRAY') { print STDERR "BUG: args not an array for command `$command'\n"; } $do_quotes = $style->{'quote'}; if (defined($style->{'function'})) { $text = &{$style->{'function'}}($command, $args, $style_stack, $state, $line_nr, $kept_line_nrs); } elsif (@{$style->{'args'}} == 1) { if (defined($style->{'inline_attribute'})) { $style = $style->{'inline_attribute'}; $use_attribute = 1; $inline_attribute = 1; } elsif (defined($style->{'attribute'})) { $style = $style->{'attribute'}; $use_attribute = 1; } #$text = $args->[0]; } } else { if ($style =~ s/^\"//) { # add quotes $do_quotes = 1; } if ($style =~ s/^\&//) { # custom $style = 'Texi2HTML::Config::' . $style; eval "\$text = &$style(\$text, \$command, \$style_stack)"; } elsif ($style ne '') { $use_attribute = 1; } else { # no style } } if ($use_attribute) { my ($attribute_text, $class); ($style, $class, $attribute_text) = html_default_parse_attribute ($style); $text = html_default_attribute_class($style, $class) . "$attribute_text>" . "$text" if (!$no_open or $inline_attribute); $text .= "" if (!$no_close or $inline_attribute); if ($do_quotes) { $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open); $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close); } } if (ref($style) eq 'HASH') { if (defined($style->{'begin'}) and !$no_open) { $text = $style->{'begin'} . $text; } if (defined($style->{'end'}) and !$no_close) { $text = $text . $style->{'end'}; } if (defined($style->{'inline_begin'})) { $text = $style->{'inline_begin'} . $text; } if (defined($style->{'inline_end'})) { $text = $text . $style->{'inline_end'}; } } if ($do_quotes and !$use_attribute) { $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open); $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close); } return $text; } sub T2H_GPL_format($$$) { my $tag = shift; my $element = shift; my $text = shift; return '' if (!defined($element) or ($text !~ /\S/)); return $text if ($element eq ''); my $attribute_text = ''; if ($element =~ /^(\w+)(\s+.*)/) { $element = $1; $attribute_text = $2; } return "<${element}$attribute_text>\n" . $text. "\n"; } # for each index holds the letters split as determined by SPLIT_INDEX. my %t2h_default_index_letters_array; # equivalent of doc_nr, but with files (and hence numbers) added when # a split index leads to an additional element and a file is created. my $t2h_default_file_number; # this is an increasing number to construct the id for each newly # created index element. my $t2h_default_index_id_nr; # this holds the file name associated with an element file, such # as to follow the splitting coming from the main program, and also use # the newly generated files. my %t2h_default_seen_files; # holds the elements and indices that are split to easily set the # directions after they are done in the main program. my $t2h_default_element_split_printindices; # construct a hash of index names holding the letter grouped how they will # be split. sub t2h_default_init_split_indices() { push @command_handler_process, \&t2h_default_index_rearrange_directions; %t2h_default_index_letters_array = (); %t2h_default_seen_files = (); $t2h_default_element_split_printindices = undef; $t2h_default_index_id_nr = 0; $t2h_default_file_number = 0; foreach my $index_name(keys %{$Texi2HTML::THISDOC{'index_letters_array'}}) { my $entries_count = 0; my @letters = (); foreach my $letter_entry (@{$Texi2HTML::THISDOC{'index_letters_array'}->{$index_name}}) { push @letters, $letter_entry; $entries_count += scalar(@{$letter_entry->{'entries'}}); # Don't split if document is not split if (get_conf('SPLIT') and $SPLIT_INDEX and $entries_count >= $SPLIT_INDEX) { push @{$t2h_default_index_letters_array{$index_name}}, [ @letters ]; @letters = (); $entries_count = 0; } } push @{$t2h_default_index_letters_array{$index_name}}, [ @letters ] if (scalar(@letters)); } } sub t2h_default_associate_index_element($$$$) { my $element = shift; my $is_top = shift; my $docu_name = shift; my $use_node_file = shift; my $default_element_file = $element->{'file'}; # redo the file naming -- the doc_nr part -- in case new elements were # inserted upon index split. But respect the default splitting to keep # the elements that are associated with the same file in the same file, # or the added file. if (!$use_node_file or $t2h_default_seen_files{$default_element_file}) { my $file; if ($t2h_default_seen_files{$default_element_file}) { $file = $t2h_default_seen_files{$default_element_file}; } else { if ($is_top eq 'top') { # this is the element_top, so we keep docu_top as associated file. # this, in fact, is not necessary since the element_top is never # associated with another element, but who knows. $t2h_default_seen_files{$default_element_file} = $default_element_file; } else { $file = "${docu_name}_$t2h_default_file_number"; $file .= '.' . $Texi2HTML::THISDOC{'extension'} if (defined($Texi2HTML::THISDOC{'extension'})); $t2h_default_seen_files{$default_element_file} = $file; } $t2h_default_file_number++; } $element->{'file'} = $file if (defined($file)); } my $level = $element->{'level'}; # Even if, without USE_SECTION, output can be split at chapter or # section we don't split indices accordingly. We don't want to add # more cases where users want split indices, this was a very difficult # to maintain feature from the beginning. #$level = $element->{'with_section'}->{'level'} if (!defined($level) and # defined($element->{'with_section'})); # if the element is not the level of splitting, then we don't split. # also if 'top' is set we don't split since the formatting is different # in that case and the result would be quite unpredictable. return if ($element->{'top'} or ((get_conf('SPLIT') ne 'node') and (!defined($level) or $level > $Texi2HTML::THISDOC{'split_level'}))); #print STDERR "Doing printindices for $element $element->{'texi'}, file $element->{'file'} (@{$element->{'place'}})\n"; # iterate over the @places of the element, which includes associated nodes, # associated elements, anchors, footnotes, floats, index entries, # printindices (including the element command itself, be it a @node or # a sectioning @-command). # during the iteration, split printindices that needs it, and reassociate # other placed elements with files and elements. my $current_element = $element; my @places = @{$element->{'place'}}; @{$element->{'place'}} = (); foreach my $place (@places) { my ($printindex, $printindex_to_split, $index_name); # determines if the placed thing is a printindex to be split if ($place->{'command'} and $place->{'command'} eq 'printindex') { $printindex = $place; $index_name = $printindex->{'name'}; # ! empty index if (exists($t2h_default_index_letters_array{$index_name}) and # split index scalar(@{$t2h_default_index_letters_array{$index_name}} > 1) # the condition defined($printindex->{'associated_element'} implies # that we don't split printindex before first element, otherwise # there will be a need to begin document without a first element # which would be annoying. and defined($printindex->{'associated_element'})) { $printindex_to_split = 1; } } # this is a non split printindex or any other placed thing. if (!$printindex_to_split) { push @{$current_element->{'place'}}, $place; # don't remodify the original element file, it was set right at the # beginning of the function. $place->{'file'} = $current_element->{'file'} if ($place ne $element); # the 'element_ref' has to be reset. Otherwise, $place->{'element_ref'} # will appear as a new element and trigger closing the file and # opening a new one. $place->{'element_ref'} = $current_element if ($place->{'element_ref'} and $current_element ne $element); # this resets the element associated with a printindex. if ($place->{'associated_element'} and $current_element ne $element) { $place->{'associated_element'} = $current_element; } next; } # now split the index my @letter_groups = (); my @letters_split = @{$t2h_default_index_letters_array{$index_name}}; foreach my $letters_split (@letters_split) { push @letter_groups, {'letters' => [@$letters_split]}; } $letter_groups[0]->{'element'} = $current_element; # besides preparing the new elements corresponding with split indices, # they are recorded for later directions rearrangements in # t2h_default_index_rearrange_directions. # this weird construct is there because the element used as a key is # converted to a string by perl, losing its meaning as a reference, # the reference must be recorded explicitly $t2h_default_element_split_printindices->{$element}->{'element'} = $element; push @{$t2h_default_element_split_printindices->{$element}->{'printindices'}}, $printindex; #print STDERR "Setting $element, $element->{'texi'}, $printindex $printindex->{'name'} as a split element\n"; foreach my $split_group (@letter_groups) { my $first_letter = $split_group->{'letters'}->[0]->{'letter'}; my $last_letter = $split_group->{'letters'}->[-1]->{'letter'}; if (!$split_group->{'element'}) { # this is not the first letters group, which is already associated # with an element, a new element is done. # construct new element name my $letters_heading; if ($last_letter ne $first_letter) { $letters_heading = &$normal_text("$first_letter -- $last_letter"); } else { $letters_heading = &$normal_text("$first_letter"); } my ($name, $simple); my $texi = "ADDED ELEMENT $element->{'texi'}: $letters_heading"; if (!defined($element->{'text'})) { my $element_heading_texi = &$heading_texi($element->{'tag'}, $element->{'texi'}, $element->{'number'}); my $index_heading_texi = &$index_element_heading_texi( $element_heading_texi, $element->{'tag'}, $element->{'texi'}, $element->{'number'}, $first_letter, $last_letter); $name = main::substitute_line($index_heading_texi, sprintf(__p("\@sectionning_command index page","\@%s index page"), $element->{'tag'})); $simple = main::simple_format(undef,undef,"simple_format \@$element->{'tag'} index page", $index_heading_texi); } else { # should never happen, at this point 'text' is always undefined. $name = "$element->{'text'}: $letters_heading"; $simple = "$element->{'simple_format'}: $letters_heading"; } #file and id my $relative_file = $Texi2HTML::THISDOC{'file_base_name'} . '_' . $t2h_default_file_number; $t2h_default_file_number++; $relative_file .= '.' . $Texi2HTML::THISDOC{'extension'} if (defined($Texi2HTML::THISDOC{'extension'})); my $id = "index_split-$t2h_default_index_id_nr"; $t2h_default_index_id_nr++; my $new_element = { 'file' => $relative_file, 'id' => $id, 'target' => $id, 'text' => $name, 'texi' => $texi, 'seen' => 1, 'simple_format' => $simple }; # to avoid crashing when there is a filename collision. main::add_file($new_element->{'file'}); $split_group->{'element'} = $new_element; $current_element = $new_element; #print STDERR "Added file $new_element->{'file'} ($new_element, $new_element->{'id'}) for $new_element->{'texi'} ($first_letter:$last_letter)\n"; } else { # this is the first index split, it is still associated with the element #print STDERR "No file added for ($first_letter:$last_letter)\n"; } } $t2h_default_seen_files{$default_element_file} = $current_element->{'file'}; $printindex->{'split_groups'} = \@letter_groups; #print STDERR "$index_name processed for $element, $element->{'texi'} (@{$printindex->{'split_groups'}})\n"; } } # set directions for added elements now that they are done in the # main program for all the other elements. sub t2h_default_index_rearrange_directions() { return if (!defined($t2h_default_element_split_printindices)); foreach my $element_string (keys(%$t2h_default_element_split_printindices)) { my $element = $t2h_default_element_split_printindices->{$element_string}->{'element'}; my $current_element = $element; #print STDERR " E Processing $element_string,$current_element $current_element->{'texi'}\n"; foreach my $printindex (@{$t2h_default_element_split_printindices->{$element_string}->{'printindices'}}) { #print STDERR " I Processing $printindex $printindex->{'name'} (@{$printindex->{'split_groups'}})\n"; foreach my $split_group (@{$printindex->{'split_groups'}}) { my $first_letter = $split_group->{'letters'}->[0]->{'letter'}; my $last_letter = $split_group->{'letters'}->[-1]->{'letter'}; my $new_element = $split_group->{'element'}; next if ($current_element eq $new_element); #print STDERR " G Processing ($first_letter:$last_letter) in $element->{'texi'}, index $printindex->{'name'}: $new_element->{'texi'}\n"; $new_element->{'This'} = $new_element; if ($current_element->{'Forward'}) { $current_element->{'Forward'}->{'Back'} = $new_element; $new_element->{'Forward'} = $current_element->{'Forward'}; } $current_element->{'Forward'} = $new_element; $new_element->{'Back'} = $current_element; if ($current_element->{'Following'}) { #print STDERR "F: C($current_element): $current_element->{'texi'}, N($new_element): $new_element->{'texi'} -- C->F: $current_element->{'Following'}->{'texi'}\n"; $new_element->{'Following'} = $current_element->{'Following'}; $current_element->{'Following'} = $new_element; } foreach my $key ('FastForward', 'FastBack', 'Up', 'tag_level', 'tag', 'level', 'node') { $new_element->{$key} = $element->{$key} if (defined($element->{$key})); } $new_element->{'this'} = $new_element; $new_element->{'element_ref'} = $new_element; $current_element = $new_element; } } } } # not needed to initialize it for a document, since it is reset # in index_summary my $t2h_symbol_indices = 0; # format a letter appearing in a summary for an index. The letter links to # the place where the index elements beginning with this letter are (called # a letter entry). # # arguments: # letter # file where the target letter entry is # identifier for the target letter entry sub html_default_summary_letter($$$$$$$) { my $letter = shift; my $file = shift; my $default_identifier = shift; my $index_element_id = shift; my $number = shift; my $index_element = shift; my $index_name = shift; return '' if ($letter =~ /^\s*$/); my $is_symbol = $letter !~ /^[A-Za-z]/; my $identifier = $default_identifier; if ($NEW_CROSSREF_STYLE) { if ($is_symbol) { $t2h_symbol_indices++; $identifier = $index_element_id . "_${index_name}_symbol-$t2h_symbol_indices"; } else { $identifier = $index_element_id . "_${index_name}_letter-${letter}"; } } my $result = &$anchor('', $file . '#' . $identifier, '' . &$protect_text($letter) . '', 'class="summary-letter"'); return $result unless ($NEW_CROSSREF_STYLE); return ($result, $identifier, $is_symbol); } # this replaces do_index_page # args should be: # index_name # printindex sub t2h_GPL_default_printindex($$) { my $index_name = shift; my $printindex = shift; # could be cross verified with argument my $identifier_index_nr = 0; my @split_letters; if (defined($printindex->{'split_groups'}) and scalar(@{$printindex->{'split_groups'}})) { @split_letters = @{$printindex->{'split_groups'}}; } elsif (defined($Texi2HTML::THISDOC{'index_letters_array'}->{$index_name}) and scalar(@{$Texi2HTML::THISDOC{'index_letters_array'}->{$index_name}})) { my $element = $printindex->{'associated_element'}; # this happens for printindex before the first element. if (!defined($element)) { $element = {'file' => '', 'id' => "$printindex->{'region'}_printindex"}; } elsif (defined($element->{'element_ref'})) { $element = $element->{'element_ref'}; } @split_letters = ({ 'letters' => $Texi2HTML::THISDOC{'index_letters_array'}->{$index_name}, 'element' => $element}); } else { return ''; } foreach my $split_group (@split_letters) { #do summmary my @non_alpha = (); my @alpha = (); #print STDERR "$index_name @{$split_group->{'letters'}}\n"; # letter_id could be done once for all instead of for each split_group # and outside of t2h_default_summary_letter (or t2h_default_summary_letter # could be simplified and inlined my %letter_id; foreach my $summary_split_group (@split_letters) { foreach my $letter_entry (@{$summary_split_group->{'letters'}}) { my $letter = $letter_entry->{'letter'}; my $dest_file = ''; ####################################### debug if (!defined($summary_split_group->{'element'})) { main::msg_debug ("index $index_name, letter $letter, element for summary_split_group $summary_split_group not defined"); } elsif (!defined($summary_split_group->{'element'}->{'id'})) { main::msg_debug ("index $index_name, letter $letter, element $summary_split_group->{'element'} `$summary_split_group->{'element'}->{'texi'}', id undef"); } ####################################### end debug $dest_file = $summary_split_group->{'element'}->{'file'} if ($summary_split_group ne $split_group); my $index_element_id = $summary_split_group->{'element'}->{'id'}; my $default_identifier = $index_element_id . "_$identifier_index_nr"; #print STDERR "$split_group $summary_split_group $summary_split_group->{'element'} $summary_split_group->{'element'}->{'id'} $identifier_index_nr $index_element_id $default_identifier\n"; $identifier_index_nr++; my ($result, $identifier, $is_symbol) = &$summary_letter($letter, $dest_file, $default_identifier, $index_element_id, '', '', $index_name); $identifier = $default_identifier if (!defined($identifier)); $letter_id{$letter} = $identifier; $is_symbol = $letter !~ /^[A-Za-z]/ if (!defined($is_symbol)); if ($result ne '') { if ($is_symbol) { push @non_alpha, $result; } else { push @alpha, $result; } } } } my $summary = &$index_summary(\@alpha, \@non_alpha); # reset symbols numbering $t2h_symbol_indices = 0; my $letters_text = ''; foreach my $letter_entry (@{$split_group->{'letters'}}) { my $letter = $letter_entry->{'letter'}; my $entries_text = ''; foreach my $index_entry_ref (@{$letter_entry->{'entries'}}) { my ($text_href, $entry_file, $element_file, $entry_target, $entry_element_target, $formatted_entry, $element_href, $entry_element_text, $in_region_not_in_output) = main::get_index_entry_infos($index_entry_ref, $split_group->{'element'}); $entries_text .= &$index_entry ($text_href, $formatted_entry, $element_href, $entry_element_text, $entry_file, $element_file, $entry_target, $entry_element_target, $in_region_not_in_output, $index_entry_ref); } $letters_text .= &$index_letter ($letter, $letter_id{$letter}, $entries_text) } my $index_text = &$print_index($letters_text, $index_name); $split_group->{'text'} = $summary . $index_text . $summary; # print STDERR " ---> $index_name @{$split_group->{'letters'}} # * elt: $split_group->{'element'}->{'id'}, $split_group->{'element'}->{'file'}, $split_group->{'element'}->{'name'} # * directions: B: $split_group->{'element'}->{'Back'}->{'name'}, F: $split_group->{'element'}->{'Forward'}->{'name'}, FB: $split_group->{'element'}->{'FastBack'}->{'name'}, FF: $split_group->{'element'}->{'FastForward'}->{'name'} # * text # #$split_group->{'text'} # #"; } my $current_page = shift @split_letters; if (!scalar(@split_letters)) { return $current_page->{'text'}; } while (1) { # print the index letters push @{$Texi2HTML::THIS_SECTION}, $current_page->{'text'}; $current_page = shift @split_letters; last if (!defined($current_page)); # there is no need to begin first element if not already done, since # the index is not split if not already in an element. # end the previous element main::finish_element ($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, $Texi2HTML::THIS_ELEMENT->{'Forward'}, 0); # do the new element beginning $Texi2HTML::THIS_ELEMENT = $current_page->{'element'}; my $new_element = $Texi2HTML::THIS_ELEMENT; main::unref_file($new_element->{'file'}); main::do_element_directions($new_element); my $do_page_head = main::open_out_file($new_element->{'file'}); if ($do_page_head) { &$print_page_head($Texi2HTML::THISDOC{'FH'}); &$print_chapter_header($Texi2HTML::THISDOC{'FH'}, $new_element) if Texi2HTML::Config::get_conf('SPLIT') eq 'chapter'; &$print_section_header($Texi2HTML::THISDOC{'FH'}, $new_element) if Texi2HTML::Config::get_conf('SPLIT') eq 'section'; } # almost nothing of this is used in the default html output @{$Texi2HTML::THIS_SECTION} = &$element_heading($new_element, $new_element->{'tag'}, $new_element->{'texi'}, $new_element->{'text'}, 0, 0, $new_element->{'this'}, 1, 0, 0, "\@$new_element->{'tag'} $new_element->{'texi'}", $new_element->{'id'}, $new_element); } return ''; } # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, # if $T2H_HOME/documentlanguages.pl exists. # # @T2H_DOCUMENT_LANGUAGES@ %language_codes = ( 'aa' => 1, 'ab' => 1, 'ae' => 1, 'af' => 1, 'ak' => 1, 'am' => 1, 'an' => 1, 'ar' => 1, 'as' => 1, 'av' => 1, 'ay' => 1, 'az' => 1, 'ba' => 1, 'be' => 1, 'bg' => 1, 'bh' => 1, 'bi' => 1, 'bm' => 1, 'bn' => 1, 'bo' => 1, 'br' => 1, 'ca' => 1, 'ce' => 1, 'ch' => 1, 'co' => 1, 'cr' => 1, 'cs' => 1, 'cu' => 1, 'cv' => 1, 'cy' => 1, 'da' => 1, 'de' => 1, 'dv' => 1, 'dz' => 1, 'ee' => 1, 'el' => 1, 'en' => 1, 'eo' => 1, 'es' => 1, 'et' => 1, 'eu' => 1, 'fa' => 1, 'ff' => 1, 'fi' => 1, 'fj' => 1, 'fo' => 1, 'fr' => 1, 'fy' => 1, 'ga' => 1, 'gd' => 1, 'gl' => 1, 'gn' => 1, 'gu' => 1, 'gv' => 1, 'ha' => 1, 'he' => 1, 'hi' => 1, 'ho' => 1, 'ht' => 1, 'hu' => 1, 'hy' => 1, 'hz' => 1, 'ia' => 1, 'ie' => 1, 'ig' => 1, 'ii' => 1, 'ik' => 1, 'io' => 1, 'is' => 1, 'it' => 1, 'iu' => 1, 'iw' => 1, 'ja' => 1, 'ji' => 1, 'jv' => 1, 'jw' => 1, 'ka' => 1, 'kg' => 1, 'ki' => 1, 'kj' => 1, 'kk' => 1, 'kl' => 1, 'km' => 1, 'kn' => 1, 'ko' => 1, 'kr' => 1, 'ks' => 1, 'ku' => 1, 'kv' => 1, 'kw' => 1, 'ky' => 1, 'la' => 1, 'lb' => 1, 'lg' => 1, 'li' => 1, 'ln' => 1, 'lo' => 1, 'lt' => 1, 'lu' => 1, 'lv' => 1, 'mg' => 1, 'mh' => 1, 'mi' => 1, 'mk' => 1, 'ml' => 1, 'mn' => 1, 'mo' => 1, 'mr' => 1, 'ms' => 1, 'mt' => 1, 'my' => 1, 'na' => 1, 'nd' => 1, 'ne' => 1, 'ng' => 1, 'nl' => 1, 'no' => 1, 'nr' => 1, 'nv' => 1, 'ny' => 1, 'oc' => 1, 'oj' => 1, 'om' => 1, 'or' => 1, 'os' => 1, 'pa' => 1, 'pi' => 1, 'pl' => 1, 'ps' => 1, 'pt' => 1, 'qu' => 1, 'rm' => 1, 'rn' => 1, 'ro' => 1, 'ru' => 1, 'rw' => 1, 'sa' => 1, 'sc' => 1, 'sd' => 1, 'se' => 1, 'sg' => 1, 'sh' => 1, 'si' => 1, 'sk' => 1, 'sl' => 1, 'sm' => 1, 'sn' => 1, 'so' => 1, 'sq' => 1, 'ss' => 1, 'st' => 1, 'su' => 1, 'sv' => 1, 'sw' => 1, 'ta' => 1, 'te' => 1, 'tg' => 1, 'th' => 1, 'ti' => 1, 'tk' => 1, 'tl' => 1, 'tn' => 1, 'to' => 1, 'tr' => 1, 'ts' => 1, 'tt' => 1, 'ty' => 1, 'ug' => 1, 'uk' => 1, 'ur' => 1, 'uz' => 1, 've' => 1, 'vi' => 1, 'vo' => 1, 'wa' => 1, 'wo' => 1, 'xh' => 1, 'yi' => 1, 'yo' => 1, 'za' => 1, 'zh' => 1, 'zu' => 1, 'aaa' => 1, 'aab' => 1, 'aac' => 1, 'aad' => 1, 'aaf' => 1, 'aag' => 1, 'aah' => 1, 'aai' => 1, 'aak' => 1, 'aal' => 1, 'aam' => 1, 'aan' => 1, 'aap' => 1, 'aaq' => 1, 'aas' => 1, 'aau' => 1, 'aav' => 1, 'aaw' => 1, 'aax' => 1, 'aaz' => 1, 'aba' => 1, 'abb' => 1, 'abc' => 1, 'abd' => 1, 'abe' => 1, 'abf' => 1, 'abg' => 1, 'abi' => 1, 'abj' => 1, 'abl' => 1, 'abm' => 1, 'abn' => 1, 'abo' => 1, 'abp' => 1, 'abq' => 1, 'abr' => 1, 'abs' => 1, 'abt' => 1, 'abu' => 1, 'abw' => 1, 'abx' => 1, 'aby' => 1, 'abz' => 1, 'aca' => 1, 'acb' => 1, 'acd' => 1, 'ace' => 1, 'acf' => 1, 'ach' => 1, 'aci' => 1, 'ack' => 1, 'acl' => 1, 'acn' => 1, 'acp' => 1, 'acr' => 1, 'acs' => 1, 'act' => 1, 'acu' => 1, 'acv' => 1, 'acz' => 1, 'ada' => 1, 'adb' => 1, 'add' => 1, 'ade' => 1, 'adg' => 1, 'adh' => 1, 'adi' => 1, 'adj' => 1, 'adl' => 1, 'adn' => 1, 'ado' => 1, 'adp' => 1, 'adq' => 1, 'adr' => 1, 'ads' => 1, 'adt' => 1, 'adu' => 1, 'adw' => 1, 'adx' => 1, 'ady' => 1, 'adz' => 1, 'aea' => 1, 'aed' => 1, 'aee' => 1, 'aek' => 1, 'ael' => 1, 'aem' => 1, 'aen' => 1, 'aeq' => 1, 'aer' => 1, 'aes' => 1, 'aeu' => 1, 'aew' => 1, 'aey' => 1, 'aez' => 1, 'afa' => 1, 'afd' => 1, 'afe' => 1, 'afg' => 1, 'afh' => 1, 'afi' => 1, 'afk' => 1, 'afn' => 1, 'afo' => 1, 'afp' => 1, 'afs' => 1, 'aft' => 1, 'afu' => 1, 'afz' => 1, 'aga' => 1, 'agb' => 1, 'agc' => 1, 'agd' => 1, 'age' => 1, 'agf' => 1, 'agg' => 1, 'agh' => 1, 'agi' => 1, 'agj' => 1, 'agk' => 1, 'agl' => 1, 'agm' => 1, 'agn' => 1, 'ago' => 1, 'agp' => 1, 'agq' => 1, 'agr' => 1, 'ags' => 1, 'agt' => 1, 'agu' => 1, 'agv' => 1, 'agw' => 1, 'agx' => 1, 'agy' => 1, 'agz' => 1, 'aha' => 1, 'ahb' => 1, 'ahg' => 1, 'ahh' => 1, 'ahi' => 1, 'ahk' => 1, 'ahl' => 1, 'ahm' => 1, 'ahn' => 1, 'aho' => 1, 'ahp' => 1, 'ahr' => 1, 'ahs' => 1, 'aht' => 1, 'aia' => 1, 'aib' => 1, 'aic' => 1, 'aid' => 1, 'aie' => 1, 'aif' => 1, 'aig' => 1, 'aih' => 1, 'aij' => 1, 'aik' => 1, 'ail' => 1, 'aim' => 1, 'ain' => 1, 'aio' => 1, 'aip' => 1, 'aiq' => 1, 'air' => 1, 'ais' => 1, 'ait' => 1, 'aiw' => 1, 'aix' => 1, 'aiy' => 1, 'aja' => 1, 'ajg' => 1, 'aji' => 1, 'ajw' => 1, 'ajz' => 1, 'akb' => 1, 'akc' => 1, 'akd' => 1, 'ake' => 1, 'akf' => 1, 'akg' => 1, 'akh' => 1, 'aki' => 1, 'akj' => 1, 'akk' => 1, 'akl' => 1, 'akm' => 1, 'ako' => 1, 'akp' => 1, 'akq' => 1, 'akr' => 1, 'aks' => 1, 'akt' => 1, 'aku' => 1, 'akv' => 1, 'akw' => 1, 'akx' => 1, 'aky' => 1, 'akz' => 1, 'ala' => 1, 'alc' => 1, 'ald' => 1, 'ale' => 1, 'alf' => 1, 'alg' => 1, 'alh' => 1, 'ali' => 1, 'alj' => 1, 'alk' => 1, 'all' => 1, 'alm' => 1, 'alo' => 1, 'alp' => 1, 'alq' => 1, 'alr' => 1, 'alt' => 1, 'alu' => 1, 'alv' => 1, 'alw' => 1, 'alx' => 1, 'aly' => 1, 'alz' => 1, 'ama' => 1, 'amb' => 1, 'amc' => 1, 'ame' => 1, 'amf' => 1, 'amg' => 1, 'ami' => 1, 'amj' => 1, 'amk' => 1, 'aml' => 1, 'amm' => 1, 'amn' => 1, 'amo' => 1, 'amp' => 1, 'amq' => 1, 'amr' => 1, 'ams' => 1, 'amt' => 1, 'amu' => 1, 'amv' => 1, 'amw' => 1, 'amx' => 1, 'amy' => 1, 'amz' => 1, 'ana' => 1, 'anb' => 1, 'anc' => 1, 'and' => 1, 'ane' => 1, 'anf' => 1, 'ang' => 1, 'anh' => 1, 'ani' => 1, 'anj' => 1, 'ank' => 1, 'anl' => 1, 'anm' => 1, 'ann' => 1, 'ano' => 1, 'anp' => 1, 'anq' => 1, 'anr' => 1, 'ans' => 1, 'ant' => 1, 'anu' => 1, 'anv' => 1, 'anw' => 1, 'anx' => 1, 'any' => 1, 'anz' => 1, 'aoa' => 1, 'aob' => 1, 'aoc' => 1, 'aod' => 1, 'aoe' => 1, 'aof' => 1, 'aog' => 1, 'aoh' => 1, 'aoi' => 1, 'aoj' => 1, 'aok' => 1, 'aol' => 1, 'aom' => 1, 'aon' => 1, 'aor' => 1, 'aos' => 1, 'aot' => 1, 'aox' => 1, 'aoz' => 1, 'apa' => 1, 'apb' => 1, 'ape' => 1, 'apg' => 1, 'aph' => 1, 'api' => 1, 'apj' => 1, 'apk' => 1, 'apl' => 1, 'apm' => 1, 'apn' => 1, 'apo' => 1, 'app' => 1, 'apq' => 1, 'apr' => 1, 'aps' => 1, 'apt' => 1, 'apu' => 1, 'apv' => 1, 'apw' => 1, 'apx' => 1, 'apy' => 1, 'apz' => 1, 'aqa' => 1, 'aqc' => 1, 'aqg' => 1, 'aql' => 1, 'aqm' => 1, 'aqn' => 1, 'aqp' => 1, 'aqr' => 1, 'arc' => 1, 'ard' => 1, 'are' => 1, 'arh' => 1, 'ari' => 1, 'arj' => 1, 'ark' => 1, 'arl' => 1, 'arn' => 1, 'aro' => 1, 'arp' => 1, 'arr' => 1, 'art' => 1, 'aru' => 1, 'arv' => 1, 'arw' => 1, 'arx' => 1, 'asa' => 1, 'asb' => 1, 'asc' => 1, 'asd' => 1, 'ase' => 1, 'asf' => 1, 'asg' => 1, 'ash' => 1, 'asi' => 1, 'asj' => 1, 'ask' => 1, 'asl' => 1, 'asn' => 1, 'aso' => 1, 'asp' => 1, 'asq' => 1, 'asr' => 1, 'ass' => 1, 'ast' => 1, 'asu' => 1, 'asv' => 1, 'asw' => 1, 'asx' => 1, 'asy' => 1, 'asz' => 1, 'ata' => 1, 'atb' => 1, 'atc' => 1, 'atd' => 1, 'ate' => 1, 'atg' => 1, 'ath' => 1, 'ati' => 1, 'atj' => 1, 'atk' => 1, 'atl' => 1, 'atm' => 1, 'atn' => 1, 'ato' => 1, 'atp' => 1, 'atq' => 1, 'atr' => 1, 'ats' => 1, 'att' => 1, 'atu' => 1, 'atv' => 1, 'atw' => 1, 'atx' => 1, 'aty' => 1, 'atz' => 1, 'aua' => 1, 'aub' => 1, 'auc' => 1, 'aud' => 1, 'aue' => 1, 'auf' => 1, 'aug' => 1, 'auh' => 1, 'aui' => 1, 'auj' => 1, 'auk' => 1, 'aul' => 1, 'aum' => 1, 'aun' => 1, 'auo' => 1, 'aup' => 1, 'auq' => 1, 'aur' => 1, 'aus' => 1, 'aut' => 1, 'auu' => 1, 'auw' => 1, 'aux' => 1, 'auy' => 1, 'avb' => 1, 'avd' => 1, 'avi' => 1, 'avk' => 1, 'avn' => 1, 'avo' => 1, 'avs' => 1, 'avt' => 1, 'avu' => 1, 'avv' => 1, 'awa' => 1, 'awb' => 1, 'awc' => 1, 'awd' => 1, 'awe' => 1, 'awh' => 1, 'awi' => 1, 'awk' => 1, 'awm' => 1, 'awn' => 1, 'awo' => 1, 'awr' => 1, 'aws' => 1, 'awt' => 1, 'awu' => 1, 'awv' => 1, 'aww' => 1, 'awx' => 1, 'awy' => 1, 'axb' => 1, 'axg' => 1, 'axk' => 1, 'axm' => 1, 'axx' => 1, 'aya' => 1, 'ayb' => 1, 'ayd' => 1, 'aye' => 1, 'ayg' => 1, 'ayi' => 1, 'ayk' => 1, 'ayo' => 1, 'ayq' => 1, 'ays' => 1, 'ayt' => 1, 'ayu' => 1, 'ayx' => 1, 'ayy' => 1, 'ayz' => 1, 'aza' => 1, 'azc' => 1, 'azg' => 1, 'azm' => 1, 'azo' => 1, 'azt' => 1, 'azz' => 1, 'baa' => 1, 'bab' => 1, 'bac' => 1, 'bad' => 1, 'bae' => 1, 'baf' => 1, 'bag' => 1, 'bah' => 1, 'bai' => 1, 'baj' => 1, 'bal' => 1, 'ban' => 1, 'bao' => 1, 'bap' => 1, 'bar' => 1, 'bas' => 1, 'bat' => 1, 'bau' => 1, 'bav' => 1, 'baw' => 1, 'bax' => 1, 'bay' => 1, 'baz' => 1, 'bba' => 1, 'bbb' => 1, 'bbc' => 1, 'bbd' => 1, 'bbe' => 1, 'bbf' => 1, 'bbg' => 1, 'bbh' => 1, 'bbi' => 1, 'bbj' => 1, 'bbk' => 1, 'bbl' => 1, 'bbm' => 1, 'bbn' => 1, 'bbo' => 1, 'bbp' => 1, 'bbq' => 1, 'bbr' => 1, 'bbs' => 1, 'bbt' => 1, 'bbu' => 1, 'bbv' => 1, 'bbw' => 1, 'bbx' => 1, 'bby' => 1, 'bca' => 1, 'bcb' => 1, 'bcd' => 1, 'bce' => 1, 'bcf' => 1, 'bcg' => 1, 'bch' => 1, 'bci' => 1, 'bcj' => 1, 'bck' => 1, 'bcm' => 1, 'bcn' => 1, 'bco' => 1, 'bcp' => 1, 'bcq' => 1, 'bcr' => 1, 'bcs' => 1, 'bct' => 1, 'bcu' => 1, 'bcv' => 1, 'bcw' => 1, 'bcy' => 1, 'bcz' => 1, 'bda' => 1, 'bdb' => 1, 'bdc' => 1, 'bdd' => 1, 'bde' => 1, 'bdg' => 1, 'bdh' => 1, 'bdi' => 1, 'bdj' => 1, 'bdk' => 1, 'bdl' => 1, 'bdm' => 1, 'bdn' => 1, 'bdo' => 1, 'bdp' => 1, 'bdq' => 1, 'bdr' => 1, 'bds' => 1, 'bdu' => 1, 'bdv' => 1, 'bdw' => 1, 'bdx' => 1, 'bdy' => 1, 'bdz' => 1, 'bea' => 1, 'beb' => 1, 'bec' => 1, 'bed' => 1, 'bee' => 1, 'bef' => 1, 'beg' => 1, 'beh' => 1, 'bei' => 1, 'bej' => 1, 'bek' => 1, 'bem' => 1, 'beo' => 1, 'bep' => 1, 'beq' => 1, 'ber' => 1, 'bes' => 1, 'bet' => 1, 'beu' => 1, 'bev' => 1, 'bew' => 1, 'bex' => 1, 'bey' => 1, 'bez' => 1, 'bfa' => 1, 'bfb' => 1, 'bfc' => 1, 'bfd' => 1, 'bfe' => 1, 'bff' => 1, 'bfg' => 1, 'bfh' => 1, 'bfi' => 1, 'bfj' => 1, 'bfk' => 1, 'bfl' => 1, 'bfm' => 1, 'bfn' => 1, 'bfo' => 1, 'bfp' => 1, 'bfq' => 1, 'bfr' => 1, 'bfs' => 1, 'bft' => 1, 'bfu' => 1, 'bfw' => 1, 'bfy' => 1, 'bfz' => 1, 'bga' => 1, 'bgb' => 1, 'bgc' => 1, 'bgd' => 1, 'bge' => 1, 'bgf' => 1, 'bgg' => 1, 'bgi' => 1, 'bgj' => 1, 'bgk' => 1, 'bgl' => 1, 'bgm' => 1, 'bgo' => 1, 'bgr' => 1, 'bgs' => 1, 'bgt' => 1, 'bgu' => 1, 'bgv' => 1, 'bgw' => 1, 'bgx' => 1, 'bgy' => 1, 'bgz' => 1, 'bha' => 1, 'bhb' => 1, 'bhc' => 1, 'bhd' => 1, 'bhe' => 1, 'bhf' => 1, 'bhg' => 1, 'bhh' => 1, 'bhi' => 1, 'bhj' => 1, 'bhl' => 1, 'bhm' => 1, 'bhn' => 1, 'bho' => 1, 'bhp' => 1, 'bhq' => 1, 'bhs' => 1, 'bht' => 1, 'bhu' => 1, 'bhv' => 1, 'bhw' => 1, 'bhx' => 1, 'bhy' => 1, 'bhz' => 1, 'bia' => 1, 'bib' => 1, 'bic' => 1, 'bid' => 1, 'bie' => 1, 'bif' => 1, 'big' => 1, 'bij' => 1, 'bik' => 1, 'bil' => 1, 'bim' => 1, 'bin' => 1, 'bio' => 1, 'bip' => 1, 'biq' => 1, 'bir' => 1, 'bit' => 1, 'biu' => 1, 'biv' => 1, 'biw' => 1, 'bix' => 1, 'biy' => 1, 'biz' => 1, 'bja' => 1, 'bjb' => 1, 'bjc' => 1, 'bjd' => 1, 'bje' => 1, 'bjf' => 1, 'bjg' => 1, 'bjh' => 1, 'bji' => 1, 'bjj' => 1, 'bjk' => 1, 'bjl' => 1, 'bjm' => 1, 'bjo' => 1, 'bjr' => 1, 'bjs' => 1, 'bjt' => 1, 'bju' => 1, 'bjv' => 1, 'bjw' => 1, 'bjx' => 1, 'bjy' => 1, 'bjz' => 1, 'bka' => 1, 'bkb' => 1, 'bkc' => 1, 'bkd' => 1, 'bkf' => 1, 'bkg' => 1, 'bkh' => 1, 'bki' => 1, 'bkj' => 1, 'bkk' => 1, 'bkl' => 1, 'bkm' => 1, 'bkn' => 1, 'bko' => 1, 'bkp' => 1, 'bkq' => 1, 'bkr' => 1, 'bks' => 1, 'bkt' => 1, 'bku' => 1, 'bkv' => 1, 'bkw' => 1, 'bkx' => 1, 'bky' => 1, 'bkz' => 1, 'bla' => 1, 'blb' => 1, 'blc' => 1, 'bld' => 1, 'ble' => 1, 'blf' => 1, 'blg' => 1, 'blh' => 1, 'bli' => 1, 'blj' => 1, 'blk' => 1, 'bll' => 1, 'blm' => 1, 'blo' => 1, 'blp' => 1, 'blq' => 1, 'blr' => 1, 'bls' => 1, 'blt' => 1, 'blv' => 1, 'blw' => 1, 'blx' => 1, 'bly' => 1, 'blz' => 1, 'bma' => 1, 'bmb' => 1, 'bmc' => 1, 'bmd' => 1, 'bme' => 1, 'bmf' => 1, 'bmg' => 1, 'bmh' => 1, 'bmi' => 1, 'bmj' => 1, 'bmk' => 1, 'bml' => 1, 'bmn' => 1, 'bmo' => 1, 'bmp' => 1, 'bmq' => 1, 'bmr' => 1, 'bms' => 1, 'bmt' => 1, 'bmu' => 1, 'bmv' => 1, 'bmw' => 1, 'bmx' => 1, 'bmy' => 1, 'bmz' => 1, 'bna' => 1, 'bnb' => 1, 'bnc' => 1, 'bnd' => 1, 'bne' => 1, 'bnf' => 1, 'bng' => 1, 'bni' => 1, 'bnj' => 1, 'bnk' => 1, 'bnl' => 1, 'bnm' => 1, 'bnn' => 1, 'bno' => 1, 'bnp' => 1, 'bnq' => 1, 'bnr' => 1, 'bns' => 1, 'bnt' => 1, 'bnu' => 1, 'bnv' => 1, 'bnw' => 1, 'bnx' => 1, 'bny' => 1, 'bnz' => 1, 'boa' => 1, 'bob' => 1, 'boe' => 1, 'bof' => 1, 'bog' => 1, 'boh' => 1, 'boi' => 1, 'boj' => 1, 'bok' => 1, 'bol' => 1, 'bom' => 1, 'bon' => 1, 'boo' => 1, 'bop' => 1, 'boq' => 1, 'bor' => 1, 'bot' => 1, 'bou' => 1, 'bov' => 1, 'bow' => 1, 'box' => 1, 'boy' => 1, 'boz' => 1, 'bpa' => 1, 'bpb' => 1, 'bpd' => 1, 'bpg' => 1, 'bph' => 1, 'bpi' => 1, 'bpj' => 1, 'bpk' => 1, 'bpl' => 1, 'bpm' => 1, 'bpn' => 1, 'bpo' => 1, 'bpp' => 1, 'bpq' => 1, 'bpr' => 1, 'bps' => 1, 'bpt' => 1, 'bpu' => 1, 'bpv' => 1, 'bpw' => 1, 'bpx' => 1, 'bpy' => 1, 'bpz' => 1, 'bqa' => 1, 'bqb' => 1, 'bqc' => 1, 'bqd' => 1, 'bqf' => 1, 'bqg' => 1, 'bqh' => 1, 'bqi' => 1, 'bqj' => 1, 'bqk' => 1, 'bql' => 1, 'bqm' => 1, 'bqn' => 1, 'bqo' => 1, 'bqp' => 1, 'bqq' => 1, 'bqr' => 1, 'bqs' => 1, 'bqt' => 1, 'bqu' => 1, 'bqv' => 1, 'bqw' => 1, 'bqx' => 1, 'bqy' => 1, 'bqz' => 1, 'bra' => 1, 'brb' => 1, 'brc' => 1, 'brd' => 1, 'brf' => 1, 'brg' => 1, 'brh' => 1, 'bri' => 1, 'brj' => 1, 'brk' => 1, 'brl' => 1, 'brm' => 1, 'brn' => 1, 'bro' => 1, 'brp' => 1, 'brq' => 1, 'brr' => 1, 'brs' => 1, 'brt' => 1, 'bru' => 1, 'brv' => 1, 'brw' => 1, 'brx' => 1, 'bry' => 1, 'brz' => 1, 'bsa' => 1, 'bsb' => 1, 'bsc' => 1, 'bse' => 1, 'bsf' => 1, 'bsg' => 1, 'bsh' => 1, 'bsi' => 1, 'bsj' => 1, 'bsk' => 1, 'bsl' => 1, 'bsm' => 1, 'bsn' => 1, 'bso' => 1, 'bsp' => 1, 'bsq' => 1, 'bsr' => 1, 'bss' => 1, 'bst' => 1, 'bsu' => 1, 'bsv' => 1, 'bsw' => 1, 'bsx' => 1, 'bsy' => 1, 'bta' => 1, 'btb' => 1, 'btc' => 1, 'btd' => 1, 'bte' => 1, 'btf' => 1, 'btg' => 1, 'bth' => 1, 'bti' => 1, 'btk' => 1, 'btl' => 1, 'btm' => 1, 'btn' => 1, 'btp' => 1, 'btq' => 1, 'btr' => 1, 'bts' => 1, 'btt' => 1, 'btu' => 1, 'btv' => 1, 'btw' => 1, 'btx' => 1, 'bty' => 1, 'btz' => 1, 'bua' => 1, 'bub' => 1, 'buc' => 1, 'bud' => 1, 'bue' => 1, 'buf' => 1, 'bug' => 1, 'buh' => 1, 'bui' => 1, 'buj' => 1, 'buk' => 1, 'bum' => 1, 'bun' => 1, 'buo' => 1, 'bup' => 1, 'buq' => 1, 'bus' => 1, 'but' => 1, 'buu' => 1, 'buv' => 1, 'buw' => 1, 'bux' => 1, 'buy' => 1, 'buz' => 1, 'bva' => 1, 'bvb' => 1, 'bvc' => 1, 'bvd' => 1, 'bvf' => 1, 'bvg' => 1, 'bvh' => 1, 'bvi' => 1, 'bvj' => 1, 'bvk' => 1, 'bvl' => 1, 'bvm' => 1, 'bvn' => 1, 'bvo' => 1, 'bvq' => 1, 'bvr' => 1, 'bvt' => 1, 'bvv' => 1, 'bvw' => 1, 'bvx' => 1, 'bvz' => 1, 'bwa' => 1, 'bwb' => 1, 'bwc' => 1, 'bwd' => 1, 'bwe' => 1, 'bwf' => 1, 'bwg' => 1, 'bwh' => 1, 'bwi' => 1, 'bwj' => 1, 'bwk' => 1, 'bwl' => 1, 'bwm' => 1, 'bwn' => 1, 'bwo' => 1, 'bwp' => 1, 'bwq' => 1, 'bwr' => 1, 'bws' => 1, 'bwt' => 1, 'bwu' => 1, 'bww' => 1, 'bwx' => 1, 'bwy' => 1, 'bwz' => 1, 'bxa' => 1, 'bxb' => 1, 'bxc' => 1, 'bxd' => 1, 'bxe' => 1, 'bxf' => 1, 'bxg' => 1, 'bxh' => 1, 'bxi' => 1, 'bxj' => 1, 'bxl' => 1, 'bxn' => 1, 'bxo' => 1, 'bxp' => 1, 'bxq' => 1, 'bxs' => 1, 'bxv' => 1, 'bxw' => 1, 'bxx' => 1, 'bxz' => 1, 'bya' => 1, 'byb' => 1, 'byc' => 1, 'byd' => 1, 'bye' => 1, 'byf' => 1, 'byg' => 1, 'byh' => 1, 'byi' => 1, 'byj' => 1, 'byk' => 1, 'byl' => 1, 'bym' => 1, 'byn' => 1, 'byo' => 1, 'byp' => 1, 'byq' => 1, 'byr' => 1, 'bys' => 1, 'byt' => 1, 'byv' => 1, 'byw' => 1, 'byx' => 1, 'byy' => 1, 'byz' => 1, 'bza' => 1, 'bzb' => 1, 'bzd' => 1, 'bze' => 1, 'bzf' => 1, 'bzg' => 1, 'bzh' => 1, 'bzi' => 1, 'bzj' => 1, 'bzk' => 1, 'bzl' => 1, 'bzm' => 1, 'bzn' => 1, 'bzo' => 1, 'bzp' => 1, 'bzq' => 1, 'bzr' => 1, 'bzs' => 1, 'bzt' => 1, 'bzu' => 1, 'bzv' => 1, 'bzw' => 1, 'bzx' => 1, 'bzy' => 1, 'bzz' => 1, 'caa' => 1, 'cab' => 1, 'cac' => 1, 'cad' => 1, 'cae' => 1, 'caf' => 1, 'cag' => 1, 'cah' => 1, 'cai' => 1, 'caj' => 1, 'cak' => 1, 'cal' => 1, 'cam' => 1, 'can' => 1, 'cao' => 1, 'cap' => 1, 'caq' => 1, 'car' => 1, 'cas' => 1, 'cau' => 1, 'cav' => 1, 'caw' => 1, 'cax' => 1, 'cay' => 1, 'caz' => 1, 'cba' => 1, 'cbb' => 1, 'cbc' => 1, 'cbd' => 1, 'cbe' => 1, 'cbg' => 1, 'cbh' => 1, 'cbi' => 1, 'cbj' => 1, 'cbk' => 1, 'cbl' => 1, 'cbn' => 1, 'cbo' => 1, 'cbr' => 1, 'cbs' => 1, 'cbt' => 1, 'cbu' => 1, 'cbv' => 1, 'cby' => 1, 'cca' => 1, 'ccc' => 1, 'ccd' => 1, 'cce' => 1, 'ccg' => 1, 'cch' => 1, 'ccj' => 1, 'ccl' => 1, 'ccm' => 1, 'ccn' => 1, 'cco' => 1, 'ccp' => 1, 'ccq' => 1, 'ccr' => 1, 'ccs' => 1, 'cda' => 1, 'cdc' => 1, 'cdd' => 1, 'cde' => 1, 'cdf' => 1, 'cdg' => 1, 'cdh' => 1, 'cdi' => 1, 'cdj' => 1, 'cdm' => 1, 'cdn' => 1, 'cdr' => 1, 'cds' => 1, 'cdy' => 1, 'cdz' => 1, 'cea' => 1, 'ceb' => 1, 'ceg' => 1, 'cel' => 1, 'cen' => 1, 'cet' => 1, 'cfa' => 1, 'cfd' => 1, 'cfg' => 1, 'cfm' => 1, 'cga' => 1, 'cgc' => 1, 'cgg' => 1, 'cgk' => 1, 'chb' => 1, 'chc' => 1, 'chd' => 1, 'chf' => 1, 'chg' => 1, 'chh' => 1, 'chj' => 1, 'chk' => 1, 'chl' => 1, 'chm' => 1, 'chn' => 1, 'cho' => 1, 'chp' => 1, 'chq' => 1, 'chr' => 1, 'cht' => 1, 'chw' => 1, 'chx' => 1, 'chy' => 1, 'chz' => 1, 'cia' => 1, 'cib' => 1, 'cic' => 1, 'cid' => 1, 'cie' => 1, 'cih' => 1, 'cik' => 1, 'cim' => 1, 'cin' => 1, 'cip' => 1, 'cir' => 1, 'ciy' => 1, 'cja' => 1, 'cje' => 1, 'cjh' => 1, 'cji' => 1, 'cjk' => 1, 'cjm' => 1, 'cjn' => 1, 'cjo' => 1, 'cjp' => 1, 'cjr' => 1, 'cjs' => 1, 'cjv' => 1, 'cka' => 1, 'ckh' => 1, 'ckl' => 1, 'cko' => 1, 'ckq' => 1, 'ckr' => 1, 'cks' => 1, 'ckt' => 1, 'cku' => 1, 'ckv' => 1, 'ckx' => 1, 'cky' => 1, 'ckz' => 1, 'cla' => 1, 'clc' => 1, 'cle' => 1, 'clh' => 1, 'cli' => 1, 'clk' => 1, 'cll' => 1, 'clm' => 1, 'clo' => 1, 'clu' => 1, 'clw' => 1, 'cly' => 1, 'cma' => 1, 'cmc' => 1, 'cme' => 1, 'cmg' => 1, 'cmi' => 1, 'cmk' => 1, 'cml' => 1, 'cmm' => 1, 'cmo' => 1, 'cmr' => 1, 'cms' => 1, 'cmt' => 1, 'cna' => 1, 'cnb' => 1, 'cnc' => 1, 'cng' => 1, 'cnh' => 1, 'cni' => 1, 'cnk' => 1, 'cnl' => 1, 'cno' => 1, 'cns' => 1, 'cnt' => 1, 'cnu' => 1, 'cnw' => 1, 'cnx' => 1, 'cob' => 1, 'coc' => 1, 'cod' => 1, 'coe' => 1, 'cof' => 1, 'cog' => 1, 'coh' => 1, 'coj' => 1, 'cok' => 1, 'col' => 1, 'com' => 1, 'con' => 1, 'coo' => 1, 'cop' => 1, 'coq' => 1, 'cot' => 1, 'cou' => 1, 'cov' => 1, 'cow' => 1, 'cox' => 1, 'coy' => 1, 'coz' => 1, 'cpa' => 1, 'cpb' => 1, 'cpc' => 1, 'cpe' => 1, 'cpf' => 1, 'cpg' => 1, 'cpi' => 1, 'cpn' => 1, 'cpp' => 1, 'cps' => 1, 'cpu' => 1, 'cpy' => 1, 'cra' => 1, 'crb' => 1, 'crc' => 1, 'crd' => 1, 'crf' => 1, 'crg' => 1, 'crh' => 1, 'cri' => 1, 'crn' => 1, 'cro' => 1, 'crp' => 1, 'crq' => 1, 'crr' => 1, 'crs' => 1, 'crt' => 1, 'crv' => 1, 'crw' => 1, 'crx' => 1, 'cry' => 1, 'crz' => 1, 'csa' => 1, 'csb' => 1, 'csc' => 1, 'csd' => 1, 'cse' => 1, 'csf' => 1, 'csg' => 1, 'csh' => 1, 'csi' => 1, 'csk' => 1, 'csl' => 1, 'csm' => 1, 'csn' => 1, 'cso' => 1, 'csq' => 1, 'csr' => 1, 'css' => 1, 'cst' => 1, 'csu' => 1, 'csy' => 1, 'csz' => 1, 'cta' => 1, 'ctc' => 1, 'ctd' => 1, 'cte' => 1, 'ctg' => 1, 'ctl' => 1, 'ctm' => 1, 'ctn' => 1, 'cto' => 1, 'ctp' => 1, 'ctt' => 1, 'ctu' => 1, 'ctz' => 1, 'cua' => 1, 'cub' => 1, 'cuc' => 1, 'cug' => 1, 'cuh' => 1, 'cui' => 1, 'cuj' => 1, 'cuk' => 1, 'cul' => 1, 'cum' => 1, 'cuo' => 1, 'cup' => 1, 'cuq' => 1, 'cur' => 1, 'cus' => 1, 'cut' => 1, 'cuu' => 1, 'cuv' => 1, 'cuw' => 1, 'cux' => 1, 'cvg' => 1, 'cvn' => 1, 'cwa' => 1, 'cwb' => 1, 'cwe' => 1, 'cwg' => 1, 'cwt' => 1, 'cya' => 1, 'cyb' => 1, 'cyo' => 1, 'czk' => 1, 'czn' => 1, 'czt' => 1, 'daa' => 1, 'dac' => 1, 'dad' => 1, 'dae' => 1, 'daf' => 1, 'dag' => 1, 'dah' => 1, 'dai' => 1, 'daj' => 1, 'dak' => 1, 'dal' => 1, 'dam' => 1, 'dao' => 1, 'dap' => 1, 'daq' => 1, 'dar' => 1, 'das' => 1, 'dau' => 1, 'dav' => 1, 'daw' => 1, 'dax' => 1, 'day' => 1, 'daz' => 1, 'dba' => 1, 'dbb' => 1, 'dbd' => 1, 'dbe' => 1, 'dbf' => 1, 'dbg' => 1, 'dbi' => 1, 'dbj' => 1, 'dbl' => 1, 'dbm' => 1, 'dbn' => 1, 'dbo' => 1, 'dbp' => 1, 'dbq' => 1, 'dbr' => 1, 'dbu' => 1, 'dbv' => 1, 'dby' => 1, 'dcc' => 1, 'dcr' => 1, 'ddd' => 1, 'dde' => 1, 'ddg' => 1, 'ddi' => 1, 'ddj' => 1, 'ddn' => 1, 'ddo' => 1, 'dds' => 1, 'ddw' => 1, 'dec' => 1, 'ded' => 1, 'dee' => 1, 'def' => 1, 'deg' => 1, 'deh' => 1, 'dei' => 1, 'dek' => 1, 'del' => 1, 'dem' => 1, 'den' => 1, 'dep' => 1, 'deq' => 1, 'der' => 1, 'des' => 1, 'dev' => 1, 'dez' => 1, 'dga' => 1, 'dgb' => 1, 'dgc' => 1, 'dgd' => 1, 'dge' => 1, 'dgg' => 1, 'dgh' => 1, 'dgi' => 1, 'dgk' => 1, 'dgn' => 1, 'dgr' => 1, 'dgs' => 1, 'dgu' => 1, 'dgx' => 1, 'dgz' => 1, 'dha' => 1, 'dhg' => 1, 'dhi' => 1, 'dhl' => 1, 'dhm' => 1, 'dhn' => 1, 'dho' => 1, 'dhr' => 1, 'dhs' => 1, 'dhu' => 1, 'dhv' => 1, 'dhw' => 1, 'dia' => 1, 'dic' => 1, 'did' => 1, 'dif' => 1, 'dig' => 1, 'dih' => 1, 'dii' => 1, 'dij' => 1, 'dil' => 1, 'dim' => 1, 'din' => 1, 'dio' => 1, 'dir' => 1, 'dis' => 1, 'dit' => 1, 'diu' => 1, 'dix' => 1, 'diy' => 1, 'diz' => 1, 'djb' => 1, 'djc' => 1, 'djd' => 1, 'dje' => 1, 'djf' => 1, 'dji' => 1, 'djj' => 1, 'djk' => 1, 'djl' => 1, 'djm' => 1, 'djn' => 1, 'djo' => 1, 'djr' => 1, 'dju' => 1, 'djw' => 1, 'dka' => 1, 'dkk' => 1, 'dkl' => 1, 'dkr' => 1, 'dkx' => 1, 'dlg' => 1, 'dlm' => 1, 'dln' => 1, 'dma' => 1, 'dmc' => 1, 'dme' => 1, 'dmg' => 1, 'dmk' => 1, 'dml' => 1, 'dmm' => 1, 'dmn' => 1, 'dmo' => 1, 'dmr' => 1, 'dms' => 1, 'dmu' => 1, 'dmv' => 1, 'dmx' => 1, 'dmy' => 1, 'dna' => 1, 'dnd' => 1, 'dne' => 1, 'dng' => 1, 'dni' => 1, 'dnk' => 1, 'dnn' => 1, 'dnr' => 1, 'dnt' => 1, 'dnu' => 1, 'dnw' => 1, 'dny' => 1, 'doa' => 1, 'dob' => 1, 'doc' => 1, 'doe' => 1, 'dof' => 1, 'doh' => 1, 'doi' => 1, 'dok' => 1, 'dol' => 1, 'don' => 1, 'doo' => 1, 'dop' => 1, 'doq' => 1, 'dor' => 1, 'dos' => 1, 'dot' => 1, 'dov' => 1, 'dow' => 1, 'dox' => 1, 'doy' => 1, 'doz' => 1, 'dpp' => 1, 'dra' => 1, 'drb' => 1, 'drd' => 1, 'dre' => 1, 'drg' => 1, 'drh' => 1, 'dri' => 1, 'drl' => 1, 'drn' => 1, 'dro' => 1, 'drq' => 1, 'drr' => 1, 'drs' => 1, 'drt' => 1, 'dru' => 1, 'drw' => 1, 'dry' => 1, 'dsb' => 1, 'dse' => 1, 'dsh' => 1, 'dsi' => 1, 'dsl' => 1, 'dsn' => 1, 'dso' => 1, 'dsq' => 1, 'dta' => 1, 'dtb' => 1, 'dti' => 1, 'dtk' => 1, 'dtm' => 1, 'dtp' => 1, 'dtr' => 1, 'dts' => 1, 'dtt' => 1, 'dtu' => 1, 'dua' => 1, 'dub' => 1, 'duc' => 1, 'dud' => 1, 'due' => 1, 'duf' => 1, 'dug' => 1, 'duh' => 1, 'dui' => 1, 'duj' => 1, 'duk' => 1, 'dul' => 1, 'dum' => 1, 'dun' => 1, 'duo' => 1, 'duq' => 1, 'dur' => 1, 'dus' => 1, 'duu' => 1, 'duv' => 1, 'duw' => 1, 'dux' => 1, 'duy' => 1, 'duz' => 1, 'dva' => 1, 'dwa' => 1, 'dwl' => 1, 'dwr' => 1, 'dws' => 1, 'dww' => 1, 'dya' => 1, 'dyb' => 1, 'dyd' => 1, 'dyg' => 1, 'dyi' => 1, 'dym' => 1, 'dyn' => 1, 'dyo' => 1, 'dyu' => 1, 'dyy' => 1, 'dza' => 1, 'dzd' => 1, 'dzg' => 1, 'dzl' => 1, 'dzn' => 1, 'ebg' => 1, 'ebo' => 1, 'ebr' => 1, 'ebu' => 1, 'ecr' => 1, 'ecs' => 1, 'ecy' => 1, 'eee' => 1, 'efa' => 1, 'efe' => 1, 'efi' => 1, 'ega' => 1, 'egl' => 1, 'ego' => 1, 'egx' => 1, 'egy' => 1, 'ehu' => 1, 'eip' => 1, 'eit' => 1, 'eiv' => 1, 'eja' => 1, 'eka' => 1, 'eke' => 1, 'ekg' => 1, 'eki' => 1, 'ekl' => 1, 'ekm' => 1, 'eko' => 1, 'ekp' => 1, 'ekr' => 1, 'eky' => 1, 'ele' => 1, 'elh' => 1, 'eli' => 1, 'elk' => 1, 'elm' => 1, 'elo' => 1, 'elp' => 1, 'elu' => 1, 'elx' => 1, 'ema' => 1, 'emb' => 1, 'eme' => 1, 'emg' => 1, 'emi' => 1, 'emm' => 1, 'emn' => 1, 'emo' => 1, 'emp' => 1, 'ems' => 1, 'emu' => 1, 'emw' => 1, 'emy' => 1, 'ena' => 1, 'enc' => 1, 'end' => 1, 'enf' => 1, 'enh' => 1, 'enm' => 1, 'enn' => 1, 'eno' => 1, 'enq' => 1, 'enr' => 1, 'enu' => 1, 'env' => 1, 'enw' => 1, 'eot' => 1, 'epi' => 1, 'era' => 1, 'erg' => 1, 'erh' => 1, 'eri' => 1, 'erk' => 1, 'ero' => 1, 'err' => 1, 'ers' => 1, 'ert' => 1, 'erw' => 1, 'ese' => 1, 'esh' => 1, 'esl' => 1, 'esm' => 1, 'esn' => 1, 'eso' => 1, 'esq' => 1, 'ess' => 1, 'esu' => 1, 'esx' => 1, 'etb' => 1, 'etc' => 1, 'eth' => 1, 'etn' => 1, 'eto' => 1, 'etr' => 1, 'ets' => 1, 'ett' => 1, 'etu' => 1, 'etx' => 1, 'etz' => 1, 'euq' => 1, 'eve' => 1, 'evh' => 1, 'evn' => 1, 'ewo' => 1, 'ext' => 1, 'eya' => 1, 'eze' => 1, 'faa' => 1, 'fab' => 1, 'fad' => 1, 'faf' => 1, 'fag' => 1, 'fah' => 1, 'fai' => 1, 'faj' => 1, 'fak' => 1, 'fal' => 1, 'fam' => 1, 'fan' => 1, 'fap' => 1, 'far' => 1, 'fau' => 1, 'fax' => 1, 'fay' => 1, 'faz' => 1, 'fcs' => 1, 'fer' => 1, 'ffi' => 1, 'fgr' => 1, 'fia' => 1, 'fie' => 1, 'fil' => 1, 'fip' => 1, 'fir' => 1, 'fit' => 1, 'fiu' => 1, 'fiw' => 1, 'fkv' => 1, 'fla' => 1, 'flh' => 1, 'fli' => 1, 'fll' => 1, 'fln' => 1, 'flr' => 1, 'fly' => 1, 'fmp' => 1, 'fmu' => 1, 'fng' => 1, 'fni' => 1, 'fod' => 1, 'foi' => 1, 'fom' => 1, 'fon' => 1, 'for' => 1, 'fos' => 1, 'fox' => 1, 'fpe' => 1, 'fqs' => 1, 'frc' => 1, 'frd' => 1, 'frk' => 1, 'frm' => 1, 'fro' => 1, 'frp' => 1, 'frq' => 1, 'frr' => 1, 'frs' => 1, 'frt' => 1, 'fse' => 1, 'fsl' => 1, 'fss' => 1, 'fud' => 1, 'fuj' => 1, 'fum' => 1, 'fun' => 1, 'fur' => 1, 'fut' => 1, 'fuu' => 1, 'fuy' => 1, 'fvr' => 1, 'fwa' => 1, 'fwe' => 1, 'gaa' => 1, 'gab' => 1, 'gad' => 1, 'gae' => 1, 'gaf' => 1, 'gag' => 1, 'gah' => 1, 'gai' => 1, 'gaj' => 1, 'gak' => 1, 'gal' => 1, 'gam' => 1, 'gao' => 1, 'gap' => 1, 'gaq' => 1, 'gar' => 1, 'gas' => 1, 'gat' => 1, 'gau' => 1, 'gav' => 1, 'gaw' => 1, 'gay' => 1, 'gba' => 1, 'gbb' => 1, 'gbc' => 1, 'gbd' => 1, 'gbe' => 1, 'gbf' => 1, 'gbg' => 1, 'gbh' => 1, 'gbi' => 1, 'gbj' => 1, 'gbk' => 1, 'gbl' => 1, 'gbm' => 1, 'gbn' => 1, 'gbr' => 1, 'gbs' => 1, 'gbu' => 1, 'gbv' => 1, 'gbx' => 1, 'gby' => 1, 'gbz' => 1, 'gcc' => 1, 'gcd' => 1, 'gce' => 1, 'gcf' => 1, 'gcl' => 1, 'gcn' => 1, 'gcr' => 1, 'gct' => 1, 'gdb' => 1, 'gdc' => 1, 'gdd' => 1, 'gde' => 1, 'gdf' => 1, 'gdg' => 1, 'gdh' => 1, 'gdi' => 1, 'gdj' => 1, 'gdk' => 1, 'gdl' => 1, 'gdm' => 1, 'gdn' => 1, 'gdo' => 1, 'gdq' => 1, 'gdr' => 1, 'gdu' => 1, 'gdx' => 1, 'gea' => 1, 'geb' => 1, 'ged' => 1, 'geg' => 1, 'geh' => 1, 'gei' => 1, 'gej' => 1, 'gek' => 1, 'gel' => 1, 'gem' => 1, 'geq' => 1, 'ges' => 1, 'gew' => 1, 'gex' => 1, 'gey' => 1, 'gez' => 1, 'gfk' => 1, 'gft' => 1, 'gga' => 1, 'ggb' => 1, 'ggd' => 1, 'gge' => 1, 'ggg' => 1, 'ggk' => 1, 'ggl' => 1, 'ggn' => 1, 'ggr' => 1, 'ggt' => 1, 'ggu' => 1, 'ggw' => 1, 'gha' => 1, 'ghc' => 1, 'ghe' => 1, 'ghh' => 1, 'ghk' => 1, 'ghl' => 1, 'ghn' => 1, 'gho' => 1, 'ghr' => 1, 'ghs' => 1, 'ght' => 1, 'gia' => 1, 'gib' => 1, 'gic' => 1, 'gid' => 1, 'gig' => 1, 'gil' => 1, 'gim' => 1, 'gin' => 1, 'gio' => 1, 'gip' => 1, 'giq' => 1, 'gir' => 1, 'gis' => 1, 'git' => 1, 'giw' => 1, 'gix' => 1, 'giy' => 1, 'giz' => 1, 'gji' => 1, 'gjk' => 1, 'gjn' => 1, 'gka' => 1, 'gke' => 1, 'gkn' => 1, 'glc' => 1, 'gld' => 1, 'glh' => 1, 'gli' => 1, 'glj' => 1, 'glk' => 1, 'glo' => 1, 'glr' => 1, 'glu' => 1, 'glw' => 1, 'gly' => 1, 'gma' => 1, 'gmb' => 1, 'gmd' => 1, 'gme' => 1, 'gmh' => 1, 'gml' => 1, 'gmn' => 1, 'gmq' => 1, 'gmu' => 1, 'gmv' => 1, 'gmw' => 1, 'gmx' => 1, 'gmy' => 1, 'gna' => 1, 'gnb' => 1, 'gnc' => 1, 'gnd' => 1, 'gne' => 1, 'gng' => 1, 'gnh' => 1, 'gni' => 1, 'gnk' => 1, 'gnl' => 1, 'gnm' => 1, 'gnn' => 1, 'gnq' => 1, 'gnr' => 1, 'gnt' => 1, 'gnu' => 1, 'gnz' => 1, 'goa' => 1, 'gob' => 1, 'goc' => 1, 'god' => 1, 'goe' => 1, 'gof' => 1, 'gog' => 1, 'goh' => 1, 'goi' => 1, 'goj' => 1, 'gok' => 1, 'gol' => 1, 'gon' => 1, 'goo' => 1, 'gop' => 1, 'goq' => 1, 'gor' => 1, 'gos' => 1, 'got' => 1, 'gou' => 1, 'gow' => 1, 'gox' => 1, 'goy' => 1, 'goz' => 1, 'gpa' => 1, 'gpn' => 1, 'gqa' => 1, 'gqi' => 1, 'gqn' => 1, 'gqr' => 1, 'gra' => 1, 'grb' => 1, 'grc' => 1, 'grd' => 1, 'grg' => 1, 'grh' => 1, 'gri' => 1, 'grk' => 1, 'grm' => 1, 'gro' => 1, 'grq' => 1, 'grr' => 1, 'grs' => 1, 'grt' => 1, 'gru' => 1, 'grw' => 1, 'grx' => 1, 'grz' => 1, 'gse' => 1, 'gsg' => 1, 'gsl' => 1, 'gsm' => 1, 'gsn' => 1, 'gsp' => 1, 'gss' => 1, 'gsw' => 1, 'gta' => 1, 'gti' => 1, 'gua' => 1, 'gub' => 1, 'guc' => 1, 'gud' => 1, 'gue' => 1, 'guf' => 1, 'guh' => 1, 'guk' => 1, 'gul' => 1, 'gum' => 1, 'guo' => 1, 'gup' => 1, 'guq' => 1, 'gur' => 1, 'gus' => 1, 'gut' => 1, 'guu' => 1, 'guv' => 1, 'guw' => 1, 'gux' => 1, 'guz' => 1, 'gva' => 1, 'gvc' => 1, 'gve' => 1, 'gvf' => 1, 'gvj' => 1, 'gvl' => 1, 'gvm' => 1, 'gvn' => 1, 'gvo' => 1, 'gvp' => 1, 'gvr' => 1, 'gvs' => 1, 'gvy' => 1, 'gwa' => 1, 'gwb' => 1, 'gwc' => 1, 'gwd' => 1, 'gwe' => 1, 'gwf' => 1, 'gwg' => 1, 'gwi' => 1, 'gwj' => 1, 'gwn' => 1, 'gwr' => 1, 'gwt' => 1, 'gwu' => 1, 'gww' => 1, 'gwx' => 1, 'gxx' => 1, 'gyb' => 1, 'gyd' => 1, 'gye' => 1, 'gyf' => 1, 'gyg' => 1, 'gyi' => 1, 'gyl' => 1, 'gym' => 1, 'gyn' => 1, 'gyr' => 1, 'gyy' => 1, 'gza' => 1, 'gzi' => 1, 'gzn' => 1, 'haa' => 1, 'hab' => 1, 'hac' => 1, 'had' => 1, 'haf' => 1, 'hag' => 1, 'hah' => 1, 'hai' => 1, 'haj' => 1, 'hal' => 1, 'ham' => 1, 'han' => 1, 'hao' => 1, 'hap' => 1, 'haq' => 1, 'har' => 1, 'has' => 1, 'hav' => 1, 'haw' => 1, 'hay' => 1, 'haz' => 1, 'hba' => 1, 'hbb' => 1, 'hbn' => 1, 'hbo' => 1, 'hbu' => 1, 'hca' => 1, 'hch' => 1, 'hds' => 1, 'hdy' => 1, 'hed' => 1, 'heg' => 1, 'heh' => 1, 'hei' => 1, 'hem' => 1, 'hgm' => 1, 'hgw' => 1, 'hhi' => 1, 'hhr' => 1, 'hhy' => 1, 'hia' => 1, 'hib' => 1, 'hid' => 1, 'hif' => 1, 'hig' => 1, 'hih' => 1, 'hii' => 1, 'hij' => 1, 'hik' => 1, 'hil' => 1, 'him' => 1, 'hio' => 1, 'hir' => 1, 'hit' => 1, 'hiw' => 1, 'hix' => 1, 'hka' => 1, 'hke' => 1, 'hkk' => 1, 'hks' => 1, 'hla' => 1, 'hlb' => 1, 'hld' => 1, 'hle' => 1, 'hlt' => 1, 'hlu' => 1, 'hmb' => 1, 'hmf' => 1, 'hmk' => 1, 'hmn' => 1, 'hmr' => 1, 'hmt' => 1, 'hmu' => 1, 'hmv' => 1, 'hmx' => 1, 'hmz' => 1, 'hna' => 1, 'hne' => 1, 'hnh' => 1, 'hni' => 1, 'hnn' => 1, 'hns' => 1, 'hnu' => 1, 'hoa' => 1, 'hob' => 1, 'hoc' => 1, 'hod' => 1, 'hoe' => 1, 'hoh' => 1, 'hoi' => 1, 'hok' => 1, 'hol' => 1, 'hom' => 1, 'hoo' => 1, 'hop' => 1, 'hor' => 1, 'hos' => 1, 'hot' => 1, 'hov' => 1, 'how' => 1, 'hoy' => 1, 'hoz' => 1, 'hpo' => 1, 'hps' => 1, 'hra' => 1, 'hre' => 1, 'hrk' => 1, 'hro' => 1, 'hrr' => 1, 'hrt' => 1, 'hru' => 1, 'hrx' => 1, 'hrz' => 1, 'hsb' => 1, 'hsh' => 1, 'hsl' => 1, 'hss' => 1, 'hti' => 1, 'hto' => 1, 'hts' => 1, 'htu' => 1, 'htx' => 1, 'hub' => 1, 'huc' => 1, 'hud' => 1, 'hue' => 1, 'huf' => 1, 'hug' => 1, 'huh' => 1, 'hui' => 1, 'huk' => 1, 'hul' => 1, 'hum' => 1, 'huo' => 1, 'hup' => 1, 'huq' => 1, 'hur' => 1, 'hus' => 1, 'hut' => 1, 'huu' => 1, 'huv' => 1, 'huw' => 1, 'hux' => 1, 'huy' => 1, 'huz' => 1, 'hvc' => 1, 'hve' => 1, 'hvk' => 1, 'hvn' => 1, 'hvv' => 1, 'hwa' => 1, 'hwc' => 1, 'hwo' => 1, 'hya' => 1, 'hyx' => 1, 'iai' => 1, 'ian' => 1, 'iap' => 1, 'iar' => 1, 'iba' => 1, 'ibb' => 1, 'ibd' => 1, 'ibe' => 1, 'ibg' => 1, 'ibi' => 1, 'ibl' => 1, 'ibm' => 1, 'ibn' => 1, 'ibr' => 1, 'ibu' => 1, 'iby' => 1, 'ica' => 1, 'ich' => 1, 'icl' => 1, 'icr' => 1, 'idb' => 1, 'idc' => 1, 'idd' => 1, 'ide' => 1, 'idi' => 1, 'idr' => 1, 'ids' => 1, 'idt' => 1, 'idu' => 1, 'ifa' => 1, 'ifb' => 1, 'ife' => 1, 'iff' => 1, 'ifk' => 1, 'ifm' => 1, 'ifu' => 1, 'ify' => 1, 'igb' => 1, 'ige' => 1, 'igg' => 1, 'igl' => 1, 'igm' => 1, 'ign' => 1, 'igo' => 1, 'igs' => 1, 'igw' => 1, 'ihb' => 1, 'ihi' => 1, 'ihp' => 1, 'iir' => 1, 'ijc' => 1, 'ije' => 1, 'ijj' => 1, 'ijn' => 1, 'ijo' => 1, 'ijs' => 1, 'iki' => 1, 'ikk' => 1, 'ikl' => 1, 'iko' => 1, 'ikp' => 1, 'ikv' => 1, 'ikw' => 1, 'ikx' => 1, 'ikz' => 1, 'ila' => 1, 'ilb' => 1, 'ilg' => 1, 'ili' => 1, 'ilk' => 1, 'ill' => 1, 'ilo' => 1, 'ils' => 1, 'ilu' => 1, 'ilv' => 1, 'ilw' => 1, 'ima' => 1, 'ime' => 1, 'imi' => 1, 'iml' => 1, 'imn' => 1, 'imo' => 1, 'imr' => 1, 'ims' => 1, 'imy' => 1, 'inb' => 1, 'inc' => 1, 'ine' => 1, 'ing' => 1, 'inh' => 1, 'inj' => 1, 'inl' => 1, 'inm' => 1, 'inn' => 1, 'ino' => 1, 'inp' => 1, 'ins' => 1, 'int' => 1, 'inz' => 1, 'ior' => 1, 'iou' => 1, 'iow' => 1, 'ipi' => 1, 'ipo' => 1, 'iqu' => 1, 'ira' => 1, 'ire' => 1, 'irh' => 1, 'iri' => 1, 'irk' => 1, 'irn' => 1, 'iro' => 1, 'irr' => 1, 'iru' => 1, 'irx' => 1, 'iry' => 1, 'isa' => 1, 'isc' => 1, 'isd' => 1, 'ise' => 1, 'isg' => 1, 'ish' => 1, 'isi' => 1, 'ism' => 1, 'isn' => 1, 'iso' => 1, 'isr' => 1, 'ist' => 1, 'isu' => 1, 'itb' => 1, 'itc' => 1, 'ite' => 1, 'iti' => 1, 'itk' => 1, 'itl' => 1, 'itm' => 1, 'ito' => 1, 'itr' => 1, 'its' => 1, 'itt' => 1, 'itv' => 1, 'itw' => 1, 'itx' => 1, 'ity' => 1, 'itz' => 1, 'ium' => 1, 'ivb' => 1, 'ivv' => 1, 'iwk' => 1, 'iwm' => 1, 'iwo' => 1, 'iws' => 1, 'ixc' => 1, 'ixl' => 1, 'iya' => 1, 'iyo' => 1, 'iyx' => 1, 'izh' => 1, 'izi' => 1, 'izr' => 1, 'jaa' => 1, 'jab' => 1, 'jac' => 1, 'jad' => 1, 'jae' => 1, 'jaf' => 1, 'jah' => 1, 'jaj' => 1, 'jal' => 1, 'jam' => 1, 'jao' => 1, 'jaq' => 1, 'jar' => 1, 'jas' => 1, 'jau' => 1, 'jay' => 1, 'jaz' => 1, 'jbe' => 1, 'jbj' => 1, 'jbn' => 1, 'jbo' => 1, 'jbr' => 1, 'jbt' => 1, 'jbu' => 1, 'jcs' => 1, 'jct' => 1, 'jda' => 1, 'jdg' => 1, 'jdt' => 1, 'jeb' => 1, 'jee' => 1, 'jeg' => 1, 'jeh' => 1, 'jei' => 1, 'jek' => 1, 'jel' => 1, 'jen' => 1, 'jer' => 1, 'jet' => 1, 'jeu' => 1, 'jgb' => 1, 'jge' => 1, 'jgo' => 1, 'jhi' => 1, 'jhs' => 1, 'jia' => 1, 'jib' => 1, 'jic' => 1, 'jid' => 1, 'jie' => 1, 'jig' => 1, 'jih' => 1, 'jii' => 1, 'jil' => 1, 'jim' => 1, 'jio' => 1, 'jiq' => 1, 'jit' => 1, 'jiu' => 1, 'jiv' => 1, 'jiy' => 1, 'jko' => 1, 'jku' => 1, 'jle' => 1, 'jma' => 1, 'jmb' => 1, 'jmc' => 1, 'jmd' => 1, 'jmi' => 1, 'jml' => 1, 'jmn' => 1, 'jmr' => 1, 'jms' => 1, 'jmx' => 1, 'jna' => 1, 'jnd' => 1, 'jng' => 1, 'jni' => 1, 'jnj' => 1, 'jnl' => 1, 'jns' => 1, 'job' => 1, 'jod' => 1, 'jor' => 1, 'jos' => 1, 'jow' => 1, 'jpa' => 1, 'jpr' => 1, 'jpx' => 1, 'jqr' => 1, 'jra' => 1, 'jrb' => 1, 'jrr' => 1, 'jrt' => 1, 'jru' => 1, 'jsl' => 1, 'jua' => 1, 'jub' => 1, 'juc' => 1, 'jud' => 1, 'juh' => 1, 'juk' => 1, 'jul' => 1, 'jum' => 1, 'jun' => 1, 'juo' => 1, 'jup' => 1, 'jur' => 1, 'jus' => 1, 'jut' => 1, 'juu' => 1, 'juw' => 1, 'juy' => 1, 'jvd' => 1, 'jvn' => 1, 'jwi' => 1, 'jya' => 1, 'jyy' => 1, 'kaa' => 1, 'kab' => 1, 'kac' => 1, 'kad' => 1, 'kae' => 1, 'kaf' => 1, 'kag' => 1, 'kah' => 1, 'kai' => 1, 'kaj' => 1, 'kak' => 1, 'kam' => 1, 'kao' => 1, 'kap' => 1, 'kaq' => 1, 'kar' => 1, 'kav' => 1, 'kaw' => 1, 'kax' => 1, 'kay' => 1, 'kba' => 1, 'kbb' => 1, 'kbc' => 1, 'kbd' => 1, 'kbe' => 1, 'kbf' => 1, 'kbg' => 1, 'kbh' => 1, 'kbi' => 1, 'kbj' => 1, 'kbk' => 1, 'kbl' => 1, 'kbm' => 1, 'kbn' => 1, 'kbo' => 1, 'kbp' => 1, 'kbq' => 1, 'kbr' => 1, 'kbs' => 1, 'kbt' => 1, 'kbu' => 1, 'kbv' => 1, 'kbw' => 1, 'kbx' => 1, 'kbz' => 1, 'kca' => 1, 'kcb' => 1, 'kcc' => 1, 'kcd' => 1, 'kce' => 1, 'kcf' => 1, 'kcg' => 1, 'kch' => 1, 'kci' => 1, 'kcj' => 1, 'kck' => 1, 'kcl' => 1, 'kcm' => 1, 'kcn' => 1, 'kco' => 1, 'kcp' => 1, 'kcq' => 1, 'kcr' => 1, 'kcs' => 1, 'kct' => 1, 'kcu' => 1, 'kcv' => 1, 'kcw' => 1, 'kcx' => 1, 'kcy' => 1, 'kcz' => 1, 'kda' => 1, 'kdc' => 1, 'kdd' => 1, 'kde' => 1, 'kdf' => 1, 'kdg' => 1, 'kdh' => 1, 'kdi' => 1, 'kdj' => 1, 'kdk' => 1, 'kdl' => 1, 'kdm' => 1, 'kdn' => 1, 'kdo' => 1, 'kdp' => 1, 'kdq' => 1, 'kdr' => 1, 'kdt' => 1, 'kdu' => 1, 'kdv' => 1, 'kdw' => 1, 'kdx' => 1, 'kdy' => 1, 'kdz' => 1, 'kea' => 1, 'keb' => 1, 'kec' => 1, 'ked' => 1, 'kee' => 1, 'kef' => 1, 'keg' => 1, 'keh' => 1, 'kei' => 1, 'kej' => 1, 'kek' => 1, 'kel' => 1, 'kem' => 1, 'ken' => 1, 'keo' => 1, 'kep' => 1, 'keq' => 1, 'ker' => 1, 'kes' => 1, 'ket' => 1, 'keu' => 1, 'kev' => 1, 'kew' => 1, 'kex' => 1, 'key' => 1, 'kez' => 1, 'kfa' => 1, 'kfb' => 1, 'kfc' => 1, 'kfd' => 1, 'kfe' => 1, 'kff' => 1, 'kfg' => 1, 'kfh' => 1, 'kfi' => 1, 'kfj' => 1, 'kfk' => 1, 'kfl' => 1, 'kfm' => 1, 'kfn' => 1, 'kfo' => 1, 'kfp' => 1, 'kfq' => 1, 'kfr' => 1, 'kfs' => 1, 'kft' => 1, 'kfu' => 1, 'kfv' => 1, 'kfw' => 1, 'kfx' => 1, 'kfy' => 1, 'kfz' => 1, 'kga' => 1, 'kgb' => 1, 'kgc' => 1, 'kgd' => 1, 'kge' => 1, 'kgf' => 1, 'kgg' => 1, 'kgh' => 1, 'kgi' => 1, 'kgj' => 1, 'kgk' => 1, 'kgl' => 1, 'kgm' => 1, 'kgn' => 1, 'kgo' => 1, 'kgp' => 1, 'kgq' => 1, 'kgr' => 1, 'kgs' => 1, 'kgt' => 1, 'kgu' => 1, 'kgv' => 1, 'kgw' => 1, 'kgx' => 1, 'kgy' => 1, 'kha' => 1, 'khb' => 1, 'khc' => 1, 'khd' => 1, 'khe' => 1, 'khf' => 1, 'khg' => 1, 'khh' => 1, 'khi' => 1, 'khj' => 1, 'khl' => 1, 'khn' => 1, 'kho' => 1, 'khp' => 1, 'khq' => 1, 'khr' => 1, 'khs' => 1, 'kht' => 1, 'khu' => 1, 'khv' => 1, 'khw' => 1, 'khx' => 1, 'khy' => 1, 'khz' => 1, 'kia' => 1, 'kib' => 1, 'kic' => 1, 'kid' => 1, 'kie' => 1, 'kif' => 1, 'kig' => 1, 'kih' => 1, 'kii' => 1, 'kij' => 1, 'kil' => 1, 'kim' => 1, 'kio' => 1, 'kip' => 1, 'kiq' => 1, 'kis' => 1, 'kit' => 1, 'kiv' => 1, 'kiw' => 1, 'kix' => 1, 'kiy' => 1, 'kiz' => 1, 'kja' => 1, 'kjb' => 1, 'kjc' => 1, 'kjd' => 1, 'kje' => 1, 'kjf' => 1, 'kjg' => 1, 'kjh' => 1, 'kji' => 1, 'kjj' => 1, 'kjk' => 1, 'kjl' => 1, 'kjm' => 1, 'kjn' => 1, 'kjo' => 1, 'kjp' => 1, 'kjq' => 1, 'kjr' => 1, 'kjs' => 1, 'kjt' => 1, 'kju' => 1, 'kjx' => 1, 'kjy' => 1, 'kjz' => 1, 'kka' => 1, 'kkb' => 1, 'kkc' => 1, 'kkd' => 1, 'kke' => 1, 'kkf' => 1, 'kkg' => 1, 'kkh' => 1, 'kki' => 1, 'kkj' => 1, 'kkk' => 1, 'kkl' => 1, 'kkm' => 1, 'kkn' => 1, 'kko' => 1, 'kkp' => 1, 'kkq' => 1, 'kkr' => 1, 'kks' => 1, 'kkt' => 1, 'kku' => 1, 'kkv' => 1, 'kkw' => 1, 'kkx' => 1, 'kky' => 1, 'kkz' => 1, 'kla' => 1, 'klb' => 1, 'klc' => 1, 'kld' => 1, 'kle' => 1, 'klf' => 1, 'klg' => 1, 'klh' => 1, 'kli' => 1, 'klj' => 1, 'klk' => 1, 'kll' => 1, 'klm' => 1, 'kln' => 1, 'klo' => 1, 'klp' => 1, 'klq' => 1, 'klr' => 1, 'kls' => 1, 'klt' => 1, 'klu' => 1, 'klv' => 1, 'klw' => 1, 'klx' => 1, 'kly' => 1, 'klz' => 1, 'kma' => 1, 'kmb' => 1, 'kmc' => 1, 'kmd' => 1, 'kme' => 1, 'kmf' => 1, 'kmg' => 1, 'kmh' => 1, 'kmi' => 1, 'kmj' => 1, 'kmk' => 1, 'kml' => 1, 'kmm' => 1, 'kmn' => 1, 'kmo' => 1, 'kmp' => 1, 'kmq' => 1, 'kms' => 1, 'kmt' => 1, 'kmu' => 1, 'kmv' => 1, 'kmw' => 1, 'kmx' => 1, 'kmy' => 1, 'kmz' => 1, 'kna' => 1, 'knb' => 1, 'knd' => 1, 'kne' => 1, 'knf' => 1, 'kni' => 1, 'knj' => 1, 'knk' => 1, 'knl' => 1, 'knm' => 1, 'kno' => 1, 'knp' => 1, 'knq' => 1, 'knr' => 1, 'kns' => 1, 'knt' => 1, 'knu' => 1, 'knv' => 1, 'knw' => 1, 'knx' => 1, 'kny' => 1, 'knz' => 1, 'koa' => 1, 'koc' => 1, 'kod' => 1, 'koe' => 1, 'kof' => 1, 'kog' => 1, 'koh' => 1, 'koj' => 1, 'kok' => 1, 'kol' => 1, 'koo' => 1, 'kop' => 1, 'koq' => 1, 'kos' => 1, 'kot' => 1, 'kou' => 1, 'kov' => 1, 'kow' => 1, 'kox' => 1, 'koy' => 1, 'koz' => 1, 'kpa' => 1, 'kpb' => 1, 'kpc' => 1, 'kpd' => 1, 'kpe' => 1, 'kpf' => 1, 'kpg' => 1, 'kph' => 1, 'kpi' => 1, 'kpj' => 1, 'kpk' => 1, 'kpl' => 1, 'kpm' => 1, 'kpn' => 1, 'kpo' => 1, 'kpp' => 1, 'kpq' => 1, 'kpr' => 1, 'kps' => 1, 'kpt' => 1, 'kpu' => 1, 'kpw' => 1, 'kpx' => 1, 'kpy' => 1, 'kpz' => 1, 'kqa' => 1, 'kqb' => 1, 'kqc' => 1, 'kqd' => 1, 'kqe' => 1, 'kqf' => 1, 'kqg' => 1, 'kqh' => 1, 'kqi' => 1, 'kqj' => 1, 'kqk' => 1, 'kql' => 1, 'kqm' => 1, 'kqn' => 1, 'kqo' => 1, 'kqp' => 1, 'kqq' => 1, 'kqr' => 1, 'kqs' => 1, 'kqt' => 1, 'kqu' => 1, 'kqv' => 1, 'kqw' => 1, 'kqx' => 1, 'kqy' => 1, 'kqz' => 1, 'kra' => 1, 'krb' => 1, 'krc' => 1, 'krd' => 1, 'kre' => 1, 'krf' => 1, 'krh' => 1, 'kri' => 1, 'krj' => 1, 'krk' => 1, 'krl' => 1, 'krm' => 1, 'krn' => 1, 'kro' => 1, 'krp' => 1, 'krr' => 1, 'krs' => 1, 'kru' => 1, 'krv' => 1, 'krw' => 1, 'krx' => 1, 'kry' => 1, 'krz' => 1, 'ksa' => 1, 'ksb' => 1, 'ksc' => 1, 'ksd' => 1, 'kse' => 1, 'ksf' => 1, 'ksg' => 1, 'ksh' => 1, 'ksi' => 1, 'ksj' => 1, 'ksk' => 1, 'ksl' => 1, 'ksm' => 1, 'ksn' => 1, 'kso' => 1, 'ksp' => 1, 'ksq' => 1, 'ksr' => 1, 'kss' => 1, 'kst' => 1, 'ksu' => 1, 'ksv' => 1, 'ksw' => 1, 'ksx' => 1, 'ksy' => 1, 'ksz' => 1, 'kta' => 1, 'ktb' => 1, 'ktc' => 1, 'ktd' => 1, 'kte' => 1, 'ktf' => 1, 'ktg' => 1, 'kth' => 1, 'kti' => 1, 'ktj' => 1, 'ktk' => 1, 'ktl' => 1, 'ktm' => 1, 'ktn' => 1, 'kto' => 1, 'ktp' => 1, 'ktq' => 1, 'ktr' => 1, 'kts' => 1, 'ktt' => 1, 'ktu' => 1, 'ktv' => 1, 'ktw' => 1, 'ktx' => 1, 'kty' => 1, 'ktz' => 1, 'kub' => 1, 'kuc' => 1, 'kud' => 1, 'kue' => 1, 'kuf' => 1, 'kug' => 1, 'kuh' => 1, 'kui' => 1, 'kuj' => 1, 'kuk' => 1, 'kul' => 1, 'kum' => 1, 'kun' => 1, 'kuo' => 1, 'kup' => 1, 'kuq' => 1, 'kus' => 1, 'kut' => 1, 'kuu' => 1, 'kuv' => 1, 'kuw' => 1, 'kux' => 1, 'kuy' => 1, 'kuz' => 1, 'kva' => 1, 'kvc' => 1, 'kvd' => 1, 'kve' => 1, 'kvf' => 1, 'kvg' => 1, 'kvh' => 1, 'kvi' => 1, 'kvj' => 1, 'kvk' => 1, 'kvl' => 1, 'kvm' => 1, 'kvn' => 1, 'kvo' => 1, 'kvp' => 1, 'kvq' => 1, 'kvs' => 1, 'kvt' => 1, 'kvu' => 1, 'kvv' => 1, 'kvw' => 1, 'kvx' => 1, 'kvy' => 1, 'kvz' => 1, 'kwa' => 1, 'kwb' => 1, 'kwc' => 1, 'kwd' => 1, 'kwe' => 1, 'kwf' => 1, 'kwg' => 1, 'kwh' => 1, 'kwi' => 1, 'kwj' => 1, 'kwk' => 1, 'kwl' => 1, 'kwm' => 1, 'kwn' => 1, 'kwo' => 1, 'kwp' => 1, 'kwq' => 1, 'kwr' => 1, 'kws' => 1, 'kwt' => 1, 'kwu' => 1, 'kwv' => 1, 'kww' => 1, 'kwx' => 1, 'kwz' => 1, 'kxa' => 1, 'kxb' => 1, 'kxc' => 1, 'kxe' => 1, 'kxf' => 1, 'kxh' => 1, 'kxi' => 1, 'kxj' => 1, 'kxk' => 1, 'kxl' => 1, 'kxm' => 1, 'kxn' => 1, 'kxo' => 1, 'kxp' => 1, 'kxq' => 1, 'kxr' => 1, 'kxs' => 1, 'kxt' => 1, 'kxu' => 1, 'kxv' => 1, 'kxw' => 1, 'kxx' => 1, 'kxy' => 1, 'kxz' => 1, 'kya' => 1, 'kyb' => 1, 'kyc' => 1, 'kyd' => 1, 'kye' => 1, 'kyf' => 1, 'kyg' => 1, 'kyh' => 1, 'kyi' => 1, 'kyj' => 1, 'kyk' => 1, 'kyl' => 1, 'kym' => 1, 'kyn' => 1, 'kyo' => 1, 'kyp' => 1, 'kyq' => 1, 'kyr' => 1, 'kys' => 1, 'kyt' => 1, 'kyu' => 1, 'kyv' => 1, 'kyw' => 1, 'kyx' => 1, 'kyy' => 1, 'kyz' => 1, 'kza' => 1, 'kzb' => 1, 'kzc' => 1, 'kzd' => 1, 'kze' => 1, 'kzf' => 1, 'kzg' => 1, 'kzh' => 1, 'kzi' => 1, 'kzj' => 1, 'kzk' => 1, 'kzl' => 1, 'kzm' => 1, 'kzn' => 1, 'kzo' => 1, 'kzp' => 1, 'kzq' => 1, 'kzr' => 1, 'kzs' => 1, 'kzt' => 1, 'kzu' => 1, 'kzv' => 1, 'kzw' => 1, 'kzx' => 1, 'kzy' => 1, 'kzz' => 1, 'laa' => 1, 'lab' => 1, 'lac' => 1, 'lad' => 1, 'lae' => 1, 'laf' => 1, 'lag' => 1, 'lah' => 1, 'lai' => 1, 'laj' => 1, 'lak' => 1, 'lal' => 1, 'lam' => 1, 'lan' => 1, 'lap' => 1, 'laq' => 1, 'lar' => 1, 'las' => 1, 'lau' => 1, 'law' => 1, 'lax' => 1, 'lay' => 1, 'laz' => 1, 'lba' => 1, 'lbb' => 1, 'lbc' => 1, 'lbe' => 1, 'lbf' => 1, 'lbg' => 1, 'lbi' => 1, 'lbj' => 1, 'lbm' => 1, 'lbn' => 1, 'lbo' => 1, 'lbq' => 1, 'lbr' => 1, 'lbs' => 1, 'lbt' => 1, 'lbu' => 1, 'lbv' => 1, 'lbw' => 1, 'lbx' => 1, 'lby' => 1, 'lbz' => 1, 'lcc' => 1, 'lcd' => 1, 'lch' => 1, 'lcl' => 1, 'lcm' => 1, 'lcp' => 1, 'lcq' => 1, 'lcs' => 1, 'ldb' => 1, 'ldd' => 1, 'ldg' => 1, 'ldh' => 1, 'ldj' => 1, 'ldk' => 1, 'ldl' => 1, 'ldm' => 1, 'ldn' => 1, 'ldo' => 1, 'ldp' => 1, 'ldq' => 1, 'lea' => 1, 'leb' => 1, 'lec' => 1, 'led' => 1, 'lee' => 1, 'lef' => 1, 'leg' => 1, 'leh' => 1, 'lei' => 1, 'lej' => 1, 'lek' => 1, 'lel' => 1, 'lem' => 1, 'len' => 1, 'leo' => 1, 'lep' => 1, 'leq' => 1, 'ler' => 1, 'les' => 1, 'let' => 1, 'leu' => 1, 'lev' => 1, 'lew' => 1, 'lex' => 1, 'ley' => 1, 'lez' => 1, 'lfa' => 1, 'lfn' => 1, 'lga' => 1, 'lgb' => 1, 'lgg' => 1, 'lgh' => 1, 'lgi' => 1, 'lgk' => 1, 'lgl' => 1, 'lgm' => 1, 'lgn' => 1, 'lgq' => 1, 'lgr' => 1, 'lgt' => 1, 'lgu' => 1, 'lgz' => 1, 'lha' => 1, 'lhh' => 1, 'lhi' => 1, 'lhl' => 1, 'lhm' => 1, 'lhn' => 1, 'lhp' => 1, 'lhs' => 1, 'lht' => 1, 'lhu' => 1, 'lia' => 1, 'lib' => 1, 'lic' => 1, 'lid' => 1, 'lie' => 1, 'lif' => 1, 'lig' => 1, 'lih' => 1, 'lii' => 1, 'lij' => 1, 'lik' => 1, 'lil' => 1, 'lio' => 1, 'lip' => 1, 'liq' => 1, 'lir' => 1, 'lis' => 1, 'liu' => 1, 'liv' => 1, 'lix' => 1, 'liy' => 1, 'liz' => 1, 'lje' => 1, 'lji' => 1, 'ljl' => 1, 'ljp' => 1, 'lka' => 1, 'lkc' => 1, 'lkd' => 1, 'lke' => 1, 'lkh' => 1, 'lki' => 1, 'lkj' => 1, 'lkl' => 1, 'lkn' => 1, 'lkr' => 1, 'lkt' => 1, 'lky' => 1, 'lla' => 1, 'llb' => 1, 'llc' => 1, 'lld' => 1, 'lle' => 1, 'llf' => 1, 'llg' => 1, 'llh' => 1, 'lli' => 1, 'llk' => 1, 'lll' => 1, 'llm' => 1, 'lln' => 1, 'llo' => 1, 'llp' => 1, 'llq' => 1, 'lls' => 1, 'llu' => 1, 'llx' => 1, 'lma' => 1, 'lmb' => 1, 'lmc' => 1, 'lmd' => 1, 'lme' => 1, 'lmf' => 1, 'lmg' => 1, 'lmh' => 1, 'lmi' => 1, 'lmj' => 1, 'lmk' => 1, 'lml' => 1, 'lmm' => 1, 'lmn' => 1, 'lmo' => 1, 'lmp' => 1, 'lmq' => 1, 'lmr' => 1, 'lmu' => 1, 'lmv' => 1, 'lmw' => 1, 'lmx' => 1, 'lmy' => 1, 'lmz' => 1, 'lna' => 1, 'lnb' => 1, 'lnd' => 1, 'lng' => 1, 'lnh' => 1, 'lni' => 1, 'lnj' => 1, 'lnl' => 1, 'lnm' => 1, 'lnn' => 1, 'lno' => 1, 'lns' => 1, 'lnu' => 1, 'lnz' => 1, 'loa' => 1, 'lob' => 1, 'loc' => 1, 'loe' => 1, 'lof' => 1, 'log' => 1, 'loh' => 1, 'loi' => 1, 'loj' => 1, 'lok' => 1, 'lol' => 1, 'lom' => 1, 'lon' => 1, 'loo' => 1, 'lop' => 1, 'loq' => 1, 'lor' => 1, 'los' => 1, 'lot' => 1, 'lou' => 1, 'lov' => 1, 'low' => 1, 'lox' => 1, 'loy' => 1, 'loz' => 1, 'lpa' => 1, 'lpe' => 1, 'lpn' => 1, 'lpo' => 1, 'lpx' => 1, 'lra' => 1, 'lrc' => 1, 'lre' => 1, 'lrg' => 1, 'lrk' => 1, 'lrl' => 1, 'lrn' => 1, 'lro' => 1, 'lrr' => 1, 'lrt' => 1, 'lrv' => 1, 'lrz' => 1, 'lsa' => 1, 'lsd' => 1, 'lse' => 1, 'lsg' => 1, 'lsh' => 1, 'lsi' => 1, 'lsl' => 1, 'lso' => 1, 'lsp' => 1, 'lsr' => 1, 'lss' => 1, 'lst' => 1, 'ltc' => 1, 'lti' => 1, 'ltn' => 1, 'ltu' => 1, 'lua' => 1, 'luc' => 1, 'lud' => 1, 'lue' => 1, 'luf' => 1, 'lui' => 1, 'luj' => 1, 'luk' => 1, 'lul' => 1, 'lum' => 1, 'lun' => 1, 'luo' => 1, 'lup' => 1, 'luq' => 1, 'lur' => 1, 'lus' => 1, 'lut' => 1, 'luu' => 1, 'luv' => 1, 'luw' => 1, 'luy' => 1, 'luz' => 1, 'lva' => 1, 'lvk' => 1, 'lvu' => 1, 'lwa' => 1, 'lwe' => 1, 'lwh' => 1, 'lwl' => 1, 'lwm' => 1, 'lwo' => 1, 'lwt' => 1, 'lww' => 1, 'lya' => 1, 'lyg' => 1, 'lyn' => 1, 'lzl' => 1, 'lzn' => 1, 'lzz' => 1, 'maa' => 1, 'mab' => 1, 'mad' => 1, 'mae' => 1, 'maf' => 1, 'mag' => 1, 'mai' => 1, 'maj' => 1, 'mak' => 1, 'mam' => 1, 'man' => 1, 'map' => 1, 'maq' => 1, 'mas' => 1, 'mat' => 1, 'mau' => 1, 'mav' => 1, 'maw' => 1, 'maz' => 1, 'mba' => 1, 'mbb' => 1, 'mbc' => 1, 'mbd' => 1, 'mbe' => 1, 'mbf' => 1, 'mbh' => 1, 'mbi' => 1, 'mbj' => 1, 'mbk' => 1, 'mbl' => 1, 'mbm' => 1, 'mbn' => 1, 'mbo' => 1, 'mbp' => 1, 'mbq' => 1, 'mbr' => 1, 'mbs' => 1, 'mbt' => 1, 'mbu' => 1, 'mbv' => 1, 'mbw' => 1, 'mbx' => 1, 'mby' => 1, 'mbz' => 1, 'mca' => 1, 'mcb' => 1, 'mcc' => 1, 'mcd' => 1, 'mce' => 1, 'mcf' => 1, 'mcg' => 1, 'mch' => 1, 'mci' => 1, 'mcj' => 1, 'mck' => 1, 'mcl' => 1, 'mcm' => 1, 'mcn' => 1, 'mco' => 1, 'mcp' => 1, 'mcq' => 1, 'mcr' => 1, 'mcs' => 1, 'mct' => 1, 'mcu' => 1, 'mcv' => 1, 'mcw' => 1, 'mcx' => 1, 'mcy' => 1, 'mcz' => 1, 'mda' => 1, 'mdb' => 1, 'mdc' => 1, 'mdd' => 1, 'mde' => 1, 'mdf' => 1, 'mdg' => 1, 'mdh' => 1, 'mdi' => 1, 'mdj' => 1, 'mdk' => 1, 'mdl' => 1, 'mdm' => 1, 'mdn' => 1, 'mdp' => 1, 'mdq' => 1, 'mdr' => 1, 'mds' => 1, 'mdt' => 1, 'mdu' => 1, 'mdv' => 1, 'mdw' => 1, 'mdx' => 1, 'mdy' => 1, 'mdz' => 1, 'mea' => 1, 'meb' => 1, 'mec' => 1, 'med' => 1, 'mee' => 1, 'mef' => 1, 'meg' => 1, 'meh' => 1, 'mei' => 1, 'mej' => 1, 'mek' => 1, 'mel' => 1, 'mem' => 1, 'men' => 1, 'mep' => 1, 'meq' => 1, 'mer' => 1, 'mes' => 1, 'met' => 1, 'meu' => 1, 'mev' => 1, 'mew' => 1, 'mey' => 1, 'mez' => 1, 'mfc' => 1, 'mfd' => 1, 'mfe' => 1, 'mff' => 1, 'mfg' => 1, 'mfh' => 1, 'mfi' => 1, 'mfj' => 1, 'mfk' => 1, 'mfl' => 1, 'mfm' => 1, 'mfn' => 1, 'mfo' => 1, 'mfp' => 1, 'mfq' => 1, 'mfr' => 1, 'mfs' => 1, 'mft' => 1, 'mfu' => 1, 'mfv' => 1, 'mfw' => 1, 'mfx' => 1, 'mfy' => 1, 'mfz' => 1, 'mga' => 1, 'mgb' => 1, 'mgc' => 1, 'mgd' => 1, 'mge' => 1, 'mgf' => 1, 'mgg' => 1, 'mgh' => 1, 'mgi' => 1, 'mgj' => 1, 'mgk' => 1, 'mgl' => 1, 'mgm' => 1, 'mgn' => 1, 'mgo' => 1, 'mgp' => 1, 'mgq' => 1, 'mgr' => 1, 'mgs' => 1, 'mgt' => 1, 'mgu' => 1, 'mgv' => 1, 'mgw' => 1, 'mgx' => 1, 'mgy' => 1, 'mgz' => 1, 'mha' => 1, 'mhb' => 1, 'mhc' => 1, 'mhd' => 1, 'mhe' => 1, 'mhf' => 1, 'mhg' => 1, 'mhh' => 1, 'mhi' => 1, 'mhj' => 1, 'mhk' => 1, 'mhl' => 1, 'mhm' => 1, 'mhn' => 1, 'mho' => 1, 'mhp' => 1, 'mhq' => 1, 'mhs' => 1, 'mht' => 1, 'mhu' => 1, 'mhw' => 1, 'mhx' => 1, 'mhy' => 1, 'mhz' => 1, 'mia' => 1, 'mib' => 1, 'mic' => 1, 'mid' => 1, 'mie' => 1, 'mif' => 1, 'mig' => 1, 'mih' => 1, 'mii' => 1, 'mij' => 1, 'mik' => 1, 'mil' => 1, 'mim' => 1, 'mio' => 1, 'mip' => 1, 'miq' => 1, 'mir' => 1, 'mit' => 1, 'miu' => 1, 'miw' => 1, 'mix' => 1, 'miy' => 1, 'miz' => 1, 'mja' => 1, 'mjc' => 1, 'mjd' => 1, 'mje' => 1, 'mjg' => 1, 'mjh' => 1, 'mji' => 1, 'mjj' => 1, 'mjk' => 1, 'mjl' => 1, 'mjm' => 1, 'mjn' => 1, 'mjo' => 1, 'mjp' => 1, 'mjq' => 1, 'mjr' => 1, 'mjs' => 1, 'mjt' => 1, 'mju' => 1, 'mjv' => 1, 'mjw' => 1, 'mjx' => 1, 'mjy' => 1, 'mjz' => 1, 'mka' => 1, 'mkb' => 1, 'mkc' => 1, 'mke' => 1, 'mkf' => 1, 'mkg' => 1, 'mkh' => 1, 'mki' => 1, 'mkj' => 1, 'mkk' => 1, 'mkl' => 1, 'mkm' => 1, 'mkn' => 1, 'mko' => 1, 'mkp' => 1, 'mkq' => 1, 'mkr' => 1, 'mks' => 1, 'mkt' => 1, 'mkv' => 1, 'mkw' => 1, 'mkx' => 1, 'mky' => 1, 'mkz' => 1, 'mla' => 1, 'mlb' => 1, 'mlc' => 1, 'mld' => 1, 'mle' => 1, 'mlf' => 1, 'mlh' => 1, 'mli' => 1, 'mlj' => 1, 'mlk' => 1, 'mll' => 1, 'mlm' => 1, 'mln' => 1, 'mlo' => 1, 'mlp' => 1, 'mlr' => 1, 'mls' => 1, 'mlu' => 1, 'mlv' => 1, 'mlw' => 1, 'mlx' => 1, 'mlz' => 1, 'mma' => 1, 'mmb' => 1, 'mmc' => 1, 'mmd' => 1, 'mme' => 1, 'mmf' => 1, 'mmg' => 1, 'mmh' => 1, 'mmi' => 1, 'mmj' => 1, 'mmk' => 1, 'mml' => 1, 'mmm' => 1, 'mmn' => 1, 'mmo' => 1, 'mmp' => 1, 'mmq' => 1, 'mmt' => 1, 'mmu' => 1, 'mmv' => 1, 'mmw' => 1, 'mmx' => 1, 'mmy' => 1, 'mmz' => 1, 'mna' => 1, 'mnb' => 1, 'mnc' => 1, 'mnd' => 1, 'mne' => 1, 'mnf' => 1, 'mng' => 1, 'mnh' => 1, 'mni' => 1, 'mnj' => 1, 'mnl' => 1, 'mnm' => 1, 'mnn' => 1, 'mno' => 1, 'mnq' => 1, 'mnr' => 1, 'mns' => 1, 'mnt' => 1, 'mnu' => 1, 'mnv' => 1, 'mnw' => 1, 'mnx' => 1, 'mny' => 1, 'mnz' => 1, 'moa' => 1, 'moc' => 1, 'mod' => 1, 'moe' => 1, 'mof' => 1, 'mog' => 1, 'moh' => 1, 'moi' => 1, 'moj' => 1, 'mok' => 1, 'mom' => 1, 'moo' => 1, 'mop' => 1, 'moq' => 1, 'mor' => 1, 'mos' => 1, 'mot' => 1, 'mou' => 1, 'mov' => 1, 'mow' => 1, 'mox' => 1, 'moy' => 1, 'moz' => 1, 'mpa' => 1, 'mpb' => 1, 'mpc' => 1, 'mpd' => 1, 'mpe' => 1, 'mpg' => 1, 'mph' => 1, 'mpi' => 1, 'mpj' => 1, 'mpk' => 1, 'mpl' => 1, 'mpm' => 1, 'mpn' => 1, 'mpo' => 1, 'mpp' => 1, 'mpq' => 1, 'mpr' => 1, 'mps' => 1, 'mpt' => 1, 'mpu' => 1, 'mpv' => 1, 'mpw' => 1, 'mpx' => 1, 'mpy' => 1, 'mpz' => 1, 'mqa' => 1, 'mqb' => 1, 'mqc' => 1, 'mqe' => 1, 'mqf' => 1, 'mqh' => 1, 'mqi' => 1, 'mqj' => 1, 'mqk' => 1, 'mql' => 1, 'mqm' => 1, 'mqn' => 1, 'mqo' => 1, 'mqp' => 1, 'mqq' => 1, 'mqr' => 1, 'mqs' => 1, 'mqt' => 1, 'mqu' => 1, 'mqv' => 1, 'mqw' => 1, 'mqx' => 1, 'mqy' => 1, 'mqz' => 1, 'mra' => 1, 'mrb' => 1, 'mrc' => 1, 'mrd' => 1, 'mre' => 1, 'mrf' => 1, 'mrg' => 1, 'mrh' => 1, 'mrk' => 1, 'mrl' => 1, 'mrm' => 1, 'mrn' => 1, 'mro' => 1, 'mrp' => 1, 'mrq' => 1, 'mrr' => 1, 'mrs' => 1, 'mrt' => 1, 'mru' => 1, 'mrv' => 1, 'mrw' => 1, 'mrx' => 1, 'mry' => 1, 'mrz' => 1, 'msb' => 1, 'msd' => 1, 'mse' => 1, 'msf' => 1, 'msg' => 1, 'msj' => 1, 'msk' => 1, 'msl' => 1, 'msm' => 1, 'msn' => 1, 'mso' => 1, 'msp' => 1, 'msq' => 1, 'msr' => 1, 'mss' => 1, 'mst' => 1, 'msu' => 1, 'msv' => 1, 'msw' => 1, 'msx' => 1, 'msy' => 1, 'msz' => 1, 'mta' => 1, 'mtb' => 1, 'mtc' => 1, 'mtd' => 1, 'mte' => 1, 'mtf' => 1, 'mtg' => 1, 'mth' => 1, 'mti' => 1, 'mtj' => 1, 'mtk' => 1, 'mtl' => 1, 'mtm' => 1, 'mtn' => 1, 'mto' => 1, 'mtp' => 1, 'mtq' => 1, 'mts' => 1, 'mtt' => 1, 'mtu' => 1, 'mtv' => 1, 'mtw' => 1, 'mtx' => 1, 'mty' => 1, 'mua' => 1, 'mub' => 1, 'muc' => 1, 'mud' => 1, 'mue' => 1, 'mug' => 1, 'muh' => 1, 'muj' => 1, 'muk' => 1, 'mum' => 1, 'mun' => 1, 'muo' => 1, 'mur' => 1, 'mus' => 1, 'mut' => 1, 'muu' => 1, 'muv' => 1, 'mux' => 1, 'muy' => 1, 'muz' => 1, 'mva' => 1, 'mvb' => 1, 'mvd' => 1, 'mvg' => 1, 'mvh' => 1, 'mvi' => 1, 'mvk' => 1, 'mvl' => 1, 'mvm' => 1, 'mvn' => 1, 'mvo' => 1, 'mvp' => 1, 'mvq' => 1, 'mvr' => 1, 'mvs' => 1, 'mvt' => 1, 'mvu' => 1, 'mvv' => 1, 'mvw' => 1, 'mvx' => 1, 'mvy' => 1, 'mvz' => 1, 'mwa' => 1, 'mwb' => 1, 'mwc' => 1, 'mwd' => 1, 'mwe' => 1, 'mwf' => 1, 'mwg' => 1, 'mwh' => 1, 'mwi' => 1, 'mwj' => 1, 'mwl' => 1, 'mwm' => 1, 'mwn' => 1, 'mwo' => 1, 'mwp' => 1, 'mwq' => 1, 'mwr' => 1, 'mws' => 1, 'mwt' => 1, 'mwu' => 1, 'mwv' => 1, 'mwx' => 1, 'mwy' => 1, 'mwz' => 1, 'mxa' => 1, 'mxb' => 1, 'mxc' => 1, 'mxd' => 1, 'mxe' => 1, 'mxf' => 1, 'mxg' => 1, 'mxh' => 1, 'mxi' => 1, 'mxj' => 1, 'mxk' => 1, 'mxl' => 1, 'mxm' => 1, 'mxn' => 1, 'mxo' => 1, 'mxp' => 1, 'mxq' => 1, 'mxr' => 1, 'mxs' => 1, 'mxt' => 1, 'mxu' => 1, 'mxv' => 1, 'mxw' => 1, 'mxx' => 1, 'mxy' => 1, 'mxz' => 1, 'myb' => 1, 'myc' => 1, 'myd' => 1, 'mye' => 1, 'myf' => 1, 'myg' => 1, 'myh' => 1, 'myi' => 1, 'myj' => 1, 'myk' => 1, 'myl' => 1, 'mym' => 1, 'myn' => 1, 'myo' => 1, 'myp' => 1, 'myr' => 1, 'mys' => 1, 'myt' => 1, 'myu' => 1, 'myv' => 1, 'myw' => 1, 'myx' => 1, 'myy' => 1, 'myz' => 1, 'mza' => 1, 'mzb' => 1, 'mzc' => 1, 'mzd' => 1, 'mze' => 1, 'mzg' => 1, 'mzh' => 1, 'mzi' => 1, 'mzj' => 1, 'mzk' => 1, 'mzl' => 1, 'mzm' => 1, 'mzn' => 1, 'mzo' => 1, 'mzp' => 1, 'mzq' => 1, 'mzr' => 1, 'mzs' => 1, 'mzt' => 1, 'mzu' => 1, 'mzv' => 1, 'mzw' => 1, 'mzx' => 1, 'mzy' => 1, 'mzz' => 1, 'naa' => 1, 'nab' => 1, 'nac' => 1, 'nad' => 1, 'nae' => 1, 'naf' => 1, 'nag' => 1, 'nah' => 1, 'nai' => 1, 'naj' => 1, 'nak' => 1, 'nal' => 1, 'nam' => 1, 'nao' => 1, 'nap' => 1, 'naq' => 1, 'nar' => 1, 'nas' => 1, 'nat' => 1, 'naw' => 1, 'nax' => 1, 'nay' => 1, 'naz' => 1, 'nba' => 1, 'nbb' => 1, 'nbc' => 1, 'nbd' => 1, 'nbe' => 1, 'nbf' => 1, 'nbg' => 1, 'nbh' => 1, 'nbi' => 1, 'nbj' => 1, 'nbk' => 1, 'nbm' => 1, 'nbn' => 1, 'nbo' => 1, 'nbp' => 1, 'nbq' => 1, 'nbr' => 1, 'nbs' => 1, 'nbt' => 1, 'nbu' => 1, 'nbv' => 1, 'nbw' => 1, 'nbx' => 1, 'nby' => 1, 'nca' => 1, 'ncb' => 1, 'ncc' => 1, 'ncd' => 1, 'nce' => 1, 'ncf' => 1, 'ncg' => 1, 'nch' => 1, 'nci' => 1, 'ncj' => 1, 'nck' => 1, 'ncl' => 1, 'ncm' => 1, 'ncn' => 1, 'nco' => 1, 'ncp' => 1, 'ncr' => 1, 'ncs' => 1, 'nct' => 1, 'ncu' => 1, 'ncx' => 1, 'ncz' => 1, 'nda' => 1, 'ndb' => 1, 'ndc' => 1, 'ndd' => 1, 'ndf' => 1, 'ndg' => 1, 'ndh' => 1, 'ndi' => 1, 'ndj' => 1, 'ndk' => 1, 'ndl' => 1, 'ndm' => 1, 'ndn' => 1, 'ndp' => 1, 'ndq' => 1, 'ndr' => 1, 'nds' => 1, 'ndt' => 1, 'ndu' => 1, 'ndv' => 1, 'ndw' => 1, 'ndx' => 1, 'ndy' => 1, 'ndz' => 1, 'nea' => 1, 'neb' => 1, 'nec' => 1, 'ned' => 1, 'nee' => 1, 'nef' => 1, 'neg' => 1, 'neh' => 1, 'nei' => 1, 'nej' => 1, 'nek' => 1, 'nem' => 1, 'nen' => 1, 'neo' => 1, 'neq' => 1, 'ner' => 1, 'nes' => 1, 'net' => 1, 'nev' => 1, 'new' => 1, 'nex' => 1, 'ney' => 1, 'nez' => 1, 'nfa' => 1, 'nfd' => 1, 'nfl' => 1, 'nfr' => 1, 'nfu' => 1, 'nga' => 1, 'ngb' => 1, 'ngc' => 1, 'ngd' => 1, 'nge' => 1, 'ngf' => 1, 'ngg' => 1, 'ngh' => 1, 'ngi' => 1, 'ngj' => 1, 'ngk' => 1, 'ngl' => 1, 'ngm' => 1, 'ngn' => 1, 'ngo' => 1, 'ngp' => 1, 'ngq' => 1, 'ngr' => 1, 'ngs' => 1, 'ngt' => 1, 'ngu' => 1, 'ngv' => 1, 'ngw' => 1, 'ngx' => 1, 'ngy' => 1, 'ngz' => 1, 'nha' => 1, 'nhb' => 1, 'nhc' => 1, 'nhe' => 1, 'nhf' => 1, 'nhg' => 1, 'nhh' => 1, 'nhi' => 1, 'nhk' => 1, 'nhm' => 1, 'nhn' => 1, 'nho' => 1, 'nhp' => 1, 'nhq' => 1, 'nhr' => 1, 'nht' => 1, 'nhu' => 1, 'nhv' => 1, 'nhw' => 1, 'nhx' => 1, 'nhy' => 1, 'nhz' => 1, 'nia' => 1, 'nib' => 1, 'nic' => 1, 'nid' => 1, 'nie' => 1, 'nif' => 1, 'nig' => 1, 'nih' => 1, 'nii' => 1, 'nij' => 1, 'nik' => 1, 'nil' => 1, 'nim' => 1, 'nin' => 1, 'nio' => 1, 'nir' => 1, 'nis' => 1, 'nit' => 1, 'niu' => 1, 'niv' => 1, 'niw' => 1, 'nix' => 1, 'niy' => 1, 'niz' => 1, 'nja' => 1, 'njb' => 1, 'njd' => 1, 'njh' => 1, 'nji' => 1, 'njj' => 1, 'njl' => 1, 'njm' => 1, 'njn' => 1, 'njo' => 1, 'njr' => 1, 'njs' => 1, 'njt' => 1, 'nju' => 1, 'njx' => 1, 'njy' => 1, 'nka' => 1, 'nkb' => 1, 'nkc' => 1, 'nkd' => 1, 'nke' => 1, 'nkf' => 1, 'nkg' => 1, 'nkh' => 1, 'nki' => 1, 'nkj' => 1, 'nkk' => 1, 'nkm' => 1, 'nkn' => 1, 'nko' => 1, 'nkp' => 1, 'nkr' => 1, 'nks' => 1, 'nkt' => 1, 'nku' => 1, 'nkv' => 1, 'nkw' => 1, 'nkx' => 1, 'nkz' => 1, 'nla' => 1, 'nlc' => 1, 'nlg' => 1, 'nli' => 1, 'nlj' => 1, 'nlk' => 1, 'nll' => 1, 'nln' => 1, 'nlo' => 1, 'nlr' => 1, 'nlu' => 1, 'nlv' => 1, 'nlx' => 1, 'nly' => 1, 'nlz' => 1, 'nma' => 1, 'nmb' => 1, 'nmc' => 1, 'nmd' => 1, 'nme' => 1, 'nmf' => 1, 'nmg' => 1, 'nmh' => 1, 'nmi' => 1, 'nmj' => 1, 'nmk' => 1, 'nml' => 1, 'nmm' => 1, 'nmn' => 1, 'nmo' => 1, 'nmp' => 1, 'nmq' => 1, 'nmr' => 1, 'nms' => 1, 'nmt' => 1, 'nmu' => 1, 'nmv' => 1, 'nmw' => 1, 'nmx' => 1, 'nmy' => 1, 'nmz' => 1, 'nna' => 1, 'nnb' => 1, 'nnc' => 1, 'nnd' => 1, 'nne' => 1, 'nnf' => 1, 'nng' => 1, 'nnh' => 1, 'nni' => 1, 'nnj' => 1, 'nnk' => 1, 'nnl' => 1, 'nnm' => 1, 'nnn' => 1, 'nnp' => 1, 'nnq' => 1, 'nnr' => 1, 'nns' => 1, 'nnt' => 1, 'nnu' => 1, 'nnv' => 1, 'nnw' => 1, 'nnx' => 1, 'nny' => 1, 'nnz' => 1, 'noa' => 1, 'noc' => 1, 'nod' => 1, 'noe' => 1, 'nof' => 1, 'nog' => 1, 'noh' => 1, 'noi' => 1, 'nok' => 1, 'nom' => 1, 'non' => 1, 'noo' => 1, 'nop' => 1, 'noq' => 1, 'nos' => 1, 'not' => 1, 'nou' => 1, 'nov' => 1, 'now' => 1, 'noy' => 1, 'noz' => 1, 'npa' => 1, 'npb' => 1, 'nph' => 1, 'npl' => 1, 'npn' => 1, 'npo' => 1, 'nps' => 1, 'npu' => 1, 'npy' => 1, 'nqg' => 1, 'nqk' => 1, 'nqm' => 1, 'nqn' => 1, 'nqo' => 1, 'nra' => 1, 'nrb' => 1, 'nrc' => 1, 'nre' => 1, 'nrg' => 1, 'nri' => 1, 'nrl' => 1, 'nrm' => 1, 'nrn' => 1, 'nrp' => 1, 'nrr' => 1, 'nrt' => 1, 'nrx' => 1, 'nrz' => 1, 'nsa' => 1, 'nsc' => 1, 'nsd' => 1, 'nse' => 1, 'nsg' => 1, 'nsh' => 1, 'nsi' => 1, 'nsk' => 1, 'nsl' => 1, 'nsm' => 1, 'nsn' => 1, 'nso' => 1, 'nsp' => 1, 'nsq' => 1, 'nsr' => 1, 'nss' => 1, 'nst' => 1, 'nsu' => 1, 'nsv' => 1, 'nsw' => 1, 'nsx' => 1, 'nsy' => 1, 'nsz' => 1, 'nte' => 1, 'nti' => 1, 'ntj' => 1, 'ntk' => 1, 'ntm' => 1, 'nto' => 1, 'ntp' => 1, 'ntr' => 1, 'nts' => 1, 'ntu' => 1, 'ntw' => 1, 'nty' => 1, 'ntz' => 1, 'nua' => 1, 'nub' => 1, 'nuc' => 1, 'nud' => 1, 'nue' => 1, 'nuf' => 1, 'nug' => 1, 'nuh' => 1, 'nui' => 1, 'nuj' => 1, 'nul' => 1, 'num' => 1, 'nun' => 1, 'nuo' => 1, 'nup' => 1, 'nuq' => 1, 'nur' => 1, 'nus' => 1, 'nut' => 1, 'nuu' => 1, 'nuv' => 1, 'nuw' => 1, 'nux' => 1, 'nuy' => 1, 'nuz' => 1, 'nvh' => 1, 'nvm' => 1, 'nwa' => 1, 'nwb' => 1, 'nwc' => 1, 'nwe' => 1, 'nwi' => 1, 'nwm' => 1, 'nwr' => 1, 'nwx' => 1, 'nwy' => 1, 'nxa' => 1, 'nxd' => 1, 'nxe' => 1, 'nxg' => 1, 'nxi' => 1, 'nxl' => 1, 'nxm' => 1, 'nxn' => 1, 'nxr' => 1, 'nxu' => 1, 'nxx' => 1, 'nyb' => 1, 'nyc' => 1, 'nye' => 1, 'nyf' => 1, 'nyg' => 1, 'nyh' => 1, 'nyi' => 1, 'nyj' => 1, 'nyk' => 1, 'nyl' => 1, 'nym' => 1, 'nyn' => 1, 'nyo' => 1, 'nyp' => 1, 'nyq' => 1, 'nyr' => 1, 'nys' => 1, 'nyt' => 1, 'nyu' => 1, 'nyv' => 1, 'nyw' => 1, 'nyx' => 1, 'nyy' => 1, 'nza' => 1, 'nzb' => 1, 'nzi' => 1, 'nzk' => 1, 'nzm' => 1, 'nzs' => 1, 'nzu' => 1, 'nzy' => 1, 'oaa' => 1, 'oac' => 1, 'oar' => 1, 'oav' => 1, 'obi' => 1, 'obl' => 1, 'obm' => 1, 'obo' => 1, 'obr' => 1, 'obt' => 1, 'obu' => 1, 'oca' => 1, 'och' => 1, 'oco' => 1, 'ocu' => 1, 'oda' => 1, 'odk' => 1, 'odt' => 1, 'odu' => 1, 'ofo' => 1, 'ofs' => 1, 'ofu' => 1, 'ogb' => 1, 'ogc' => 1, 'oge' => 1, 'ogg' => 1, 'ogo' => 1, 'ogu' => 1, 'oht' => 1, 'ohu' => 1, 'oia' => 1, 'oin' => 1, 'ojp' => 1, 'ojv' => 1, 'oka' => 1, 'okb' => 1, 'okd' => 1, 'oke' => 1, 'okh' => 1, 'okj' => 1, 'okk' => 1, 'okl' => 1, 'okm' => 1, 'okn' => 1, 'oko' => 1, 'okr' => 1, 'oks' => 1, 'oku' => 1, 'okv' => 1, 'okx' => 1, 'ola' => 1, 'old' => 1, 'ole' => 1, 'olm' => 1, 'olo' => 1, 'olr' => 1, 'oma' => 1, 'omb' => 1, 'omc' => 1, 'ome' => 1, 'omg' => 1, 'omi' => 1, 'omk' => 1, 'oml' => 1, 'omn' => 1, 'omo' => 1, 'omp' => 1, 'omq' => 1, 'omr' => 1, 'omt' => 1, 'omu' => 1, 'omv' => 1, 'omw' => 1, 'omx' => 1, 'ona' => 1, 'onb' => 1, 'one' => 1, 'ong' => 1, 'oni' => 1, 'onj' => 1, 'onk' => 1, 'onn' => 1, 'ono' => 1, 'onp' => 1, 'onr' => 1, 'ons' => 1, 'ont' => 1, 'onu' => 1, 'onw' => 1, 'onx' => 1, 'ood' => 1, 'oog' => 1, 'oon' => 1, 'oor' => 1, 'oos' => 1, 'opa' => 1, 'opk' => 1, 'opm' => 1, 'opo' => 1, 'opt' => 1, 'opy' => 1, 'ora' => 1, 'ore' => 1, 'org' => 1, 'orh' => 1, 'oro' => 1, 'orr' => 1, 'ort' => 1, 'oru' => 1, 'orv' => 1, 'orw' => 1, 'orx' => 1, 'orz' => 1, 'osa' => 1, 'osc' => 1, 'osi' => 1, 'oso' => 1, 'osp' => 1, 'ost' => 1, 'osu' => 1, 'osx' => 1, 'ota' => 1, 'otb' => 1, 'otd' => 1, 'ote' => 1, 'oti' => 1, 'otk' => 1, 'otl' => 1, 'otm' => 1, 'otn' => 1, 'oto' => 1, 'otq' => 1, 'otr' => 1, 'ots' => 1, 'ott' => 1, 'otu' => 1, 'otx' => 1, 'oty' => 1, 'otz' => 1, 'oua' => 1, 'oub' => 1, 'oue' => 1, 'oui' => 1, 'oum' => 1, 'oun' => 1, 'owi' => 1, 'owl' => 1, 'oyb' => 1, 'oyd' => 1, 'oym' => 1, 'oyy' => 1, 'ozm' => 1, 'paa' => 1, 'pab' => 1, 'pac' => 1, 'pad' => 1, 'pae' => 1, 'paf' => 1, 'pag' => 1, 'pah' => 1, 'pai' => 1, 'pak' => 1, 'pal' => 1, 'pam' => 1, 'pao' => 1, 'pap' => 1, 'paq' => 1, 'par' => 1, 'pas' => 1, 'pat' => 1, 'pau' => 1, 'pav' => 1, 'paw' => 1, 'pax' => 1, 'pay' => 1, 'paz' => 1, 'pbb' => 1, 'pbc' => 1, 'pbe' => 1, 'pbf' => 1, 'pbg' => 1, 'pbh' => 1, 'pbi' => 1, 'pbl' => 1, 'pbn' => 1, 'pbo' => 1, 'pbp' => 1, 'pbr' => 1, 'pbs' => 1, 'pbv' => 1, 'pby' => 1, 'pbz' => 1, 'pca' => 1, 'pcb' => 1, 'pcc' => 1, 'pcd' => 1, 'pce' => 1, 'pcf' => 1, 'pcg' => 1, 'pch' => 1, 'pci' => 1, 'pcj' => 1, 'pck' => 1, 'pcl' => 1, 'pcm' => 1, 'pcn' => 1, 'pcp' => 1, 'pcr' => 1, 'pcw' => 1, 'pda' => 1, 'pdc' => 1, 'pdi' => 1, 'pdn' => 1, 'pdo' => 1, 'pdt' => 1, 'pdu' => 1, 'pea' => 1, 'peb' => 1, 'ped' => 1, 'pee' => 1, 'pef' => 1, 'peg' => 1, 'peh' => 1, 'pei' => 1, 'pej' => 1, 'pek' => 1, 'pem' => 1, 'peo' => 1, 'pep' => 1, 'peq' => 1, 'pev' => 1, 'pex' => 1, 'pey' => 1, 'pez' => 1, 'pfa' => 1, 'pfe' => 1, 'pfl' => 1, 'pgg' => 1, 'pgi' => 1, 'pgk' => 1, 'pgn' => 1, 'pgs' => 1, 'pgu' => 1, 'pgy' => 1, 'pha' => 1, 'phd' => 1, 'phg' => 1, 'phh' => 1, 'phi' => 1, 'phk' => 1, 'phl' => 1, 'phm' => 1, 'phn' => 1, 'pho' => 1, 'phq' => 1, 'pht' => 1, 'phu' => 1, 'phv' => 1, 'phw' => 1, 'pia' => 1, 'pib' => 1, 'pic' => 1, 'pid' => 1, 'pie' => 1, 'pif' => 1, 'pig' => 1, 'pih' => 1, 'pii' => 1, 'pij' => 1, 'pil' => 1, 'pim' => 1, 'pin' => 1, 'pio' => 1, 'pip' => 1, 'pir' => 1, 'pis' => 1, 'pit' => 1, 'piu' => 1, 'piv' => 1, 'piw' => 1, 'pix' => 1, 'piy' => 1, 'piz' => 1, 'pjt' => 1, 'pka' => 1, 'pkb' => 1, 'pkc' => 1, 'pkg' => 1, 'pkh' => 1, 'pkn' => 1, 'pkp' => 1, 'pkr' => 1, 'pks' => 1, 'pkt' => 1, 'pku' => 1, 'pla' => 1, 'plb' => 1, 'plc' => 1, 'pld' => 1, 'ple' => 1, 'plf' => 1, 'plg' => 1, 'plh' => 1, 'plj' => 1, 'plk' => 1, 'pll' => 1, 'pln' => 1, 'plo' => 1, 'plp' => 1, 'plq' => 1, 'plr' => 1, 'pls' => 1, 'plu' => 1, 'plv' => 1, 'plw' => 1, 'ply' => 1, 'plz' => 1, 'pma' => 1, 'pmb' => 1, 'pmc' => 1, 'pme' => 1, 'pmf' => 1, 'pmh' => 1, 'pmi' => 1, 'pmj' => 1, 'pmk' => 1, 'pml' => 1, 'pmm' => 1, 'pmn' => 1, 'pmo' => 1, 'pmq' => 1, 'pmr' => 1, 'pms' => 1, 'pmt' => 1, 'pmw' => 1, 'pmx' => 1, 'pmy' => 1, 'pmz' => 1, 'pna' => 1, 'pnc' => 1, 'pne' => 1, 'png' => 1, 'pnh' => 1, 'pni' => 1, 'pnm' => 1, 'pnn' => 1, 'pno' => 1, 'pnp' => 1, 'pnq' => 1, 'pnr' => 1, 'pns' => 1, 'pnt' => 1, 'pnu' => 1, 'pnv' => 1, 'pnw' => 1, 'pnx' => 1, 'pny' => 1, 'pnz' => 1, 'poc' => 1, 'pod' => 1, 'poe' => 1, 'pof' => 1, 'pog' => 1, 'poh' => 1, 'poi' => 1, 'pok' => 1, 'pom' => 1, 'pon' => 1, 'poo' => 1, 'pop' => 1, 'poq' => 1, 'pos' => 1, 'pot' => 1, 'pov' => 1, 'pow' => 1, 'pox' => 1, 'poy' => 1, 'poz' => 1, 'ppa' => 1, 'ppe' => 1, 'ppi' => 1, 'ppk' => 1, 'ppl' => 1, 'ppm' => 1, 'ppn' => 1, 'ppo' => 1, 'ppp' => 1, 'ppq' => 1, 'ppr' => 1, 'pps' => 1, 'ppt' => 1, 'ppu' => 1, 'pqa' => 1, 'pqe' => 1, 'pqm' => 1, 'pqw' => 1, 'pra' => 1, 'prb' => 1, 'prc' => 1, 'prd' => 1, 'pre' => 1, 'prg' => 1, 'prh' => 1, 'pri' => 1, 'prk' => 1, 'prl' => 1, 'prm' => 1, 'prn' => 1, 'pro' => 1, 'prp' => 1, 'prq' => 1, 'prr' => 1, 'prt' => 1, 'pru' => 1, 'prw' => 1, 'prx' => 1, 'pry' => 1, 'prz' => 1, 'psa' => 1, 'psc' => 1, 'psd' => 1, 'psg' => 1, 'psh' => 1, 'psi' => 1, 'psl' => 1, 'psm' => 1, 'psn' => 1, 'pso' => 1, 'psp' => 1, 'psq' => 1, 'psr' => 1, 'pss' => 1, 'psu' => 1, 'psw' => 1, 'psy' => 1, 'pta' => 1, 'pth' => 1, 'pti' => 1, 'ptn' => 1, 'pto' => 1, 'ptp' => 1, 'ptr' => 1, 'ptt' => 1, 'ptu' => 1, 'ptv' => 1, 'ptw' => 1, 'pty' => 1, 'pua' => 1, 'pub' => 1, 'puc' => 1, 'pud' => 1, 'pue' => 1, 'puf' => 1, 'pug' => 1, 'pui' => 1, 'puj' => 1, 'puk' => 1, 'pum' => 1, 'puo' => 1, 'pup' => 1, 'puq' => 1, 'pur' => 1, 'put' => 1, 'puu' => 1, 'puw' => 1, 'pux' => 1, 'puy' => 1, 'puz' => 1, 'pwa' => 1, 'pwb' => 1, 'pwg' => 1, 'pwm' => 1, 'pwn' => 1, 'pwo' => 1, 'pwr' => 1, 'pww' => 1, 'pxm' => 1, 'pye' => 1, 'pym' => 1, 'pyn' => 1, 'pyu' => 1, 'pyx' => 1, 'pyy' => 1, 'pzn' => 1, 'qua' => 1, 'quc' => 1, 'qui' => 1, 'qum' => 1, 'qun' => 1, 'quq' => 1, 'quv' => 1, 'qvy' => 1, 'qwe' => 1, 'qwm' => 1, 'qwt' => 1, 'qxq' => 1, 'qxs' => 1, 'qya' => 1, 'qyp' => 1, 'raa' => 1, 'rab' => 1, 'rac' => 1, 'rad' => 1, 'raf' => 1, 'rah' => 1, 'rai' => 1, 'raj' => 1, 'rak' => 1, 'ral' => 1, 'ram' => 1, 'ran' => 1, 'rao' => 1, 'rap' => 1, 'raq' => 1, 'rar' => 1, 'ras' => 1, 'rat' => 1, 'rau' => 1, 'rav' => 1, 'raw' => 1, 'rax' => 1, 'ray' => 1, 'raz' => 1, 'rbb' => 1, 'rcf' => 1, 'rdb' => 1, 'rea' => 1, 'reb' => 1, 'ree' => 1, 'reg' => 1, 'rei' => 1, 'rej' => 1, 'rel' => 1, 'rem' => 1, 'ren' => 1, 'rer' => 1, 'res' => 1, 'ret' => 1, 'rey' => 1, 'rga' => 1, 'rge' => 1, 'rgk' => 1, 'rgn' => 1, 'rgr' => 1, 'rgs' => 1, 'rgu' => 1, 'rhg' => 1, 'rhp' => 1, 'ria' => 1, 'rie' => 1, 'rif' => 1, 'ril' => 1, 'rim' => 1, 'rin' => 1, 'rir' => 1, 'rit' => 1, 'riu' => 1, 'rjg' => 1, 'rji' => 1, 'rjs' => 1, 'rka' => 1, 'rkb' => 1, 'rkh' => 1, 'rki' => 1, 'rkm' => 1, 'rkt' => 1, 'rma' => 1, 'rmb' => 1, 'rmd' => 1, 'rme' => 1, 'rmg' => 1, 'rmh' => 1, 'rmi' => 1, 'rmk' => 1, 'rmm' => 1, 'rmp' => 1, 'rmr' => 1, 'rms' => 1, 'rmt' => 1, 'rmu' => 1, 'rmv' => 1, 'rmx' => 1, 'rmz' => 1, 'rna' => 1, 'rnd' => 1, 'rng' => 1, 'rnl' => 1, 'rnn' => 1, 'rnp' => 1, 'rnw' => 1, 'roa' => 1, 'rob' => 1, 'roc' => 1, 'rod' => 1, 'roe' => 1, 'rof' => 1, 'rog' => 1, 'rol' => 1, 'rom' => 1, 'roo' => 1, 'rop' => 1, 'ror' => 1, 'rou' => 1, 'row' => 1, 'rpn' => 1, 'rpt' => 1, 'rri' => 1, 'rro' => 1, 'rsb' => 1, 'rsi' => 1, 'rsl' => 1, 'rth' => 1, 'rtm' => 1, 'rtw' => 1, 'rub' => 1, 'ruc' => 1, 'rue' => 1, 'ruf' => 1, 'rug' => 1, 'ruh' => 1, 'rui' => 1, 'ruk' => 1, 'ruo' => 1, 'rup' => 1, 'ruq' => 1, 'rut' => 1, 'ruu' => 1, 'ruy' => 1, 'ruz' => 1, 'rwa' => 1, 'rwk' => 1, 'rwm' => 1, 'rwo' => 1, 'ryn' => 1, 'rys' => 1, 'ryu' => 1, 'saa' => 1, 'sab' => 1, 'sac' => 1, 'sad' => 1, 'sae' => 1, 'saf' => 1, 'sah' => 1, 'sai' => 1, 'saj' => 1, 'sak' => 1, 'sal' => 1, 'sam' => 1, 'sao' => 1, 'sap' => 1, 'saq' => 1, 'sar' => 1, 'sas' => 1, 'sat' => 1, 'sau' => 1, 'sav' => 1, 'saw' => 1, 'sax' => 1, 'say' => 1, 'saz' => 1, 'sba' => 1, 'sbb' => 1, 'sbc' => 1, 'sbd' => 1, 'sbe' => 1, 'sbf' => 1, 'sbg' => 1, 'sbh' => 1, 'sbi' => 1, 'sbj' => 1, 'sbk' => 1, 'sbl' => 1, 'sbm' => 1, 'sbn' => 1, 'sbo' => 1, 'sbp' => 1, 'sbq' => 1, 'sbr' => 1, 'sbs' => 1, 'sbt' => 1, 'sbu' => 1, 'sbv' => 1, 'sbw' => 1, 'sbx' => 1, 'sby' => 1, 'sbz' => 1, 'sca' => 1, 'scb' => 1, 'sce' => 1, 'scf' => 1, 'scg' => 1, 'sch' => 1, 'sci' => 1, 'sck' => 1, 'scl' => 1, 'scn' => 1, 'sco' => 1, 'scp' => 1, 'scq' => 1, 'scu' => 1, 'scv' => 1, 'scw' => 1, 'scx' => 1, 'sda' => 1, 'sdb' => 1, 'sde' => 1, 'sdf' => 1, 'sdg' => 1, 'sdj' => 1, 'sdk' => 1, 'sdl' => 1, 'sdm' => 1, 'sdo' => 1, 'sdp' => 1, 'sdr' => 1, 'sds' => 1, 'sdt' => 1, 'sdu' => 1, 'sdv' => 1, 'sdx' => 1, 'sdz' => 1, 'sea' => 1, 'seb' => 1, 'sec' => 1, 'sed' => 1, 'see' => 1, 'sef' => 1, 'seg' => 1, 'seh' => 1, 'sei' => 1, 'sej' => 1, 'sek' => 1, 'sel' => 1, 'sem' => 1, 'sen' => 1, 'seo' => 1, 'sep' => 1, 'seq' => 1, 'ser' => 1, 'ses' => 1, 'set' => 1, 'seu' => 1, 'sev' => 1, 'sew' => 1, 'sey' => 1, 'sez' => 1, 'sfb' => 1, 'sfs' => 1, 'sfw' => 1, 'sga' => 1, 'sgb' => 1, 'sge' => 1, 'sgg' => 1, 'sgh' => 1, 'sgi' => 1, 'sgk' => 1, 'sgl' => 1, 'sgm' => 1, 'sgn' => 1, 'sgo' => 1, 'sgp' => 1, 'sgr' => 1, 'sgt' => 1, 'sgu' => 1, 'sgw' => 1, 'sgx' => 1, 'sgz' => 1, 'sha' => 1, 'shb' => 1, 'shc' => 1, 'she' => 1, 'shg' => 1, 'shh' => 1, 'shi' => 1, 'shj' => 1, 'shk' => 1, 'shl' => 1, 'shm' => 1, 'shn' => 1, 'sho' => 1, 'shp' => 1, 'shq' => 1, 'shr' => 1, 'shs' => 1, 'sht' => 1, 'shv' => 1, 'shw' => 1, 'shx' => 1, 'shy' => 1, 'shz' => 1, 'sia' => 1, 'sib' => 1, 'sid' => 1, 'sie' => 1, 'sif' => 1, 'sig' => 1, 'sih' => 1, 'sii' => 1, 'sij' => 1, 'sik' => 1, 'sil' => 1, 'sim' => 1, 'sio' => 1, 'sip' => 1, 'siq' => 1, 'sir' => 1, 'sis' => 1, 'sit' => 1, 'siu' => 1, 'siv' => 1, 'siw' => 1, 'six' => 1, 'siy' => 1, 'siz' => 1, 'sja' => 1, 'sjb' => 1, 'sjd' => 1, 'sje' => 1, 'sjg' => 1, 'sjk' => 1, 'sjl' => 1, 'sjm' => 1, 'sjn' => 1, 'sjo' => 1, 'sjp' => 1, 'sjr' => 1, 'sjs' => 1, 'sjt' => 1, 'sju' => 1, 'sjw' => 1, 'ska' => 1, 'skb' => 1, 'skc' => 1, 'skd' => 1, 'ske' => 1, 'skf' => 1, 'skh' => 1, 'ski' => 1, 'skj' => 1, 'skk' => 1, 'skm' => 1, 'skn' => 1, 'sko' => 1, 'skp' => 1, 'skq' => 1, 'sks' => 1, 'skt' => 1, 'sku' => 1, 'skv' => 1, 'skw' => 1, 'skx' => 1, 'sky' => 1, 'skz' => 1, 'sla' => 1, 'slc' => 1, 'sld' => 1, 'sle' => 1, 'slf' => 1, 'slg' => 1, 'slh' => 1, 'sli' => 1, 'slj' => 1, 'sll' => 1, 'slm' => 1, 'sln' => 1, 'slp' => 1, 'slq' => 1, 'slr' => 1, 'sls' => 1, 'slt' => 1, 'slu' => 1, 'slw' => 1, 'slx' => 1, 'sly' => 1, 'slz' => 1, 'sma' => 1, 'smb' => 1, 'smc' => 1, 'smd' => 1, 'smf' => 1, 'smg' => 1, 'smh' => 1, 'smi' => 1, 'smj' => 1, 'smk' => 1, 'sml' => 1, 'smm' => 1, 'smn' => 1, 'smp' => 1, 'smq' => 1, 'smr' => 1, 'sms' => 1, 'smt' => 1, 'smu' => 1, 'smv' => 1, 'smw' => 1, 'smx' => 1, 'smy' => 1, 'smz' => 1, 'snb' => 1, 'snc' => 1, 'sne' => 1, 'snf' => 1, 'sng' => 1, 'snh' => 1, 'sni' => 1, 'snj' => 1, 'snk' => 1, 'snl' => 1, 'snm' => 1, 'snn' => 1, 'sno' => 1, 'snp' => 1, 'snq' => 1, 'snr' => 1, 'sns' => 1, 'snu' => 1, 'snv' => 1, 'snw' => 1, 'snx' => 1, 'sny' => 1, 'snz' => 1, 'soa' => 1, 'sob' => 1, 'soc' => 1, 'sod' => 1, 'soe' => 1, 'sog' => 1, 'soh' => 1, 'soi' => 1, 'soj' => 1, 'sok' => 1, 'sol' => 1, 'son' => 1, 'soo' => 1, 'sop' => 1, 'soq' => 1, 'sor' => 1, 'sos' => 1, 'sou' => 1, 'sov' => 1, 'sow' => 1, 'sox' => 1, 'soy' => 1, 'soz' => 1, 'spb' => 1, 'spc' => 1, 'spd' => 1, 'spe' => 1, 'spg' => 1, 'spi' => 1, 'spk' => 1, 'spl' => 1, 'spm' => 1, 'spo' => 1, 'spp' => 1, 'spq' => 1, 'spr' => 1, 'sps' => 1, 'spt' => 1, 'spu' => 1, 'spx' => 1, 'sqa' => 1, 'sqh' => 1, 'sqj' => 1, 'sqm' => 1, 'sqn' => 1, 'sqo' => 1, 'sqq' => 1, 'sqr' => 1, 'sqs' => 1, 'sqt' => 1, 'squ' => 1, 'sra' => 1, 'srb' => 1, 'sre' => 1, 'srf' => 1, 'srg' => 1, 'srh' => 1, 'sri' => 1, 'srk' => 1, 'srl' => 1, 'srm' => 1, 'srn' => 1, 'srq' => 1, 'srr' => 1, 'srs' => 1, 'srt' => 1, 'sru' => 1, 'srv' => 1, 'srw' => 1, 'srx' => 1, 'sry' => 1, 'srz' => 1, 'ssa' => 1, 'ssb' => 1, 'ssc' => 1, 'ssd' => 1, 'sse' => 1, 'ssf' => 1, 'ssg' => 1, 'ssi' => 1, 'ssj' => 1, 'ssk' => 1, 'ssl' => 1, 'ssm' => 1, 'ssn' => 1, 'sso' => 1, 'ssp' => 1, 'ssq' => 1, 'ssr' => 1, 'sss' => 1, 'sst' => 1, 'ssu' => 1, 'ssv' => 1, 'ssx' => 1, 'ssy' => 1, 'ssz' => 1, 'sta' => 1, 'stb' => 1, 'std' => 1, 'ste' => 1, 'stf' => 1, 'stg' => 1, 'sth' => 1, 'sti' => 1, 'stj' => 1, 'stk' => 1, 'stl' => 1, 'stm' => 1, 'stn' => 1, 'sto' => 1, 'stp' => 1, 'stq' => 1, 'str' => 1, 'sts' => 1, 'stt' => 1, 'stu' => 1, 'stv' => 1, 'stw' => 1, 'sua' => 1, 'sub' => 1, 'suc' => 1, 'sue' => 1, 'sug' => 1, 'sui' => 1, 'suj' => 1, 'suk' => 1, 'sul' => 1, 'sum' => 1, 'suq' => 1, 'sur' => 1, 'sus' => 1, 'sut' => 1, 'suv' => 1, 'suw' => 1, 'sux' => 1, 'suy' => 1, 'suz' => 1, 'sva' => 1, 'svb' => 1, 'svc' => 1, 'sve' => 1, 'svk' => 1, 'svr' => 1, 'svs' => 1, 'svx' => 1, 'swb' => 1, 'swf' => 1, 'swg' => 1, 'swi' => 1, 'swj' => 1, 'swk' => 1, 'swl' => 1, 'swm' => 1, 'swn' => 1, 'swo' => 1, 'swp' => 1, 'swq' => 1, 'swr' => 1, 'sws' => 1, 'swt' => 1, 'swu' => 1, 'sww' => 1, 'swx' => 1, 'swy' => 1, 'sxb' => 1, 'sxc' => 1, 'sxe' => 1, 'sxg' => 1, 'sxk' => 1, 'sxl' => 1, 'sxm' => 1, 'sxn' => 1, 'sxo' => 1, 'sxr' => 1, 'sxs' => 1, 'sxu' => 1, 'sxw' => 1, 'sya' => 1, 'syb' => 1, 'syc' => 1, 'syd' => 1, 'syi' => 1, 'syk' => 1, 'syl' => 1, 'sym' => 1, 'syn' => 1, 'syo' => 1, 'syr' => 1, 'sys' => 1, 'syw' => 1, 'syy' => 1, 'sza' => 1, 'szb' => 1, 'szc' => 1, 'szd' => 1, 'sze' => 1, 'szg' => 1, 'szl' => 1, 'szn' => 1, 'szp' => 1, 'szv' => 1, 'szw' => 1, 'taa' => 1, 'tab' => 1, 'tac' => 1, 'tad' => 1, 'tae' => 1, 'taf' => 1, 'tag' => 1, 'tai' => 1, 'taj' => 1, 'tak' => 1, 'tal' => 1, 'tan' => 1, 'tao' => 1, 'tap' => 1, 'tar' => 1, 'tas' => 1, 'tau' => 1, 'tav' => 1, 'taw' => 1, 'tax' => 1, 'tay' => 1, 'taz' => 1, 'tba' => 1, 'tbb' => 1, 'tbc' => 1, 'tbd' => 1, 'tbe' => 1, 'tbf' => 1, 'tbg' => 1, 'tbh' => 1, 'tbi' => 1, 'tbj' => 1, 'tbk' => 1, 'tbl' => 1, 'tbm' => 1, 'tbn' => 1, 'tbo' => 1, 'tbp' => 1, 'tbq' => 1, 'tbr' => 1, 'tbs' => 1, 'tbt' => 1, 'tbu' => 1, 'tbv' => 1, 'tbw' => 1, 'tbx' => 1, 'tby' => 1, 'tbz' => 1, 'tca' => 1, 'tcb' => 1, 'tcc' => 1, 'tcd' => 1, 'tce' => 1, 'tcf' => 1, 'tcg' => 1, 'tch' => 1, 'tci' => 1, 'tck' => 1, 'tcl' => 1, 'tcm' => 1, 'tcn' => 1, 'tco' => 1, 'tcp' => 1, 'tcq' => 1, 'tcs' => 1, 'tct' => 1, 'tcu' => 1, 'tcw' => 1, 'tcx' => 1, 'tcy' => 1, 'tcz' => 1, 'tda' => 1, 'tdb' => 1, 'tdc' => 1, 'tdd' => 1, 'tdf' => 1, 'tdg' => 1, 'tdh' => 1, 'tdi' => 1, 'tdj' => 1, 'tdk' => 1, 'tdl' => 1, 'tdn' => 1, 'tdo' => 1, 'tdq' => 1, 'tdr' => 1, 'tds' => 1, 'tdt' => 1, 'tdu' => 1, 'tdv' => 1, 'tdy' => 1, 'tea' => 1, 'teb' => 1, 'ted' => 1, 'tee' => 1, 'tef' => 1, 'teg' => 1, 'teh' => 1, 'tei' => 1, 'tek' => 1, 'tem' => 1, 'ten' => 1, 'teo' => 1, 'tep' => 1, 'teq' => 1, 'ter' => 1, 'tes' => 1, 'tet' => 1, 'teu' => 1, 'tev' => 1, 'tew' => 1, 'tex' => 1, 'tey' => 1, 'tfi' => 1, 'tfn' => 1, 'tfo' => 1, 'tfr' => 1, 'tft' => 1, 'tga' => 1, 'tgb' => 1, 'tgc' => 1, 'tgd' => 1, 'tge' => 1, 'tgf' => 1, 'tgg' => 1, 'tgh' => 1, 'tgi' => 1, 'tgo' => 1, 'tgp' => 1, 'tgq' => 1, 'tgr' => 1, 'tgs' => 1, 'tgt' => 1, 'tgu' => 1, 'tgv' => 1, 'tgw' => 1, 'tgx' => 1, 'tgy' => 1, 'thc' => 1, 'thd' => 1, 'the' => 1, 'thf' => 1, 'thh' => 1, 'thi' => 1, 'thk' => 1, 'thl' => 1, 'thm' => 1, 'thn' => 1, 'thp' => 1, 'thq' => 1, 'thr' => 1, 'ths' => 1, 'tht' => 1, 'thu' => 1, 'thw' => 1, 'thx' => 1, 'thy' => 1, 'tia' => 1, 'tic' => 1, 'tid' => 1, 'tie' => 1, 'tif' => 1, 'tig' => 1, 'tih' => 1, 'tii' => 1, 'tij' => 1, 'tik' => 1, 'til' => 1, 'tim' => 1, 'tin' => 1, 'tio' => 1, 'tip' => 1, 'tiq' => 1, 'tis' => 1, 'tit' => 1, 'tiu' => 1, 'tiv' => 1, 'tiw' => 1, 'tix' => 1, 'tiy' => 1, 'tiz' => 1, 'tja' => 1, 'tjg' => 1, 'tji' => 1, 'tjm' => 1, 'tjn' => 1, 'tjo' => 1, 'tjs' => 1, 'tju' => 1, 'tka' => 1, 'tkb' => 1, 'tkd' => 1, 'tke' => 1, 'tkf' => 1, 'tkk' => 1, 'tkl' => 1, 'tkm' => 1, 'tkn' => 1, 'tkp' => 1, 'tkq' => 1, 'tkr' => 1, 'tks' => 1, 'tkt' => 1, 'tku' => 1, 'tkw' => 1, 'tkx' => 1, 'tkz' => 1, 'tla' => 1, 'tlb' => 1, 'tlc' => 1, 'tld' => 1, 'tlf' => 1, 'tlg' => 1, 'tlh' => 1, 'tli' => 1, 'tlj' => 1, 'tlk' => 1, 'tll' => 1, 'tlm' => 1, 'tln' => 1, 'tlo' => 1, 'tlp' => 1, 'tlq' => 1, 'tlr' => 1, 'tls' => 1, 'tlt' => 1, 'tlu' => 1, 'tlv' => 1, 'tlw' => 1, 'tlx' => 1, 'tly' => 1, 'tma' => 1, 'tmb' => 1, 'tmc' => 1, 'tmd' => 1, 'tme' => 1, 'tmf' => 1, 'tmg' => 1, 'tmh' => 1, 'tmi' => 1, 'tmj' => 1, 'tmk' => 1, 'tml' => 1, 'tmm' => 1, 'tmn' => 1, 'tmo' => 1, 'tmp' => 1, 'tmq' => 1, 'tmr' => 1, 'tms' => 1, 'tmt' => 1, 'tmu' => 1, 'tmv' => 1, 'tmy' => 1, 'tmz' => 1, 'tna' => 1, 'tnb' => 1, 'tnc' => 1, 'tnd' => 1, 'tne' => 1, 'tnf' => 1, 'tng' => 1, 'tnh' => 1, 'tni' => 1, 'tnk' => 1, 'tnl' => 1, 'tnm' => 1, 'tnn' => 1, 'tno' => 1, 'tnp' => 1, 'tnq' => 1, 'tnr' => 1, 'tns' => 1, 'tnt' => 1, 'tnu' => 1, 'tnv' => 1, 'tnw' => 1, 'tnx' => 1, 'tny' => 1, 'tnz' => 1, 'tob' => 1, 'toc' => 1, 'tod' => 1, 'toe' => 1, 'tof' => 1, 'tog' => 1, 'toh' => 1, 'toi' => 1, 'toj' => 1, 'tol' => 1, 'tom' => 1, 'too' => 1, 'top' => 1, 'toq' => 1, 'tor' => 1, 'tos' => 1, 'tou' => 1, 'tov' => 1, 'tow' => 1, 'tox' => 1, 'toy' => 1, 'toz' => 1, 'tpa' => 1, 'tpc' => 1, 'tpe' => 1, 'tpf' => 1, 'tpg' => 1, 'tpi' => 1, 'tpj' => 1, 'tpk' => 1, 'tpl' => 1, 'tpm' => 1, 'tpn' => 1, 'tpo' => 1, 'tpp' => 1, 'tpq' => 1, 'tpr' => 1, 'tpt' => 1, 'tpu' => 1, 'tpv' => 1, 'tpw' => 1, 'tpx' => 1, 'tpy' => 1, 'tpz' => 1, 'tqb' => 1, 'tql' => 1, 'tqm' => 1, 'tqn' => 1, 'tqo' => 1, 'tqp' => 1, 'tqq' => 1, 'tqr' => 1, 'tqt' => 1, 'tqu' => 1, 'tqw' => 1, 'tra' => 1, 'trb' => 1, 'trc' => 1, 'trd' => 1, 'tre' => 1, 'trf' => 1, 'trg' => 1, 'trh' => 1, 'tri' => 1, 'trj' => 1, 'trk' => 1, 'trl' => 1, 'trm' => 1, 'trn' => 1, 'tro' => 1, 'trp' => 1, 'trq' => 1, 'trr' => 1, 'trs' => 1, 'trt' => 1, 'tru' => 1, 'trv' => 1, 'trw' => 1, 'trx' => 1, 'try' => 1, 'trz' => 1, 'tsa' => 1, 'tsb' => 1, 'tsc' => 1, 'tsd' => 1, 'tse' => 1, 'tsf' => 1, 'tsg' => 1, 'tsh' => 1, 'tsi' => 1, 'tsj' => 1, 'tsk' => 1, 'tsl' => 1, 'tsm' => 1, 'tsp' => 1, 'tsq' => 1, 'tsr' => 1, 'tss' => 1, 'tsu' => 1, 'tsv' => 1, 'tsw' => 1, 'tsx' => 1, 'tsy' => 1, 'tsz' => 1, 'tta' => 1, 'ttb' => 1, 'ttc' => 1, 'ttd' => 1, 'tte' => 1, 'ttf' => 1, 'ttg' => 1, 'tth' => 1, 'tti' => 1, 'ttj' => 1, 'ttk' => 1, 'ttl' => 1, 'ttm' => 1, 'ttn' => 1, 'tto' => 1, 'ttp' => 1, 'ttr' => 1, 'tts' => 1, 'ttt' => 1, 'ttu' => 1, 'ttv' => 1, 'ttw' => 1, 'tty' => 1, 'ttz' => 1, 'tua' => 1, 'tub' => 1, 'tuc' => 1, 'tud' => 1, 'tue' => 1, 'tuf' => 1, 'tug' => 1, 'tuh' => 1, 'tui' => 1, 'tuj' => 1, 'tul' => 1, 'tum' => 1, 'tun' => 1, 'tuo' => 1, 'tup' => 1, 'tuq' => 1, 'tus' => 1, 'tut' => 1, 'tuu' => 1, 'tuv' => 1, 'tuw' => 1, 'tux' => 1, 'tuz' => 1, 'tva' => 1, 'tvd' => 1, 'tve' => 1, 'tvk' => 1, 'tvl' => 1, 'tvm' => 1, 'tvn' => 1, 'tvo' => 1, 'tvs' => 1, 'tvt' => 1, 'tvw' => 1, 'tvy' => 1, 'twa' => 1, 'twb' => 1, 'twc' => 1, 'twd' => 1, 'twe' => 1, 'twf' => 1, 'twg' => 1, 'twh' => 1, 'twl' => 1, 'twm' => 1, 'twn' => 1, 'two' => 1, 'twp' => 1, 'twq' => 1, 'twr' => 1, 'twt' => 1, 'twu' => 1, 'tww' => 1, 'twx' => 1, 'twy' => 1, 'txa' => 1, 'txb' => 1, 'txc' => 1, 'txe' => 1, 'txg' => 1, 'txh' => 1, 'txi' => 1, 'txm' => 1, 'txn' => 1, 'txo' => 1, 'txq' => 1, 'txr' => 1, 'txs' => 1, 'txt' => 1, 'txu' => 1, 'txx' => 1, 'tya' => 1, 'tye' => 1, 'tyh' => 1, 'tyi' => 1, 'tyj' => 1, 'tyl' => 1, 'tyn' => 1, 'typ' => 1, 'tyr' => 1, 'tys' => 1, 'tyt' => 1, 'tyu' => 1, 'tyv' => 1, 'tyx' => 1, 'tyz' => 1, 'tza' => 1, 'tzh' => 1, 'tzj' => 1, 'tzm' => 1, 'tzn' => 1, 'tzo' => 1, 'tzx' => 1, 'uam' => 1, 'uan' => 1, 'uar' => 1, 'uba' => 1, 'ubi' => 1, 'ubr' => 1, 'ubu' => 1, 'uby' => 1, 'uda' => 1, 'ude' => 1, 'udg' => 1, 'udi' => 1, 'udj' => 1, 'udl' => 1, 'udm' => 1, 'udu' => 1, 'ues' => 1, 'ufi' => 1, 'uga' => 1, 'ugb' => 1, 'uge' => 1, 'ugn' => 1, 'ugo' => 1, 'ugy' => 1, 'uha' => 1, 'uhn' => 1, 'uis' => 1, 'uiv' => 1, 'uji' => 1, 'uka' => 1, 'ukg' => 1, 'ukh' => 1, 'ukl' => 1, 'ukp' => 1, 'ukq' => 1, 'uks' => 1, 'uku' => 1, 'ukw' => 1, 'ula' => 1, 'ulb' => 1, 'ulc' => 1, 'ulf' => 1, 'uli' => 1, 'ulk' => 1, 'ull' => 1, 'ulm' => 1, 'uln' => 1, 'ulu' => 1, 'uma' => 1, 'umb' => 1, 'umc' => 1, 'umd' => 1, 'umg' => 1, 'umi' => 1, 'umm' => 1, 'umn' => 1, 'umo' => 1, 'ump' => 1, 'umr' => 1, 'ums' => 1, 'una' => 1, 'une' => 1, 'ung' => 1, 'unk' => 1, 'unp' => 1, 'unr' => 1, 'unx' => 1, 'unz' => 1, 'uok' => 1, 'upi' => 1, 'upv' => 1, 'ura' => 1, 'urb' => 1, 'urc' => 1, 'ure' => 1, 'urf' => 1, 'urg' => 1, 'urh' => 1, 'uri' => 1, 'urj' => 1, 'url' => 1, 'urm' => 1, 'urn' => 1, 'uro' => 1, 'urp' => 1, 'urr' => 1, 'urt' => 1, 'uru' => 1, 'urv' => 1, 'urw' => 1, 'urx' => 1, 'ury' => 1, 'urz' => 1, 'usa' => 1, 'ush' => 1, 'usi' => 1, 'usk' => 1, 'usp' => 1, 'usu' => 1, 'uta' => 1, 'ute' => 1, 'utp' => 1, 'utr' => 1, 'utu' => 1, 'uum' => 1, 'uun' => 1, 'uur' => 1, 'uuu' => 1, 'uve' => 1, 'uvh' => 1, 'uvl' => 1, 'uwa' => 1, 'uya' => 1, 'vaa' => 1, 'vae' => 1, 'vaf' => 1, 'vag' => 1, 'vah' => 1, 'vai' => 1, 'vaj' => 1, 'val' => 1, 'vam' => 1, 'van' => 1, 'vao' => 1, 'vap' => 1, 'var' => 1, 'vas' => 1, 'vau' => 1, 'vav' => 1, 'vay' => 1, 'vbb' => 1, 'vec' => 1, 'ved' => 1, 'vel' => 1, 'vem' => 1, 'veo' => 1, 'vep' => 1, 'ver' => 1, 'vgr' => 1, 'vgt' => 1, 'vic' => 1, 'vid' => 1, 'vif' => 1, 'vig' => 1, 'vil' => 1, 'vin' => 1, 'vis' => 1, 'vit' => 1, 'viv' => 1, 'vka' => 1, 'vki' => 1, 'vkj' => 1, 'vkl' => 1, 'vkm' => 1, 'vko' => 1, 'vkp' => 1, 'vku' => 1, 'vlp' => 1, 'vls' => 1, 'vma' => 1, 'vmb' => 1, 'vmc' => 1, 'vmd' => 1, 'vme' => 1, 'vmf' => 1, 'vmg' => 1, 'vmh' => 1, 'vmi' => 1, 'vmj' => 1, 'vmk' => 1, 'vml' => 1, 'vmm' => 1, 'vmp' => 1, 'vmq' => 1, 'vmr' => 1, 'vms' => 1, 'vmu' => 1, 'vmv' => 1, 'vmw' => 1, 'vmx' => 1, 'vmy' => 1, 'vmz' => 1, 'vnk' => 1, 'vnm' => 1, 'vnp' => 1, 'vor' => 1, 'vot' => 1, 'vra' => 1, 'vrs' => 1, 'vrt' => 1, 'vsi' => 1, 'vsl' => 1, 'vsv' => 1, 'vto' => 1, 'vum' => 1, 'vun' => 1, 'vut' => 1, 'vwa' => 1, 'waa' => 1, 'wab' => 1, 'wac' => 1, 'wad' => 1, 'wae' => 1, 'waf' => 1, 'wag' => 1, 'wah' => 1, 'wai' => 1, 'waj' => 1, 'wak' => 1, 'wal' => 1, 'wam' => 1, 'wan' => 1, 'wao' => 1, 'wap' => 1, 'waq' => 1, 'war' => 1, 'was' => 1, 'wat' => 1, 'wau' => 1, 'wav' => 1, 'waw' => 1, 'wax' => 1, 'way' => 1, 'waz' => 1, 'wba' => 1, 'wbb' => 1, 'wbe' => 1, 'wbf' => 1, 'wbh' => 1, 'wbi' => 1, 'wbj' => 1, 'wbk' => 1, 'wbl' => 1, 'wbm' => 1, 'wbp' => 1, 'wbq' => 1, 'wbt' => 1, 'wbv' => 1, 'wbw' => 1, 'wca' => 1, 'wci' => 1, 'wdd' => 1, 'wdg' => 1, 'wdj' => 1, 'wdu' => 1, 'wea' => 1, 'wec' => 1, 'wed' => 1, 'weh' => 1, 'wei' => 1, 'wem' => 1, 'wen' => 1, 'weo' => 1, 'wep' => 1, 'wer' => 1, 'wes' => 1, 'wet' => 1, 'weu' => 1, 'wew' => 1, 'wfg' => 1, 'wga' => 1, 'wgg' => 1, 'wgi' => 1, 'wgo' => 1, 'wgw' => 1, 'wgy' => 1, 'wha' => 1, 'whg' => 1, 'whk' => 1, 'whu' => 1, 'wib' => 1, 'wic' => 1, 'wie' => 1, 'wif' => 1, 'wig' => 1, 'wih' => 1, 'wii' => 1, 'wij' => 1, 'wik' => 1, 'wil' => 1, 'wim' => 1, 'win' => 1, 'wir' => 1, 'wit' => 1, 'wiu' => 1, 'wiv' => 1, 'wiw' => 1, 'wiy' => 1, 'wja' => 1, 'wji' => 1, 'wka' => 1, 'wkb' => 1, 'wkd' => 1, 'wkl' => 1, 'wku' => 1, 'wkw' => 1, 'wla' => 1, 'wlc' => 1, 'wle' => 1, 'wlg' => 1, 'wli' => 1, 'wlk' => 1, 'wll' => 1, 'wlm' => 1, 'wlo' => 1, 'wlr' => 1, 'wls' => 1, 'wlu' => 1, 'wlv' => 1, 'wlw' => 1, 'wlx' => 1, 'wly' => 1, 'wma' => 1, 'wmb' => 1, 'wmc' => 1, 'wmd' => 1, 'wme' => 1, 'wmh' => 1, 'wmi' => 1, 'wmm' => 1, 'wmn' => 1, 'wmo' => 1, 'wms' => 1, 'wmt' => 1, 'wmw' => 1, 'wmx' => 1, 'wnb' => 1, 'wnc' => 1, 'wnd' => 1, 'wne' => 1, 'wng' => 1, 'wni' => 1, 'wnk' => 1, 'wnm' => 1, 'wno' => 1, 'wnp' => 1, 'wnu' => 1, 'woa' => 1, 'wob' => 1, 'woc' => 1, 'wod' => 1, 'woe' => 1, 'wof' => 1, 'wog' => 1, 'woi' => 1, 'wok' => 1, 'wom' => 1, 'won' => 1, 'woo' => 1, 'wor' => 1, 'wos' => 1, 'wow' => 1, 'woy' => 1, 'wpc' => 1, 'wra' => 1, 'wrb' => 1, 'wrd' => 1, 'wrg' => 1, 'wrh' => 1, 'wri' => 1, 'wrl' => 1, 'wrm' => 1, 'wrn' => 1, 'wrp' => 1, 'wrr' => 1, 'wrs' => 1, 'wru' => 1, 'wrv' => 1, 'wrw' => 1, 'wrx' => 1, 'wrz' => 1, 'wsa' => 1, 'wsi' => 1, 'wsk' => 1, 'wsr' => 1, 'wss' => 1, 'wsu' => 1, 'wsv' => 1, 'wtf' => 1, 'wti' => 1, 'wtk' => 1, 'wtm' => 1, 'wtw' => 1, 'wua' => 1, 'wub' => 1, 'wud' => 1, 'wuh' => 1, 'wul' => 1, 'wum' => 1, 'wun' => 1, 'wur' => 1, 'wut' => 1, 'wuv' => 1, 'wux' => 1, 'wuy' => 1, 'wwa' => 1, 'wwo' => 1, 'wwr' => 1, 'www' => 1, 'wxa' => 1, 'wya' => 1, 'wyb' => 1, 'wym' => 1, 'wyr' => 1, 'wyy' => 1, 'xaa' => 1, 'xab' => 1, 'xac' => 1, 'xad' => 1, 'xae' => 1, 'xag' => 1, 'xai' => 1, 'xal' => 1, 'xam' => 1, 'xan' => 1, 'xao' => 1, 'xap' => 1, 'xaq' => 1, 'xar' => 1, 'xas' => 1, 'xat' => 1, 'xau' => 1, 'xav' => 1, 'xaw' => 1, 'xay' => 1, 'xba' => 1, 'xbc' => 1, 'xbi' => 1, 'xbm' => 1, 'xbo' => 1, 'xbr' => 1, 'xbw' => 1, 'xbx' => 1, 'xcb' => 1, 'xcc' => 1, 'xce' => 1, 'xcg' => 1, 'xch' => 1, 'xcl' => 1, 'xcm' => 1, 'xcn' => 1, 'xco' => 1, 'xcr' => 1, 'xct' => 1, 'xcu' => 1, 'xcv' => 1, 'xcw' => 1, 'xcy' => 1, 'xdc' => 1, 'xdm' => 1, 'xdy' => 1, 'xeb' => 1, 'xed' => 1, 'xeg' => 1, 'xel' => 1, 'xem' => 1, 'xep' => 1, 'xer' => 1, 'xes' => 1, 'xet' => 1, 'xeu' => 1, 'xfa' => 1, 'xga' => 1, 'xgf' => 1, 'xgl' => 1, 'xgn' => 1, 'xgr' => 1, 'xha' => 1, 'xhc' => 1, 'xhd' => 1, 'xhr' => 1, 'xht' => 1, 'xhu' => 1, 'xhv' => 1, 'xia' => 1, 'xib' => 1, 'xii' => 1, 'xil' => 1, 'xin' => 1, 'xip' => 1, 'xir' => 1, 'xiv' => 1, 'xiy' => 1, 'xka' => 1, 'xkb' => 1, 'xkc' => 1, 'xkd' => 1, 'xke' => 1, 'xkf' => 1, 'xkg' => 1, 'xkh' => 1, 'xki' => 1, 'xkj' => 1, 'xkk' => 1, 'xkl' => 1, 'xkn' => 1, 'xko' => 1, 'xkp' => 1, 'xkq' => 1, 'xkr' => 1, 'xks' => 1, 'xkt' => 1, 'xku' => 1, 'xkv' => 1, 'xkw' => 1, 'xkx' => 1, 'xky' => 1, 'xkz' => 1, 'xla' => 1, 'xlb' => 1, 'xlc' => 1, 'xld' => 1, 'xle' => 1, 'xlg' => 1, 'xli' => 1, 'xln' => 1, 'xlo' => 1, 'xlp' => 1, 'xls' => 1, 'xlu' => 1, 'xly' => 1, 'xma' => 1, 'xmb' => 1, 'xmc' => 1, 'xmd' => 1, 'xme' => 1, 'xmf' => 1, 'xmg' => 1, 'xmh' => 1, 'xmj' => 1, 'xmk' => 1, 'xml' => 1, 'xmn' => 1, 'xmo' => 1, 'xmp' => 1, 'xmq' => 1, 'xmr' => 1, 'xms' => 1, 'xmt' => 1, 'xmu' => 1, 'xmx' => 1, 'xmy' => 1, 'xmz' => 1, 'xna' => 1, 'xnb' => 1, 'xnd' => 1, 'xng' => 1, 'xnh' => 1, 'xnn' => 1, 'xno' => 1, 'xns' => 1, 'xoc' => 1, 'xod' => 1, 'xog' => 1, 'xoi' => 1, 'xok' => 1, 'xom' => 1, 'xon' => 1, 'xoo' => 1, 'xop' => 1, 'xor' => 1, 'xow' => 1, 'xpc' => 1, 'xpg' => 1, 'xpi' => 1, 'xpk' => 1, 'xpm' => 1, 'xpn' => 1, 'xpo' => 1, 'xpp' => 1, 'xpr' => 1, 'xps' => 1, 'xpu' => 1, 'xpy' => 1, 'xqa' => 1, 'xqt' => 1, 'xra' => 1, 'xrb' => 1, 'xre' => 1, 'xri' => 1, 'xrm' => 1, 'xrn' => 1, 'xrr' => 1, 'xrt' => 1, 'xru' => 1, 'xrw' => 1, 'xsa' => 1, 'xsb' => 1, 'xsc' => 1, 'xsd' => 1, 'xse' => 1, 'xsh' => 1, 'xsi' => 1, 'xsj' => 1, 'xsm' => 1, 'xsn' => 1, 'xso' => 1, 'xsp' => 1, 'xsq' => 1, 'xsr' => 1, 'xss' => 1, 'xsu' => 1, 'xsv' => 1, 'xsy' => 1, 'xta' => 1, 'xtb' => 1, 'xtc' => 1, 'xtd' => 1, 'xte' => 1, 'xtg' => 1, 'xti' => 1, 'xtj' => 1, 'xtl' => 1, 'xtm' => 1, 'xtn' => 1, 'xto' => 1, 'xtp' => 1, 'xtq' => 1, 'xtr' => 1, 'xts' => 1, 'xtt' => 1, 'xtu' => 1, 'xtw' => 1, 'xty' => 1, 'xtz' => 1, 'xua' => 1, 'xub' => 1, 'xug' => 1, 'xuj' => 1, 'xum' => 1, 'xuo' => 1, 'xup' => 1, 'xur' => 1, 'xut' => 1, 'xuu' => 1, 'xve' => 1, 'xvi' => 1, 'xvn' => 1, 'xvo' => 1, 'xvs' => 1, 'xwa' => 1, 'xwc' => 1, 'xwe' => 1, 'xwg' => 1, 'xwl' => 1, 'xwo' => 1, 'xwr' => 1, 'xxb' => 1, 'xxk' => 1, 'xxr' => 1, 'xxt' => 1, 'xyl' => 1, 'xzh' => 1, 'xzm' => 1, 'xzp' => 1, 'yaa' => 1, 'yab' => 1, 'yac' => 1, 'yad' => 1, 'yae' => 1, 'yaf' => 1, 'yag' => 1, 'yah' => 1, 'yai' => 1, 'yaj' => 1, 'yak' => 1, 'yal' => 1, 'yam' => 1, 'yao' => 1, 'yap' => 1, 'yaq' => 1, 'yar' => 1, 'yas' => 1, 'yat' => 1, 'yau' => 1, 'yav' => 1, 'yaw' => 1, 'yax' => 1, 'yay' => 1, 'yaz' => 1, 'yba' => 1, 'ybb' => 1, 'ybd' => 1, 'ybe' => 1, 'ybh' => 1, 'ybi' => 1, 'ybj' => 1, 'ybk' => 1, 'ybl' => 1, 'ybm' => 1, 'ybn' => 1, 'ybo' => 1, 'ybx' => 1, 'yby' => 1, 'ych' => 1, 'ycl' => 1, 'ycn' => 1, 'ycp' => 1, 'yde' => 1, 'ydg' => 1, 'ydk' => 1, 'yds' => 1, 'yea' => 1, 'yec' => 1, 'yee' => 1, 'yei' => 1, 'yej' => 1, 'yel' => 1, 'yen' => 1, 'yer' => 1, 'yes' => 1, 'yet' => 1, 'yeu' => 1, 'yev' => 1, 'yey' => 1, 'ygl' => 1, 'ygm' => 1, 'ygp' => 1, 'ygr' => 1, 'ygw' => 1, 'yha' => 1, 'yhl' => 1, 'yia' => 1, 'yif' => 1, 'yig' => 1, 'yii' => 1, 'yij' => 1, 'yik' => 1, 'yil' => 1, 'yim' => 1, 'yin' => 1, 'yip' => 1, 'yiq' => 1, 'yir' => 1, 'yis' => 1, 'yit' => 1, 'yiu' => 1, 'yiv' => 1, 'yix' => 1, 'yiy' => 1, 'yiz' => 1, 'yka' => 1, 'ykg' => 1, 'yki' => 1, 'ykk' => 1, 'ykl' => 1, 'ykm' => 1, 'yko' => 1, 'ykr' => 1, 'ykt' => 1, 'yky' => 1, 'yla' => 1, 'yle' => 1, 'ylg' => 1, 'yli' => 1, 'yll' => 1, 'ylm' => 1, 'yln' => 1, 'ylo' => 1, 'ylr' => 1, 'ylu' => 1, 'yly' => 1, 'yma' => 1, 'ymb' => 1, 'ymc' => 1, 'ymd' => 1, 'yme' => 1, 'ymg' => 1, 'ymh' => 1, 'ymi' => 1, 'ymk' => 1, 'yml' => 1, 'ymm' => 1, 'ymn' => 1, 'ymo' => 1, 'ymp' => 1, 'ymq' => 1, 'ymr' => 1, 'yms' => 1, 'ymt' => 1, 'ymx' => 1, 'ymz' => 1, 'yna' => 1, 'ynd' => 1, 'yne' => 1, 'yng' => 1, 'ynh' => 1, 'ynk' => 1, 'ynl' => 1, 'ynn' => 1, 'yno' => 1, 'yns' => 1, 'ynu' => 1, 'yob' => 1, 'yog' => 1, 'yoi' => 1, 'yok' => 1, 'yol' => 1, 'yom' => 1, 'yon' => 1, 'yos' => 1, 'yox' => 1, 'yoy' => 1, 'ypa' => 1, 'ypb' => 1, 'ypg' => 1, 'yph' => 1, 'ypk' => 1, 'ypm' => 1, 'ypn' => 1, 'ypo' => 1, 'ypp' => 1, 'ypz' => 1, 'yra' => 1, 'yrb' => 1, 'yre' => 1, 'yri' => 1, 'yrk' => 1, 'yrl' => 1, 'yrn' => 1, 'yrs' => 1, 'yrw' => 1, 'ysc' => 1, 'ysd' => 1, 'ysl' => 1, 'ysn' => 1, 'yso' => 1, 'ysp' => 1, 'ysr' => 1, 'yss' => 1, 'ysy' => 1, 'yta' => 1, 'ytl' => 1, 'ytp' => 1, 'yua' => 1, 'yub' => 1, 'yuc' => 1, 'yuf' => 1, 'yug' => 1, 'yui' => 1, 'yuj' => 1, 'yuk' => 1, 'yul' => 1, 'yum' => 1, 'yun' => 1, 'yup' => 1, 'yuq' => 1, 'yur' => 1, 'yut' => 1, 'yuu' => 1, 'yuw' => 1, 'yux' => 1, 'yuy' => 1, 'yuz' => 1, 'yva' => 1, 'yvt' => 1, 'ywa' => 1, 'ywl' => 1, 'ywn' => 1, 'ywq' => 1, 'ywr' => 1, 'ywt' => 1, 'ywu' => 1, 'yww' => 1, 'yyu' => 1, 'yyz' => 1, 'yzg' => 1, 'yzk' => 1, 'zag' => 1, 'zah' => 1, 'zaj' => 1, 'zak' => 1, 'zal' => 1, 'zap' => 1, 'zau' => 1, 'zay' => 1, 'zaz' => 1, 'zbc' => 1, 'zbe' => 1, 'zbl' => 1, 'zbt' => 1, 'zbw' => 1, 'zdj' => 1, 'zea' => 1, 'zeg' => 1, 'zen' => 1, 'zga' => 1, 'zgr' => 1, 'zhb' => 1, 'zhi' => 1, 'zhw' => 1, 'zhx' => 1, 'zia' => 1, 'zib' => 1, 'zik' => 1, 'zim' => 1, 'zin' => 1, 'zir' => 1, 'ziw' => 1, 'ziz' => 1, 'zka' => 1, 'zkb' => 1, 'zkg' => 1, 'zkh' => 1, 'zkk' => 1, 'zko' => 1, 'zkp' => 1, 'zkr' => 1, 'zkt' => 1, 'zku' => 1, 'zkv' => 1, 'zkz' => 1, 'zle' => 1, 'zls' => 1, 'zlw' => 1, 'zma' => 1, 'zmb' => 1, 'zmc' => 1, 'zmd' => 1, 'zme' => 1, 'zmf' => 1, 'zmg' => 1, 'zmh' => 1, 'zmj' => 1, 'zmk' => 1, 'zml' => 1, 'zmm' => 1, 'zmn' => 1, 'zmo' => 1, 'zmp' => 1, 'zmq' => 1, 'zmr' => 1, 'zms' => 1, 'zmt' => 1, 'zmu' => 1, 'zmv' => 1, 'zmw' => 1, 'zmx' => 1, 'zmy' => 1, 'zmz' => 1, 'zna' => 1, 'znd' => 1, 'zne' => 1, 'zng' => 1, 'znk' => 1, 'zns' => 1, 'zoc' => 1, 'zoh' => 1, 'zom' => 1, 'zoq' => 1, 'zor' => 1, 'zos' => 1, 'zra' => 1, 'zrg' => 1, 'zrn' => 1, 'zro' => 1, 'zrp' => 1, 'zrs' => 1, 'zsa' => 1, 'zsk' => 1, 'zsl' => 1, 'zsu' => 1, 'zua' => 1, 'zuh' => 1, 'zum' => 1, 'zun' => 1, 'zuy' => 1, 'zwa' => 1, 'zyp' => 1, 'zza' => 1, ); %region_codes = ( 'AC' => 1, 'AD' => 1, 'AE' => 1, 'AF' => 1, 'AG' => 1, 'AI' => 1, 'AL' => 1, 'AM' => 1, 'AN' => 1, 'AO' => 1, 'AQ' => 1, 'AR' => 1, 'AS' => 1, 'AT' => 1, 'AU' => 1, 'AW' => 1, 'AX' => 1, 'AZ' => 1, 'BA' => 1, 'BB' => 1, 'BD' => 1, 'BE' => 1, 'BF' => 1, 'BG' => 1, 'BH' => 1, 'BI' => 1, 'BJ' => 1, 'BL' => 1, 'BM' => 1, 'BN' => 1, 'BO' => 1, 'BR' => 1, 'BS' => 1, 'BT' => 1, 'BU' => 1, 'BV' => 1, 'BW' => 1, 'BY' => 1, 'BZ' => 1, 'CA' => 1, 'CC' => 1, 'CD' => 1, 'CF' => 1, 'CG' => 1, 'CH' => 1, 'CI' => 1, 'CK' => 1, 'CL' => 1, 'CM' => 1, 'CN' => 1, 'CO' => 1, 'CP' => 1, 'CR' => 1, 'CS' => 1, 'CU' => 1, 'CV' => 1, 'CX' => 1, 'CY' => 1, 'CZ' => 1, 'DD' => 1, 'DE' => 1, 'DG' => 1, 'DJ' => 1, 'DK' => 1, 'DM' => 1, 'DO' => 1, 'DZ' => 1, 'EA' => 1, 'EC' => 1, 'EE' => 1, 'EG' => 1, 'EH' => 1, 'ER' => 1, 'ES' => 1, 'ET' => 1, 'EU' => 1, 'FI' => 1, 'FJ' => 1, 'FK' => 1, 'FM' => 1, 'FO' => 1, 'FR' => 1, 'FX' => 1, 'GA' => 1, 'GB' => 1, 'GD' => 1, 'GE' => 1, 'GF' => 1, 'GG' => 1, 'GH' => 1, 'GI' => 1, 'GL' => 1, 'GM' => 1, 'GN' => 1, 'GP' => 1, 'GQ' => 1, 'GR' => 1, 'GS' => 1, 'GT' => 1, 'GU' => 1, 'GW' => 1, 'GY' => 1, 'HK' => 1, 'HM' => 1, 'HN' => 1, 'HR' => 1, 'HT' => 1, 'HU' => 1, 'IC' => 1, 'ID' => 1, 'IE' => 1, 'IL' => 1, 'IM' => 1, 'IN' => 1, 'IO' => 1, 'IQ' => 1, 'IR' => 1, 'IS' => 1, 'IT' => 1, 'JE' => 1, 'JM' => 1, 'JO' => 1, 'JP' => 1, 'KE' => 1, 'KG' => 1, 'KH' => 1, 'KI' => 1, 'KM' => 1, 'KN' => 1, 'KP' => 1, 'KR' => 1, 'KW' => 1, 'KY' => 1, 'KZ' => 1, 'LA' => 1, 'LB' => 1, 'LC' => 1, 'LI' => 1, 'LK' => 1, 'LR' => 1, 'LS' => 1, 'LT' => 1, 'LU' => 1, 'LV' => 1, 'LY' => 1, 'MA' => 1, 'MC' => 1, 'MD' => 1, 'ME' => 1, 'MF' => 1, 'MG' => 1, 'MH' => 1, 'MK' => 1, 'ML' => 1, 'MM' => 1, 'MN' => 1, 'MO' => 1, 'MP' => 1, 'MQ' => 1, 'MR' => 1, 'MS' => 1, 'MT' => 1, 'MU' => 1, 'MV' => 1, 'MW' => 1, 'MX' => 1, 'MY' => 1, 'MZ' => 1, 'NA' => 1, 'NC' => 1, 'NE' => 1, 'NF' => 1, 'NG' => 1, 'NI' => 1, 'NL' => 1, 'NO' => 1, 'NP' => 1, 'NR' => 1, 'NT' => 1, 'NU' => 1, 'NZ' => 1, 'OM' => 1, 'PA' => 1, 'PE' => 1, 'PF' => 1, 'PG' => 1, 'PH' => 1, 'PK' => 1, 'PL' => 1, 'PM' => 1, 'PN' => 1, 'PR' => 1, 'PS' => 1, 'PT' => 1, 'PW' => 1, 'PY' => 1, 'QA' => 1, 'RE' => 1, 'RO' => 1, 'RS' => 1, 'RU' => 1, 'RW' => 1, 'SA' => 1, 'SB' => 1, 'SC' => 1, 'SD' => 1, 'SE' => 1, 'SG' => 1, 'SH' => 1, 'SI' => 1, 'SJ' => 1, 'SK' => 1, 'SL' => 1, 'SM' => 1, 'SN' => 1, 'SO' => 1, 'SR' => 1, 'ST' => 1, 'SU' => 1, 'SV' => 1, 'SY' => 1, 'SZ' => 1, 'TA' => 1, 'TC' => 1, 'TD' => 1, 'TF' => 1, 'TG' => 1, 'TH' => 1, 'TJ' => 1, 'TK' => 1, 'TL' => 1, 'TM' => 1, 'TN' => 1, 'TO' => 1, 'TP' => 1, 'TR' => 1, 'TT' => 1, 'TV' => 1, 'TW' => 1, 'TZ' => 1, 'UA' => 1, 'UG' => 1, 'UM' => 1, 'US' => 1, 'UY' => 1, 'UZ' => 1, 'VA' => 1, 'VC' => 1, 'VE' => 1, 'VG' => 1, 'VI' => 1, 'VN' => 1, 'VU' => 1, 'WF' => 1, 'WS' => 1, 'YD' => 1, 'YE' => 1, 'YT' => 1, 'YU' => 1, 'ZA' => 1, 'ZM' => 1, 'ZR' => 1, 'ZW' => 1, ); require "$T2H_HOME/documentlanguages.pl" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/documentlanguages.pl" && -r "$T2H_HOME/documentlanguages.pl"); # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, if # $T2H_HOME/texi2html.init exists. # @INIT@ # -*-perl-*- # vim: set filetype=perl: ###################################################################### # File: texi2html.init # # Default values for command-line arguments and for various customizable # procedures are set in this file. # # A copy of this file is pasted into the beginning of texi2html by # running './configure'. # # Copy this file, rename it and make changes to it, if you like. # Afterwards, load the file with command-line # option --init-file # # $Id: texi2html.init,v 1.272 2010/06/26 09:54:22 pertusus Exp $ ###################################################################### # The following variables can also be set by command-line options # # # The default values are set in this file, texi2html.init and the content # of this file is included at the beginning of the texi2html script file. # Those values may be overrided by values set in $sysconfdir/texi2html/Config # and then by values set in $HOME/texi2html/Config. # # command line switches may override these values, and values set in files # specified by --init-file are also taken into account. # values set in these files overwrite values set by the command-line # options appearing before --init-file and might still be overwritten by # command-line arguments following the --init-file option. ################################################################## # options common with makeinfo # -I # add a directory to the list of directories where @include files are # searched for (besides the directory of the file). additional '-I' # args are appended to this list. # (APA: Don't implicitely search ., to conform with the docs!) # my @INCLUDE_DIRS = ("."); #use strict; @INCLUDE_DIRS = (); # -P # prepend a directory to the list of directories where @include files are # searched for before the directory of the file. additional '-P' # args are prepended to this list. @PREPEND_DIRS = (); # --split section|chapter|node|none # if $SPLIT is set to 'section' (resp. 'chapter') one html file per section # (resp. chapter) is generated. If $SPLIT is set to 'node' one html file per # node or sectioning element is generated. In all these cases separate pages # for Top, Table of content (Toc), Overview and About are generated. # Otherwise a monolithic html file that contains the whole document is # created. #$SPLIT = 'section'; $SPLIT = ''; # --separated-footnotes # if this is set footnotes are on a separated page. Otherwise they are at # the end of each file (if the document is split). $FOOTNOTESTYLE = 'end'; # --fill-column $FILLCOLUMN = 72; # --number | --no-number # if this is set the sections are numbered, and section names and numbers # are used in references and menus (instead of node names). $NUMBER_SECTIONS = 1; # --headers # if this is set then navigation panels are printed at the beginning of each # section. # If the document is split at nodes then navigation panels are # printed at the end if there were more than $WORDS_IN_PAGE words on page. # # Navigation panels are always printed at the beginning of output files. # # This is most useful if you do not want to have section navigation # with --split chapter. There will be chapter navigation panel at the # beginning and at the end of chapters anyway. # this is mostly not used in the default case, important for html. $HEADERS = 0; # -o filename # If this is set a monolithic document is outputted into $filename. $OUT = undef; # --split-size # if undef, the info output is not split $SPLIT_SIZE = 300000; # --internal-links $INTERNAL_LINKS = undef; # --no-validate # suppress node cross-reference validation $NOVALIDATE = 0; # --documentlanguage # use gdt('my string') if you want to have translations of 'my string' # and provide the translations in $LANGUAGES->{$DOCUMENTLANGUAGE} with # 'my string' as key. # To add a new language use ISO 639 language codes (see e.g. perl module # Locale-Codes-1.02 for definitions). Supply translations in the # $LANGUAGES hash and put it in a file with $LANG as name in an i18n # directory. # This is used for the initial language, it is overriden during # document processing if there is a @documentlanguage. # It is ignored if the language is passed on the command line. $DOCUMENTLANGUAGE = 'en'; # --transliterate-file-names # transliterate node names for external refs (and internal if NODE_FILES) $TRANSLITERATE_FILE_NAMES = 1; # --error-limit # quit after NUM errors (default 1000). $ERROR_LIMIT = 1000; # --css-include # All the specified css files are used. More precisely the @import sections # are added to the beginning of the CSS_LINES the remaining is added at # the end of the CSS_LINES (after the css rules generated by the program). # cf texinfo manual for more info. # - means STDIN @CSS_FILES = (); # --css-ref # the specified url are used as stylesheet links @CSS_REFS = (); # --paragraph-indent $PARAGRAPHINDENT = 3; # --enable-encoding $ENABLE_ENCODING = 0; # --force $FORCE = 0; # --no-warn $NO_WARN = 0; # --number-footnotes $NUMBER_FOOTNOTES = 1; # not in makeinfo but in texi2dvi # --command @COMMANDS = (); ################################################################## # option specific of texi2html # --debug # The integer value specifies what kind of debugging output is generated. $DEBUG = 0; # --doctype # The value is the 'SystemLiteral' which identifies the canonical DTD # for the document. # Definition: The SystemLiteral is called the entity's system # identifier. It is a URI, which may be used to retrieve the entity. # See http://www.xml.com/axml/target.html#NT-ExternalID $DOCTYPE = ''; # --frameset-doctype # When frames are used, this SystemLiteral identifies the DTD used for # the file containing the frame description. $FRAMESET_DOCTYPE = ''; # --test # If this value is true, some variables which should be dynamically generated # (the date, the user running texi2html, the version of texi2html) are set to # fix and given values. This is usefull in case the resulting manual is # compared with a reference. For example this is used in the tests. $TEST = 0; # --dump-texi # This value is usefull for debugging purposes. The result of the first pass is # put in .passtexi, the result of the second pass is put in # .passfirst. $DUMP_TEXI = 0; # --expand # the @EXPAND array contains the expanded section names. @EXPAND = (); # --invisible # This seems obsolete and is not used anywhere. # This was a workaround for a known bug of many WWW browsers, including # netscape. This was used to create invisible destination in anchors. $INVISIBLE_MARK = ''; # $INVISIBLE_MARK = ' '; # --iso # if this value is true, ISO8859 characters are used for quotes. # --iso does more than what USE_ISO does. $USE_ISO = 0; # --conf-dir # append to the files searched for init files. @CONF_DIRS = (); # --top-file # This file name is used for the top-level file. # The extension is set appropriately, if necessary. # If empty, .html is used. # Typically, you would set this to "index.html". $TOP_FILE = ''; # --toc-file # This file name is used for the table of contents. The # extension is set appropriately, if necessary. # If empty, _toc.html is used. $TOC_FILE = ''; # --frames # if the value is true, HTML 4.0 "frames" are used. # A file describing the frame layout is generated, together with a file # with the short table of contents. $FRAMES = 0; # --menu | --no-menu # if the value is true the Texinfo menus are shown. # this is defined in all the formats $SHOW_MENU = 1; # --use-nodes # if this is set the nodes are used as sectioning elements. # Otherwise the nodes are incorporated in sections. $USE_NODES = 1; # --node-files # if this is set one file per node is generated, which can be a target for # cross manual references. $NODE_FILES = 0; # --toc-links # if this is set, links from headings to toc entries are created. $TOC_LINKS = 0; # --subdir # If this is set, then put result files into the specified directory. # If not set, then result files are put into the current directory. #$SUBDIR = 'html'; $SUBDIR = ''; # --short-extn # If this is set, then all HTML files will have extension ".htm" instead of # ".html". This is helpful when shipping the document to DOS-based systems. $SHORTEXTN = 0; # --prefix # This set the output file prefix, prepended to all .html, .gif and .pl files. # By default, this is the basename of the document. $PREFIX = ''; # --short-ref # if this is set cross-references are given without section. $SHORT_REF = 1; # --idx-sum # if value is set, then for each @printindex # _.idx is created which contains lines of the form # key ref sorted alphabetically (case matters). $IDX_SUMMARY = 0; # --def-table # If this is set a table construction for @def.... instead of definition # lists. # (New Option: 27.07.2000 Karl Heinz Marbaise) $DEF_TABLE = 0; # --verbose # if this is set chatter about what we are doing. $VERBOSE = ''; # --ignore-preamble-text # If this is set the text before @node and sectioning commands is ignored. $IGNORE_PREAMBLE_TEXT = 0; # --html-xref-prefix # base directory for external manuals. #$EXTERNAL_DIR = '../'; $EXTERNAL_DIR = undef; # --l2h # if this is set, latex2html is used for generation of math content. $L2H = ''; # --monolithic # output only one file including ToC. It only makes sense when not split $MONOLITHIC = 1; ###################### # The following options are only relevant if $L2H is set # # --l2h-l2h # name/location of latex2html program $L2H_L2H = "latex2html"; # --l2h-skip # If this is set the actual call to latex2html is skipped. The previously # generated content is reused, instead. # If set to 0, the cache is not used. # If undef the cache is used for as many tex fragments as possible # and for the remaining the command is run. $L2H_SKIP = undef; # --l2h-tmp # If this is set l2h uses the specified directory for temporary files. The path # leading to this directory may not contain a dot (i.e., a "."); # otherwise, l2h will fail. $L2H_TMP = ''; # --l2h-file # If set, l2h uses the file as latex2html init file $L2H_FILE = 'l2h.init'; # --l2h-clean # if this is set the intermediate files generated by texi2html in relation with # latex2html are cleaned (they all have the prefix _l2h_). $L2H_CLEAN = 1; ############################################################################## # # The following can only be set in the init file # ############################################################################## @INPUT_FILE_SUFFIXES = ('.txi','.texinfo','.texi','.txinfo',''); $FIRSTPARAGRAPHINDENT = 'none'; @T2H_FORMAT_EXPAND = ('plaintext'); # simple headers formatting, not in a table and using node names. $HEADER_IN_TABLE = 0; # output the generation date in the header. $DATE_IN_HEADER = 0; # use table for indentation of complex formats $COMPLEX_FORMAT_IN_TABLE = 0; # if set, node names are used to construct file names # if undef, it is set if split at node, or $NODE_FILES is set. $NODE_FILENAMES = undef; # If true do table of contents even if there is no @content $CONTENTS = undef; # If true do short table of contents even if there is no @shortcontent $SHORTCONTENTS = undef; # set by @setcontentsaftertitlepage/@setshortcontentsaftertitlepage $SETCONTENTSAFTERTITLEPAGE = undef; $SETSHORTCONTENTSAFTERTITLEPAGE = undef; # corresponds with @kbdinputstyle $KBDINPUTSTYLE = 'distinct'; # corresponds with @frenchspacing $FRENCHSPACING = 'off'; # correspond with @allowcodebreaks $ALLOWCODEBREAKS = 'true'; # corresponds with @setfilename. Set with caution. $SETFILENAME = undef; # if unset, don't show a title $SHOW_TITLE = 1; # if set style is added in attribute. $INLINE_CSS_STYLE = 0; # if set, no css is used. $NO_CSS = 0; # if set, the image files are completed to be relative from the # document directory, to the source manual directory and then to # the image $COMPLETE_IMAGE_PATHS = 0; # if true, begin outputting at @setfilename, if this command is present. $IGNORE_BEFORE_SETFILENAME = 1; # if true the link in Overview link to the corresponding Toc entry. $OVERVIEW_LINK_TO_TOC = 1; # if set, use node anchors for sections targets $USE_NODE_TARGET = 1; # new style for crossrefs $NEW_CROSSREF_STYLE = 1; # top heading is always at the beginning of the element. $TOP_HEADING_AT_BEGINNING = 0; # use titlepage for the title instead of a simplest title $USE_TITLEPAGE_FOR_TITLE = 0; # if set, center @image by default # otherwise, do not center by default # Deprecated and not used anymore $CENTER_IMAGE = 1; # used as identation for block enclosing command @example, etc # If not empty, must be enclosed in $EXAMPLE_INDENT_CELL = ''; # same as above, only for @small $SMALL_EXAMPLE_INDENT_CELL = ''; # unused $SMALL_FONT_SIZE = '-1'; # horizontal rules # not used $SMALL_RULE = ''; $MIDDLE_RULE = ''; # used in html $DEFAULT_RULE = ''; $BIG_RULE = ''; # output the program name in the footer $PROGRAM_NAME_IN_FOOTER = 0; # if non-empty, and no @..heading appeared in Top node, then # use this as header for top node/section, otherwise use value of # @settitle or @shorttitle (in that order) $TOP_HEADING = ''; # if set, use this chapter for 'Index' button, else # use first chapter with @printindex $INDEX_CHAPTER = ''; $SIMPLE_MENU = 1; $OPEN_QUOTE_SYMBOL = "\`"; $CLOSE_QUOTE_SYMBOL = "'"; $NO_NUMBER_FOOTNOTE_SYMBOL = '*'; # if true put a $MENU_SYMBOL before unnumbered in menus $UNNUMBERED_SYMBOL_IN_MENU = 0; # extension for nodes files when NODE_FILES is true $NODE_FILE_EXTENSION = 'txt'; # extension $EXTENSION = 'txt'; # file name used for Top node when NODE_FILES is true #$TOP_NODE_FILE = 'index'; $TOP_NODE_FILE = undef; # file name used for Top node in references $TOP_NODE_FILE_TARGET = 'index'; # file used as document basename, when input file is - $STDIN_DOCU_NAME = 'stdin'; # file used as document output basename, when output file is - $STDOUT_DOCU_NAME = 'stdout'; # node name used for Top node when automatic node directions are used $TOP_NODE_UP = '(dir)'; # this controls the pre style for menus $MENU_PRE_STYLE = 'font-family: serif'; # on bug-texinfo is has been said the the style is not code_style # for menus (except for the node name). # this controls the menu preformatted format # FIXME this is not dynamic, so change in MENU_PRE_STYLE is not taken # into account. # This is used if the menu appears within a preformatted format (which # is certainly an invalid construct), and SIMPLE_MENU is not set. $MENU_PRE_COMPLEX_FORMAT = { 'class' => 'menu-preformatted', # 'style' => 'code' }; # This controls the ul style for toc $NO_BULLET_LIST_STYLE = ''; $NO_BULLET_LIST_ATTRIBUTE = ''; # These lines are inserted before and after the shortcontents $BEFORE_OVERVIEW = ""; $AFTER_OVERVIEW = ""; # These lines are inserted before and after the contents $BEFORE_TOC_LINES = ""; $AFTER_TOC_LINES = ""; # if set (e.g., to index.html) replace hrefs to this file # (i.e., to index.html) by ./ # Obsolete. Worked around a bug that is fixed now. $HREF_DIR_INSTEAD_FILE = ''; # text inserted after $AFTER_BODY_OPEN = ''; # text inserted before , this will be automatically inside

    $PRE_BODY_CLOSE = ''; # this is added inside after and some <meta name> # stuff, it can be used for eg. <style>, <script>, <meta> etc. tags. $EXTRA_HEAD = ''; # Specifies the minimum page length required before a navigation panel # is placed at the bottom of a page # FIXME this is not true: # THIS_WORDS_IN_PAGE holds number of words of current page $WORDS_IN_PAGE = 300; # if this is set a vertical navigation panel is used. $VERTICAL_HEAD_NAVIGATION = 0; # html version for latex2html $L2H_HTML_VERSION = "4.0"; # use icons. $ICONS = 0; # use old framework for translations $I18N_PERL_HASH = 0; # this resets some defaults, those that are also set in formats and # not set in every formats. # # this is called below after %default_style_map_texi is defined sub t2h_default_set_variables_default() { $CAPTION_STYLE = 'strong'; # if this variable is true, @setfilename is used if found to determine the # out file name $USE_SETFILENAME = 1; # if true, use the filename and extension from setfilename. For Info. $USE_SETFILENAME_EXTENSION = 0; # FIXME is this right? # default used in init_out for the setting of the ENCODING_NAME variable $DEFAULT_ENCODING = 'utf8'; # if set and menu entry equals menu description, then do not print # menu description. # Likewise, if node name equals entry name, do not print entry name. $AVOID_MENU_REDUNDANCY = 0; # if true, use the original command if the result is an entity $ENABLE_ENCODING_USE_ENTITY = 0; # if set, output the contents where the command is located # This is ignored if set*contentsaftertitlepage is set $INLINE_CONTENTS = 1; # symbol put at the beginning of nodes entry in menu (and optionnaly of # unnumbered in menus, see UNNUMBERED_SYMBOL_IN_MENU variable) $MENU_SYMBOL = '*'; # symbol put at the end of nodes entry in menu $MENU_ENTRY_COLON = ':'; # symbol put at the end of index entries $INDEX_ENTRY_COLON = ':'; # if set, then use node names in menu entries, instead of section names $NODE_NAME_IN_MENU = 1; # if set use the node names in index entry, instead of section names # if not set, it is set to the same value than NODE_NAME_IN_MENU $NODE_NAME_IN_INDEX = undef; # if set always separate description and menu link, even in # preformatted environment $SEPARATE_DESCRIPTION = 0; # try up sections to complete the node directions $USE_UP_FOR_ADJACENT_NODES = 0; # use accesskey in hrefs $USE_ACCESSKEY = 1; # use rel= and rev= in hrefs. Currently only rel is used $USE_REL_REV = 1; # generate <link> elements in head $USE_LINKS = 1; # if this variable is true, numeric entities are used when there is no # corresponding textual entity. $USE_NUMERIC_ENTITY = 0; # if set and $SPLIT is set, then split index pages at the next letter # after they have more than that many entries $SPLIT_INDEX = 0; # file name used for Top node when NODE_FILES is true $TOP_NODE_FILE = undef; # extensions used for images @IMAGE_EXTENSIONS = ('png','jpg', 'txt'); $USE_NODES = 1; $USE_SECTIONS = 1; # also set by command line options $FOOTNOTESTYLE = 'end'; $DOCTYPE = ''; $USE_ISO = 0; $NUMBER_SECTIONS = 1; $TOP_FILE = ''; $ENABLE_ENCODING = 0; # # Formatting functions # # They will be reset here between formats switch # if they are defined in this function. # # these are more or less the documented vanilla versions, so they # are reset $unknown = \&t2h_default_unknown; $unknown_style = \&t2h_default_unknown_style; $external_ref = \&t2h_default_external_ref; $internal_ref = \&t2h_default_internal_ref; $tab_item_texi = \&t2h_default_tab_item_texi; $complex_format = \&t2h_default_complex_format; $toc_body = \&T2H_DEFAULT_toc_body; $misc_command_line = \&t2h_default_misc_command_line; $misc_command_line_texi = \&t2h_default_misc_command_line; $print_title = \&T2H_DEFAULT_print_title; # reset in info and xml $element_heading = \&t2h_default_element_heading; # reset in html $inline_contents = \&T2H_DEFAULT_inline_contents; # reset in docbook and info. $style = \&T2H_GPL_style; $format = \&T2H_GPL_format; # reset in info $simple_command = \&t2h_default_simple_command; # reset in info $thing_command = \&t2h_default_thing_command; # reset in html and xml $caption_shortcaption = \&t2h_default_caption_shortcaption; $caption_shortcaption_command = \&t2h_default_caption_shortcaption_command; # reset in docbook and xml. Not really vanilla, but documented. $printindex = \&t2h_GPL_default_printindex; # reset by xml and html $misc_element_label = \&t2h_default_misc_element_label; # set in html $init_out = \&t2h_default_init_out; # set in info and xml $paragraph_style_command = \&t2h_default_paragraph_style_command; # set in info $colon_command = \&t2h_default_colon_command; # set in docbook $quotation_prepend_text = \&t2h_default_quotation_prepend_text; # set in info $copying_comment = \&t2h_default_copying_comment; # set in html and info $print_section = \&T2H_DEFAULT_print_section; # set in docbook and xml %colon_command_punctuation_characters = ( '.' => '.', ':' => ':', '?' => '?', '!' => '!' ); # in info $footnote_texi = undef; $begin_paragraph_texi = undef; $begin_style_texi = undef; $begin_special_region = undef; $end_special_region = undef; $empty_preformatted = undef; %line_command_map = ( 'title' => '', 'subtitle' => '', 'author' => '', ); %format_in_paragraph = ( ); # map mapping css specification to style %css_map = ( ); @text_substitutions_normal = (); @text_substitutions_texi = (); @text_substitutions_simple_format = (); @text_substitutions_pre = (); %region_formats_kept = (); %style_map_texi = (); t2h_default_copy_style_map (\%default_style_map_texi, \%style_map_texi); # reset in info %simple_map_texi = %default_simple_map; # modified in docbook %special_accents = ( 'ringaccent' => 'aA', "'" => 'aeiouyAEIOUY', ',' => 'cC', '^' => 'aeiouAEIOU', '`' => 'aeiouAEIOU', '~' => 'nNaoAO', '"' => 'aeiouyAEIOU', # according to http://www2.lib.virginia.edu/small/vhp/download/ISO.txt # however this doesn't seems to work in firefox # 'ogonek' => 'aeiuAEIU', ); # modified by info, xml, docbook # %no_paragraph_commands should not be reset since it has been # filled with defaults for many other commands. # FIXME this prevents the user from setting those entries. $no_paragraph_commands{'cindex'} = 1; $no_paragraph_commands{'float'} = 1; delete $no_paragraph_commands{'anchor'}; # modified in docbook and xml %stop_paragraph_command = ( 'titlefont' => 1, 'insertcopying' => 1, 'sp' => 1, 'verbatiminclude' => 1, 'page' => 1, # FIXME they also stop preformatted, so cannot be here. # 'printindex' => 1, # 'listoffloats' => 1 ); } sub t2h_default_raw_text_load() { $SPLIT = ''; # extension for nodes files when NODE_FILES is true $NODE_FILE_EXTENSION = 'txt'; # extension $EXTENSION = 'txt'; @T2H_FORMAT_EXPAND = ('plaintext'); $USE_TITLEPAGE_FOR_TITLE = 0; $HEADERS = 0; $SIMPLE_MENU = 1; $INLINE_INSERTCOPYING = 0; $NODE_FILENAMES = undef; %simple_map = %default_simple_map; %simple_map_pre = %simple_map; %things_map = %default_things_map; %pre_map = %things_map; %style_map = (); %style_map_pre = (); t2h_default_copy_style_map (\%default_style_map, \%style_map); t2h_default_copy_style_map (\%default_style_map_pre, \%style_map_pre); # could also be t2h_default_set_iso_symbols() t2h_remove_text_substitutions("'", 1, 0, 0, 1); t2h_remove_text_substitutions('`', 1, 0, 0, 1); $OPEN_QUOTE_SYMBOL = '`'; $CLOSE_QUOTE_SYMBOL = "'"; $BEFORE_OVERVIEW = ""; $AFTER_OVERVIEW = ""; $BEFORE_TOC_LINES = ""; $AFTER_TOC_LINES = ""; foreach my $complex_format ('example', 'smallexample', 'display', 'smalldisplay', 'lisp', 'smalllisp', 'format', 'smallformat', 'menu', 'detailmenu', 'direntry', 'menu_comment') { $complex_format_map{$complex_format}->{'begin'} = ''; $complex_format_map{$complex_format}->{'end'} = ''; } %format_map = ( # 'quotation' => 'blockquote', # lists # 'itemize' => 'ul', 'enumerate' => '', # 'multitable' => 'table', 'table' => '', 'vtable' => '', 'ftable' => '', 'group' => '', 'raggedright' => '', # 'detailmenu' => '', ); # # Controls the layout # $print_page_head = \&T2H_DEFAULT_print_page_head; $contents = \&T2H_DEFAULT_contents; $shortcontents = \&T2H_DEFAULT_shortcontents; $one_section = \&T2H_DEFAULT_one_section; $print_Top = \&T2H_DEFAULT_print_Top; $print_Top_footer = \&T2H_DEFAULT_print_Top_footer; $print_misc_header = \&T2H_DEFAULT_print_misc_header; $print_misc_footer = \&T2H_DEFAULT_print_misc_footer; $print_section_footer = \&T2H_DEFAULT_print_section_footer; $print_chapter_header = \&T2H_DEFAULT_print_chapter_header; $print_section_header = \&T2H_DEFAULT_print_section_header; $print_chapter_footer = \&T2H_DEFAULT_print_chapter_footer; $print_page_foot = \&T2H_DEFAULT_print_page_foot; $print_head_navigation = \&T2H_DEFAULT_print_head_navigation; $print_foot_navigation = \&T2H_DEFAULT_print_foot_navigation; $end_section = \&T2H_DEFAULT_end_section; # changed in info $print_Footnotes = \&T2H_DEFAULT_print_Footnotes; # used if split $about_body = \&T2H_DEFAULT_about_body; $print_navigation = \&T2H_DEFAULT_print_navigation; # # Controls the formatting # $empty_line = \&t2h_default_empty_line; $anchor = \&t2h_default_anchor; $anchor_label = \&t2h_default_anchor_label; $image = \&t2h_default_image; $heading = \&t2h_default_heading; $heading_text = \&t2h_default_heading_text; $heading_text_preformatted = \&t2h_default_heading_text_preformatted; $element_label = \&t2h_default_element_label; $index_entry_label = \&t2h_default_index_entry_label; #$menu_command = \&t2h_default_menu_command; $menu_link = \&t2h_default_menu_link; #$menu_description = \&t2h_default_menu_description; $paragraph = \&t2h_default_paragraph; $preformatted = \&t2h_default_preformatted; $protect_text = \&t2h_default_protect_text; $normal_text = \&t2h_default_normal_text; $acronym_like = \&t2h_default_acronym_like; $sp = \&t2h_default_sp; $quotation = \&t2h_default_quotation; $table_list = \&t2h_default_table_list; $list_item = \&t2h_default_list_item; $table_line = \&t2h_default_table_line; $table_item = \&t2h_default_table_item; $cell = \&t2h_default_cell; $row = \&t2h_default_row; $def_item = \&t2h_default_def_item; $def = \&t2h_default_def; $def_line = \&t2h_default_def_line; $cartouche = \&t2h_default_cartouche; $raw = \&t2h_default_raw; $format_list_item_texi = \&t2h_default_format_list_item_texi; $print_index = \&t2h_default_print_index; $index_summary = \&t2h_default_index_summary; $index_entry = \&t2h_default_index_entry; $index_letter = \&t2h_default_index_letter; $foot_line_and_ref = \&t2h_default_foot_line_and_ref; $foot_section = \&t2h_default_foot_section; $tab_item_texi = \&t2h_default_tab_item_texi; $listoffloats = \&t2h_default_listoffloats; $listoffloats_entry = \&t2h_default_listoffloats_entry; $float = \&t2h_default_float; t2h_default_set_variables_default(); } my %things_map_xml; my %pre_map_xml; sub t2h_default_set_variables_xml() { t2h_default_set_variables_default(); $ENABLE_ENCODING_USE_ENTITY = 1; $EXTENSION = 'xml'; t2h_default_set_iso_symbols(1); $empty_line = \&t2h_default_empty_line; $comment = \&xml_default_comment; $line_command = \&xml_default_line_command; %things_map = %things_map_xml; %pre_map = %pre_map_xml; %simple_format_texi_map = %pre_map; %simple_format_style_map_texi = (); t2h_default_copy_style_map (\%default_style_map_texi, \%simple_format_style_map_texi); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { # $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal']; $simple_format_style_map_texi{$accent_command}->{'function'} = \&xml_default_accent; } } sub t2h_default_set_variables_texi2html() { $USE_SETFILENAME = 0; $USE_SETFILENAME_EXTENSION = 0; $FOOTNOTESTYLE = 'separate'; $INLINE_CONTENTS = 0; $FORCE = 1; $AVOID_MENU_REDUNDANCY = 1; $TOP_HEADING_AT_BEGINNING = 1; $TOP_FILE = ''; $USE_ACCESSKEY = 0; $NODE_NAME_IN_MENU = 0; $OVERVIEW_LINK_TO_TOC = 0; $USE_UP_FOR_ADJACENT_NODES = 1; $USE_ACCESSKEY = 0; $USE_REL_REV = 0; $USE_LINKS = 0; $USE_NODES = undef; $USE_SECTIONS = 1; $NODE_FILENAMES = 0; $USE_NUMERIC_ENTITY = 1; $SPLIT = ''; $SPLIT_INDEX = 100; $PROGRAM_NAME_IN_FOOTER = 1; $HEADER_IN_TABLE = 1; $SHORT_REF = 0; $USE_TITLEPAGE_FOR_TITLE = 1; $MENU_ENTRY_COLON = ''; $INDEX_ENTRY_COLON = ''; $ENABLE_ENCODING_USE_ENTITY = 1; } # specify in this array which "buttons" should appear in which order # in the navigation panel for sections; use ' ' for empty buttons (space) @SECTION_BUTTONS = ( 'FastBack', 'Back', 'Up', 'Forward', 'FastForward', ' ', ' ', ' ', ' ', 'Top', 'Contents', 'Index', 'About', ); # buttons for misc stuff @MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About'); @TOP_BUTTONS = ( 'Back', 'Forward', ' ','Contents', 'Index', 'About'); #@TOP_BUTTONS = ('Top', 'Contents', 'Index', 'About'); # buttons for chapter file footers # (and headers but only if HEADERS is false) @CHAPTER_BUTTONS = ( 'FastBack', 'FastForward', ' ', ' ', ' ', ' ', ' ', 'Top', 'Contents', 'Index', 'About', ); # buttons for section file footers @SECTION_FOOTER_BUTTONS = ( 'FastBack', 'Back', 'Up', 'Forward', 'FastForward', ); @NODE_FOOTER_BUTTONS = @SECTION_BUTTONS; @LINKS_BUTTONS = ( 'Top', 'Index', 'Contents', 'About', 'Up', 'NextFile', 'PrevFile' ); # insert here name of icon images for buttons # Icons are used, if $ICONS and resp. value are set %ACTIVE_ICONS = ( 'Top', '', 'Contents', '', 'Overview', '', 'Index', '', 'This', '', 'Back', '', 'FastBack', '', 'Prev', '', 'Up', '', 'Next', '', 'NodeUp', '', 'NodeNext', '', 'NodePrev', '', 'Following', '', 'Forward', '', 'FastForward', '', 'About' , '', 'First', '', 'Last', '', 'NextFile', '', 'PrevFile', '', ' ', '', ); # insert here name of icon images for these, if button is inactive %PASSIVE_ICONS = ( 'Top', '', 'Contents', '', 'Overview', '', 'Index', '', 'This', '', 'Back', '', 'FastBack', '', 'Prev', '', 'Up', '', 'Next', '', 'NodeUp', '', 'NodeNext', '', 'NodePrev', '', 'Following', '', 'Forward', '', 'FastForward', '', 'About', '', 'First', '', 'Last', '', 'NextFile', '', 'PrevFile', '', ); %misc_pages_targets = ( 'Overview' => 'SEC_Overview', 'Contents' => 'SEC_Contents', 'Footnotes' => 'SEC_Foot', 'About' => 'SEC_About' ); # determine the null devices my $default_null_device = File::Spec->devnull(); %null_device_file = ( $default_null_device => 1 ); # special case, djgpp recognizes both null devices if ($Config{osname} eq 'dos' and $Config{osvers} eq 'djgpp') { $null_device_file{'/dev/null'} = 1; $null_device_file{'NUL'} = 1; } $finish_out = \&t2h_default_finish_out; $translate_names = \&t2h_default_translate_names; sub t2h_default_translate_names() { # Names of text as alternative for icons # FIXME maybe get those in simple_format? %NAVIGATION_TEXT = ( 'Top', gdt('Top'), 'Contents', gdt('Contents'), 'Overview', gdt('Overview'), 'Index', gdt('Index'), ' ', ' ', 'This', gdt('Current'), 'Back', ' < ', 'FastBack', ' << ', 'Prev', gdt('Previous'), 'Up', gdt('Up'), 'Next', gdt('Next'), 'NodeUp', gdt('Up'), 'NodeNext', gdt('Next'), 'NodePrev', gdt('Previous'), 'Following', gdt('Following'), 'Forward', ' > ', 'FastForward', ' >> ', 'About', ' ? ', 'First', ' |< ', 'Last', ' >| ', 'NextFile', gdt('Next file'), 'PrevFile', gdt('Previous file'), ); %BUTTONS_TEXT = %NAVIGATION_TEXT; %BUTTONS_GOTO = ( 'Top', gdt('Cover (top) of document'), 'Contents', gdt('Table of contents'), 'Overview', gdt('Short table of contents'), 'Index', gdt('Index'), 'This', gdt('Current section'), 'Back', gdt('Previous section in reading order'), 'FastBack', gdt('Beginning of this chapter or previous chapter'), 'Prev', gdt('Previous section on same level'), 'Up', gdt('Up section'), 'Next', gdt('Next section on same level'), 'NodeUp', gdt('Up node'), 'NodeNext', gdt('Next node'), 'NodePrev', gdt('Previous node'), 'Following', gdt('Node following in node reading order'), 'Forward', gdt('Next section in reading order'), 'FastForward', gdt('Next chapter'), 'About' , gdt('About (help)'), 'First', gdt('First section in reading order'), 'Last', gdt('Last section in reading order'), 'NextFile', gdt('Forward section in next file'), 'PrevFile', gdt('Back section in previous file'), ); %BUTTONS_NAME = ( 'Top', gdt('Top'), 'Contents', gdt('Contents'), 'Overview', gdt('Overview'), 'Index', gdt('Index'), ' ', ' ', 'This', gdt('This'), 'Back', gdt('Back'), 'FastBack', gdt('FastBack'), 'Prev', gdt('Prev'), 'Up', gdt('Up'), 'Next', gdt('Next'), 'NodeUp', gdt('NodeUp'), 'NodeNext', gdt('NodeNext'), 'NodePrev', gdt('NodePrev'), 'Following', gdt('Following'), 'Forward', gdt('Forward'), 'FastForward', gdt('FastForward'), 'About', gdt('About'), 'First', gdt('First'), 'Last', gdt('Last'), 'NextFile', gdt('NextFile'), 'PrevFile', gdt('PrevFile'), ); } sub t2h_default_set_iso_symbols($) { my $value = shift; $USE_ISO = $value; if ($value) { foreach my $association ([\%things_map, \%things_map_xml], [\%pre_map, \%pre_map_xml], [\%simple_format_simple_map_texi, \%pre_map_xml]) { foreach my $thing (keys(%{$association->[0]})) { if (defined($association->[0]->{$thing}) and $association->[0]->{$thing} !~ /^\&\w+\;$/ and defined($association->[1]->{$thing}) and $association->[1]->{$thing} =~ /^\&\w+\;$/) { $association->[0]->{$thing} = $association->[1]->{$thing}; } } } t2h_add_text_substitutions(["'", '’'], 1, 0, 0, 1); t2h_add_text_substitutions(['`', '‘'], 1, 0, 0, 1); $OPEN_QUOTE_SYMBOL = '‘'; $CLOSE_QUOTE_SYMBOL = '’'; } else { foreach my $association ([\%things_map, \%default_things_map], [\%pre_map, \%default_things_map], [\%simple_format_simple_map_texi, \%default_things_map]) { foreach my $thing (keys(%{$association->[0]})) { if (defined($association->[0]->{$thing}) and $association->[0]->{$thing} =~ /^\&\w+\;$/ and defined($association->[1]->{$thing}) and $association->[1]->{$thing} !~ /^\&\w+\;$/) { $association->[0]->{$thing} = &$protect_text($association->[1]->{$thing}); } } } t2h_remove_text_substitutions("'", 1, 0, 0, 1); t2h_remove_text_substitutions('`', 1, 0, 0, 1); $OPEN_QUOTE_SYMBOL = '`'; $CLOSE_QUOTE_SYMBOL = "'"; } } # is used in main program for dumping texi too. sub t2h_default_set_out_encoding() { # these variables are used for the corresponding # $Texi2HTML::THISDOC{'*_ENCODING'} to keep code shorter my ($out_encoding, $encoding_name, $document_encoding); $document_encoding = get_conf('DOCUMENT_ENCODING'); if (defined($OUT_ENCODING)) { $out_encoding = $OUT_ENCODING; } if (defined($ENCODING_NAME)) { $encoding_name = $ENCODING_NAME; } if (!defined($out_encoding) and (defined($encoding_name))) { my $possible_out_encoding = main::encoding_alias ($encoding_name, undef, 'determining encoding from default encoding'); $out_encoding = $possible_out_encoding if (defined($possible_out_encoding)); } if (!defined($out_encoding) and (defined(get_conf('IN_ENCODING')))) { $out_encoding = get_conf('IN_ENCODING'); } if (!defined($out_encoding) and (defined($document_encoding))) { my $possible_out_encoding = main::encoding_alias ($document_encoding, undef, 'determining encoding from documentencoding'); $out_encoding = $possible_out_encoding if (defined($possible_out_encoding)); } if (!defined($encoding_name)) { if (defined($out_encoding) and defined($perl_charset_to_html{$out_encoding})) { $encoding_name = $perl_charset_to_html{$out_encoding}; } elsif (defined(get_conf('IN_ENCODING')) and defined($perl_charset_to_html{get_conf('IN_ENCODING')})) { $encoding_name = $perl_charset_to_html{get_conf('IN_ENCODING')}; } elsif (defined($document_encoding) and defined($perl_charset_to_html{$document_encoding})) { $encoding_name = $perl_charset_to_html{$document_encoding}; } elsif (defined($out_encoding)) { $encoding_name = $out_encoding; } elsif (defined(get_conf('IN_ENCODING'))) { $encoding_name = get_conf('IN_ENCODING'); } elsif (defined($document_encoding)) { $encoding_name = $document_encoding; } elsif (defined($perl_charset_to_html{$DEFAULT_ENCODING})) { $encoding_name = $perl_charset_to_html{$DEFAULT_ENCODING}; } else { $encoding_name = 'us-ascii'; } } $Texi2HTML::THISDOC{'OUT_ENCODING'} = $out_encoding; $Texi2HTML::THISDOC{'ENCODING_NAME'} = $encoding_name; $out_encoding = 'UNDEF' if (!defined($out_encoding)); my $in_encoding = get_conf('IN_ENCODING'); $in_encoding = 'UNDEF' if (!defined($in_encoding)); $document_encoding = 'UNDEF' if (!defined($document_encoding)); print STDERR "# Encodings: doc $document_encoding, in $in_encoding out $out_encoding, name $encoding_name\n" if ($VERBOSE); } sub t2h_default_init_out() { &$translate_names; # set external cross ref splitting like splitting. if (!defined($EXTERNAL_CROSSREF_SPLIT)) { if (get_conf('SPLIT')) { $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = 1; } else { $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = 0; } } else { $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} = $EXTERNAL_CROSSREF_SPLIT; } } my %t2h_default_formats_load_table = ( 'html' => \&html_default_load, 'info' => \&info_default_load, 'docbook' => \&docbook_default_load, 'xml' => \&xml_default_load, 'plaintext' => \&plaintext_default_load, 'raw-text' => \&t2h_default_raw_text_load, ); sub t2h_default_load_format($;$) { my $format = shift; my $from_command_line = shift; if (defined($t2h_default_formats_load_table{$format})) { $OUTPUT_FORMAT = $format; &{$t2h_default_formats_load_table{$format}}($from_command_line); $Texi2HTML::THISDOC{'format_from_command_line'} = $format if ($from_command_line); return 1; } else { return 0; } } sub t2h_encoding_is_entity($) { my $text = shift; return 0 if (!$ENABLE_ENCODING_USE_ENTITY); return 1 if ($text =~ /^&/ and $text =~ /;$/); } # this is for info.init use vars qw(%t2h_enable_encoding_default_accent); my @t2h_enable_encoding_accents_stack; my %t2h_enable_encoding_default_commands; sub t2h_enable_encoding_load() { t2h_default_push_handler(\&t2h_enable_encoding_init, \@command_handler_names); t2h_default_push_handler(\&t2h_enable_encoding_finish, \@command_handler_finish); #push @command_handler_process, \&t2h_enable_encoding_init; #push @command_handler_finish, \&t2h_enable_encoding_finish; foreach my $key (keys(%unicode_accents), 'dotless') { $t2h_enable_encoding_default_accent{'normal'}->{$key} = $style_map{$key}->{'function'}; $t2h_enable_encoding_default_accent{'texi'}->{$key} = $style_map_texi{$key}->{'function'}; $t2h_enable_encoding_default_accent{'pre'}->{$key} = $style_map_pre{$key}->{'function'}; $style_map{$key}->{'function'} = \&t2h_enable_encoding_normal_accent; $style_map_texi{$key}->{'function'} = \&t2h_enable_encoding_texi_accent; $style_map_pre{$key}->{'function'} = \&t2h_enable_encoding_pre_accent; } foreach my $key (%things_map) { if (exists($unicode_map{$key}) and ($unicode_map{$key} ne '')) { $t2h_enable_encoding_default_commands{'normal'}->{$key} = $things_map{$key}; $t2h_enable_encoding_default_commands{'texi'}->{$key} = $texi_map{$key}; $t2h_enable_encoding_default_commands{'sorting'}->{$key} = $sorting_things_map{$key}; $t2h_enable_encoding_default_commands{'pre'}->{$key} = $pre_map{$key}; } } } sub t2h_enable_encoding_finish() { foreach my $key (%things_map) { if (exists($unicode_map{$key}) and ($unicode_map{$key} ne '')) { $things_map{$key} = $t2h_enable_encoding_default_commands{'normal'}->{$key}; $texi_map{$key} = $t2h_enable_encoding_default_commands{'texi'}->{$key}; $sorting_things_map{$key} = $t2h_enable_encoding_default_commands{'sorting'}->{$key}; $pre_map{$key} = $t2h_enable_encoding_default_commands{'pre'}->{$key}; } } } sub t2h_enable_encoding_init() { if ($Texi2HTML::THISDOC{'ENCODING_NAME'} eq 'utf-8') { foreach my $key (%things_map) { if (exists($unicode_map{$key}) and ($unicode_map{$key} ne '')) { $things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($things_map{$key})); $texi_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($texi_map{$key})); $sorting_things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($sorting_things_map{$key})); $pre_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($pre_map{$key})); } } } elsif (exists($makeinfo_encoding_to_map{$Texi2HTML::THISDOC{'ENCODING_NAME'}})) { my $enc_map = $makeinfo_encoding_to_map{$Texi2HTML::THISDOC{'ENCODING_NAME'}}; foreach my $key (%things_map) { if (exists($unicode_map{$key}) and ($unicode_map{$key} ne '') and exists($makeinfo_unicode_to_eight_bit{$enc_map}->{$unicode_map{$key}})) { # we let perl handle the conversion $things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($things_map{$key})); $texi_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($texi_map{$key})); $sorting_things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($sorting_things_map{$key})); $pre_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($pre_map{$key})); } } @t2h_enable_encoding_accents_stack = (); } } sub t2h_default_string_width($) { my $string = shift; if ($USE_UNICODE) { my $width = 0; foreach my $character(split '', $string) { if ($character =~ /\p{Unicode::EastAsianWidth::InFullwidth}/) { $width += 2; } else { $width += 1; } } return $width; } else { return length($string); } } sub t2h_default_finish_out() { } ####################################################################### # # Values guessed if not set here. The value used is in # $Texi2HTML::THISDOC{'VARNAME'} # ####################################################################### # In file encoding. The @documentencoding allows autodetection of # that variable. $DOCUMENT_ENCODING = undef; # In file encoding, understandable by perl. Set according to DOCUMENT_ENCODING $IN_ENCODING = undef; # Formatted document encoding name. If undef, set in init_out based on # $OUT_ENCODING or $DOCUMENT_ENCODING if they are defined $ENCODING_NAME = undef; # Out files encoding, understandable by perl. If undef, set in init_out # using $ENCODING_NAME or $IN_ENCODING if they are defined $OUT_ENCODING = undef; # Used to set $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'}. # if undef set to @documentdescription. If there is no @documentdescription, # set in page_head. $DOCUMENT_DESCRIPTION = undef; # if undef $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'} set 1 if SPLIT, # to 0 otherwise $EXTERNAL_CROSSREF_SPLIT = undef; $DATE = undef; ######################################################################## # Control of Page layout: # You can make changes of the Page layout at two levels: # 1.) For small changes, it is often enough to change the value of # some global string/hash/array variables # 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines, # give them another name, and assign them to the respective # $<fnc> variable. # As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, Texi2HTML::SIMPLE_TEXT hold # href, html-name, node-name, name after removal of texi commands of # This -- current section (resp. html page) # Top -- top element # Contents -- Table of contents element # Overview -- Short table of contents element # Index -- Index page element # About -- page which explain "navigation buttons" element # First -- first node element # Last -- last node element # # Whether or not the following hash values are set, depends on the context # (all values are w.r.t. 'This' section) # Next -- next element of texinfo # Prev -- previous element of texinfo # NodeUp -- up node of texinfo # Following -- following node in node reading order, taking menu into account # Forward -- next node in reading order # Back -- previous node in reading order # Up -- parent given by sectioning commands # FastForward -- if leave node, up and next, else next node # FastBackward-- if leave node, up and prev, else prev node # # Furthermore, the following global variabels are set: # $Texi2HTML::THISDOC{title} -- title as set by @title... # $Texi2HTML::THISDOC{title_no_texi} -- title without texi (without html elements) # $Texi2HTML::THISDOC{title_texi} -- title with texinfo @-commands # $Texi2HTML::THISDOC{fulltitle} -- full title as set by @title... # $Texi2HTML::THISDOC{subtitle} -- subtitle as set by @subtitle # $Texi2HTML::THISDOC{author} -- author as set by @author # $Texi2HTML::THISDOC{copying_comment} -- text of @copying and @end copying in comment # # $Texi2HTML::THISDOC{program} -- name and version of texi2html # $Texi2HTML::THISDOC{program_homepage} -- homepage for texi2html # $Texi2HTML::THISDOC{program_authors} -- authors of texi2html # $Texi2HTML::THISDOC{today} -- date formatted with pretty_date # $Texi2HTML::THISDOC{toc_file} -- table of contents file # $Texi2HTML::THISDOC{file_base_name} -- base name of the texinfo manual file # $Texi2HTML::THISDOC{input_file_name} -- name of the texinfo manual file # $Texi2HTML::THISDOC{destination_directory} # -- directory for the resulting files # $Texi2HTML::THISDOC{user} -- user running the script # $Texi2HTML::THISDOC{css_import_lines} -- ref on @import lines in css files # $Texi2HTML::THISDOC{css_rule_lines} -- ref on css rules lines # other $Texi2HTML::THISDOC keys corresponds with texinfo commands, the value # being the command arg, for the following commands: # kbdinputstyle, paragraphindent, setchapternewpage, headings, footnotestyle, # exampleindent, firstparagraphindent, everyheading, everyfooting, # evenheading, evenfooting, oddheading, oddfooting # # and pointer to arrays of lines which need to be printed by main::print_lines # $Texi2HTML::THIS_SECTION -- lines of 'This' section # $Texi2HTML::OVERVIEW -- lines of short table of contents # $Texi2HTML::TOC_LINES -- lines of table of contents # $Texi2HTML::TITLEPAGE -- lines of title page # # $Texi2HTML::THIS_ELEMENT holds the element reference. # most of the functions are either reset when switching format, in # t2h_default_set_variables_default, or set in format, the simplest # one being setup above in t2h_default_raw_text_load # # The following generic subs control the layout: # # misc element formatting functions. They are rather generic, # their call is controlled by other variables (separate or not # footnotes, about_body, handling of table of contents...). # print_Footnotes is the only to be redefined, in info $print_Toc = \&T2H_DEFAULT_print_Toc; $print_Overview = \&T2H_DEFAULT_print_Overview; $print_About = \&T2H_DEFAULT_print_About; $print_misc = \&T2H_DEFAULT_print_misc; # generic enough (call print_page_head if needed) $print_Top_header = \&T2H_DEFAULT_print_Top_header; # the following are less generic, but in case a specific format # doesn't redefine them, the raw text functions are always defined. $print_page_head = \&T2H_DEFAULT_print_page_head; $contents = \&T2H_DEFAULT_contents; $shortcontents = \&T2H_DEFAULT_shortcontents; $one_section = \&T2H_DEFAULT_one_section; $print_Top = \&T2H_DEFAULT_print_Top; $print_Top_footer = \&T2H_DEFAULT_print_Top_footer; $print_misc_header = \&T2H_DEFAULT_print_misc_header; $print_misc_footer = \&T2H_DEFAULT_print_misc_footer; $print_section_footer = \&T2H_DEFAULT_print_section_footer; $print_chapter_header = \&T2H_DEFAULT_print_chapter_header; $print_section_header = \&T2H_DEFAULT_print_section_header; $print_chapter_footer = \&T2H_DEFAULT_print_chapter_footer; $print_page_foot = \&T2H_DEFAULT_print_page_foot; $print_head_navigation = \&T2H_DEFAULT_print_head_navigation; $print_foot_navigation = \&T2H_DEFAULT_print_foot_navigation; $end_section = \&T2H_DEFAULT_end_section; # changed in info $print_Footnotes = \&T2H_DEFAULT_print_Footnotes; # used if split $about_body = \&T2H_DEFAULT_about_body; $print_navigation = \&T2H_DEFAULT_print_navigation; # # generic formatting functions # $button_icon_img = \&T2H_DEFAULT_button_icon_img; # not really needed nor relevant except for html $print_frame = \&T2H_DEFAULT_print_frame; $print_toc_frame = \&T2H_DEFAULT_print_toc_frame; # generic $titlepage = \&T2H_DEFAULT_titlepage; $css_lines = \&T2H_DEFAULT_css_lines; $print_redirection_page = \&T2H_DEFAULT_print_redirection_page; $node_file_name = \&T2H_DEFAULT_node_file_name; $inline_contents = \&T2H_DEFAULT_inline_contents; $program_string = \&T2H_DEFAULT_program_string; $element_file_name = \&t2h_default_element_file_name; ######################################################################## # Layout for every sections # sub T2H_DEFAULT_print_section($$$$) { my $fh = shift; my $first_in_page = shift; my $previous_is_top = shift; my $element = shift; my $nw = main::print_lines($fh); } sub T2H_DEFAULT_one_section($$) { my $fh = shift; my $element = shift; main::print_lines($fh); &$print_page_foot($fh); } ################################################################### # Layout of top-page. It is possible to use @ifnothtml, @ifhtml, # @html within the Top texinfo node to specify content of top-level # page. # sub T2H_DEFAULT_print_Top_header($$) { my $fh = shift; my $do_page_head = shift; &$print_page_head($fh) if ($do_page_head); } sub T2H_DEFAULT_print_Top_footer($$$) { my $fh = shift; my $end_page = shift; my $element = shift; if ($end_page) { &$print_page_foot($fh); } } sub T2H_DEFAULT_print_Top($$$) { my $fh = shift; my $has_top_heading = shift; my $element = shift; if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'}) { my $shortcontents = &$inline_contents($fh, 'shortcontents'); print $fh "".join('',@$shortcontents) if (defined($shortcontents)); } if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'}) { my $contents = &$inline_contents($fh, 'contents'); print $fh "".join('',@$contents) if (defined($contents)); } main::print_lines($fh, $Texi2HTML::THIS_SECTION); } ################################################################### # Layout of Toc, Overview, and Footnotes pages # By default, we use "normal" layout # Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined # redefine \@MISC_BUTTONS to change the navigation sub T2H_DEFAULT_print_Toc { return &$print_misc(@_); } sub T2H_DEFAULT_print_Overview { return &$print_misc(@_); } sub T2H_DEFAULT_print_Footnotes { return &$print_misc(@_); } sub T2H_DEFAULT_print_About { return &$print_misc(@_); } sub T2H_DEFAULT_print_misc_header($$$$) { my $fh = shift; my $buttons = shift; my $new_file = shift; my $misc_page = shift; &$print_page_head($fh) if ($new_file); } sub T2H_DEFAULT_print_misc_footer($$$) { my $fh = shift; my $buttons = shift; my $new_file = shift; if ($new_file) { &$print_page_foot($fh); } } use vars qw( %t2h_default_underline_symbol ); %t2h_default_underline_symbol = ( 0 => '*', 1 => '*', 2 => '=', 3 => '-', 4 => '.' ); sub t2h_default_heading_text($$$) { my $command = shift; my $text = shift; my $level = shift; return '' if ($text !~ /\S/); my $result = $text ."\n"; # as seen in encodings/nodetest_utf8_no_unicode, the length can be in # bytes (certainly) when there hasn't been a require Encode #$result .=($t2h_default_underline_symbol{$level} x length($text))."\n"; $result .=($t2h_default_underline_symbol{$level} x t2h_default_string_width($text))."\n"; return $result; } sub t2h_default_heading_text_preformatted($$$) { my $command = shift; my $text = shift; my $level = shift; return t2h_default_heading_text($command, $text, $level); } sub T2H_DEFAULT_print_misc($$$) { my $fh = shift; my $new_file = shift; my $misc_page = shift; my $buttons = \@MISC_BUTTONS; &$print_misc_header($fh, $buttons, $new_file, $misc_page); print $fh "".&$heading_text('misc heading', $Texi2HTML::NAME{This}, 1) . "\n"; main::print_lines($fh); &$print_misc_footer($fh, $buttons, $new_file); } ################################################################## # section_footer is only called if SPLIT eq 'section' # section_footer: after print_section of last section, before print_page_foot # sub T2H_DEFAULT_print_section_footer { my $fh = shift; my $element = shift; } ################################################################### # chapter_header and chapter_footer are only called if # SPLIT eq 'chapter' # chapter_header: after print_page_head, before print_section # chapter_footer: after print_section of last section, before print_page_foot sub T2H_DEFAULT_print_chapter_header { my $fh = shift; my $element = shift; } sub T2H_DEFAULT_print_chapter_footer { my $fh = shift; my $element = shift; } sub T2H_DEFAULT_print_section_header { my $fh = shift; } ################################################################### # Layout of standard header and footer # sub T2H_DEFAULT_print_page_head($) { my $fh = shift; } sub T2H_DEFAULT_program_string() { my $date = $Texi2HTML::THISDOC{'today'}; $date = '' if (!defined($date)); if ($date ne '') { return gdt('This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.', { 'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} },{'duplicate'=>1}); } return gdt('This document was generated using @uref{{program_homepage}, @emph{{program}}}.', { 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} },{'duplicate'=>1}); } sub T2H_DEFAULT_end_section($$$) { my $fh = shift; my $misc_or_top_and_section_separation = shift; my $element = shift; } sub T2H_DEFAULT_print_page_foot($) { my $fh = shift; } ################################################################### # Layout of navigation panel sub T2H_DEFAULT_print_head_navigation($$$$$) { my $fh = shift; my $buttons = shift; my $first_in_page = shift; my $previous_is_top = shift; my $element = shift; return ''; } sub T2H_DEFAULT_print_foot_navigation { my $fh = shift; my $buttons = shift; my $rule = shift; my $print_navigation_panel = shift; my $element = shift; $rule = '' if (!defined($rule)); print $fh "$rule\n" if ($rule ne ''); } ###################################################################### # navigation panel # # how to create IMG tag # this is only used in html, and only if ICONS is set and the button # is active. sub T2H_DEFAULT_button_icon_img { my $button = shift; my $icon = shift; my $name = shift; return '' if (!defined($icon)); $button = "" if (!defined ($button)); $name = '' if (!defined($name)); my $alt = ''; if ($name ne '') { if ($button ne '') { $alt = "$button: $name"; } else { $alt = $name; } } else { $alt = $button; } return "$icon $alt"; } sub T2H_DEFAULT_print_navigation { my $buttons = shift; my $vertical = shift; return ''; } ###################################################################### # Frames: this is from "Richard Y. Kim" <ryk@coho.net> # Should be improved to be more conforming to other _print* functions # toc_file and main_file passed as args are relative to the texinfo manual # location, and therefore are not used. # no-ops in the default case, doesn't really make sense if output is # not html sub T2H_DEFAULT_print_frame { my $fh = shift; my $toc_file = shift; my $main_file = shift; $main_file = $Texi2HTML::THISDOC{'filename'}->{'top'}; $toc_file = $Texi2HTML::THISDOC{'filename'}->{'toc_frame'}; } sub T2H_DEFAULT_print_toc_frame { my $fh = shift; my $stoc_lines = shift; } # This subroutine is intended to fill @Texi2HTML::TOC_LINES and # @Texi2HTML::OVERVIEW with the table of contents and short table of # contents. # # arguments: # ref on an array containing all the elements # each element is a reference on a hash. The following keys might be of # use: # 'top': true if this is the top element # 'toc_level': level of the element in the table of content. Highest level # is 1 for the @top element and for chapters, appendix and so on, # 2 for section, unnumberedsec and so on... # 'tocid': label used for reference linking to the element in table of # contents # 'file': the file containing the element, usefull to do href to that file # in case the document is split. # 'text': text of the element, with section number # 'text_nonumber': text of the element, without section number # Relevant configuration variables are: # $NO_BULLET_LIST_ATTRIBUTE: usefull in case a list is used # $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames. # $BEFORE_OVERVIEW # $AFTER_OVERVIEW # $BEFORE_TOC_LINES # $AFTER_TOC_LINES # get_conf('contents') # get_conf('shortcontents') sub T2H_DEFAULT_contents($$) { my $elements = shift; my $toc_file = shift; my @result; return unless (get_conf('contents')); foreach my $element (@$elements) { my $level = $element->{'toc_level'}; $level = 1 if ($level < 1); my $text = $element->{'text'}; my $result = (' ' x ($level - 1)) . $text ."\n"; push @result, $result; } if (@result) { unshift @result, $BEFORE_TOC_LINES; push @result, $AFTER_TOC_LINES; } return \@result; } sub T2H_DEFAULT_shortcontents($$) { my $elements = shift; my $stoc_file = shift; my @result; return unless (get_conf('shortcontents')); foreach my $element (@$elements) { my $level = $element->{'toc_level'}; next if ($level > 1); $level = 1 if ($level < 1); my $text = $element->{'text'}; push @result, $text ."\n"; } if (@result) { unshift @result, $BEFORE_OVERVIEW; push @result, $AFTER_OVERVIEW; } return \@result; } sub T2H_DEFAULT_print_title() { my $element = shift; return undef unless ($SHOW_TITLE); if ($USE_TITLEPAGE_FOR_TITLE) { my ($titlepage_text, $titlepage_no_texi, $titlepage_simple_format) = main::do_special_region_lines('titlepage',$Texi2HTML::THISDOC{'state'}); &$titlepage([],$titlepage_text, $titlepage_no_texi, $titlepage_simple_format); return $Texi2HTML::TITLEPAGE; } else { my $title = ''; $title = $Texi2HTML::THISDOC{'simpletitle'} if (defined($Texi2HTML::THISDOC{'simpletitle'}) and $Texi2HTML::THISDOC{'simpletitle'} !~ /^\s*$/); if ($title ne '') { return &$heading_text('@settitle', $title, 0) . "\n"; } } } sub T2H_DEFAULT_toc_body($) { my $elements_list = shift; my $toc_lines = &$contents($elements_list, $Texi2HTML::THISDOC{'toc_file'}); @{$Texi2HTML::TOC_LINES} = @$toc_lines if ($toc_lines); my $stoc_lines = &$shortcontents($elements_list, $Texi2HTML::THISDOC{'stoc_file'}); @{$Texi2HTML::OVERVIEW} = @$stoc_lines if ($stoc_lines); } # element and elements_list may not be undef when called from the # main program, but may be if called from other customization function, # for example, here, print_Top. sub T2H_DEFAULT_inline_contents($$$$) { my $fh = shift; my $command = shift; my $element = shift; my $elements_list = shift; my $name; my $lines; my $toc_file; $toc_file = $element->{'file'} if (defined($element)); my $result = undef; if ($command eq 'contents') { $name = $Texi2HTML::NAME{'Contents'}; $toc_file = $Texi2HTML::THISDOC{'toc_file'} if (!defined($toc_file)); if (defined($elements_list)) { $lines = &$contents($elements_list, $toc_file); } else { $lines = $Texi2HTML::TOC_LINES; } } else { $name = $Texi2HTML::NAME{'Overview'}; $toc_file = $Texi2HTML::THISDOC{'stoc_file'} if (!defined($toc_file)); if (defined($elements_list)) { $lines = &$shortcontents($elements_list, $toc_file); } else { $lines = $Texi2HTML::OVERVIEW; } } if ($lines and @{$lines}) { $result = [ &$heading_text("\@$command", $name, 1), "\n" ]; my $contents_anchor = &$anchor($element->{'id'}); if (defined($contents_anchor) and $contents_anchor =~ /\S/) { unshift @$result, $contents_anchor."\n"; } push @$result, (@$lines, "\n"); } return $result; } sub T2H_DEFAULT_css_lines ($$) { my $import_lines = shift; my $rule_lines = shift; # return if (defined($CSS_LINES) or (!@$rule_lines and !@$import_lines and (! keys(%css_map)))); if (defined($CSS_LINES)) { # if predefined, use CSS_LINES. $Texi2HTML::THISDOC{'CSS_LINES'} = $CSS_LINES; return; } return if ((!@$rule_lines and !@$import_lines and !keys(%css_map) and !@CSS_REFS) or $NO_CSS); my $css_text = "<style type=\"text/css\">\n<!--\n"; $css_text .= join('',@$import_lines) . "\n" if (@$import_lines); foreach my $css_rule (sort(keys(%css_map))) { next unless ($css_map{$css_rule}); $css_text .= "$css_rule {$css_map{$css_rule}}\n"; } $css_text .= join('',@$rule_lines) . "\n" if (@$rule_lines); $css_text .= "-->\n</style>\n"; foreach my $ref (@CSS_REFS) { $css_text .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$ref\">\n"; } $Texi2HTML::THISDOC{'CSS_LINES'} = $css_text; } ###################################################################### # About page # # PRE_ABOUT can be a function reference or a scalar. # Note that if it is a scalar, T2H_InitGlobals has not been called, # and all global variables like $ADDRESS are not available. $PRE_ABOUT = sub { return ' ' . &$program_string() . "\n"; }; # If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>. $AFTER_ABOUT = ''; %BUTTONS_EXAMPLE = ( 'Top', ' ', 'Contents', ' ', 'Overview', ' ', 'Index', ' ', 'This', '1.2.3', 'Back', '1.2.2', 'FastBack', '1', 'Prev', '1.2.2', 'Up', '1.2', 'Next', '1.2.4', 'NodeUp', '1.2', 'NodeNext', '1.2.4', 'NodePrev', '1.2.2', 'Following', '1.2.4', 'Forward', '1.2.4', 'FastForward', '2', 'About', ' ', 'First', '1.', 'Last', '1.2.4', 'NextFile', ' ', 'PrevFile', ' ', ); sub T2H_DEFAULT_about_body { my $about = ""; if (ref($PRE_ABOUT) eq 'CODE') { $about .= &$PRE_ABOUT(); } else { $about .= $PRE_ABOUT; } return $about; } # return value is currently ignored sub T2H_DEFAULT_titlepage($$$$) { my $titlepage_lines = shift; my $titlepage_text = shift; my $titlepage_no_texi = shift; my $titlepage_simple_format = shift; $Texi2HTML::TITLEPAGE = $titlepage_text; if ($titlepage_text eq '') { my $title = ''; $title = $Texi2HTML::THISDOC{'simpletitle'} if (defined($Texi2HTML::THISDOC{'simpletitle'}) and $Texi2HTML::THISDOC{'simpletitle'} !~ /^\s*$/); if ($title ne '') { $Texi2HTML::TITLEPAGE = &$heading_text('@settitle', $title, 0); $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; } } else { $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; } if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'} and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'contents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}}) { foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}}) { $Texi2HTML::TITLEPAGE .= $line; } $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; } if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'} and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}}) { foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}}) { $Texi2HTML::TITLEPAGE .= $line; } $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; } return $Texi2HTML::TITLEPAGE; } sub T2H_DEFAULT_print_redirection_page() { #return "Redirection files are not of use for the current format.\n"; return undef; } sub T2H_DEFAULT_node_file_name($$) { my $node = shift; my $type = shift; return undef if ($node->{'external_node'} or ($type eq 'top' and !$NEW_CROSSREF_STYLE)); my $node_file_base; if ($type eq 'top' and defined($TOP_NODE_FILE)) { $node_file_base = $TOP_NODE_FILE; } elsif ($NEW_CROSSREF_STYLE) { if ($TRANSLITERATE_FILE_NAMES) { $node_file_base = $node->{'cross_manual_file'}; } else { $node_file_base = $node->{'cross_manual_target'}; } } else { $node_file_base = main::remove_texi($node->{'texi'}); $node_file_base =~ s/[^\w\.\-]/-/g; } if (defined($NODE_FILE_EXTENSION) and $NODE_FILE_EXTENSION ne '') { return ($node_file_base . ".$NODE_FILE_EXTENSION"); } return $node_file_base; } ######################################################################## # Control of formatting: # 1.) For some changes, it is often enough to change the value of # some global map. It might necessitate building a little # function along with the change in hash, if the change is the use # of another function (in style_map). # 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines, # give them another name, and assign them to the respective # $<fnc> variable (below). %deprecated_commands = ( 'ctrl' => '', 'allow-recursion' => N__('recursion is always allowed'), 'quote-arg' => N__('arguments are quoted by default'), ); # # This hash should have keys corresponding with the nonletter command accent # whose following character is considered to be the argument # This hash associates an accent macro to the ISO name for the accent if any. # The customary use of this map is to find the ISO name appearing in html # entity (like é) associated with a texinfo accent macro. # # The keys of the hash are # ": umlaut # ~: tilda accent # ^: circumflex accent # `: grave accent # ': acute accent # =: macron accent %accent_map = ( '"', 'uml', '~', 'tilde', '^', 'circ', '`', 'grave', "'", 'acute', ",", 'cedil', '=', '', 'ringaccent', 'ring', 'H', '', 'dotaccent', '', 'u', '', 'ubaraccent', '', 'udotaccent', '', 'v', '', 'ogonek', 'ogon', ); # # ascii representation of texinfo "simple things" @-commands %default_simple_map = ( '*', "\n", ' ', ' ', "\t", ' ', "\n", ' ', '-', '', # hyphenation hint '|', '', # used in formatting commands @evenfooting and friends '/', '', ':', '', '!', '!', '?', '?', '.', '.', '@', '@', '}', '}', '{', '{', ); # texinfo "simple things" @-commands %simple_map = %default_simple_map; # this map is used in preformatted text %simple_map_pre = %simple_map; # This map is used when texi elements are removed and replaced # by simple text %simple_map_texi = %default_simple_map; # maps for the math specific commands %simple_map_math = ( '\\', '\\' ); #%simple_map_pre_math = %simple_map_math; #%simple_map_texi_math = %simple_map_math; $punctuation_characters = '.?!'; $after_punctuation_characters = '"\')]'; %default_things_map = ( 'TeX' => 'TeX', 'LaTeX' => 'LaTeX', 'bullet' => '*', 'copyright' => '(C)', 'registeredsymbol' => '(R)', 'dots' => '...', 'enddots' => '...', 'equiv' => '==', # FIXME i18n 'error' => 'error-->', 'expansion' => '==>', 'arrow' => '->', 'minus' => '-', 'point' => '-!-', 'print' => '-|', 'result' => '=>', 'today' => '', 'aa' => 'aa', 'AA' => 'AA', 'ae' => 'ae', 'oe' => 'oe', 'AE' => 'AE', 'OE' => 'OE', 'o' => '/o', 'O' => '/O', 'ss' => 'ss', 'l' => '/l', 'L' => '/L', 'DH' => 'D', 'dh' => 'd', 'TH' => 'TH', # http://www.evertype.com/standards/wynnyogh/thorn.html 'th' => 'th', 'exclamdown' => '!', 'questiondown' => '?', 'pounds' => '#', 'ordf' => 'a', 'ordm' => 'o', 'comma' => ',', 'euro' => 'Euro', 'geq' => '>=', 'leq' => '<=', 'tie' => ' ', 'textdegree' => 'o', 'quotedblleft' => '``', 'quotedblright' => "''", 'quoteleft' => '`', 'quoteright' => "'", 'quotedblbase' => ',,', 'quotesinglbase' => ',', 'guillemetleft' => '<<', 'guillemetright' => '>>', 'guillemotleft' => '<<', 'guillemotright' => '>>', 'guilsinglleft' => '<', 'guilsinglright' => '>', ); %things_map = %default_things_map; # This map is used in preformatted environments %pre_map = %things_map; # used in math. If not found, pre_map is used. %math_map = (); # text replacing macros when texi commands are removed and plain text is # produced. %texi_map = %default_things_map; # used for index sorting. %sorting_things_map = %default_things_map; foreach my $accent_letter ('o','O','l','L') { $sorting_things_map{$accent_letter} = $accent_letter; } $sorting_things_map{'copyright'} = 'C'; $sorting_things_map{'registeredsymbol'} = 'R'; $sorting_things_map{'today'} = 't'; %default_texi_map = %texi_map; # # texinfo "things" (@foo{}) to XML ones # %things_map_xml = ( 'TeX' => 'TeX', 'LaTeX' => 'LaTeX', # pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing) # 'br', '<br>', # paragraph break 'bullet' => '•', # #'copyright' => '(C)', 'copyright' => '©', 'registeredsymbol' => '®', 'dots' => '…', 'enddots' => '...', 'equiv' => '≡', # FIXME i18n 'error' => 'error-->', 'expansion' => '→', 'arrow' => '→', 'minus' => '-', 'point' => '∗', 'print' => '-|', 'result' => '⇒', # set in code using the language # 'today', &pretty_date, 'today' => '', 'aa' => 'å', 'AA' => 'Å', 'ae' => 'æ', 'oe' => 'œ', #pertusus: also œ. œ not in html 3.2 'AE' => 'Æ', 'OE' => 'Œ', #pertusus: also Œ. Œ not in html 3.2 'o' => 'ø', 'O' => 'Ø', 'ss' => 'ß', 'DH' => 'Ð', 'dh' => 'ð', 'TH' => 'Þ', 'th' => 'þ', 'l' => 'ł', 'L' => 'Ł', 'exclamdown' => '¡', 'questiondown' => '¿', 'pounds' => '£', 'ordf' => 'ª', 'ordm' => 'º', 'comma' => ',', 'euro' => '€', 'geq' => '≥', 'leq' => '≤', 'tie' => ' ', 'textdegree' => '°', 'quotedblleft' => '“', 'quotedblright' => '”', 'quoteleft' => '‘', 'quoteright' => '’', 'quotedblbase' => '„', 'quotesinglbase' => '‚', 'guillemetleft' => '«', 'guillemetright' => '»', 'guillemotleft' => '«', 'guillemotright' => '»', 'guilsinglleft' => '‹', 'guilsinglright' => '›', ); # This map is used in preformatted environments %pre_map_xml = %things_map_xml; # taken from #Latin extended additionnal #http://www.alanwood.net/unicode/latin_extended_additional.html #C1 Controls and Latin-1 Supplement #http://www.alanwood.net/unicode/latin_1_supplement.html #Latin Extended-A #http://www.alanwood.net/unicode/latin_extended_a.html #Latin Extended-B #http://www.alanwood.net/unicode/latin_extended_b.html #dotless i: 0131 #http://www.alanwood.net/unicode/arrows.html 21** #http://www.alanwood.net/unicode/general_punctuation.html 20** #http://www.alanwood.net/unicode/mathematical_operators.html 22** %unicode_map = ( 'bullet' => '2022', 'copyright' => '00A9', 'registeredsymbol' => '00AE', 'dots' => '2026', 'enddots' => '', 'equiv' => '2261', 'error' => '', 'expansion' => '2192', 'arrow' => '2192', 'minus' => '2212', # in mathematical operators # 'minus' => '002D', # in latin1 'point' => '2605', 'print' => '22A3', 'result' => '21D2', 'today' => '', 'aa' => '00E5', 'AA' => '00C5', 'ae' => '00E6', 'oe' => '0153', 'AE' => '00C6', 'OE' => '0152', 'o' => '00F8', 'O' => '00D8', 'ss' => '00DF', 'DH' => '00D0', 'dh' => '00F0', 'TH' => '00DE', 'th' => '00FE', 'l' => '0142', 'L' => '0141', 'exclamdown' => '00A1', 'questiondown' => '00BF', 'pounds' => '00A3', 'ordf' => '00AA', 'ordm' => '00BA', 'comma' => '002C', 'euro' => '20AC', 'geq' => '2265', 'leq' => '2264', 'tie' => '', # 'tie' => '0020', 'textdegree' => '00B0', 'quotedblleft' => '201C', 'quotedblright' => '201D', 'quoteleft' => '2018', 'quoteright' => '2019', 'quotedblbase' => '201E', 'quotesinglbase' => '201A', 'guillemetleft' => '00AB', 'guillemetright' => '00BB', 'guillemotleft' => '00AB', 'guillemotright' => '00BB', 'guilsinglleft' => '2039', 'guilsinglright' => '203A', ); %makeinfo_encoding_to_map = ( "iso-8859-1", 'iso8859_1', "iso-8859-2", 'iso8859_2', "iso-8859-15", 'iso8859_15', "koi8-r", 'koi8', "koi8-u", 'koi8', ); foreach my $encoding (keys(%makeinfo_encoding_to_map)) { $t2h_encoding_aliases{$encoding} = $encoding; $t2h_encoding_aliases{$makeinfo_encoding_to_map{$encoding}} = $encoding; } # cut and pasted from eigth_bit_makeinfo_maps.pl, in turn generated with # ./parse_8bit_makeinfo_maps.pl %makeinfo_unicode_to_eight_bit = ( 'iso8859_1' => { '00A0' => 'A0', '00A1' => 'A1', '00A2' => 'A2', '00A3' => 'A3', '00A4' => 'A4', '00A5' => 'A5', '00A6' => 'A6', '00A7' => 'A7', '00A8' => 'A8', '00A9' => 'A9', '00AA' => 'AA', '00AB' => 'AB', '00AC' => 'AC', '00AD' => 'AD', '00AE' => 'AE', '00AF' => 'AF', '00B0' => 'B0', '00B1' => 'B1', '00B2' => 'B2', '00B3' => 'B3', '00B4' => 'B4', '00B5' => 'B5', '00B6' => 'B6', '00B7' => 'B7', '00B8' => 'B8', '00B9' => 'B9', '00BA' => 'BA', '00BB' => 'BB', '00BC' => 'BC', '00BD' => 'BD', '00BE' => 'BE', '00BF' => 'BF', '00C0' => 'C0', '00C1' => 'C1', '00C2' => 'C2', '00C3' => 'C3', '00C4' => 'C4', '00C5' => 'C5', '00C6' => 'C6', '00C7' => 'C7', '00C7' => 'C7', '00C8' => 'C8', '00C9' => 'C9', '00CA' => 'CA', '00CB' => 'CB', '00CC' => 'CC', '00CD' => 'CD', '00CE' => 'CE', '00CF' => 'CF', '00D0' => 'D0', '00D1' => 'D1', '00D2' => 'D2', '00D3' => 'D3', '00D4' => 'D4', '00D5' => 'D5', '00D6' => 'D6', '00D7' => 'D7', '00D8' => 'D8', '00D9' => 'D9', '00DA' => 'DA', '00DB' => 'DB', '00DC' => 'DC', '00DD' => 'DD', '00DE' => 'DE', '00DF' => 'DF', '00E0' => 'E0', '00E1' => 'E1', '00E2' => 'E2', '00E3' => 'E3', '00E4' => 'E4', '00E5' => 'E5', '00E6' => 'E6', '00E7' => 'E7', '00E8' => 'E8', '00E9' => 'E9', '00EA' => 'EA', '00EB' => 'EB', '00EC' => 'EC', '00ED' => 'ED', '00EE' => 'EE', '00EF' => 'EF', '00F0' => 'F0', '00F1' => 'F1', '00F2' => 'F2', '00F3' => 'F3', '00F4' => 'F4', '00F5' => 'F5', '00F6' => 'F6', '00F7' => 'F7', '00F8' => 'F8', '00F9' => 'F9', '00FA' => 'FA', '00FB' => 'FB', '00FC' => 'FC', '00FD' => 'FD', '00FE' => 'FE', '00FF' => 'FF', }, 'iso8859_15' => { '00A0' => 'A0', '00A1' => 'A1', '00A2' => 'A2', '00A3' => 'A3', '20AC' => 'A4', '00A5' => 'A5', '0160' => 'A6', '00A7' => 'A7', '0161' => 'A8', '00A9' => 'A9', '00AA' => 'AA', '00AB' => 'AB', '00AC' => 'AC', '00AD' => 'AD', '00AE' => 'AE', '00AF' => 'AF', '00B0' => 'B0', '00B1' => 'B1', '00B2' => 'B2', '00B3' => 'B3', '017D' => 'B4', '00B5' => 'B5', '00B6' => 'B6', '00B7' => 'B7', '017E' => 'B8', '00B9' => 'B9', '00BA' => 'BA', '00BB' => 'BB', '0152' => 'BC', '0153' => 'BD', '0178' => 'BE', '00BF' => 'BF', '00C0' => 'C0', '00C1' => 'C1', '00C2' => 'C2', '00C3' => 'C3', '00C4' => 'C4', '00C5' => 'C5', '00C6' => 'C6', '00C7' => 'C7', '00C8' => 'C8', '00C9' => 'C9', '00CA' => 'CA', '00CB' => 'CB', '00CC' => 'CC', '00CD' => 'CD', '00CE' => 'CE', '00CF' => 'CF', '00D0' => 'D0', '00D1' => 'D1', '00D2' => 'D2', '00D3' => 'D3', '00D4' => 'D4', '00D5' => 'D5', '00D6' => 'D6', '00D7' => 'D7', '00D8' => 'D8', '00D9' => 'D9', '00DA' => 'DA', '00DB' => 'DB', '00DC' => 'DC', '00DD' => 'DD', '00DE' => 'DE', '00DF' => 'DF', '00E0' => 'E0', '00E1' => 'E1', '00E2' => 'E2', '00E3' => 'E3', '00E4' => 'E4', '00E5' => 'E5', '00E6' => 'E6', '00E7' => 'E7', '00E8' => 'E8', '00E9' => 'E9', '00EA' => 'EA', '00EB' => 'EB', '00EC' => 'EC', '00ED' => 'ED', '00EE' => 'EE', '00EF' => 'EF', '00F0' => 'F0', '00F1' => 'F1', '00F2' => 'F2', '00F3' => 'F3', '00F4' => 'F4', '00F5' => 'F5', '00F6' => 'F6', '00F7' => 'F7', '00F8' => 'F8', '00F9' => 'F9', '00FA' => 'FA', '00FB' => 'FB', '00FC' => 'FC', '00FD' => 'FD', '00FE' => 'FE', '00FF' => 'FF', }, 'iso8859_2' => { '00A0' => 'A0', '0104' => 'A1', '02D8' => 'A2', '0141' => 'A3', '00A4' => 'A4', '013D' => 'A5', '015A' => 'A6', '00A7' => 'A7', '00A8' => 'A8', '015E' => 'AA', '0164' => 'AB', '0179' => 'AC', '00AD' => 'AD', '017D' => 'AE', '017B' => 'AF', '00B0' => 'B0', '0105' => 'B1', '02DB' => 'B2', '0142' => 'B3', '00B4' => 'B4', '013E' => 'B5', '015B' => 'B6', '02C7' => 'B7', '00B8' => 'B8', '0161' => 'B9', '015F' => 'BA', '0165' => 'BB', '017A' => 'BC', '02DD' => 'BD', '017E' => 'BE', '017C' => 'BF', '0154' => 'C0', '00C1' => 'C1', '00C2' => 'C2', '0102' => 'C3', '00C4' => 'C4', '0139' => 'C5', '0106' => 'C6', '00C7' => 'C7', '010C' => 'C8', '00C9' => 'C9', '0118' => 'CA', '00CB' => 'CB', '011A' => 'CC', '00CD' => 'CD', '00CE' => 'CE', '010E' => 'CF', '0110' => 'D0', '0143' => 'D1', '0147' => 'D2', '00D3' => 'D3', '00D4' => 'D4', '0150' => 'D5', '00D6' => 'D6', '00D7' => 'D7', '0158' => 'D8', '016E' => 'D9', '00DA' => 'DA', '0170' => 'DB', '00DC' => 'DC', '00DD' => 'DD', '0162' => 'DE', '00DF' => 'DF', '0155' => 'E0', '00E1' => 'E1', '00E2' => 'E2', '0103' => 'E3', '00E4' => 'E4', '013A' => 'E5', '0107' => 'E6', '00E7' => 'E7', '010D' => 'E8', '00E9' => 'E9', '0119' => 'EA', '00EB' => 'EB', '011B' => 'EC', '00ED' => 'ED', '00EE' => 'EE', '010F' => 'EF', '0111' => 'F0', '0144' => 'F1', '0148' => 'F2', '00F3' => 'F3', '00F4' => 'F4', '0151' => 'F5', '00F6' => 'F6', '00F7' => 'F7', '0159' => 'F8', '016F' => 'F9', '00FA' => 'FA', '0171' => 'FB', '00FC' => 'FC', '00FD' => 'FD', '0163' => 'FE', '02D9' => 'FF', }, 'koi8' => { '0415' => 'A3', '0454' => 'A4', '0456' => 'A6', '0457' => 'A7', '04D7' => 'B3', '0404' => 'B4', '0406' => 'B6', '0407' => 'B7', '042E' => 'C0', '0430' => 'C1', '0431' => 'C2', '0446' => 'C3', '0434' => 'C4', '0435' => 'C5', '0444' => 'C6', '0433' => 'C7', '0445' => 'C8', '0438' => 'C9', '0439' => 'CA', '043A' => 'CB', '043B' => 'CC', '043C' => 'CD', '043D' => 'CE', '043E' => 'CF', '043F' => 'D0', '044F' => 'D1', '0440' => 'D2', '0441' => 'D3', '0442' => 'D4', '0443' => 'D5', '0436' => 'D6', '0432' => 'D7', '044C' => 'D8', '044B' => 'D9', '0437' => 'DA', '0448' => 'DB', '044D' => 'DC', '0449' => 'DD', '0447' => 'DE', '044A' => 'DF', '042D' => 'E0', '0410' => 'E1', '0411' => 'E2', '0426' => 'E3', '0414' => 'E4', '0415' => 'E5', '0424' => 'E6', '0413' => 'E7', '0425' => 'E8', '0418' => 'E9', '0419' => 'EA', '041A' => 'EB', '041B' => 'EC', '041C' => 'ED', '041D' => 'EE', '041E' => 'EF', '041F' => 'F0', '042F' => 'F1', '0420' => 'F2', '0421' => 'F3', '0422' => 'F4', '0423' => 'F5', '0416' => 'F6', '0412' => 'F7', '042C' => 'F8', '042B' => 'F9', '0417' => 'FA', '0428' => 'FB', '042D' => 'FC', '0429' => 'FD', '0427' => 'FE', '042A' => 'FF', }, ); %eight_bit_to_unicode = (); foreach my $encoding (keys(%makeinfo_encoding_to_map)) { my $unicode_to_eight = $makeinfo_unicode_to_eight_bit{$makeinfo_encoding_to_map{$encoding}}; #print STDERR "$encoding, $makeinfo_encoding_to_map{$encoding}, $unicode_to_eight\n"; foreach my $utf8_key (keys(%{$unicode_to_eight})) { $eight_bit_to_unicode{$encoding}->{$unicode_to_eight->{$utf8_key}} = $utf8_key; } } # currently unused my %makeinfo_transliterate_map = ( '0416' => 'ZH', '0447' => 'ch', '00EB' => 'e', '0414' => 'D', '0159' => 'r', '00E6' => 'ae', '042B' => 'Y', '00FA' => 'u', '043B' => 'l', '00DE' => 'TH', '00D9' => 'U', '00C4' => 'A', '0148' => 'n', '00F6' => 'o', '0434' => 'd', '041E' => 'O', '041B' => 'L', '044B' => 'y', '0107' => 'c', '0415' => 'E', '00C1' => 'A', '00D3' => 'O', '00DB' => 'U', '016E' => 'U', '013A' => 'l', '017B' => 'Z', '00F1' => 'n', '0428' => 'SH', '0153' => 'oe', '00F4' => 'o', '0144' => 'n', '0404' => 'IE', '0427' => 'CH', '0162' => 'T', '017A' => 'z', '0448' => 'sh', '0436' => 'zh', '00F9' => 'u', '0406' => 'I', '0103' => 'a', '0422' => 'T', '0160' => 'S', '0165' => 't', '017E' => 'z', '00F0' => 'd', '043E' => 'o', '043D' => 'n', '013E' => 'l', '0412' => 'V', '0111' => 'd', '0155' => 's', '017C' => 'z', '00CE' => 'I', '042D' => 'E', '00C8' => 'E', '00F8' => 'oe', '00F2' => 'o', '00FF' => 'y', '0420' => 'R', '0119' => 'e', '00D2' => 'O', '043C' => 'm', '00D0' => 'DH', '0179' => 'Z', '0110' => 'D', '043F' => 'p', '0170' => 'U', '011A' => 'E', '010C' => 'C', '015A' => 'S', '0433' => 'g', '00E1' => 'a', '010D' => 'c', '00CC' => 'I', '016F' => 'u', '0457' => 'yi', '00C2' => 'A', '0438' => 'i', '00E3' => 'a', '0435' => 'e', '0440' => 'r', '042A' => 'W', '0431' => 'b', '00EE' => 'i', '0150' => 'O', '00E8' => 'e', '0418' => 'I', '00CF' => 'I', '015F' => 's', '0142' => 'l', '0147' => 'N', '00DF' => 'ss', '00E5' => 'aa', '00C3' => 'A', '0106' => 'C', '0141' => 'L', '0164' => 'T', '017D' => 'Z', '00EC' => 'i', '041C' => 'M', '00C9' => 'E', '00E0' => 'a', '043A' => 'k', '00F5' => 'o', '042C' => 'X', '0449' => 'shch', '0444' => 'f', '0139' => 'L', '0158' => 'R', '00F3' => 'o', '00FB' => 'u', '0424' => 'F', '0446' => 'c', '0423' => 'U', '0442' => 't', '00FD' => 'y', '0102' => 'A', '0104' => 'A', '00CB' => 'E', '0426' => 'C', '00CD' => 'I', '0437' => 'z', '0178' => 'y', '00D4' => 'O', '044D' => 'e', '0432' => 'v', '013D' => 'L', '0163' => 't', '0456' => 'i', '011B' => 'e', '044F' => 'ya', '0429' => 'SHCH', '0411' => 'B', '044A' => 'w', '00C6' => 'AE', '041D' => 'N', '00DA' => 'U', '00C0' => 'A', '0152' => 'OE', '00DD' => 'Y', '0154' => 'R', '00E9' => 'e', '00D5' => 'O', '041F' => 'P', '0161' => 's', '0430' => 'a', '0445' => 'h', '00E2' => 'a', '00D6' => 'O', '0407' => 'YI', '00CA' => 'E', '0439' => 'i', '0171' => 'u', '00DC' => 'U', '042F' => 'YA', '0425' => 'H', '00FE' => 'th', '00D1' => 'N', '044C' => 'x', '010F' => 'd', '0410' => 'A', '0443' => 'u', '00EF' => 'i', '0105' => 'a', '00EA' => 'e', '00E4' => 'a', '015E' => 'S', '0417' => 'Z', '00ED' => 'i', '00FC' => 'u', '04D7' => 'IO', '00D8' => 'OE', '0419' => 'I', '0421' => 'S', '0143' => 'N', '010E' => 'D', '0413' => 'G', '015B' => 's', '0151' => 'o', '00E7' => 'c', '00C5' => 'AA', '0441' => 's', '0118' => 'E', '00C7' => 'C', '041A' => 'K', '0454' => 'ie', '042E' => 'yu', ); %transliterate_map = ( '00C5' => 'AA', '00E5' => 'aa', '00D8' => 'O', '00F8' => 'o', '00E6' => 'ae', '0153' => 'oe', '00C6' => 'AE', '0152' => 'OE', '00DF' => 'ss', '0141' => 'L', '0142' => 'l', '00D0' => 'D', '00F0' => 'd', '00DE' => 'TH', '00FE' => 'th', '0415' => 'E', '0435' => 'e', '0426' => 'C', '042A' => 'W', '044A' => 'w', '042C' => 'X', '044C' => 'x', '042E' => 'yu', '042F' => 'YA', '044F' => 'ya', '0433' => 'g', '0446' => 'c', '04D7' => 'IO', '00DD' => 'Y', # unidecode gets this wrong ? # following appears in tests, this is required to have # the same output with and without unidecode '4E2D' => 'Zhong', '6587' => 'Wen', '793A' => 'Shi', '4F8B' => 'Li', '7B2C' => 'Di', '7AE0' => 'Zhang', '53E6' => 'Ling', '4E2A' => 'Ge', # in http://www.cantonese.sheik.co.uk/dictionary/characters/7/ # unidecode certainly gets it wrong '4E00' => 'Yi', 'FF08' => '(', 'FF09' => ')', 'FF0C' => ',', '5B66' => 'Xue', '7FD2' => 'Xi', '30DE' => 'ma', '30CB' => 'ni', '30E5' => 'yu', '30A2' => 'a', '30EB' => 'ru', ); foreach my $symbol(keys(%unicode_map)) { if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol})) { $no_transliterate_map{$unicode_map{$symbol}} = 1; } } %ascii_character_map = ( ' ' => '0020', '!' => '0021', '"' => '0022', '#' => '0023', '$' => '0024', '%' => '0025', '&' => '0026', "'" => '0027', '(' => '0028', ')' => '0029', '*' => '002A', '+' => '002B', ',' => '002C', '-' => '002D', '.' => '002E', '/' => '002F', ':' => '003A', ';' => '003B', '<' => '003C', '=' => '003D', '>' => '003E', '?' => '003F', '@' => '0040', '[' => '005B', '\\' => '005C', ']' => '005D', '^' => '005E', '_' => '005F', '`' => '0060', '{' => '007B', '|' => '007C', '}' => '007D', '~' => '007E', ); %perl_charset_to_html = ( 'utf8' => 'utf-8', 'utf-8-strict' => 'utf-8', 'ascii' => 'us-ascii', 'shiftjis' => 'shift_jis', ); %t2h_encoding_aliases = ( 'latin1' => 'iso-8859-1', ); foreach my $perl_charset (keys(%perl_charset_to_html)) { $t2h_encoding_aliases{$perl_charset} = $perl_charset_to_html{$perl_charset}; $t2h_encoding_aliases{$perl_charset_to_html{$perl_charset}} = $perl_charset_to_html{$perl_charset}; } # These are the encodings from the texinfo manual foreach my $canonical_encoding('us-ascii', 'utf-8', 'iso-8859-1', 'iso-8859-15','iso-8859-2','koi8-r', 'koi8-u') { $canonical_texinfo_encodings{$canonical_encoding} = 1; } # not used currently for html, but used in chm.init %numeric_entity_map = (); foreach my $symbol (keys(%unicode_map)) { if ($symbol ne '') { $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';'; } } # When the value begins with & the function with that name is used to do the # html. The first argument is the text enclosed within {}, the second is the # style name (which is also the key of the hash) # # Otherwithe the value is the html element used to enclose the text, and if # there is a " the resulting text is also enclosed within `' my %old_style_map = ( 'acronym', '', 'asis', '', 'b', 'b', 'cite', 'cite', 'clicksequence', '', 'code', 'code', 'command', 'code', 'ctrl', '&default_ctrl', 'dfn', 'em', 'dmn', '', 'email', '&default_email', 'emph', 'em', 'env', 'code', 'file', '"tt', 'i', 'i', 'kbd', 'kbd', 'key', 'kbd', 'math', 'em', 'option', '"samp', 'r', '', 'samp', '"samp', 'sc', '&default_sc', 'strong', 'strong', 't', 'tt', 'uref', '&default_uref', 'url', '&default_url', 'var', 'var', 'verb', 'tt', 'titlefont', '&default_titlefont', 'w', '', ); sub t2h_default_copy_style_map ($$;$) { my $from = shift; my $to = shift; my $merge = shift; foreach my $command (keys(%$from)) { $to->{$command} = {} if (!exists($to->{$command})); foreach my $key (keys(%{$from->{$command}})) { next if (exists($to->{$command}->{$key}) and $merge); if ($key eq 'args') { $to->{$command}->{$key} = [ @{$from->{$command}->{$key}} ]; } else { $to->{$command}->{$key} = $from->{$command}->{$key}; } } } } # default is {'args' => ['normal'], 'attribute' => ''}, %style_map = ( 'asis', {}, 'b', {}, 'cite', {}, 'clicksequence', {}, 'click', {'function' => \&t2h_default_click_normal, 'type' => 'simple_style'}, 'code', {'args' => ['code']}, 'command', {'args' => ['code']}, 'ctrl', {'function' => \&t2h_default_ctrl,'type' => 'simple_style'}, 'dfn', {}, 'dmn', {'type' => 'simple_style'}, 'email', {'args' => ['code', 'normal'], 'function' => \&t2h_default_email, 'type' => 'simple_style'}, #'email', {'args' => ['normal', 'normal'], # 'function' => \&t2h_default_email}, 'emph', {}, 'env', {'args' => ['code']}, 'file', {'args' => ['code'], 'quote' => '"'}, 'headitemfont', {}, 'i', {}, 'slanted', {}, 'sansserif', {}, 'kbd', {'args' => ['code'], }, 'key', {'args' => ['code'], 'begin' => '<', 'end' => '>'}, 'math', {'function' => \&t2h_default_math, 'args' => ['math'] }, 'option', {'args' => ['code'], 'quote' => '"'}, 'r', {}, 'samp', {'args' => ['code'], 'quote' => '"'}, # 'sc', {'function' => \&t2h_default_sc}, 'sc', {}, 'strong', {}, 't', {}, 'uref', {'function' => \&t2h_default_uref, 'args' => ['code', 'normal', 'normal'], 'type' => 'simple_style' }, #'uref', {'function' => \&t2h_default_uref, # 'args' => ['normal', 'normal', 'normal']}, 'url', {'function' => \&t2h_default_uref, 'args' => ['code', 'normal', 'normal'], 'type' => 'simple_style'}, 'indicateurl', {'args' => ['code'], 'begin' => '<', 'end' => '>','type' => 'simple_style'}, 'var', {}, 'verb', {'args' => ['code'], }, 'titlefont', {'function' => \&t2h_default_titlefont, 'type' => 'simple_style'}, 'w', {}, 'hyphenation', {'function' => \&t2h_default_hyphenation, 'args' => ['keep']}, ); %command_type = (); foreach my $style (keys(%style_map)) { if (exists($style_map{$style}->{'type'})) { $command_type{$style} = $style_map{$style}->{'type'}; } else { $command_type{$style} = 'style'; } } sub t2h_default_select_substitution($$$) { my $in_raw_text = shift; my $in_preformatted = shift; my $in_simple = shift; my $substitutions = \@text_substitutions_normal; if ($in_raw_text) { $substitutions = \@text_substitutions_texi; } elsif ($in_simple) { $substitutions = \@text_substitutions_simple_format; } elsif ($in_preformatted) { $substitutions = \@text_substitutions_pre; } return $substitutions; } sub t2h_text_substitutions($$$$) { my $text = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_simple = shift; my $substitutions = t2h_default_select_substitution($in_raw_text, $in_preformatted, $in_simple); foreach my $substitution_entry (@$substitutions) { my $from = quotemeta($substitution_entry->[0]); my $to = $substitution_entry->[1]; $text =~ s/$from/$to/g; } return $text; } sub t2h_add_text_substitutions($$$$$) { my $entry = shift; my $in_normal = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_simple = shift; my @formats_to_be_done = ($in_normal, $in_raw_text, $in_preformatted, $in_simple); for (my $index = 0; $index < scalar(@formats_to_be_done); $index++) { next unless ($formats_to_be_done[$index]); my @args = (0, 0, 0); my $found = 0; $args[$index -1] = 1 if ($index > 0); my $substitutions = &t2h_default_select_substitution(@args); foreach my $substitution_entry (@$substitutions) { if ($substitution_entry->[0] eq $entry->[0]) { $found = 1; $substitution_entry->[1] = $entry->[1]; } } push @$substitutions, $entry unless ($found); } } sub t2h_remove_text_substitutions($$$$$) { my $entry = shift; my $in_normal = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_simple = shift; my @formats_to_be_done = ($in_normal, $in_raw_text, $in_preformatted, $in_simple); for (my $index = 0; $index < scalar(@formats_to_be_done); $index++) { next unless ($formats_to_be_done[$index]); my @args = (0, 0, 0); $args[$index -1] = 1 if ($index > 0); my $substitutions = &t2h_default_select_substitution(@args); @$substitutions = grep {$_->[0] ne $entry} @$substitutions; } } %unicode_diacritical = ( 'H' => '030B', 'ringaccent' => '030A', "'" => '0301', 'v' => '030C', ',' => '0327', '^' => '0302', 'dotaccent' => '0307', '`' => '0300', '=' => '0304', '~' => '0303', '"' => '0308', 'udotaccent' => '0323', 'ubaraccent' => '0332', 'u' => '0306', 'tieaccent' => '0361', 'ogonek' => '0328' ); %unicode_accents = ( 'dotaccent' => { # dot above 'A' => '0226', #C moz-1.2 'a' => '0227', #c moz-1.2 'B' => '1E02', 'b' => '1E03', 'C' => '010A', 'c' => '010B', 'D' => '1E0A', 'd' => '1E0B', 'E' => '0116', 'e' => '0117', 'F' => '1E1E', 'f' => '1E1F', 'G' => '0120', 'g' => '0121', 'H' => '1E22', 'h' => '1E23', 'i' => '0069', 'I' => '0130', 'N' => '1E44', 'n' => '1E45', 'O' => '022E', #Y moz-1.2 'o' => '022F', #v moz-1.2 'P' => '1E56', 'p' => '1E57', 'R' => '1E58', 'r' => '1E59', 'S' => '1E60', 's' => '1E61', 'T' => '1E6A', 't' => '1E6B', 'W' => '1E86', 'w' => '1E87', 'X' => '1E8A', 'x' => '1E8B', 'Y' => '1E8E', 'y' => '1E8F', 'Z' => '017B', 'z' => '017C', }, 'udotaccent' => { # dot below 'A' => '1EA0', 'a' => '1EA1', 'B' => '1E04', 'b' => '1E05', 'D' => '1E0C', 'd' => '1E0D', 'E' => '1EB8', 'e' => '1EB9', 'H' => '1E24', 'h' => '1E25', 'I' => '1ECA', 'i' => '1ECB', 'K' => '1E32', 'k' => '1E33', 'L' => '1E36', 'l' => '1E37', 'M' => '1E42', 'm' => '1E43', 'N' => '1E46', 'n' => '1E47', 'O' => '1ECC', 'o' => '1ECD', 'R' => '1E5A', 'r' => '1E5B', 'S' => '1E62', 's' => '1E63', 'T' => '1E6C', 't' => '1E6D', 'U' => '1EE4', 'u' => '1EE5', 'V' => '1E7E', 'v' => '1E7F', 'W' => '1E88', 'w' => '1E89', 'Y' => '1EF4', 'y' => '1EF5', 'Z' => '1E92', 'z' => '1E93', }, 'ubaraccent' => { # line below 'B' => '1E06', 'b' => '1E07', 'D' => '1E0E', 'd' => '1E0F', 'h' => '1E96', 'K' => '1E34', 'k' => '1E35', 'L' => '1E3A', 'l' => '1E3B', 'N' => '1E48', 'n' => '1E49', 'R' => '1E5E', 'r' => '1E5F', 'T' => '1E6E', 't' => '1E6F', 'Z' => '1E94', 'z' => '1E95', }, ',' => { # cedilla 'C' => '00C7', 'c' => '00E7', 'D' => '1E10', 'd' => '1E11', 'E' => '0228', #C moz-1.2 'e' => '0229', #c moz-1.2 'G' => '0122', 'g' => '0123', 'H' => '1E28', 'h' => '1E29', 'K' => '0136', 'k' => '0137', 'L' => '013B', 'l' => '013C', 'N' => '0145', 'n' => '0146', 'R' => '0156', 'r' => '0157', 'S' => '015E', 's' => '015F', 'T' => '0162', 't' => '0163', }, '=' => { # macron 'A' => '0100', 'a' => '0101', 'E' => '0112', 'e' => '0113', 'I' => '012A', 'i' => '012B', 'G' => '1E20', 'g' => '1E21', 'O' => '014C', 'o' => '014D', 'U' => '016A', 'u' => '016B', 'Y' => '0232', #? moz-1.2 'y' => '0233', #? moz-1.2 }, '"' => { # diaeresis 'A' => '00C4', 'a' => '00E4', 'E' => '00CB', 'e' => '00EB', 'H' => '1E26', 'h' => '1E27', 'I' => '00CF', 'i' => '00EF', 'O' => '00D6', 'o' => '00F6', 't' => '1E97', 'U' => '00DC', 'u' => '00FC', 'W' => '1E84', 'w' => '1E85', 'X' => '1E8C', 'x' => '1E8D', 'y' => '00FF', 'Y' => '0178', }, 'u' => { # breve 'A' => '0102', 'a' => '0103', 'E' => '0114', 'e' => '0115', 'G' => '011E', 'g' => '011F', 'I' => '012C', 'i' => '012D', 'O' => '014E', 'o' => '014F', 'U' => '016C', 'u' => '016D', }, "'" => { # acute 'A' => '00C1', 'a' => '00E1', 'C' => '0106', 'c' => '0107', 'E' => '00C9', 'e' => '00E9', 'G' => '01F4', 'g' => '01F5', 'I' => '00CD', 'i' => '00ED', 'K' => '1E30', 'k' => '1E31', 'L' => '0139', 'l' => '013A', 'M' => '1E3E', 'm' => '1E3F', 'N' => '0143', 'n' => '0144', 'O' => '00D3', 'o' => '00F3', 'P' => '1E54', 'p' => '1E55', 'R' => '0154', 'r' => '0155', 'S' => '015A', 's' => '015B', 'U' => '00DA', 'u' => '00FA', 'W' => '1E82', 'w' => '1E83', 'Y' => '00DD', 'y' => '00FD', 'Z' => '0179', 'z' => '018A', }, '~' => { # tilde 'A' => '00C3', 'a' => '00E3', 'E' => '1EBC', 'e' => '1EBD', 'I' => '0128', 'i' => '0129', 'N' => '00D1', 'n' => '00F1', 'O' => '00D5', 'o' => '00F5', 'U' => '0168', 'u' => '0169', 'V' => '1E7C', 'v' => '1E7D', 'Y' => '1EF8', 'y' => '1EF9', }, '`' => { # grave 'A' => '00C0', 'a' => '00E0', 'E' => '00C8', 'e' => '00E8', 'I' => '00CC', 'i' => '00EC', 'N' => '01F8', 'n' => '01F9', 'O' => '00D2', 'o' => '00F2', 'U' => '00D9', 'u' => '00F9', 'W' => '1E80', 'w' => '1E81', 'Y' => '1EF2', 'y' => '1EF3', }, '^' => { # circumflex 'A' => '00C2', 'a' => '00E2', 'C' => '0108', 'c' => '0109', 'E' => '00CA', 'e' => '00EA', 'G' => '011C', 'g' => '011D', 'H' => '0124', 'h' => '0125', 'I' => '00CE', 'i' => '00EE', 'J' => '0134', 'j' => '0135', 'O' => '00D4', 'o' => '00F4', 'S' => '015C', 's' => '015D', 'U' => '00DB', 'u' => '00FB', 'W' => '0174', 'w' => '0175', 'Y' => '0176', 'y' => '0177', 'Z' => '1E90', 'z' => '1E91', }, 'ringaccent' => { # ring 'A' => '00C5', 'a' => '00E5', 'U' => '016E', 'u' => '016F', 'w' => '1E98', 'y' => '1E99', }, 'v' => { # caron 'A' => '01CD', 'a' => '01CE', 'C' => '010C', 'c' => '010D', 'D' => '010E', 'd' => '010F', 'E' => '011A', 'e' => '011B', 'G' => '01E6', 'g' => '01E7', 'H' => '021E', #K with moz-1.2 'h' => '021F', #k with moz-1.2 'I' => '01CF', 'i' => '01D0', 'K' => '01E8', 'k' => '01E9', 'L' => '013D', #L' with moz-1.2 'l' => '013E', #l' with moz-1.2 'N' => '0147', 'n' => '0148', 'O' => '01D1', 'o' => '01D2', 'R' => '0158', 'r' => '0159', 'S' => '0160', 's' => '0161', 'T' => '0164', 't' => '0165', 'U' => '01D3', 'u' => '01D4', 'Z' => '017D', 'z' => '017E', }, 'H' => { # double acute 'O' => '0150', 'o' => '0151', 'U' => '0170', 'u' => '0171', }, 'ogonek' => { 'A' => '0104', 'a' => '0105', 'E' => '0118', 'e' => '0119', 'I' => '012E', 'i' => '012F', 'U' => '0172', 'u' => '0173', 'O' => '01EA', 'o' => '01EB', }, ); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { $style_map{$accent_command} = { 'function' => \&t2h_default_accent }; $old_style_map{$accent_command} = '&default_accent'; $style_map_texi{$accent_command} = { 'function' => \&t2h_default_accent }; } %transliterate_accent_map = (); foreach my $command (keys(%unicode_accents)) { foreach my $letter(keys (%{$unicode_accents{$command}})) { $transliterate_accent_map{$unicode_accents{$command}->{$letter}} = $letter unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}})); } } sub default_accent($$) { my $text = shift; my $accent = shift; return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/)); return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); return $text . '<' if ($accent eq 'v'); return ascii_accents($text, $accent); } sub t2h_default_accent($$) { my $accent = shift; my $args = shift; my $text = $args->[0]; return ascii_accents($text, $accent); } #################################################################### # special accent/encoding commands # # Some functions used to override normal formatting functions in specific # cases. The user shouldn't want to change them, but can use them. # sub ascii_accents($$) { my $text = shift; my $accent = shift; return $text if ($accent eq 'dotless'); return $text . "''" if ($accent eq 'H'); return $text . '.' if ($accent eq 'dotaccent'); return $text . '*' if ($accent eq 'ringaccent'); return $text . '[' if ($accent eq 'tieaccent'); return $text . '(' if ($accent eq 'u'); return $text . '_' if ($accent eq 'ubaraccent'); return '.' . $text if ($accent eq 'udotaccent'); return $text . '<' if ($accent eq 'v'); return $text . ';' if ($accent eq 'ogonek'); return $text . $accent if (defined($accent_map{$accent})); } sub xml_default_accent($$) { my $accent = shift; my $args = shift; my $text = $args->[0]; return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/)); return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); return $text . '<' if ($accent eq 'v'); # FIXME here there could be a conversion to the character in the right # encoding, like # if ($USE_UNICODE and defined($OUT_ENCODING) and $OUT_ENCODING ne '' # and exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text})) # { # my $encoded_char = Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET); # return $encoded_char if ($encoded_char ne ''); # } if ($USE_NUMERIC_ENTITY) { if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text})) { return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';'); } } return ascii_accents($text, $accent); } # used to utf8 encode the result sub t2h_utf8_accent($$$) { my $accent = shift; my $args = shift; my $style_stack = shift; my $text = $args->[0]; #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n"; # special handling of @dotless{i} if ($accent eq 'dotless') { if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent'))) { return "\x{0131}"; } #return "\x{}" if ($text eq 'j'); # not found ! return $text; } # FIXME \x{0131}\x{0308} for @dotless{i} @" doesn't lead to NFC 00ef. return Unicode::Normalize::NFC($text . chr(hex($unicode_diacritical{$accent}))) if (defined($unicode_diacritical{$accent})); return ascii_accents($text, $accent); } sub t2h_utf8_normal_text($$$$$$$;$) { my $text = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; my $style_stack = shift; my $state = shift; $text = &$protect_text($text) unless($in_raw_text); $text = uc($text) if (in_small_caps($style_stack)); if (!$in_code and !$in_preformatted) { $text =~ s/---/\x{2014}/g; $text =~ s/--/\x{2013}/g; $text =~ s/``/\x{201C}/g; $text =~ s/''/\x{201D}/g; } $text = t2h_text_substitutions($text, $in_raw_text, ($in_preformatted or $in_code), $in_simple); return Unicode::Normalize::NFC($text); } sub t2h_enable_encoding_normal_accent($$$) { return t2h_enable_encoding_accent ('normal', @_); } sub t2h_enable_encoding_texi_accent($$$) { return t2h_enable_encoding_accent ('texi', @_); } sub t2h_enable_encoding_pre_accent($$$) { return t2h_enable_encoding_accent ('pre', @_); } sub t2h_enable_encoding_accent($$$$) { my $context = shift; my @other_args = @_; my $accent = shift; my $args = shift; my $style_stack = shift; my $text = $args->[0]; #print STDERR "enable_encoding_accent called($context) $accent (@$style_stack)\n"; # in case ENCODING_NAME is not known, the accent functions saved previously # are used. # This should happen rarely, like during @setfilename parsing. return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args) if (!defined($Texi2HTML::THISDOC{'ENCODING_NAME'})); return t2h_utf8_accent($accent,[$text],$style_stack) if ($Texi2HTML::THISDOC{'ENCODING_NAME'} eq 'utf-8'); # use the saved default handling if this is not a known 8 bit encoding return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args) if (!exists($makeinfo_encoding_to_map{$Texi2HTML::THISDOC{'ENCODING_NAME'}})); # the following is for the handling of known 8 bit encodings. if (scalar(@t2h_enable_encoding_accents_stack)) { # in that case, we already have a result ready that corresponds with the # formatting of a part of the stack mapped to # t2h_enable_encoding_accents_stack, so it is emptied and the innermost # $text is returned as is, such that the unmodified already formatted # innermost formatted accented text is returned. #print STDERR " doing nothing, still in stack (@t2h_enable_encoding_accents_stack), accent: $accent"; my $stack_accent = shift @t2h_enable_encoding_accents_stack; #print STDERR " stack_accent $stack_accent\n"; return $text; } # in that case there is no t2h_enable_encoding_accents_stack, so we are # at the closing of the innermost accented command. We will try to format # all the stack in reverse(@$style_stack) that coresponds with # accent commands my @accents_stack = (); my @styles = reverse(@$style_stack); # accents are formatted and the intermediate results are kept, such # that we can return the maximum of multiaccented letters that can be # rendered with a given eight bit formatting. # first put the letter in the stack my @utf8_partial_results = { 'result' => $text, 'accents_stack' => [ @accents_stack ]}; # then the accent that is associated with the function call my $current_accent = t2h_utf8_accent($accent,[$text],$style_stack); @accents_stack = ($accent); push @utf8_partial_results, { 'result' => $current_accent, 'accents_stack' => [ @accents_stack ]}; # and then all the other accents on the stack while (scalar(@styles) and (defined($unicode_accents{$styles[0]}) or $styles[0] eq 'dotless')) { my $next_style = shift @styles; my @new_stack = reverse(@styles); $current_accent = t2h_utf8_accent($next_style,[$current_accent],\@new_stack); push @accents_stack, $next_style; push @utf8_partial_results, { 'result' => $current_accent, 'accents_stack' => [ @accents_stack ]} ; } my $enc_map = $makeinfo_encoding_to_map{$Texi2HTML::THISDOC{'ENCODING_NAME'}}; my $eight_bit; my $result; # At this point we have the utf8 encoded results for the accent # commands stack, with all the intermediate results. # For each one we'll check if it is possible to encode it in the # current eight bit output encoding table foreach my $partial_result (@utf8_partial_results) { my $char = $partial_result->{'result'}; my $new_eight_bit = ''; my $new_codepoint; if (ord($char) <= 128) { $new_eight_bit = uc(sprintf("%02x",ord($char))); $new_codepoint = uc(sprintf("%04x",ord($char))); } elsif (ord($char) <= hex(0xFFFF)) { $new_codepoint = uc(sprintf("%04x",ord($char))); if (exists($makeinfo_unicode_to_eight_bit{$enc_map}->{$new_codepoint})) { $new_eight_bit = $makeinfo_unicode_to_eight_bit{$enc_map}->{$new_codepoint}; } } #my $eight_bit_txt = 'undef'; #$eight_bit_txt = $eight_bit if (defined($eight_bit)); #print STDERR "" . Encode::encode('utf8', "$char") . " (@{$partial_result->{'accents_stack'}}), new_codepoint: $new_codepoint 8bit: $new_eight_bit old:$eight_bit_txt\n"; # no corresponding eight bit character found last if ($new_eight_bit eq ''); # in that case, the new eight bit character is the same than the one # found with one less character (and it isnt a @dotless{i}). It may # mean 2 things # -> there are 2 characters in accent. This could happen, for example # if an accent that cannot be rendered is found and it leads to # appending or prepending a character. For example this happens for # @={@,{@~{n}}}, where @,{@~{n}} is expanded to a 2 character: # n with a tilde, followed by a , # In nthat case, the additional utf8 accent is prepended, which # means that it is composed with the , and leaves n with a tilde # untouched. # -> ord(char) leads to the same for the more inner character. # this, for example, happens for @ubaraccent{a}, where ord(a) is # the same than ord(a with underbar). last if (defined($eight_bit) and (($new_eight_bit eq $eight_bit) and !($partial_result->{'accents_stack'}[0] eq 'dotless' and $char eq 'i'))); $result = $partial_result; $eight_bit = $new_eight_bit; } if (defined($result) and scalar(@{$result->{'accents_stack'}})) { # we got a result, return it and put in t2h_enable_encoding_accents_stack # the stack of accent commands that were processed. They wont be used # further, but only unshifted. #print STDERR "Result: ".Encode::encode('utf8', $result->{'result'}) ." '$eight_bit' (@{$result->{'accents_stack'}})\n" if defined($result); @t2h_enable_encoding_accents_stack = @{$result->{'accents_stack'}}; # remove the first, it is the accent being processed shift @t2h_enable_encoding_accents_stack; # it should be noted that we return the 'utf8' accent (which is really # a codepoint, and not the eight bit representation, we leave the # conversion to perl, which should handle it fine return $result->{'result'}; } return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args); } # end special accent/encoding commands #################################################################### #################################################################### # TeX/LaTeX, that can especially be used in @math # To load the appropriate hash, use # default_load_tex_math my %tex_default_simple_map_math = ( '{' => '\{', '}' => '\}', '\\' => '\\' ); my %tex_default_math_things_map = %default_things_map; $tex_default_math_things_map{'bullet'} = '\bullet'; $tex_default_math_things_map{'copyright'} = '\copyright'; $tex_default_math_things_map{'registeredsymbol'} = '\circledR'; $tex_default_math_things_map{'dots'} = '\dots'; $tex_default_math_things_map{'endots'} = '\dots'; $tex_default_math_things_map{'equiv'} = '\equiv'; $tex_default_math_things_map{'expansion'} = '\mapsto'; $tex_default_math_things_map{'arrow'} = '\rightarrow'; $tex_default_math_things_map{'point'} = '\star'; $tex_default_math_things_map{'print'} = '\dashv'; $tex_default_math_things_map{'result'} = '\Rightarrow'; $tex_default_math_things_map{'pounds'} = '\pounds'; $tex_default_math_things_map{'geq'} = '\geq'; $tex_default_math_things_map{'leq'} = '\leq'; $tex_default_math_things_map{'textdegree'} = '^\circ'; my %latex_default_math_things_map = %tex_default_math_things_map; $latex_default_math_things_map{'aa'} = '\mathring{a}'; $latex_default_math_things_map{'AA'} = '\mathring{A}'; # FIXME Maybe this should not be there since it is not for math but # more for a completly separate format. my %latex_default_things_map; foreach my $thing (keys(%default_things_map)) { $latex_default_things_map{$thing} = '\\'.$thing; } $latex_default_things_map{'error'} = '\fbox{error}'; $latex_default_things_map{'enddots'} = '\dots\@'; $latex_default_things_map{'exclamdown'} = '\textexclamdown'; $latex_default_things_map{'questiondown'} = '\textquestiondown'; $latex_default_things_map{'tie'} = '~'; $latex_default_things_map{'registeredsymbol'} = '\textregistered'; $latex_default_things_map{'ordf'} = '\textordfeminine'; $latex_default_things_map{'ordm'} = '\textordmasculine'; $latex_default_things_map{'guillemetleft'} = '\guillemotleft'; $latex_default_things_map{'guillemetright'} = '\guillemotright'; foreach my $text_prefixed_symbols ('bullet', 'exclamdown', 'questiondown', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright') { $latex_default_things_map{$text_prefixed_symbols} = '\text'.$text_prefixed_symbols; } foreach my $math_only ('equiv', 'expansion', 'arrow', 'minus', 'point', 'print', 'result', 'geq', 'leq') { $latex_default_things_map{$math_only} = '$'.$latex_default_math_things_map{$math_only}.'$'; } # End TeX/LaTeX ############################################################# sub default_sc($$) { return uc($_[0]); } sub default_ctrl($$) { return "^$_[0]"; } # obsolete, no warning, but noop sub t2h_default_ctrl($$$) { shift; my $args = shift; #return "^$args->[0]"; return "$args->[0]"; } sub default_sc_pre($$) { return uc($_[0]); } sub default_titlefont($$) { return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/); return ''; } # Return nothing if the text is empty sub t2h_default_titlefont($$$) { shift; my $args = shift; my $heading = $args->[0]; return '' unless ($heading =~ /\S/); return &$heading_text('@titlefont', $heading, 0); } # At some point in time (before 4.7?) according to the texinfo # manual, url shouldn't lead to a link but rather be formatted # like text. It is now what indicateurl do, url is the same that # uref with one arg. If we did like makeinfo did it would have been #sub url($$) #{ # return '<<code>' . $_[0] . '</code>>'; #} # # This is unused, t2h_default_uref is used instead sub t2h_default_url ($$) { shift; my $args = shift; my $url = shift @$args; $url = main::normalise_space($url); return '' unless ($url =~ /\S/); return t2h_default_url_and_text($url); } sub default_url ($$) { my $url = shift; my $command = shift; $url =~ s/\s*$//; $url =~ s/^\s*//; return t2h_default_url_and_text($url); } sub default_uref($$) { my $arg = shift; my $command = shift; my ($url, $text, $replacement); ($url, $text, $replacement) = split /,\s*/, $arg; $url =~ s/\s*$//; $url =~ s/^\s*//; $text = $replacement if (defined($replacement)); return t2h_default_url_and_text($url, $text); } sub t2h_default_uref($$) { shift; my $args = shift; my $url = shift @$args; my $text = shift @$args; my $replacement = shift @$args; $url = main::normalise_space($url); $replacement = '' if (!defined($replacement)); $replacement = main::normalise_space($replacement); $text = '' if (!defined($text)); $text = main::normalise_space($text); $text = $replacement if ($replacement ne ''); return t2h_default_url_and_text($url, $text); } sub t2h_default_math($$) { shift; my $args = shift; my $text = shift @$args; return "$text"; } sub default_email($$) { my $arg = shift; my $command = shift; my ($mail, $text); ($mail, $text) = split /,\s*/, $arg; $mail =~ s/\s*$//; $mail =~ s/^\s*//; return t2h_default_url_and_text("mailto:$mail", $text); } sub t2h_default_email($$) { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); if (defined($text)) { #$text =~ s/^\s*//; #$text =~ s/^\s*$//; $text = main::normalise_space($text); } my $mailto = ''; $mailto = "mailto:$mail" if ($mail ne ''); return t2h_default_url_and_text($mailto, $text); } sub t2h_default_click_normal($$$) { return t2h_default_click('normal', @_); } sub t2h_default_click_pre($$$) { return t2h_default_click('pre', @_); } sub t2h_default_click_texi($$$) { return t2h_default_click('texi', @_); } sub t2h_default_click($$$$$) { my $context = shift; my $command = shift; my $args = shift; my $arg = shift @$args; my $cmd = $Texi2HTML::THISDOC{'clickstyle'}; $cmd = 'arrow' if (!defined($cmd) or ($cmd eq '')); my $hash = \%things_map; if ($context eq 'pre') { $hash = \%pre_map; } elsif ($context eq 'texi') { $hash = \%texi_map; } return $hash->{$cmd} . $arg if (exists($hash->{$cmd})); return $arg; } sub t2h_default_hyphenation($$) { my $command = shift; my $args = shift; my $text = shift @$args; $text =~ s/^\s*//; $text =~ s/\s*$//; my @list = split /\s+/, $text; foreach my $entry (@list) { my $word = $entry; $word =~ s/-//g; $Texi2HTML::THISDOC{'hyphenation'}->{$word} = $entry; } } sub t2h_default_no_texi_email { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); return $text if (defined($text) and ($text ne '')); return $mail; } sub t2h_default_no_texi_image($$$$) { my $command = shift; my $args = shift; my $file = $args->[0]; $file = main::trim_around_spaces($file); return main::substitute_line($file, "\@$command", {'remove_texi' => 1, 'code_style' => 1}); } sub t2h_default_no_texi_acronym_like($$) { my $command = shift; my $args = shift; my $acronym_texi = $args->[0]; return (main::remove_texi($acronym_texi)); } sub t2h_remove_command($$$$) { return ''; } # This is used for style in preformatted sections my %old_style_map_pre = %old_style_map; $old_style_map_pre{'sc'} = '&default_sc_pre'; $old_style_map_pre{'titlefont'} = ''; foreach my $command (keys(%style_map)) { $style_map_texi{$command} = {} if (!exists($style_map_texi{$command})); $style_map_texi{$command}->{'args'} = [ @{$style_map{$command}->{'args'}} ] if (exists($style_map{$command}->{'args'})); #print STDERR "COMMAND $command"; } %style_map_pre = (); t2h_default_copy_style_map(\%style_map, \%style_map_pre); $style_map_pre{'sc'} = {}; $style_map_pre{'titlefont'} = {}; $style_map_pre{'click'}->{'function'} = \&t2h_default_click_pre; $style_map_texi{'sc'} = {}; $style_map_texi{'email'}->{'function'} = \&t2h_default_no_texi_email; $style_map_texi{'click'}->{'function'} = \&t2h_default_click_texi; ####### special styles. You shouldn't need to change them %special_style = ( #'xref' => ['keep','normal','normal','keep','normal'], 'xref' => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_xref }, 'ref' => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_xref }, 'pxref' => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_xref }, 'inforef' => { 'args' => ['keep','keep','keep'], 'function' => \&main::do_xref }, 'image' => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_image }, 'anchor' => { 'args' => ['keep'], 'function' => \&main::do_anchor_label }, 'footnote' => { 'args' => ['keep'], 'function' => \&main::do_footnote }, 'shortcaption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption }, 'caption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption }, 'acronym', {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like}, 'abbr', {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like}, ); # @image is replaced by the first arg in strings $style_map_texi{'image'} = { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&t2h_default_no_texi_image }; $style_map_texi{'acronym'} = { 'args' => ['keep','keep'], 'function' => \&t2h_default_no_texi_acronym_like }; $style_map_texi{'abbr'} = { 'args' => ['keep','keep'], 'function' => \&t2h_default_no_texi_acronym_like }; foreach my $special (keys(%special_style)) { $style_map{$special} = $special_style{$special} unless (defined($style_map{$special})); $style_map_pre{$special} = $special_style{$special} unless (defined($style_map_pre{$special})); $style_map_texi{$special} = { 'args' => ['keep'], 'function' => \&t2h_remove_command } unless (defined($style_map_texi{$special})); } ####### end special styles. #foreach my $command (keys(%style_map)) #{ # print STDERR "STYLE_MAP_TEXI $command($style_map_texi{$command}) "; # print STDERR "ARGS $style_map_texi{$command}->{'args'} " if (defined($style_map_texi{$command}->{'args'})); # print STDERR "FUN $style_map_texi{$command}->{'function'} " if (defined($style_map_texi{$command}->{'function'})); # print STDERR "\n"; #} # uncomment to use the old interface #%style_map = %old_style_map; #%style_map_pre = %old_style_map_pre; %simple_format_simple_map_texi = %simple_map_pre; %simple_format_texi_map = %pre_map; %simple_format_style_map_texi = (); t2h_default_copy_style_map(\%style_map_texi, \%simple_format_style_map_texi); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { # $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal']; $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent; } foreach my $hash (\%style_map, \%style_map_pre, \%style_map_texi, \%simple_format_style_map_texi) { foreach my $style (keys(%{$hash})) { $hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'})); } } %default_style_map = (); %default_style_map_pre = (); %default_style_map_texi = (); %default_simple_format_style_map_texi = (); t2h_default_copy_style_map(\%style_map, \%default_style_map); t2h_default_copy_style_map(\%style_map_pre, \%default_style_map_pre); t2h_default_copy_style_map(\%style_map_texi, \%default_style_map_texi); t2h_default_copy_style_map(\%simple_format_style_map_texi, \%default_simple_format_style_map_texi); # called here because %default_style_map_texi is used. t2h_default_set_variables_default(); ################################################################# # TeX/LaTeX styles, that can be used in math my %default_style_tex_map; my %default_style_latex_map; t2h_default_copy_style_map(\%default_style_map, \%default_style_tex_map); t2h_default_copy_style_map(\%default_style_map, \%default_style_latex_map); # common in TeX and LaTeX and both for math and normal text $default_style_latex_map{'w'}->{'inline_begin'} = '\mbox{'; $default_style_tex_map{'w'}->{'inline_begin'} = '\mbox{'; $default_style_latex_map{'dmn'}->{'inline_begin'} = '{\thinspace '; $default_style_tex_map{'dmn'}->{'inline_begin'} = '{\thinspace '; my %default_style_latex_math_map; t2h_default_copy_style_map(\%default_style_latex_map, \%default_style_latex_math_map); my %default_tex_latex_map = ( 'bf' => [ 'b', 'strong' ], 'tt' => [ 'code', 'command', 'env', 'file', 'option', 'samp', 't' ], 'it' => [ 'i', 'var', 'emph' ], 'sf' => [ 'sanserif' ], 'rm' => [ 'r' ], 'sl' => [ 'dfn', 'slanted' ], ); foreach my $style (keys (%default_tex_latex_map)) { foreach my $command (@{$default_tex_latex_map{$style}}) { $default_style_tex_map{$command}->{'inline_begin'} = '{\\' . $style .' '; $default_style_latex_map{$command}->{'inline_begin'} = '\text' . $style .'{'; $style = 'normal' if ($style eq 'sl'); $default_style_latex_math_map{$command}->{'inline_begin'} = '\math' . $style .'{'; } } # only in text $default_style_latex_map{'emph'}->{'inline_begin'} = '\emph{'; $default_style_latex_map{'var'}->{'inline_begin'} = '\emph{'; $default_style_latex_map{'sc'}->{'inline_begin'} = '\textsc{'; foreach my $hash (\%default_style_tex_map, \%default_style_latex_map, \%default_style_latex_math_map) { foreach my $command (keys(%$hash)) { $hash->{$command}->{'inline_end'} = '}' if ($hash->{$command}->{'inline_begin'}); } } # no kbd key sc in math # 'kbd' - ? # 'key' - ? my %default_style_tex_math_map; t2h_default_copy_style_map(\%default_style_tex_map, \%default_style_tex_math_map); # We don't want to override special commands in math mode for now, as long # as they are not handled especially. Also we don't want to modify the math # function, it is called to close the @math command and we don't want # it to be the turned to the default one when calling # FIXME maybe it would be even better not to duplicate default styles in # math, like 'email', 'uref'.... foreach my $command (keys(%special_style), 'math') { delete $default_style_tex_math_map{$command}; delete $default_style_latex_math_map{$command}; } foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { $default_style_latex_map{$accent_command} = { 'function' => \&default_tex_accent }; $default_style_tex_map{$accent_command} = { 'function' => \&default_tex_accent }; $default_style_tex_math_map{$accent_command} = { 'function' => \&default_tex_math_accent }; $default_style_latex_math_map{$accent_command} = { 'function' => \&default_latex_math_accent }; } my %tex_text_accent_map = ( ',' => 'c', 'ringaccent' => 'r', 'dotaccent' => '.', 'ubaraccent' => 'b', 'udotaccent' => 'd', 'ogonek' => 'k', 'tieaccent' => 'tie', ); sub default_tex_accent($$) { my $text = shift; my $accent = shift; return "\\$tex_text_accent_map{$accent}\{$text\}" if ($tex_text_accent_map{$accent}); if ($accent eq 'dotless') { return "\\$text" if ($text eq 'i' or $text eq 'j'); return $text; } return "\\$accent\{$text\}"; } my %tex_math_accent_map = ( "'" => 'acute', '^' => 'hat', '`' => 'grave', '~' => 'tilde', '"' => 'ddot', '=' => 'bar', 'dotaccent' => 'dot', 'u' => 'breve', 'ubaraccent' => 'underline', ); sub default_latex_math_accent($$) { my $text = shift; my $accent = shift; return '\mathring{'.$text.'}' if ($accent eq 'ringaccent'); return default_tex_math_accent($text, $accent); } sub default_tex_math_accent($$) { my $text = shift; my $accent = shift; return "\\$tex_text_accent_map{$accent}\{$text\}" if ($tex_text_accent_map{$accent}); if ($accent eq 'dotless') { return "\\${text}math" if ($text eq 'i' or $text eq 'j'); return $text; } return ascii_accent($text, $accent); } my $kept_normal_text; # We assume that in @math the TeX characters have already been # rightly protected and so don't protect once more. sub default_tex_normal_math_text($$$$$$$;$) { my @initial_args = @_; my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; my $style_stack = shift; my $state = shift; # Don't protect text in math if ($in_math) { $text = uc($text) if (in_cmd($style_stack, 'sc')); return $text; } return &kept_normal_text(@initial_args); } # This is the entry point to be used by users. sub default_load_tex_math(;$) { my $style = shift; $style = 'latex' if (!defined($style)); %simple_map_math = %tex_default_simple_map_math; if ($style eq 'tex') { %math_map = %tex_default_math_things_map; t2h_default_copy_style_map(\%default_style_tex_math_map, \%style_map_math); } else { %math_map = %latex_default_math_things_map; t2h_default_copy_style_map(\%default_style_latex_math_map, \%style_map_math); } $kept_normal_text = $normal_text; $normal_text = \&default_tex_normal_math_text; } # End TeX/LaTeX styles ################################################################# # regions expanded or not depending on the value of this hash. # @EXPAND sets entries in this hash, and you should better use # @EXPAND unless you know what you are doing. %texi_formats_map = ( 'iftex' => 0, 'ignore' => 0, 'menu' => 0, 'ifplaintext' => 0, 'ifinfo' => 0, 'ifxml' => 0, 'ifhtml' => 0, 'ifdocbook' => 0, # 'html' => 0, # 'tex' => 0, # 'xml' => 0, # 'docbook' => 0, 'titlepage' => 1, 'documentdescription' => 1, 'copying' => 1, 'ifnothtml' => 1, 'ifnottex' => 1, 'ifnotplaintext' => 1, 'ifnotinfo' => 1, 'ifnotxml' => 1, 'ifnotdocbook' => 1, 'direntry' => 'normal', 'verbatim' => 'raw', 'macro' => 'raw', 'ifclear' => 'value', 'ifset' => 'value' , ); %format_map = ( # 'quotation' => 'blockquote', # lists # 'itemize' => 'ul', 'enumerate' => '', # 'multitable' => 'table', 'table' => '', 'vtable' => '', 'ftable' => '', 'group' => '', 'raggedright' => '', # 'detailmenu' => '', ); %special_list_commands = ( 'table' => {}, 'vtable' => {}, 'ftable' => {}, # 'itemize' => { 'bullet' => '' } 'itemize' => {}, ); %inter_item_commands = ( 'c' => 1, 'comment' => 1, 'cindex' => 1 ); # # texinfo format to align attribute of paragraphs # %paragraph_style = ( 'center' => 'center', 'flushleft' => 'left', 'flushright' => 'right', ); # complex formats (preformatted) %complex_format_map = (); foreach my $complex_format ('example', 'smallexample', 'display', 'smalldisplay', 'lisp', 'smalllisp', 'format', 'smallformat', 'menu', 'detailmenu', 'direntry', 'menu_comment') { $complex_format_map{$complex_format} = { 'begin' => '', 'end' => '' }; } foreach my $code_complex_format ('example', 'smallexample', 'lisp', 'smalllisp') { $complex_format_map{$code_complex_format}->{'style'} = 'code'; } # not in code_style, according to post on bug-texinfo foreach my $format ('menu', 'detailmenu', 'direntry') { $complex_format_map{$format}->{'class'} = 'menu-preformatted'; } # not in code_style, according to post on bug-texinfo $complex_format_map{'menu_comment'}->{'class'} = 'menu-comment'; %def_map = ( # basic commands 'deffn', [ 'f', 'category', 'name', 'arg' ], 'defvr', [ 'v', 'category', 'name' ], 'deftypefn', [ 'f', 'category', 'type', 'name', 'argtype' ], 'deftypeop', [ 'f', 'category', 'class' , 'type', 'name', 'argtype' ], 'deftypevr', [ 'v', 'category', 'type', 'name' ], 'defcv', [ 'v', 'category', 'class' , 'name' ], 'deftypecv', [ 'v', 'category', 'class' , 'type', 'name' ], 'defop', [ 'f', 'category', 'class' , 'name', 'arg' ], 'deftp', [ 't', 'category', 'name', 'argtype' ], # shortcuts # FIXME i18n 'defun', 'deffn Function', 'defmac', 'deffn Macro', 'defspec', 'deffn {Special Form}', 'defvar', 'defvr Variable', 'defopt', 'defvr {User Option}', 'deftypefun', 'deftypefn {Function}', 'deftypevar', 'deftypevr Variable', 'defivar', 'defcv {Instance Variable}', 'deftypeivar', 'deftypecv {Instance Variable}', 'defmethod', 'defop Method', 'deftypemethod', 'deftypeop Method', ); $def_always_delimiters = "()[]"; $def_in_type_delimiters = ",;"; $def_argument_separator_delimiters = "()[],"; # basic x commands foreach my $key (keys(%def_map)) { $def_map{$key . 'x'} = $def_map{$key}; } # # miscalleneous commands # # Depending on the value, the command arg or spaces following the command # are handled differently: # # the value is a reference on a hash. # the hash keys are # 'arg' if the value is 'line' then the remaining of the line is the arg # if it is a number it is the number of args (separated by spaces) # 'skip' if the value is 'line' then the remaining of the line is skipped # if the value is 'space' space but no newline is skipped # if the value is 'whitespace' space is skipped # if the value is 'linewhitespace' space is skipped if there are # only spaces remaining on the line # if the value is 'linespace' space but no newline is skipped if # there are only spaces remaining on the line # 'keep' if true the args and the macro are kept, otherwise the macro # args and skipped stuffs are removed %misc_command = ( 'bye' => {'skip' => 'line'}, # no arg # set, clear 'set' => {'skip' => 'line'}, # special arg 'clear' => {'skip' => 'line'}, # special arg 'alias' => {'args' => 3, 'skip' => 'line'}, # special arg # comments 'comment' => {'arg' => 'line'}, 'c' => {'arg' => 'line'}, # not needed for formatting 'raisesections' => {'skip' => 'line'}, # no arg 'lowersections' => {'skip' => 'line'}, # no arg 'contents' => {}, # no arg 'shortcontents' => {}, # no arg 'summarycontents'=> {}, # no arg 'setcontentsaftertitlepage' => {}, # no arg 'setshortcontentsaftertitlepage' => {}, # no arg # 'detailmenu' => {'skip' => 'whitespace'}, # no arg # 'end detailmenu' => {'skip' => 'whitespace'}, # no arg 'clickstyle' => {'skip' => 'line'}, # arg should be an @-command # in preamble 'novalidate' => {}, # no arg 'dircategory'=> {'arg' => 'line'}, # line. Position with regard # with direntry is significant 'pagesizes' => {'skip' => 'line', 'arg' => 'line'}, # can have 2 args # or one? 200mm,150mm 11.5in 'finalout' => {'skip' => 'line'}, # no arg 'paragraphindent' => {'skip' => 'line', 'arg' => 1}, # arg none asis # or a number and forbids anything else on the line 'firstparagraphindent' => {'skip' => 'line', 'arg' => 1}, # none insert 'frenchspacing' => {'arg' => 1, 'skip' => 'line'}, # on off # not so sure about 'skip' => 'line' 'fonttextsize' => {'arg' => 1}, # 10 11 'allowcodebreaks' => {'arg' => 1, 'skip' => 'line'}, # false or true 'exampleindent' => {'skip' => 'line', 'arg' => 1}, # asis or a number 'footnotestyle'=> {'skip' => 'line', 'arg' => 1}, # end and separate # and nothing else on the line 'afourpaper' => {'skip' => 'line'}, # no arg 'afivepaper' => {'skip' => 'line'}, # no arg 'afourlatex' => {'skip' => 'line'}, # no arg 'afourwide' => {'skip' => 'line'}, # no arg 'headings'=> {'skip' => 'line', 'arg' => 1}, #off on single double singleafter doubleafter # interacts with setchapternewpage 'setchapternewpage' => {'skip' => 'line', 'arg' => 1}, # off on odd 'everyheading' => {'arg' => 'line'}, 'everyfooting' => {'arg' => 'line'}, 'evenheading' => {'arg' => 'line'}, 'evenfooting' => {'arg' => 'line'}, 'oddheading' => {'arg' => 'line'}, 'oddfooting' => {'arg' => 'line'}, 'smallbook' => {'skip' => 'line'}, # no arg 'setfilename' => {'arg' => 'line'}, 'definfoenclose' => {'arg' => 'line'}, #'shorttitle' => {'arg' => 'line', 'texi' => 1}, #'shorttitlepage' => {'arg' => 'line', 'texi' => 1}, #'settitle' => {'arg' => 'line', 'texi' => 1}, #'author' => {'arg' => 'line', 'texi' => 1}, #'subtitle' => {'arg' => 'line', 'texi' => 1}, #'title' => {'arg' => 'line', 'texi' => 1}, 'shorttitle' => {'arg' => 'line'}, 'shorttitlepage' => {'arg' => 'line'}, 'settitle' => {'arg' => 'line'}, 'author' => {'arg' => 'line'}, 'subtitle' => {'arg' => 'line'}, 'title' => {'arg' => 'line'}, 'syncodeindex' => {'skip' => 'line', 'arg' => 2}, # args are index identifiers 'synindex' => {'skip' => 'line', 'arg' => 2}, 'defindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg 'defcodeindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg #'documentlanguage' => {'skip' => 'whitespace', 'arg' => 1}, 'documentlanguage' => {'skip' => 'line', 'arg' => 1}, # language code arg 'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code #example distinct 'everyheadingmarks' => {'skip' => 'line', 'arg' => 1}, # top bottom 'everyfootingmarks' => {'skip' => 'whitespace', 'arg' => 1}, 'evenheadingmarks' => {'skip' => 'whitespace', 'arg' => 1}, 'oddheadingmarks' => {'skip' => 'whitespace', 'arg' => 1}, 'evenfootingmarks' => {'skip' => 'whitespace', 'arg' => 1}, 'oddfootingmarks' => {'skip' => 'whitespace', 'arg' => 1}, 'sp' => {'skip' => 'line', 'arg' => 1}, # no arg # at the end of line or a numerical arg # formatting 'page' => {}, # no arg (pagebreak) 'refill' => {}, # no arg (obsolete, to be ignored) 'noindent' => {'skip' => 'whitespace'}, # no arg 'indent' => {'skip' => 'whitespace'}, 'need' => {'skip' => 'line', 'arg' => 1}, # one numerical/real arg 'exdent' => {'skip' => 'space'}, # not valid for info (should be in @iftex) 'vskip' => {'arg' => 'line'}, # arg line in TeX 'cropmarks' => {}, # no arg # miscalleneous 'verbatiminclude'=> {'skip' => 'line'}, 'documentencoding' => {'arg' => 1, 'skip' => 'line'}, # ??? 'filbreak' => {}, # obsolete @-commands. Remove spaces and end of lines after the # commands? If no, they can lead to empty lines 'quote-arg' => {'skip' => 'line'}, 'allow-recursion' => {'skip' => 'line'}, ); my %misc_command_old = ( # not needed for formatting 'raisesections', 'line', # no arg 'lowersections', 'line', # no arg 'contents', 1, # no arg 'shortcontents', 1, # no arg 'summarycontents', 1, # no arg 'detailmenu', 'whitespace', # no arg 'end detailmenu', 'whitespace', # no arg #'end detailmenu', 1, # no arg 'novalidate', 1, # no arg 'bye', 'line', # no arg # comments 'comment', 'line', 'c', 'line', # in preamble 'dircategory', 'line', # line. Position with regard with direntry is # significant 'pagesizes', 'line arg2', # can have 2 args 'finalout', 1, # no arg 'paragraphindent', 'line arg1', # in fact accepts only none asis # or a number and forbids anything else on the line 'firstparagraphindent', 'line arg1', # in fact accepts only none insert 'exampleindent', 'line arg1', # in fact accepts only asis or a number 'footnotestyle', 'line arg1', # in fact accepts only end and separate # and nothing else on the line 'afourpaper', 'line', # no arg 'afourlatex', 'line', # no arg 'afourwide', 'line', # no arg 'headings', 'line', # one arg, possibilities are #off on single double singleafter doubleafter # interacts with setchapternewpage 'setchapternewpage', 'line', # no arg 'everyheading', 'line', 'everyfooting', 'line', 'evenheading', 'line', 'evenfooting', 'line', 'oddheading', 'line', 'oddfooting', 'line', 'smallbook', 'line', # no arg 'setfilename', 'line', 'shorttitle', 'linetexi', 'shorttitlepage', 'linetexi', 'settitle', 'linetexi', 'author', 'linetexi', 'subtitle', 'linetexi', 'title','linetexi', 'syncodeindex','linespace arg2', # args are 'synindex','linespace arg2', 'defindex', 'line arg1', # one identifier arg 'defcodeindex', 'line arg1', # one identifier arg 'documentlanguage', 'whitespace arg1', # one language code arg 'kbdinputstyle', 'whitespace arg1', # one arg within #code example distnct 'sp', 'whitespace arg1', # no arg at the en of line or a numerical arg # formatting 'page', 1, # no arg (pagebreak) 'refill', 1, # no arg (obsolete, to be ignored)) 'noindent', 'space', # no arg 'need', 'line arg1', # one numerical/real arg 'exdent', 'space', # not valid for info (should be in @iftex) 'vskip', 'line', # arg line in TeX 'cropmarks', 1, # no arg # miscalleneous 'verbatiminclude', 'line', 'documentencoding', 'arg1', # ??? 'filbreak', 1, ); # The command_handler arrays are for commands formatted externally. # The function references in @command_handler_init are called # before the second pass, before the @-commands text collection. # Those in @command_handler_process are called between the second pass # and the third pass, after collection of @-commands text and before their # expansion. # Those in @command_handler_process are called after the third pass, # after the document generation. @command_handler_setup = (); @command_handler_init = (); @command_handler_names = (); @command_handler_process = (); @command_handler_output = (); @command_handler_finish = (); sub t2h_default_push_handler($$) { my $function = shift; my $handlers = shift; push @$handlers, $function unless (grep {$_ eq $function} @$handlers); } # the keys of %command_handler are @-command names and the value # is a hash reference with the following keys: # 'init' function reference used to collect the @-command text # 'expand' function reference used when expanding the @-command text %command_handler = (); # formatting functions $anchor = \&t2h_default_anchor; $def_item = \&t2h_default_def_item; $def = \&t2h_default_def; $menu_command = \&t2h_default_menu_command; $menu_link = \&t2h_default_menu_link; #$menu_comment = \&t2h_default_menu_comment; $menu_description = \&t2h_default_menu_description; #$simple_menu_link = \&t2h_default_simple_menu_link; $table_item = \&t2h_default_table_item; $table_line = \&t2h_default_table_line; $table_list = \&t2h_default_table_list; $row = \&t2h_default_row; $cell = \&t2h_default_cell; $list_item = \&t2h_default_list_item; $comment = \&t2h_default_comment; $def_line = \&t2h_default_def_line; $def_line_no_texi = \&t2h_default_def_line_no_texi; $raw = \&t2h_default_raw; $raw_no_texi = \&t2h_default_raw_no_texi; $heading = \&t2h_default_heading; $heading_text = \&t2h_default_heading_text; $heading_text_preformatted = \&t2h_default_heading_text_preformatted; $element_heading = \&t2h_default_element_heading; $heading_no_texi = \&t2h_default_heading_no_texi; $external_href = \&t2h_default_external_href; $paragraph = \&t2h_default_paragraph; $preformatted = \&t2h_default_preformatted; $foot_line_and_ref = \&t2h_default_foot_line_and_ref; $foot_section = \&t2h_default_foot_section; $image_files = \&t2h_default_image_files; $image = \&t2h_default_image; $index_entry_label = \&t2h_default_index_entry_label; $index_summary = \&t2h_default_index_summary; $summary_letter = \&t2h_default_summary_letter; $index_entry = \&t2h_default_index_entry; $index_entry_command = \&t2h_default_index_entry_command; $index_letter = \&t2h_default_index_letter; #$printindex = \&t2h_default_printindex; $print_index = \&t2h_default_print_index; $protect_text = \&t2h_default_protect_text; $normal_text = \&t2h_default_normal_text; $cartouche = \&t2h_default_cartouche; $sp = \&t2h_default_sp; $definition_category = \&t2h_default_definition_category; $definition_index_entry = \&t2h_default_definition_index_entry; $copying_comment = \&t2h_default_copying_comment; $documentdescription = \&t2h_default_documentdescription; $index_summary_file_entry = \&t2h_default_index_summary_file_entry; $index_summary_file_end = \&t2h_default_index_summary_file_end; $index_summary_file_begin = \&t2h_default_index_summary_file_begin; $empty_line = \&t2h_default_empty_line; $float = \&t2h_default_float; $listoffloats = \&t2h_default_listoffloats; $listoffloats_entry = \&t2h_default_listoffloats_entry; $listoffloats_caption = \&t2h_default_listoffloats_caption; $listoffloats_float_style = \&t2h_default_listoffloats_float_style; $listoffloats_style = \&t2h_default_listoffloats_style; $acronym_like = \&t2h_default_acronym_like; $quotation = \&t2h_default_quotation; $paragraph_style_command = \&t2h_default_paragraph_style_command; $heading_texi = \&t2h_default_heading_texi; $index_element_heading_texi = \&t2h_default_index_element_heading_texi; $element_label = \&t2h_default_element_label; $anchor_label = \&t2h_default_anchor_label; $preserve_misc_command = \&t2h_default_preserve_misc_command; $format_list_item_texi = \&t2h_default_format_list_item_texi; $begin_format_texi = \&t2h_default_begin_format_texi; $insertcopying = \&t2h_default_insertcopying; $simple_command = \&t2h_default_simple_command; $thing_command = \&t2h_default_thing_command; $line_command = \&t2h_default_line_command; $internal_links = \&t2h_default_internal_links; # address is not used anymore $address = \&t2h_default_address; # return the line after preserving things according to misc_command map. # You should not change it. It is here, nevertheless, to be used # in other function references if needed. sub t2h_default_preserve_misc_command($$) { my $line = shift; my $macro = shift; my $text = ''; my $args = []; my $skip_spec = ''; my $arg_spec = ''; #print STDERR "HHHHHHHHH $line $macro\n"; $skip_spec = $misc_command{$macro}->{'skip'} if (defined($misc_command{$macro}->{'skip'})); $arg_spec = $misc_command{$macro}->{'arg'} if (defined($misc_command{$macro}->{'arg'})); if ($arg_spec eq 'line') { $text .= $line; $args = [ $line ]; $line = ''; } elsif ($arg_spec) { my $arg_nr = $misc_command{$macro}->{'arg'}; while ($arg_nr) { $line =~ s/(\s+\S*)//o; my $argument = $1; if (defined($argument)) { $text .= $argument; push @$args, $argument; } $arg_nr--; } } if ($macro eq 'bye') { $line = ''; $text = "\n"; } elsif ($skip_spec eq 'linespace') { if ($line =~ /^\s*$/o) { $line =~ s/([ \t]*)//o; $text .= $1; } } elsif ($skip_spec eq 'linewhitespace') { if ($line =~ /^\s*$/o) { $text .= $line; $line = ''; } } elsif ($skip_spec eq 'line') { $text .= $line; $line = ''; } elsif ($skip_spec eq 'whitespace') { $line =~ s/(\s*)//o; $text .= $1; } elsif ($skip_spec eq 'space') { $line =~ s/([ \t]*)//o; $text .= $1; } $line = '' if (!defined($line)); return ($line, $text, $args); } sub t2h_default_simple_command($$$$$) { my $command = shift; my $in_preformatted = shift; my $in_math = shift; my $line_nr = shift; my $state = shift; if ($in_math) { my $result = $simple_map_pre{$command}; $result = $simple_map_math{$command} if (defined($simple_map_math{$command})); return $result; } elsif ($in_preformatted) { return $simple_map_pre{$command}; } else { return $simple_map{$command}; } } sub t2h_default_thing_command($$$$$$) { my $command = shift; my $text = shift; my $in_preformatted = shift; my $in_math = shift; my $line_nr = shift; my $state = shift; my $result; if ($in_math) { $result = $pre_map{$command}; $result = $math_map{$command} if (defined($math_map{$command})); } elsif ($in_preformatted) { $result = $pre_map{$command}; } else { $result = $things_map{$command}; } return $result . $text; } # this is called each time a format begins. Here it is used to keep a # record of the multitables to have a faithful count of the cell nr. sub t2h_default_begin_format_texi($$$) { my $command = shift; my $line = shift; my $state = shift; # remove space in front of center, unless it removes the end of line! $line =~ s/^\s*// if ($command eq 'center' and $line =~ /\S/); return $line; } # This function is called whenever a complex format is processed # # arguments: # name of the format # text appearing inside the format # # an eval of $complex_format->{format name}->{'begin'} should lead to the # beginning of the complex format, an eval of # $complex_format->{format name}->{'end'} should lead to the end of the # complex format. sub t2h_default_complex_format($$) { my $name = shift; my $text = shift; return '' if ($text eq ''); return '' if ($name eq 'direntry'); my $beginning; my $end; # FIXME obsoleted in nov 2009 if (exists($complex_format_map->{$name})) { $beginning = eval "$complex_format_map->{$name}->{'begin'}"; if ($@ ne '') { main::msg_debug("Evaluation of $complex_format_map->{$name}->{'begin'}: $@"); $beginning = ''; } $end = eval "$complex_format_map->{$name}->{'end'}"; if ($@ ne '') { main::msg_debug("Evaluation of $complex_format_map->{$name}->{'end'}: $@"); $end = ''; } } else { $beginning = $complex_format_map{$name}->{'begin'}; $beginning = '' if (!defined($beginning)); $end = $complex_format_map{$name}->{'end'}; $end = '' if (!defined($end)); } return $beginning . $text . $end; } sub t2h_default_empty_line($$) { my $text = shift; my $state = shift; #ignore the line if it just follows a deff return '' if ($state->{'deff_line'}); return $text; } sub t2h_default_unknown($$$$$) { my $macro = shift; my $line = shift; my $pass = shift; my $stack = shift; my $state = shift; my ($result_line, $result, $result_text, $message); return ($line, 0, undef, undef); } sub t2h_default_unknown_style($$$$$) { my $command = shift; my $text = shift; my $state = shift; my $no_close = shift; my $no_open = shift; my ($result, $result_text, $message); return (0, undef, undef); } sub t2h_default_caption_shortcaption($) { my $float = shift; my $caption_lines; my $shortcaption_lines; my $style = $float->{'style_texi'}; if (defined($float->{'nr'})) { my $nr = $float->{'nr'}; if ($style ne '') { $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr}); } else { $style = $nr; } } my $empty_caption = 1; if (defined($float->{'caption_texi'}) and @{$float->{'caption_texi'}}) { @$caption_lines = @{$float->{'caption_texi'}}; $caption_lines->[0] =~ s/^\s*//; if ($caption_lines->[0] =~ /\S/ or @$caption_lines > 2) { $empty_caption = 0; } } if (!$empty_caption) { if (defined($style)) { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] }); } else { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $caption_lines->[0]; } push @$caption_lines, "}\n"; } elsif (defined($style)) { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n"; } my $empty_shortcaption = 1; if (defined($float->{'shortcaption_texi'}) and @{$float->{'shortcaption_texi'}}) { @$shortcaption_lines = @{$float->{'shortcaption_texi'}}; $shortcaption_lines->[0] =~ s/^\s*//; if ($shortcaption_lines->[0] =~ /\S/ or @$shortcaption_lines > 1) { $empty_shortcaption = 0; } } if (!$empty_shortcaption) { if (defined($style)) { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] }); } else { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $shortcaption_lines->[0]; } push @$shortcaption_lines, "}\n"; } elsif (defined($style)) { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n"; } return ($caption_lines, $shortcaption_lines); } # everything is done in &$float sub t2h_default_caption_shortcaption_command($$$$) { my $command = shift; my $text = shift; my $texi_lines = shift; my $float_element = shift; return ''; } sub t2h_default_float($$$$$) { my $text = shift; my $float = shift; my $caption = shift; my $shortcaption = shift; my $label = ''; if (exists($float->{'id'})) { $label = &$anchor($float->{'id'}); } my $caption_text = ''; if (defined($float->{'caption_texi'})) { $caption_text = $caption; } elsif (defined($float->{'shortcaption_texi'})) { $caption_text = $shortcaption; } elsif (defined($caption)) { $caption_text = $caption; } return $text . "\n" . $caption_text; } sub t2h_default_listoffloats_style($) { my $style_texi = shift; return ($style_texi); } sub t2h_default_listoffloats_float_style($$) { my $style_texi = shift; my $float = shift; my $style = $float->{'style_texi'}; #print STDERR "listoffloat/float style mismatch $style_texi $style\n" if ($style_texi ne $style); if (defined($float->{'nr'})) { my $nr = $float->{'nr'}; if ($style ne '') { $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr}); } else { $style = $nr; } } return $style; } sub t2h_default_listoffloats_caption($) { my $float = shift; if (defined($float->{'shortcaption_texi'})) { return ([ @{$float->{'shortcaption_texi'}} ], 'shortcaption'); } elsif (defined($float->{'caption_texi'})) { return ([ @{$float->{'caption_texi'}} ], 'caption'); } return ([ ], undef); } sub t2h_default_listoffloats_entry($$$$) { my $style_texi = shift; my $float = shift; my $float_style = shift; my $caption = shift; my $href = shift; my @lines = split /^/, $caption; $caption = $lines[0]; $caption = '' if (!defined($caption)); chomp ($caption); $caption = $float->{'text'} if ($caption eq '' and defined($float->{'text'}) and $float->{'text'} =~ /\S/); return "* $float_style: ${caption}\n"; } sub t2h_default_listoffloats($$$) { my $style_texi = shift; my $style = shift; my $float_entries = shift; my $result = "* List of $style:\n"; foreach my $float_entry (@$float_entries) { $result .= $float_entry; } return $result . "\n"; } sub t2h_default_insertcopying($$$) { my $text = shift; my $comment = shift; my $simple_text = shift; return $text; } sub t2h_default_protect_text($) { my $text = shift; return $text; } # This function is used to protect characters which are special in xml # in inline text: &, ", <, and >. # # argument: # text to be protected sub xml_default_protect_text($) { my $text = shift; $text =~ s/&/&/g; $text =~ s/</</g; $text =~ s/>/>/g; $text =~ s/\"/"/g; return $text; } sub in_cmd($$) { my $style_stack = shift; my $command = shift; my $result = 0; if ($style_stack and scalar(@{$style_stack})) { my $level = $#$style_stack; #print STDERR ":::$level ::@{$style_stack}\n"; while ($level >= 0) { if ($style_stack->[$level] eq $command) { $result = 1; last; } $level--; } } return $result; } # # sub in_small_caps($) { my $style_stack = shift; my $in_sc = 0; if ($style_stack and scalar(@{$style_stack})) { my $level = $#$style_stack; #print STDERR ":::$level ::@{$style_stack}\n"; while ($level >= 0) { if ($style_stack->[$level] eq 'sc') { $in_sc = 1; last; } $level--; } } return $in_sc; } # # sub t2h_default_normal_text($$$$$$$;$) { my @initial_args = @_; my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; my $style_stack = shift; my $state = shift; # like utf8.init if ($ENABLE_ENCODING and !$ENABLE_ENCODING_USE_ENTITY and defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and $Texi2HTML::THISDOC{'ENCODING_NAME'} eq 'utf-8' and $USE_UNICODE) { return &t2h_utf8_normal_text(@initial_args); } $text = uc($text) if (in_cmd($style_stack, 'sc')); if (! $in_code and !$in_preformatted) { $text =~ s/---/\x{1F}/g; $text =~ s/--/-/g; $text =~ s/\x{1F}/--/g; $text =~ s/``/"/g; $text =~ s/\'\'/"/g; } else { # to be like tex. This would be wrong, however. # my $special_code = 0; # $special_code = 1 if (in_cmd($style_stack, 'code') or # in_cmd($style_stack, 'example') or in_cmd($style_stack, 'verbatim')); # $text =~ s/'/\&rsquo\;/g unless ($special_code and exists($main::value{'txicodequoteundirected'})); # $text =~ s/`/\&lsquo\;/g unless ($special_code and exists($main::value{'txicodequotebacktick'})); } $text = t2h_text_substitutions($text, $in_raw_text, ($in_preformatted or $in_code), $in_simple); return $text; } sub t2h_default_url_and_text($;$) { my $url = shift; my $text = shift; if (!defined($text) or $text eq '') { return "<$url>" if (defined($url) and $url ne ''); return ''; } else { return $text if (!defined($url) or $url eq ''); return "$text <$url>"; } } # This function produces an anchor. This need is quite html specific. # # arguments: # $name : anchor name # $href : anchor href # text : text displayed # extra_attribs : added to anchor attributes list sub t2h_default_anchor($;$$$) { my $name = shift; my $href = shift; my $text = shift; my $attributes = shift; return $text if (defined($text)); return ''; } # This function is used to format the text associated with a @deff/@end deff # # argument: # text # # $DEF_TABLE should be used to distinguish between @def formatted as table # and as definition lists. sub t2h_default_def_item($$$) { my $text = shift; my $only_inter_item_commands = shift; my $command = shift; if ($text =~ /\S/) { return $text; } return ''; } sub t2h_default_definition_category($$$$) { my $name = shift; my $class = shift; my $style = shift; my $command = shift; return ($name) if (!defined($class) or $class =~ /^\s*$/); if ($style eq 'f') { return gdt('{name} on {class}', { 'name' => $name, 'class' => $class }); } elsif ($style eq 'v') { return gdt('{name} of {class}', { 'name' => $name, 'class' => $class }); } else { return $name; } } sub t2h_default_definition_index_entry($$$$) { my $name = shift; my $class = shift; my $style = shift; my $command = shift; return ($name) if (!defined($class) or $class =~ /^\s*$/); if ($style eq 'f') { return gdt('{name} on {class}', { 'name' => $name, 'class' => $class }); } elsif ($style eq 'v' and $command ne 'defcv') { return gdt('{name} of {class}', { 'name' => $name, 'class' => $class }); } else { return $name; } } sub t2h_default_summary_letter($$$$$$$) { my $letter = shift; my $file = shift; my $default_identifier = shift; my $index_element_id = shift; my $number = shift; my $index_element = shift; my $index_name = shift; return ''; } # format the container for the @deffn line and text # # argument # text of the whole @def, line and associated text. # # $DEF_TABLE should be used. sub t2h_default_def($$) { my $text = shift; my $command = shift; if ($text =~ /\S/) { return $text; } return ''; } # a whole menu # # argument: # the whole menu text (entries and menu comments) # # argument: # whole menu text. # not used since menu is a normal preformatted command with SIMPLE_MENU sub t2h_default_menu_command($$$) { my $format = shift; my $text = shift; my $in_preformatted = shift; return "* Menu:\n".$text."\n"; } # formats a menu entry link pointing to a node or section # # arguments: # the entry text # the state, a hash reference holding informations about the context, with a # usefull entry, 'preformatted', true if we are in a preformatted format # (a format keeping space between words). In that case a function # of the main program, main::do_preformatted($text, $state) might # be used to format the text with the current format style. # href is optionnal. It is the reference to the section or the node anchor # which should be used to make the link (typically it is the argument # of a href= attribute in a <a> element). sub t2h_default_menu_link($$$$$$$$) { my $entry = shift; my $state = shift; my $href = shift; my $node = shift; my $title = shift; my $ending = shift; my $has_title = shift; my $command_stack = shift; my $preformatted = shift; $title = '' unless ($has_title); $title .= ':' if ($title ne ''); return "$MENU_SYMBOL$title$node$ending" if ($NODE_NAME_IN_MENU); return "$MENU_SYMBOL$title$entry$ending"; } # formats a menu entry description, ie the text appearing after the node # specification in a menu entry an spanning until there is another # menu entry, an empty line or some text at the very beginning of the line # (we consider that text at the beginning of the line begins a menu comment) # # arguments: # the description text # the state. See menu_entry. # the heading of the element associated with the node. # not usd since in SIMPLE_MENU sub t2h_default_menu_description($$$$) { my $text = shift; my $state = shift; my $element_text = shift; my $command_stack = shift; my $preformatted = shift; return $text; } %htmlxref_entries = ( 'node' => [ 'node', 'section', 'chapter', 'mono' ], 'section' => [ 'section', 'chapter','node', 'mono' ], 'chapter' => [ 'chapter', 'section', 'node', 'mono' ], 'mono' => [ 'mono', 'chapter', 'section', 'node' ], ); # Construct a href to an external source of information. # node is the node with texinfo @-commands # node_id is the node transliterated and transformed as explained in the # texinfo manual # node_xhtml_id is the node transformed such that it is unique and can # be used to make an html cross ref as explained in the texinfo manual # file is the file in '(file)node' # This is used to construct href, so is likely to be ignored oustside of # html. sub t2h_default_external_href($$$) { my $node = shift; my $node_id = shift; my $node_xhtml_id = shift; my $file = shift; $file = '' if (!defined($file)); my $default_target_split = $Texi2HTML::THISDOC{'EXTERNAL_CROSSREF_SPLIT'}; my $target_split; #my $target_mono; #my $href_split; #my $href_mono; if ($file ne '') { if ($NEW_CROSSREF_STYLE) { $file =~ s/\.[^\.]*$//; $file =~ s/^.*\///; my $href; my $document_split = get_conf('SPLIT'); $document_split = 'mono' if (!$document_split); my $split_found; if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file})) { foreach my $split_ordered (@{$htmlxref_entries{$document_split}}) { if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{$split_ordered})) { $split_found = $split_ordered; $href = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{$split_ordered}->{'href'}; last; } } } if (defined($split_found)) { $target_split = 1 unless ($split_found eq 'mono'); } else { # nothing specified for that manual, use default $target_split = $default_target_split; } if ($target_split) { if (defined($href)) { $file = $href; } elsif (defined($EXTERNAL_DIR)) { $file = "$EXTERNAL_DIR/$file"; } elsif (get_conf('SPLIT')) { $file = "../$file"; } $file .= "/"; } else {# target not split if (defined($href)) { $file = $href; } else { if (defined($EXTERNAL_DIR)) { $file = "$EXTERNAL_DIR/$file"; } elsif (get_conf('SPLIT')) { $file = "../$file"; } $file .= "." . $NODE_FILE_EXTENSION; } } } else { $file .= "/"; if (defined($EXTERNAL_DIR)) { $file = $EXTERNAL_DIR . $file; } else { $file = '../' . $file; } } } else { $target_split = $default_target_split; } if ($node eq '') { if ($NEW_CROSSREF_STYLE) { if ($target_split) { if (defined($TOP_NODE_FILE_TARGET)) { return $file . $TOP_NODE_FILE_TARGET . '.' . $NODE_FILE_EXTENSION . '#Top'; } else { return $file . '#Top'; } } else { return $file . '#Top'; } } else { return $file; } } my $target; if ($NEW_CROSSREF_STYLE) { $node = $node_id; $target = $node_xhtml_id; } else { $node = main::remove_texi($node); $node =~ s/[^\w\.\-]/-/g; } my $file_basename = $node; $file_basename = $TOP_NODE_FILE_TARGET if ($node =~ /^top$/i and defined($TOP_NODE_FILE_TARGET)); if ($NEW_CROSSREF_STYLE) { if ($target_split) { return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target; } else { return $file . '#' . $target; } } else { return $file . $file_basename . ".$NODE_FILE_EXTENSION"; } } # format a reference external to the generated manual. This produces a full # reference with introductive words and the reference itself. # # arguments: # type of the reference: xref (reference at the beginning of a sentence), # pxref (reference in a parenthesis), # section in the book. This might be undef. # book name. # manual file name # href linking to the html page containing the referenced node. A typical # use for this href is a href attribute in an <a> element # cross reference name # array of texi arguments of the reference # array of the formatted arguments of the reference # node name sub t2h_default_external_ref($$$$$$$$$) { my $type = shift; my $section = shift; my $book = shift; my $file = shift; #my $file_node = shift; my $href = shift; my $cross_ref = shift; my $args_texi = shift; my $formatted_args = shift; my $node = shift; my $name = $section; $name = $cross_ref if ($name eq ''); $name = $node if ($name eq ''); my $reference = $name; if ($book eq '' and $file ne '') { $name = "($file)$name"; } $reference = &$anchor('', $href, $name) if ($href ne ''); # Yes, this is ugly, yet this helps internationalization if ($type eq 'pxref') { if (($book ne '') and ($href ne '')) { return gdt('see {reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif (($book ne '') and ($reference ne '')) { return gdt('see `{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif ($book ne '') { # should seldom or even never happen return gdt('see @cite{{book}}', { 'book' => $book },{'duplicate'=>1}); } elsif ($href ne '') { return gdt('see {reference}', { 'reference' => $reference },{'duplicate'=>1}); } elsif ($reference ne '') { return gdt('see `{section}\'', { 'section' => $reference },{'duplicate'=>1}); } } if ($type eq 'xref' or $type eq 'inforef') { if (($book ne '') and ($href ne '')) { return gdt('See {reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif (($book ne '') and ($reference ne '')) { return gdt('See `{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif ($book ne '') { # should seldom or even never happen return gdt('See @cite{{book}}', { 'book' => $book },{'duplicate'=>1}); } elsif ($href ne '') { return gdt('See {reference}', { 'reference' => $reference },{'duplicate'=>1}); } elsif ($reference ne '') { return gdt('See `{section}\'', { 'section' => $reference },{'duplicate'=>1}); } } if ($type eq 'ref') { if (($book ne '') and ($href ne '')) { return gdt('{reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif (($book ne '') and ($reference ne '')) { return gdt('`{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1}); } elsif ($book ne '') { # should seldom or even never happen return gdt('@cite{{book}}', { 'book' => $book },{'duplicate'=>1}); } elsif ($href ne '') { return gdt('{reference}', { 'reference' => $reference },{'duplicate'=>1}); } elsif ($reference ne '') { return gdt('`{section}\'', { 'section' => $reference },{'duplicate'=>1}); } } return ''; } # format a reference to a node or a section in the generated manual. This # produces a full reference with introductive words and the reference itself. # # arguments: # type of the reference: xref (reference at the beginning of a sentence), # pxref (reference in a parenthesis), # href linking to the html page containing the node or the section. A typical # use for this href is a href attribute in an <a> element # short name for this reference # name for this reference # boolean true if the reference is a reference to a section # # $SHORT_REF should be used. sub t2h_default_internal_ref($$$$$$$$) { my $type = shift; my $href = shift; my $short_name = shift; my $name = shift; my $is_section = shift; my $args_texi = shift; my $formatted_args = shift; my $element = shift; if (! $SHORT_REF) { $name = &$anchor('', $href, $name); if ($type eq 'pxref') { return gdt('see section {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section); return gdt('see {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } elsif ($type eq 'xref' or $type eq 'inforef') { return gdt('See section {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section); return gdt('See {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } elsif ($type eq 'ref') { return gdt('{reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } } else { $name = &$anchor('', $href, $short_name); if ($type eq 'pxref') { return gdt('see {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } elsif ($type eq 'xref' or $type eq 'inforef') { return gdt('See {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } elsif ($type eq 'ref') { return gdt('{reference_name}', { 'reference_name' => $name },{'duplicate'=>1}); } } return ''; } # text after @item in table, vtable and ftable sub t2h_default_table_item($$$$$$$) { my $text = shift; my $index_label = shift; my $format = shift; my $command = shift; my $style_stack = shift; my $item_cmd = shift; my $formatted_index_entry = shift; return $text . "\n"; } # format text on the line following the @item line (in table, vtable and ftable) sub t2h_default_table_line($$$) { my $text = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); if ($text =~ /\S/) { return $text; } return ''; } #my $cell_nr = -1; # row in multitable sub t2h_default_row($$$$$$$$) { my $text = shift; my $macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); if ($text =~ /\S/) { return $text ."\n"; } return ''; } # cell in multitable sub t2h_default_cell($$$$$$$$) { my $text = shift; my $row_macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); $text =~ s/^\s*//; $text =~ s/\s*$//; return " $text"; } # format an itemize, enumerate or @*table @item line, returning # a texinfo line. sub t2h_default_format_list_item_texi($$$$$) { my $format = shift; my $line = shift; my $prepended = shift; my $command = shift; my $number = shift; my $result_line; my $open_command = 0; $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize'); $prepended = "\@$command\{\}" if (defined($command) and $command ne ''); $prepended = "$number." if (defined($number) and $number ne ''); if (defined($command) and $command ne '' and $format ne 'itemize') { #@*table $open_command = 1; $line =~ s/^\s*//; $line =~ s/\s*$//; if (exists ($style_map{$command})) { $result_line = "\@$command\{$line\}\n"; } elsif (exists ($things_map{$command})) { $result_line = "\@$command\{\} $line\n"; } else { $result_line = "\@$command $line\n"; } } elsif (defined($prepended) and $prepended ne '') { $prepended =~ s/^\s*//; $prepended =~ s/\s*$//; $line =~ s/^\s*//; $result_line = $prepended . ' ' . $line; } return ($result_line, $open_command); } # format an item in a list # # argument: # text of the item # format of the list (itemize or enumerate) # command passed as argument to the format # formatted_command leading command formatted, if it is a thing command sub t2h_default_list_item($$$$$$$$$$$$) { my $text = shift; my $format = shift; my $command = shift; my $formatted_command = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $prepended = shift; my $prepended_formatted = shift; my $only_inter_item_commands = shift; my $before_items = shift; my $item_command = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); if ($text =~ /\S/) { return $text; } return ''; } sub t2h_default_table_list($$$$$$$$$) { my $format_command = shift; my $text = shift; my $command = shift; my $formatted_command = shift; # enumerate my $item_nr = shift; my $enumerate_style = shift; # itemize my $prepended = shift; my $prepended_formatted = shift; # multitable my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; # my $number = shift; return $text; } # an comment sub t2h_default_comment($) { my $text = shift; return ''; } # an xml comment sub xml_default_comment($) { my $text = shift; $text =~ s/--+/-/go; return '<!-- ' . $text . ' -->' . "\n"; } sub t2h_collect_styles($) { my $cmd_stack = shift; my @result = (); foreach my $style (reverse(@$cmd_stack)) { # last unless (defined($command_type{$style}) and $command_type{$style} eq 'style'); push @result, $style if (defined($command_type{$style}) and $command_type{$style} eq 'style'); } return @result; } sub html_default_parse_attribute($) { my $element = shift; return ('', '', '') if (!defined($element)); my ($class, $attributes) = ('', ''); if ($element =~ /^(\w+)(\s+.*)/) { $element = $1; $attributes = $2; if ($attributes =~ s/^\s+class=\"([^\"]+)\"//) { $class = $1; } } return ($element, $class, $attributes); } sub t2h_get_attribute($;$) { my $command = shift; my $map_ref = shift; $map_ref = \%style_map if (!defined($map_ref)); return unless (defined($map_ref->{$command})); my ($element, $class, $attributes) = ('', '', ''); if (defined($map_ref->{$command})) { if (ref($map_ref->{$command}) eq 'HASH') { ($element, $class, $attributes) = t2h_html_parse_attribute ($map_ref->{$command}->{'attribute'}); } elsif ($map_ref->{$command} !~ /^&/) { $element = $map_ref->{$command}; $element =~ s/^\"//; } } return ($element, $class, $attributes); } # a paragraph # arguments: # $text of the paragraph # $align for the alignement # $indent for the indent style (indent or noindent) # The following is usefull if the paragraph is in an itemize. # $paragraph_command is the leading formatting command (like @minus) # $paragraph_command_formatted is the leading formatting command formatted # $paragraph_number is a reference on the number of paragraphs appearing # in the format. The value should be increased if a paragraph is done # $format is the format name (@itemize) sub t2h_default_paragraph($$$$$$$$$$$$) { my $text = shift; my $align = shift; my $indent = shift; my $paragraph_command = shift; my $paragraph_command_formatted = shift; my $paragraph_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; #print STDERR "format: $format\n" if (defined($format)); #print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n"; # $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or # exists($special_list_commands{$format}->{$paragraph_command})); return '' if ($text =~ /^\s*$/); return $text; } # a preformatted region # arguments: # $text of the preformatted region # $pre_style css style # $class identifier for the preformatted region (example, menu-comment) # The following is usefull if the preformatted is in an itemize. # $leading_command is the leading formatting command (like @minus) # $leading_command_formatted is the leading formatting command formatted # $preformatted_number is a reference on the number of preformatteds appearing # in the format. The value should be increased if a preformatted is done sub t2h_default_preformatted($$$$$$$$$$$$) { my $text = shift; my $pre_style = shift; my $class = shift; my $leading_command = shift; my $leading_command_formatted = shift; my $preformatted_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; #print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n"; return '' if ($text eq ''); my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); if ($top_stack eq 'multitable') { $text =~ s/^\s*//; $text =~ s/\s*$//; } # add a new line at the end in case there is none chomp($text); return $text . "\n"; } # $new_element is set if the element is associated with a different # reference element than the preceding element. This is where we # do the navigation. For example it could be a @node before a @section. # # The heading function is always called, though -- in the default case # nodes don't lead to an outputted title. sub t2h_default_element_heading($$$$$$$$$$$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; my $one_section = shift; my $element_heading = shift; my $first_in_page = shift; my $is_top = shift; my $previous_is_top = shift; my $command_line = shift; my $element_id = shift; my $new_element = shift; #print STDERR ":::::::: $element $command i_p $in_preformatted o_s $one_section e_h $element_heading f_p $first_in_page i_t $is_top p_i_t $previous_is_top id $element_id new $new_element\n"; # my $result = ''; my $result = &$element_label($element_id, $element, $command, $command_line); # in default case, print_head_navigation and print_navigation are no-ops. # and $print_element_header is undef, so the following nothing. if ($new_element and !$one_section) { main::msg_debug ("For $element->{'texi'}, element_ref not defined", $element->{'line_nr'}) if (!defined($element->{'element_ref'})); if (!defined($element->{'element_ref'}->{'top'})) { if (defined($print_element_header)) { # FIXME backward compatibility, print_element_header is obsoleted in nov 2009 $result .= &$print_element_header($first_in_page, $previous_is_top); } else { if (($first_in_page or $previous_is_top) and get_conf('headers')) { $result .= &$print_head_navigation(undef, \@SECTION_BUTTONS, $first_in_page, $previous_is_top, $element); } else { # got to do this here, as it isn't done otherwise sinc # print_head_navigation is not called $result .= &$print_navigation(\@SECTION_BUTTONS) if (get_conf('headers') or get_conf('SPLIT') eq 'node'); } } } else { # this is here because we want to always print the head navigation for top # and use TOP_BUTTONS $result .= &$print_head_navigation(undef, \@TOP_BUTTONS, $first_in_page, $previous_is_top, $element) if (get_conf('SPLIT') or get_conf('headers')); } } return $result. &$heading($element, $command, $texi_line, $line, $in_preformatted, $one_section, $element_heading); } # This function formats a heading for an element # # argument: # an element. It is a hash reference for a node or a sectioning command. # it may be the wrong one in case of headings. # The interesting keys are: # 'text': the heading text # 'text_nonumber': the heading text without section number # 'node': true if it is a node # 'level': level of the element. 0 for @top, 1 for chapter, heading, # appendix..., 2 for section and so on... # 'tag_level': the sectioning element name, raisesections and lowersections # taken into account sub t2h_default_heading($$$$$;$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; my $one_section = shift; my $element_heading = shift; my $level = $element->{'level'}; if ($element->{'node'}) { if ($element->{'text'} =~ /^top$/i) { $level = 0; } else { $level = 3; } return '' if (!$element->{'this'} or $element->{'with_section'}) } else { $command = $element->{'tag_level'}; } my $text = $element->{'text'}; if ($TOC_LINKS and $command !~ /heading/ and defined($element->{'tocid'})) { $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text); } my $result; if ($in_preformatted) { $result = &$heading_text_preformatted("\@$command", $text, $level); } else { $result = &$heading_text("\@$command", $text, $level); } #$result .= "\n"; return $result; } sub t2h_default_heading_no_texi($$$) { my $element = shift; my $command = shift; my $line = shift; return main::remove_texi($line) . "\n"; } # formatting of raw regions # if L2H is true another mechanism is used for tex sub t2h_default_raw($$;$) { my $style = shift; my $text = shift; my $line_nr = shift; my $expanded = 1 if (grep {$style eq $_} @EXPAND); if ($style eq 'verbatim' or $style eq 'verbatiminclude' or ($style eq 'tex' and $expanded)) { return $text; } elsif ($expanded) { main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr); return $text; } else { return ''; } } # raw environment when removing texi (in comments) sub t2h_default_raw_no_texi($$) { my $style = shift; my $text = shift; if ($style eq 'verbatim' or $style eq 'verbatiminclude' or grep {$style eq $_} @EXPAND) { return $text; } return ''; } # This function formats a footnote reference and the footnote text associated # with a given footnote. # The footnote reference is the text appearing in the main document pointing # to the footnote text. # # arguments: # absolute number of the footnote (in the document) # relative number of the footnote (in the page) # identifier for the footnote # identifier for the footnote reference in the main document # main document file # footnote text file # array with the footnote text lines # the state. See menu entry. # # returns: # reference on an array containing the footnote text lines which should # have been updated # the text for the reference pointing on the footnote text sub t2h_default_foot_line_and_ref($$$$$$$$$) { my $number_in_doc = shift; my $number_in_page = shift; my $footnote_id = shift; my $place_id = shift; my $document_file = shift; my $footnote_file = shift; my $lines = shift; my $document_state = shift; $number_in_doc = $NO_NUMBER_FOOTNOTE_SYMBOL if (!$NUMBER_FOOTNOTES); if ($document_file eq $footnote_file) { $document_file = $footnote_file = ''; } unshift (@$lines, "($number_in_doc)\n"); push @$lines, "\n"; return ($lines, "($number_in_doc)"); } # formats a group of footnotes. # # argument: # array reference on the footnotes texts lines # # returns an array reference on the group of footnotes lines sub t2h_default_foot_section($) { my $lines = shift; my $header = &$heading_text('footnotes', gdt('Footnotes'), 3); unshift (@$lines, "$header\n"); return $lines; } sub t2h_default_image_files($$$$) { my $base = shift; my $extension = shift; my $texi_base = shift; my $texi_extension = shift; my @files = (); return @files if (!defined($base) or ($base eq '')); if (defined($extension) and ($extension ne '')) { push @files,["$base.$extension", "$texi_base.$texi_extension"]; } foreach my $ext (@IMAGE_EXTENSIONS) { push @files,["$base.$ext", "$texi_base.$ext"]; } return @files; } # format an image # # arguments: # image file name with path # image basename # a boolean true if we are in a preformatted format # image file name without path # alt text # width # height # raw alt # extension # path to working dir # path to file relative from working dir sub t2h_default_image($$$$$$$$$$$$$$$$$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; my $base_simple_format = shift; my $extension_simple_format = shift; my $file_name_simple_format = shift; my $line_nr = shift; if (!defined($file_path) or $file_path eq '') { if (defined($extension) and $extension ne '') { $file = "$base.$extension"; } else { $file = "$base.txt"; } } elsif (! $COMPLETE_IMAGE_PATHS) { $file = $file_name; } my $alt_txt = ''; $alt_txt = ": $alt" if (defined($alt) and $alt =~ /\S/); return "[ $file$alt_txt ]"; # it is possible that $file_name is more correct as it allows the user # to chose the relative path. } # address put in footer describing when was generated and who did the manual # not used anymore sub t2h_default_address($) { my $date = shift; $date = '' if (!defined($date)); if ($date ne '') { return gdt('on @emph{{date}}', { 'date' => $date }); } return ''; } # format a target in the main document for an index entry. # # arguments: # target identifier # boolean true if in preformatted format sub t2h_default_index_entry_label($$$$$$$$$) { my $identifier = shift; my $preformatted = shift; my $entry = shift; my $index_name = shift; my $index_command = shift; my $texi_entry = shift; my $formatted_entry = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; return '' if (!defined($identifier) or ($identifier !~ /\S/)); my $label = &$anchor($identifier); return $label; } sub t2h_default_index_entry_command($$$$$$) { my $command = shift; my $index_name = shift; my $label = shift; my $entry_texi = shift; my $entry_formatted = shift; my $index_entry_ref = shift; return $label; } # process definition commands line @deffn for example sub t2h_default_def_line($$$$$$$$$$$$$$$$) { my $category_prepared = shift; my $name = shift; my $type = shift; my $arguments = shift; my $index_label = shift; my $arguments_array = shift; my $arguments_type_array = shift; my $unformatted_arguments_array = shift; my $command = shift; my $class_name = shift; my $category = shift; my $class = shift; my $style = shift; my $original_command = shift; $name = '' if (!defined($name) or ($name =~ /^\s*$/)); $type = '' if (!defined($type) or $type =~ /^\s*$/); $arguments = '' if (!defined($arguments) or $arguments =~ /^\s*$/); my $type_name = ''; $type_name .= "$type " if ($type ne ''); $type_name .= $name if ($name ne ''); my $result = " -- $category_prepared: ${type_name}$arguments"; $result =~ s/\s*$//; $result .= "\n"; } # process definition commands line @deffn for example while removing texi # commands sub t2h_default_def_line_no_texi($$$$$) { my $category = shift; my $name = shift; my $type = shift; my $arguments = shift; $name = '' if (!defined($name) or ($name =~ /^\s*$/)); $type = '' if (!defined($type) or $type =~ /^\s*$/); if (!defined($arguments) or $arguments =~ /^\s*$/) { $arguments = ''; } my $type_name = ''; $type_name = " $type" if ($type ne ''); $type_name .= ' ' . $name if ($name ne ''); $type_name .= $arguments; if (! $DEF_TABLE) { return $category . ':' . $type_name . "\n"; } else { return $type_name . " " . $category . "\n"; } } # a cartouche sub t2h_default_cartouche($$) { my $text = shift; if ($text =~ /\S/) { return $text; } return ''; } my $IDXFILE; # key: # origin_href: # entry: # texi entry: # element_href: # element_text: sub t2h_default_index_summary_file_entry ($$$$$$$$$) { my $index_name = shift; my $key = shift; my $origin_href = shift; my $entry = shift; my $texi_entry = shift; my $element_href = shift; my $element_text = shift; my $is_printed = shift; my $manual_name = shift; $element_text = 'UNDEF' if (!defined($element_text)); print $IDXFILE "key: $key\n origin_href: $origin_href\n entry: $entry\n" . " texi_entry: $texi_entry\n" . " element_href: $element_href\n element_text: $element_text\n"; } sub t2h_default_index_summary_file_begin($$$) { my $name = shift; my $is_printed = shift; my $manual_name = shift; $IDXFILE = main::open_out("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx"); #open(IDXFILE, ">$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx") # || die "Can't open >$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx for writing: $!\n"; } sub t2h_default_index_summary_file_end($$$) { my $name = shift; my $is_printed = shift; my $manual_name = shift; close ($IDXFILE); } sub t2h_default_sp($$) { my $number = shift; my $preformatted = shift; return "\n" x $number; } sub t2h_default_acronym_like($$$$$$) { my $command = shift; my $acronym_texi = shift; my $acronym_text = shift; my $with_explanation = shift; my $explanation_lines = shift; my $explanation_text = shift; my $explanation_simply_formatted = shift; if ($with_explanation) { #return "$acronym_text ($explanation_text)"; return gdt('{acronym_like} ({explanation})', {'acronym_like' => $acronym_text, 'explanation' => $explanation_text},{'duplicate'=>1}); } else { return "$acronym_text"; } } sub t2h_default_quotation_prepend_text($$) { my $command = shift; my $text = shift; return undef if (!defined($text) or $text =~ /^$/); # If there is a @ protecting the end of line the result is, # after the chomp: # @b{some text @:} # It is likely not to be what was intended, but it is certainly right. # this is tested in formatting/quotation.texi chomp($text); return gdt('@b{{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1}); } sub t2h_default_quotation($$$$$) { my $command = shift; my $text = shift; my $argument_text = shift; my $argument_text_texi = shift; my $authors = shift; my $class_text = ''; # this allows to add an end of line if there was none, which can happen # if there is an argument to @quotation, but an empty quotation, like # @quotation something # @end quotation chomp($text); $text .= "\n"; return $text; } # format the text within a paragraph style format, # # argument: # format name # text within the format sub t2h_default_paragraph_style_command($$) { my $format = shift; my $text = shift; return $text; } # format a whole index # # argument: # index text # index name sub t2h_default_print_index($$) { my $text = shift; my $name = shift; return '' if (!defined($text)); return "* Index:\n" . $text; } # format a letter entry in an index page. The letter entry contains # the index entries for the words beginning with that letter. It is # a target for links pointing from the summary of the index. # # arguments: # the letter # identifier for the letter entry. This should be used to make the target # identifier # text of the index entries sub t2h_default_index_letter($$$) { my $letter = shift; my $id = shift; my $text = shift; return $text; } # format an index entry (in a letter entry). # # arguments: # href to the main text, linking to the place where the index entry appears # entry text # href to the main text, linking to the section or node where the index # entry appears # section or node heading sub t2h_default_index_entry($$$$$$$$$$) { my $text_href = shift; my $entry = shift; my $element_href = shift; my $element_text = shift; my $entry_file = shift; my $current_element_file = shift; my $entry_target = shift; my $entry_element_target = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; return '' if ($in_region_not_in_output); #!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'})); $entry = main::substitute_line($index_entry_ref->{'texi'}, "index entry in \@printindex"); return '' if ($entry =~ /^\s*$/); my $real_element_text; my $element = $index_entry_ref->{'real_element'}; # in case $element->{'text'} is not defined, it certainly means that we # are n a special elemet, most likely the virtual element appearing # before anything else if (defined($element->{'text'})) { my $element_set = 0; if ($NODE_NAME_IN_INDEX) { if ($element->{'node'}) { $element_set = 1; } elsif ($element->{'with_node'}) { $element = $element->{'with_node'}; $element_set = 1; } } elsif (defined($NODE_NAME_IN_INDEX)) { if (!$element->{'node'}) { $element_set = 1; } elsif ($element->{'with_section'}) { $element = $element->{'with_section'}; $element_set = 1; } } $element = $element->{'element_ref'} if ($element->{'element_ref'} and !$element_set); $real_element_text = $element->{'text'}; } else { $real_element_text = gdt('(outside of any element)'); } return "* $entry: ".$real_element_text . '.'."\n"; } sub t2h_default_copying_comment($$$$) { my $copying_lines = shift; my $copying_text = shift; my $copying_no_texi = shift; my $copying_simple_text = shift; return '' if ($copying_no_texi eq ''); my $text = &$comment($copying_no_texi); return $text; } # return value is currently ignored sub t2h_default_documentdescription($$$$) { my $decription_lines = shift; my $description_text = shift; my $description_no_texi = shift; my $description_simple_text = shift; if (defined($DOCUMENT_DESCRIPTION)) { $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = $DOCUMENT_DESCRIPTION; return $DOCUMENT_DESCRIPTION; } #return '' if ($description_no_texi eq ''); #my @documentdescription = split (/\n/, $description_no_texi); if ($description_simple_text eq '') { $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = undef; return undef; } my @documentdescription = split (/\n/, $description_simple_text); my $document_description = shift @documentdescription; chomp $document_description; foreach my $line (@documentdescription) { chomp $line; $document_description .= ' ' . $line; } $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'} = $document_description; return $document_description; } # format an index summary. This is a list of letters linking to the letter # entries. # # arguments: # array reference containing the formatted alphabetical letters # array reference containing the formatted non lphabetical letters sub t2h_default_index_summary($$) { my $alpha = shift; my $nonalpha = shift; my $join = ''; my $nonalpha_text = ''; my $alpha_text = ''; return ''; } # return the heading with number texinfo text # also called for nodes. sub t2h_default_heading_texi($$$) { my $tag = shift; my $texi = shift; my $number = shift; #$texi = main::trim_around_spaces($texi); return "$number $texi" if ($NUMBER_SECTIONS and defined($number) and ($number !~ /^\s*$/)) ; return $texi; } # return the heading texinfo text for split index sections sub t2h_default_index_element_heading_texi($$$) { # FIXME i18n my $heading_texi = shift; my $tag = shift; my $texi = shift; my $number = shift; my $first_letter = shift; my $last_letter = shift; return "$heading_texi: $first_letter -- $last_letter" if ($last_letter ne $first_letter); return "$heading_texi: $first_letter"; } sub t2h_default_element_label($$$$) { my $id = shift; my $element = shift; my $command = shift; my $line = shift; return &$anchor($id); } sub t2h_default_misc_element_label($$) { my $id = shift; my $misc_page_name = shift; return &$anchor($id); } sub t2h_default_anchor_label($$$$) { my $id = shift; my $anchor_text = shift; my $anchor_reference = shift; my $in_special_region = shift; return &$anchor($id); } sub t2h_default_colon_command($) { my $punctuation_character = shift; return $colon_command_punctuation_characters{$punctuation_character} if defined($colon_command_punctuation_characters{$punctuation_character}); return $punctuation_character; } # called each time a @tab or an @itemx is encountered. # To be noticed that there is another function better suited for # formatting of an @item line: $format_list_item_texi sub t2h_default_tab_item_texi($$$$$$) { my $command = shift; my $commands_stack = shift; my $stack = shift; my $state = shift; my $line = shift; my $line_nr = shift; return undef; } sub xml_default_line_command($$$$) { my $command = shift; my $arg_text = shift; my $arg_texi = shift; my $state = shift; my $style = $line_command_map{$command}; return '' if ($arg_text eq '' and !defined($style) or $style eq ''); if ($style) { my $attribute_text = ''; if ($style =~ /^(\w+)(\s+.*)/) { $style = $1; $attribute_text = $2; } $arg_text = "<${style}$attribute_text>$arg_text</$style>"; } $arg_text .= "\n"; return $arg_text; } sub t2h_default_line_command($$$$) { my $command = shift; my $arg_text = shift; my $arg_texi = shift; my $state = shift; return $arg_text; } # info is special, since it doesn't use the basename but directly the # setfilename output, contrary to all the other formats sub t2h_default_element_file_name($$$) { my $element = shift; my $type = shift; my $prefix = shift; my $outname; return unless ($USE_SETFILENAME_EXTENSION and $PREFIX eq ''); $outname = $OUT if (defined($OUT) and $OUT ne '' and $OUT !~ /\/$/ and $Texi2HTML::THISDOC{'input_file_number'} == 0); if ($type eq 'doc' or !get_conf('SPLIT')) { if (defined($Texi2HTML::THISDOC{'setfilename'}) and !defined($outname)) { $Texi2HTML::THISDOC{'extension'} = ''; return $Texi2HTML::THISDOC{'setfilename'}; } } return undef; } sub t2h_default_misc_command_line($$$$$) { my $macro = shift; my $line = shift; my $args = shift; my $stack = shift; my $state = shift; my $result; return ($macro, $line, $result); } sub t2h_default_internal_links($$$) { my $fh = shift; my $elements_list = shift; my $indices = shift; foreach my $element (@$elements_list) { my $text = $element->{'no_texi'}; #$text =~ s/^([\w.]+)\. /$1 /; #$text = "Annexe ".$text if ($element->{'tag'} =~ /appendix/); print $fh "$element->{'file'}#$element->{'id'}\ttoc\t$text\n"; } foreach my $index_name (sort(keys(%$indices))) { my $entries = $indices->{$index_name}; foreach my $letter_entries (@$entries) { foreach my $entry (@{$letter_entries->{'entries'}}) { #print STDERR "($index_name) key $key, t $entry->{'texi'}: $entry->{'file'}#$entry->{'target'}\n"; print $fh "$entry->{'file'}#$entry->{'target'}\t$index_name\t$entry->{'key'}\n" if ($entry->{'key'} =~ /\S/); } } } } 1; require "$T2H_HOME/texi2html.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/texi2html.init" && -r "$T2H_HOME/texi2html.init"); # @INIT_HTML@ # -*-perl-*- # vim: set filetype=perl: ###################################################################### # File: html.init # html output formatting # # A copy of this file is pasted into the beginning of texi2html by # running './configure'. # # $Id: html.init,v 1.53 2010/06/26 09:54:23 pertusus Exp $ use strict; use vars qw(@html_default_multitable_stack); # used in mediawiki.init #my @html_default_multitable_stack; # tracks menu entry index my $html_menu_entry_index; # the simple_formatted document title my $html_default_title; # initialise the html output sub html_default_load(;$) { my $from_command_line = shift; t2h_default_set_variables_xml(); ############################################################### # defaults $HEADERS = 1; @T2H_FORMAT_EXPAND = ('html'); # The value is the 'SystemLiteral' which identifies the canonical DTD # for the document. # Definition: The SystemLiteral is called the entity's system # identifier. It is a URI, which may be used to retrieve the entity. # See http://www.xml.com/axml/target.html#NT-ExternalID $DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'; # When frames are used, this SystemLiteral identifies the DTD used for # the file containing the frame description. $FRAMESET_DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'; # if this value is true, ISO8859 characters are used for special symbols # (like copyright, etc). $USE_ISO = 1; # if the value is true the Texinfo menus are shown. $SHOW_MENU = 1; $SHOW_TITLE = 1; # default is to use nodes only as elements. $USE_SECTIONS = undef; $TOP_FILE = 'index.html'; # file name used for Top node when NODE_FILES is true $TOP_NODE_FILE = 'index'; ############################################################################## # # The following can only be set in the init file # ############################################################################## $INLINE_INSERTCOPYING = 0; # if this variable is true, numeric entities are used when there is no # corresponding textual entity. $USE_NUMERIC_ENTITY = 1; # if true, use the original command if the result is an entity $ENABLE_ENCODING_USE_ENTITY = 1; # used as identation for block enclosing command @example, etc # If not empty, must be enclosed in <td></td> $EXAMPLE_INDENT_CELL = '<td> </td>'; # same as above, only for @small $SMALL_EXAMPLE_INDENT_CELL = '<td> </td>'; # font size for @small $SMALL_FONT_SIZE = '-1'; # horizontal rules # Not used $SMALL_RULE = '<hr size="1">'; $MIDDLE_RULE = '<hr size="2">'; # used almost everywhere $DEFAULT_RULE = '<hr>'; # used for top element and before misc elements $BIG_RULE = '<hr size="6">'; # symbol put at the beginning of nodes entry in menu (and optionnaly of # unnumbered in menus, see next variable) $MENU_SYMBOL = '•'; #$MENU_SYMBOL = '*'; $SIMPLE_MENU = 0; # extension for nodes files when NODE_FILES is true $NODE_FILE_EXTENSION = 'html'; # extension $EXTENSION = 'html'; # default is to split the html output $SPLIT = 'node'; # this resets all the variables to the texi2html specific values if # called as texi2html t2h_default_set_variables_texi2html() if ($COMMAND_NAME eq 'texi2html'); # this controls the pre style for menus $MENU_PRE_STYLE = 'font-family: serif'; # on bug-texinfo is has been said the the style is not code_style # for menus (except for the node name). # this controls the menu preformatted format # FIXME this is not dynamic, so change in MENU_PRE_STYLE is not taken # into account. # This is used if the menu appears within a preformatted format (which # is certainly an invalid construct), and SIMPLE_MENU is not set. $MENU_PRE_COMPLEX_FORMAT = { 'pre_style' => $MENU_PRE_STYLE, 'class' => 'menu-preformatted', # 'style' => 'code' }; # This controls the ul style for toc $NO_BULLET_LIST_STYLE = 'list-style: none'; $NO_BULLET_LIST_CLASS = 'no-bullet'; $NO_BULLET_LIST_ATTRIBUTE = ' class="'.$NO_BULLET_LIST_CLASS.'"'; # These lines are inserted before and after the shortcontents $BEFORE_OVERVIEW = "<div class=\"shortcontents\">\n"; $AFTER_OVERVIEW = "</div>\n"; # These lines are inserted before and after the contents $BEFORE_TOC_LINES = "<div class=\"contents\">\n"; $AFTER_TOC_LINES = "</div>\n"; # text inserted after <body ...> $AFTER_BODY_OPEN = ''; # text inserted before </body>, this will be automatically inside <p></p> $PRE_BODY_CLOSE = ''; # this is added inside <head></head> after <title> and some <meta name> # stuff, it can be used for eg. <style>, <script>, <meta> etc. tags. $EXTRA_HEAD = ''; # Specifies the minimum page length required before a navigation panel # is placed at the bottom of a page $WORDS_IN_PAGE = 300; # html version for latex2html $L2H_HTML_VERSION = "4.0"; # this is not set dynamically if (!$HEADER_IN_TABLE) { @SECTION_BUTTONS = ([ 'NodeNext', \&html_default_node_direction ], [ 'NodePrev', \&html_default_node_direction ], [ 'NodeUp', \&html_default_node_direction ], ' ', 'Contents', 'Index'); @CHAPTER_BUTTONS = @SECTION_FOOTER_BUTTONS = @NODE_FOOTER_BUTTONS = @MISC_BUTTONS = @TOP_BUTTONS = @SECTION_BUTTONS; $BIG_RULE = $DEFAULT_RULE; } $ICONS = 0; %BUTTONS_ACCESSKEY = ( 'Top', '', 'Contents', '', 'Overview', '', 'Index', '', 'This', '', 'Back', 'p', 'FastBack', '', 'Prev', 'p', 'Up', 'u', 'Next', 'n', 'NodeUp', 'u', 'NodeNext', 'n', 'NodePrev', 'p', 'Following', '', 'Forward', 'n', 'FastForward', '', 'About' , '', 'First', '', 'Last', '', 'NextFile', '', 'PrevFile', '', ); # see http://www.w3.org/TR/REC-html40/types.html#type-links %BUTTONS_REL = ( 'Top', 'start', 'Contents', 'contents', 'Overview', '', 'Index', 'index', 'This', '', 'Back', 'previous', 'FastBack', '', 'Prev', 'previous', 'Up', 'up', 'Next', 'next', 'NodeUp', 'up', 'NodeNext', 'next', 'NodePrev', 'previous', 'Following', '', 'Forward', 'next', 'FastForward', '', 'About' , 'help', 'First', '', 'Last', '', 'NextFile', 'next', 'PrevFile', 'previous', ); # PRE_ABOUT can be a function reference or a scalar. # Note that if it is a scalar, T2H_InitGlobals has not been called, # and all global variables like $ADDRESS are not available. $PRE_ABOUT = sub { return ' ' . &$program_string() . "\n"; }; # If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>. $AFTER_ABOUT = ''; %BUTTONS_EXAMPLE = ( 'Top', '   ', 'Contents', '   ', 'Overview', '   ', 'Index', '   ', 'This', '1.2.3', 'Back', '1.2.2', 'FastBack', '1', 'Prev', '1.2.2', 'Up', '1.2', 'Next', '1.2.4', 'NodeUp', '1.2', 'NodeNext', '1.2.4', 'NodePrev', '1.2.2', 'Following', '1.2.4', 'Forward', '1.2.4', 'FastForward', '2', 'About', '   ', 'First', '1.', 'Last', '1.2.4', 'NextFile', '   ', 'PrevFile', '   ', ); @IMAGE_EXTENSIONS = ('png','jpg','jpeg','gif'); #, 'txt'); ####################################################################### # # Values guessed if not set here. The value used is in # $Texi2HTML::THISDOC{'VARNAME'} # ####################################################################### $BODYTEXT = undef; #$init_out = \&html_default_init_out; $translate_names = \&html_default_translate_names; t2h_default_push_handler(\&html_default_initialize, \@command_handler_init); # This must be done after language has been set t2h_default_push_handler(\&html_default_bodytext, \@command_handler_process); # This must be done after the fulltitle has been set t2h_default_push_handler(\&html_default_do_title, \@command_handler_output); ######################################################################## # Control of Page layout: # You can make changes of the Page layout at two levels: # 1.) For small changes, it is often enough to change the value of # some global string/hash/array variables # 2.) For larger changes, reimplement one of the HTML_DEFAULT_<fnc>* routines, # give them another name, and assign them to the respective # $<fnc> variable. # As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, Texi2HTML::SIMPLE_TEXT hold # href, html-name, node-name, name after removal of texi commands of # This -- current section (resp. html page) # Top -- top element # Contents -- Table of contents element # Overview -- Short table of contents element # Index -- Index page element # About -- page which explain "navigation buttons" element # First -- first node element # Last -- last node element # # Whether or not the following hash values are set, depends on the context # (all values are w.r.t. 'This' section) # Next -- next element of texinfo # Prev -- previous element of texinfo # NodeUp -- up node of texinfo # Following -- following node in node reading order, taking menu into account # Forward -- next node in reading order # Back -- previous node in reading order # Up -- parent given by sectioning commands # FastForward -- if leave node, up and next, else next node # FastBackward-- if leave node, up and prev, else prev node # # Furthermore, the following global variabels are set: # $Texi2HTML::THISDOC{title} -- title as set by @title... # $Texi2HTML::THISDOC{title_no_texi} -- title without texi (without html elements) # $Texi2HTML::THISDOC{title_texi} -- title with texinfo @-commands # $Texi2HTML::THISDOC{fulltitle} -- full title as set by @title... # $Texi2HTML::THISDOC{subtitle} -- subtitle as set by @subtitle # $Texi2HTML::THISDOC{author} -- author as set by @author # $Texi2HTML::THISDOC{copying_comment} -- text of @copying and @end copying in comment # # $Texi2HTML::THISDOC{program} -- name and version of texi2html # $Texi2HTML::THISDOC{program_homepage} -- homepage for texi2html # $Texi2HTML::THISDOC{program_authors} -- authors of texi2html # $Texi2HTML::THISDOC{today} -- date formatted with pretty_date # $Texi2HTML::THISDOC{toc_file} -- table of contents file # $Texi2HTML::THISDOC{file_base_name} -- base name of the texinfo manual file # $Texi2HTML::THISDOC{input_file_name} -- name of the texinfo manual file # $Texi2HTML::THISDOC{destination_directory} # -- directory for the resulting files # $Texi2HTML::THISDOC{user} -- user running the script # $Texi2HTML::THISDOC{css_import_lines} -- ref on @import lines in css files # $Texi2HTML::THISDOC{css_rule_lines} -- ref on css rules lines # other $Texi2HTML::THISDOC keys corresponds with texinfo commands, the value # being the command arg, for the following commands: # kbdinputstyle, paragraphindent, setchapternewpage, headings, footnotestyle, # exampleindent, firstparagraphindent, everyheading, everyfooting, # evenheading, evenfooting, oddheading, oddfooting # # and pointer to arrays of lines which need to be printed by main::print_lines # $Texi2HTML::THIS_SECTION -- lines of 'This' section # $Texi2HTML::OVERVIEW -- lines of short table of contents # $Texi2HTML::TOC_LINES -- lines of table of contents # $Texi2HTML::TITLEPAGE -- lines of title page # # $Texi2HTML::THIS_ELEMENT holds the element reference. # # There are the following subs which control the layout: # $print_section = \&HTML_DEFAULT_print_section; $end_section = \&HTML_DEFAULT_end_section; $one_section = \&HTML_DEFAULT_one_section; $print_Top_footer = \&HTML_DEFAULT_print_Top_footer; $print_Top = \&HTML_DEFAULT_print_Top; # changed in info format, but irrelevant for non-split formats $print_Footnotes = \&T2H_DEFAULT_print_Footnotes; $print_misc_header = \&HTML_DEFAULT_print_misc_header; $print_misc_footer = \&HTML_DEFAULT_print_misc_footer; $print_section_footer = \&HTML_DEFAULT_print_section_footer; $print_chapter_header = \&HTML_DEFAULT_print_chapter_header; $print_section_header = \&HTML_DEFAULT_print_section_header; $print_chapter_footer = \&HTML_DEFAULT_print_chapter_footer; $print_page_head = \&HTML_DEFAULT_print_page_head; $print_page_foot = \&HTML_DEFAULT_print_page_foot; $print_head_navigation = \&HTML_DEFAULT_print_head_navigation; $print_foot_navigation = \&HTML_DEFAULT_print_foot_navigation; $button_icon_img = \&HTML_DEFAULT_button_icon_img; $button_formatting = \&HTML_DEFAULT_button_formatting; $print_navigation = \&HTML_DEFAULT_print_navigation; $about_body = \&HTML_DEFAULT_about_body; $print_frame = \&HTML_DEFAULT_print_frame; $print_toc_frame = \&HTML_DEFAULT_print_toc_frame; $contents = \&HTML_DEFAULT_contents; $shortcontents = \&HTML_DEFAULT_shortcontents; $print_redirection_page = \&HTML_DEFAULT_print_redirection_page; ######################################################################## # Control of formatting: # 1.) For some changes, it is often enough to change the value of # some global map. It might necessitate building a little # function along with the change in hash, if the change is the use # of another function (in style_map). # 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines, # give them another name, and assign them to the respective # $<fnc> variable (below). # # texinfo "simple things" (@foo) to HTML ones # %simple_map = %default_simple_map; $simple_map{'*'} = '<br>'; # HTML+ $simple_map{' '} = ' '; $simple_map{"\t"} = ' '; $simple_map{"\n"} = ' '; # "­" or "­" could also be possible for @-, but it seems # that some browser will consider this as an always visible hyphen mark # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html) #$simple_map{'-'} = ''; # hyphenation hint # this map is used in preformatted text %simple_map_pre = %simple_map; $simple_map_pre{'*'} = "\n"; # use entities in the default case #$things_map{'dots'} = '<small class="dots">...</small>'; $things_map{'enddots'} = '<small class="enddots">...</small>'; %style_map = (); %style_map_pre = (); t2h_default_copy_style_map (\%default_style_map, \%style_map); t2h_default_copy_style_map (\%default_style_map_pre, \%style_map_pre); # default is {'args' => ['normal'], 'attribute' => ''}, my %style_map_html = ( 'b', {'inline_attribute' => 'b'}, 'cite', {'inline_attribute' => 'cite'}, 'code', {'inline_attribute' => 'code'}, 'command', {'inline_attribute' => 'code'}, 'dfn', {'inline_attribute' => 'em'}, 'email', {'function' => \&html_default_email}, 'emph', {'inline_attribute' => 'em'}, 'env', {'inline_attribute' => 'code'}, 'file', {'inline_attribute' => 'tt', 'quote' => '"'}, 'headitemfont', {'inline_attribute' => 'b'}, # not really that, in fact it is # in <th> rather than <td> 'i', {'inline_attribute' => 'i'}, 'slanted', {'inline_attribute' => 'i'}, 'sansserif', {'inline_attribute' => 'span class="sansserif"'}, 'kbd', {'inline_attribute' => 'kbd'}, 'key', {'begin' => '<', 'end' => '>'}, 'math', {'function' => \&html_default_math}, 'option', {'inline_attribute' => 'samp', 'quote' => '"'}, 'r', {'inline_attribute' => 'span class="roman"'}, 'samp', {'inline_attribute' => 'samp', 'quote' => '"'}, 'sc', {'inline_attribute' => 'small'}, 'strong', {'inline_attribute' => 'strong'}, 't', {'inline_attribute' => 'tt'}, 'uref', {'function' => \&html_default_uref}, 'url', {'function' => \&html_default_uref}, 'indicateurl', {'begin' => '<<code>', 'end' => '</code>>'}, 'var', {'inline_attribute' => 'var'}, 'verb', {'inline_attribute' => 'tt'}, ); foreach my $style_command (keys(%style_map_html)) { foreach my $key (keys(%{$style_map_html{$style_command}})) { $style_map_pre{$style_command}->{$key} = $style_map_html{$style_command}->{$key}; $style_map{$style_command}->{$key} = $style_map_html{$style_command}->{$key}; } } %line_command_map = ( 'title' => 'h1', 'subtitle' => 'h3 align="right"', 'author' => 'strong', ); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { $style_map{$accent_command} = { 'function' => \&xml_default_accent }; $style_map_pre{$accent_command} = { 'function' => \&xml_default_accent }; } $style_map_pre{'sc'} = {}; $style_map_pre{'titlefont'} = {}; $style_map_pre{'click'}->{'function'} = \&t2h_default_click_pre; # uncomment to use the old interface #%style_map = %old_style_map; #%style_map_pre = %old_style_map_pre; %simple_format_simple_map_texi = %simple_map_pre; %format_map = ( # 'quotation' => 'blockquote', # lists # 'itemize' => 'ul', 'enumerate' => 'ol', # 'multitable' => 'table', 'table' => 'dl compact="compact"', 'vtable' => 'dl compact="compact"', 'ftable' => 'dl compact="compact"', 'group' => '', 'raggedright' => '', # 'detailmenu' => '', ); #%special_list_commands = ( # 'table' => {}, # 'vtable' => {}, # 'ftable' => {}, # 'itemize' => { 'bullet' => '' } # ); $special_list_commands{'itemize'}->{ 'bullet'} = ''; # # texinfo format to align attribute of paragraphs # %paragraph_style = ( 'center' => 'center', 'flushleft' => 'left', 'flushright' => 'right', ); # preformatted formats formatting if ($COMPLEX_FORMAT_IN_TABLE) { foreach my $indented_format ('example', 'display', 'lisp') { $complex_format_map{"small$indented_format"}->{'begin'} = "<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"; $complex_format_map{$indented_format}->{'begin'} = "<table><tr>$EXAMPLE_INDENT_CELL<td>"; $complex_format_map{$indented_format}->{'end'} = "</td></tr></table>\n"; $complex_format_map{"small$indented_format"}->{'end'} = "</td></tr></table>\n"; } foreach my $non_indented_formats ('format', 'smallformat') { $complex_format_map{$non_indented_formats}->{'begin'} = ''; $complex_format_map{$non_indented_formats}->{'end'} = "\n"; } } else { foreach my $format ('example', 'display', 'lisp', 'format') { $complex_format_map{$format}->{'begin'} = html_default_attribute_class('div', $format).">\n"; $complex_format_map{"small$format"}->{'begin'} = html_default_attribute_class('div', "small$format").">\n"; $complex_format_map{$format}->{'end'} = '</div>'."\n"; $complex_format_map{"small$format"}->{'end'} = '</div>'."\n"; } } foreach my $format ('menu', 'detailmenu', 'direntry') { $complex_format_map{$format} = { 'begin' => '' , 'end' => '', 'class' => 'menu-preformatted', }; } $complex_format_map{'menu_comment'} = { 'begin' => "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">", 'end' => "</th></tr>", 'class' => 'menu-comment', }; %format_in_paragraph = ( 'html' => 1, ); # map mapping css specification to style %css_map = ( "ul.$NO_BULLET_LIST_CLASS" => "$NO_BULLET_LIST_STYLE", 'pre.menu-comment' => "$MENU_PRE_STYLE", 'pre.menu-preformatted' => "$MENU_PRE_STYLE", 'a.summary-letter' => 'text-decoration: none', 'blockquote.smallquotation' => 'font-size: smaller', # 'pre.display' => 'font-family: inherit', # 'pre.smalldisplay' => 'font-family: inherit; font-size: smaller', 'pre.display' => 'font-family: serif', 'pre.smalldisplay' => 'font-family: serif; font-size: smaller', 'pre.smallexample' => 'font-size: smaller', 'span.sansserif' => 'font-family:sans-serif; font-weight:normal', 'span.roman' => 'font-family:serif; font-weight:normal', 'span.nocodebreak' => 'white-space:pre', 'span.nolinebreak' => 'white-space:pre' ); $css_map{'pre.format'} = $css_map{'pre.display'}; $css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'}; $css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'}; foreach my $indented_format ('example', 'display', 'lisp') { $css_map{"div.$indented_format"} = 'margin-left: 3.2em'; $css_map{"div.small$indented_format"} = 'margin-left: 3.2em'; } # formatting functions $acronym_like = \&html_default_acronym_like; $anchor = \&html_default_anchor; $anchor_label = \&html_default_anchor_label; $begin_format_texi = \&html_default_begin_format_texi; $caption_shortcaption = \&html_default_caption_shortcaption; $caption_shortcaption_command = \&html_default_caption_shortcaption_command; $cartouche = \&html_default_cartouche; $cell = \&html_default_cell; $def = \&html_default_def; $def_item = \&html_default_def_item; $def_line = \&html_default_def_line; $element_label = \&html_default_element_label; $float = \&html_default_float; $foot_line_and_ref = \&html_default_foot_line_and_ref; $foot_section = \&html_default_foot_section; $format_list_item_texi = \&html_default_format_list_item_texi; $heading = \&t2h_default_heading; $heading_text = \&html_default_heading_text; $heading_text_preformatted = \&html_default_heading_text_preformatted; $image = \&html_default_image; $image_files = \&html_default_image_files; $index_entry = \&html_default_index_entry; $index_entry_command = \&html_default_index_entry_command; $index_entry_label = \&html_default_index_entry_label; $index_letter = \&html_default_index_letter; $index_summary = \&html_default_index_summary; $insertcopying = \&html_default_insertcopying; $line_command = \&html_default_line_command; $list_item = \&html_default_list_item; $listoffloats = \&html_default_listoffloats; $listoffloats_entry = \&html_default_listoffloats_entry; $listoffloats_caption = \&html_default_listoffloats_caption; $listoffloats_float_style = \&html_default_listoffloats_float_style; $menu_command = \&html_default_menu_command; $menu_link = \&html_default_menu_link; $menu_description = \&html_default_menu_description; $misc_element_label = \&html_default_misc_element_label; $normal_text = \&html_default_normal_text; $paragraph = \&html_default_paragraph; $preformatted = \&html_default_preformatted; $print_index = \&html_default_print_index; $protect_text = \&xml_default_protect_text; $quotation = \&html_default_quotation; $sp = \&html_default_sp; $summary_letter = \&html_default_summary_letter; $tab_item_texi = \&html_default_tab_item_texi; $table_item = \&html_default_table_item; $table_line = \&html_default_table_line; $table_list = \&html_default_table_list; $raw = \&html_default_raw; $row = \&html_default_row; } # The functions sub html_default_initialize() { @html_default_multitable_stack = (); $html_default_title = undef; } # We have to do this dynamically because of internationalization and because # in body $DOCUMENTLANGUAGE could be used. sub html_default_bodytext() { # Set the default body text, inserted between <body ... > if (defined($BODYTEXT)) { $Texi2HTML::THISDOC{'BODYTEXT'} = $BODYTEXT; } else { $Texi2HTML::THISDOC{'BODYTEXT'} = 'lang="' . get_conf('documentlanguage') . '" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"'; } } sub html_default_translate_names() { t2h_default_translate_names(); %NAVIGATION_TEXT = ( 'Top', gdt('Top'), 'Contents', gdt('Contents'), 'Overview', gdt('Overview'), 'Index', gdt('Index'), ' ', '   ', 'This', gdt('current'), 'Back', ' < ', 'FastBack', ' << ', 'Prev', gdt('Prev'), 'Up', gdt(' Up '), 'Next', gdt('Next'), 'NodeUp', gdt('Node up'), 'NodeNext', gdt('Next node'), 'NodePrev', gdt('Previous node'), 'Following', gdt('Following node'), 'Forward', ' > ', 'FastForward', ' >> ', 'About', ' ? ', 'First', ' |< ', 'Last', ' >| ', 'NextFile', gdt('Next file'), 'PrevFile', gdt('Previous file'), ); } sub html_default_do_title() { $html_default_title = "$Texi2HTML::THISDOC{'fulltitle_simple_format'}"; if ($html_default_title !~ /\S/) { $html_default_title = gdt('Untitled Document',{},{'simple_format' => 1}); main::document_warn("Must specify a title with a title command or \@top"); } } ######################################################################## # Page formatting functions # ######################################################################## # Layout for html for every sections # sub HTML_DEFAULT_print_section { my $fh = shift; my $first_in_page = shift; my $previous_is_top = shift; my $element = shift; my $buttons = \@SECTION_BUTTONS; my $nw = main::print_lines($fh); if ((get_conf('SPLIT') eq 'node') && get_conf('headers')) { my $buttons = \@NODE_FOOTER_BUTTONS; &$print_foot_navigation($fh, $buttons, $DEFAULT_RULE, (!defined($WORDS_IN_PAGE) or (defined ($nw) and $nw >= $WORDS_IN_PAGE)), $element); } } sub HTML_DEFAULT_one_section($$) { my $fh = shift; my $element = shift; main::print_lines($fh); print $fh "$DEFAULT_RULE\n"; &$print_page_foot($fh); } ################################################################### # Layout of top-page I recommend that you use @ifnothtml, @ifhtml, # @html within the Top texinfo node to specify content of top-level # page. # sub HTML_DEFAULT_print_Top_footer($$$) { my $fh = shift; my $end_page = shift; my $element = shift; my $buttons = \@TOP_BUTTONS; my $rule = $DEFAULT_RULE; $rule = $BIG_RULE if (!$end_page); #print STDERR "end_page: $end_page\n"; &$print_foot_navigation($fh, $buttons, $rule, ($end_page and (get_conf('headers') or (get_conf('SPLIT') and get_conf('SPLIT') ne 'node'))), $element); if ($end_page) { &$print_page_foot($fh); } } sub HTML_DEFAULT_print_Top($$$) { my $fh = shift; my $has_top_heading = shift; my $element = shift; main::print_lines($fh, $Texi2HTML::THIS_SECTION); } ################################################################### # Layout of Toc, Overview, and Footnotes pages # By default, we use "normal" layout # Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined # use: my $buttons = [...] to redefine navigation buttons sub HTML_DEFAULT_print_Footnotes { return &$print_misc(@_); } sub HTML_DEFAULT_print_misc_header { my $fh = shift; my $buttons = shift; my $new_file = shift; my $misc_page = shift; &$print_page_head($fh) if ($new_file); print $fh "".&$misc_element_label($misc_pages_targets{$misc_page}, $misc_page); &$print_head_navigation($fh, $buttons) if ($new_file or get_conf('headers')); } sub HTML_DEFAULT_print_misc_footer { my $fh = shift; my $buttons = shift; my $new_file = shift; &$print_foot_navigation($fh, $buttons, $DEFAULT_RULE, ($new_file and (get_conf('headers') or (get_conf('SPLIT') and get_conf('SPLIT') ne 'node'))), undef); if ($new_file) { &$print_page_foot($fh); } } ################################################################## # section_footer is only called if SPLIT eq 'section' # section_footer: after print_section of last section, before print_page_foot # sub HTML_DEFAULT_print_section_footer { my $fh = shift; my $element = shift; my $buttons = \@SECTION_FOOTER_BUTTONS; &$print_foot_navigation($fh, $buttons, $DEFAULT_RULE, 1, $element); } ################################################################### # chapter_header and chapter_footer are only called if # SPLIT eq 'chapter' # chapter_header: after print_page_head, before print_section # chapter_footer: after print_section of last section, before print_page_foot # # If you want to get rid of navigation stuff after each section, # redefine print_section such that it does not call print_navigation, # and put print_navigation into print_chapter_header sub HTML_DEFAULT_print_chapter_header { my $fh = shift; my $element = shift; # nothing to do there, by default, the navigation panel # is the element navigation panel if (! get_conf('headers')) { # in this case print_navigation is called here. my $buttons = \@CHAPTER_BUTTONS; &$print_head_navigation($fh, $buttons); print $fh "\n$DEFAULT_RULE\n" unless ($VERTICAL_HEAD_NAVIGATION); } } sub HTML_DEFAULT_print_chapter_footer { my $fh = shift; my $element = shift; my $buttons = \@CHAPTER_BUTTONS; &$print_foot_navigation($fh, $buttons, $DEFAULT_RULE, 1, $element); } sub HTML_DEFAULT_print_section_header { # nothing to do there, by default if (! get_conf('headers')) { # in this case print_navigation is called here. my $fh = shift; my $buttons = \@SECTION_BUTTONS; &$print_head_navigation($fh, $buttons); } } ################################################################### # Layout of standard header and footer # sub HTML_DEFAULT_print_page_head($) { my $fh = shift; my $longtitle = $html_default_title; $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if (defined ($Texi2HTML::SIMPLE_TEXT{'This'}) and ($Texi2HTML::SIMPLE_TEXT{'This'} !~ /^\s*$/) and get_conf('SPLIT') and ($html_default_title ne $Texi2HTML::SIMPLE_TEXT{'This'})); my $description = $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'}; $description = $longtitle if (!defined($description)); $description = "<meta name=\"description\" content=\"$description\">" if ($description ne ''); my $encoding = ''; $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$Texi2HTML::THISDOC{'ENCODING_NAME'}\">" if (defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and ($Texi2HTML::THISDOC{'ENCODING_NAME'} ne '')); my $date = ''; my $today = $Texi2HTML::THISDOC{'today'}; $today = '' if (!defined($today)); $date = "\n<meta name=\"date\" content=\"$today\">" if ($DATE_IN_HEADER and $today ne ''); my $links = ''; if ($USE_LINKS) { foreach my $link (@LINKS_BUTTONS) { #print STDERR "$link!!$Texi2HTML::HREF{$link}\n"; if (defined($Texi2HTML::HREF{$link}) and $Texi2HTML::HREF{$link} ne '') { my $title = ''; $title = " title=\"$Texi2HTML::SIMPLE_TEXT{$link}\"" if (defined($Texi2HTML::SIMPLE_TEXT{$link})); my $rel = ''; $rel = " rel=\"$BUTTONS_REL{$link}\"" if (defined($BUTTONS_REL{$link})); $links .= "<link href=\"$Texi2HTML::HREF{$link}\"${rel}${title}>\n"; } } } my $css_text = ''; $css_text = $Texi2HTML::THISDOC{'CSS_LINES'} if (defined($Texi2HTML::THISDOC{'CSS_LINES'})); my $doctype = get_conf('doctype'); print $fh <<EOT; $doctype <html> $Texi2HTML::THISDOC{'copying_comment'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program} $Texi2HTML::THISDOC{program_authors}--> <head> <title>$longtitle $description $date $encoding ${links}$css_text $EXTRA_HEAD $AFTER_BODY_OPEN EOT } sub HTML_DEFAULT_end_section($$$) { my $fh = shift; my $misc_or_top_and_section_separation = shift; my $element = shift; if ($misc_or_top_and_section_separation) { my $rule = $BIG_RULE; # in that case we are almost surely at the end of the document $rule = $DEFAULT_RULE if (! $MONOLITHIC); &$print_foot_navigation($fh, undef, $rule, 0, $element, 1); } else { print $fh "$DEFAULT_RULE\n"; } } sub HTML_DEFAULT_print_page_foot($) { my $fh = shift; my $program_text = ''; if ($PROGRAM_NAME_IN_FOOTER) { my $program_string = &$program_string(); $program_text = " $program_string
    "; } print $fh < $program_text $PRE_BODY_CLOSE

    EOT } ################################################################### # Layout of navigation panel sub HTML_DEFAULT_print_head_navigation($$$$$) { my $fh = shift; my $buttons = shift; my $first_in_page = shift; my $previous_is_top = shift; my $element = shift; my $result = ''; if ($VERTICAL_HEAD_NAVIGATION) { $result .= < EOT } $result .= &$print_navigation($buttons, $VERTICAL_HEAD_NAVIGATION); if ($VERTICAL_HEAD_NAVIGATION) { $result .= < EOT } elsif (get_conf('SPLIT') eq 'node') { $result .= "$DEFAULT_RULE\n"; } print $fh $result if (defined($fh)); return $result; } sub HTML_DEFAULT_print_foot_navigation { my $fh = shift; my $buttons = shift; my $rule = shift; my $print_navigation_panel = shift; my $element = shift; # set if called between sections and top or between sections and misc. # could also be the last element my $maybe_in_page = shift; $rule = '' if (!defined($rule)); $print_navigation_panel = 1 if (!defined($print_navigation_panel) and defined($buttons)); # avoid the rule if at the end of a page and there is nothing below $rule = '' if (!$PROGRAM_NAME_IN_FOOTER and !$print_navigation_panel and !$maybe_in_page); if ($VERTICAL_HEAD_NAVIGATION) { print $fh < EOT } print $fh "$rule\n" if ($rule ne ''); print $fh "".&$print_navigation($buttons) if ($print_navigation_panel); } ###################################################################### # navigation panel # # how to create IMG tag sub HTML_DEFAULT_button_icon_img { my $button = shift; my $icon = shift; my $name = shift; return '' if (!defined($icon)); $button = "" if (!defined ($button)); $name = '' if (!defined($name)); my $alt = ''; if ($name ne '') { if ($button ne '') { $alt = "$button: $name"; } else { $alt = $name; } } else { $alt = $button; } return qq{$alt}; } sub HTML_DEFAULT_button_formatting($$) { my $button = shift; my $vertical = shift; my ($active, $passive); if (ref($button) eq 'CODE') { $active = &$button($vertical); } elsif (ref($button) eq 'SCALAR') { $active = "$$button" if defined($$button); } elsif (ref($button) eq 'ARRAY') { my $text = $button->[1]; my $button_href = $button->[0]; # verify that $button_href is simple text and text is a reference if (defined($button_href) and !ref($button_href) and defined($text) and (ref($text) eq 'SCALAR') and defined($$text)) { # use given text if ($Texi2HTML::HREF{$button_href}) { my $anchor_attributes = ''; if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button_href})) and ($BUTTONS_ACCESSKEY{$button_href} ne '')) { $anchor_attributes = "accesskey=\"$BUTTONS_ACCESSKEY{$button_href}\""; } if ($USE_REL_REV and (defined($BUTTONS_REL{$button_href})) and ($BUTTONS_REL{$button_href} ne '')) { $anchor_attributes .= " rel=\"$BUTTONS_REL{$button_href}\""; } $active = "" . &$anchor('', $Texi2HTML::HREF{$button_href}, $$text, $anchor_attributes ); } else { $passive = $$text; } } elsif (defined($button_href) and !ref($button_href) and defined($text) and (ref($text) eq 'CODE')) { $active = &$text($button_href); } } elsif ($button eq ' ') { # handle space button $active = ($ICONS && $ACTIVE_ICONS{' '}) ? &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) : $NAVIGATION_TEXT{' '}; #next; } elsif ($Texi2HTML::HREF{$button}) { # button is active my $btitle = $BUTTONS_GOTO{$button} ? 'title="' . $BUTTONS_GOTO{$button} . '"' : ''; if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button})) and ($BUTTONS_ACCESSKEY{$button} ne '')) { $btitle .= " accesskey=\"$BUTTONS_ACCESSKEY{$button}\""; } if ($USE_REL_REV and (defined($BUTTONS_REL{$button})) and ($BUTTONS_REL{$button} ne '')) { $btitle .= " rel=\"$BUTTONS_REL{$button}\""; } if ($ICONS && $ACTIVE_ICONS{$button}) { # use icon $active = '' . &$anchor('', $Texi2HTML::HREF{$button}, &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}, $Texi2HTML::SIMPLE_TEXT{$button}), $btitle ); } else { # use text $active = '[' . &$anchor('', $Texi2HTML::HREF{$button}, $NAVIGATION_TEXT{$button}, $btitle ) . ']'; } } else { # button is passive $passive = $ICONS && $PASSIVE_ICONS{$button} ? &$button_icon_img($BUTTONS_NAME{$button}, $PASSIVE_ICONS{$button}, $Texi2HTML::SIMPLE_TEXT{$button}) : "[" . $NAVIGATION_TEXT{$button} . "]"; } return ($active, $passive); } my %html_default_node_directions; foreach my $node_directions ('NodeNext', 'NodePrev', 'NodeUp') { $html_default_node_directions{$node_directions} = 1; } sub HTML_DEFAULT_print_navigation($;$) { my $buttons = shift; my $vertical = shift; my $first_button = 1; my $result = ''; if ($HEADER_IN_TABLE) { $result .= html_default_attribute_class('table', 'header').' cellpadding="1" cellspacing="1" border="0">'."\n"; $result .= "" unless $vertical; } else { $result .= html_default_attribute_class('div', 'header').">\n

    \n"; } for my $button (@$buttons) { if ($HEADER_IN_TABLE) { $result .= qq{\n} if $vertical; $result .= qq{}; } my $direction; if (ref($button) eq 'ARRAY' and defined($button->[0]) and !ref($button->[0])) { $direction = $button->[0]; } elsif (defined($button) and !ref($button)) { $direction = $button; } my ($active, $passive) = &$button_formatting($button, $vertical); if ($HEADER_IN_TABLE) { if (defined($active)) { $first_button = 0 if ($first_button); $result .= $active; } elsif (defined($passive)) { $first_button = 0 if ($first_button); $result .= $passive; } $result .= "\n"; $result .= "\n" if $vertical; } elsif (defined($active)) { # only active buttons are print out when not in table if (defined($direction) and $html_default_node_directions{$direction} and !$first_button) { $active = ', ' .$active; } $result .= $active; $first_button = 0 if ($first_button); } } if ($HEADER_IN_TABLE) { $result .= "" unless $vertical; $result .= "\n"; } else { $result .= "

    \n\n"; } return $result; } sub html_default_node_direction($) { my $direction = shift; my $result = undef; if ($Texi2HTML::HREF{$direction} and $Texi2HTML::NODE{$direction}) { my $anchor_attributes = ''; if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$direction})) and ($BUTTONS_ACCESSKEY{$direction} ne '')) { $anchor_attributes = "accesskey=\"$BUTTONS_ACCESSKEY{$direction}\""; } if ($USE_REL_REV and (defined($BUTTONS_REL{$direction})) and ($BUTTONS_REL{$direction} ne '')) { $anchor_attributes .= " rel=\"$BUTTONS_REL{$direction}\""; } my $anchor = &$anchor('', $Texi2HTML::HREF{$direction}, $Texi2HTML::NODE{$direction}, $anchor_attributes ) ; # i18n $result = "$BUTTONS_TEXT{$direction}: $anchor"; } return $result; } ###################################################################### # Frames: this is from "Richard Y. Kim" # Should be improved to be more conforming to other _print* functions # toc_file and main_file passed as args are relative to the texinfo manual # location, and therefore are not used. sub HTML_DEFAULT_print_frame { my $fh = shift; my $toc_file = shift; my $main_file = shift; $main_file = $Texi2HTML::THISDOC{'filename'}->{'top'}; $toc_file = $Texi2HTML::THISDOC{'filename'}->{'toc_frame'}; print $fh < $Texi2HTML::THISDOC{'fulltitle'} EOT } sub HTML_DEFAULT_print_toc_frame { my $fh = shift; my $stoc_lines = shift; &$print_page_head($fh); print $fh <Content EOT print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines; print $fh "\n"; } ###################################################################### # About page # sub HTML_DEFAULT_about_body { return undef if (!$HEADER_IN_TABLE); my $about = "

    \n"; if (ref($PRE_ABOUT) eq 'CODE') { $about .= &$PRE_ABOUT(); } else { $about .= $PRE_ABOUT; } $about .= <

    EOT $about .= gdt(' The buttons in the navigation panels have the following meaning:') . "\n"; $about .= < EOT $about .= ' \n" . ' \n" . ' \n" . ' \n" . " \n"; for my $button (@SECTION_BUTTONS) { next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY'; $about .= " \n \n"; $about .= <$BUTTONS_NAME{$button} EOT } $about .= <

    EOT $about .= gdt(' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:') . "\n"; # where the Example assumes that the current position # is at Subsubsection One-Two-Three of a document of # the following structure: $about .= <

      EOT $about .= '
    • 1. ' . gdt('Section One') . "\n" . "
        \n" . '
      • 1.1 ' . gdt('Subsection One-One') . "\n"; $about .= <
      • ...
    • EOT $about .= '
    • 1.2 ' . gdt('Subsection One-Two') . "\n" . "
        \n" . '
      • 1.2.1 ' . gdt('Subsubsection One-Two-One') . "
      • \n" . '
      • 1.2.2 ' . gdt('Subsubsection One-Two-Two') . "
      • \n" . '
      • 1.2.3 ' . gdt('Subsubsection One-Two-Three') . "    \n" . ' <== ' . gdt('Current Position') . "
      • \n" . '
      • 1.2.4 ' . gdt('Subsubsection One-Two-Four') . "
      • \n" . "
      \n" . "
    • \n" . '
    • 1.3 ' . gdt('Subsection One-Three') . "\n"; $about .= <
    • ...
    EOT $about .= '
  • 1.4 ' . gdt('Subsection One-Four') . "
  • \n"; $about .= < $AFTER_ABOUT EOT return $about; } sub HTML_DEFAULT_print_redirection_page() { #my $fh = shift; my $longtitle = $html_default_title; $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if (defined ($Texi2HTML::SIMPLE_TEXT{'This'}) and ($Texi2HTML::SIMPLE_TEXT{'This'} !~ /^\s*$/) and ($html_default_title ne $Texi2HTML::SIMPLE_TEXT{'This'})); my $description = $Texi2HTML::THISDOC{'DOCUMENT_DESCRIPTION'}; $description = $longtitle if (!defined($description)); my $encoding = ''; $encoding = "" if (defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and ($Texi2HTML::THISDOC{'ENCODING_NAME'} ne '')); my $href = &$anchor('', $Texi2HTML::HREF{'This'}, $Texi2HTML::NAME{'This'}); my $string = gdt('The node you are looking for is at {href}.', { 'href' => $href }); my $doctype = get_conf('doctype'); my $css_text = ''; $css_text = $Texi2HTML::THISDOC{'CSS_LINES'} if (defined($Texi2HTML::THISDOC{'CSS_LINES'})); #print $fh < $longtitle $encoding $css_text $EXTRA_HEAD $AFTER_BODY_OPEN

    $string

    EOT return $result; } sub html_default_uref($$) { shift; my $args = shift; my $url = shift @$args; my $text = shift @$args; my $replacement = shift @$args; $url = main::normalise_space($url); $replacement = '' if (!defined($replacement)); $replacement = main::normalise_space($replacement); $text = '' if (!defined($text)); $text = main::normalise_space($text); $text = $replacement if ($replacement ne ''); $text = $url unless ($text ne ''); return $text if ($url eq ''); return &$anchor('', $url, $text); } sub html_default_math($$) { shift; my $args = shift; my $text = shift @$args; return "$text"; } sub html_default_email($$) { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); $text = $mail unless (defined($text) and ($text ne '')); $text = main::normalise_space($text); return $text if ($mail eq ''); return &$anchor('', "mailto:$mail", $text); } sub html_default_attribute_class($$) { my $element = shift; my $class = shift; return "<$element" if (!defined($class) or $class eq '' or $NO_CSS); my $style = ''; if ($INLINE_CSS_STYLE and defined($css_map{"$element.$class"})) { $style = ' style="'.$css_map{"$element.$class"}.'"'; } return "<$element class=\"$class\"$style"; } # this is called each time a format begins. Here it is used to keep a # record of the multitables to have a faithful count of the cell nr. sub html_default_begin_format_texi($$$) { my $command = shift; my $line = shift; my $state = shift; # first array element is the number of cell in a row # second is the number of paragraphs in a cell push (@html_default_multitable_stack, [-1,-1]) if ($command eq 'multitable'); return $line; } sub html_default_caption_shortcaption($) { my $float = shift; my $caption_lines; my $shortcaption_lines; my $style = $float->{'style_texi'}; if (defined($float->{'nr'})) { my $nr = $float->{'nr'}; if ($style ne '') { $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr}); } else { $style = $nr; } } if (defined($float->{'caption_texi'})) { @$caption_lines = @{$float->{'caption_texi'}}; $caption_lines->[0] =~ s/^\s*//; if (defined($style)) { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] }); } else { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $caption_lines->[0]; } push @$caption_lines, "}\n"; } elsif (defined($style)) { $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n"; } if (defined($float->{'shortcaption_texi'})) { @$shortcaption_lines = @{$float->{'shortcaption_texi'}}; if (defined($style)) { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] }); } else { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $shortcaption_lines->[0]; } push @$shortcaption_lines, "}\n"; } elsif (defined($style)) { $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n"; } return ($caption_lines, $shortcaption_lines); } # everything is done in &$float sub html_default_caption_shortcaption_command($$$$) { my $command = shift; my $text = shift; my $texi_lines = shift; my $float_element = shift; return ''; } sub html_default_float($$$$$) { my $text = shift; my $float = shift; my $caption = shift; my $shortcaption = shift; my $label = ''; if (exists($float->{'id'})) { $label = &$anchor($float->{'id'}); } my $caption_text = ''; if (defined($float->{'caption_texi'})) { $caption_text = $caption; } elsif (defined($float->{'shortcaption_texi'})) { $caption_text = $shortcaption; } elsif (defined($caption)) { $caption_text = $caption; } return html_default_attribute_class('div','float'). '>' . "$label\n" . $text . '' . $caption_text; } sub html_default_listoffloats_float_style($$) { my $style_texi = shift; my $float = shift; my $style = $float->{'style_texi'}; #print STDERR "listoffloat/float style mismatch $style_texi $style\n" if ($style_texi ne $style); if (defined($float->{'nr'})) { my $nr = $float->{'nr'}; if ($style ne '') { $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr}); } else { $style = $nr; } } return $style; } sub html_default_listoffloats_caption($) { my $float = shift; if (defined($float->{'shortcaption_texi'})) { return ([ @{$float->{'shortcaption_texi'}} ], 'shortcaption'); } elsif (defined($float->{'caption_texi'})) { return ([ @{$float->{'caption_texi'}} ], 'caption'); } return ([ ], undef); } sub html_default_listoffloats_entry($$$$) { my $style_texi = shift; my $float = shift; my $float_style = shift; my $caption = shift; my $href = shift; return '
    ' . &$anchor('', $href, $float_style) . '
    ' . $caption . '
    ' . "\n"; } sub html_default_listoffloats($$$) { my $style_texi = shift; my $style = shift; my $float_entries = shift; my $result = html_default_attribute_class('dl', 'listoffloats').">\n" ; foreach my $float_entry (@$float_entries) { $result .= $float_entry; } return $result . "\n"; } sub html_default_insertcopying($$$) { my $text = shift; my $comment = shift; my $simple_text = shift; return $text; } sub html_default_protect_space_codebreak($$$$$) { my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $style_stack = shift; return $text if ($in_preformatted or $in_raw_text); my $in_w = 1 if (in_cmd($style_stack, 'w')); if ($in_w or ($in_code and get_conf('allowcodebreaks') eq 'false')) { my $class = 'nolinebreak'; $class = 'nocodebreak' if ($in_code and get_conf('allowcodebreaks') eq 'false'); my $open = html_default_attribute_class('span', $class).'>'; # protect spaces in the html leading attribute in case we are in 'w' $open =~ s/ /\x{1F}/g if ($in_w); $text =~ s/(\S*[_-]\S*)/${open}$1<\/span>/g; } if ($in_w) { $text .= ' ' if (chomp($text)); # protect spaces within text $text =~ s/ / /g; # revert protected spaces in leading html attribute $text =~ s/\x{1F}/ /g; } return $text; } sub html_default_normal_text($$$$$$$;$) { my @initial_args = @_; my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; my $style_stack = shift; my $state = shift; # like utf8.init if ($ENABLE_ENCODING and !$ENABLE_ENCODING_USE_ENTITY and defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and $Texi2HTML::THISDOC{'ENCODING_NAME'} eq 'utf-8') { my $result = &t2h_utf8_normal_text(@initial_args); $result = html_default_protect_space_codebreak($result, $in_raw_text, $in_preformatted, $in_code, $style_stack); return $result; } $text = uc($text) if (in_cmd($style_stack, 'sc')); $text = &$protect_text($text) unless($in_raw_text); #$text =~ s/ / /g # if (!$in_raw_text and !$in_preformatted and in_cmd($style_stack, 'w')); if (! $in_code and !$in_preformatted) { if ($USE_ISO and !$in_raw_text) { $text =~ s/---/\&mdash\;/g; $text =~ s/--/\&ndash\;/g; $text =~ s/``/\&ldquo\;/g; $text =~ s/''/\&rdquo\;/g; } else { if ($in_raw_text) #FIXME really do that ? It is done by makeinfo { $text =~ s/``/"/g; $text =~ s/''/"/g; } else { $text =~ s/``/"/g; $text =~ s/''/"/g; # to be like texinfo #$text =~ s/'/\&rsquo\;/g; #$text =~ s/`/\&lsquo\;/g; } # FIXME really do that in raw text? $text =~ s/---/\x{1F}/g; $text =~ s/--/-/g; $text =~ s/\x{1F}/--/g; } } $text = html_default_protect_space_codebreak($text, $in_raw_text, $in_preformatted, $in_code, $style_stack); $text = t2h_text_substitutions($text, $in_raw_text, ($in_preformatted or $in_code), $in_simple); return $text; } # This function produces an anchor # # arguments: # $name : anchor name # $href : anchor href # text : text displayed # extra_attribs : added to anchor attributes list sub html_default_anchor($;$$$) { my $name = shift; my $href = shift; my $text = shift; my $attributes = shift; my $class = ''; #print STDERR "!$name!$href!$text!$attributes!\n"; if (!defined($attributes) or ($attributes !~ /\S/)) { $attributes = ''; } else { if ($attributes =~ s/^class=\"([^\"]+)\"//) { $class = $1; } $attributes = ' ' . $attributes if ($attributes ne ''); } $name = '' if (!defined($name) or ($name !~ /\S/)); $href = '' if (!defined($href) or ($href !~ /\S/)); $text = '' if (!defined($text)); return $text if (($name eq '') and ($href eq '')); $name = "name=\"$name\"" if ($name ne ''); $href = "href=\"$href\"" if ($href ne ''); $href = ' ' . $href if (($name ne '') and ($href ne '')); #print STDERR "!!!$name!$href!$text!$attributes!\n"; return html_default_attribute_class('a', $class). " ${name}${href}${attributes}>$text"; } # This function is used to format the text associated with a @deff/@end deff # # argument: # text # # $DEF_TABLE should be used to distinguish between @def formatted as table # and as definition lists. sub html_default_def_item($$$) { my $text = shift; my $only_inter_item_commands = shift; my $command = shift; if ($text =~ /\S/) { if (! $DEF_TABLE) { return '
    ' . $text . '
    ';# unless $only_inter_item_commands; #return $text; # invalid without dd in ul } else { return '
    '; } } return ''; } # format the container for the @deffn line and text # # argument # text of the whole @def, line and associated text. # # $DEF_TABLE should be used. sub html_default_def($$) { my $text = shift; my $command = shift; if ($text =~ /\S/) { if (! $DEF_TABLE) { return "
    \n" . $text . "
    \n"; } else { return "
    ' . gdt('Button') . " ' . gdt('Name') . " ' . gdt('Go to') . " ' . gdt('From 1.2.3 go to') . "
    "; $about .= ($ICONS && $ACTIVE_ICONS{$button} ? &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) : ' [' . $NAVIGATION_TEXT{$button} . '] '); $about .= "$BUTTONS_GOTO{$button} $BUTTONS_EXAMPLE{$button}
    ' . $text . '
    \n" . $text . "
    \n"; } } return ''; } # a whole menu # # argument: # the whole menu text (entries and menu comments) # # argument: # whole menu text. sub html_default_menu_command($$$) { my $format = shift; my $text = shift; my $in_preformatted = shift; $html_menu_entry_index=0; my $begin_row = ''; my $end_row = ''; if ($in_preformatted) { $begin_row = ''; $end_row = ''; } if ($text =~ /\S/) { return '' if ($format eq 'direntry'); return $text if ($format eq 'detailmenu'); return html_default_attribute_class('table', 'menu')." border=\"0\" cellspacing=\"0\">${begin_row}\n" . $text . "${end_row}\n"; } } # formats a menu entry link pointing to a node or section # # arguments: # the entry text # the state, a hash reference holding informations about the context, with a # usefull entry, 'preformatted', true if we are in a preformatted format # (a format keeping space between words). In that case a function # of the main program, main::do_preformatted($text, $state) might # be used to format the text with the current format style. # href is optionnal. It is the reference to the section or the node anchor # which should be used to make the link (typically it is the argument # of a href= attribute in a element). sub html_default_menu_link($$$$$$$$) { my $element_name = shift; my $state = shift; my $href = shift; my $node = shift; my $title = shift; my $ending = shift; my $has_title = shift; my $command_stack = shift; my $preformatted = shift; my $in_commands = 0; $in_commands = 1 if ($command_stack->[-1] and $command_stack->[-1] ne 'menu' and $command_stack->[-1] ne 'detailmenu' and $command_stack->[-1] ne 'direntry'); $title = '' unless ($has_title); #print STDERR "MENU_LINK($in_commands)($state->{'preformatted'})\n"; my $entry; my $symbol = ''; if ($preformatted) { $title .= ':' if ($title ne ''); $entry = "$MENU_SYMBOL$title$node"; } elsif ($element_name eq '' or $NODE_NAME_IN_MENU) { if ($has_title) { $entry = "$title"; } else { $entry = "$node"; } $entry =~ s/^\s*//; $symbol = "$MENU_SYMBOL "; } else { $entry = $element_name; } $html_menu_entry_index++; my $accesskey; $accesskey = "accesskey=\"$html_menu_entry_index\"" if ($USE_ACCESSKEY and ($html_menu_entry_index < 10)); $entry = &$anchor ('', $href, $entry, $accesskey) if (defined($href)); return $entry.$ending if ($preformatted); # FIXME conditionalise to not having a description return "$symbol$entry$MENU_ENTRY_COLON" .' ' if ($in_commands); return "$symbol$entry$MENU_ENTRY_COLON  "; } sub html_simplify_text($) { my $text = shift; $text =~ s/[^\w]//og; return $text; } # formats a menu entry description, ie the text appearing after the node # specification in a menu entry an spanning until there is another # menu entry, or empty line # # arguments: # the description text # the state. See menu_entry. # the heading of the element associated with the node. sub html_default_menu_description($$$$) { my $text = shift; my $state = shift; my $element_text = shift; my $command_stack = shift; my $preformatted = shift; my $in_commands = 0; $in_commands = 1 if ($command_stack->[-1] and $command_stack->[-1] ne 'menu' and $command_stack->[-1] ne 'detailmenu' and $command_stack->[-1] ne 'direntry'); return $text if ($preformatted); return $text."
    " if ($in_commands); if ($AVOID_MENU_REDUNDANCY) { $text = '' if (html_simplify_text($element_text) eq html_simplify_text($text)); } return "$text\n"; } sub html_teletyped_in_stack($) { my $stack = shift; foreach my $element(reverse(@$stack)) { return 1 if ($complex_format_map{$element} and $complex_format_map{$element}->{'style'} and $complex_format_map{$element}->{'style'} eq 'code'); } return 0; } # text after @item in table, vtable and ftable sub html_default_table_item($$$$$$$) { my $text = shift; my $index_label = shift; my $format = shift; my $command = shift; # my $formatted_command = shift; my $style_stack = shift; # my $text_formatted = shift; # my $text_formatted_leading_spaces = shift; # my $text_formatted_trailing_spaces = shift; my $item_cmd = shift; my $formatted_index_entry = shift; # if (defined($text_formatted) and !exists $special_list_commands{$format}->{$command}) # { # $text = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces; # } # $formatted_command = '' if (!defined($formatted_command) or # exists($special_list_commands{$format}->{$command})); if (html_teletyped_in_stack($style_stack)) { # $text .= ''; # $formatted_command = '' . $formatted_command; $text = '' . $text . ''; } $text .= "\n" . $index_label if (defined($index_label)); # return '

    ' . $formatted_command . $text . '
    ' . "\n"; return '
    ' . $text . '
    ' . "\n"; } # format text on the line following the @item line (in table, vtable and ftable) sub html_default_table_line($$$) { my $text = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); if ($text =~ /\S/) { return '
    ' . $text . '
    ' . "\n";# unless ($only_inter_item_commands); #return $text; # invalid without dd in ul } return ''; } #my $cell_nr = -1; # row in multitable sub html_default_row($$$$$$$$) { my $text = shift; my $macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); # this is used to keep the cell number $html_default_multitable_stack[-1]->[0] = -1; if ($text =~ /\S/) { if ($macro eq 'headitem') { return '' . $text . '' . "\n"; } return '' . $text . '' . "\n"; } return ''; } # cell in multitable sub html_default_cell($$$$$$$$) { my $text = shift; my $row_macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); $html_default_multitable_stack[-1]->[0]++; my $cell_nr = $html_default_multitable_stack[-1]->[0]; my $fractions = ''; if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY') and exists($columnfractions->[$cell_nr])) { my $fraction = sprintf('%d', 100*$columnfractions->[$cell_nr]); $fractions = " width=\"$fraction%\""; } # in constructs like # @strong{ # @multitable .... # } # the space won't be removed since the is put before the space. $text =~ s/^\s*//; $text =~ s/\s*$//; if ($row_macro eq 'headitem') { return "" . $text . ''; } return "" . $text . ''; } sub html_default_format_list_item_texi($$$$$) { my $format = shift; my $line = shift; my $prepended = shift; my $command = shift; my $number = shift; my $result_line; my $open_command = 0; if (defined($command) and $command ne '' and !exists $special_list_commands{$format}->{$command} and $format ne 'itemize') { #@*table $open_command = 1; $line =~ s/^\s*//; $line =~ s/\s*$//; if (exists ($style_map{$command})) { $result_line = "\@$command\{$line\}\n"; } elsif (exists ($things_map{$command})) { $result_line = "\@$command\{\} $line\n"; } else { $result_line = "\@$command $line\n"; } } elsif (defined($prepended) and $prepended ne '') { $prepended =~ s/^\s*//; $prepended =~ s/\s*$//; $line =~ s/^\s*//; $result_line = $prepended . ' ' . $line; } return ($result_line, $open_command); } # format an item in a list # # argument: # text of the item # format of the list (itemize or enumerate) # command passed as argument to the format # formatted_command leading command formatted, if it is a thing command sub html_default_list_item($$$$$$$$$$$) { my $text = shift; my $format = shift; my $command = shift; my $formatted_command = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $prepended = shift; my $prepended_formatted = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); $formatted_command = '' if (!defined($formatted_command) or exists($special_list_commands{$format}->{$command})); my $prepend = ''; # if (defined($prepended) and $prepended ne '') # { # $prepend = $prepended; # } # elsif ($formatted_command ne '') if ($formatted_command ne '') { $prepend = $formatted_command; } if ($text =~ /\S/) { return '
  • ' . $prepend . $text . '
  • '; } return ''; } sub html_default_table_list($$$$$$$$$) { my $format_command = shift; my $text = shift; my $command = shift; my $formatted_command = shift; # enumerate my $item_nr = shift; my $enumerate_style = shift; # itemize my $prepended = shift; my $prepended_formatted = shift; # multitable my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; # my $number = shift; $formatted_command = '' if (!defined($formatted_command) or exists($special_list_commands{$format}->{$command})); if ($format_command eq 'itemize') { return "
      \n" . $text . "
    \n" if (($command eq 'bullet') or (($command eq '') and ($prepended eq ''))); return html_default_attribute_class('ul',$NO_BULLET_LIST_CLASS).">\n" . $text . "\n"; } elsif ($format_command eq 'multitable') { pop @html_default_multitable_stack; return &$format('multitable', 'table', $text); } } # a paragraph # arguments: # $text of the paragraph # $align for the alignement # $indent for the indent style (indent or noindent) # The following is usefull if the paragraph is in an itemize. # $paragraph_command is the leading formatting command (like @minus) # $paragraph_command_formatted is the leading formatting command formatted # $paragraph_number is a reference on the number of paragraphs appearing # in the format. The value should be increased if a paragraph is done # $format is the format name (@itemize) sub html_default_paragraph($$$$$$$$$$$$) { my $text = shift; my $align = shift; my $indent = shift; my $paragraph_command = shift; my $paragraph_command_formatted = shift; my $paragraph_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; #print STDERR "format: $format\n" if (defined($format)); #print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n"; # $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or # exists($special_list_commands{$format}->{$paragraph_command})); return '' if ($text =~ /^\s*$/); if (defined($paragraph_number) and defined($$paragraph_number)) { $$paragraph_number++; return $text if (($format eq 'itemize' or $format eq 'enumerate') and ($$paragraph_number == 1)); } my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); if ($top_stack eq 'multitable') { $html_default_multitable_stack[-1]->[1]++; if ($html_default_multitable_stack[-1]->[1] == 0) { return $text; } } my $open = '

    '; if ($align) { $open = "

    "; } return $open.$text.'

    '; } # a preformatted region # arguments: # $text of the preformatted region # $pre_style css style # $class identifier for the preformatted region (example, menu-comment) # The following is usefull if the preformatted is in an itemize. # $leading_command is the leading formatting command (like @minus) # $leading_command_formatted is the leading formatting command formatted # $preformatted_number is a reference on the number of preformatteds appearing # in the format. The value should be increased if a preformatted is done sub html_default_preformatted($$$$$$$$$$$$) { my $text = shift; my $pre_style = shift; my $class = shift; my $leading_command = shift; my $leading_command_formatted = shift; my $preformatted_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; #print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n"; return '' if ($text eq ''); $leading_command_formatted = '' if (!defined($leading_command_formatted) or exists($special_list_commands{$format}->{$leading_command})); if (defined($preformatted_number) and defined($$preformatted_number)) { $$preformatted_number++; } my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); if ($top_stack eq 'multitable') { $text =~ s/^\s*//; $text =~ s/\s*$//; } return html_default_attribute_class('pre', $class).">".$text.""; } sub html_default_heading_text($$$) { my $command = shift; my $text = shift; my $level = shift; return '' if ($text !~ /\S/); # FIXME use a class=*contents? my $class = ''; if ($command =~ /^@/ and $command !~ /^@.*contents$/) { $class = $command; $class =~ s/^@//; $class = 'node-heading' if ($command eq '@node'); } my $align = ''; $align = ' align="center"' if ($command eq '@centerchap' or $command eq '@settitle'); $level = 1 if ($level == 0); my $result = html_default_attribute_class ("h$level", $class) ."$align>$text"; # FIXME titlefont appears inline in text, so no end of line is # added. The end of line should be added by the user if needed. $result .= "\n" unless ($command eq '@titlefont'); $result .= $DEFAULT_RULE . "\n" if ($command eq '@part' and defined($DEFAULT_RULE) and $DEFAULT_RULE ne ''); return $result; } sub html_default_heading_text_preformatted($$$) { my $command = shift; my $text = shift; my $level = shift; return '' if ($text !~ /\S/); return ''.$text.''."\n"; } # formatting of raw regions # if L2H is true another mechanism is used for tex sub html_default_raw($$;$) { my $style = shift; my $text = shift; my $line_nr = shift; my $expanded = 1 if (grep {$style eq $_} @EXPAND); if ($style eq 'verbatim' or $style eq 'verbatiminclude' or ($style eq 'tex' and $expanded)) { $style = 'verbatim' if ($style eq 'verbatiminclude'); return html_default_attribute_class('pre', $style).">" . &$protect_text($text) . ''; } elsif ($style eq 'html' and $expanded) { chomp ($text); return $text; } elsif ($expanded) { main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr); return &$protect_text($text); } else { return ''; } } # This function formats a footnote reference and the footnote text associated # with a given footnote. # The footnote reference is the text appearing in the main document pointing # to the footnote text. # # arguments: # absolute number of the footnote (in the document) # relative number of the footnote (in the page) # identifier for the footnote # identifier for the footnote reference in the main document # main document file # footnote text file # array with the footnote text lines # the state. See menu entry. # # returns: # reference on an array containing the footnote text lines which should # have been updated # the text for the reference pointing on the footnote text sub html_default_foot_line_and_ref($$$$$$$$$) { my $number_in_doc = shift; my $number_in_page = shift; my $footnote_id = shift; my $place_id = shift; my $document_file = shift; my $footnote_file = shift; my $lines = shift; my $document_state = shift; if ($document_file eq $footnote_file) { $document_file = $footnote_file = ''; } $number_in_doc = $NO_NUMBER_FOOTNOTE_SYMBOL if (!$NUMBER_FOOTNOTES); unshift (@$lines, '

    ' . &$anchor($footnote_id, $document_file . "#$place_id", "($number_in_doc)") . "

    \n"); # this is a bit obscure, this allows to add an anchor only if formatted # as part of the document. #$place_id = '' if ($document_state->{'outside_document'} or $document_state->{'multiple_pass'} or $document_state->{'expansion'}); $place_id = '' if ($document_state->{'outside_document'} or (defined($document_state->{'multiple_pass'}) and $document_state->{'multiple_pass'} > 0)); return ($lines, &$anchor($place_id, $footnote_file . "#$footnote_id", "($number_in_doc)")); } # formats a group of footnotes. # # argument: # array reference on the footnotes texts lines # # returns an array reference on the group of footnotes lines sub html_default_foot_section($) { my $lines = shift; unshift (@$lines, html_default_attribute_class('div', 'footnote').">\n" ,"$DEFAULT_RULE\n", &$heading_text('footnotes', gdt('Footnotes'), 3) ); push (@$lines, "\n"); return $lines; } sub html_default_image_files($$$$) { my $base = shift; my $extension = shift; my $texi_base = shift; my $texi_extension = shift; my @files = (); return @files if (!defined($base) or ($base eq '')); if (defined($extension) and ($extension ne '')) { push @files,["$base.$extension", "$texi_base.$texi_extension"]; } foreach my $ext (@IMAGE_EXTENSIONS) { push @files,["$base.$ext", "$texi_base.$ext"]; } return @files; } # format an image # # arguments: # image file name with path # image basename # a boolean true if we are in a preformatted format # image file name without path # alt text # width # height # raw alt # extension # path to working dir # path to file relative from working dir sub html_default_image($$$$$$$$$$$$$$$$$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; my $base_simple_format = shift; my $extension_simple_format = shift; my $file_name_simple_format = shift; my $line_nr = shift; if (!defined($file_path) or $file_path eq '') { if (defined($extension) and $extension ne '') { $file = "$base.$extension"; } else { $file = "$base.jpg"; } main::line_warn (sprintf(__("\@image file `%s' (for HTML) not found, using `%s'"), $base, $file), $line_nr); } elsif (! $COMPLETE_IMAGE_PATHS) { $file = $file_name; } $alt = &$protect_text($base) if (!defined($alt) or ($alt eq '')); return "[ $alt ]" if ($preformatted); # it is possible that $file_name is more correct as it allows the user # to chose the relative path. $file = &$protect_text($file); return "\"$alt\""; } # format a target in the main document for an index entry. # # arguments: # target identifier # boolean true if in preformatted format # FIXME document the remaining sub html_default_index_entry_label($$$$$$$$$) { my $identifier = shift; my $preformatted = shift; my $entry = shift; my $index_name = shift; my $index_command = shift; my $texi_entry = shift; my $formatted_entry = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; return '' if (!defined($identifier) or ($identifier !~ /\S/)); my $label = &$anchor($identifier); return $label . "\n" if (!$preformatted); return $label; } sub html_default_index_entry_command($$$$$$) { my $command = shift; my $index_name = shift; my $label = shift; my $entry_texi = shift; my $entry_formatted = shift; my $index_entry_ref = shift; return $label; } # process definition commands line @deffn for example sub html_default_def_line($$$$$$$$$$$$$$$$) { my $category_prepared = shift; my $name = shift; my $type = shift; my $arguments = shift; my $index_label = shift; my $arguments_array = shift; my $arguments_type_array = shift; my $unformatted_arguments_array = shift; my $command = shift; my $class_name = shift; my $category = shift; my $class = shift; my $style = shift; my $original_command = shift; $index_label = '' if (!defined($index_label)); chomp($index_label); $category_prepared = '' if (!defined($category_prepared) or ($category_prepared =~ /^\s*$/)); $name = '' if (!defined($name) or ($name =~ /^\s*$/)); $type = '' if (!defined($type) or $type =~ /^\s*$/); if (!defined($arguments) or $arguments =~ /^\s*$/) { $arguments = ''; } else { chomp ($arguments); $arguments = '' . $arguments . ''; } my $type_name = ''; $type_name = " $type" if ($type ne ''); $type_name .= ' ' . $name . '' if ($name ne ''); $type_name .= $arguments; if (! $DEF_TABLE) { return '
    '. $index_label. $category_prepared . ':' . $type_name . "
    \n"; } else { return "" . $type_name . "" . $category_prepared . $index_label . "\n"; } } # a cartouche sub html_default_cartouche($$) { my $text = shift; if ($text =~ /\S/) { return html_default_attribute_class('table', 'cartouche')." border=\"1\">\n" . $text . "\n"; } return ''; } sub html_default_sp($$) { my $number = shift; my $preformatted = shift; return "
    \n" x $number if (!$preformatted); return "\n" x $number; } sub html_default_acronym_like($$$$$$) { my $command = shift; my $acronym_texi = shift; my $acronym_text = shift; my $with_explanation = shift; my $explanation_lines = shift; my $explanation_text = shift; my $explanation_simply_formatted = shift; my $attribute = $command; my $opening = "<$attribute>"; if (defined($explanation_simply_formatted)) { $opening = "<$attribute title=\"$explanation_simply_formatted\">"; } if ($with_explanation) { return gdt('{acronym_like} ({explanation})', {'acronym_like' => $opening . $acronym_text . "", 'explanation' => $explanation_text},{'duplicate'=>1}) } else { return $opening . $acronym_text . ""; } } sub html_default_quotation($$$$$) { my $command = shift; my $text = shift; my $argument_text = shift; my $argument_text_texi = shift; my $authors = shift; my $class = ''; $class = $command if ($command ne 'quotation'); my $attribution = ''; if ($authors) { foreach my $author (@$authors) { my $author_texi = $author->{'author_texi'}; chomp($author_texi); $attribution .= gdt("\@center --- \@emph{{author}}\n", {'author' => $author_texi}, {'duplicate' => 1, 'allow_paragraph' => 1}); } } return html_default_attribute_class('blockquote', $class).">\n" . $text ."\n" . $attribution; } # format a whole index # # argument: # index text # index name sub html_default_print_index($$) { my $text = shift; my $name = shift; return '' if (!defined($text)); return html_default_attribute_class('table', "index-$name")." border=\"0\">\n" . "" . gdt('Index Entry') . "  " . gdt('Section') . "\n" . " $DEFAULT_RULE\n" . $text . "\n"; } # format a letter entry in an index page. The letter entry contains # the index entries for the words beginning with that letter. It is # a target for links pointing from the summary of the index. # # arguments: # the letter # identifier for the letter entry. This should be used to make the target # identifier # text of the index entries sub html_default_index_letter($$$) { my $letter = shift; my $id = shift; my $text = shift; return $text if ($letter =~ /^\s*$/); return '' . &$anchor($id,'',&$normal_text($letter, 0, 0, 0, 0, 0, [])) . "\n" . $text . " $DEFAULT_RULE\n"; } # format an index entry (in a letter entry). # # arguments: # href to the main text, linking to the place where the index entry appears # entry text # href to the main text, linking to the section or node where the index # entry appears # section or node heading sub html_default_index_entry($$$$$$$$$$) { my $text_href = shift; my $entry = shift; my $element_href = shift; my $element_text = shift; my $entry_file = shift; my $current_element_file = shift; my $entry_target = shift; my $entry_element_target = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; return '' if ($entry !~ /\S/); my $element = $index_entry_ref->{'real_element'}; if (defined($element)) { my $element_set = 0; if ($NODE_NAME_IN_INDEX) { if ($element->{'node'}) { $element_set = 1; } elsif ($element->{'with_node'}) { $element = $element->{'with_node'}; $element_set = 1; } } elsif (defined($NODE_NAME_IN_INDEX)) { if (!$element->{'node'}) { $element_set = 1; } elsif ($element->{'with_section'}) { $element = $element->{'with_section'}; $element_set = 1; } } if ($element_set) { $element_href = main::href($element, $Texi2HTML::THIS_ELEMENT->{'file'}, $Texi2HTML::THISDOC{'line_nr'}); $element_text = $element->{'text'}; } } return '' . &$anchor('', $text_href, $entry) . $INDEX_ENTRY_COLON . ' ' . &$anchor('', $element_href, $element_text) . "\n"; } # format an index summary. This is a list of letters linking to the letter # entries. # # arguments: # array reference containing the formatted alphabetical letters # array reference containing the formatted non lphabetical letters sub html_default_index_summary($$) { my $alpha = shift; my $nonalpha = shift; my $join = ''; my $nonalpha_text = ''; my $alpha_text = ''; $join = "   \n
    \n" if (@$nonalpha and @$alpha); if (@$nonalpha) { $nonalpha_text = join("\n   \n", @$nonalpha) . "\n"; } if (@$alpha) { $alpha_text = join("\n   \n", @$alpha) . "\n   \n"; } return "
    " . gdt('Jump to') .":   " . $nonalpha_text . $join . $alpha_text . "
    \n"; } sub html_default_element_label($$$$) { my $id = shift; my $element = shift; my $command = shift; my $line = shift; return &$anchor($id) . "\n"; } sub html_default_misc_element_label($$) { my $id = shift; my $misc_page_name = shift; return &$anchor($id) . "\n"; } sub html_default_anchor_label($$$$) { my $id = shift; my $anchor_text = shift; my $anchor_reference = shift; my $in_special_region = shift; return &$anchor($id); } sub html_default_tab_item_texi($$$$$$) { my $command = shift; my $commands_stack = shift; my $stack = shift; my $state = shift; my $line = shift; my $line_nr = shift; if (defined($commands_stack) and @$commands_stack and $commands_stack->[-1] eq 'multitable' and @html_default_multitable_stack) { $html_default_multitable_stack[-1]->[1] = -1; } return undef; } sub html_default_line_command($$$$) { my $command = shift; my $arg_text = shift; my $arg_texi = shift; my $state = shift; return '' if ($arg_text eq '' or ($command eq 'author' and (!$state->{'region'} or $state->{'region'} ne 'titlepage'))); my $style = $line_command_map{$command}; if ($style) { my $attribute_text = ''; if ($style =~ /^(\w+)(\s+.*)/) { $style = $1; $attribute_text = $2; } $arg_text = "<${style}$attribute_text>$arg_text"; } $arg_text .= "
    " if ($command eq 'author'); $arg_text .= "\n"; return $arg_text; } 1; require "$T2H_HOME/formats/html.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/formats/html.init" && -r "$T2H_HOME/formats/html.init"); # @INIT_INFO@ # vim: set filetype=perl: # #+############################################################################## # # info.init: convert to info # # Copyright (C) 2008, 2009 Patrice Dumas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # # Some error messages come from texinfo (makeinfo), so copyright holder # is the FSF or the individual who wrote them. All come from before the # switch of texinfo to GPLv3+. # #-############################################################################## use Data::Dumper; use strict; $Data::Dumper::Maxdepth = 25; my %info_default_indented_commands; my %info_default_format; my %info_default_enable_encoding_accents; my @simple_quoted_commands; my @asis_commands; my @chevron_commands; my %info_default_accent_commands = (); my %info_default_leaf_command = (); my $info_default_end_sentence_character; my $info_default_after_punctuation_characters; my $info_default_indent_length; my %info_default_indent_format_length; my $info_default_index_length_to_node; my $info_default_listoffloat_caption_entry_length; my $info_default_listoffloat_append; my %info_default_index_entries_counts; sub info_default_load(;$) { my $from_command_line = shift; t2h_default_set_variables_default(); $USE_SECTIONS = 0; $USE_NODES = 1; #set_conf('SPLIT', 0, 1); $SPLIT = ''; @T2H_FORMAT_EXPAND = ('info', 'direntry'); $EXTENSION = 'info'; $SHOW_MENU = 1; $SHOW_TITLE = 0; $USE_SETFILENAME_EXTENSION = 1; $INLINE_INSERTCOPYING = 1; $SIMPLE_MENU = 1; $MENU_SYMBOL = '*'; $USE_ISO = 0; $ENABLE_ENCODING_USE_ENTITY = 0; $ENABLE_ENCODING = 1; @IMAGE_EXTENSIONS = ('png', 'jpg', 'txt'); $CAPTION_STYLE = 'asis'; $DEFAULT_ENCODING = 'ascii'; $HEADERS = 1; $INLINE_CONTENTS = 0; $no_paragraph_commands{'anchor'} = 1; %simple_map = %default_simple_map; %simple_map_pre = %simple_map; %simple_map_texi = %simple_map; %things_map = %default_things_map; %pre_map = %things_map; %line_command_map = ( 'dircategory' => '' ); # sc and var upcase. @simple_quoted_commands = ('cite', 'code', 'command', 'env', 'file', 'kbd', 'option', 'samp'); @asis_commands = ('asis', 'w', 'b', 'ctrl', 'i', 'math', 'sc', 't', 'r', 'slanted', 'sansserif', 'var', 'titlefont', 'verb', 'clickstyle', 'headitemfont'); @chevron_commands = ('key', 'indicateurl'); %info_default_accent_commands = (); %info_default_leaf_command = (); %style_map = (); t2h_default_copy_style_map (\%default_style_map, \%style_map); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents), keys(%accent_map)) { $info_default_accent_commands{$accent_command} = 1; $style_map{$accent_command} = { 'function' => \&info_default_accent }; } foreach my $command (keys(%style_map)) { delete $style_map{$command}->{'quote'} if (exists($style_map{$command}->{'quote'})); if (grep {$_ eq $command} @simple_quoted_commands) { delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'})); $style_map{$command}->{'begin'} = '`'; $style_map{$command}->{'end'} = "'"; next; } elsif (grep {$_ eq $command} @asis_commands) { delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'})); delete $style_map{$command}->{'begin'} if (exists($style_map{$command}->{'begin'})); delete $style_map{$command}->{'end'} if (exists($style_map{$command}->{'end'})); } if (grep {$_ eq $command} @chevron_commands) { delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'})); $style_map{$command}->{'begin'} = '<'; $style_map{$command}->{'end'} = '>'; next; } $info_default_leaf_command{$command} = 1 if ($style_map{$command}->{'type'} and $style_map{$command}->{'type'} eq 'simple_style'); } $style_map{'strong'}->{'begin'} = '*'; $style_map{'strong'}->{'end'} = '*'; $style_map{'dfn'}->{'begin'} = '"'; $style_map{'dfn'}->{'end'} = '"'; $style_map{'emph'}->{'begin'} = '_'; $style_map{'emph'}->{'end'} = '_'; foreach my $command (keys(%info_default_leaf_command)) { if (defined ($style_map{$command}->{'args'})) { $style_map{$command}->{'orig_args'} = [ @{$style_map{$command}->{'args'}} ]; } else { $style_map{$command}->{'orig_args'} = [ 'normal' ]; } $style_map{$command}->{'args'} = []; foreach my $arg (@{$style_map{$command}->{'orig_args'}}) { push @{$style_map{$command}->{'args'}}, 'keep'; } } $style_map{'uref'}->{'function'} = \&info_default_uref; $style_map{'url'}->{'function'} = \&info_default_uref; $style_map{'email'}->{'function'} = \&info_default_email; %style_map_pre = (); %style_map_texi = (); t2h_default_copy_style_map (\%style_map, \%style_map_pre); t2h_default_copy_style_map (\%style_map, \%style_map_texi); $special_list_commands{'itemize'} = {}; %info_default_indent_format_length = ('enumerate' => 2, 'itemize' => 3, 'table' => 0, 'vtable' => 0, 'ftable' => 0, ); %format_map = (); foreach my $format ('group', 'raggedright', 'cartouche') { $format_map{$format} = ''; } foreach my $menu_command('menu', 'detailmenu', 'direntry', 'menu_comment') { $complex_format_map{$menu_command} = {'begin' => '' , 'end' => ''}; } foreach my $command (keys (%complex_format_map), keys(%info_default_indent_format_length), 'quotation', 'smallquotation', 'deff_item', 'deff_itemx') { $info_default_indented_commands{$command} = 1; } foreach my $command (keys(%info_default_indented_commands), 'multitable', 'float', 'flushright', 'flushleft', 'center') { $info_default_format{$command} = 1; } # it doesn't change anything for multitable foreach my $non_indented_command('format', 'smallformat', 'menu', 'detailmenu', 'direntry', 'multitable') { $info_default_indented_commands{$non_indented_command} = 0; } $info_default_end_sentence_character = quotemeta($punctuation_characters); $info_default_after_punctuation_characters = quotemeta($after_punctuation_characters); $info_default_indent_length = 5; $info_default_index_length_to_node = 41; $info_default_listoffloat_caption_entry_length = 41; #$info_default_listoffloat_append = '...: '; $info_default_listoffloat_append = '...'; t2h_default_push_handler(\&info_default_init_accent_enable_encoding, \@command_handler_init); t2h_default_push_handler(\&info_default_init_variables, \@command_handler_init); $style = \&info_default_style; $print_page_head = \&info_default_print_page_head; $contents = \&info_default_noop; $shortcontents = \&info_default_noop; $about_body = \&info_default_noop; $print_Footnotes = \&info_default_noop; $copying_comment = \&info_default_copying_comment; $element_heading = \&info_default_element_heading; $heading = \&info_default_heading; $normal_text = \&info_default_normal_text; $paragraph = \&info_default_paragraph; $preformatted = \&info_default_preformatted; $empty_preformatted = \&info_default_preformatted; $empty_line = \&info_default_empty_line; # maybe should not be called from the main program? $print_page_foot = \&info_default_print_page_foot; $print_Top_footer = \&info_default_print_Top_footer; $print_Top = \&info_default_print_section; $print_section = \&info_default_print_section; $end_section = \&info_default_end_section; $one_section = \&info_default_one_section; $begin_format_texi = \&info_default_begin_format_texi; $begin_style_texi = \&info_default_begin_style_texi; $begin_paragraph_texi = \&info_default_begin_paragraph_texi; $simple_command = \&info_default_simple_command; $thing_command = \&info_default_thing_command; $begin_special_region = \&info_default_begin_special_region; $end_special_region = \&info_default_end_special_region; $anchor_label = \&info_default_anchor_label; $element_label = \&info_default_noop; $menu_link = \&info_default_menu_link; #$menu_command = \&info_default_menu_command; $complex_format = \&info_default_complex_format; $quotation = \&info_default_quotation; $misc_command_line = \&info_default_misc_commands; $external_ref = \&info_default_external_ref; $internal_ref = \&info_default_internal_ref; $image = \&info_default_image; $image_files = \&info_default_image_files; $index_summary = \&info_default_index_summary; $summary_letter = \&info_default_summary_letter; $index_entry = \&info_default_index_entry; $index_entry_command = \&t2h_default_index_entry_command; $index_letter = \&info_default_index_letter; $printindex = \&info_default_printindex; $print_index = \&info_default_print_index; $index_entry_label = \&info_default_index_entry_label; $foot_section = \&info_default_foot_lines; $foot_line_and_ref = \&info_default_foot_line_and_ref; $footnote_texi = \&info_default_footnote_texi; $list_item = \&info_default_list_item; $format_list_item_texi = \&info_default_format_list_item_texi; $format = \&info_default_format; $tab_item_texi = \&info_default_tab_item_texi; $acronym_like = \&info_default_acronym_like; $sp = \&info_default_sp; $paragraph_style_command = \&info_default_paragraph_style_command; $cell = \&info_default_cell; $row = \&info_default_row; $table_list = \&info_default_table_list; $def_item = \&info_default_def_item; $def = \&info_default_def; $def_line = \&info_default_def_line; $float = \&info_default_float; $listoffloats_entry = \&info_default_listoffloats_entry; $listoffloats = \&info_default_listoffloats; $colon_command = \&info_default_colon_command; $raw = \&info_default_raw; $line_command = \&info_default_line_command; $comment = \&t2h_default_comment; $unknown_style = \&info_default_unknown_style; $heading_text = \&t2h_default_heading_text; } my %info_default_state_map = (); my $info_default_out_file_nr = 1; my $info_default_dir_specification = ''; my @info_default_pending_indirect = (); my @info_default_pending_footnotes = (); my $info_default_state_nr = 0; # maximal length of index entries line number information. Each entry is # an index name. my %info_default_index_line_string_length = (); my %info_default_index_entries = (); my $info_default_footnote_index = 0; my $info_default_current_node = undef; my %info_default_command_handler_expand; sub info_default_intercept_handler { my $command = $_[0]; my $result = &{$info_default_command_handler_expand{$command}}(@_); return info_default_store_text (undef, $result, $command); } sub info_default_init_variables() { %info_default_state_map = (); $info_default_out_file_nr = 1; $info_default_dir_specification = ''; @info_default_pending_indirect = (); @info_default_pending_footnotes = (); $info_default_state_nr = 0; %info_default_index_line_string_length = (); %info_default_index_entries = (); $info_default_footnote_index = 0; $info_default_current_node = undef; $Texi2HTML::THISDOC{'SPLIT'} = 0 if ($OUTPUT_FORMAT eq 'info'); $FRAMES = 0 if ($OUTPUT_FORMAT eq 'info'); foreach my $command (keys (%command_handler)) { if ($command_handler{$command}->{'expand'}) { $info_default_command_handler_expand{$command} = $command_handler{$command}->{'expand'}; $command_handler{$command}->{'expand'} = \&info_default_intercept_handler; } } } # this is put in command_handler_init such that it sets things right # in case $ENABLE_ENCODING is set and has lead to modification of the # accent functions sub info_default_init_accent_enable_encoding() { return unless ($ENABLE_ENCODING and $USE_UNICODE); foreach my $key (keys(%unicode_accents), 'dotless') { $info_default_enable_encoding_accents{$key} = 1; $t2h_enable_encoding_default_accent{'normal'}->{$key} = \&t2h_default_accent; $t2h_enable_encoding_default_accent{'texi'}->{$key} = \&t2h_default_accent; $t2h_enable_encoding_default_accent{'pre'}->{$key} = \&t2h_default_accent; $style_map{$key}->{'function'} = \&info_default_accent; $style_map_texi{$key}->{'function'} = \&info_default_accent; $style_map_pre{$key}->{'function'} = \&info_default_accent; } } sub info_default_uref($$) { shift; my $args = shift; my $url = shift @$args; my $text = shift @$args; my $replacement = shift @$args; $url = main::normalise_space($url); $replacement = '' if (!defined($replacement)); $replacement = main::normalise_space($replacement); return $replacement if ($replacement ne ''); $text = '' if (!defined($text)); $text = main::normalise_space($text); return "`$url'" if ($text eq ''); return "$text ($url)"; } sub info_default_email($$) { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); $text = '' if (!defined($text)); $text = main::normalise_space($text); $mail = "<$mail>"; return $mail unless ($text ne ''); return "$text $mail"; } sub info_default_accent($$$) { my @args = @_; my $command = shift; my $args = shift; my $text = $args->[0]; my $style_stack = shift; my $state = shift; my $result; if ($ENABLE_ENCODING and $info_default_enable_encoding_accents{$command}) { $result = &t2h_enable_encoding_normal_accent(@args); } else { $result = &t2h_default_accent(@args); } if (scalar(@$style_stack) and $info_default_accent_commands{$style_stack->[-1]}) { # still more accents on the stack return $result; } return info_default_store_text($state,$result,'accents_commands'); } sub info_default_noop { return ''; } sub info_default_copying_comment($$$$) { my $copying_lines = shift; my $copying_text = shift; my $copying_no_texi = shift; my $copying_simple_text = shift; return '' if ($copying_text eq ''); return $copying_text; } sub info_default_byte_count($) { my $string = shift; my $out_encoding = Texi2HTML::Config::get_conf('OUT_ENCODING'); if ($out_encoding and lc($out_encoding) ne 'us-ascii' and $USE_UNICODE) { return length (Encode::encode($out_encoding, $string)); } # There is no default encoding. We assume it is us-ascii. Not sure # about what perl thinks it is... #print STDERR "Unknown encoding for: $string\n" if (!$out_encoding); return length($string); } sub info_default_count_lines($;$$) { my $text = shift; my $indent_length = shift; my $indentation_done = shift; my $blank_line; my $no_indentation = 0; if (!defined($indentation_done) or $indentation_done) { $no_indentation = 1; $indent_length = 0; } my @lines = split /^/, $text; # don't accept empty text. @lines = ('') if (!@lines); my $line_passed = scalar(@lines); $line_passed-- if ($line_passed); my $end_of_line = 0; if (($#lines > 1) and !$end_of_line and ($lines[-1] !~ /\S/) and ($lines[-2] !~ /\S/)) { $blank_line = 1; } my $last_line = $lines[-1]; my $indented_text = shift (@lines); #print STDERR "COUNT info_default_count_lines(i_done $no_indentation, i_l $indent_length) i_t `$indented_text'\n"; foreach my $line (@lines) { if ($indent_length and $line =~ /\S/) { $indented_text .= ' ' x $indent_length . $line; } else { $indented_text .= $line; } } if (chomp($text)) { $line_passed++; $end_of_line = 1; } return ($line_passed, $end_of_line, $last_line, $indented_text, $blank_line); } sub info_default_get_state($) { my $state = shift; if (!exists $info_default_state_map{$state}) { #print STDERR "NEW state $info_default_state_nr\n"; my ($current_command, $top_stack); $info_default_state_map{$state} = {}; info_default_reset_state($info_default_state_map{$state}); # since the page head always leave a blank line, and the state may be # used for text right after the page head, we set it to 1 here. # it may be wrong in other contexts, to be seen. $info_default_state_map{$state}->{'blank_line'} = 1; $info_default_state_map{$state}->{'only_spaces'} = 1; # this is the first line, so set to 1. This is reset later in # most cases, when a node is seen, but may still be useful in # @footnote, for example $info_default_state_map{$state}->{'line_count'} = 1; $info_default_state_map{$state}->{'offset_in_file'} = 0; $info_default_state_map{$state}->{'nr'} = $info_default_state_nr; $info_default_state_map{$state}->{'state'} = $state; $info_default_state_map{$state}->{'multitable_stack'} = []; @{$info_default_state_map{$state}->{'align_stack'}} = ({'command'=>'normal'}); $info_default_state_nr++; } #print STDERR "RETURN state $state $info_default_state_map{$state} $info_default_state_map{$state}->{'nr'}\n"; return $info_default_state_map{$state}; } sub info_default_reset_state($) { my $info_state = shift; $info_state->{'top'} = {}; $info_state->{'current'} = $info_state->{'top'}; } sub info_default_iterator_next($$$) { my $current_command = shift; my $command_index = shift; my $command_close = shift; #print STDERR "NNNNNNNNNNNNNN iterator_next current $current_command idx $command_index close $command_close\n"; my $sub_command = $current_command->{'content'}->[$command_index]; if ($sub_command->{'content'} and !$command_close) { return ($sub_command, 0, 0); } if ($current_command->{'content'}->[$command_index+1]) { return ($current_command, $command_index+1, 0); } elsif (defined($current_command->{'parent'})) { return ($current_command->{'parent'}, $current_command->{'index_in_parent'}, 1); } else { return (undef, undef, undef); } } # return ($current_next, $index_next, $close_next, $text, $command); # # returns the next in tree, identified by the triplet # ($current_next, $index_next, $close_next) and also the command # and/or text if defined, in $text and $command. sub info_default_next($$$) { my $current = shift; my $index = shift; my $close = shift; my $text; my $command; my ($current_next, $index_next, $close_next) = info_default_iterator_next($current, $index, $close); return ($current_next, $index_next, $close_next, $text, $command) if (!defined($current_next)); my $content = $current_next->{'content'}->[$index_next]; $command = $content->{'command'} if (defined($content->{'command'})); if ($close_next) { return ($current_next, $index_next, $close_next, $content->{'end'}, $command); } if (defined($content->{'text'})) { return ($current_next, $index_next, $close_next, $content->{'text'}, $command); } if (defined($content->{'begin'})) { $text = $content->{'begin'}; } if (defined($content->{'end'}) and !defined($content->{'content'})) { if (!defined($text)) { $text = $content->{'end'}; } else { $text .= $content->{'end'}; } } return ($current_next, $index_next, $close_next, $text, $command); } sub info_default_process_line_text($$$) { my $text = shift; my $line_width_counter = shift; my $indent_length = shift; $indent_length = 0 if (!defined($indent_length)); my $line_passed = 0; my $chomped_text = $text; my $end_of_line = chomp($chomped_text); if ($indent_length > $line_width_counter and $chomped_text ne '') { $text = ' ' x ($indent_length - $line_width_counter) . $text; } $line_width_counter += t2h_default_string_width($text); # it seems like it never happens in the tests. if ($end_of_line) { $line_passed = 1; $line_width_counter = 0; } return ($line_width_counter, $line_passed, $text); } # Beware that there is a pending word if the text doesn't end with # a space sub info_default_process_para_text($$$$$;$$) { my $text = shift; my $line_char_counter = shift; my $pending_spaces_word = shift; my $indent_length = shift; my $max_column = shift; my $keep_end_of_lines = shift; $keep_end_of_lines = 0 if (!$keep_end_of_lines); # indentation for the lines except for the first one my $indent_length_next = shift; $indent_length = 0 if (!defined($indent_length)); $indent_length_next = $indent_length if (!defined($indent_length_next)); my $line_passed = 0; my $result = ''; #print STDERR "process_text(indent($indent_length,$indent_length_next),keep_eol $keep_end_of_lines) spaces `$pending_spaces_word->{'spaces'}') line_char_counter $line_char_counter |$text|\n"; while ($text ne '') { #print STDERR "l_c_c $line_char_counter pending_word ".var_to_str($pending_spaces_word->{'word'}).", pending_spaces `$pending_spaces_word->{'spaces'}', result `$result'\n"; if (!$keep_end_of_lines and $text =~ s/^(\s+)//) { my $new_spaces = $1; # in general there are no end of lines in the lines cut, since they # are replaced by spaces in the main loop. However, it may happen # with @* in @def* lines my @lines = split /^/, $new_spaces; my $eol_spaces; # last line is in $new_spaces, other lines are in $eol_spaces if (@lines > 1) { $new_spaces = pop @lines; $eol_spaces = join ("", @lines); #print STDERR "EOL_SPACES[$line_char_counter](+$pending_spaces_word->{'spaces'}) `$eol_spaces'\n"; } if (defined($pending_spaces_word->{'word'})) { # add spaces in front if needed for the indentation if ($indent_length > $line_char_counter + t2h_default_string_width($pending_spaces_word->{'spaces'})) { $pending_spaces_word->{'spaces'} = ' ' x ($indent_length - $line_char_counter) . $pending_spaces_word->{'spaces'}; } $result .= $pending_spaces_word->{'spaces'} . $pending_spaces_word->{'word'}; $line_char_counter += t2h_default_string_width($pending_spaces_word->{'spaces'})+t2h_default_string_width($pending_spaces_word->{'word'}); $pending_spaces_word->{'spaces'} = $new_spaces; $pending_spaces_word->{'word'} = undef; } elsif (!$eol_spaces) { $pending_spaces_word->{'spaces'} .= $new_spaces; } if ($eol_spaces) { $result .= $eol_spaces; $line_passed += scalar(@lines); $indent_length = $indent_length_next; $line_char_counter = 0; $pending_spaces_word->{'spaces'} = ''; } if ((t2h_default_string_width($pending_spaces_word->{'spaces'}) + $line_char_counter > $max_column)) { $pending_spaces_word->{'spaces'} = ''; $result .= "\n"; $line_passed++; $indent_length = $indent_length_next; $line_char_counter = 0; } } else { my $word; if ($keep_end_of_lines) { $word = $text; $text = ''; } elsif ($text =~ s/^([^\s]+)//) { $word = $1; } #else #{ # die "BUG: Impossible situation.\n"; #} $pending_spaces_word->{'word'} = '' if (!defined($pending_spaces_word->{'word'})); $pending_spaces_word->{'word'} .= $word; # The $line_char_counter != 0 is here to cope with the case of a # word longer than $line_char_counter followed by more text: # a line would be passed each time some piece text is appended. if ((t2h_default_string_width($pending_spaces_word->{'spaces'})+t2h_default_string_width($pending_spaces_word->{'word'}) + $line_char_counter > $max_column) and $line_char_counter != 0) { $pending_spaces_word->{'spaces'} = ''; $result .= "\n"; $line_passed++; $indent_length = $indent_length_next; $line_char_counter = 0; } } } return ($line_char_counter, $pending_spaces_word, $line_passed, $result) } sub info_default_skip_spaces($$$) { my $current = shift; my $index = shift; my $close = shift; #print STDERR "SKIP_SPACES\n"; while(1) { my ($current_next, $index_next, $close_next) = info_default_iterator_next($current, $index, $close); return if ($close_next or (!defined($current_next))); my $content = $current_next->{'content'}->[$index_next]; if (defined($content->{'begin'})) { $content->{'begin'} =~ s/^\s*//; #print STDERR "SKIP_SPACES begin\n"; return if ($content->{'begin'} ne ''); } if (defined($content->{'content'}) or defined($content->{'format_name'}) or $content->{'definition_line'}) { # non empty commands stop space skipping, even if they contain # only spaces, like @asis{ } # also for item(x) that have format_name defined #print STDERR "SKIP_SPACES command?\n"; return; } if (defined($content->{'text'})) { my $command = ''; $command = $content->{'command'} if (defined($content->{'command'})); #print STDERR "SKIP_SPACES($command) text\n"; $content->{'text'} =~ s/^\s*//; return if ($content->{'text'} ne ''); } if (defined($content->{'end'})) { #print STDERR "SKIP_SPACES end\n"; $content->{'end'} =~ s/^\s*//; return if ($content->{'end'} ne ''); } ($current, $index, $close) = ($current_next, $index_next, $close_next); } } sub info_default_store_pending($$;$) { my $line_char_counter = shift; my $pending_spaces_word = shift; my $indent_length = shift; $indent_length = 0 if (!defined($indent_length)); my $indent_text = ''; $indent_text = ' ' x $indent_length; #print STDERR "store_pending(spaces `$pending_spaces_word->{'spaces'}', indent($indent_length) `$indent_text' word `".var_to_str($pending_spaces_word->{'word'})."'\n"; my $result = $pending_spaces_word->{'spaces'}; $pending_spaces_word->{'spaces'} = ''; if (defined($pending_spaces_word->{'word'})) { $result .= $pending_spaces_word->{'word'}; $pending_spaces_word->{'word'} = undef; } my $chomped_result = $result; chomp ($chomped_result); if ($line_char_counter == 0 and $chomped_result ne '') { $result = $indent_text . $result; } $line_char_counter += t2h_default_string_width($result); return ($line_char_counter, $pending_spaces_word, $result); } sub info_default_output($) { my $info_state = shift; my $result = ''; #print STDERR "Storing the stack\n"; print STDERR "" . Data::Dumper->Dump([$info_state->{'top'}]) if ($DEBUG); my ($bytes_count, $lines_count); ($bytes_count, $result, $lines_count) = info_default_process_content($info_state->{'top'}, $info_state); $info_state->{'offset_in_file'} += $bytes_count; $info_state->{'line_count'} += $lines_count; #print STDERR "HHHHHH($lines_count) $info_state->{'line_count'}: $result\n"; info_default_reset_state($info_state) if (!defined($info_state->{'current'}->{'command'})); return $result; } sub info_default_process_content($$) { my $current_command = shift; my $info_state = shift; my $length = 0; my $result = ''; my $line_char_counter = 0; my $all_line_passed = 0; my $pending_spaces_word; $pending_spaces_word->{'spaces'} = ''; my $preformatted = 0; my $indent_level = 0; my $item_pending; my $in_exdent = 0; my $in_para = 0; my $in_w = 0; my $table_item_line = 0; my $in_table_item = 0; my $max_column = get_conf('fillcolumn'); my $direntry = 0; my $preformatted_format = 0; my $indent_length = 0; # for formats that needs to process a full line (center and flushright) # to know the line length before outputing my $current_line = undef; my ($current, $index, $close) = ($current_command, 0, 0); #print STDERR "info_default_process_content: $current_command\n"; while(1) { last if (!defined($current)); my $content = $current->{'content'}->[$index]; my $text_added = ''; my $line_added_before_item = 0; my $indentation_done = 0; my $prepend_newline; if ($DEBUG) { my $text_item_pending = ''; $text_item_pending = $item_pending if (defined($item_pending)); my $text_length = ''; $text_length = "$content->{'text'}" if defined($content->{'text'}); my $text_command = ''; $text_command = $content->{'command'} if defined($content->{'command'}); my $in_node_count = 0; $in_node_count = $info_state->{'line_count'} if defined($info_state->{'line_count'}); print STDERR "($text_command|$text_length|$close|${all_line_passed}+$in_node_count|l_c_cnt $line_char_counter) prfrmted $preformatted para $in_para indent_lvl $indent_level($indent_length) in_exdent $in_exdent in_w $in_w only_spaces $info_state->{'only_spaces'} blank_line $info_state->{'blank_line'} table_item_line $table_item_line in_table_item $in_table_item item_pending $text_item_pending spaces: `$pending_spaces_word->{'spaces'}' word: ".main::var_to_str($pending_spaces_word->{'word'})."\n"; } if ($close) { if (defined($content->{'end'})) { $text_added .= $content->{'end'}; } if ($complex_format_map{$content->{'command'}} and $content->{'content'}) { $preformatted_format--; } # the format is always empty in the main program so the warning # has to be done here if (defined($content->{'total_item_nr'}) and !$content->{'total_item_nr'} and $content->{'content'}) { main::line_warn (sprintf(__("\@%s has text but no \@item"), $content->{'command'}), $content->{'line_nr'}); } # check whether there is a blank line following, to avoid adding # one when closing a format. # This is not a required check if not in preformatted since doubled # blank lines are discarded. my $followed_by_blank_line = 0; if ($preformatted_format) { my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close); if (defined($command_next) and $command_next eq 'preformatted') { ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next); $followed_by_blank_line = 1 if (defined($text_next) and $text_next =~ /^\s*$/); } } if ($info_default_indented_commands{$content->{'command'}}) { $indent_level--; $indent_length = $indent_level * $info_default_indent_length; # $preformatteed cannot be used here since preformatted # is closed before the end of a format #if ($indent_level > 0 and !$info_state->{'blank_line'} and $content->{'command'} !~ /^deff_item/ and !$preformatted_format) if ($indent_level > 0 and !$info_state->{'blank_line'} and $content->{'command'} !~ /^deff_item/ and !$followed_by_blank_line) { $text_added .= "\n"; } # this nullify a potential noindent in a random format $info_state->{'indent_para'} = undef; } elsif (($complex_format_map{$content->{'command'}} and $content->{'command'} ne 'menu') or $content->{'command'} eq 'cartouche') { if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level > 0) and !$followed_by_blank_line) { $text_added .= "\n"; } } if ($content->{'command'} eq 'paragraph' and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal') { # if there is no space at the end of a paragraph, there may be # pending text, for example, if there is an ending line like # Some text@c a comment my $pending; ($line_char_counter, $pending_spaces_word, $pending) = info_default_store_pending($line_char_counter, $pending_spaces_word, $indent_length); $text_added .= $pending if (defined($pending)); $text_added =~ s/\s*$//; $pending_spaces_word->{'spaces'} = ''; $in_para = 0; $info_state->{'indent_para'} = undef; $text_added .= "\n" unless (($line_char_counter + t2h_default_string_width($text_added)) == 0); } elsif ($content->{'command'} eq 'preformatted') { # if preformatted doesn't end with a newline, it is added here $text_added .= "\n" unless ($line_char_counter == 0); $preformatted--; } elsif ($content->{'command'} eq 'menu') { $text_added .= "\n" unless ($info_state->{'blank_line'}); } elsif ($content->{'command'} eq 'float') { #$text_added = "\n" . $text_added unless ($info_state->{'blank_line'}); $prepend_newline = 1 unless ($info_state->{'blank_line'}); } elsif ($content->{'command'} eq 'w') { $in_w--; } elsif ($paragraph_style{$content->{'command'}}) { my $popped = pop @{$info_state->{'align_stack'}}; print STDERR "BUG".main::format_line_number().": align_stack, popped $popped->{'command'} ne command $content->{'command'}\n" if ($popped->{'command'} ne $content->{'command'}); } elsif ($content->{'command'} eq 'multitable') { my $multitable = pop @{$info_state->{'multitable_stack'}}; if (!defined($multitable->{'cells'}) and ($result ne '')) { $multitable->{'result'} .= $result; $multitable->{'length'} += $length; $multitable->{'line_count'} += $all_line_passed; } $max_column = $multitable->{'max_column_kept'}; $result = $multitable->{'result_kept'}; $line_char_counter = $multitable->{'line_char_counter_kept'}; $all_line_passed = $multitable->{'all_line_passed_kept'}; $indent_level = $multitable->{'indent_level_kept'}; $indent_length = $multitable->{'indent_length_kept'}; #$indent_length_next_line = undef; $length = $multitable->{'length_kept'}; $info_state->{'offset_in_file'} = $multitable->{'offset_in_file_kept'}; $info_state->{'line_count'} = $multitable->{'line_count_kept'}; #print STDERR "MULTITABLE close, lines: $multitable->{'line_count_kept'} + $all_line_passed\n"; foreach my $anchor_and_index (@{$multitable->{'anchors'}}, @{$multitable->{'index_entries'}}) { $anchor_and_index->{'line_nr'} += $multitable->{'line_count_kept'} + $all_line_passed; } if (! scalar(@{$info_state->{'multitable_stack'}})) { #print STDERR "MULTITABLE close, lengths: $multitable->{'offset_in_file_kept'} + $length\n"; foreach my $anchor (@{$multitable->{'anchors'}}) { $anchor->{'info_offset'} += $multitable->{'offset_in_file_kept'} + $length; } } else { push @{$info_state->{'multitable_stack'}->[-1]->{'anchors'}}, @{$multitable->{'anchors'}}; push @{$info_state->{'multitable_stack'}->[-1]->{'index_entries'}}, @{$multitable->{'index_entries'}}; } $text_added .= $multitable->{'result'}; $indentation_done = 1; goto new_text; } elsif ($content->{'command'} eq 'multitable_cell') { my $cell = $info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1]; $cell->{'result'} = $result; $cell->{'length'} = $length; $cell->{'line_passed'} = $all_line_passed; } elsif ($content->{'command'} eq 'direntry') { $direntry--; # this has to be done here, otherwise, at the end, $direntry # would be 0 $info_default_dir_specification .= $text_added; $text_added = ''; } elsif ($content->{'command'} eq 'multitable_row') { my $multitable = $info_state->{'multitable_stack'}->[-1]; my $indent_len = $multitable->{'indent_length_kept'}; #print STDERR "INDENT: $indent_len\n"; my $row_length = 0; my $row = ''; my $max_lines = 0; my $cell_beginning = 0; my @anchor_lines_array; my $cell_idx = 0; my @anchors; my @indices; foreach my $cell (@{$multitable->{'cells'}}) { $cell->{'beginning'} = $cell_beginning; $cell_beginning += $cell->{'cell_width'}+1; @{$cell->{'lines'}} = split /^/, $cell->{'result'}; $max_lines = scalar(@{$cell->{'lines'}}) if (scalar(@{$cell->{'lines'}}) > $max_lines); foreach my $anchor (@{$cell->{'anchors'}}) { push @{$anchor_lines_array[$anchor->{'line_nr'}]}, $anchor; $anchor->{'cell_idx'} = $cell_idx; push @anchors, $anchor; } push @indices, @{$cell->{'index_entries'}}; $cell_idx++; } my $previous_last_cell = scalar(@{$multitable->{'cells'}}); #print STDERR "ROW cell_beginning $cell_beginning, max_lines $max_lines, previous_last_cell $previous_last_cell\n"; for (my $line_idx = 0; $line_idx < $max_lines; $line_idx++) { my $line_width = $indent_len; my $line_bytes = info_default_byte_count(' ' x$indent_len); my $line = ''; # determine the last cell in the line, to fill spaces in # cells preceding that cell on the line my $last_cell = 0; for (my $cell_idx = 0; $cell_idx < $previous_last_cell; $cell_idx++) { $last_cell = $cell_idx+1 if (defined($multitable->{'cells'}->[$cell_idx]->{'lines'}->[$line_idx])); } #print STDERR " L(last_cell $last_cell): $line_idx\n"; for (my $cell_idx = 0; $cell_idx < $last_cell; $cell_idx++) { my $cell_text = $multitable->{'cells'}->[$cell_idx]->{'lines'}->[$line_idx]; #print STDERR " C($cell_idx) "; if (defined($cell_text)) { chomp($cell_text); #print STDERR "$cell_text"; if ($line eq '' and $cell_text ne '') { $line = ' ' x $indent_len; } $line .= $cell_text; $line_width += t2h_default_string_width($cell_text); $line_bytes += info_default_byte_count($cell_text); } if ($cell_idx+1 < $last_cell) { if ($line_width < $indent_len + $multitable->{'cells'}->[$cell_idx+1]->{'beginning'}) { if ($line eq '') { $line = ' ' x $indent_len; } my $spaces = ' ' x ($indent_len + $multitable->{'cells'}->[$cell_idx+1]->{'beginning'} - $line_width); $line_width += t2h_default_string_width($spaces); $line_bytes += info_default_byte_count($spaces); $line .= $spaces; #print STDERR " Csp($line_width) `$spaces'"; } } } if (defined($anchor_lines_array[$line_idx])) { foreach my $anchor (@{$anchor_lines_array[$line_idx]}) { my $anchor_position = $indent_len + $anchor->{'line_char_counter'} + $multitable->{'cells'}->[$anchor->{'cell_idx'}]->{'beginning'}; if ($anchor_position > $line_width) { my $spaces = ' ' x ($anchor_position - $line_width); $line .= $spaces; $line_width += t2h_default_string_width($spaces); $line_bytes += info_default_byte_count($spaces); } $anchor->{'info_offset'} = $line_bytes + $row_length + $multitable->{'length'}; #print STDERR "ROW anchor close: anchor[$anchor->{'cell_idx'}]($multitable->{'cells'}->[$anchor->{'cell_idx'}]->{'beginning'}+$anchor->{'line_char_counter'}) $anchor_position $anchor->{'info_offset'}\n"; $anchor->{'line_char_counter'} = $anchor_position; } } $line .= "\n"; $row_length += info_default_byte_count($line); #print STDERR " ($line_width,".length($line).") $line"; $row .= $line; $previous_last_cell = $last_cell; } foreach my $anchor_and_index (@anchors, @indices) { $anchor_and_index->{'line_nr'} += $multitable->{'line_count'}; #print STDERR "ROW close: new line count: $anchor_and_index->{'line_nr'} + \n"; } if ($content->{'item_command'} eq 'headitem') { # at this point cell_beginning is at the beginning of # the cell following the end of the table -> full width my $line = ' ' x $indent_len . '-' x $cell_beginning . "\n"; $row .= $line; $row_length += info_default_byte_count($line); } #print STDERR "ROW_LENGTH $row_length\n"; $multitable->{'result'} .= $row; $multitable->{'length'} += $row_length; $multitable->{'line_count'} += $max_lines; $multitable->{'cells'} = []; push @{$multitable->{'anchors'}}, @anchors; push @{$multitable->{'index_entries'}}, @indices; } } else { if ($content->{'command'}) { # if processing a paragraph, there may be some pending text # and spaces, as the idea is to write them down only when # there is a space in case of pending text, or when there is some # text in case of pending space. So all the commands # that should write something within paragraph must flush the # pending text/spaces _before_ they output something, or the # text order will be reversed, with the pending things output # after the other commands text. my $pending_added_length = 0; my $pending_added_bytes = 0; if ($content->{'command'} eq 'anchor' or $content->{'command'} eq 'image' or $content->{'command'} eq 'index_command' or $content->{'command'} eq 'sp' or $content->{'raw_command'}) { my $pending; ($line_char_counter, $pending_spaces_word, $pending) = info_default_store_pending($line_char_counter, $pending_spaces_word, $indent_length); # here spaces out of any environment are ignored. if ($in_para or $preformatted or $pending =~ /\S/) { # this has to be done before the anchor related code # to have the right count. # FIXME this is wrong if an end of line was passed. # in that case line_char_counter has been increased and # $pending ends with an end of line $pending_added_length += t2h_default_string_width($pending); $pending_added_bytes += info_default_byte_count($pending); $text_added .= $pending; } } if ($content->{'command'} eq 'strong') { my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close); if (defined($text_next) and $text_next =~ /^Note\b/i) { main::line_warn(__("\@strong{Note...} produces a spurious cross-reference in Info; reword to avoid that"), $content->{'line_nr'}); } } elsif ($content->{'command'} eq 'w') { $in_w++ if ($content->{'content'}); } elsif ($content->{'command'} eq 'anchor' or ($content->{'command'} eq 'float' and $content->{'anchor_reference'})) { #print STDERR "anchor: offset_in_file $info_state->{'offset_in_file'}, line_count $info_state->{'line_count'}, line_char_counter $line_char_counter pending_added_length $pending_added_length\n"; $content->{'anchor_reference'}->{'info_offset'} = $length + $info_state->{'offset_in_file'} + $pending_added_bytes; $content->{'anchor_reference'}->{'line_nr'} = $all_line_passed + $info_state->{'line_count'}; $content->{'anchor_reference'}->{'line_char_counter'} = $line_char_counter + $pending_added_length; if (@{$info_state->{'multitable_stack'}}) { if ($info_state->{'multitable_stack'}->[-1]->{'cells'}) { push @{$info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1]->{'anchors'}}, $content->{'anchor_reference'}; } else { push @{$info_state->{'multitable_stack'}->[-1]->{'anchors'}}, $content->{'anchor_reference'}; } } push @{$info_state->{'pending_tags'}}, $content->{'anchor_reference'}; push @{$info_state->{'align_stack'}->[-1]->{'anchors'}}, $content->{'anchor_reference'} if ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center' or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright'); } elsif ($content->{'command'} eq 'index_label') { #print STDERR "FFFFFFFFF($content->{'index_command'}) $all_line_passed + $info_state->{'line_count'} `$content->{'texi_entry'}'\n"; my $index_line_nr = $all_line_passed + $info_state->{'line_count'}; if ($info_state->{'blank_line'} and $content->{'index_command'} =~ /index$/) { my ($current_next, $index_next, $close_nex) = info_default_iterator_next($current, $index, $close); $index_line_nr-- if (!defined($current_next)); } elsif ($content->{'index_command'} =~ /^[vf]table$/) { # if in a table, index label is systematically entered after # the line is processed, as the line is processed with the # item command, while the index entry is entered with the # index_label callback that is done much later. $index_line_nr--; } #print STDERR "index in a blank_line $content->{'index_command'} `$content->{'texi_entry'}'\n" if ($info_state->{'blank_line'}); my $index_name = $content->{'index_entry_reference'}->{'index_name'}; $info_default_index_line_string_length{$index_name} = t2h_default_string_width($index_line_nr) if (!defined($info_default_index_line_string_length{$index_name}) or $info_default_index_line_string_length{$index_name} < t2h_default_string_width($index_line_nr)); #print STDERR "RRRRRRRRRRRRR($content->{'index_entry_reference'}) $content->{'index_entry_reference'}->{'texi'} name: $index_name line: $index_line_nr max: $info_default_index_line_string_length{$index_name}\n"; my $index_ref = { 'index_entry_reference' => $content->{'index_entry_reference'}, 'line_nr' => $index_line_nr }; #print STDERR "INDEX($index_name) line $index_line_nr\n"; $info_default_index_entries{$content->{'index_entry_reference'}} = $index_ref; # there may be no cell in case of an empty multitable if (@{$info_state->{'multitable_stack'}}) { if ($info_state->{'multitable_stack'}->[-1]->{'cells'}) { push @{$info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1]->{'index_entries'}}, $index_ref; } else { push @{$info_state->{'multitable_stack'}->[-1]->{'index_entries'}}, $index_ref; } } push @{$info_state->{'pending_index_entries'}}, $index_ref; } elsif ($content->{'command'} eq '*' and !$preformatted) { if (defined($pending_spaces_word->{'word'})) { $text_added .= $pending_spaces_word->{'spaces'} . $pending_spaces_word->{'word'}; $pending_spaces_word->{'word'} = undef; } # spaces preceding @* are skipped $pending_spaces_word->{'spaces'} = ''; $text_added .= $content->{'text'}; # just like following spaces info_default_skip_spaces($current, $index, $close); # this isn't done otherwise, though, here it is not important # since this end the line $line_char_counter += t2h_default_string_width($content->{'text'}); goto new_text; } elsif ($content->{'command'} eq 'paragraph' and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal') { # empty paragraph goto new_text if (!$content->{'content'}); my $paragraphindent = get_conf('paragraphindent'); $paragraphindent = 0 if ($paragraphindent eq 'none'); if ($paragraphindent ne 'asis') { info_default_skip_spaces($current, $index, $close); } # if within a format $content->{'paragraph_in_element_nr'} # should not be defined so no indentation will take place if ($paragraphindent ne 'asis' and $paragraphindent and $line_char_counter == 0 and (defined($content->{'paragraph_in_element_nr'})) and ($info_state->{'indent_para'} or (!defined($info_state->{'indent_para'}) and ($content->{'paragraph_in_element_nr'} or (get_conf('firstparagraphindent') eq 'insert'))))) { $text_added .= ' ' x $paragraphindent; } $in_para = 1; } elsif ($content->{'command'} eq 'preformatted') { $preformatted++ if ($content->{'content'}); } elsif ($content->{'command'} eq 'exdent') { # if an end of line is added, in_exdent is set to 2 and # set to one when processing the end of line that was just # added, and set to 0 at the end of the line. # if there is no end of line added, it is only set to 1. if ($line_char_counter != 0) { $text_added .= "\n"; $in_exdent = 2; } else { $in_exdent = 1; } $indent_length = ($indent_level -1) * $info_default_indent_length if ($indent_level > 0); #goto new_text; } elsif ($content->{'command'} eq 'indent') { $info_state->{'indent_para'} = 1; } elsif ($content->{'command'} eq 'noindent') { $info_state->{'indent_para'} = 0; } elsif ($content->{'command'} eq 'sp') { $text_added .= $content->{'text'}; goto new_text; } elsif ($content->{'command'} eq 'image') { # @image result count isn't counted in line_char_counter # since it is not displayed in info my $indent_added = 0; $indent_added = ($indent_length - $line_char_counter) if ($indent_length - $line_char_counter > 0); $text_added .= ' ' x $indent_added . $content->{'text'}; $line_char_counter += $indent_added; goto new_text; } elsif ($content->{'command'} eq 'ref') { # adds a . if needed. if ($content->{'text'} !~ /[\.,]$/ and $content->{'text'} !~ /::$/) { my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close); if (!defined($text_next) or $text_next !~ /^[\.,]/) { $content->{'text'} .= '.'; } } } elsif ($content->{'command'} eq 'xref') { # warn if there is no punctuation following my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close); if (!defined($text_next) or $text_next !~ /^./) { # in makeinfo it is # "End of file reached while looking for `.' or `,'" # but maybe it may not be true. main::line_warn(__("`.' or `,' must follow \@xref."), $Texi2HTML::THISDOC{'line_nr'}); } elsif ($text_next !~ /^[\.,]/) { my $char = substr($text_next, 0, 1); main::line_warn(sprintf(__("`.' or `,' must follow \@xref, not %s"), $char), $Texi2HTML::THISDOC{'line_nr'}); } } elsif ($content->{'definition_line'}) { my $dummy_line_passed; print STDERR "BUG: defined pending_word before DEFINITION_LINE\n" if defined($pending_spaces_word->{'word'}); #print STDERR "DEFINITION_LINE($line_char_counter,$pending_spaces_word->{'spaces'},$indent_length,$in_para,$max_column): $content->{'text'}"; ($line_char_counter, $pending_spaces_word, $dummy_line_passed, $text_added) = info_default_process_para_text($content->{'text'}, $line_char_counter, $pending_spaces_word, $indent_length, $max_column, 0, $indent_length+2*$info_default_indent_length); $text_added .= $pending_spaces_word->{'spaces'}; $pending_spaces_word->{'spaces'} = ''; #print STDERR "DEFINITION_LINE($line_char_counter,$pending_spaces_word->{'spaces'}) -> $text_added"; print STDERR "BUG: defined pending_word after DEFINITION_LINE\n" if defined($pending_spaces_word->{'word'}); $indentation_done = 1; goto new_text; } elsif (($content->{'command'} eq 'item' or $content->{'command'} eq 'itemx') and exists $info_default_indent_format_length{$content->{'format_name'}}) { $item_pending = $content->{'format_name'}; #if (!$info_state->{'blank_line'} and $content->{'command'} eq 'item') my $first_item = 0; if ($content->{'command'} eq 'item') { if (!defined($content->{'parent'}->{'item_nr'})) { $content->{'parent'}->{'item_nr'} = 1; $first_item = 1; } else { $content->{'parent'}->{'item_nr'}++; } } if ($item_pending =~ /table$/) { $table_item_line = 1; $indent_length = ($indent_level -1) * $info_default_indent_length if ($indent_level > 0); $in_table_item = 0; } else { $indent_length = ($info_default_indent_format_length{$item_pending} +($indent_level -1)* $info_default_indent_length); } if (!$info_state->{'blank_line'} and ($content->{'command'} ne 'itemx') and (!$first_item or $indent_level > 1)) { my $dummy_line_passed; ($line_char_counter, $dummy_line_passed, $text_added) = info_default_process_line_text($text_added, $line_char_counter, $indent_length); $indentation_done = 1; $line_added_before_item = 1; $prepend_newline = 1; #$text_added = "\n" . $text_added; } if ($item_pending =~ /table$/) { # one less indentation level and no line break # adding line_added_before_item allows the table_item_line to # still be active after the additional blank line $table_item_line = 1+$line_added_before_item; } else { info_default_skip_spaces($current, $index, $close); } } elsif ($content->{'command'} eq 'menu' or $content->{'command'} eq 'listoffloats' or $content->{'heading_command'}) { $text_added .= "\n" unless ($info_state->{'blank_line'}); } elsif ($content->{'command'} eq 'direntry') { if ($content->{'content'}) { $direntry++; } } elsif ($paragraph_style{$content->{'command'}}) { goto new_text if (!$content->{'content'}); push @{$info_state->{'align_stack'}}, {'command' => $content->{'command'}}; } elsif ($content->{'command'} eq 'verbatim' or $content->{'command'} eq 'verbatiminclude') { # $preformatted cannot be used here since preformatted # is closed before a verbatim, $preformatted_format is used if (!$preformatted_format and $indent_level != 0) { if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'}) { $text_added .= "\n"; } my $verb_text = $content->{'text'}; my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($verb_text); $content->{'text'} .= "\n" unless ($blank_line or ($last_line =~ /^\s*$/)); } } # other raw commands elsif ($content->{'raw_command'}) { # not considered as in a paragraph even if in a paragraph $text_added .= $content->{'text'}; goto new_text; } elsif ($content->{'command'} eq 'multitable' and $content->{'content'}) { my $indent_length_kept = $indent_level * $info_default_indent_length; my $multitable = { 'offset_in_file_kept' => $info_state->{'offset_in_file'}, 'line_count_kept' => $info_state->{'line_count'}, 'columns_size' => [ @{$content->{'columns_size'}} ], 'result' => '', 'length' => 0, 'line_count' => 0, 'result_kept' => $result, 'length_kept' => $length, 'all_line_passed_kept' => $all_line_passed, 'line_char_counter_kept' => $line_char_counter, 'max_column_kept' => $max_column, 'indent_level_kept' => $indent_level, 'indent_length_kept' => $indent_length_kept, }; push @{$info_state->{'multitable_stack'}}, $multitable; $info_state->{'offset_in_file'} = 0; $info_state->{'line_count'} = 0; $result = ''; $length = 0; $all_line_passed = 0; $line_char_counter = 0; $indent_level = 0; $indent_length = 0; } elsif ($content->{'command'} eq 'multitable_row') { my $multitable = $info_state->{'multitable_stack'}->[-1]; if (!defined($multitable->{'cells'}) and ($result ne '')) { $multitable->{'result'} .= $result; $multitable->{'length'} += $length; $multitable->{'line_count'} += $all_line_passed; $multitable->{'cells'} = []; } $multitable->{'cell_index'} = -1; } elsif ($content->{'command'} eq 'multitable_cell') { my $multitable = $info_state->{'multitable_stack'}->[-1]; $multitable->{'cell_index'}++; my $cell_width = $content->{'parent'}->{'parent'}->{'columns_size'}->[$multitable->{'cell_index'}]; #$max_column = $cell_width-1; $max_column = $cell_width -2; my $cell = {'cell_width' => $cell_width, 'index_entries' => [], 'anchors' => []}; push @{$multitable->{'cells'}}, $cell; $result = ''; $length = 0; $all_line_passed = 0; $line_char_counter = 0; $indent_level = 0; $indent_length = 0; if (!$content->{'content'}) {# empty cell $cell->{'result'} = $result; $cell->{'length'} = $length; $cell->{'line_passed'} = $all_line_passed; } #info_default_skip_spaces($current, $index, $close); } if ($info_default_indented_commands{$content->{'command'}}) { if ($content->{'command'} =~ /^deff_item/) { info_default_skip_spaces($current, $index, $close); } #elsif (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0) and !$preformatted) elsif (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0)) { $text_added .= "\n"; } # there is no close if !$content->{'content'} $indent_level++ if ($content->{'content'}); $indent_length = $indent_level * $info_default_indent_length; } elsif (($complex_format_map{$content->{'command'}} and $content->{'command'} ne 'menu') or $content->{'command'} eq 'cartouche') { #if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0) and !$preformatted_format) if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0)) { $text_added .= "\n"; } } if ($complex_format_map{$content->{'command'}} and $content->{'content'}) { $preformatted_format++; } } if (defined($content->{'text'})) { if ($in_para and !$in_exdent) { #print STDERR "IN_PARA text\n"; my $new_text = $content->{'text'}; # first find if in a context of no puncutation related # modification: code style command or @var, @cite, @math # acceptable for punctuation related modifications: # asis b dfn emph i slanted sansserif r sc strong t w my $current_tested = $content; my $no_punctation_munging_command; while ($current_tested) { if (defined($current_tested->{'command'}) and (($style_map{$current_tested->{'command'}} and $style_map{$current_tested->{'command'}}->{'args'} and $style_map{$current_tested->{'command'}}->{'args'}->[0] and $style_map{$current_tested->{'command'}}->{'args'}->[0] eq 'code') or $current_tested->{'command'} eq 'var' or $current_tested->{'command'} eq 'cite' or $current_tested->{'command'} eq 'math')) { $no_punctation_munging_command = 1; last; } $current_tested = $current_tested->{'parent'}; } # a punctuation at the end of line in a command is treated # like a punctuation in plain text, except for @:, # accent commands, @dots, 'simple_style' command, and if in # a command as found out just above. if (!$no_punctation_munging_command and (!defined($content->{'command'}) or ($content->{'command'} ne ':' and $content->{'command'} ne 'accents_commands' and $content->{'command'} ne 'dots') and !$info_default_leaf_command{$content->{'command'}}) and get_conf('frenchspacing') ne 'on' and $new_text =~ /([$info_default_end_sentence_character])([$info_default_after_punctuation_characters]*)(\s*)$/) { my $spaces = $3; if (chomp($new_text)) { $new_text =~ s/(\s*)$/ /; } else { # these variables hold the place where the end # of line characters are normalized. my ($current_start_from, $index_start_from, $close_start_from) = ($current, $index, $close); my $only_after_punctuation_characters = 1; my $spaces_to_normalize = 0; # first find whether there are only # after_punctuation_characters followed by spaces # and find the place where the # after_punctuation_characters end my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close); # go through the text as long as there are after_punctuation_characters if (!$spaces) { while (1) { # !defined($text_next) catches many special # commands, like anchor, index. Not sure if # it is right or wrong. # Also a style_map command never stops # the search, so that @emph{ or @strong{ # begin and end are not taken into account if (!defined($current_next) or (!defined($text_next)) or (defined($command_next) and $command_next eq '*') or ($text_next !~ /^[$info_default_after_punctuation_characters]*(\s*)$/ and (!defined($command_next) or !$style_map{$command_next}))) { $only_after_punctuation_characters = 0; last; } my $text_next_kept = $text_next; # begin normalizing spaces at the last place # where there are after_punctuation_characters $current_start_from = $current_next; $index_start_from = $index_next; $index_start_from = $index_next; ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next); if ($text_next_kept =~ /^[$info_default_after_punctuation_characters]*\s+$/) { if (chomp($text_next_kept)) { $spaces_to_normalize = 1; } last; } } } # check if there are only spaces until end of line if ($only_after_punctuation_characters and !$spaces_to_normalize) { while (1) { # !defined($text_next) catches many special # commands, like anchor, index. Not sure if # it is right or wrong. last if (!defined($current_next) or (!defined($text_next)) or (defined($command_next) and $command_next eq '*')); if ($text_next =~ /\S/ and (!defined($command_next) or !$style_map{$command_next})) { last; } else { if (chomp($text_next)) { $spaces_to_normalize = 1; last; } } ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next); } } if ($spaces_to_normalize) { # now do the spaces normalization info_default_skip_spaces($current_start_from, $index_start_from, $close_start_from); my $content = $current_start_from->{'content'}->[$index_start_from]; $content->{'text'} =~ s/(\s*)$/ /; } } } elsif (chomp($new_text)) { $new_text =~ s/(\s*)$/ /; } $text_added .= $new_text; } # ignore spaces outside of paragraphs and preformatted elsif ($preformatted or $info_state->{'align_stack'}->[-1]->{'command'} ne 'normal') { #print STDERR "IN_PREFORMATTED or ALIGN text\n"; $text_added .= $content->{'text'}; } else { my $chomped_text = $content->{'text'}; if ($chomped_text !~ /\S/ and chomp($chomped_text) and !$item_pending) { if ($in_table_item and $info_state->{'only_spaces'}) { # in a blank_line #print STDERR "IN_ITEM ignored: `$content->{'text'}'\n"; } elsif (!$info_state->{'blank_line'} or !$info_state->{'only_spaces'}) { #print STDERR "IN_ADDING_BLANK_LINE because no line before or text before\n"; $text_added .= "\n"; } else { #print STDERR "IN_NOT_ADDING_BLANK_LINE\n"; } } else { # exdent, item not in paragraph nor in preformatted #print STDERR "NOWHERE and not end of line (or item_pending) `$content->{'text'}'\n"; $text_added .= $content->{'text'}; } } } else { if (defined($content->{'begin'})) { $text_added .= $content->{'begin'}; } # command that won't be closed, so the end has to be added # here. It should mostly happen for empty style @-commands. if (defined($content->{'end'}) and !defined($content->{'content'})) { $text_added .= $content->{'end'}; } } } if (!$preformatted and !$in_exdent and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal' and $in_para) { # the line_passed returned here are not used, since they are computed # below. $indentation_done = 1; my $dummy_line_passed; ($line_char_counter, $pending_spaces_word, $dummy_line_passed, $text_added) = info_default_process_para_text($text_added, $line_char_counter, $pending_spaces_word, $indent_length, $max_column, $in_w, $indent_level * $info_default_indent_length) if ($text_added ne ''); } elsif ($info_state->{'align_stack'}->[-1]->{'command'} ne 'center' and $info_state->{'align_stack'}->[-1]->{'command'} ne 'flushright') { my $dummy_line_passed; ($line_char_counter, $dummy_line_passed, $text_added) = info_default_process_line_text($text_added, $line_char_counter, $indent_length); #$indentation_done = 1; } else { $line_char_counter += t2h_default_string_width($text_added); } new_text: if ($text_added ne '') { if ($item_pending and !$line_added_before_item) { #info_default_skip_spaces($current, $index, $close); $item_pending = undef; } } if ($text_added =~ /\S/) { $in_table_item = 0 if ($in_table_item); $info_state->{'blank_line'} = 0; } $text_added = "\n" . $text_added if ($prepend_newline); print STDERR "TEXT_ADDED($indent_length) `$text_added'\n" if ($text_added ne '' and $DEBUG); #print STDERR "TEXT_ADDED($indent_length) `$text_added'\n"; # from here, the next cmmand is available ($current, $index, $close) = info_default_iterator_next($current, $index, $close); my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($text_added, $indent_length, ($indentation_done or $info_state->{'align_stack'}->[-1]->{'command'} eq 'center' or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright')); $info_state->{'blank_line'} = 1 if ($blank_line); print STDERR "ADDING `$text_indented'\n" if ($text_indented ne '' and $DEBUG); # only_space is set in all the conditionals if ($end_of_line) { $line_char_counter = 0; if ($in_exdent) { $in_exdent--; } if ($table_item_line) { $table_item_line--; $in_table_item = 1; } if (!$table_item_line and !$in_exdent and !$item_pending) { $indent_length = $indent_level * $info_default_indent_length; } $info_state->{'blank_line'} = 1 if ($info_state->{'only_spaces'} and ($last_line !~ /\S/)); $info_state->{'only_spaces'} = 1; } else { if ($line_passed) {# in that case we added more than one line, the $line_char_counter # is reset to the last line length. $line_char_counter = t2h_default_string_width($last_line); $in_exdent = 0; $indent_length = $indent_level * $info_default_indent_length; if ($last_line !~ /\S/) { $info_state->{'only_spaces'} = 1; } else { $info_state->{'only_spaces'} = 0; } } else { $info_state->{'only_spaces'} = 0 if ($last_line =~ /\S/); } } if ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center' or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright') { if (defined($current_line)) { $text_added = $current_line . $text_added; } $text_indented = ''; $current_line = undef; my $spaces_prepended = undef; foreach my $line (split /^/, $text_added) { my $chomped_line = $line; if (chomp($chomped_line)) { $line =~ s/^\s*//; $line =~ s/\s*$//; if (t2h_default_string_width($line) eq 0) { $spaces_prepended = 0; $text_indented .= "\n"; } else { my $line_width = t2h_default_string_width($line); if ($line_width > $max_column) { $spaces_prepended = 0; } elsif ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center') { $spaces_prepended = (($max_column -1 - $line_width) /2); } else { $spaces_prepended = ($max_column -1 - $line_width); } $text_indented .= ' ' x$spaces_prepended . $line ."\n"; } } else { $current_line = $line; } } if (defined ($spaces_prepended) and defined($info_state->{'align_stack'}->[-1]->{'anchors'})) { while (@{$info_state->{'align_stack'}->[-1]->{'anchors'}}) { my $anchor = shift @{$info_state->{'align_stack'}->[-1]->{'anchors'}}; $anchor->{'info_offset'} += info_default_byte_count(' ' x$spaces_prepended); } } } if ($direntry) { $info_default_dir_specification .= $text_indented; } else { $result .= $text_indented; $length += info_default_byte_count($text_indented); $all_line_passed += $line_passed; } } return ($length, $result, $all_line_passed); } sub info_default_open_command($$;$) { my $state = shift; my $command = shift; my $additional_entries = shift; my $index = 0; my $info_state = info_default_get_state($state); # index in the parent content list $index = scalar(@{$info_state->{'current'}->{'content'}}) if (defined($info_state->{'current'}->{'content'})); my $new_command = {'command' => $command, 'parent' => $info_state->{'current'}, 'index_in_parent' => $index }; if (defined($additional_entries)) { foreach my $key (keys(%$additional_entries)) { $new_command->{$key} = $additional_entries->{$key}; } } push @{$info_state->{'current'}->{'content'}}, $new_command; $info_state->{'current'} = $new_command; print STDERR "TREE($info_state->{'nr'}): Opened $command\n" if ($DEBUG); } sub info_default_close_command($$;$$$) { my $state = shift; my $command = shift; my $begin = shift; my $end = shift; my $command_entries = shift; $state = $Texi2HTML::THISDOC{'state'} if (!defined($state)); my $info_state = info_default_get_state($state); print STDERR "TREE($info_state->{'nr'}): Closing $command\n" if ($DEBUG); if (!defined($info_state->{'current'})) { print STDERR "info_state->{'current'} not defined (closing $command)\n"; } elsif (!defined($info_state->{'current'}->{'command'})) { print STDERR "info_state->{'current'}->{'command'} not defined (closing $command)\n"; } elsif ($command ne $info_state->{'current'}->{'command'}) { print STDERR "Was waiting for $info_state->{'current'}->{'command'} (closing $command)\n"; } #return if $no_close; $command_entries->{'begin'} = $begin; $command_entries->{'end'} = $end; $command_entries->{'line_nr'} = $Texi2HTML::THISDOC{'line_nr'}; foreach my $key (keys(%$command_entries)) { $info_state->{'current'}->{$key} = $command_entries->{$key} if (defined($command_entries->{$key})); } $info_state->{'current'} = $info_state->{'current'}->{'parent'}; return info_default_output($info_state) if (!defined($info_state->{'current'}->{'command'})); return ''; } sub info_default_store_text($$;$$) { my $state = shift; my $text = shift; my $command = shift; my $text_entries = shift; $state = $Texi2HTML::THISDOC{'state'} if (!defined($state)); my $info_state = info_default_get_state($state); return '' if ((!defined($text) or $text eq '') and !defined($command)); ################################## debug my $command_text = ''; $command_text = "\[$command\]" if (defined($command)); $command_text .= $text if (defined($text)); print STDERR "TREE($info_state->{'nr'}) Storing: ${command_text}\n" if ($DEBUG); ################################## end debug $text_entries->{'text'} = $text if (defined($text)); $text_entries->{'command'} = $command if (defined($command)); $text_entries->{'parent'} = $info_state->{'current'}; $text_entries->{'line_nr'} = $Texi2HTML::THISDOC{'line_nr'}; push @{$info_state->{'current'}->{'content'}}, $text_entries; return info_default_output($info_state) if (!defined($info_state->{'current'}->{'command'})); return ''; } sub info_default_increment_paragraph ($$$;$) { my $in_format = shift; my $parent_format = shift; my $info_state = shift; my $command = shift; if ($in_format) { $parent_format->{'paragraph_in_format_nr'} = 0 if (!defined($parent_format->{'paragraph_in_format_nr'})); $parent_format->{'paragraph_in_format_nr'}++; } else { $info_state->{'paragraph_in_element_nr'}++; } ####################### debug $command = 'PARA' if (!defined($command)); if (0) #if (1) { my $format_info = ''; if ($in_format) { $format_info = "format: [$parent_format->{'command'}],$parent_format->{'paragraph_in_format_nr'}" } print STDERR "INCREMENT_PARA($command) $info_state->{'paragraph_in_element_nr'} $format_info\n"; } ####################### end debug } sub info_default_begin_format_texi($$$) { my $command = shift; my $line = shift; my $state = shift; my $info_state = info_default_get_state ($state); my ($parent_format, $in_format); ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'}); info_default_increment_paragraph ($in_format, $parent_format, $info_state, $command); # remove space in front of center, unless it removes the end of line! $line =~ s/^\s*// if ($command eq 'center' and $line =~ /\S/); # don't open a format if it is a @def*x command and we are already in the # corresponding @def* command info_default_open_command($state,$command) unless ($def_map{$command} and $command =~ /x$/ and defined($info_state->{'current'}->{'command'}) and "$info_state->{'current'}->{'command'}x" eq $command); return $line; } sub info_default_begin_style_texi($$$$$) { my $command = shift; my $state = shift; my $stack = shift; my $real_style_command = shift; my $remove_texi = shift; info_default_open_command($state,$command) unless ($info_default_accent_commands{$command} or exists $things_map{$command} or $command =~ /^special_(\w+)_(\d+)$/); # if ($real_style_command); } sub info_default_begin_paragraph_texi($$$) { my $command = shift; my $paragraph_macros = shift; my $paragraph_command = shift; #print STDERR "begin_paragraph $command\n"; my $state = shift; my $stack = shift; info_default_open_command($state,$command); foreach my $style_command (@$paragraph_macros) { #print STDERR "para stack: $style_command->{'style'}\n"; info_default_open_command($state,$style_command->{'style'}); } } sub info_default_simple_command($$$$$) { my $command = shift; my $in_preformatted = shift; my $in_math = shift; my $line_nr = shift; my $state = shift; my $result = $simple_map{$command}; $result = $simple_map_math{$command} if ($in_math and defined($simple_map_math{$command})); # discards '-' '|' '/' and ':'. If ':' is associated with a punctuation # character it is added to the tree in info_default_colon_command return info_default_store_text($state,$result,$command) if ($result ne ''); return ''; } sub info_default_colon_command($) { my $punctuation_character = shift; if (defined($colon_command_punctuation_characters{$punctuation_character}) and $punctuation_character =~ /^[$punctuation_characters]$/) { return info_default_store_text(undef,$colon_command_punctuation_characters{$punctuation_character}, ':'); } else { return info_default_store_text(undef,$punctuation_character); } } sub info_default_thing_command($$$$$$) { my $command = shift; my $text = shift; my $in_preformatted = shift; my $in_math = shift; my $line_nr = shift; my $state = shift; my $result = $things_map{$command}; #return info_default_close_command($state, $command, $result, $text, ''); return info_default_store_text($state, $result, $command); # return $result . $text; } sub info_default_style($$$$$$$$$$) { my $style = shift; my $command = shift; my $text = shift; my $args = shift; my $no_close = shift; my $no_open = shift; my $line_nr = shift; my $state = shift; my $command_stack = shift; my $kept_line_nrs = shift; my $begin = ''; my $end = ''; # note that the $text is always discarded for closed commands # the formatting is done right here, and the result is entered as text below. if ($info_default_leaf_command{$command}) { my $style_index = 0; my @formatted_args = (); foreach my $arg (@$args) { # we don't use style, since we only set 'orig_args' in style_map # and not in style_map_pre. my $arg_style = $style_map{$command}->{'orig_args'}->[$style_index]; my $new_state = main::duplicate_formatting_state($state); if ($arg_style eq 'normal') { push @formatted_args, main::substitute_line($arg, "\@$command", $new_state); } elsif ($arg_style eq 'code') { $new_state->{'code_style'} = 1; push @formatted_args, main::substitute_line($arg, "\@$command", $new_state); } else { print STDERR "Unknown arg style($style_index) $arg_style for $command, $state->{'remove_texi'}\n"; } $style_index++; } $args = \@formatted_args; } if (defined($style->{'function'})) { # in case of an accent, some text is returned here if there are still # more accents on the command_stack, otherwise it is put in the tree. # Other commands text results are put in the tree below. $text = &{$style->{'function'}}($command, $args, $command_stack, $state, $line_nr, $kept_line_nrs); } elsif ($info_default_leaf_command{$command}) { # no formatting function but a leaf command, it is just replaced # by the formatted argument, and put in the tree below. $text = $args->[0]; } if (defined($style->{'begin'}) and !$no_open) { $begin = $style->{'begin'}; } if (defined($style->{'end'}) and !$no_close) { $end = $style->{'end'}; } # normal style commands unless($special_style{$command} or $info_default_accent_commands{$command} or ($command eq 'hyphenation') or $info_default_leaf_command{$command}) { return info_default_close_command($state, $command, $begin, $end); } # this is for *ref, images and footnotes text registering and putting # in the tree. # anchor is already in the tree, from anchor_label. if (($special_style{$command} or $info_default_leaf_command{$command}) and $command ne 'anchor') { return info_default_store_text ($state, $begin.$text.$end, $command); } # for accents, hyphenation and anchor # (though the result for anchor is always an empty string). return $begin.$text.$end; } sub info_default_header () { return $Texi2HTML::THISDOC{'info_header'} if (defined($Texi2HTML::THISDOC{'info_header'})); # $Texi2HTML::THISDOC{'program'} my $input_basename = $Texi2HTML::THISDOC{'input_file_name'}; $input_basename =~ s/^.*\///; # if ($TEST); $input_basename = $STDIN_DOCU_NAME if ($input_basename eq '-'); my $output_basename = $Texi2HTML::THISDOC{'filename'}->{'top'}; $output_basename =~ s/^.*\///; my $result = "This is $output_basename, produced by makeinfo version 4.13 from $input_basename. "; my $dummy; ($dummy, $dummy, $dummy, $result) = info_default_process_para_text($result, 0, {'spaces' => ''}, undef, get_conf('fillcolumn')); $result .= "\n\n"; $result .= "$Texi2HTML::THISDOC{'copying_comment'}"; if ($info_default_dir_specification) { $result .= "$info_default_dir_specification\n"; } $Texi2HTML::THISDOC{'info_header'} = $result; return $result; } sub info_default_print_page_head($) { my $fh = shift; my $header = info_default_header(); print $fh "".$header; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); $info_state->{'offset_in_file'} += info_default_byte_count($header); $info_state->{'blank_line'} = 1 if ($Texi2HTML::THISDOC{'copying_comment'} eq ''); } sub info_default_parent_format($) { my $parent_format = shift; my $in_format = 0; while (1) { if (defined($parent_format->{'command'}) and $info_default_format{$parent_format->{'command'}}) { $in_format = 1; last; } last if (!defined($parent_format->{'parent'})); $parent_format = $parent_format->{'parent'}; } return ($parent_format, $in_format); } sub info_default_paragraph($$$$$$$$$$$$) { my $text = shift; my $align = shift; my $indent = shift; my $paragraph_command = shift; my $paragraph_command_formatted = shift; my $paragraph_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); my ($parent_format, $in_format); ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'}->{'parent'}); info_default_increment_paragraph ($in_format, $parent_format, $info_state); my $additional_args = {'top_stack' => $top_stack, 'parent_format' => $parent_format}; $additional_args->{'paragraph_in_element_nr'} = ($info_state->{'paragraph_in_element_nr'} - 1) if (!$in_format); return info_default_close_command(undef, 'paragraph', undef, undef, $additional_args); } # currently not used, but could be used if info_default_preformatted # return something that is not 'false', for example spaces, though we # want the preformatted to be ignored. Though it is not sure that if there # are spaces we want to ignore the preformatted. sub info_default_empty_preformatted($) { my $text = shift; my $result = info_default_preformatted($text, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef); return 0; } sub info_default_preformatted($$$$$$$$$$$$) { my $text = shift; my $pre_style = shift; my $class = shift; my $leading_command = shift; my $leading_command_formatted = shift; my $preformatted_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; return info_default_close_command(undef, 'preformatted'); } sub info_default_node_line($$) { my $element = shift; my $info_state = shift; my $outfile = $Texi2HTML::THISDOC{'filename'}->{'top'}; $outfile = $STDOUT_DOCU_NAME if ($outfile eq '-'); my $result = "\x{1F}\nFile: $outfile, Node: $element->{'text'}"; if (defined($element->{'NodeNext'})) { # This is not translatable $result .= ", Next: $element->{'NodeNext'}->{'text'}"; } if (defined($element->{'NodePrev'})) { $result .= ", Prev: $element->{'NodePrev'}->{'text'}"; } if (defined($element->{'NodeUp'})) { $result .= ", Up: $element->{'NodeUp'}->{'text'}"; } $result .= "\n\n"; # the line_count is ahead from the number of lines by one. $info_state->{'line_count'} = 3; $info_state->{'offset_in_file'} += info_default_byte_count($result); $info_state->{'blank_line'} = 1; return $result; } sub info_default_element_heading($$$$$$$$$$$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; my $one_section = shift; my $element_heading = shift; my $first_in_page = shift; my $is_top = shift; my $previous_is_top = shift; my $command_line = shift; my $element_id = shift; my $new_element = shift; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); # FIXME use $element or $Texi2HTML::THIS_ELEMENT? Main program should # ensure they are the same. if ($new_element and ($element ne $new_element and $element->{'node'})) { die "There is a new element, but element `$element->{'texi'}' is not the new element\n"; } # FIXME # non node element may appear if the element appears before the first # node/section element. For example `element not associated with a node' # won't be associated with a node. # @unnumbered element not associated with a node # @node Top # @top Top element if (!$element->{'node'}) { return &$heading($element, $command, $texi_line, $line, $in_preformatted, $one_section, $element_heading); } my $before = ''; $element->{'info_offset'} = $info_state->{'offset_in_file'}; push @{$info_state->{'pending_tags'}}, $element; my $result = info_default_node_line($element, $info_state); $info_default_footnote_index = 0; $info_default_current_node = $element; return $before.$result; } sub info_default_heading($$$$$;$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; my $one_section = shift; my $element_heading = shift; die "Heading called for a node\n" if ($element->{'node'}); my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); $info_state->{'paragraph_in_element_nr'} = 0; if (!defined($element->{'texi'})) { main::msg_debug("for $element, element->{'texi'} not defined, texi_line: $texi_line"); } elsif (!defined($element->{'text'})) { main::msg_debug("for $element, $element->{'texi'}, element->{'text'} not defined"); } return '' if ($element->{'tag'} eq 'part'); my $text = "$element->{'text'}"; # when @top is empty, use settitle $text = $Texi2HTML::THISDOC{'settitle'} if (!length($text) and $element->{'tag'} eq 'top' and defined ($Texi2HTML::THISDOC{'settitle'}) and length($Texi2HTML::THISDOC{'settitle'})); my $result = &$heading_text ("\@$command", $text, $element->{'level'}); $result .= "\n"; return info_default_store_text($state, $result, $command, {'heading_command' => 1}); } sub info_default_normal_text($$$$$$$;$) { my @initial_args = @_; my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; my $style_stack = shift; my $state = shift; # $Texi2HTML::THISDOC{'ENCODING_NAME'}) should be defined, but maybe # not when parsing commands in first or second pass, and removeing texi # like what is done for @setfilename. if ($ENABLE_ENCODING and defined($Texi2HTML::THISDOC{'ENCODING_NAME'}) and ($Texi2HTML::THISDOC{'ENCODING_NAME'} eq 'utf-8') and $USE_UNICODE) { $text = &t2h_utf8_normal_text(@initial_args); } else { #print STDERR "info_default_normal_text $text $in_preformatted $in_code \n"; $text = uc($text) if (in_cmd($style_stack, 'sc')); $text = uc($text) if (in_cmd($style_stack, 'var')); if (! $in_code and !$in_preformatted) { $text =~ s/---/\x{1F}/g; $text =~ s/--/-/g; $text =~ s/\x{1F}/--/g; $text =~ s/``/"/g; $text =~ s/\'\'/"/g; } } # accented characters are not handled as normal text, but when the last # accent command on the stack is closed. if ($style_stack and @$style_stack and $info_default_accent_commands{$style_stack->[-1]}) { return $text; } #print STDERR "NORMAL\n"; return info_default_store_text($state,$text); } # this is not called in preformatted sub info_default_empty_line($$) { my $text = shift; my $state = shift; #ignore the line if it just follows a deff #return '' if ($state->{'deff_line'}); return info_default_store_text($state,$text); # return ''; } # change interface? sub info_default_anchor_label($$$$) { my $id = shift; my $anchor_text = shift; my $anchor_reference = shift; my $in_special_region = shift; return '' if ($in_special_region); #print STDERR "Storing anchor $anchor_reference->{'text'}\n"; main::line_warn(__("anchor outside of any node, it won't be registered"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node)); return info_default_store_text(undef,undef,'anchor',{'anchor_reference' => $anchor_reference}); } sub info_default_acronym_like($$$$$$) { my $command = shift; my $acronym_texi = shift; my $acronym_text = shift; my $with_explanation = shift; my $explanation_lines = shift; my $explanation_text = shift; my $explanation_simply_formatted = shift; if ($with_explanation) { return "$acronym_text ($explanation_text)"; } else { return "$acronym_text"; } } sub info_default_print_page_foot($) { my $fh = shift; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); my $indirect = 0; if (!defined ($info_state->{'pending_tags'})) { # i18n main::document_warn ("Document without nodes."); } else { $indirect = 1 if ($info_default_out_file_nr > 1); if ($indirect) { close ($Texi2HTML::THISDOC{'FH'}); unless (rename ("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}", "$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}-1")) { main::document_warn ("Rename $Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'} failed: $!"); } my $INDIRECT = main::open_out("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}"); print $INDIRECT "".info_default_header(); print $INDIRECT "\x{1F}\nIndirect:"; foreach my $indirect (@info_default_pending_indirect) { print $INDIRECT "\n$indirect->{'file'}: $indirect->{'offset'}"; } $fh = $INDIRECT; } # makeinfo seems to add systematically an additional \n, done just below print $fh "\n\x{1F}\nTag Table:\n"; if ($indirect) { print $fh "(Indirect)\n"; } my $Top_seen; foreach my $element (@{$info_state->{'pending_tags'}}) { my $prefix; $prefix = 'Node' if ($element->{'node'}); $prefix = 'Ref' if ($element->{'anchor'} or $element->{'float'}); print $fh "$prefix: $element->{'text'}\x{7F}$element->{'info_offset'}\n"; $Top_seen = 1 if ($element->{'text'} =~ /^top$/i); } if (!$Top_seen) {# i18n main::document_warn ("Document without Top node."); } print $fh "\x{1F}\nEnd Tag Table\n"; } # IN_ENCODING is the documentencoding transformed to the encoding names # usually seen in html. This is what the info readers should understand. my $coding = get_conf('IN_ENCODING'); $coding = get_conf('DOCUMENT_ENCODING') if (!defined($coding)); if (defined($coding)) { print $fh "\n\x{1F}\nLocal Variables:\ncoding: $coding\nEnd:\n"; } } sub info_default_print_Top_footer($$$) { my $fh = shift; my $end_page = shift; my $element = shift; if ($end_page) { &$print_page_foot($fh); } info_default_end_section($fh, $end_page, $element); } sub info_default_footnote_texi($$$) { my $text = shift; my $state = shift; my $style_stack = shift; unless ($state->{'outside_document'} or (defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0)) { $info_default_footnote_index++; } my $footnote_number = $info_default_footnote_index; $footnote_number = $NO_NUMBER_FOOTNOTE_SYMBOL if (!$NUMBER_FOOTNOTES); return "($footnote_number) $text"; #return undef; } sub info_default_print_section { my $fh = shift; my $first_in_page = shift; my $previous_is_top = shift; my $element = shift; my $nw = main::print_lines($fh); my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); if (!$info_state->{'blank_line'}) { my $end = "\n"; $info_state->{'offset_in_file'} += info_default_byte_count($end); $info_state->{'line_count'}++; print $fh "$end"; } if (@info_default_pending_footnotes) { my $footnote_text; my $footnote_element; if (get_conf('footnotestyle') eq 'separate') { my $node_ref = $info_default_current_node; # thee is a warning when processing the footnote, like # "Footnote defined without parent node" $node_ref = {'text' => 'no node', 'file' => ''} if (!defined($node_ref)); $footnote_element = { 'NodeUp' => $node_ref, 'text' => $node_ref->{'text'} . "-Footnotes", 'file' => $node_ref->{'file'}, 'info_offset' => $info_state->{'offset_in_file'}, 'node' => 1, }; $footnote_element->{'element_ref'} = $footnote_element; push @{$info_state->{'pending_tags'}}, $footnote_element; $footnote_text = info_default_node_line($footnote_element, $info_state); } else { # FIXME i18n? $footnote_text = " ---------- Footnotes ----------\n\n"; $info_state->{'offset_in_file'} += info_default_byte_count($footnote_text); $info_state->{'line_count'} += 2; #print STDERR "MMMMMMMMMMMMMMMMMM $info_state->{'line_count'}\n"; } while (@info_default_pending_footnotes) { #push @info_default_pending_footnotes, [$lines, $footnote_text, ${info_default_footnote_index}, $node_name, $footnote_info_state]; my $footnote = shift @info_default_pending_footnotes; my $foot_nr = $footnote->{'footnote_index'}; my $node_name = $footnote->{'node_name'}; my $lines = $footnote->{'lines'}; push @{$info_state->{'pending_tags'}}, {'anchor' => 1, 'text' => "${node_name}-Footnote-${foot_nr}", 'info_offset' => $info_state->{'offset_in_file'} }; my $footnote_info_state = $footnote->{'footnote_info_state'}; my $footnote_result = shift @{$lines}; # this is used to keep track of the size when there were # leading spaces that will be removed below. This is only used # to get the difference, the value itself is not of use. my $initial_length = info_default_byte_count($footnote_result); $footnote_result =~ s/^\s*//; #$footnote_result = " ($foot_nr) " . $footnote_result; $footnote_result = ' ' x get_conf('paragraphindent') . $footnote_result; foreach my $footnote_pending_tags(@{$footnote_info_state->{'pending_tags'}}) { $footnote_pending_tags->{'info_offset'} += $info_state->{'offset_in_file'} + info_default_byte_count($footnote_result) - $initial_length; push @{$info_state->{'pending_tags'}}, $footnote_pending_tags; } foreach my $footnote_pending_index_entry(@{$footnote_info_state->{'pending_index_entries'}}) { #print STDERR "TTTTTTTTTTT($footnote_pending_index_entry->{'index_entry_reference'}->{'entry'}) $footnote_pending_index_entry->{'line_nr'} $info_state->{'line_count'}\n"; $footnote_pending_index_entry->{'line_nr'} += $info_state->{'line_count'}; $footnote_pending_index_entry->{'index_entry_reference'}->{'real_element'} = $footnote_element if (get_conf('footnotestyle') eq 'separate'); } my $line; while (@$lines) { $line = shift @$lines; $footnote_result .= $line; } my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($footnote_result); if ($line_passed == 0) {# certainly out of paragraph commands $footnote_result =~ s/\s*$//; $footnote_result .= "\n"; $line_passed = 1; } unless (($last_line !~ /\S/ and $end_of_line) or ($blank_line)) { $footnote_result .= "\n"; $line_passed += 1; } $info_state->{'offset_in_file'} += info_default_byte_count($footnote_result); $info_state->{'line_count'} += $line_passed; $footnote_text .= $footnote_result; } print $fh "$footnote_text"; } } sub info_default_end_section($$$) { my $fh = shift; my $end_foot_navigation = shift; my $element = shift; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); if (defined($Texi2HTML::THISDOC{'SPLIT_SIZE'}) and $info_state->{'offset_in_file'} > ($info_default_out_file_nr) * $Texi2HTML::THISDOC{'SPLIT_SIZE'}) { if ($info_default_out_file_nr == 1) { # push also the first node, which is always the first pending_tags push @info_default_pending_indirect, {'file'=>"$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr", 'offset' => $info_state->{'pending_tags'}->[0]->{'info_offset'} }; } $info_default_out_file_nr++; # these file descriptors leak, but this allows the user to write a # foot navigation himself, otherwise he would write on a closed file # descriptor #close($Texi2HTML::THISDOC{'FH'}); if (!$end_foot_navigation) { main::open_out_file("$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr"); #print STDERR "X-$info_default_out_file_nr: $info_state->{'offset_in_file'}\n"; &$print_page_head($Texi2HTML::THISDOC{'FH'}); push @info_default_pending_indirect, {'file'=>"$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr", 'offset' => $info_state->{'offset_in_file'}}; } } } sub info_default_one_section($$) { my $fh = shift; my $element = shift; &$print_section($fh, 1, 0, $element); &$print_page_foot($fh); } sub info_default_begin_special_region($$$) { my $region = shift; my $state = shift; my $lines = shift; my $info_state = info_default_get_state ($state); # reset paragraph_in_element_nr if out ofdocument formatting if ($state->{'outside_document'}) { $info_state->{'paragraph_in_element_nr'} = 0; } } sub info_default_end_special_region($$$) { my $region = shift; my $state = shift; my $text = shift; my $info_state = info_default_get_state ($state); my $end = ''; if (!$info_state->{'blank_line'}) { $end = "\n"; $info_state->{'offset_in_file'} += info_default_byte_count($end); } return $text.$end; } sub info_default_menu_link($$$$$$$$) { my $entry = shift; my $state = shift; my $href = shift; my $node = shift; my $title = shift; my $ending = shift; my $has_title = shift; my $command_stack = shift; my $preformatted = shift; $title = '' unless ($has_title); $title .= ':' if ($title ne ''); my $result = "$MENU_SYMBOL$title$node$ending"; return info_default_store_text($state,$result,'menu_entry'); } # not used, menu is a normal preformatted command #sub info_default_menu_command($$$) #{ # my $format = shift; # my $text = shift; # my $in_preformatted = shift; # return info_default_close_command(undef, $format, "* Menu:\n", undef, "\n"); #} sub info_default_complex_format($$) { my $name = shift; my $text = shift; my ($begin, $end); if ($name eq 'menu') { main::line_warn(__("\@menu before first node"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node)); $begin = "* Menu:\n\n"; } elsif ($name eq 'direntry') { main::line_warn(__("\@direntry after first node"), $Texi2HTML::THISDOC{'line_nr'}) if (defined($info_default_current_node)); $begin = "START-INFO-DIR-ENTRY\n"; $end = "END-INFO-DIR-ENTRY\n"; } return info_default_close_command(undef, $name, $begin, $end); } sub info_default_quotation($$$$$) { my $command = shift; my $text = shift; my $argument_text = shift; my $argument_text_texi = shift; my $authors = shift; my $attribution; if ($authors) { $attribution = ''; foreach my $author (@$authors) { my $author_texi = $author->{'author_texi'}; chomp($author_texi); $attribution .= gdt("\@center --- \@emph{{author}}\n", {'author' => $author_texi}, {'duplicate' => 1, 'allow_paragraph' => 1}); } } return info_default_close_command(undef, $command, undef, $attribution); } sub info_default_misc_commands($$$$$) { my $command = shift; my $line = shift; my $args = shift; my $stack = shift; my $state = shift; info_default_store_text($state,undef,$command) if ($command eq 'exdent' or $command eq 'noindent' or $command eq 'indent'); return ($command, $line, undef); } sub info_default_external_ref($$$$$$$$$) { my $type = shift; my $section = shift; my $book = shift; my $file = shift; my $href = shift; my $cross_ref = shift; my $args_texi = shift; my $formatted_args = shift; my $node = shift; return info_default_inforef($formatted_args) if ($type eq 'inforef'); return info_default_normal_reference($type, $formatted_args); } sub info_default_internal_ref($$$$$$$$) { my $type = shift; my $href = shift; my $short_name = shift; my $name = shift; my $is_section = shift; my $args_texi = shift; my $formatted_args = shift; my $element = shift; $formatted_args->[1] = $name if ($element->{'float'} and (!defined($formatted_args->[1]) or $formatted_args->[1] eq '')); return info_default_inforef($formatted_args) if ($type eq 'inforef'); return info_default_normal_reference($type, $formatted_args); } sub info_default_normal_reference($$) { my $command = shift; my $formatted_args = shift; for (my $i = 0; $i < scalar(@$formatted_args); $i++) { $formatted_args->[$i] = undef if (defined($formatted_args->[$i]) and $formatted_args->[$i] =~ /^\s*$/); } my $node = $formatted_args->[0]; # an error, should trigger the message: Undefined node `' in @ref. # avoid undef value and use an empty string instead. $node = '' if (!defined($node)); my $name = $formatted_args->[1]; $name = $formatted_args->[2] if (!defined($name)); my $file = $formatted_args->[3]; $file = '' if (!defined($file) and defined($formatted_args->[4])); $name = $node if (!defined($name) and defined($file)); my $result = '*note '; $result = '*Note ' if ($command eq 'xref'); if (defined($name)) { $result .= "${name}: "; $result .= "($file)" if (defined($file)); $result .= "$node"; $result .= '.' if ($command eq 'pxref'); } else { $result .= "${node}::"; } return $result; } sub info_default_inforef($) { my $formatted_args = shift; return info_default_normal_reference('ref', [$formatted_args->[0], $formatted_args->[1], undef, $formatted_args->[2], 'dumb manual name']); } sub info_default_image_files($$$$) { my $base = shift; my $extension = shift; my $texi_base = shift; my $texi_extension = shift; my @files = (); return @files if (!defined($base) or ($base eq '')); if (defined($extension) and ($extension ne '')) { push @files, ["${base}$extension", "${texi_base}$extension"]; push @files, ["$base.$extension", "$texi_base.$extension"]; } foreach my $ext (@IMAGE_EXTENSIONS) { push @files, ["$base.$ext", "$texi_base.$ext"]; } return @files; } sub info_default_image($$$$$$$$$$$$$$$$$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; my $base_simple_format = shift; my $extension_simple_format = shift; my $file_name_simple_format = shift; my $line_nr = shift; my $txt_path; my $found_file; my @extensions = @IMAGE_EXTENSIONS; if (defined($extension) and ($extension ne '')) { unshift @extensions, ".$extension"; unshift @extensions, "$extension"; } else { $extension = undef; } my $file_found_index = undef; my $file_index = 0; foreach my $file_location (@$file_locations) { my ($file_located, $path, $file_simple_format) = @$file_location; my $extension = shift @extensions; if (defined($path)) { if ($extension eq 'txt' and !defined($txt_path)) { $txt_path = $path; } elsif (!defined($found_file)) { $found_file = [$file_located, $extension, $file_simple_format]; $file_found_index = $file_index; } } $file_index++; } my $text; if (defined($txt_path)) { if (open(TXT, "<$txt_path")) { if (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and $USE_UNICODE) { binmode(TXT, ":encoding($Texi2HTML::THISDOC{'IN_ENCODING'})"); } $text='[' if ($in_paragraph or $preformatted); while (my $img_txt = ) { $text .= $img_txt; } # remove last end of line chomp ($text); $text .= ']' if ($in_paragraph or $preformatted); close(TXT); } else { main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr); } } elsif (!defined($found_file)) { main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr); } if (defined($found_file) and (!defined($extension) or $file_found_index <= 1)) { my $filename = $found_file->[2]; $filename =~ s/\\/\\\\/g; $filename =~ s/\"/\\\"/g; my $result = "\x{00}\x{08}[image src=\"$filename\""; if (defined($alt)) { $alt =~ s/\\/\\\\/g; $alt =~ s/\"/\\\"/g; $result .= " alt=\"$alt\""; } if (defined($text)) { $text =~ s/\\/\\\\/g; $text =~ s/\"/\\\"/g; $result .= " text=\"$text\""; } $result .= "\x{00}\x{08}]"; return $result; } return $text if (defined($text)); return ''; } sub info_default_printindex($$) { my $index_name = shift; my $printindex = shift; %info_default_index_entries_counts = (); return info_default_store_text(undef,t2h_GPL_default_printindex($index_name,$printindex),'printindex'); } sub info_default_print_index($$) { my $text = shift; my $name = shift; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); my $before = ''; if (!$info_state->{'blank_line'}) { $before = "\n"; } return $before if (!defined($text)); my $result = "\x{00}\x{08}[index\x{00}\x{08}]\n* Menu:\n\n" .$text."\n"; return $before.$result; } sub info_default_index_letter($$$) { my $letter = shift; my $id = shift; my $text = shift; return $text; } sub info_default_index_entry_label($$$$$$$$$) { my $identifier = shift; my $preformatted = shift; my $entry = shift; my $index_name = shift; my $index_command = shift; my $texi_entry = shift; my $formatted_entry = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; #return '' if ($index_entry_ref->{'hidden'}); #return '' if (!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'})); return '' if ($in_region_not_in_output or !defined($index_entry_ref->{'index_name'})); main::line_warn(sprintf(__("Entry for index `%s' outside of any node"), $index_entry_ref->{'index_name'}), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node) and !$Texi2HTML::THISDOC{'state'}->{'outside_document'}); my $index_entry_stored = {'index_entry_reference' => $index_entry_ref, 'index_command' => $index_command, 'texi_entry' => $texi_entry}; return info_default_store_text(undef, undef, 'index_label', $index_entry_stored); } sub info_default_index_entry($$$$$$$$$$) { my $text_href = shift; my $entry = shift; my $element_href = shift; my $element_text = shift; my $entry_file = shift; my $current_element_file = shift; my $entry_target = shift; my $entry_element_target = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; #return '' if ($index_entry_ref->{'hidden'}); #return '' if (!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'})); return '' if ($in_region_not_in_output); $entry = main::substitute_line($index_entry_ref->{'texi'}, "index entry in \@printindex"); return '' if ($entry =~ /^\s*$/); my $entry_nr = ''; if (!defined($info_default_index_entries_counts{$entry})) { $info_default_index_entries_counts{$entry} = 0; } else { $info_default_index_entries_counts{$entry} ++; $entry_nr = ' <'.$info_default_index_entries_counts{$entry}.'>'; } my $result = "* $entry${entry_nr}: "; if (t2h_default_string_width($result) < $info_default_index_length_to_node) { $result .= ' ' x($info_default_index_length_to_node - t2h_default_string_width($result)); } #print STDERR "DDDDDDDDDDD $index_entry_ref `$index_entry_ref->{'texi'}'\n"; my $info_index_entry_ref = $info_default_index_entries{$index_entry_ref}; my $line_nr = $info_index_entry_ref->{'line_nr'}; my $real_element_text; my $element = $index_entry_ref->{'real_element'}; # in case $element->{'text'} is not defined, it certainly means that we # are n a special elemet, most likely the virtual element appearing # before anything else if (!defined($element->{'text'})) { $real_element_text = gdt('(outside of any node)'); $line_nr = 0; } else { $element = $element->{'element_ref'} if ($element->{'element_ref'}); $real_element_text = $element->{'text'}; # this happens for index entries appearing after @printindex. In that case # it is considered that they are at the beginning of the node. $line_nr = 3 if (defined($line_nr) and $line_nr < 3); $line_nr = 4 if (!defined($line_nr)); } $result .= $real_element_text . '.'; my $max_len = $info_default_index_line_string_length{$index_entry_ref->{'index_name'}}; $max_len = t2h_default_string_width($line_nr) if (!defined($max_len)); my $line_nr_spaces = sprintf("%${max_len}d", $line_nr); my $line_part = "(line ${line_nr_spaces})"; #print STDERR "GGGGGGGGGG name: $index_entry_ref->{'index_name'} max: ${max_len} line_nr: `$line_nr' line_nr_spaces `$line_nr_spaces' $line_part \n"; if (t2h_default_string_width($result)+t2h_default_string_width($line_part) +1 > get_conf('fillcolumn')) { $result .= "\n" . ' ' x (get_conf('fillcolumn') - t2h_default_string_width($line_part)) ; } else { $result .= ' ' x (get_conf('fillcolumn') - t2h_default_string_width($line_part) - t2h_default_string_width($result)); } $result .= "$line_part\n"; return $result; } sub info_default_index_summary($$) { my $alpha = shift; my $nonalpha = shift; return ''; } sub info_default_summary_letter { return ''; } sub info_default_foot_line_and_ref($$$$$$$$) { my $foot_num = shift; my $relative_num = shift; my $footid = shift; my $docid = shift; my $from_file = shift; my $footnote_file = shift; my $lines = shift; my $state = shift; my $footnote_state = $Texi2HTML::THISDOC{'state'}; my $footnote_info_state = info_default_get_state ($footnote_state); my $footnote_text = "($info_default_footnote_index)"; $footnote_text = "($NO_NUMBER_FOOTNOTE_SYMBOL)" if (!$NUMBER_FOOTNOTES); my $node_name; $node_name = ''; if (defined($info_default_current_node)) { $node_name = $info_default_current_node->{'text'}; } else { # i18n # no warning when outside of document, for footnotes in # titlepage and copying main::line_error(__("Footnote defined without parent node"), $Texi2HTML::THISDOC{'line_nr'}) unless ($footnote_state->{'outside_document'}); #print STDERR "".main::context_string()."\n"; } if (get_conf('footnotestyle') eq 'separate') { $footnote_text .= ' (' . info_default_normal_reference('pxref', ["${node_name}-Footnote-${info_default_footnote_index}"]) . ')'; } push @info_default_pending_footnotes, {'lines' => $lines, 'footnote_text' => $footnote_text, 'footnote_index' => ${info_default_footnote_index}, 'node_name' => $node_name, 'footnote_info_state' => $footnote_info_state} unless ($state->{'outside_document'} or (defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0)); return ([], $footnote_text); } sub info_default_foot_lines($) { my $lines = shift; #my $state = $Texi2HTML::THISDOC{'state'}; #my $info_state = info_default_get_state ($state); @$lines = (); } # remark: table_item is the html one, but it gets added to the table text # on the stack, and is ignored there (in info_default_format). sub info_default_format_list_item_texi($$$$) { my $format = shift; my $line = shift; my $prepended = shift; my $command = shift; my $number = shift; my $open_command = 0; my $result_line; $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize'); $prepended = "\@$command\{\}" if (defined($command) and $command ne ''); $prepended = "$number." if (defined($number) and $number ne ''); $line =~ s/^\s*//; if (defined($command) and $command ne '' and $format ne 'itemize') { #@*table $line =~ s/\s*$//; if (exists ($style_map{$command})) { $result_line = "\@$command\{$line\}\n"; } elsif (exists ($things_map{$command})) { $result_line = "\@$command\{\} $line\n"; } else { $result_line = "\@$command $line\n"; } } # elsif (defined($prepended) and $prepended ne '') # { # @enumerate and @itemize # $prepended =~ s/^\s*//; # $prepended =~ s/\s*$//; # $result_line = $prepended . ' ' . $line; # } return ($result_line, $open_command); } sub info_default_list_item($$$$$$$$$$$$) { my $text = shift; my $format = shift; my $command = shift; my $formatted_command = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $prepended = shift; my $prepended_formatted = shift; my $only_inter_item_commands = shift; my $before_items = shift; my $item_command = shift; # my $prepend = ''; # if (defined($formatted_command) and $formatted_command ne '') # { # $prepend = $formatted_command; # } # return $prepend . $text; # $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize'); $formatted_command = $things_map{'bullet'} if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize'); if ($format !~ /table$/) { my $result = ''; if ($format eq 'enumerate') { $result = $number.'.'; } elsif ($format eq 'itemize') { if (defined($formatted_command) and $formatted_command ne '') { $result = $formatted_command; } elsif (defined ($prepended_formatted) and $prepended_formatted ne '') { $prepended_formatted =~ s/^\s*//; $prepended_formatted =~ s/\s*$//; $result = $prepended_formatted; } } else { $result = ''; } $result .= ' ' if ($result ne ''); return info_default_close_command (undef, $item_command, $result); } return $text; } sub info_default_format($$$) { my $tag = shift; my $element = shift; my $text = shift; # currently no command has something else than '' as $element. # notice that any text is discarded $element = undef if ($element eq ''); my $element_end = $element; if (defined($element) and $element =~ /^(\w+)(\s+)(.+)/) { $element = $1; $element_end = $2; } return info_default_close_command(undef, $tag, $element, $element_end); } sub info_default_tab_item_texi($$$$$$) { my $command = shift; my $commands_stack = shift; my $stack = shift; my $state = shift; my $line = shift; my $line_nr = shift; $line =~ s/^\s*//; my $format; my $info_state = info_default_get_state ($state); #$format = $commands_stack->[-1] if (defined($commands_stack) and @$commands_stack and $commands_stack->[-1]); my ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'}); print STDERR "Not in_format in info_default_tab_item_texi\n" if (!$in_format); $format = $parent_format->{'command'}; # in case of an @item or @tab outside of any format $format will be # undefined, or not multitable for a @tab. # however the main program still do as if something was opened, plus # it is checked there that the nesting is correct #return $line if (!defined($format) or $command eq 'tab' and $format ne 'multitable'); #print STDERR "tab_item_texi $format $command $commands_stack, $stack, $state, $line, ".main::format_line_number($line_nr)."\n"; if ($format eq 'multitable') { # even if it is a tab, if it is not already in a multitable_row, one # should be started if ($command ne 'tab' or $info_state->{'current'}->{'command'} ne 'multitable_row') { info_default_open_command($state, 'multitable_row'); } info_default_open_command($state, 'multitable_cell'); } elsif ($format =~ /table$/) { info_default_store_text ($state, undef, $command, {'format_name' => $format}); } else { info_default_open_command ($state, $command, {'format_name' => $format}); } # this should have already been done for @item when the line # is modified by the @-command and so on. return $line; } sub info_default_sp($$) { my $number = shift; my $preformatted = shift; my $result = "\n" x $number; return info_default_store_text(undef,$result,'sp'); } sub info_default_paragraph_style_command($$) { my $format = shift; my $text = shift; return info_default_close_command(undef, $format); } sub info_default_row($$$$$$$$) { my $text = shift; my $macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; #print STDERR "info_default_row: $text\n"; return info_default_close_command(undef, 'multitable_row', undef, undef, {'item_command' => $macro}); } sub info_default_cell($$$$$$$$) { my $text = shift; my $row_macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $only_inter_item_commands = shift; my $before_items = shift; # in general, when before_items, there will be no call to the function # since there should never be a text sent back, so that this # function will not be called for the first row (the multitable title). # However, if there is a @tab before the first @item, the main program # is less careful and closes the cell in any case, so before_items # has to be checked for that case. return info_default_close_command(undef, 'multitable_cell') unless ($before_items); } sub info_default_table_list($$$$$$$$$) { my $format_command = shift; my $text = shift; my $command = shift; my $formatted_command = shift; # enumerate my $item_nr = shift; my $enumerate_style = shift; # itemize my $prepended = shift; my $prepended_formatted = shift; # multitable my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; die "BUG: $format_command item_nr undef\n" if (!defined($item_nr)); return info_default_close_command(undef, $format_command, undef, undef, {'total_item_nr' => $item_nr}) if ($format_command ne 'multitable'); my $columnsize = []; if (defined($prototype_lengths) and @$prototype_lengths) { $columnsize = [ @$prototype_lengths ]; } elsif (defined($columnfractions) and @$columnfractions) { foreach my $fraction (@$columnfractions) { push @$columnsize, int($fraction * get_conf('fillcolumn') +0.5); } } else { # empty multitable #print STDERR "Empty multitable?\n"; } return info_default_close_command(undef, $format_command, undef, undef, {'columns_size' => $columnsize, 'total_item_nr' => $item_nr}); } sub info_default_def_item($$$) { my $text = shift; my $only_inter_item_commands = shift; my $command = shift; my $format = 'deff_item'; $format = 'deff_itemx' if ($command =~ /x$/); return info_default_close_command(undef, $format); } sub info_default_def_line($$$$$$$$$$$$$$$$) { my $category_prepared = shift; my $name = shift; my $type = shift; my $arguments = shift; my $index_label = shift; my $arguments_array = shift; my $arguments_type_array = shift; my $unformatted_arguments_array = shift; my $command = shift; my $class_name = shift; my $category = shift; my $class = shift; my $style = shift; my $original_command = shift; $name = '' if (!defined($name) or ($name =~ /^\s*$/)); $type = '' if (!defined($type) or $type =~ /^\s*$/); $arguments = '' if (!defined($arguments) or $arguments =~ /^\s*$/); my $type_name = ''; $type_name .= "$type " if ($type ne ''); $type_name .= $name if ($name ne ''); my $result = " -- $category_prepared: ${type_name}$arguments"; $result =~ s/\s*$//; $result .= "\n"; my $state = $Texi2HTML::THISDOC{'state'}; info_default_store_text(undef,$result,"${command}_line",{'definition_line' => 1}); my $format = 'deff_item'; $format = 'deff_itemx' if ($original_command =~ /x$/); return info_default_open_command($state, $format); } sub info_default_def($$) { my $text = shift; my $command = shift; return info_default_close_command(undef, $command); } sub info_default_float($$$$$) { my $text = shift; my $float = shift; my $caption = shift; my $shortcaption = shift; my $additional_arguments; if (exists($float->{'id'})) { $additional_arguments->{'anchor_reference'} = $float; main::line_warn(__("float reference outside of any node, it won't be registered"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node) and !$Texi2HTML::THISDOC{'state'}->{'outside_document'}); } my $caption_text = ''; if (defined($float->{'caption_texi'})) { $caption_text = $caption; } elsif (defined($float->{'shortcaption_texi'})) { $caption_text = $shortcaption; } elsif (defined($caption)) { $caption_text = $caption; } #return $caption_text; return info_default_close_command(undef, 'float', undef, $caption_text, $additional_arguments); } sub info_default_listoffloats_entry($$$$) { my $style_texi = shift; my $float = shift; my $float_style = shift; my $caption = shift; my $href = shift; my @lines = split /^/, $caption; $caption = $lines[0]; $caption = '' if (!defined($caption)); chomp ($caption); my $result = ''; #$caption .= ':' if ($caption ne ''); my $caption_entry = "* $float_style: $float->{'text'}."; if (t2h_default_string_width($caption_entry) > $info_default_listoffloat_caption_entry_length) { $caption_entry .= "\n" . ' ' x $info_default_listoffloat_caption_entry_length; } else { $caption_entry .= ' ' x ($info_default_listoffloat_caption_entry_length - length($caption_entry)); } my $width = $info_default_listoffloat_caption_entry_length; while ($caption =~ s/^(\S+\s*)//) { my $new_word = $1; if ((t2h_default_string_width($new_word) + $width) > get_conf('fillcolumn') - 3) { $caption_entry .= $info_default_listoffloat_append; last; } else { $caption_entry .= $new_word; $width += t2h_default_string_width($new_word); } } return $caption_entry. "\n"; } sub info_default_listoffloats($$$) { my $style_texi = shift; my $style = shift; my $float_entries = shift; my $state = $Texi2HTML::THISDOC{'state'}; my $info_state = info_default_get_state ($state); my $result = "* Menu:\n\n"; foreach my $float_entry (@$float_entries) { $result .= $float_entry; } my ($parent_format, $in_format); ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'}); #print STDERR "\@listoffloats not at top level\n" if ($in_format); info_default_increment_paragraph ($in_format, $parent_format, $info_state, 'listoffloats'); return info_default_store_text($state,$result,'listoffloats'); } sub info_default_raw($$) { my $style = shift; my $text = shift; my $expanded = 1 if (grep {$style eq $_} @EXPAND); # no warning for unknown raw formats if ($style eq 'verbatim' or $style eq 'verbatiminclude' or $expanded) { return info_default_store_text(undef, $text, $style, {'raw_command' => 1}); } return ''; } sub info_default_line_command($$$$) { my $command = shift; my $arg_text = shift; my $arg_texi = shift; my $state = shift; main::line_warn(__("\@dircategory after first node"), $Texi2HTML::THISDOC{'line_nr'}) if (defined($info_default_current_node)); return '' if ($arg_text eq ''); $info_default_dir_specification .= "INFO-DIR-SECTION $arg_text\n"; return ''; } sub info_default_unknown_style($$$$$) { my $command = shift; my $text = shift; my $state = shift; my $no_close = shift; my $no_open = shift; my ($result, $result_text, $message); $result_text = info_default_close_command(undef, $command, undef, undef, undef); $message = "Unknown command with braces `\@$command'" if (!$no_open); return (1, $result_text, $message); } 1; require "$T2H_HOME/formats/info.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/formats/info.init" && -r "$T2H_HOME/formats/info.init"); # @INIT_DOCBOOK@ #+############################################################################## # # docbook.init: convert to docbook # # Copyright (C) 2008, 2009 Patrice Dumas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # #-############################################################################## # regarding sections and nodes, in docbook we don't care at all about the # splitting done in the main program. When there is a node, it is recorded as # being pending. When there is a section it is opened, and closed when # there is the next section or end of file. use strict; my %docbook_complex_format; my $kept_footnote_function; my $docbook_in_footnote; my %docbook_sections; my %def_format_docbook; my %def_argument_types_docbook; my $docbook_pending_node_id; my $docbook_current_section; my @docbook_multitable_stack = (); my @docbook_table_stack = (); my @docbook_special_quotation; sub docbook_default_load(;$) { my $from_command_line = shift; t2h_default_set_variables_xml(); $DOCTYPE = ' ]>'; @T2H_FORMAT_EXPAND = ('docbook'); @IMAGE_EXTENSIONS = ('eps', 'gif', 'jpg', 'jpeg', 'pdf', 'png', 'svg', 'txt'); $INLINE_INSERTCOPYING = 1; # this should lead to end_section being only called at the end of sectioning $USE_NODES = 0; $USE_SECTIONS = 1; $SHOW_MENU = 0; $SHOW_TITLE = 0; $HEADERS = 0; # certainly irrelevant $SIMPLE_MENU = 0; t2h_default_push_handler(\&docbook_initialize_variables, \@command_handler_init); %style_map = (); t2h_default_copy_style_map (\%default_style_map, \%style_map); foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) { $style_map{$accent_command} = { 'function' => \&xml_default_accent }; } delete $style_map{'sc'}->{'inline_attribute'}; # FIXME there is a code element in v4.3 $style_map{'code'}->{'inline_attribute'} = 'literal'; $style_map{'strong'}->{'inline_attribute'} = 'emphasis role="bold"'; $style_map{'kbd'}->{'inline_attribute'} = 'userinput'; $style_map{'w'}->{'end'} = ''; $style_map{'='}->{'function'} = \&docbook_macron; $style_map{'b'}->{'inline_attribute'} = 'emphasis role="bold"'; $style_map{'cite'}->{'inline_attribute'} = 'citetitle'; $style_map{'command'}->{'inline_attribute'} = 'command'; $style_map{'dfn'}->{'inline_attribute'} = 'firstterm'; $style_map{'emph'}->{'inline_attribute'} = 'emphasis'; $style_map{'env'}->{'inline_attribute'} = 'envar'; $style_map{'file'}->{'inline_attribute'} = 'filename'; $style_map{'i'}->{'inline_attribute'} = 'wordasword'; $style_map{'key'}->{'inline_attribute'} = 'keycap'; delete $style_map{'key'}->{'begin'}; delete $style_map{'key'}->{'end'}; $style_map{'option'}->{'inline_attribute'} = 'option'; $style_map{'t'}->{'inline_attribute'} = 'literal'; delete $style_map{'sansserif'}->{'inline_attribute'}; delete $style_map{'r'}->{'inline_attribute'}; $style_map{'indicateurl'}->{'inline_attribute'} = 'wordasword'; delete $style_map{'indicateurl'}->{'begin'}; delete $style_map{'indicateurl'}->{'end'}; $style_map{'var'}->{'inline_attribute'} = 'replaceable'; delete $style_map{'verb'}->{'inline_attribute'}; $style_map{'email'}->{'function'} = \&docbook_email; $style_map{'math'}->{'function'} = \&docbook_math; $style_map{'uref'}->{'function'} = \&docbook_uref; $style_map{'url'}->{'function'} = \&docbook_uref; $style_map{'titlefont'}->{'function'} = \&docbook_titlefont; #$style_map{'samp'}->{'function'} = \&docbook_samp; #delete $style_map{'samp'}->{'inline_attribute'}; $style_map{'samp'}->{'inline_attribute'} = 'literal'; $style_map{'samp'}->{'begin'} = '‘'; $style_map{'samp'}->{'end'} = '’'; $kept_footnote_function = $style_map{'footnote'}->{'function'}; $style_map{'footnote'}->{'function'} = \&docbook_footnote; foreach my $style (keys(%style_map)) { delete ($style_map{$style}->{'quote'}); } #use Data::Dumper; %style_map_pre = (); t2h_default_copy_style_map (\%style_map, \%style_map_pre); $style_map_pre{'r'}->{'inline_attribute'} = 'lineannotation'; $colon_command_punctuation_characters{'.'} = '.'; $colon_command_punctuation_characters{':'} = ':'; $colon_command_punctuation_characters{'?'} = '?'; $colon_command_punctuation_characters{'!'} = '!'; $stop_paragraph_command{'titlefont'} = 0; # FIXME #$no_paragraph_commands{'anchor'} = 0; # FIXME delete $special_accents{'ringaccent'}; $special_accents{'ogonek'} = 'aeiuAEIU'; %simple_map = %default_simple_map; %simple_map_pre = %simple_map; # FIXME right? ł Ł $things_map{'l'} = '/l'; $things_map{'L'} = '/L'; $things_map{'TeX'} = '&tex;'; $things_map{'LaTeX'} = '&latex;'; $things_map{'enddots'} = '….'; $things_map{'minus'} = '−'; # FIXME ∗ $things_map{'point'} = '-!-'; # FIXME ≡ $things_map{'equiv'} = '=='; # FIXME no ‹ nor › $things_map{'guilsinglright'} = '>'; $things_map{'guilsinglleft'} = '<'; # The following is unneeded because normal_text is redefined. # FIXME it should certainly be better to leave those substitutions, # or even hardcodes them in normal_text. # t2h_remove_text_substitutions("'", 1, 0, 0, 1); # t2h_remove_text_substitutions('`', 1, 0, 0, 1); $things_map{'quotedblbase'} = '„'; $things_map{'quotesinglbase'} = '‚'; %pre_map = %things_map; #delete $inter_item_commands{'cindex'}; #$no_paragraph_commands{'cindex'} = 0; $no_paragraph_commands{'float'} = 0; %docbook_complex_format = ( 'example' => 'screen', 'smallexample' => 'screen', 'display' => 'literallayout', 'smalldisplay' => 'literallayout', 'lisp' => 'programlisting', 'smalllisp' => 'programlisting', 'format' => 'abstract', 'smallformat' => 'screen' ); %docbook_sections = ( 'top' => 'chapter', 'part' => 'part', 'chapter' => 'chapter', 'unnumbered' => 'chapter', 'centerchap' => 'chapter', 'appendix' => 'appendix', 'majorheading' => 'other', 'chapheading' => 'other', 'heading' => 'sect1', 'subheading' => 'sect2', 'subsubheading' => 'sect3', 2 => 'sect1', 3 => 'sect2', 4 => 'sect3' ); %def_format_docbook = ( 'deffn' => [ ['function', 'name'] ], 'defvr' => [ ['varname', 'name'] ], 'deftypefn' => [ [ 'returnvalue', 'type' ], ['function', 'name'] ], 'deftypeop' => [ ['returnvalue', 'type'], ['methodname', 'name'] ], 'deftypevr' => [ ['returnvalue', 'type'], ['varname', 'name'] ], 'defcv' => [ ['classname', 'class'], ['property', 'name'] ], 'deftypecv' => [ ['returnvalue', 'type'], ['property', 'name'] ], 'defop' => [ ['classname', 'class'], ['methodname', 'name'] ], 'deftp' => [ ['structname', 'name'] ] ); %def_argument_types_docbook = ( 'param' => 'replaceable', 'paramtype' => 'type', 'delimiter' => '' ); @docbook_special_quotation = ('note', 'caution', 'important', 'tip', 'warning'); $region_formats_kept{'copying'} = 1; %format_map = ( 'group' => '', 'raggedright' => '', 'copying' => 'copying', ); $print_Top = \&docbook_print_Top; $print_Top_footer = \&docbook_print_Top_footer; $print_page_head = \&docbook_print_page_head; $print_foot_navigation = \&docbook_noop; $contents = \&docbook_noop; $shortcontents = \&docbook_noop; $about_body = \&docbook_noop; $print_page_foot = \&docbook_print_page_foot; $end_section = \&docbook_end_section; $one_section = \&docbook_one_section; $acronym_like = \&docbook_acronym_like; $anchor_label = \&docbook_anchor_label; $begin_format_texi = \&docbook_begin_format_texi; $cartouche = \&docbook_cartouche; $cell = \&docbook_cell; $complex_format = \&docbook_complex_format; $def = \&docbook_def; $def_line = \&docbook_def_line; $def_item = \&docbook_def_item; $element_label = \&docbook_element_label; $external_ref = \&docbook_external_ref; $float = \&docbook_float; $foot_line_and_ref = \&docbook_foot_line_and_ref; $format = \&docbook_format; $format_list_item_texi = \&docbook_format_list_item_texi; $heading = \&docbook_heading; $image = \&docbook_image; $image_files = \&docbook_image_files; $index_entry_command = \&docbook_index_entry_command; $index_entry_label = \&docbook_index_entry_label; $index_summary = \&docbook_index_summary; $internal_ref = \&docbook_internal_ref; $insertcopying = \&docbook_insertcopying; $list_item = \&docbook_list_item; $misc_element_label = \&docbook_noop; $normal_text = \&docbook_normal_text; $paragraph = \&docbook_paragraph; $preformatted = \&docbook_preformatted; $printindex = \&docbook_printindex; $protect_text = \&xml_default_protect_text; $quotation = \&docbook_quotation; $quotation_prepend_text = \&docbook_quotation_prepend_text; $listoffloats = \&docbook_noop; $raw = \&docbook_raw; $row = \&docbook_row; $sp = \&docbook_sp; $style = \&docbook_style; $table_item = \&docbook_table_item; $table_line = \&docbook_table_line; $table_list = \&docbook_table_list; $misc_command_line = \&docbook_misc_commands; } sub docbook_footnote { $docbook_in_footnote = 1; my $result = &$kept_footnote_function(@_); $docbook_in_footnote = 0; return $result; } sub docbook_macron($$) { my $accent = shift; my $args = shift; return $args->[0] . "¯"; } sub docbook_samp($$) { shift; my $args = shift; return "‘$args->[0]’"; } sub docbook_email($$) { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); if (defined($text) and $text =~ /\S/) { # FIXME normalise_space would be more legible. #return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.main::normalise_space($text).''; return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.$text.''; } return docbook_add_id('email').">$mail"; } sub docbook_uref($$) { shift; my $args = shift; my $url = shift @$args; my $text = shift @$args; my $replacement = shift @$args; $url = main::normalise_space($url); $text = '' if (!defined($text)); $replacement = '' if (!defined($replacement)); $replacement = $text if ($replacement eq ''); $replacement = $url if ($replacement eq ''); $replacement = main::normalise_space($replacement); return docbook_add_id('ulink')." url=\"$url\">$replacement"; } # FIXME sub docbook_titlefont($$) { shift; my $args = shift; return "$args->[0]"; } # FIXME there ought to be something better... Like use tex4ht mathml # output or something like that sub docbook_math($$) { shift; my $args = shift; my $text = shift @$args; return $text; } sub docbook_print_page_head($) { my $fh = shift; my $language = get_conf('documentlanguage'); my $doctype = get_conf('doctype'); print $fh < $doctype EOT } sub docbook_print_page_foot($) { my $fh = shift; print $fh "". docbook_close_section(); print $fh < EOT } sub docbook_print_Top($$$) { my $fh = shift; my $has_top_heading = shift; my $element = shift; main::print_lines($fh, $Texi2HTML::THIS_SECTION); } sub docbook_element_tag($) { my $element = shift; #print STDERR "$element->{'texi'}, $element->{'tag_level'}, $element->{'level'}\n"; return $docbook_sections{$element->{'tag_level'}} if (exists($docbook_sections{$element->{'tag_level'}})); return $docbook_sections{$element->{'level'}} if (exists($docbook_sections{$element->{'level'}})); } sub docbook_node_id($) { my $node_texi = shift; my $node = main::substitute_line($node_texi, 'docbook node id', {'code_style' => 1, 'remove_texi' => 1}); $node =~ s/[\s\"]/-/g; return &$protect_text($node); } sub docbook_initialize_variables() { $docbook_pending_node_id = undef; $docbook_current_section = undef; @docbook_multitable_stack = (); @docbook_table_stack = (); $Texi2HTML::THISDOC{'SPLIT'} = 0 if ($OUTPUT_FORMAT eq 'docbook'); } sub docbook_add_id($) { my $element = shift; my $result = "<$element"; if (defined($docbook_pending_node_id) and (!$docbook_in_footnote or $element eq 'footnote')) { $result .= " id=\"$docbook_pending_node_id\""; $docbook_pending_node_id = undef; } return $result; } sub docbook_heading($$$$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; if (defined($command) and $command =~ /heading/) { my $text = ''; if (defined($line)) { $text = $line; # this isn't done in main program in that case... chomp ($text); $text =~ s/^\s*//; } return docbook_add_id('bridgehead')." renderas=\"$docbook_sections{$command}\">$text\n"; } my $result = ''; # FIXME verify xreflabel if ($command ne 'node') { # close previous section $result .= docbook_close_section(); my $title = $element->{'text_nonumber'}; my $label = ''; my $xreflabel = ''; if ($element->{'number'}) { my $label_nr = $element->{'number'}; #$label_nr =~ s/\.$//; $label = $label_nr; } else { my $xreftitle = $title; $xreflabel = " xreflabel=\"$xreftitle\""; } $result .= docbook_add_id(docbook_element_tag($element) . " label=\"${label}\"${xreflabel}"); $result .= ">\n$title\n"; $docbook_current_section = $element; } return $result; } sub docbook_element_label($$$$) { my $id = shift; my $element = shift; my $command = shift; my $line = shift; if ($command eq 'node') { $docbook_pending_node_id = docbook_node_id($element->{'texi'}); } return ''; } sub docbook_paragraph($$$$$$$$$$$$) { my $text = shift; my $align = shift; my $indent = shift; my $paragraph_command = shift; my $paragraph_command_formatted = shift; my $paragraph_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; if (defined($paragraph_number) and defined($$paragraph_number)) { $$paragraph_number++; } # no para in multitables, caption and shortcaptions. my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); return $text if ($top_stack eq 'multitable' or $top_stack eq 'shortcaption' or $top_stack eq 'caption' or $top_stack eq 'documentdescription'); if ($text =~ /\S/) { #return docbook_add_id('para').">$text"; return "$text"; } return $text; } sub docbook_def_line($$$$$$$$$$$$$$$) { my $category_prepared = shift; my $name = shift; my $type = shift; my $arguments = shift; my $index_label = shift; my $arguments_array = shift; my $arguments_type_array = shift; my $unformatted_arguments_array = shift; my $command = shift; my $class_name = shift; my $category = shift; my $class = shift; my $style = shift; my $original_command = shift; my %unformatted_arguments = (); my @unformatted_args = @$unformatted_arguments_array; foreach my $type (@$arguments_type_array) { my $unformatted_arg = shift @unformatted_args; $unformatted_arguments{$type} = $unformatted_arg; } # FIXME unformatted! my $result = "$class_name"; my %arguments = ( 'prepared_category' => $category_prepared, 'category' => $category, 'name' => $name, 'type' => $type, 'class' => $class ); foreach my $type (keys(%arguments)) { $arguments{$type} = '' if (!defined($arguments{$type})); } foreach my $mandatory_arg (@{$def_format_docbook{$command}}) { my $elem = $mandatory_arg->[0]; #if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /^\s*\@code\{/) if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /\@code\{/) { # FIXME unformatted my $arg_without_at_command = $unformatted_arguments{$mandatory_arg->[1]}; #$arg_without_at_command =~ s/\s*\@code\{//; #$arg_without_at_command =~ s/\}\s*$//; while ($arg_without_at_command =~ /\@code\{([^\{\}]*)\}/) { $arg_without_at_command =~ s/\@code\{([^\{\}]*)\}/$1/; } $result .= "<$elem>$arg_without_at_command"; } else { $result .= "<$elem>$arguments{$mandatory_arg->[1]}"; } } my @types = @$arguments_type_array; @unformatted_args = @$unformatted_arguments_array; foreach my $arg (@$arguments_array) { my $type = shift @types; my $unformatted = shift @unformatted_args; if (exists ($def_argument_types_docbook{$type})) { if ($def_argument_types_docbook{$type} and ($type eq 'paramtype' or ($unformatted !~ /^\s*\@var\{/))) { $result .= "<$def_argument_types_docbook{$type}>$arg"; } else { $result .= $arg; } } } $result .= "\n"; return $result; } # FIXME # @deffn # @c comment # @end deffn # leads to the creation of a with a comment within, # while there should be no definitionitem sub docbook_def_item($) { my $text = shift; my $only_inter_item_commands = shift; if ($text =~ /\S/) { return '
    ' . $text . '
    ' unless $only_inter_item_commands; return $text; } return ''; } sub docbook_def($) { my $text = shift; return docbook_add_id('informalfigure').'>'.$text.''; } sub docbook_preformatted($$$$$$$$$$$$) { my $text = shift; my $pre_style = shift; my $class = shift; my $leading_command = shift; my $leading_command_formatted = shift; my $preformatted_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; return $text; } sub docbook_misc_commands($$$$$) { my $macro = shift; my $line = shift; my $args = shift; my $stack = shift; my $state = shift; #print STDERR "$macro $line"; #print STDERR "ARGS @$args\n" if defined ($args); my $result_text = undef; if ($macro eq 'c' or $macro eq 'comment' and scalar(@$args)) { my $comment_line = $args->[0]; chomp ($comment_line); # makeinfo remove all the leading spaces $comment_line =~ s/^\s//; $result_text = &$comment ($comment_line); } elsif ($macro eq 'settitle') { # FIXME to be formatted? Also maybe in line_command. And in html, it # is handled by heading _text my $arg = $args->[0]; $arg =~ s/^\s*//; chomp($arg); $result_text = "$arg\n"; } return ($macro, $line, $result_text); } sub docbook_foot_line_and_ref($$$$$$$) { my $number_in_doc = shift; my $number_in_page = shift; my $footnote_id = shift; my $place_id = shift; my $document_file = shift; my $footnote_file = shift; my $lines = shift; my $state = shift; my $result = docbook_add_id('footnote').'>'; foreach my $line (@$lines) { $result .= $line; } return ([], $result . ''); } sub docbook_any_ref($$$) { my $type = shift; my $args = shift; my $unformatted_args = shift; # FIXME? if ($type eq 'inforef') { my $node_file = "($args->[2])$args->[0]"; if ($args->[1] ne '') { return "*note $args->[1]: $node_file"; } else { return "*note ${node_file}::"; } } else { if (($args->[3] ne '') or ($args->[4] ne '')) { return '' if ($args->[4] eq ''); my $section_name = $args->[2]; $section_name = $args->[0] if ($section_name eq ''); if ($type eq 'ref') { return gdt('section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); } elsif ($type eq 'xref') { return gdt('See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); } elsif ($type eq 'pxref') { return gdt('see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); } } my $link = docbook_node_id($unformatted_args->[0]); my $title = $args->[2]; $title = $args->[1] if ($title eq ''); if ($title eq '') { if ($type eq 'ref') { return gdt('{ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\">"}); } elsif ($type eq 'pxref') { return gdt('see {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\">"}); } elsif ($type eq 'xref') { return gdt('See {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\">"}); } } else { if ($type eq 'ref') { return gdt('{title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title"}); } elsif ($type eq 'pxref') { return gdt('see {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title"},{'duplicate'=>1}); } elsif ($type eq 'xref') { return gdt('See {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title"},{'duplicate'=>1}); } } } } sub docbook_external_ref($$$$$$$$$) { my $type = shift; my $section = shift; my $book = shift; my $file = shift; my $href = shift; my $cross_ref = shift; my $args_texi = shift; my $formatted_args = shift; my $node = shift; return docbook_any_ref ($type, $formatted_args, $args_texi); } sub docbook_internal_ref($$$$$) { my $type = shift; my $href = shift; my $short_name = shift; my $name = shift; my $is_section = shift; my $args_texi = shift; my $formatted_args = shift; return docbook_any_ref ($type, $formatted_args, $args_texi ); } sub docbook_index_entry_command($$$$$) { my $command = shift; my $index_name = shift; my $label = shift; my $entry_texi = shift; my $entry_formatted = shift; return $label if (defined($label) and $label ne ''); return docbook_index_entry_label('','','',$main::index_prefix_to_name{$index_name}, '', '', $entry_formatted, {}); } sub docbook_index_entry_label($$$$$$$$$) { my $identifier = shift; my $preformatted = shift; my $entry = shift; my $index_name = shift; my $index_command = shift; my $texi_entry = shift; my $formatted_entry = shift; my $in_region_not_in_output = shift; my $index_entry = shift; return "${formatted_entry}"; } sub docbook_close_section() { my $element = $docbook_current_section; if (!defined($element)) { return ''; } my $result = ''; # there is a special case for a @chapter that is a child of @top # but should not be considered as is, since it is also toplevel. # @part, however may have other toplevel elements as children. return '' if ($element->{'child'} and (!$element->{'child'}->{'toplevel'} or $element->{'tag'} ne 'top')); $result .= '\n"; my $current = $element; # the second condition is such that top is closed only if it has # sub-elements below chapter. # the third condition is such that elements with a next element are # only closed for the last element, except when the next element is # toplevel and below top, such that @top is closed before the first # @chapter if there are @section or the like below @top while ($current->{'sectionup'} and !($current->{'sectionup'}->{'tag'} eq 'top' and $current->{'toplevel'}) and (!$current->{'childnext'} or ($current->{'childnext'}->{'toplevel'} and $current->{'sectionup'}->{'tag'} eq 'top'))) { $current = $current->{'sectionup'}; $result .= '\n"; } return $result; } sub docbook_end_section($$$) { my $fh = shift; my $end_foot_navigation = shift; my $element = shift; } sub docbook_print_Top_footer($$) { my $fh = shift; my $end_page = shift; my $element = shift; } sub docbook_one_section($$) { my $fh = shift; my $element = shift; main::print_lines($fh); &$print_page_foot($fh); } sub docbook_insertcopying($) { my $text = shift; my $comment = shift; my $simple_text = shift; return $text; } sub docbook_acronym_like($$$$$$) { my $command = shift; my $acronym_texi = shift; my $acronym_text = shift; my $with_explanation = shift; my $explanation_lines = shift; my $explanation_text = shift; my $explanation_simply_formatted = shift; $command = 'abbrev' if ($command eq 'abbr'); my $result = docbook_add_id($command).">$acronym_text"; if ($with_explanation) { $result .= " ($explanation_text)"; } return $result; } sub docbook_image_files($$$$) { my $base = shift; my $extension = shift; my $texi_base = shift; my $texi_extension = shift; my @files = (); return @files if (!defined($base) or ($base eq '')); # FIXME should look at extension argument? makeinfo doesn't # push @files,"$base.$extension" if (defined($extension) and ($extension ne '')); foreach my $ext (@IMAGE_EXTENSIONS) { push @files, ["$base.$ext", "$texi_base.$ext"]; } return @files; } sub docbook_image($$$$$$$$$$$$$$$$;$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; my $base_simple_format = shift; my $extension_simple_format = shift; my $file_name_simple_format = shift; my $line_nr = shift; # if (!defined($file_path) or $file_path eq '' or $file_path =~ /\.txt$/) # { # if (defined($extension) and $extension ne '') # { # $file = "$base.$extension"; # } # else # { # $file = "$base.jpg"; # $extension = 'jpg'; # } # main::line_warn ("no image file for $base, (using $file)"); # } my $txt_path; my @files = (); my @extensions = @IMAGE_EXTENSIONS; foreach my $file_location (@$file_locations) { my ($file_located, $path, $file_simple_format) = @$file_location; my $extension = shift @extensions; if (defined($path)) { if ($extension eq 'txt' and !defined($txt_path)) { $txt_path = $path; } else { push @files, [$file_located, uc($extension), $file_simple_format]; } } } push @files, ["$base.jpg", 'JPG', "$base_simple_format.jpg" ] unless (@files); my $begin = docbook_add_id('inlinemediaobject').'>'; my $end = ''; if ($preformatted or !$in_paragraph) { $begin = docbook_add_id('informalfigure').'>'; $end = ''; } my $result = $begin; foreach my $file_spec (@files) { $result .= "[2]\" format=\"$file_spec->[1]\">"; } if (defined($txt_path)) { if (open(TXT, "<$txt_path")) { if (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and $USE_UNICODE) { binmode(TXT, ":encoding($Texi2HTML::THISDOC{'IN_ENCODING'})"); } $result.=""; while (my $img_txt = ) { $result .= $img_txt; } $result .= ''; close(TXT); } else { main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr); } } else { main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr); } return "$result$end"; } sub docbook_format_list_item_texi($$$$) { my $format = shift; my $line = shift; my $prepended = shift; my $command = shift; my $result_line = undef; if (defined($command) and $command ne '' and !exists $special_list_commands{$format}->{$command} and $format ne 'itemize') { #@*table $line =~ s/^\s*//; $line =~ s/\s*$//; if (exists ($style_map{$command})) { $result_line = "\@$command\{$line\}\n"; } elsif (exists ($things_map{$command})) { $result_line = "\@$command\{\} $line\n"; } else { $result_line = "\@$command $line\n"; } } return ($result_line, 0); } # row in multitable sub docbook_row($$;$$) { my $text = shift; my $macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $result = ''; if ($macro eq 'headitem') { if ($docbook_multitable_stack[-1] != 0) { $result .= ""; $result = "" . $result if ($docbook_multitable_stack[-1] == 1); $docbook_multitable_stack[-1] = 0; } } elsif ($docbook_multitable_stack[-1] != 1) { $result .= ""; $result = "" . $result if ($docbook_multitable_stack[-1] == 0); $docbook_multitable_stack[-1] = 1; } $result .= "$text"; return $result; } # cell in multitable sub docbook_cell($$;$$) { my $text = shift; my $row_macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; return "" . $text . ''; } # if varlistentry_state is > 0 it means that a varlistentry is opened. # if varlistentry_state is == 2 it means that we are in a succession # of term # if varlistentry_state is == 1 it means that we are in the line # Having a listitem in a varlistentry is a must, so an empty # listitem is added if a varlistentry is closed and varlistentry_state == 2 # # varlistentry acceps only term and listitem, so inter_item_commands # are put in the next term, or, if at the end of the table in a last # listitem sub docbook_table_item($$$$$$) { my $text = shift; my $index_label = shift; my $format = shift; my $command = shift; # my $formatted_command = shift; my $style_stack = shift; # my $text_formatted = shift; # my $text_formatted_leading_spaces = shift; # my $text_formatted_trailing_spaces = shift; my $item_cmd = shift; # $formatted_command = '' if (!defined($formatted_command)); # if (defined($text_formatted)) # { # $text_item = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces; # } # else # { # $text_item = $text; # } my $result = ''; my $prepended = ''; if (defined($docbook_table_stack[-1]->{'inter_item'})) { #$formatted_command = $docbook_table_stack[-1]->{'inter_item'} . $formatted_command; $prepended = $docbook_table_stack[-1]->{'inter_item'}; delete $docbook_table_stack[-1]->{'inter_item'}; } if ($item_cmd eq 'item') { if ($docbook_table_stack[-1]->{'varlistentry_state'} == 2) { $result .= ""; } if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1) { $result .= ''; } $docbook_table_stack[-1]->{'varlistentry_state'} = 2; $result .= ''; } $result .= ''; $result .= $prepended . $text ."\n"; return $result; } sub docbook_table_line($$$) { my $text = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); #print STDERR if ($text =~ /\S/) { if ($before_items) { return $text; } if ($only_inter_item_commands) { $docbook_table_stack[-1]->{'inter_item'} = $text; return ''; } else { $docbook_table_stack[-1]->{'varlistentry_state'} = 1; return "$text"; } #return $text; } else { return ''; } } sub docbook_list_item($$$$$$$$$) { my $text = shift; my $format = shift; my $command = shift; my $formatted_command = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $prepended = shift; my $prepended_formatted = shift; my $only_inter_item_commands = shift; my $before_items = shift; $only_inter_item_commands = '' if (!defined($only_inter_item_commands)); #my $prep_t = 'UNDEF'; $prep_t = $prepended if (defined($prepended)); #$item_nr = 0 if (!defined($item_nr)); #print STDERR " $item_nr --> $prep_t|${text}!!!!!\n"; #return $text if ($only_inter_item_commands and $before_items); return $text if ($before_items); return '' . $text . "\n"; } sub docbook_table_list($$$$$$$$$) { my $format_command = shift; my $text = shift; my $command = shift; my $formatted_command = shift; # enumerate my $item_nr = shift; my $enumerate_style = shift; # itemize my $prepended = shift; my $prepended_formatted = shift; # multitable my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $number = shift; my $result = "<$format_command>"; if ($format_command eq 'itemize') { my $itemfunction; #$prepended_formatted =~ s/^\s*// if (defined($prepended_formatted)); $prepended =~ s/^\s*// if (defined($prepended)); #if (defined($formatted_command) and $formatted_command ne '') if (defined($command) and $command ne '') { #$itemfunction = $formatted_command; $itemfunction = $command; #$itemfunction .= " $prepended_formatted" if (defined($prepended_formatted) and $prepended_formatted ne ''); $itemfunction .= " $prepended" if (defined($prepended) and $prepended ne ''); } #elsif (defined($prepended_formatted)) elsif (defined($prepended)) { #$itemfunction = $prepended_formatted; $itemfunction = $prepended; } my $mark = ''; $mark = " mark=\"$itemfunction\"" if (defined($itemfunction) and $itemfunction ne ''); return docbook_add_id('itemizedlist')."${mark}>$text"; } elsif ($format_command eq 'enumerate') { my $numeration='arabic'; if (defined($enumerate_style) and $enumerate_style ne '') { if ($enumerate_style =~ /^[A-Z]/) { $numeration = 'upperalpha'; } elsif ($enumerate_style =~ /^[a-z]/) { $numeration = 'loweralpha'; } } return docbook_add_id('orderedlist') ." numeration=\"$numeration\">$text"; } elsif ($format_command eq 'multitable') { my $result = docbook_add_id('informaltable').'>'; my $fractions; my $multiply = 1; if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY') and scalar(@$columnfractions)) { $fractions = [ @$columnfractions ]; $multiply = 100; } elsif (defined($prototype_lengths) and (ref($prototype_lengths) eq 'ARRAY') and scalar(@$prototype_lengths)) { $fractions = [ @$prototype_lengths ]; } if (defined ($fractions)) { foreach my $fraction (@$fractions) { $result .= ''; } } $text .= "" if ($docbook_multitable_stack[-1] == 1); $text .= "" if ($docbook_multitable_stack[-1] == 0); pop @docbook_multitable_stack; return $result . "$text"; } elsif ($format_command =~ /^(v|f)?table$/) { $result = docbook_add_id('variablelist').'>'; if (defined($docbook_table_stack[-1]->{'inter_item'})) { # there is a para in case there is only a comment, to avoid # an empty listitem $text .= "$docbook_table_stack[-1]->{'inter_item'}"; } elsif ($docbook_table_stack[-1]->{'varlistentry_state'} == 2) { $text .= ""; } $text .= '' if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1); pop @docbook_table_stack; return $result . "$text\n"; } } sub docbook_begin_format_texi($$$) { my $command = shift; my $line = shift; my $state = shift; push (@docbook_multitable_stack, -1) if ($command eq 'multitable'); push (@docbook_table_stack, {'varlistentry_state' => 0}) if ($command =~ /^(v|f)?table/); return $line; } # FIXME sub docbook_sp($$) { my $number = shift; my $preformatted = shift; return ""; } sub docbook_index_summary($$) { my $alpha = shift; my $nonalpha = shift; return ''; } sub docbook_printindex($$) { my $name = shift; my $printindex = shift; return docbook_add_id('index').">
    \n"; } sub docbook_complex_format($$) { my $name = shift; my $text = shift; return '' if ($text eq ''); my $result = docbook_add_id($docbook_complex_format{$name}).'>' .$text.""; return $result; } sub docbook_format($$) { my $name = shift; my $element = shift; my $text = shift; return '' if ($text eq ''); return $text if ($format_map{$name} eq ''); if ($name eq 'copying') { # FIXME is info in docbook 5.0 return "\n\n$text\n\n"; } return docbook_add_id($format_map{$name}).'>' .$text.""; } sub docbook_quotation_prepend_text($$) { my $command = shift; my $argument_text = shift; return undef if (!defined($argument_text) or $argument_text =~ /^$/); chomp($argument_text); return undef if (grep {lc($argument_text) eq $_} @docbook_special_quotation); return gdt('@b{{quotation_arg}:} ', {'quotation_arg' => $argument_text}, {'keep_texi' => 1}); } sub docbook_quotation($$$$$) { my $command = shift; my $text = shift; my $argument_text = shift; my $argument_text_texi = shift; my $authors = shift; $argument_text_texi = '' if (!defined($argument_text_texi)); chomp($argument_text_texi); my $docbook_command = 'blockquote'; if (grep {lc($argument_text_texi) eq $_} @docbook_special_quotation) { $docbook_command = lc($argument_text_texi); } my $attribution = ''; if ($authors) { foreach my $author (@$authors) { $attribution .= $author->{'author_text'}; } $attribution = '' .$attribution. '' . "\n"; } return docbook_add_id($docbook_command).'>' .$attribution . $text . "\n"; } sub docbook_style($$$$$$$$$) { my $style = shift; my $command = shift; my $text = shift; my $args = shift; my $no_close =shift; my $no_open = shift; my $line_nr = shift; my $state = shift; my $command_stack = shift; my $kept_line_nrs = shift; my $result = $text; if (exists($style->{'function'})) { my $function = $style->{'function'}; $result = &$function($command, $args, $command_stack, $state, $line_nr, $kept_line_nrs); } elsif (exists($style->{'inline_attribute'})) { my $element = $style->{'inline_attribute'}; my $attribute_text = ''; if ($element =~ /^(\w+)(\s+.*)/) { $element = $1; $attribute_text = $2; } if ($no_open) { $result = "<$element"; } else { $result = docbook_add_id($element); } $result .= "$attribute_text>$text"; } if (exists($style->{'begin'}) and !$no_open) { $result = $style->{'begin'} . $result; } if (exists($style->{'end'}) and !$no_close) { $result .= $style->{'end'}; } return $result; } sub docbook_raw($$$) { my $style = shift; my $text = shift; my $line_nr = shift; if ($style eq 'verbatim' or $style eq 'verbatiminclude') { return docbook_add_id('screen').'>' . &$protect_text($text) . ''; } return '' unless (grep {$style eq $_} @EXPAND); if ($style eq 'docbook') { chomp ($text); return $text; } else { main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr); return &$protect_text($text); } } sub docbook_cartouche($$) { my $text = shift; return $text; } sub docbook_anchor_label($$) { my $id = shift; my $anchor_text = shift; # FIXME use docbook_node_id return ''; } sub docbook_float($$$$$) { my $text = shift; my $float = shift; my $caption = shift; my $shortcaption = shift; my $label_texi = $float->{'texi'}; return $text if (!defined($label_texi) or $label_texi eq ''); return docbook_anchor_label('',$label_texi) . $text; } sub docbook_normal_text($$$$$$$;$) { my $text = shift; my $in_raw_text = shift; # remove_texi my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; #print STDERR "Bug: in_raw_text in_simple $text\n" if ($in_raw_text and $in_simple); my $style_stack = shift; my $state = shift; #$text = uc($text) if (in_cmd($style_stack, 'sc')); $text = &$protect_text($text) unless($in_raw_text); if (! $in_code and !$in_preformatted) { if (!$in_raw_text) { $text =~ s/---/\&mdash\;/g; $text =~ s/--/\&ndash\;/g; $text =~ s/``/\&ldquo\;/g; $text =~ s/''/\&rdquo\;/g; } else { #FIXME really do that ? It is done by makeinfo in html $text =~ s/``/"/g; $text =~ s/''/"/g; # FIXME really do that in raw text? $text =~ s/---/\x{1F}/g; $text =~ s/--/-/g; $text =~ s/\x{1F}/--/g; } } return $text; } sub docbook_noop { return ''; } 1; require "$T2H_HOME/formats/docbook.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/formats/docbook.init" && -r "$T2H_HOME/formats/docbook.init"); # @INIT_XML@ # vim: set filetype=perl: use strict; my @xml_multitable_stack = (); my @xml_table_stack = (); my @xml_ignored_misc_commands; my %xml_misc_command_output; my %xml_misc_elements_with_arg_map; my @xml_misc_elements_with_arg; my %def_format_xml; my $xml_current_section; sub xml_default_load(;$) { my $from_command_line = shift; t2h_default_set_variables_xml(); $DOCTYPE = ''; $SIMPLE_MENU = 0; $SEPARATE_DESCRIPTION = 1; @T2H_FORMAT_EXPAND = ('xml', 'direntry'); $USE_ISO = 0; $HEADERS = 0; $INLINE_INSERTCOPYING = 0; $SHOW_MENU = 1; $SHOW_TITLE = 0; $NUMBER_SECTIONS = 0; $USE_NODES = 1; $USE_SECTIONS = 1; t2h_default_push_handler(\&xml_init_variables, \@command_handler_init); $colon_command_punctuation_characters{'.'} = '.'; $colon_command_punctuation_characters{':'} = ':'; $colon_command_punctuation_characters{'?'} = '?'; $colon_command_punctuation_characters{'!'} = '!'; $simple_map{'*'} = '&linebreak;'; $simple_map{' '} = '&space;'; $simple_map{"\t"} = '&space;'; $simple_map{"\n"} = '&space;'; $simple_map{'.'} = '&eosperiod;'; $simple_map{'!'} = '&eosexcl;'; $simple_map{'?'} = '&eosquest;'; %simple_map_pre = %simple_map; # FIXME right? $things_map{'l'} = '/l'; $things_map{'L'} = '/L'; $things_map{'enddots'} = '&enddots;'; $things_map{'dots'} = '&dots;'; # FIXME equiv, point, expansion could be ameliorated $things_map{'equiv'} = '=='; $things_map{'point'} = '-!-'; $things_map{'expansion'} = '==>'; # →? $things_map{'minus'} = '−'; $things_map{'result'} = '⇒'; $things_map{'bullet'} = '•'; $things_map{'copyright'} = '©right;'; $things_map{'registeredsymbol'} = '®istered;'; $things_map{'arrow'} = '→'; $things_map{'TeX'} = '&tex;'; $things_map{'LaTeX'} = '&latex;'; %pre_map = %things_map; $stop_paragraph_command{'caption'} = 1; $stop_paragraph_command{'shortcaption'} = 1; %line_command_map = (); foreach my $command ('contents', 'shortcontents', 'summarycontents') { $line_command_map{$command} = $command; } %format_map = (); $format_map{'copying'} = ''; $format_map{'titlepage'} = 'titlepage'; $format_map{'documentdescription'} = 'documentdescription'; $format_map{'group'} = 'group'; $format_map{'raggedright'} = 'raggedright'; foreach my $region ('titlepage', 'documentdescription', 'copying') { $region_formats_kept{$region} = 1; } %style_map = (); t2h_default_copy_style_map (\%default_style_map, \%style_map); foreach my $style (keys(%style_map)) { next if grep {$style eq $_} ('asis', 'ctrl', 'w'); if (grep {$style eq $_} ('tieaccent', 'dotless', keys(%unicode_accents))) { $style_map{$style} = { 'function' => \&xml_default_accent }; } elsif (!exists($style_map{$style}->{'args'}) or (scalar(@{$style_map{$style}->{'args'}}) eq 1 and ($style_map{$style}->{'args'}->[0] eq 'code' or $style_map{$style}->{'args'}->[0] eq 'normal'))) { $style_map{$style}->{'inline_attribute'} = $style; delete ($style_map{$style}->{'quote'}); delete ($style_map{$style}->{'begin'}); delete ($style_map{$style}->{'end'}); delete ($style_map{$style}->{'function'}); } } foreach my $complex_format (keys(%complex_format_map)) { my $style = $complex_format_map{$complex_format}->{'style'}; delete $complex_format_map{$complex_format}; $complex_format_map{$complex_format}->{'begin'} = "<$complex_format xml:space=\"preserve\">"; $complex_format_map{$complex_format}->{'end'} = ""; $complex_format_map{$complex_format}->{'style'} = $style if (defined($style)); } foreach my $menu_command('menu', 'detailmenu', 'direntry', 'menu_comment') { $complex_format_map{$menu_command} = undef; delete $complex_format_map{$menu_command}; } # this is not needed because normal_text isn't the same than in html #t2h_remove_text_substitutions("'", 1, 0, 0, 1); #t2h_remove_text_substitutions('`', 1, 0, 0, 1); $style_map{'w'}->{'end'} = ''; $style_map{'='}->{'function'} = \&xml_macron; $style_map{'email'}->{'function'} = \&xml_email; $style_map{'titlefont'}->{'function'} = \&xml_titlefont; $style_map{'math'}->{'function'} = \&xml_math; $style_map{'uref'}->{'function'} = \&xml_uref; $style_map{'url'}->{'function'} = \&xml_uref; $style_map{'t'}->{'inline_attribute'} = 'tt'; # FIXME delete $special_accents{'ringaccent'}; $special_accents{'ogonek'} = 'aeiuAEIU'; %style_map_pre = %style_map; $no_paragraph_commands{'cindex'} = 0; #my @xml_ignored_misc_commands = ('bye', 'sp', 'verbatiminclude'); @xml_ignored_misc_commands = ('bye', 'sp', 'verbatiminclude', 'clickstyle', 'defcodeindex', 'syncodeindex', 'paragraphindent', 'shorttitlepage', 'refill', 'noindent'); # we want to proceed all the misc commands # makeinfo ignores clickstyle, changes setfilename. Not sure it is right. foreach my $misc_command (keys(%misc_command)) { next if (grep {$misc_command eq $_} @xml_ignored_misc_commands); $xml_misc_command_output{$misc_command} = 1; } $format_map{'menu'} = 'menu'; # checked on bug-texinfo, only node is in code_style, as with makeinfo --xml #$format_code_style{'menu'} = 1; #$format_code_style{'menu_name'} = 1; #$format_code_style{'menu_description'} = 1; $format_map{'detailmenu'} = 'detailmenu'; $format_map{'direntry'} = 'direntry'; $format_map{'menu_comment'} = ''; $menu_description = \&xml_menu_description; $menu_link = \&xml_menu_link; $element_heading = \&xml_heading; $heading = \&xml_heading; $paragraph = \&xml_paragraph; $preformatted = \&xml_preformatted; $misc_element_label = \&xml_noop; $element_label = \&xml_noop; $anchor_label = \&xml_anchor_label; $index_entry_label = \&xml_index_entry_label; $index_entry_command = \&xml_index_entry_command; $listoffloats = \&xml_listoffloats; $acronym_like = \&xml_acronym_like; $foot_line_and_ref = \&xml_foot_line_and_ref; $image = \&xml_image; $sp = \&xml_sp; $quotation = \&xml_quotation; $table_list = \&xml_table_list; $row = \&xml_row; $cell = \&xml_cell; $list_item = \&xml_list_item; $format_list_item_texi = \&xml_format_list_item_texi; $misc_command_line = \&xml_misc_commands; $begin_format_texi = \&xml_begin_format_texi; $def_line = \&xml_def_line; $def = \&xml_def; $def_item = \&xml_def_item; $printindex = \&xml_printindex; $index_summary = \&xml_index_summary; $external_ref = \&xml_external_ref; $internal_ref = \&xml_internal_ref; $table_item = \&xml_table_item; $table_line = \&xml_table_line; $float = \&xml_float; $caption_shortcaption = \&xml_caption_shortcaption; $caption_shortcaption_command = \&xml_caption_shortcaption_command; $normal_text = \&xml_normal_text; $protect_text = \&xml_default_protect_text; $paragraph_style_command = \&xml_paragraph_style_command; $raw = \&xml_raw; $cartouche = \&xml_cartouche; $print_Top = \&xml_print_Top; $print_Top_footer = \&xml_print_Top_footer; $print_page_head = \&xml_print_page_head; $print_foot_navigation = \&xml_noop; $toc_body = \&xml_noop; $about_body = \&xml_noop; $print_page_foot = \&xml_print_page_foot; $end_section = \&xml_end_section; $one_section = \&xml_one_section; %xml_misc_elements_with_arg_map = ( 'title' => 'booktitle', 'subtitle' => 'booksubtitle' ); @xml_misc_elements_with_arg = ('author', 'dircategory', 'settitle'); #my @xml_misc_elements_with_arg = ('author', 'shorttitlepage', # 'vskip', 'dircategory', 'settitle'); %def_format_xml = ( 'deffn' => [ ['category', 'category'], ['function', 'name'] ], 'defvr' => [ ['category', 'category'], ['variable', 'name'] ], 'deftypefn' => [ ['category', 'category'], ['type', 'type'], ['function', 'name'] ], 'deftypeop' => [ ['category', 'category'], ['type', 'type'], ['operation', 'name'] ], 'deftypevr' => [ ['category', 'category'], ['type', 'type'], ['variable', 'name'] ], 'defcv' => [ ['category' , 'category'], ['class', 'class'], ['classvar', 'name'] ], 'deftypecv' => [ ['category', 'category'], ['type', 'type'], ['classvar', 'name'] ], 'defop' => [ ['category', 'category'], ['class', 'class'], ['operation', 'name'] ], 'deftp' => [ ['category', 'category'], ['datatype', 'name'] ] ); } sub xml_macron($$) { my $accent = shift; my $args = shift; return $args->[0] . "¯"; } sub xml_email($$) { my $command = shift; my $args = shift; my $mail = shift @$args; my $text = shift @$args; $mail = main::normalise_space($mail); my $result = "$mail"; if (defined($text) and $text =~ /\S/) { $result .= "".main::normalise_space($text).""; } return $result . ''; } sub xml_uref($$) { shift; my $args = shift; my $url = shift @$args; my $text = shift @$args; my $replacement = shift @$args; $url = main::normalise_space($url); $replacement = '' if (!defined($replacement)); $replacement = main::normalise_space($replacement); $text = '' if (!defined($text)); $text = main::normalise_space($text); my $result = "$url"; $result .= "$text" if ($text ne ''); $result .= "$replacement" if ($replacement ne ''); return $result.''; } sub xml_titlefont($$) { shift; my $args = shift; return "$args->[0]"; } sub xml_math($$) { shift; my $args = shift; my $text = shift @$args; return "$text"; } sub xml_menu_description($$$) { my $text = shift; my $state = shift; my $element_text = shift; return "$text\n"; } sub xml_menu_link($$$$$$$$$$) { my $entry = shift; my $state = shift; my $href = shift; my $menunode = shift; my $menutitle = shift; my $ending = shift; my $has_title = shift; my $command_stack = shift; my $in_preformatted = shift; my $menunode_normalized = shift; return "\n$menunode_normalized\n$menutitle\n"; } sub xml_print_page_head($) { my $fh = shift; my $setfilename = ''; $setfilename = "$Texi2HTML::THISDOC{file_base_name}.$EXTENSION" unless (defined($Texi2HTML::THISDOC{'setfilename'}) and $Texi2HTML::THISDOC{'setfilename'} ne ''); my $language = get_conf('documentlanguage'); my $doctype = get_conf('doctype'); print $fh < $doctype $setfilename EOT } sub xml_print_page_foot($) { my $fh = shift; print $fh "". xml_close_section(); print $fh < EOT } sub xml_one_section($$) { my $fh = shift; my $element = shift; main::print_lines($fh); #print $fh "". xml_footing($element); &$print_foot_navigation($fh); &$print_page_foot($fh); } sub xml_heading($$$$$) { my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; #print STDERR "'$command' $line"; if (defined($command) and $command =~ /heading/) { my $text = ''; if (defined($line)) { $text = $line; # this isn't done in main program in that case... chomp ($text); $text =~ s/^\s*//; } return "<${command}>$text\n"; } elsif (defined($command) and $command eq 'node') { #print STDERR "node $command $node_element->{'texi'}\n"; my $result = ''; $result .= xml_close_section(); $result .= "\n"; $result .= "$element->{'text'}\n"; foreach my $direction('nodenext', 'nodeprev', 'nodeup') { if ($element->{$direction}) { $result .= "<${direction}>$element->{$direction}->{'text'}\n"; } } $result .= "\n"; return $result; } else { my $result = ''; $result .= xml_close_section(); $result .= "<".xml_element_tag($element).">\n$element->{'text'}\n"; $xml_current_section = $element; return $result; } } sub xml_element_tag($) { my $element = shift; my $class = $element->{'tag_level'}; return $class; } sub xml_close_section() { my $element = $xml_current_section; if (!defined($element)) { return ''; } my $result = ''; $xml_current_section = undef; # there is a special case for a @chapter that is a child of @top # but should not be considered as is, since it is also toplevel. # @part, however may have other toplevel elements as children. return '' if ($element->{'child'} and (!$element->{'child'}->{'toplevel'} or $element->{'tag'} ne 'top')); $result .= '\n"; my $current = $element; # the second condition is such that top is closed only if it has # sub-elements below chapter. # the third condition is such that elements with a next element are # only closed for the last element, except when the next element is # toplevel and below top, such that @top is closed before the first # @chapter if there are @section or the like below @top while ($current->{'sectionup'} and !($current->{'sectionup'}->{'tag'} eq 'top' and $current->{'toplevel'}) and (!$current->{'childnext'} or ($current->{'childnext'}->{'toplevel'} and $current->{'sectionup'}->{'tag'} eq 'top'))) { $current = $current->{'sectionup'}; $result .= '\n"; } return $result; ## there is a special case for a @chapter that is a child of @top ## but should not be considered as is, since it is also toplevel. #return '' if ($element->{'child'} and !$element->{'child'}->{'toplevel'}); #$result .= '\n"; #return $result if ($element->{'sectionnext'} or $element->{'level'} <= 1); #my $current = $element; #while ($current->{'level'} != 1 and $current->{'sectionup'} and !$current->{'sectionnext'}) #{ # $current = $current->{'sectionup'}; # $result .= '\n"; #} #return $result; } sub xml_end_section($$$) { my $fh = shift; my $end_foot_navigation = shift; my $element = shift; } sub xml_print_Top($$$) { my $fh = shift; my $has_top_heading = shift; my $element = shift; main::print_lines($fh, $Texi2HTML::THIS_SECTION); } sub xml_print_Top_footer($$) { my $fh = shift; my $end_page = shift; my $element = shift; } # FIXME warning: # # @samp{first para # # second para}. # # maybe should lead to: # first para second para. # # But it leads to # first para # # second para. # sub xml_paragraph($$$$$$$$$$$$) { my $text = shift; my $align = shift; my $indent = shift; my $paragraph_command = shift; my $paragraph_command_formatted = shift; my $paragraph_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; # no para in multitables, caption and shortcaptions. my $top_stack = ''; $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); return $text if ($top_stack eq 'multitable' or $top_stack eq 'shortcaption' or $top_stack eq 'caption' or $top_stack eq 'documentdescription'); if ($text =~ /\S/) { return "$text"; } return $text; } sub xml_preformatted($$$$$$$$$$$$) { my $text = shift; my $pre_style = shift; my $class = shift; my $leading_command = shift; my $leading_command_formatted = shift; my $preformatted_number = shift; my $format = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $command_stack_at_end = shift; my $command_stack_at_begin = shift; return $text; } sub xml_misc_commands($$$$$) { my $macro = shift; my $line = shift; my $args = shift; my $stack = shift; my $state = shift; #print STDERR "$macro $line"; #print STDERR "ARGS @$args\n" if defined ($args); return ($macro, $line, undef) unless($xml_misc_command_output{$macro}); my $value_name = ''; my $value = ''; if ($macro eq 'set' or $macro eq 'clear') { my $value_line = $line; if ($value_line =~ s/^\s+([\w\-]+)//) { $value_name = $1; if ($macro eq 'set') { $value = $value_line; chomp ($value); $value =~ s/^\s*//; } } } my $result_text = "<${macro}>"; if ($macro eq 'set' or $macro eq 'clear') { $result_text = "<${macro}value name=\"$value_name\">$value\n"; } if ($macro eq 'c' or $macro eq 'comment' and scalar(@$args)) { my $comment_line = $args->[0]; chomp ($comment_line); # makeinfo remove all the leading spaces $comment_line =~ s/^\s//; $result_text = &$comment ($comment_line); } if ($macro eq 'frenchspacing') { my $value = $args->[0]; $value =~ s/\s*//g; $result_text = "<${macro} var=\"$value\">"; } if (grep {$macro eq $_} @xml_misc_elements_with_arg) { my $arg = $args->[0]; $arg =~ s/^\s*//; chomp($arg); $result_text = "<${macro}>".main::substitute_line($arg, "\@$macro")."\n"; } if (exists($xml_misc_elements_with_arg_map{$macro})) { my $arg = $args->[0]; $arg =~ s/^\s*//; chomp($arg); $result_text = "<$xml_misc_elements_with_arg_map{$macro}>".main::substitute_line($arg, "\@$macro")."\n"; } if ($macro eq 'setfilename') { my $arg = $args->[0]; #$arg =~ s/^\s*//; #$arg =~ s/\s*$//; #$arg = main::substitute_line($arg, "\@$macro"); if ($arg =~ /\S/) { $arg = get_conf('setfilename'); $arg =~ s/\.[^\.]*$//; $result_text = "<${macro}>${arg}.xml\n"; } } return ($macro, $line, $result_text); } sub xml_anchor_label($$) { my $id = shift; my $anchor_text = shift; return ''; } sub xml_index_entry_command($$$$$) { my $command = shift; my $index_name = shift; my $label = shift; my $entry_texi = shift; my $entry_formatted = shift; return $label if (defined($label) and $label ne ''); return xml_index_entry_label('','','',$main::index_prefix_to_name{$index_name}, '', '', $entry_formatted, {}); } sub xml_index_entry_label($$$$$$$$$) { my $identifier = shift; my $preformatted = shift; my $formatted_entry = shift; my $index_name = shift; my $index_command = shift; my $texi_entry = shift; my $formatted_entry_reference = shift; my $in_region_not_in_output = shift; my $index_entry_ref = shift; return "${formatted_entry_reference}"; } sub xml_listoffloats($$$) { my $style_texi = shift; my $style = shift; my $float_entries = shift; # FIXME style, style_texi? Protected? return ""; } sub xml_acronym_like($$$$$$) { my $command = shift; my $acronym_texi = shift; my $acronym_text = shift; my $with_explanation = shift; my $explanation_lines = shift; my $explanation_text = shift; my $explanation_simply_formatted = shift; $command = 'abbrev' if ($command eq 'abbr'); my $opening = "<${command}><${command}word>$acronym_text"; if ($with_explanation) { $opening .= "<${command}desc>$explanation_text"; } return $opening . ""; } sub xml_foot_line_and_ref($$$$$$$) { my $number_in_doc = shift; my $number_in_page = shift; my $footnote_id = shift; my $place_id = shift; my $document_file = shift; my $footnote_file = shift; my $lines = shift; my $state = shift; my $result = ''; foreach my $line (@$lines) { $result .= $line; } return ([], $result . ''); } sub xml_image($$$$$$$$$$$$$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; $alt = '' if (!defined($alt)); # dirty hack to avoid " that can be here because of a @verb $alt =~ s/"/"/g; $width = '' if (!defined($width)); $height = '' if (!defined($height)); my $tag = 'inlineimage'; $tag = 'image' if ($preformatted or !$in_paragraph); return "<$tag width=\"$width\" height=\"$height\" name=\"". &$protect_text($base)."\" extension=\"$extension\">$alt"; } sub xml_sp($$) { my $number = shift; my $preformatted = shift; return "\n"; } sub xml_quotation($$$$$) { my $command = shift; my $text = shift; my $argument_text = shift; my $argument_text_texi = shift; my $authors = shift; return "<$command>\n" . $text . "\n"; } sub xml_format_list_item_texi($$$$) { my $format = shift; my $line = shift; my $prepended = shift; my $command = shift; my $result_line = undef; if (defined($command) and $command ne '' and !exists $special_list_commands{$format}->{$command} and $format ne 'itemize') { #@*table $line =~ s/^\s*//; $line =~ s/\s*$//; if (exists ($style_map{$command})) { $result_line = "\@$command\{$line\}\n"; } elsif (exists ($things_map{$command})) { $result_line = "\@$command\{\} $line\n"; } else { $result_line = "\@$command $line\n"; } } return ($result_line, 0); } sub xml_list_item($$$$$$$$$) { my $text = shift; my $format = shift; my $command = shift; my $formatted_command = shift; my $item_nr = shift; my $enumerate_style = shift; my $number = shift; my $prepended = shift; my $prepended_formatted = shift; return '' . $text . "\n"; } sub xml_init_variables() { @xml_multitable_stack = (); @xml_table_stack = (); $xml_current_section = undef; $Texi2HTML::THISDOC{'SPLIT'} = 0 if ($OUTPUT_FORMAT eq 'xml'); } # row in multitable sub xml_row($$;$$) { my $text = shift; my $macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; my $result = ''; if ($macro eq 'headitem') { if ($xml_multitable_stack[-1] != 0) { $result .= ""; $result = "" . $result if ($xml_multitable_stack[-1] == 1); $xml_multitable_stack[-1] = 0; } } elsif ($xml_multitable_stack[-1] != 1) { $result .= ""; $result = "" . $result if ($xml_multitable_stack[-1] == 0); $xml_multitable_stack[-1] = 1; } $result .= "$text"; return $result; } # cell in multitable sub xml_cell($$;$$) { my $text = shift; my $row_macro = shift; my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $column_number = shift; return "" . $text . ''; } sub xml_table_list($$$$$$$$$) { my $format_command = shift; my $text = shift; my $command = shift; my $formatted_command = shift; # enumerate my $item_nr = shift; my $enumerate_style = shift; # itemize my $prepended = shift; my $prepended_formatted = shift; # multitable my $columnfractions = shift; my $prototype_row = shift; my $prototype_lengths = shift; my $number = shift; my $result = "<$format_command>"; if ($format_command eq 'itemize') { my $itemfunction; $prepended_formatted =~ s/^\s*// if (defined($prepended_formatted)); if (defined($formatted_command) and $formatted_command ne '') { $itemfunction = $formatted_command; $itemfunction .= " $prepended_formatted" if (defined($prepended_formatted) and $prepended_formatted ne ''); } elsif (defined($prepended_formatted)) { $itemfunction = $prepended_formatted; } $itemfunction = "•" if (!defined($itemfunction) or $itemfunction eq ''); $result .= "$itemfunction"; } elsif ($format_command eq 'enumerate') { $result = "<$format_command first=\"$enumerate_style\">"; } elsif ($format_command eq 'multitable') { my $fractions; my $multiply = 1; if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY') and scalar(@$columnfractions)) { $fractions = [ @$columnfractions ]; $multiply = 100; } elsif (defined($prototype_lengths) and (ref($prototype_lengths) eq 'ARRAY') and scalar(@$prototype_lengths)) { $fractions = [ @$prototype_lengths ]; } if (defined ($fractions)) { foreach my $fraction (@$fractions) { $result .= "".($fraction*$multiply)."\n"; } } $text .= "" if ($xml_multitable_stack[-1] == 1); $text .= "" if ($xml_multitable_stack[-1] == 0); pop @xml_multitable_stack; } elsif ($format_command =~ /^(v|f)?table$/) { $result = ''; $text .= '' if ($xml_table_stack[-1] == 1); pop @xml_table_stack; return $result . "$text
    \n"; } return $result . "$text\n"; } sub xml_begin_format_texi($$$) { my $command = shift; my $line = shift; my $state = shift; push (@xml_multitable_stack, -1) if ($command eq 'multitable'); push (@xml_table_stack, 0) if ($command =~ /^(v|f)?table/); return $line; } sub xml_def_line($$$$$$$$$$$$$$$) { my $category_prepared = shift; my $name = shift; my $type = shift; my $arguments = shift; my $index_label = shift; my $arguments_array = shift; my $arguments_type_array = shift; my $unformatted_arguments_array = shift; my $command = shift; my $class_name = shift; my $category = shift; my $class = shift; my $style = shift; my $original_command = shift; my $result = "$class_name"; my %arguments = ( 'prepared_category' => $category_prepared, 'category' => $category, 'name' => $name, 'type' => $type, 'class' => $class ); foreach my $type (keys(%arguments)) { $arguments{$type} = '' if (!defined($arguments{$type})); } foreach my $mandatory_arg (@{$def_format_xml{$command}}) { my $elem = $mandatory_arg->[0]; $result .= "$arguments{$mandatory_arg->[1]}"; } my $params = ''; my @types = @$arguments_type_array; foreach my $arg (@$arguments_array) { my $type = shift @types; if (grep {$_ eq $type} ('param', 'paramtype', 'delimiter')) { $result .= "$arg"; } } $result .= "\n"; return $result; } # FIXME # @deffn # @c comment # @end deffn # leads to the creation of a with a comment within, # while there should be no definitionitem sub xml_def_item($$) { my $text = shift; my $only_inter_item_commands = shift; if ($text =~ /\S/) { return '' . $text . '' unless $only_inter_item_commands; return $text; } return ''; } sub xml_def($) { my $text = shift; return ''.$text.''; } sub xml_index_summary($$) { my $alpha = shift; my $nonalpha = shift; return ''; } sub xml_printindex($$) { my $name = shift; my $printindex = shift; return "$name\n"; } sub xml_any_ref($$) { my $type = shift; my $args = shift; my $result = ''; if ($type eq 'pxref') { $result = gdt('see ',{'duplicate'=>1}); } elsif ($type eq 'xref' or $type eq 'inforef') { $result = gdt('See ',{'duplicate'=>1}); } if ($type eq 'inforef') { $result .= "$args->[0]"; $result .= "$args->[1]" if ($args->[1] ne ''); $result .= "$args->[2]" } else { $result .= "$args->[0]"; $result .= "$args->[1]" if ($args->[1] ne ''); $result .= "$args->[2]" if ($args->[2] ne ''); $result .= "$args->[3]" if ($args->[3] ne ''); $result .= "$args->[4]" if ($args->[4] ne ''); $result .= ''; } return $result; } sub xml_external_ref($$$$$$$$$) { my $type = shift; my $section = shift; my $book = shift; my $file = shift; my $href = shift; my $cross_ref = shift; my $args_texi = shift; my $formatted_args = shift; my $node = shift; return xml_any_ref ($type, $formatted_args); } sub xml_internal_ref($$$$$) { my $type = shift; my $href = shift; my $short_name = shift; my $name = shift; my $is_section = shift; my $args_texi = shift; my $formatted_args = shift; return xml_any_ref ($type, $formatted_args); } sub xml_table_item($$$$$$$) { my $text = shift; my $index_label = shift; my $format = shift; my $command = shift; # my $formatted_command = shift; my $style_stack = shift; # my $text_formatted = shift; # my $text_formatted_leading_spaces = shift; # my $text_formatted_trailing_spaces = shift; my $item_cmd = shift; my $formatted_index_entry = shift; # $formatted_command = '' if (!defined($formatted_command)); # # if (defined($text_formatted)) # { # $text_item = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces; # } # else # { # $text_item = $text; # } my $result = ''; if ($item_cmd eq 'item') { $result .= '' if ($xml_table_stack[-1] == 1); $xml_table_stack[-1] = 1; $result .= ''; } $result .= ''; #print STDERR "$text | $format | $command | $formatted_command | $text_formatted | $item_cmd \n"; my $indexterm = ''; #print STDERR "FFFFFFFFFFFFFFFFf `$index_label' `$text'\n"; if ($format =~ /^(v|f)/) { # my $index_prefix = $1; # $indexterm = $text; # $indexterm =~ s/^\s*//; # $result .= "$formatted_index_entry"; $result .= "$index_label"; } $result .= $text ."\n"; return $result; } sub xml_table_line($) { my $text = shift; my $only_inter_item_commands = shift; my $before_items = shift; if ($text =~ /\S/) { return "$text" unless $only_inter_item_commands; return $text; } else { return ''; } } sub xml_caption_shortcaption($) { my $float = shift; my $caption_lines; my $shortcaption_lines; if (defined($float->{'caption_texi'})) { @$caption_lines = @{$float->{'caption_texi'}}; } if (defined($float->{'shortcaption_texi'})) { @$shortcaption_lines = @{$float->{'shortcaption_texi'}}; } return ($caption_lines, $shortcaption_lines); } sub xml_caption_shortcaption_command($$$) { my $command = shift; my $text = shift; my $texi_lines = shift; my $float_element = shift; if ($text =~ /\S/) { return "<$command>$text"; } return ''; } sub xml_float($$$$$) { my $text = shift; my $float = shift; my $caption = shift; my $shortcaption = shift; # FIXME don't use the texi, but a normalized node name my $label_texi = $float->{'texi'}; $label_texi = '' if (!defined($label_texi)); my $result = "\n"; my $style = $float->{'style'}; $style = '' if (!defined($style)); $result .= "$style\n"; $result .= "\n"; $result .= $text; return $result."\n"; } sub xml_normal_text($$$$$$$;$) { my $text = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_code = shift; my $in_math = shift; my $in_simple = shift; #print STDERR "Bug: in_raw_text in_simple $text\n" if ($in_raw_text and $in_simple); my $style_stack = shift; my $state = shift; $text = &$protect_text($text) unless($in_raw_text); if (! $in_code and !$in_preformatted and !$in_raw_text) { $text =~ s/---/\&mdash\;/g; $text =~ s/--/\&ndash\;/g; $text =~ s/``/\&ldquo\;/g; $text =~ s/''/\&rdquo\;/g; } return $text; } sub xml_paragraph_style_command($$) { my $format = shift; my $text = shift; return "<$format>$text" if ($format eq 'center'); return $text; } sub xml_raw($$) { my $style = shift; my $text = shift; if ($style eq 'verbatim' or $style eq 'verbatiminclude') { return '' . &$protect_text($text) . ''; } return '' unless (grep {$style eq $_} @EXPAND); if ($style eq 'xml') { chomp ($text); return $text; } else { main::msg_warn ("Raw style $style not handled", $Texi2HTML::THISDOC{'line_nr'}); return &$protect_text($text); } } sub xml_cartouche($$) { my $text = shift; return "$text"; } sub xml_noop { return ''; } 1; require "$T2H_HOME/formats/xml.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/formats/xml.init" && -r "$T2H_HOME/formats/xml.init"); # @INIT_PLAINTEXT@ #+############################################################################## # # plaintext.init: convert to plaintext # # Copyright (C) 2009 Patrice Dumas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # #-############################################################################## use strict; sub plaintext_default_load(;$) { my $from_command_line = shift; info_default_load(); $SHOW_MENU = 0; $OUT = '-' unless(defined($OUT) and $OUT !~ m:/$:); $HEADERS = 0; @T2H_FORMAT_EXPAND = ('plaintext'); $print_page_head = \&plaintext_default_print_page_head; $print_page_foot = \&plaintest_default_print_page_foot; $element_heading = \&plaintext_default_element_heading; $image = \&plaintext_default_image; $print_index = \&plaintext_default_print_index; } sub plaintext_default_print_page_head($) { my $fh = shift; } sub plaintest_default_print_page_foot($) { my $fh = shift; } sub plaintext_default_element_heading($$$$$$$$$$$$) { my $info_result = &Texi2HTML::Config::info_default_element_heading(@_); my $element = shift; my $command = shift; my $texi_line = shift; my $line = shift; my $in_preformatted = shift; my $one_section = shift; my $element_heading = shift; my $first_in_page = shift; my $is_top = shift; my $previous_is_top = shift; my $command_line = shift; my $element_id = shift; my $new_element = shift; return $info_result if (!$element->{'node'}); return ''; } sub plaintext_default_image($$$$$$$$$$$$$$$$$) { my $file = shift; my $base = shift; my $preformatted = shift; my $file_name = shift; my $alt = shift; my $width = shift; my $height = shift; my $raw_alt = shift; my $extension = shift; my $working_dir = shift; my $file_path = shift; my $in_paragraph = shift; my $file_locations = shift; my $base_simple_format = shift; my $extension_simple_format = shift; my $file_name_simple_format = shift; my $line_nr = shift; my $txt_path; my $found_file; my @extensions = @IMAGE_EXTENSIONS; if (defined($extension) and ($extension ne '')) { unshift @extensions, ".$extension"; unshift @extensions, "$extension"; } else { $extension = undef; } my $file_found_index = undef; my $file_index = 0; foreach my $file_location (@$file_locations) { my ($file_located, $path, $file_simple_format) = @$file_location; my $extension = shift @extensions; if (defined($path)) { if ($extension eq 'txt' and !defined($txt_path)) { $txt_path = $path; } elsif (!defined($found_file)) { $found_file = [$file_located, $extension, $file_simple_format]; $file_found_index = $file_index; } } $file_index++; } my $text = ''; if (defined($txt_path)) { if (open(TXT, "<$txt_path")) { if (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and $USE_UNICODE) { binmode(TXT, ":encoding($Texi2HTML::THISDOC{'IN_ENCODING'})"); } $text='[' if ($in_paragraph or $preformatted); while (my $img_txt = ) { $text .= $img_txt; } $text .= ']' if ($in_paragraph or $preformatted); close(TXT); } else { main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr); } } elsif (!defined($found_file)) { main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr); } return $text; } sub plaintext_default_print_index($$) { my $text = shift; my $name = shift; return ''; } 1; require "$T2H_HOME/formats/plaintext.init" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/formats/plaintext.init" && -r "$T2H_HOME/formats/plaintext.init"); my $translation_file = 'translations.pl'; # file containing all the translations my $T2H_OBSOLETE_STRINGS; # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, # if $T2H_HOME/translations.pl exists. # # @T2H_TRANSLATIONS_FILE@ # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'nl'} = { ' The buttons in the navigation panels have the following meaning:' => '', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', ' Up ' => '', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => '', 'About (help)' => '', 'About This Document' => 'No translation available!', 'April' => 'April', 'August' => 'Augustus', 'Back' => '', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => '', 'Button' => '', 'Contents' => '', 'Cover (top) of document' => '', 'Current' => '', 'Current Position' => '', 'Current section' => '', 'December' => 'December', 'FastBack' => '', 'FastForward' => '', 'February' => 'Februari', 'First' => '', 'First section in reading order' => '', 'Following' => '', 'Following node' => '', 'Footnotes' => 'No translation available!', 'Forward' => '', 'Forward section in next file' => '', 'From 1.2.3 go to' => '', 'Go to' => '', 'Index' => 'Index', 'Index Entry' => '', 'January' => 'Januari', 'July' => 'Juli', 'Jump to' => '', 'June' => 'Juni', 'Last' => '', 'Last section in reading order' => '', 'March' => 'Maart', 'May' => 'Mei', 'Menu:' => '', 'Name' => '', 'Next' => '', 'Next chapter' => '', 'Next file' => '', 'Next node' => '', 'Next section in reading order' => '', 'Next section on same level' => '', 'NextFile' => '', 'Node following in node reading order' => '', 'Node up' => '', 'NodeNext' => '', 'NodePrev' => '', 'NodeUp' => '', 'November' => 'November', 'October' => 'Oktober', 'Overview' => '', 'Prev' => '', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => '', 'Previous section in reading order' => '', 'Previous section on same level' => '', 'Section' => '', 'Section One' => '', 'See ' => '', 'See @cite{{book}}' => '', 'See `{section}\'' => '', 'See `{section}\' in @cite{{book}}' => '', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => '', 'See {reference_name}' => '', 'See {reference}' => '', 'See {reference} in @cite{{book}}' => '', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'September', 'Short Table of Contents' => 'Korte inhoudsopgave', 'Short table of contents' => '', 'Subsection One-Four' => '', 'Subsection One-One' => '', 'Subsection One-Three' => '', 'Subsection One-Two' => '', 'Subsubsection One-Two-Four' => '', 'Subsubsection One-Two-One' => '', 'Subsubsection One-Two-Three' => '', 'Subsubsection One-Two-Two' => '', 'Table of Contents' => 'Inhoudsopgave', 'Table of contents' => '', 'The node you are looking for is at {href}.' => '', 'This' => '', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => '', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => '', 'Top' => '', 'Untitled Document' => '', 'Up' => '', 'Up node' => '', 'Up section' => '', '`{section}\'' => '', '`{section}\' in @cite{{book}}' => '', 'current' => '', 'on @emph{{date}}' => '', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => '', 'see `{section}\'' => '', 'see `{section}\' in @cite{{book}}' => '', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section {reference_name}' => '', 'see {reference_name}' => '', 'see {reference}' => '', 'see {reference} in @cite{{book}}' => '', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '', '{name} of {class}' => '', '{name} on {class}' => '', '{reference_name}' => '', '{reference}' => '', '{reference} in @cite{{book}}' => '', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'ja'} = { ' The buttons in the navigation panels have the following meaning:' => 'ナビゲーションパネル中のボタンには以下の意味があります。', ' 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項}を現在位置に仮定しています。', ' Up ' => '上', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => '', 'About (help)' => '', 'About This Document' => 'この文書について', 'April' => '4月', 'August' => '8月', 'Back' => '', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => '', 'Button' => 'ボタン', 'Contents' => '目次', 'Cover (top) of document' => '', 'Current' => '', 'Current Position' => '現在位置', 'Current section' => '', 'December' => '12月', 'FastBack' => '', 'FastForward' => '', 'February' => '2月', 'First' => '', 'First section in reading order' => '', 'Following' => '', 'Following node' => '', 'Footnotes' => '脚注', 'Forward' => '', 'Forward section in next file' => '', 'From 1.2.3 go to' => '1.2.3項からの移動先', 'Go to' => '移動先', 'Index' => '見出し', 'Index Entry' => '見出し一覧', 'January' => '1月', 'July' => '7月', 'Jump to' => '移動', 'June' => '6月', 'Last' => '', 'Last section in reading order' => '', 'March' => '3月', 'May' => '5月', 'Menu:' => 'メニュー', 'Name' => '名称', 'Next' => '次', 'Next chapter' => '', 'Next file' => '', 'Next node' => '', 'Next section in reading order' => '', 'Next section on same level' => '', 'NextFile' => '', 'Node following in node reading order' => '', 'Node up' => '', 'NodeNext' => '', 'NodePrev' => '', 'NodeUp' => '', 'November' => '11月', 'October' => '10月', 'Overview' => '概要', 'Prev' => '前', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => '', 'Previous section in reading order' => '', 'Previous section on same level' => '', 'Section' => '項', 'Section One' => '第1項', 'See ' => '', 'See @cite{{book}}' => '', 'See `{section}\'' => '項', 'See `{section}\' in @cite{{book}}' => '@cite{{book}}の `{section}\' ', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => '', 'See {reference_name}' => '', 'See {reference}' => '', 'See {reference} in @cite{{book}}' => '{node_file_href} @cite{{book}}参照', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => '9月', 'Short Table of Contents' => '簡略化した目次', 'Short table of contents' => '', 'Subsection One-Four' => '第1.4項', 'Subsection One-One' => '第1.1項', 'Subsection One-Three' => '第1.3項', 'Subsection One-Two' => '第1.2項', 'Subsubsection One-Two-Four' => '第1.2.4項', 'Subsubsection One-Two-One' => '第1.2.1項', 'Subsubsection One-Two-Three' => '第1.2.3項', 'Subsubsection One-Two-Two' => '第1.2.2項', 'Table of Contents' => '目次', 'Table of contents' => '', 'The node you are looking for is at {href}.' => '', 'This' => '', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'この文書は@emph{{date}}に@uref{{program_homepage}, @emph{{program}}}を用いて生成されました。', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'この文書は@uref{{program_homepage}, @emph{{program}}}を用いて生成されました。', 'Top' => '冒頭', 'Untitled Document' => '無題の文書', 'Up' => '', 'Up node' => '', 'Up section' => '', '`{section}\'' => '項', '`{section}\' in @cite{{book}}' => '@cite{{book}}の `{section}\' ', 'current' => '現在位置', 'on @emph{{date}}' => '@emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => '', 'see `{section}\'' => '', 'see `{section}\' in @cite{{book}}' => '@cite{{book}}の `{section}\' ', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section {reference_name}' => '', 'see {reference_name}' => '', 'see {reference}' => '{node_file_href}参照', 'see {reference} in @cite{{book}}' => '{node_file_href} @cite{{book}}参照', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '', '{name} of {class}' => '', '{name} on {class}' => '', '{reference_name}' => '', '{reference}' => '', '{reference} in @cite{{book}}' => '{node_file_href} @cite{{book}}参照', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'fr'} = { ' The buttons in the navigation panels have the following meaning:' => ' Les boutons de navigation ont la signification suivante :', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' Dans cet exemple on est @`a @strong{ Sous sous section un-deux-trois } dans un document dont la structure est :', ' Up ' => 'Plus haut', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => 'A propos', 'About (help)' => 'A propos (page d\'aide)', 'About This Document' => 'A propos de ce document', 'April' => 'avril', 'August' => 'ao@^ut', 'Back' => 'Retour', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => 'D@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent', 'Button' => 'Bouton', 'Contents' => 'Table des mati@`eres', 'Cover (top) of document' => 'Couverture (top) du document', 'Current' => '', 'Current Position' => 'Position', 'Current section' => 'Section actuelle', 'December' => 'd@\'ecembre', 'FastBack' => 'RetourRapide', 'FastForward' => 'AvanceRapide', 'February' => 'f@\'evrier', 'First' => 'Premier', 'First section in reading order' => 'Premi@`e section dans l\'ordre de lecture', 'Following' => 'Suivant', 'Following node' => 'N@oe{}ud suivant', 'Footnotes' => 'Notes de bas de page', 'Forward' => 'Avant', 'Forward section in next file' => '', 'From 1.2.3 go to' => 'Depuis 1.2.3 aller @`a', 'Go to' => 'Aller @`a', 'Index' => 'Index', 'Index Entry' => 'Entr@\'ee d\'index', 'January' => 'janvier', 'July' => 'juillet', 'Jump to' => 'Aller @`a', 'June' => 'juin', 'Last' => 'Dernier', 'Last section in reading order' => 'Derni@`ere section dans l\'ordre de lecture', 'March' => 'mars', 'May' => 'mai', 'Menu:' => 'Menu@ :', 'Name' => 'Nom', 'Next' => 'Suivant', 'Next chapter' => 'Chapitre suivant', 'Next file' => 'Fichier suivant', 'Next node' => 'N@oe{}ud suivant', 'Next section in reading order' => 'Section suivante dans l\'ordre de lecture', 'Next section on same level' => 'Section suivante au m@^eme niveau', 'NextFile' => 'FichierSuivant', 'Node following in node reading order' => 'N@oe{}ud suivant dans l\'ordre de lecture', 'Node up' => 'N@oe{}ud au dessus', 'NodeNext' => 'N@oe{}udSuivant', 'NodePrev' => 'N@oe{}udPr@\'ec@\'edent', 'NodeUp' => 'N@oe{}udMonter', 'November' => 'novembre', 'October' => 'octobre', 'Overview' => 'Vue d\'ensemble', 'Prev' => 'Pr@\'ec@\'edent', 'PrevFile' => '', 'Previous' => '', 'Previous file' => 'Fichier pr@\'ec@\'edent', 'Previous node' => 'N@oe{}ud pr@\'ec@\'edent', 'Previous section in reading order' => 'Section pr@\'ec@\'edente dans l\'ordre de lecture', 'Previous section on same level' => 'Section pr@\'ec@\'edente au m@^eme niveau', 'Section' => '', 'Section One' => 'Section un', 'See ' => '', 'See @cite{{book}}' => 'Voir @cite{{book}}', 'See `{section}\'' => 'Section sup@\'erieure', 'See `{section}\' in @cite{{book}}' => 'Voir la section `{section}\' dans @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => 'Voir la section {reference_name}', 'See {node_file_href}' => 'Voir {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Voir {node_file_href} section `{section}\' dans @cite{{book}}', 'See {reference_name}' => 'Voir {reference_name}', 'See {reference}' => 'Voir {reference_name}', 'See {reference} in @cite{{book}}' => 'Voir {node_file_href} @cite{{book}}', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'septembre', 'Short Table of Contents' => 'R@\'esum@\'e du contenu', 'Short table of contents' => 'R@\'esum@\'e du contenu', 'Subsection One-Four' => 'Sous section un-quatre', 'Subsection One-One' => 'Sous section un-un', 'Subsection One-Three' => 'Sous section un-trois', 'Subsection One-Two' => 'Sous section un-deux', 'Subsubsection One-Two-Four' => 'Sous sous section un-deux-quatre', 'Subsubsection One-Two-One' => 'Sous sous section un-deux-un', 'Subsubsection One-Two-Three' => 'Sous sous section un-deux-trois', 'Subsubsection One-Two-Two' => 'Sous sous section un-deux-deux', 'Table of Contents' => 'Table des mati@`eres', 'Table of contents' => 'Table des mati@`eres', 'The node you are looking for is at {href}.' => 'Le n@oe{}ud que vous recherchez est ici@ : {href}.', 'This' => 'Ici', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e le @emph{{date}} en utilisant @uref{{program_homepage}, @emph{{program}}}', '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}}}.', 'Top' => 'Racine', 'Untitled Document' => 'Document sans titre', 'Up' => 'Monter', 'Up node' => 'N@oe{}ud au dessus', 'Up section' => 'Section sup@\'erieure', '`{section}\'' => 'Section sup@\'erieure', '`{section}\' in @cite{{book}}' => 'section `{section}\' dans @cite{{book}}', 'current' => 'courante', 'on @emph{{date}}' => 'le @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => 'voir @cite{{book}}', 'see `{section}\'' => 'Section sup@\'erieure', 'see `{section}\' in @cite{{book}}' => 'section `{section}\' dans @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section `{section}\' in @cite{{book}}' => 'voir la section `{section}\' dans @cite{{book}}', 'see section {reference_name}' => 'voir la section {reference_name}', 'see {node_file_href}' => 'voir {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'voir {node_file_href} section `{section}\' dans @cite{{book}}', 'see {reference_name}' => 'voir {reference_name}', 'see {reference}' => 'voir {reference_name}', 'see {reference} in @cite{{book}}' => 'voir {node_file_href} @cite{{book}}', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => 'le {day} {month} {year}', '{name} of {class}' => '{name} de {class}', '{name} on {class}' => '{name} de {class}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} section `{section}\' dans @cite{{book}}', '{reference_name}' => '', '{reference}' => 'voir {reference_name}', '{reference} in @cite{{book}}' => 'voir @cite{{book}}', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'de'} = { ' The buttons in the navigation panels have the following meaning:' => ' Die Links in der Navigationsleiste haben die folgende Bedeutung: ', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' wobei das @strong{ Beispiel } annimmt, dass die aktuelle Position bei @strong{ Unterabschnitt 1-2-3 } in einem Dokument mit folgender Struktur liegt:', ' Up ' => ' Nach oben ', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '@b{{quotation_arg}:} ', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '@cite{{book}}', '@{No value for `{value}\'@}' => '', 'About' => '@"Uber', 'About (help)' => '@"Uber (Hilfe)', 'About This Document' => '@"Uber dieses Dokument', 'April' => 'April', 'August' => 'August', 'Back' => 'Zur@"uck', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => 'Anfang dieses oder des letzten Kapitels', 'Button' => '', 'Contents' => 'Inhalt', 'Cover (top) of document' => 'Titelseite des Dokuments', 'Current' => '', 'Current Position' => 'Aktuelle Position', 'Current section' => 'Aktueller Abschnitt', 'December' => 'Dezember', 'FastBack' => '', 'FastForward' => '', 'February' => 'Februar', 'First' => '', 'First section in reading order' => 'Erster Abschnitt in Lesereihenfolge', 'Following' => '', 'Following node' => 'N@"achster Knoten', 'Footnotes' => 'Fu@ss{}noten', 'Forward' => 'Nach vorne', 'Forward section in next file' => '', 'From 1.2.3 go to' => 'Von 1.2.3 gehe zu', 'Go to' => 'Gehe zu', 'Index' => 'Index', 'Index Entry' => 'Indexeintrag', 'January' => 'Januar', 'July' => 'Juli', 'Jump to' => 'Springe zu', 'June' => 'Juni', 'Last' => '', 'Last section in reading order' => 'Letzter Abschnitt in Lesereihenfolge', 'March' => 'M@"arz', 'May' => 'Mai', 'Menu:' => 'Auswahl:', 'Name' => 'Name', 'Next' => '', 'Next chapter' => 'N@"achstes Kapitel', 'Next file' => '', 'Next node' => 'N@"achster Knoten', 'Next section in reading order' => 'N@"achster Abschnitt in Lesereihenfolge', 'Next section on same level' => 'N@"achster Abschitt derselben Ebene', 'NextFile' => '', 'Node following in node reading order' => 'N@"achster Abschnitt in Lesereihenfolge', 'Node up' => 'Knoten nach oben', 'NodeNext' => '', 'NodePrev' => '', 'NodeUp' => '', 'November' => 'November', 'October' => 'Oktober', 'Overview' => '@"Ubersicht', 'Prev' => '', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => 'Voriger Knoten', 'Previous section in reading order' => 'Voriger Abschnitt in Lesereihenfolge', 'Previous section on same level' => 'Voriger Abschnitt derselben Ebene', 'Section' => 'Abschnitt', 'Section One' => 'Abschnitt 1', 'See ' => '', 'See @cite{{book}}' => '', 'See `{section}\'' => 'Abschnitt nach oben', 'See `{section}\' in @cite{{book}}' => 'Siehe Abschnitt `{section}\' in @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => '', 'See {node_file_href}' => 'Siehe {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Siehe {node_file_href} in Abschnitt `{section}\' in @cite{{book}}', 'See {reference_name}' => '', 'See {reference}' => 'siehe {reference_name}', 'See {reference} in @cite{{book}}' => 'Siehe {node_file_href} @cite{{book}}', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'September', 'Short Table of Contents' => 'Kurzes Inhaltsverzeichnis', 'Short table of contents' => 'Kurzes Inhaltsverzeichnis', 'Subsection One-Four' => 'Unterabschnitt 1-4', 'Subsection One-One' => 'Unterabschnitt 1-1', 'Subsection One-Three' => 'Unterabschnitt 1-3', 'Subsection One-Two' => 'Unterabschnitt 1-2', 'Subsubsection One-Two-Four' => 'Unterabschnitt 1-2-4', 'Subsubsection One-Two-One' => 'Unterabschnitt 1-2-1', 'Subsubsection One-Two-Three' => 'Unterabschnitt 1-2-3', 'Subsubsection One-Two-Two' => 'Unterabschnitt 1-2-2', 'Table of Contents' => 'Inhaltsverzeichnis', 'Table of contents' => 'Inhaltsverzeichnis', 'The node you are looking for is at {href}.' => 'Der Knoten, den Sie sehen, befindet sich bei {href}', 'This' => '', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Dieses Dokument wurde erzeugt am @i{{date}} durch @uref{{program_homepage}, @i{{program}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Dieses Dokument wurde erzeugt durch @uref{{program_homepage}, @emph{{program}}}.', 'Top' => 'Anfang', 'Untitled Document' => 'Unbenanntes Dokumen', 'Up' => 'Nach oben', 'Up node' => 'Knoten nach oben', 'Up section' => 'Abschnitt nach oben', '`{section}\'' => 'Abschnitt nach oben', '`{section}\' in @cite{{book}}' => 'Abschnitt `{section}\' in @cite{{book}}', 'current' => '', 'on @emph{{date}}' => 'am @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => 'siehe @cite{{book}}', 'see `{section}\'' => 'Abschnitt nach oben', 'see `{section}\' in @cite{{book}}' => 'Abschnitt `{section}\' in @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section `{section}\' in @cite{{book}}' => 'siehe Abschnitt `{section}\' in @cite{{book}}', 'see section {reference_name}' => 'siehe Abschnitt {reference_name}', 'see {node_file_href}' => 'siehe {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'siehe {node_file_href} im Abschnitt `{section}\' in @cite{{book}}', 'see {reference_name}' => 'siehe {reference_name}', 'see {reference}' => 'siehe {reference_name}', 'see {reference} in @cite{{book}}' => 'siehe {node_file_href} @cite{{book}}', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '{acronym_like} ({explanation})', '{month} {day}, {year}' => '{day}. {month} {year}', '{name} of {class}' => '', '{name} on {class}' => '', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} in Abschnitt `{section}\' in @cite{{book}}', '{reference_name}' => '{reference_name}', '{reference}' => '{reference_name}', '{reference} in @cite{{book}}' => 'siehe @cite{{book}}', '{ref}' => '', '{style} {number}' => '{style} {number}', '{style}: {caption_first_line}' => '{style}: {caption_first_line}', '{style}: {shortcaption_first_line}' => '{style}: {shortcaption_first_line}', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'pt'} = { ' The buttons in the navigation panels have the following meaning:' => ' Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:', ' 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:', ' Up ' => ' Acima ', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => 'Sobre', 'About (help)' => 'Sobre (ajuda)', 'About This Document' => 'Sobre Esse Documento', 'April' => 'Abril', 'August' => 'Agosto', 'Back' => 'Volta', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 'Button' => 'Bot@~ao', 'Contents' => 'Conte@\'udo', 'Cover (top) of document' => 'In@\'icio (topo) do documento', 'Current' => '', 'Current Position' => 'Posi@,{c}@~ao Atual', 'Current section' => 'Se@,{c}@~ao atual', 'December' => 'Dezembro', 'FastBack' => 'Voltar R@\'apido', 'FastForward' => 'Avan@,{c}ar R@\'apido', 'February' => 'Fevereiro', 'First' => 'Primeiro', 'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura', 'Following' => 'Seguinte', 'Following node' => 'Nodo seguinte', 'Footnotes' => 'Notas de Rodap@\'e', 'Forward' => 'Avan@,{c}ar', 'Forward section in next file' => '', 'From 1.2.3 go to' => 'De 1.2.3 v@\'a para', 'Go to' => 'V@\'a para', 'Index' => '@\'Indice', 'Index Entry' => 'Entrada de @\'Indice', 'January' => 'Janeiro', 'July' => 'Julho', 'Jump to' => 'Pular para', 'June' => 'Junho', 'Last' => '@\'Ultimo', 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura', 'March' => 'Mar@,{c}o', 'May' => 'Maio', 'Menu:' => '', 'Name' => 'Nome', 'Next' => 'Pr@\'oximo', 'Next chapter' => 'Pr@\'oximo cap@\'itulo', 'Next file' => '', 'Next node' => 'Pr@\'oximo nodo', 'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura', 'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 'NextFile' => '', 'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos', 'Node up' => 'Nodo acima', 'NodeNext' => 'Pr@\'oximo Nodo', 'NodePrev' => 'Nodo Anterior', 'NodeUp' => 'Nodo Acima', 'November' => 'Novembro', 'October' => 'Outubro', 'Overview' => 'Vis@~ao geral', 'Prev' => 'Pr@\'evio', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => 'Nodo anterior', 'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura', 'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel', 'Section' => 'Se@,{c}@~ao', 'Section One' => 'Se@,{c}@~ao Um', 'See ' => '', 'See @cite{{book}}' => 'Veja @cite{{book}}', 'See `{section}\'' => 'Se@,{c}@~ao acima', 'See `{section}\' in @cite{{book}}' => 'Veja se@,{c}@~ao `{section}\' em @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => 'Veja se@,{c}@~ao {reference_name}', 'See {node_file_href}' => 'Veja {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Veja {node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', 'See {reference_name}' => 'Veja {reference_name}', 'See {reference}' => 'Veja {reference_name}', 'See {reference} in @cite{{book}}' => 'Veja {node_file_href} @cite{{book}}', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'Setembro', 'Short Table of Contents' => 'Breve Sum@\'ario', 'Short table of contents' => 'Breve sum@\'ario', 'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro', 'Subsection One-One' => 'Subse@,{c}@~ao Um-Um', 'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es', 'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois', 'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro', 'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um', 'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es', 'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois', 'Table of Contents' => 'Sum@\'ario', 'Table of contents' => 'Sum@\'ario', 'The node you are looking for is at {href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em {href}.', 'This' => 'Esse', '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}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Esse documento foi gerado usando @uref{{program_homepage}, @emph{{program}}}.', 'Top' => 'Topo', 'Untitled Document' => 'Documento Sem Nome', 'Up' => 'Acima', 'Up node' => 'Nodo acima', 'Up section' => 'Se@,{c}@~ao acima', '`{section}\'' => 'Se@,{c}@~ao acima', '`{section}\' in @cite{{book}}' => 'se@,{c}@~ao `{section}\' em @cite{{book}}', 'current' => 'atual', 'on @emph{{date}}' => 'em @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => 'veja @cite{{book}}', 'see `{section}\'' => 'Se@,{c}@~ao acima', 'see `{section}\' in @cite{{book}}' => 'se@,{c}@~ao `{section}\' em @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section `{section}\' in @cite{{book}}' => 'veja se@,{c}@~ao `{section}\' em @cite{{book}}', 'see section {reference_name}' => 'veja se@,{c}@~ao {reference_name}', 'see {node_file_href}' => 'veja {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'veja {node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', 'see {reference_name}' => 'veja {reference_name}', 'see {reference}' => 'veja {reference_name}', 'see {reference} in @cite{{book}}' => 'veja {node_file_href} @cite{{book}}', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '{day} de {month} de {year}', '{name} of {class}' => '{name} da {class}', '{name} on {class}' => '{name} na {class}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', '{reference_name}' => '', '{reference}' => 'veja {reference_name}', '{reference} in @cite{{book}}' => 'veja @cite{{book}}', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'hu'} = { ' The buttons in the navigation panels have the following meaning:' => ' A navigációs panelen levő gombok jelentése a következő:', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' @strong{ Példánkban } az aktuális pozíció az @strong{ 1.2.3 alalszakasz } egy olyan dokumentumban, melynek szerkezete a következő:', ' Up ' => 'Fel', '(outside of any element)' => '(bármelyik elemen kívül)', '(outside of any node)' => '(bármelyik csomóponton kívül)', '@b{{quotation_arg}:} ' => '@b{{quotation_arg}:} ', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '@cite{{book}}', '@{No value for `{value}\'@}' => '@{Nincs értéke ennek: `{value}\'@}', 'About' => 'Súgó', 'About (help)' => 'Segítség a navigációhoz', 'About This Document' => 'A navigációs panel használata', 'April' => 'április', 'August' => 'augusztus', 'Back' => 'Vissza', 'Back section in previous file' => 'Előző fájl hátsó szakasza', 'Beginning of this chapter or previous chapter' => 'Fejezet eleje vagy előző fejezet', 'Button' => 'Gomb', 'Contents' => 'Tartalom', 'Cover (top) of document' => 'Dokumentum címoldala', 'Current' => 'Aktuális', 'Current Position' => 'Aktuális pozíció', 'Current section' => 'Aktuális szakasz', 'December' => 'december', 'FastBack' => 'Visszaugrás', 'FastForward' => 'Előreugrás', 'February' => 'február', 'First' => 'Első', 'First section in reading order' => 'Első szakasz az olvasási sorrendben', 'Following' => 'Következő', 'Following node' => 'Következő csomópont', 'Footnotes' => 'Lábjegyzet', 'Forward' => 'Előre', 'Forward section in next file' => 'Következő fájl elülső szakasza', 'From 1.2.3 go to' => '1.2.3-ból ide jutunk', 'Go to' => 'Cél', 'Index' => 'Tárgymutató', 'Index Entry' => 'Tárgymutató-bejegyzés', 'January' => 'január', 'July' => 'július', 'Jump to' => 'Ugorj ide', 'June' => 'június', 'Last' => 'Utolsó', 'Last section in reading order' => 'Utolsó szakasz az olvasási sorrendben', 'March' => 'március', 'May' => 'május', 'Menu:' => 'Menü:', 'Name' => 'Név', 'Next' => 'Következő', 'Next chapter' => 'Következő fejezet', 'Next file' => 'Következő fájl', 'Next node' => 'Következő csomópont', 'Next section in reading order' => 'Következő szakasz az olvasási sorrendben', 'Next section on same level' => 'Következő szakasz ugyanazon a szinten', 'NextFile' => 'KövetkezőFájl', 'Node following in node reading order' => 'Következő csomópont az olvasási sorrendben', 'Node up' => 'Szülő csomópont', 'NodeNext' => 'KövetkezőCsomópont', 'NodePrev' => 'ElőzőCsomópont', 'NodeUp' => 'SzülőCsomópont', 'November' => 'november', 'October' => 'október', 'Overview' => 'Áttekintés', 'Prev' => 'Előző', 'PrevFile' => 'ElőzőFájl', 'Previous' => 'Előző', 'Previous file' => 'Előző fájl', 'Previous node' => 'Előző csomópont', 'Previous section in reading order' => 'Előző szakasz az olvasási sorrendben', 'Previous section on same level' => 'Előző szakasz ugyanazon a szinten', 'Section' => 'Szakasz', 'Section One' => 'szakasz', 'See ' => 'Ld. ', 'See @cite{{book}}' => 'Ld. @cite{{book}}', 'See `{section}\'' => 'Szülő szakasz', 'See `{section}\' in @cite{{book}}' => 'Ld. ezt a szakaszt: `{section}\' itt: @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'Ld. ezt a szakaszt: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}', 'See section {reference_name}' => 'Ld. ezt a szakaszt: {reference_name}', 'See {node_file_href}' => 'Ld. {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Ld. {node_file_href} ezt a szakaszt: `{section}\' itt: @cite{{book}}', 'See {reference_name}' => 'Ld. {reference_name}', 'See {reference}' => 'Ld. {reference_name}', 'See {reference} in @cite{{book}}' => 'See {node_file_href} @cite{{book}}', 'See {ref}' => 'Ld. {ref}', 'See {title_ref}' => 'Ld. {title_ref}', 'September' => 'szeptember', 'Short Table of Contents' => 'Rövid tartalomjegyzék', 'Short table of contents' => 'Rövid tartalomjegyzék', 'Subsection One-Four' => 'alszakasz', 'Subsection One-One' => 'alszakasz', 'Subsection One-Three' => 'alszakasz', 'Subsection One-Two' => 'alszakasz', 'Subsubsection One-Two-Four' => 'alalszakasz', 'Subsubsection One-Two-One' => 'alalszakasz', 'Subsubsection One-Two-Three' => 'alalszakasz', 'Subsubsection One-Two-Two' => 'alalszakasz', 'Table of Contents' => 'Tartalomjegyzék', 'Table of contents' => 'Tartalomjegyzék', 'The node you are looking for is at {href}.' => 'A keresett csomópont itt található: {href}.', 'This' => 'Ez a(z)', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Ezt a dokumentumot @i{{date}} napon generálta a(z) @uref{{program_homepage}, @i{{program}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Ezt a dokumentumot a(z) @uref{{program_homepage}, @emph{{program}}} generálta.', 'Top' => 'Címoldal', 'Untitled Document' => 'Névtelen dokumentum', 'Up' => 'Fel', 'Up node' => 'Szülő csomópont', 'Up section' => 'Szülő szakasz', '`{section}\'' => 'Szülő szakasz', '`{section}\' in @cite{{book}}' => 'szakasz: `{section}\' itt: @cite{{book}}', 'current' => 'aktuális', 'on @emph{{date}}' => 'ekkor: @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'szakasz: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}', 'see ' => 'ld. ', 'see @cite{{book}}' => 'ld. @cite{{book}}', 'see `{section}\'' => 'Szülő szakasz', 'see `{section}\' in @cite{{book}}' => 'szakasz: `{section}\' itt: @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'ld. ezt a szakaszt: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}', 'see section `{section}\' in @cite{{book}}' => 'ld. ezt a szakaszt: `{section}\' itt: @cite{{book}}', 'see section {reference_name}' => 'ld. ezt a szakaszt: {reference_name}', 'see {node_file_href}' => 'ld. {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'ld. {node_file_href} ezt a szakaszt: `{section}\' itt: @cite{{book}}', 'see {reference_name}' => 'ld. {reference_name}', 'see {reference}' => 'ld. {reference_name}', 'see {reference} in @cite{{book}}' => 'ld. {node_file_href} @cite{{book}}', 'see {ref}' => 'ld. {ref}', 'see {title_ref}' => 'ld. {title_ref}', '{acronym_like} ({explanation})' => '{acronym_like} ({explanation})', '{month} {day}, {year}' => '', '{name} of {class}' => '{name} típusa: {class}', '{name} on {class}' => '{name} ezen: {class}', '{node_file_href}' => '{node_file_href}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} szakasz: `{section}\' itt: @cite{{book}}', '{reference_name}' => '{reference_name}', '{reference}' => '{reference_name}', '{reference} in @cite{{book}}' => '{node_file_href} @cite{{book}}', '{ref}' => '{ref}', '{style} {number}' => '{style} {number}', '{style}: {caption_first_line}' => '{style}: {caption_first_line}', '{style}: {shortcaption_first_line}' => '{style}: {shortcaption_first_line}', '{title_ref}' => '{title_ref}' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'pt_BR'} = { ' The buttons in the navigation panels have the following meaning:' => ' Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:', ' 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:', ' Up ' => ' Acima ', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => 'Sobre', 'About (help)' => 'Sobre (ajuda)', 'About This Document' => 'Sobre Esse Documento', 'April' => 'Abril', 'August' => 'Agosto', 'Back' => 'Volta', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 'Button' => 'Bot@~ao', 'Contents' => 'Conte@\'udo', 'Cover (top) of document' => 'In@\'icio (topo) do documento', 'Current' => '', 'Current Position' => 'Posi@,{c}@~ao Atual', 'Current section' => 'Se@,{c}@~ao atual', 'December' => 'Dezembro', 'FastBack' => 'Voltar R@\'apido', 'FastForward' => 'Avan@,{c}ar R@\'apido', 'February' => 'Fevereiro', 'First' => 'Primeiro', 'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura', 'Following' => 'Seguinte', 'Following node' => 'Nodo seguinte', 'Footnotes' => 'Notas de Rodap@\'e', 'Forward' => 'Avan@,{c}ar', 'Forward section in next file' => '', 'From 1.2.3 go to' => 'De 1.2.3 v@\'a para', 'Go to' => 'V@\'a para', 'Index' => '@\'Indice', 'Index Entry' => 'Entrada de @\'Indice', 'January' => 'Janeiro', 'July' => 'Julho', 'Jump to' => 'Pular para', 'June' => 'Junho', 'Last' => '@\'Ultimo', 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura', 'March' => 'Mar@,{c}o', 'May' => 'Maio', 'Menu:' => '', 'Name' => 'Nome', 'Next' => 'Pr@\'oximo', 'Next chapter' => 'Pr@\'oximo cap@\'itulo', 'Next file' => '', 'Next node' => 'Pr@\'oximo nodo', 'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura', 'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 'NextFile' => '', 'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos', 'Node up' => 'Nodo acima', 'NodeNext' => 'Pr@\'oximo Nodo', 'NodePrev' => 'Nodo Anterior', 'NodeUp' => 'Nodo Acima', 'November' => 'Novembro', 'October' => 'Outubro', 'Overview' => 'Vis@~ao geral', 'Prev' => 'Pr@\'evio', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => 'Nodo anterior', 'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura', 'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel', 'Section' => 'Se@,{c}@~ao', 'Section One' => 'Se@,{c}@~ao Um', 'See ' => '', 'See @cite{{book}}' => 'Veja @cite{{book}}', 'See `{section}\'' => 'Se@,{c}@~ao acima', 'See `{section}\' in @cite{{book}}' => 'Veja se@,{c}@~ao `{section}\' em @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => 'Veja se@,{c}@~ao {reference_name}', 'See {node_file_href}' => 'Veja {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Veja {node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', 'See {reference_name}' => 'Veja {reference_name}', 'See {reference}' => 'Veja {reference_name}', 'See {reference} in @cite{{book}}' => 'Veja {node_file_href} @cite{{book}}', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'Setembro', 'Short Table of Contents' => 'Breve Sum@\'ario', 'Short table of contents' => 'Breve sum@\'ario', 'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro', 'Subsection One-One' => 'Subse@,{c}@~ao Um-Um', 'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es', 'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois', 'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro', 'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um', 'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es', 'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois', 'Table of Contents' => 'Sum@\'ario', 'Table of contents' => 'Sum@\'ario', 'The node you are looking for is at {href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em {href}.', 'This' => 'Esse', '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}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Esse documento foi gerado usando @uref{{program_homepage}, @emph{{program}}}.', 'Top' => 'Topo', 'Untitled Document' => 'Documento Sem Nome', 'Up' => 'Acima', 'Up node' => 'Nodo acima', 'Up section' => 'Se@,{c}@~ao acima', '`{section}\'' => 'Se@,{c}@~ao acima', '`{section}\' in @cite{{book}}' => 'se@,{c}@~ao `{section}\' em @cite{{book}}', 'current' => 'atual', 'on @emph{{date}}' => 'em @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => 'veja @cite{{book}}', 'see `{section}\'' => 'Se@,{c}@~ao acima', 'see `{section}\' in @cite{{book}}' => 'se@,{c}@~ao `{section}\' em @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section `{section}\' in @cite{{book}}' => 'veja se@,{c}@~ao `{section}\' em @cite{{book}}', 'see section {reference_name}' => 'veja se@,{c}@~ao {reference_name}', 'see {node_file_href}' => 'veja {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'veja {node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', 'see {reference_name}' => 'veja {reference_name}', 'see {reference}' => 'veja {reference_name}', 'see {reference} in @cite{{book}}' => 'veja {node_file_href} @cite{{book}}', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '{day} de {month} de {year}', '{name} of {class}' => '{name} da {class}', '{name} on {class}' => '{name} na {class}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} se@,{c}@~ao `{section}\' em @cite{{book}}', '{reference_name}' => '', '{reference}' => 'veja {reference_name}', '{reference} in @cite{{book}}' => 'veja @cite{{book}}', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'es'} = { ' The buttons in the navigation panels have the following meaning:' => ' Los botones de los paneles de navegaci@\'on tienen el significado siguiente:', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' donde el @strong{ Ejemplo } supone que la posici@\'on actual est@\'a en la @strong{ Sub-subsecci@\'on uno-dos-tres } de un documento de la estructura siguiente:', ' Up ' => ' Subir ', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => 'Acerca de', 'About (help)' => 'Acerca de (p@\'agina de ayuda)', 'About This Document' => 'Acerca de este documento', 'April' => 'abril', 'August' => 'agosto', 'Back' => 'Atr@\'as', 'Back section in previous file' => 'Retroceder secci@\'on en el archivo anterior', 'Beginning of this chapter or previous chapter' => 'Inicio de este cap@\'itulo o cap@\'itulo anterior', 'Button' => 'Bot@\'on', 'Contents' => '@\'Indice general', 'Cover (top) of document' => 'Portada del documento', 'Current' => '', 'Current Position' => 'Posici@\'on actual', 'Current section' => 'Secci@\'on actual', 'December' => 'diciembre', 'FastBack' => 'Retroceso r@\'apido', 'FastForward' => 'Avance r@\'apido', 'February' => 'febrero', 'First' => 'Primero', 'First section in reading order' => 'Primera secci@\'on en orden de lectura', 'Following' => 'Siguiente', 'Following node' => 'Nodo siguiente', 'Footnotes' => 'Notas al pie', 'Forward' => 'Adelante', 'Forward section in next file' => 'Avanzar secci@\'on en el pr@\'oximo archivo', 'From 1.2.3 go to' => 'Desde 1.2.3 ir a', 'Go to' => 'Ir a', 'Index' => '@\'Indice', 'Index Entry' => 'Entrada de @\'indice', 'January' => 'enero', 'July' => 'julio', 'Jump to' => 'Saltar a', 'June' => 'junio', 'Last' => '@\'Ultimo', 'Last section in reading order' => '@\'Ultima secci@\'on en orden de lectura', 'March' => 'marzo', 'May' => 'mayo', 'Menu:' => 'Men@\'u:', 'Name' => 'Nombre', 'Next' => 'Siguiente', 'Next chapter' => 'Cap@\'itulo siguiente', 'Next file' => 'Archivo siguiente', 'Next node' => 'Nodo siguiente', 'Next section in reading order' => 'Secci@\'on siguiente en orden de lectura', 'Next section on same level' => 'Secci@\'on siguiente en el mismo nivel', 'NextFile' => 'ArchivoSiguiente', 'Node following in node reading order' => 'Nodo siguiente en orden de lectura de nodos', 'Node up' => 'Subir nodo', 'NodeNext' => 'NodoSiguiente', 'NodePrev' => 'NodoAnterior', 'NodeUp' => 'SubirNodo', 'November' => 'noviembre', 'October' => 'octubre', 'Overview' => 'Panor@\'amica', 'Prev' => 'Ant', 'PrevFile' => 'ArchivoAnt', 'Previous' => '', 'Previous file' => 'Archivo anterior', 'Previous node' => 'Nodo anterior', 'Previous section in reading order' => 'Secci@\'on anterior en orden de lectura', 'Previous section on same level' => 'Secci@\'on anterior en el mismo nivel', 'Section' => 'Secci@\'on', 'Section One' => 'Secci@\'on Uno', 'See ' => '', 'See @cite{{book}}' => 'V@\'ease @cite{{book}}', 'See `{section}\'' => 'Subir secci@\'on', 'See `{section}\' in @cite{{book}}' => 'V@\'ease la secci@\'on `{section}\' en @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => 'V@\'ease la secci@\'on {reference_name}', 'See {node_file_href}' => 'V@\'ease {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'V@\'ease {node_file_href} secci@\'on `{section}\' en @cite{{book}}', 'See {reference_name}' => 'V@\'ease {reference_name}', 'See {reference}' => 'V@\'ease {reference_name}', 'See {reference} in @cite{{book}}' => 'V@\'ease {node_file_href} @cite{{book}}', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'septiembre', 'Short Table of Contents' => 'Resumen del Contenido', 'Short table of contents' => 'Resumen del contenido', 'Subsection One-Four' => 'Subsecci@\'on uno-cuatro', 'Subsection One-One' => 'Subsecci@\'on uno-uno', 'Subsection One-Three' => 'Subsecci@\'on uno-tres', 'Subsection One-Two' => 'Subsecci@\'on uno-dos', 'Subsubsection One-Two-Four' => 'Sub-subsecci@\'on uno-dos-cuatro', 'Subsubsection One-Two-One' => 'Sub-subsecci@\'on uno-dos-uno', 'Subsubsection One-Two-Three' => 'Sub-subsecci@\'on uno-dos-tres', 'Subsubsection One-Two-Two' => 'Sub-subsecci@\'on uno-dos-dos', 'Table of Contents' => '@\'{@dotless{I}}ndice General', 'Table of contents' => '@\'{@dotless{I}}ndice general', 'The node you are looking for is at {href}.' => 'El nodo que busca se encuentra en {href}.', 'This' => 'Este', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Este documento se gener@\'o el @i{{date}} utilizando @uref{{program_homepage}, @i{{program}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Este documento se gener@\'o utilizando @uref{{program_homepage}, @emph{{program}}}.', 'Top' => 'Arriba', 'Untitled Document' => 'Documento sin t@\'itulo', 'Up' => 'Subir', 'Up node' => 'Subir nodo', 'Up section' => 'Subir secci@\'on', '`{section}\'' => 'Subir secci@\'on', '`{section}\' in @cite{{book}}' => 'secci@\'on `{section}\' en @cite{{book}}', 'current' => 'actual', 'on @emph{{date}}' => 'el @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => 'v@\'ease @cite{{book}}', 'see `{section}\'' => 'Subir secci@\'on', 'see `{section}\' in @cite{{book}}' => 'secci@\'on `{section}\' en @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section `{section}\' in @cite{{book}}' => 'v@\'ease la secci@\'on `{section}\' en @cite{{book}}', 'see section {reference_name}' => 'v@\'ease la secci@\'on {reference_name}', 'see {node_file_href}' => 'v@\'ease {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'v@\'ease {node_file_href} secci@\'on `{section}\' en @cite{{book}}', 'see {reference_name}' => 'v@\'ease {reference_name}', 'see {reference}' => 'v@\'ease {reference_name}', 'see {reference} in @cite{{book}}' => 'v@\'ease {node_file_href} @cite{{book}}', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => 'el {day} {month} {year}', '{name} of {class}' => '{name} de {class}', '{name} on {class}' => '{name} en {class}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} secci@\'on `{section}\' en @cite{{book}}', '{reference_name}' => '', '{reference}' => 'v@\'ease {reference_name}', '{reference} in @cite{{book}}' => 'v@\'ease @cite{{book}}', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'it'} = { ' The buttons in the navigation panels have the following meaning:' => ' I bottoni nei pannelli di navigazione hanno il seguente significato:', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' dove @strong{ Esempio } assume che l\'attuale posizione è alla @strong{ Sottosottosezione Uno-Due-Tre } di un documento che ha la seguente struttura:', ' Up ' => ' Su ', '(outside of any element)' => '(fuori da qualsiasi elemento)', '(outside of any node)' => '(fuori da qualsiasi nodo)', '@b{{quotation_arg}:} ' => '@b{{quotation_arg}:} ', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '@cite{{book}}', '@{No value for `{value}\'@}' => '@{Nessun valore per `{value}\'@}', 'About' => 'Informazioni', 'About (help)' => 'Informazioni (aiuto)', 'About This Document' => 'Informazioni su questo documento', 'April' => 'Aprile', 'August' => 'Agosto', 'Back' => 'Indietro', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => 'Inizio di questo capitolo o capitolo precedente', 'Button' => 'Bottone', 'Contents' => 'Contenuti', 'Cover (top) of document' => 'Copertina (inizio) del documento', 'Current' => 'Attuale', 'Current Position' => 'Posizione Attuale', 'Current section' => 'Sezione attuale', 'December' => 'Dicembre', 'FastBack' => 'Indietro veloce', 'FastForward' => 'Avanti veloce', 'February' => 'Febbraio', 'First' => 'Primo', 'First section in reading order' => 'Prima sezione in ordine di lettura', 'Following' => 'Seguente', 'Following node' => 'Nodo seguente', 'Footnotes' => 'Note a piè di pagina', 'Forward' => 'Avanti', 'Forward section in next file' => 'Sezione successiva nel prossimo file', 'From 1.2.3 go to' => 'Da 1.2.3 vai a', 'Go to' => 'Vai a', 'Index' => 'Indice', 'Index Entry' => 'Voce dell\'indice', 'January' => 'Gennaio', 'July' => 'Luglio', 'Jump to' => 'Salta a', 'June' => 'Giugno', 'Last' => 'Ultimo', 'Last section in reading order' => 'Ultima sezione in ordine di lettura', 'March' => 'Marzo', 'May' => 'Maggio', 'Menu:' => 'Menu', 'Name' => 'Nome', 'Next' => 'Successivo', 'Next chapter' => 'Capitolo successivo', 'Next file' => 'File successivo', 'Next node' => 'Nodo successivo', 'Next section in reading order' => 'Sezione successiva in ordine di lettura', 'Next section on same level' => 'Sezione successiva sullo stesso livello', 'NextFile' => 'File successivo', 'Node following in node reading order' => 'Nodo seguente in ordine di lettura', 'Node up' => 'Nodo superiore', 'NodeNext' => 'Nodo successivo', 'NodePrev' => 'Nodo precedente', 'NodeUp' => 'Nodo superiore', 'November' => 'Novembre', 'October' => 'Ottobre', 'Overview' => 'Panoramica', 'Prev' => 'Prec.', 'PrevFile' => 'File precedente', 'Previous' => 'Precedente', 'Previous file' => 'File precedente', 'Previous node' => 'Nodo precedente', 'Previous section in reading order' => 'Sezione precedente in ordine di lettura', 'Previous section on same level' => 'Sezione precedente sullo stesso livello', 'Section' => 'Sezione', 'Section One' => 'Sezione uno', 'See ' => 'Vedi', 'See @cite{{book}}' => 'Vedi @cite{{book}}', 'See `{section}\'' => 'Sezione superiore', 'See `{section}\' in @cite{{book}}' => 'Vedi la sezione `{section}\' in @cite{{book}}', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'Vedi la sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', 'See section {reference_name}' => 'Vedi la sezione {reference_name}', 'See {node_file_href}' => 'Vedi {node_file_href}', 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Vedi {node_file_href} nella sezione `{section}\' in @cite{{book}}', 'See {reference_name}' => 'Vedi {reference_name}', 'See {reference}' => 'Vedi {reference_name}', 'See {reference} in @cite{{book}}' => 'Vedi {node_file_href} @cite{{book}}', 'See {ref}' => 'Vedi {ref}', 'See {title_ref}' => 'Vedi {title_ref}', 'September' => 'Settembre', 'Short Table of Contents' => 'Indice breve', 'Short table of contents' => 'Indice breve', 'Subsection One-Four' => 'Sottosezione Uno-Quattro', 'Subsection One-One' => 'Sottosezione Uno-Uno', 'Subsection One-Three' => 'Sottosezione Uno-Tre', 'Subsection One-Two' => 'Sottosezione Uno-Due', 'Subsubsection One-Two-Four' => 'Sottosottosezione Uno-Due-Quattro', 'Subsubsection One-Two-One' => 'Sottosottosezione Uno-Due-Uno', 'Subsubsection One-Two-Three' => 'Sottosottosezione Uno-Due-Tre', 'Subsubsection One-Two-Two' => 'Sottosottosezione Uno-Due-Due', 'Table of Contents' => 'Indice', 'Table of contents' => 'Indice', 'The node you are looking for is at {href}.' => 'Il nodo che stai cercando è {href}', 'This' => 'Questo', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Questo documento è stato generato il @i{{date}} con @uref{{program_homepage}, @i{{program}}}.', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Questo documento è stato generato con @uref{{program_homepage}, @emph{{program}}}.', 'Top' => 'Inizio', 'Untitled Document' => 'Documento senza titolo', 'Up' => 'Su', 'Up node' => 'Nodo superiore', 'Up section' => 'Sezione superiore', '`{section}\'' => 'Sezione superiore', '`{section}\' in @cite{{book}}' => 'sezione `{section}\' in @cite{{book}}', 'current' => 'attuale', 'on @emph{{date}}' => 'il @emph{{date}}', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', 'see ' => 'vedi ', 'see @cite{{book}}' => 'vedi @cite{{book}}', 'see `{section}\'' => 'Sezione superiore', 'see `{section}\' in @cite{{book}}' => 'sezione `{section}\' in @cite{{book}}', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'vedi la sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', 'see section `{section}\' in @cite{{book}}' => 'vedi la sezione `{section}\' in @cite{{book}}', 'see section {reference_name}' => 'vedi la sezione {reference_name}', 'see {node_file_href}' => 'vedi {node_file_href}', 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'vedi {node_file_href} nella sezione `{section}\' in @cite{{book}}', 'see {reference_name}' => 'vedi {reference_name}', 'see {reference}' => 'vedi {reference_name}', 'see {reference} in @cite{{book}}' => 'vedi {node_file_href} @cite{{book}}', 'see {ref}' => 'vedi {ref}', 'see {title_ref}' => 'vedi {title_ref}', '{acronym_like} ({explanation})' => '{acronym_like} ({explanation})', '{month} {day}, {year}' => '', '{name} of {class}' => '{name} di {class}', '{name} on {class}' => '{name} in {class}', '{node_file_href}' => '{node_file_href}', '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} nella sezione `{section}\' in @cite{{book}}', '{reference_name}' => '{reference_name}', '{reference}' => '{reference_name}', '{reference} in @cite{{book}}' => '{node_file_href} @cite{{book}}', '{ref}' => '{ref}', '{style} {number}' => '{style} {number}', '{style}: {caption_first_line}' => '{style}: {caption_first_line}', '{style}: {shortcaption_first_line}' => '{style}: {shortcaption_first_line}', '{title_ref}' => '{title_ref}' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'no'} = { ' The buttons in the navigation panels have the following meaning:' => '', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', ' Up ' => '', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => '', 'About (help)' => '', 'About This Document' => 'No translation available!', 'April' => 'april', 'August' => 'august', 'Back' => '', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => '', 'Button' => '', 'Contents' => '', 'Cover (top) of document' => '', 'Current' => '', 'Current Position' => '', 'Current section' => '', 'December' => 'desember', 'FastBack' => '', 'FastForward' => '', 'February' => 'februar', 'First' => '', 'First section in reading order' => '', 'Following' => '', 'Following node' => '', 'Footnotes' => 'No translation available!', 'Forward' => '', 'Forward section in next file' => '', 'From 1.2.3 go to' => '', 'Go to' => '', 'Index' => 'Indeks', 'Index Entry' => '', 'January' => 'januar', 'July' => 'juli', 'Jump to' => '', 'June' => 'juni', 'Last' => '', 'Last section in reading order' => '', 'March' => 'mars', 'May' => 'mai', 'Menu:' => '', 'Name' => '', 'Next' => '', 'Next chapter' => '', 'Next file' => '', 'Next node' => '', 'Next section in reading order' => '', 'Next section on same level' => '', 'NextFile' => '', 'Node following in node reading order' => '', 'Node up' => '', 'NodeNext' => '', 'NodePrev' => '', 'NodeUp' => '', 'November' => 'november', 'October' => 'oktober', 'Overview' => '', 'Prev' => '', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => '', 'Previous section in reading order' => '', 'Previous section on same level' => '', 'Section' => '', 'Section One' => '', 'See ' => '', 'See @cite{{book}}' => '', 'See `{section}\'' => '', 'See `{section}\' in @cite{{book}}' => '', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => '', 'See {reference_name}' => '', 'See {reference}' => '', 'See {reference} in @cite{{book}}' => '', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => 'september', 'Short Table of Contents' => 'Kort innholdsfortegnelse', 'Short table of contents' => '', 'Subsection One-Four' => '', 'Subsection One-One' => '', 'Subsection One-Three' => '', 'Subsection One-Two' => '', 'Subsubsection One-Two-Four' => '', 'Subsubsection One-Two-One' => '', 'Subsubsection One-Two-Three' => '', 'Subsubsection One-Two-Two' => '', 'Table of Contents' => 'Innholdsfortegnelse', 'Table of contents' => '', 'The node you are looking for is at {href}.' => '', 'This' => '', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => '', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => '', 'Top' => '', 'Untitled Document' => '', 'Up' => '', 'Up node' => '', 'Up section' => '', '`{section}\'' => '', '`{section}\' in @cite{{book}}' => '', 'current' => '', 'on @emph{{date}}' => '', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => '', 'see `{section}\'' => '', 'see `{section}\' in @cite{{book}}' => '', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section {reference_name}' => '', 'see {reference_name}' => '', 'see {reference}' => '', 'see {reference} in @cite{{book}}' => '', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '', '{name} of {class}' => '', '{name} on {class}' => '', '{reference_name}' => '', '{reference}' => '', '{reference} in @cite{{book}}' => '', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; # Automatically generated file. Edit the .po file instead. $LANGUAGES->{'en'} = { ' The buttons in the navigation panels have the following meaning:' => '', ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', ' Up ' => '', '(outside of any element)' => '', '(outside of any node)' => '', '@b{{quotation_arg}:} ' => '', '@center --- @emph{{author}} ' => '', '@cite{{book}}' => '', '@{No value for `{value}\'@}' => '', 'About' => '', 'About (help)' => '', 'About This Document' => '', 'April' => '', 'August' => '', 'Back' => '', 'Back section in previous file' => '', 'Beginning of this chapter or previous chapter' => '', 'Button' => '', 'Contents' => '', 'Cover (top) of document' => '', 'Current' => '', 'Current Position' => '', 'Current section' => '', 'December' => '', 'FastBack' => '', 'FastForward' => '', 'February' => '', 'First' => '', 'First section in reading order' => '', 'Following' => '', 'Following node' => '', 'Footnotes' => '', 'Forward' => '', 'Forward section in next file' => '', 'From 1.2.3 go to' => '', 'Go to' => '', 'Index' => '', 'Index Entry' => '', 'January' => '', 'July' => '', 'Jump to' => '', 'June' => '', 'Last' => '', 'Last section in reading order' => '', 'March' => '', 'May' => '', 'Menu:' => '', 'Name' => '', 'Next' => '', 'Next chapter' => '', 'Next file' => '', 'Next node' => '', 'Next section in reading order' => '', 'Next section on same level' => '', 'NextFile' => '', 'Node following in node reading order' => '', 'Node up' => '', 'NodeNext' => '', 'NodePrev' => '', 'NodeUp' => '', 'November' => '', 'October' => '', 'Overview' => '', 'Prev' => '', 'PrevFile' => '', 'Previous' => '', 'Previous file' => '', 'Previous node' => '', 'Previous section in reading order' => '', 'Previous section on same level' => '', 'Section' => '', 'Section One' => '', 'See ' => '', 'See @cite{{book}}' => '', 'See `{section}\'' => '', 'See `{section}\' in @cite{{book}}' => '', 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'See section {reference_name}' => '', 'See {reference_name}' => '', 'See {reference}' => '', 'See {reference} in @cite{{book}}' => '', 'See {ref}' => '', 'See {title_ref}' => '', 'September' => '', 'Short Table of Contents' => '', 'Short table of contents' => '', 'Subsection One-Four' => '', 'Subsection One-One' => '', 'Subsection One-Three' => '', 'Subsection One-Two' => '', 'Subsubsection One-Two-Four' => '', 'Subsubsection One-Two-One' => '', 'Subsubsection One-Two-Three' => '', 'Subsubsection One-Two-Two' => '', 'Table of Contents' => '', 'Table of contents' => '', 'The node you are looking for is at {href}.' => '', 'This' => '', 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => '', 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => '', 'Top' => '', 'Untitled Document' => '', 'Up' => '', 'Up node' => '', 'Up section' => '', '`{section}\'' => '', '`{section}\' in @cite{{book}}' => '', 'current' => '', 'on @emph{{date}}' => '', 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see ' => '', 'see @cite{{book}}' => '', 'see `{section}\'' => '', 'see `{section}\' in @cite{{book}}' => '', 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => '', 'see section {reference_name}' => '', 'see {reference_name}' => '', 'see {reference}' => '', 'see {reference} in @cite{{book}}' => '', 'see {ref}' => '', 'see {title_ref}' => '', '{acronym_like} ({explanation})' => '', '{month} {day}, {year}' => '', '{name} of {class}' => '', '{name} on {class}' => '', '{reference_name}' => '', '{reference}' => '', '{reference} in @cite{{book}}' => '', '{ref}' => '', '{style} {number}' => '', '{style}: {caption_first_line}' => '', '{style}: {shortcaption_first_line}' => '', '{title_ref}' => '' }; require "$T2H_HOME/$translation_file" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/$translation_file" && -r "$T2H_HOME/$translation_file"); # these are unlikely to be used by users, as they are essentially # used to follow the html external refs specification in texinfo sub t2h_cross_manual_normal_text($$$$$$$;$) { my $text = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_code =shift; my $in_math = shift; my $in_simple =shift; my $style_stack = shift; my $state = shift; $text = uc($text) if (in_small_caps($style_stack)); return $text if ($USE_UNICODE); return t2h_no_unicode_cross_manual_normal_text($text, 0); } sub t2h_cross_manual_normal_text_transliterate($$$$$$$;$) { my $text = shift; my $in_raw_text = shift; my $in_preformatted = shift; my $in_code =shift; my $in_math = shift; my $in_simple =shift; my $style_stack = shift; my $state = shift; $text = uc($text) if (in_small_caps($style_stack)); return $text if ($USE_UNICODE); return t2h_no_unicode_cross_manual_normal_text($text, 1); } sub t2h_no_unicode_cross_manual_normal_text($$) { # if there is no unicode support, we do all the transformations here my $text = shift; my $transliterate = shift; my $result = ''; my $encoding = get_conf('DOCUMENT_ENCODING'); if (defined($encoding) and exists($t2h_encoding_aliases{$encoding})) { $encoding = $t2h_encoding_aliases{$encoding}; } while ($text ne '') { if ($text =~ s/^([A-Za-z0-9]+)//o) { $result .= $1; } elsif ($text =~ s/^ //o) { $result .= '-'; } elsif ($text =~ s/^(.)//o) { if (exists($ascii_character_map{$1})) { $result .= '_' . lc($ascii_character_map{$1}); } else { my $character = $1; my $charcode = uc(sprintf("%02x",ord($1))); my $done = 0; if (defined($encoding) and exists($eight_bit_to_unicode{$encoding}) and exists($eight_bit_to_unicode{$encoding}->{$charcode})) { $done = 1; my $unicode_point = $eight_bit_to_unicode{$encoding}->{$charcode}; if (!$transliterate) { $result .= '_' . lc($unicode_point); } elsif (exists($transliterate_map{$unicode_point})) { $result .= $transliterate_map{$unicode_point}; } elsif (exists($unicode_diacritical{$unicode_point})) { $result .= ''; } else { $done = 0; } } if (!$done) { # wild guess that work for latin1, and thus, should fail $result .= '_' . '00' . lc($charcode); } } } else { msg_debug("Bug: unknown character in cross ref (likely in infinite loop)"); msg_debug("Text: !!$text!!"); sleep 1; } } return $result; } sub t2h_nounicode_cross_manual_accent($$$) { my $accent = shift; my $args = shift; my $style_stack = shift; my $text = $args->[0]; if ($accent eq 'dotless') { if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent'))) { return "_0131"; } #return "\x{}" if ($text eq 'j'); # not found ! return $text; } return '_' . lc($unicode_accents{$accent}->{$text}) if (defined($unicode_accents{$accent}->{$text})); return ($text . '_' . lc($unicode_diacritical{$accent})) if (defined($unicode_diacritical{$accent})); return ascii_accents($text, $accent); } sub t2h_transliterate_cross_manual_accent($$) { my $accent = shift; my $args = shift; my $text = $args->[0]; if (exists($unicode_accents{$accent}->{$text}) and exists ($transliterate_map{$unicode_accents{$accent}->{$text}})) { return $transliterate_map{$unicode_accents{$accent}->{$text}}; } return $text; } } # end package Texi2HTML::Config # set the defaults based on real command name set_config_init_dirs_output($real_command_name); use vars qw( %value %alias ); # variables which might be redefined by the user but aren't likely to be # they seem to be in the main namespace use vars qw( %index_names %index_prefix_to_name %predefined_index %valid_index %reference_sec2level %code_style_map %forbidden_index_name ); # Some global variables are set in the script, and used in the subroutines # they are in the Texi2HTML namespace, thus prefixed with Texi2HTML::. # see texi2html.init for details. #+++############################################################################ # # # Pasted content of File $(srcdir)/MySimple.pm: Command-line processing # # # #---############################################################################ # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, if $T2H_HOME/MySimple.pm # exists. # @MYSIMPLE@ package Getopt::MySimple; # Name: # Getopt::MySimple. # # Documentation: # POD-style (incomplete) documentation is in file MySimple.pod # # Tabs: # 4 spaces || die. # # Author: # Ron Savage rpsavage@ozemail.com.au. # 1.00 19-Aug-97 Initial version. # 1.10 13-Oct-97 Add arrays of switches (eg '=s@'). # 1.20 3-Dec-97 Add 'Help' on a per-switch basis. # 1.30 11-Dec-97 Change 'Help' to 'verbose'. Make all hash keys lowercase. # 1.40 10-Nov-98 Change width of help report. Restructure tests. # 1-Jul-00 Modifications for Texi2html # -------------------------------------------------------------------------- # Locally modified by obachman (Display type instead of env, order by cmp) # $Id: MySimple.pm,v 1.8 2009/08/23 21:50:15 pertusus Exp $ # use strict; # no strict 'refs'; use vars qw(@EXPORT @EXPORT_OK @ISA); use vars qw($fieldWidth $opt $VERSION); use Exporter(); use Getopt::Long; @ISA = qw(Exporter); @EXPORT = qw(); @EXPORT_OK = qw($opt); # An alias for $self -> {'opt'}. # -------------------------------------------------------------------------- $fieldWidth = 20; $VERSION = '1.41'; # -------------------------------------------------------------------------- sub byOrder { my($self) = @_; return uc($a) cmp (uc($b)); } # -------------------------------------------------------------------------- sub dumpOptions { my($self) = @_; print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n"; for (sort byOrder keys(%{$self -> {'opt'} }) ) { print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n"; } print "\n"; } # End of dumpOptions. # -------------------------------------------------------------------------- # Return: # 0 -> Error. # 1 -> Ok. sub getOptions { push(@_, 0) if ($#_ == 2); # Default for $ignoreCase is 0. push(@_, 1) if ($#_ == 3); # Default for $helpThenExit is 1. my($self, $default, $helpText, $versionText, $helpThenExit, $versionThenExit, $ignoreCase) = @_; $helpThenExit = 1 unless (defined($helpThenExit)); $versionThenExit = 1 unless (defined($versionThenExit)); $ignoreCase = 0 unless (defined($ignoreCase)); $self -> {'default'} = $default; $self -> {'helpText'} = $helpText; $self -> {'versionText'} = $versionText; $Getopt::Long::ignorecase = $ignoreCase; unless (defined($self -> {'default'}{'help'})) { $self -> {'default'}{'help'} = { type => ':i', default => '', linkage => sub {$self->helpOptions($_[1]); sleep 5;exit (0) if $helpThenExit;}, verbose => "print help and exit" }; } unless (defined($self -> {'default'}{'version'})) { $self -> {'default'}{'version'} = { type => '', default => '', linkage => sub {print $self->{'versionText'}; exit (0) if $versionThenExit;}, verbose => "print version and exit" }; } for (keys(%{$self -> {'default'} }) ) { next unless (ref(${$self -> {'default'} }{$_}) eq 'HASH'); my $type = ${$self -> {'default'} }{$_}{'type'}; push(@{$self -> {'type'} }, "$_$type"); my $key = $_; # get rid of aliases, if any $key =~ s/\|.*//; $self->{'opt'}->{$key} = ${$self -> {'default'} }{$_}{'linkage'} if ${$self -> {'default'} }{$_}{'linkage'}; } my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} }); return $result unless $result; for (keys(%{$self -> {'default'} }) ) { if (! defined(${$self -> {'opt'} }{$_})) #{ { ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'}; } } $result; } # End of getOptions. # -------------------------------------------------------------------------- sub helpOptions { my($self) = shift; my($noHelp) = shift; $noHelp = 0 unless $noHelp; my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth) = (10, 5, 9, 78, 4, 11); print "$self->{'helpText'}" if ($self -> {'helpText'}); print ' Option', ' ' x ($optwidth - length('Option') -1 ), 'Type', ' ' x ($typewidth - length('Type') + 1), 'Default', ' ' x ($defaultwidth - length('Default') ), "Description\n"; for (sort byOrder keys(%{$self -> {'default'} }) ) { my($line, $help, $option, $val); $option = $_; next if (ref(${$self -> {'default'} }{$_}) ne 'HASH' or (${$self->{'default'} }{$_}{'noHelp'} && ${$self->{'default'} }{$_}{'noHelp'} > $noHelp)); #$line = " -$_" . ' ' x ($optwidth - (2 + length) ) . # "${$self->{'default'} }{$_}{'type'} ". # ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) )); $line = " --$_" . "${$self->{'default'} }{$_}{'type'}". ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) )); $val = ${$self->{'default'} }{$_}{'linkage'}; if ($val) { if ((ref($val) eq 'SCALAR') and (defined($$val))) { $val = $$val; } else { $val = ''; } } elsif (defined(${$self->{'default'} }{$_}{'default'})) { $val = ${$self->{'default'} }{$_}{'default'}; } else { $val = ''; } $line .= "$val "; $line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line)); if (defined(${$self -> {'default'} }{$_}{'verbose'}) && ${$self -> {'default'} }{$_}{'verbose'} ne '') { $help = "${$self->{'default'} }{$_}{'verbose'}"; } else { $help = ' '; } if ((length("$line") + length($help)) < $maxlinewidth) { print $line , $help, "\n"; } else { print $line, "\n", ' ' x $valind, $help, "\n"; } for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}})) { print ' ' x ($valind + 2); print $val, ' ', ' ' x ($valwidth - length($val) - 2); print ${$self->{'default'}}{$option}{'values'}{$val}, "\n"; } } print <| ! no argument: variable is set to 1 on -foo (or, to 0 on -nofoo) =s | :s mandatory (or, optional) string argument =i | :i mandatory (or, optional) integer argument EOT } # End of helpOptions. #------------------------------------------------------------------- sub new { my($class) = @_; my($self) = {}; $self -> {'default'} = {}; $self -> {'helpText'} = ''; $self -> {'opt'} = {}; $opt = $self -> {'opt'}; # An alias for $self -> {'opt'}. $self -> {'type'} = (); return bless $self, $class; } # End of new. # -------------------------------------------------------------------------- 1; # End MySimple.pm require "$T2H_HOME/MySimple.pm" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/MySimple.pm" && -r "$T2H_HOME/MySimple.pm"); #+++######################################################################## # # # Pasted content of File $(srcdir)/T2h_i18n.pm: Internationalisation # # # #---######################################################################## # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, if $T2H_HOME/T2h_i18n.pm # exists. { # @T2H_I18N@ #+############################################################################## # # T2h_i18n.pm: Internationalization for texi2html # # Copyright (C) 1999-2005 Patrice Dumas , # Derek Price , # Adrian Aichner , # & others. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # #-############################################################################## # This requires perl version 5 or higher require 5.0; package Texi2HTML::I18n; use strict; use vars qw( @ISA @EXPORT ); use Exporter; @ISA = qw(Exporter); @EXPORT = qw(pretty_date); my $language; my $i18n_dir = 'i18n'; # name of the directory containing the per language files #my $translation_file = 'translations.pl'; # file containing all the translations #my @known_languages = ('de', 'nl', 'es', 'no', 'pt', 'fr'); # The supported # languages ######################################################################## # Language dependencies: # To add a new language extend the WORDS hash and create $T2H_<...>_WORDS hash # To redefine one word, simply do: # $T2h_i18n::T2H_LANGUAGES->{}->{} = 'whatever' in your personal init file. # # Those hashes are obsolete but retained here for reference my $T2H_WORDS_EN = { # titles of pages #'Table of Contents' => 'Table of Contents', #'Short Table of Contents' => 'Short Table of Contents', #'Index' => 'Index', #'About This Document' => 'About This Document', #'Footnotes' => 'Footnotes', #'See' => 'See', #'see' => 'see', #'section' => 'section', 'About This Document' => '', 'Table of Contents' => '', 'Short Table of Contents', => '', 'Index' => '', 'Footnotes' => '', 'See' => '', 'see' => '', 'section' => '', 'Top' => '', 'Untitled Document' => '', # If necessary, we could extend this as follows: # # text for buttons # 'Top_Button' => 'Top', # 'ToC_Button' => 'Contents', # 'Overview_Button' => 'Overview', # 'Index_button' => 'Index', # 'Back_Button' => 'Back', # 'FastBack_Button' => 'FastBack', # 'Prev_Button' => 'Prev', # 'Up_Button' => 'Up', # 'Next_Button' => 'Next', # 'Forward_Button' =>'Forward', # 'FastWorward_Button' => 'FastForward', # 'First_Button' => 'First', # 'Last_Button' => 'Last', # 'About_Button' => 'About' 'January' => '', 'February' => '', 'March' => '', 'April' => '', 'May' => '', 'June' => '', 'July' => '', 'August' => '', 'September' => '', 'October' => '', 'November' => '', 'December' => '', 'T2H_today' => '%s, %d %d', }; my $T2H_WORDS_DE = { 'Table of Contents' => 'Inhaltsverzeichniss', 'Short Table of Contents' => 'Kurzes Inhaltsverzeichniss', 'Index' => 'Index', 'About This Document' => 'Über dieses Dokument', 'Footnotes' => 'Fußnoten', 'See' => 'Siehe', 'see' => 'siehe', 'section' => 'Abschnitt', 'January' => 'Januar', 'February' => 'Februar', 'March' => 'März', 'April' => 'April', 'May' => 'Mai', 'June' => 'Juni', 'July' => 'Juli', 'August' => 'August', 'September' => 'September', 'October' => 'Oktober', 'November' => 'November', 'December' => 'Dezember', }; my $T2H_WORDS_NL = { 'Table of Contents' => 'Inhoudsopgave', 'Short Table of Contents' => 'Korte inhoudsopgave', 'Index' => 'Index', #Not sure ;-) 'About This Document' => 'No translation available!', #No translation available! 'Footnotes' => 'No translation available!', #No translation available! 'See' => 'Zie', 'see' => 'zie', 'section' => 'sectie', 'January' => 'Januari', 'February' => 'Februari', 'March' => 'Maart', 'April' => 'April', 'May' => 'Mei', 'June' => 'Juni', 'July' => 'Juli', 'August' => 'Augustus', 'September' => 'September', 'October' => 'Oktober', 'November' => 'November', 'December' => 'December', }; my $T2H_WORDS_ES = { 'Table of Contents' => 'índice General', 'Short Table of Contents' => 'Resumen del Contenido', 'Index' => 'Index', #Not sure ;-) 'About This Document' => 'No translation available!', #No translation available! 'Footnotes' => 'Fußnoten', 'See' => 'Véase', 'see' => 'véase', 'section' => 'sección', 'January' => 'enero', 'February' => 'febrero', 'March' => 'marzo', 'April' => 'abril', 'May' => 'mayo', 'June' => 'junio', 'July' => 'julio', 'August' => 'agosto', 'September' => 'septiembre', 'October' => 'octubre', 'November' => 'noviembre', 'December' => 'diciembre', }; my $T2H_WORDS_NO = { 'Table of Contents' => 'Innholdsfortegnelse', 'Short Table of Contents' => 'Kort innholdsfortegnelse', 'Index' => 'Indeks', #Not sure ;-) 'About This Document' => 'No translation available!', #No translation available! 'Footnotes' => 'No translation available!', 'See' => 'Se', 'see' => 'se', 'section' => 'avsnitt', 'January' => 'januar', 'February' => 'februar', 'March' => 'mars', 'April' => 'april', 'May' => 'mai', 'June' => 'juni', 'July' => 'juli', 'August' => 'august', 'September' => 'september', 'October' => 'oktober', 'November' => 'november', 'December' => 'desember', }; my $T2H_WORDS_PT = { 'Table of Contents' => 'Sumário', 'Short Table of Contents' => 'Breve Sumário', 'Index' => 'Índice', #Not sure ;-) 'About This Document' => 'No translation available!', #No translation available! 'Footnotes' => 'No translation available!', 'See' => 'Veja', 'see' => 'veja', 'section' => 'Seção', 'January' => 'Janeiro', 'February' => 'Fevereiro', 'March' => 'Março', 'April' => 'Abril', 'May' => 'Maio', 'June' => 'Junho', 'July' => 'Julho', 'August' => 'Agosto', 'September' => 'Setembro', 'October' => 'Outubro', 'November' => 'Novembro', 'December' => 'Dezembro', }; my $T2H_WORDS_FR = { 'Table of Contents' => 'Table des matières', 'Short Table of Contents' => 'Résumée du contenu', 'Index' => 'Index', 'About This Document' => 'A propos de ce document', 'Footnotes' => 'Notes de bas de page', 'See' => 'Voir', 'see' => 'voir', 'section' => 'section', 'January' => 'Janvier', 'February' => 'Février', 'March' => 'Mars', 'April' => 'Avril', 'May' => 'Mai', 'June' => 'Juin', 'July' => 'Juillet', 'August' => 'Août', 'September' => 'Septembre', 'October' => 'Octobre', 'November' => 'Novembre', 'December' => 'Décembre', 'T2H_today' => 'le %2$d %1$s %3$d' }; #$T2H_LANGUAGES = #{ # 'en' => $T2H_WORDS_EN, # 'de' => $T2H_WORDS_DE, # 'nl' => $T2H_WORDS_NL, # 'es' => $T2H_WORDS_ES, # 'no' => $T2H_WORDS_NO, # 'pt' => $T2H_WORDS_PT, # 'fr' => $T2H_WORDS_FR, #}; sub set_language($) { my $lang = shift; if (defined($lang) && exists($Texi2HTML::Config::LANGUAGES->{$lang}) && defined($Texi2HTML::Config::LANGUAGES->{$lang})) { $language = $lang; return 1; } else { return 0; } } sub get_language() { return $language; } my @MONTH_NAMES = ( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ); # This is not used as code, but used to mark months as strings to be # translated if (0) { my @mark_month_for_translation = ( gdt('January'), gdt('February'), gdt('March'), gdt('April'), gdt('May'), gdt('June'), gdt('July'), gdt('August'), gdt('September'), gdt('October'), gdt('November'), gdt('December') ); } my $I = \&get_string; sub pretty_date($) { my $lang = shift; my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); $year += ($year < 70) ? 2000 : 1900; return main::gdt('{month} {day}, {year}', { 'month' => main::gdt($MONTH_NAMES[$mon]), 'day' => $mday, 'year' => $year }); } my $error_no_en = 0; my %missing_strings; # arguments should already be converted sub get_string($;$$) { my $string = shift; my $arguments = shift; $arguments = undef if (!ref($arguments)); my $state = shift; # if duplicate is passed, it means that we are in the text and so should # use the main state if (defined($state) and $state->{'duplicate'} and defined($Texi2HTML::THISDOC{'state'})) { $state = main::duplicate_formatting_state($Texi2HTML::THISDOC{'state'}); } my $translated_string; my $T2H_LANGUAGES = $Texi2HTML::Config::LANGUAGES; if (! exists($T2H_LANGUAGES->{'en'})) { unless($error_no_en) { print STDERR "i18n: no LANGUAGES->{'en'} hash\n"; $error_no_en = 1; } } else { unless (exists ($T2H_LANGUAGES->{'en'}->{$string})) { unless (exists($missing_strings{$string})) { #print STDERR "i18n: missing string $string\n"; $missing_strings{$string} = 1; } } if (defined ($T2H_LANGUAGES->{$language}->{$string}) and ($T2H_LANGUAGES->{$language}->{$string} ne '')) { $translated_string = $T2H_LANGUAGES->{$language}->{$string}; } elsif (defined ($T2H_LANGUAGES->{'en'}->{$string}) and ($T2H_LANGUAGES->{'en'}->{$string} ne '')) { $translated_string = $T2H_LANGUAGES->{'en'}->{$string}; } else { $translated_string = $string; } } return main::substitute_line($translated_string, "translation", $state) unless (defined($arguments) or !keys(%$arguments)); # taken from libintl perl, copyright Guido. sub __expand my %args = %$arguments; my $re = join '|', map { quotemeta $_ } keys %args; if ($state->{'keep_texi'}) { $translated_string =~ s/\{($re)\}/defined $args{$1} ? $args{$1} : "{$1}"/ge; return $translated_string; } # if there are arguments, we must protect the {arg} constructs before # doing substitute_line. So there is a first pass here to change {arg} # to %@internal_translation_open_brace{}arg@internal_translation_close_brace{} $translated_string =~ s/\{($re)\}/\@internal_translation_open_brace\{\}$1\@internal_translation_close_brace\{\}/g; foreach my $map (\%Texi2HTML::Config::things_map, \%Texi2HTML::Config::pre_map, \%Texi2HTML::Config::texi_map, \%Texi2HTML::Config::simple_format_texi_map) { $map->{'internal_translation_open_brace'} = '{'; $map->{'internal_translation_close_brace'} = '}'; } $translated_string = main::substitute_line($translated_string, "translation", $state); $translated_string =~ s/\{($re)\}/defined $args{$1} ? $args{$1} : "{$1}"/ge; foreach my $map (\%Texi2HTML::Config::things_map, \%Texi2HTML::Config::pre_map, \%Texi2HTML::Config::texi_map, \%Texi2HTML::Config::simple_format_texi_map) { delete $map->{'internal_translation_open_brace'}; delete $map->{'internal_translation_close_brace'}; } return $translated_string; } 1; require "$T2H_HOME/T2h_i18n.pm" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/T2h_i18n.pm" && -r "$T2H_HOME/T2h_i18n.pm"); } ######################################################################### # # latex2html code # #---###################################################################### { # leave this within comments, and keep the require statement # This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_l2h.pm # exists. # @T2H_L2H@ #+############################################################################## # # T2h_l2h.pm: interface to LaTeX2HTML # # Copyright (C) 1999-2005 Patrice Dumas , # Derek Price , # Adrian Aichner , # & others. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # #-############################################################################## require 5.0; use strict; package Texi2HTML::LaTeX2HTML; use Cwd; # latex2html conversions consist of three stages: # 1) to latex: Put "latex" code into a latex file # (init, to_latex, finish_to_latex) # 2) to html: Use latex2html to generate corresponding html code and images # (to_html) # 3) from html: Extract generated code and images from latex2html run # (init_from_html, do_tex) # init l2h defaults for files and names # global variable used for caching # FIXME there is no reason for this variable to be global use vars qw( %l2h_cache ); my ($l2h_name, $l2h_latex_file, $l2h_cache_file, $l2h_html_file, $l2h_prefix); # holds the status of latex2html operations. If 0 it means that there was # an error my $status = 0; my $debug; my $verbose; my $docu_rdir; my $docu_name; # init_from_html my $extract_error_count; my $invalid_counter_count; # change_image_file_names my %l2h_img; # associate src file to destination file # such that files are not copied twice my $image_count; # do_tex my $html_output_count = 0; # html text outputed in html result file ########################## # # First stage: Generation of Latex file # Initialize with: init # Add content with: to_latex ($text) --> HTML placeholder comment # Finish with: finish_to_latex # my $l2h_latex_preamble = <{'top'}}); $docu_name = $Texi2HTML::THISDOC{'file_base_name'}; $docu_rdir = $Texi2HTML::THISDOC{'destination_directory'}; $docu_rdir = '' if (!defined($docu_rdir)); $l2h_name = "${docu_name}_l2h"; $l2h_latex_file = "$docu_rdir${l2h_name}.tex"; $l2h_cache_file = "${docu_rdir}${docu_name}-l2h_cache.pm"; # destination dir -- generated images are put there, should be the same # as dir of enclosing html document -- $l2h_html_file = "$docu_rdir${l2h_name}.html"; $l2h_prefix = "${l2h_name}_"; $debug = $Texi2HTML::THISDOC{'debug_l2h'}; $verbose = $Texi2HTML::Config::VERBOSE; unless ($Texi2HTML::Config::L2H_SKIP) { unless (open(L2H_LATEX, ">$l2h_latex_file")) { main::document_error ("l2h: Can't open latex file '$l2h_latex_file' for writing: $!"); $status = 0; return; } warn "# l2h: use ${l2h_latex_file} as latex file\n" if ($verbose); print L2H_LATEX $l2h_latex_preamble; } # open the database that holds cached text init_cache() if (!defined($Texi2HTML::Config::L2H_SKIP) or $Texi2HTML::Config::L2H_SKIP); $status = 1; } # print text (2nd arg) into latex file (if not already there nor in cache) # which can be later on replaced by the latex2html generated text. # sub to_latex($$$) { my $command = shift; my $text = shift; my $counter = shift; return unless ($status); if ($command eq 'tex') { $text .= ' '; } elsif ($command eq 'math') { $text = "\$".$text."\$"; } $to_latex_count++; $text =~ s/(\s*)$//; # try whether we have text already on things to do my $count = $l2h_to_latex{$text}; unless ($count) { $latex_count++; $count = $latex_count; # try whether we can get it from cache my $cached_text = from_cache($text); if (defined($cached_text)) { $cached_count++; # put the cached result in the html result array $l2h_from_html[$count] = $cached_text; } else { $latex_converted_count++; unless ($Texi2HTML::Config::L2H_SKIP) { print L2H_LATEX "\\begin{rawhtml}\n\n"; print L2H_LATEX "\n"; print L2H_LATEX "\\end{rawhtml}\n"; print L2H_LATEX "$text\n"; print L2H_LATEX "\\begin{rawhtml}\n"; print L2H_LATEX "\n\n"; print L2H_LATEX "\\end{rawhtml}\n"; } } $l2h_to_latex[$count] = $text; $l2h_to_latex{$text} = $count; } $global_count{"${command}_$counter"} = $count; return 1; } # print closing into latex file and close it sub finish_to_latex() { my $reused = $to_latex_count - $latex_converted_count - $cached_count; unless ($Texi2HTML::Config::L2H_SKIP) { print L2H_LATEX $l2h_latex_closing; close (L2H_LATEX); } warn "# l2h: finished to latex ($cached_count cached, $reused reused, $latex_converted_count to process)\n" if ($verbose); unless ($latex_count) { # no @tex nor @math finish(); return 0; } return 1; } ################################### # Second stage: Use latex2html to generate corresponding html code and images # # to_html([$l2h_latex_file, [$l2h_html_dir]]): # Call latex2html on $l2h_latex_file # Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir # Return 1, on success # 0, otherwise # sub to_html() { my ($call, $dotbug); # when there are no tex constructs to convert (happens in case everything # comes from the cache), there is no latex2html run if ($Texi2HTML::Config::L2H_SKIP or ($latex_converted_count == 0)) { warn "# l2h: skipping latex2html run\n" if ($verbose); return 1; } # Check for dot in directory where dvips will work if ($Texi2HTML::Config::L2H_TMP) { if ($Texi2HTML::Config::L2H_TMP =~ /\./) { main::document_warn ("l2h: l2h_tmp dir contains a dot."); $dotbug = 1; } } else { if (cwd() =~ /\./) { main::document_warn ("l2h: current dir contains a dot."); $dotbug = 1; } } # fix it, if necessary and hope that it works #$Texi2HTML::Config::L2H_TMP = "/tmp" if ($dotbug); return 0 if ($dotbug); $call = $Texi2HTML::Config::L2H_L2H; # use init file, if specified my $init_file = main::locate_init_file($Texi2HTML::Config::L2H_FILE); $call = $call . " -init_file " . $init_file if ($init_file); # set output dir $call .= (($docu_rdir ne '') ? " -dir $docu_rdir" : " -no_subdir"); # use l2h_tmp, if specified $call .= " -tmp $Texi2HTML::Config::L2H_TMP" if (defined($Texi2HTML::Config::L2H_TMP) and $Texi2HTML::Config::L2H_TMP ne ''); # use a given html version if specified $call .= " -html_version $Texi2HTML::Config::L2H_HTML_VERSION" if (defined($Texi2HTML::Config::L2H_HTML_VERSION) and $Texi2HTML::Config::L2H_HTML_VERSION ne ''); # options we want to be sure of $call .= " -address 0 -info 0 -split 0 -no_navigation -no_auto_link"; $call .= " -prefix $l2h_prefix $l2h_latex_file"; warn "# l2h: executing '$call'\n" if ($verbose); if (system($call)) { main::document_error ("l2h: '${call}' did not succeed"); return 0; } else { warn "# l2h: latex2html finished successfully\n" if ($verbose); return 1; } } ########################## # Third stage: Extract generated contents from latex2html run # Initialize with: init_from_html # open $l2h_html_file for reading # reads in contents into array indexed by numbers # return 1, on success -- 0, otherwise # Finish with: finish # closes $l2h_html_dir/$l2h_name.".$docu_ext" # the images generated by latex2html have names like ${docu_name}_l2h_img?.png # they are copied to ${docu_name}_?.png, and html is changed accordingly. # FIXME is it really necessary to bother doing that? Looks like an unneeded # complication to me (pertusus, 2009), and it could go bad if there is some # SRC="(.*?)" in the text (though the regexp could be made more specific). # %l2h_img; # associate src file to destination file # such that files are not copied twice sub change_image_file_names($) { my $content = shift; my @images = ($content =~ /SRC="(.*?)"/g); my ($src, $dest); for $src (@images) { $dest = $l2h_img{$src}; unless ($dest) { my $ext = ''; if ($src =~ /.*\.(.*)$/ and (!defined($Texi2HTML::THISDOC{'extension'}) or $1 ne $Texi2HTML::THISDOC{'extension'})) { $ext = ".$1"; } else { # A warning when the image extension is the same than the # document extension. copying the file could result in # overwriting an output file (almost surely if the default # texi2html file names are used). main::document_warn ("L2h image $src has invalid extension"); next; } while (-e "$docu_rdir${docu_name}_${image_count}$ext") { $image_count++; } $dest = "${docu_name}_${image_count}$ext"; if ($debug) { # not portable, but only used with debug. system("cp -f $docu_rdir$src $docu_rdir$dest"); } else { # FIXME error condition not checked. rename ("$docu_rdir$src", "$docu_rdir$dest"); } $l2h_img{$src} = $dest; #unlink "$docu_rdir$src" unless ($debug); } $content =~ s/SRC="$src"/SRC="$dest"/g; } return $content; } sub init_from_html() { # when there are no tex constructs to convert (happens in case everything # comes from the cache), the html file that was generated by previous # latex2html runs isn't reused. if ($latex_converted_count == 0) { return 1; } if (! open(L2H_HTML, "<$l2h_html_file")) { main::document_warn ("l2h: Can't open $l2h_html_file for reading"); return 0; } warn "# l2h: use $l2h_html_file as html file\n" if ($verbose); my $html_converted_count = 0; # number of html resulting texts # retrieved in the file my ($count, $h_line); while ($h_line = ) { if ($h_line =~ /!-- l2h_begin $l2h_name ([0-9]+) --/) { $count = $1; my $h_content = ''; my $h_end_found = 0; while ($h_line = ) { if ($h_line =~ /!-- l2h_end $l2h_name $count --/) { $h_end_found = 1; chomp $h_content; chomp $h_content; $html_converted_count++; # transform image file names and copy image files $h_content = change_image_file_names($h_content); # store result in the html result array $l2h_from_html[$count] = $h_content; # also add the result in cache hash $l2h_cache{$l2h_to_latex[$count]} = $h_content; last; } $h_content = $h_content.$h_line; } unless ($h_end_found) { # couldn't found the closing comment. Certainly a bug. main::msg_debug ("l2h: l2h_end $l2h_name $count not found"); close(L2H_HTML); return 0; } } } # Not the same number of converted elements and retrieved elements if ($latex_converted_count != $html_converted_count) { main::msg_debug ("l2h: waiting for $latex_converted_count elements found $html_converted_count"); } warn "# l2h: Got $html_converted_count of $latex_count html contents\n" if ($verbose); close(L2H_HTML); return 1; } # $html_output_count = 0; # html text outputed in html result file # called each time a construct handled by latex2html is encountered, should # output the corresponding html sub do_tex($$$$) { my $style = shift; my $counter = shift; my $state = shift; return unless ($status); my $count = $global_count{"${style}_$counter"}; ################################## begin debug section (incorrect counts) if (!defined($count)) { # counter is undefined $invalid_counter_count++; main::msg_debug ("l2h: undefined count for ${style}_$counter"); return ("") if ($debug); return ''; } elsif(($count <= 0) or ($count > $latex_count)) { # counter out of range $invalid_counter_count++; main::msg_debug ("l2h: Request of $count content which is out of valide range [0,$latex_count)"); return ("") if ($debug); return ''; } ################################## end debug section (incorrect counts) # this seems to be a valid counter my $result = ''; $result = "" if ($debug); if (defined($l2h_from_html[$count])) { $html_output_count++; # maybe we could also have something if simple_format # with Texi2HTML::Config::protect_text in case there # was some @math on a line passed through simple_format. # This would certainly be illegal texinfo, however. if ($state->{'remove_texi'}) {# don't protect anything $result .= $l2h_to_latex[$count]; } else { $result .= $l2h_from_html[$count]; } } else { # if the result is not in @l2h_from_html, there is an error somewhere. $extract_error_count++; main::msg_debug ("l2h: can't extract content $count from html"); # try simple (ordinary) substitution (without l2h) $result .= "" if ($debug); $result .= main::substitute_text({}, undef, 'error in l2h', $l2h_to_latex[$count]); } $result .= "" if ($debug); return $result; } # store results in the cache and remove temporary files. sub finish() { return unless($status); if ($verbose) { if ($extract_error_count + $invalid_counter_count) { warn "# l2h: finished from html ($extract_error_count extract and $invalid_counter_count invalid counter errors)\n"; } else { warn "# l2h: finished from html (no error)\n"; } if ($html_output_count != $latex_converted_count) { # this may happen if @-commands are collected at some places # but @-command at those places are not expanded later. For # example @math on @multitable lines. warn "# l2h: $html_output_count html outputed for $latex_converted_count converted\n"; } } store_cache(); if ($Texi2HTML::Config::L2H_CLEAN) { local ($_); warn "# l2h: removing temporary files generated by l2h extension\n" if $verbose; while (<"$docu_rdir$l2h_name"*>) { # FIXME error condition not checked unlink $_; } } warn "# l2h: Finished\n" if $verbose; return 1; } # the driver of end of first pass and second pass # sub latex2html() { return unless($status); return unless ($status = finish_to_latex()); return unless ($status = to_html()); } ############################## # stuff for l2h caching # # FIXME it is clear that l2h stuff takes very long compared with texi2html # which is already quite long. However this also adds some complexity # I tried doing this with a dbm data base, but it did not store all # keys/values. Hence, I did as latex2html does it sub init_cache { if (-r "$l2h_cache_file") { my $rdo = do "$l2h_cache_file"; main::document_error ("l2h: could not load $docu_rdir$l2h_cache_file: $@") unless ($rdo); } } # store all the text obtained through latex2html sub store_cache { return unless $latex_count; my ($key, $value); unless (open(FH, ">$l2h_cache_file")) { main::document_error ("l2h: could not open $docu_rdir$l2h_cache_file for writing: $!"); return; } while (($key, $value) = each %l2h_cache) { # escape stuff $key =~ s|/|\\/|g; $key =~ s|\\\\/|\\/|g; # weird, a \ at the end of the key results in an error # maybe this also broke the dbm database stuff $key =~ s|\\$|\\\\|; $value =~ s/\|/\\\|/go; $value =~ s/\\\\\|/\\\|/go; $value =~ s|\\\\|\\\\\\\\|g; print FH "\n\$l2h_cache_key = q/$key/;\n"; print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n"; } print FH "1;"; close (FH); } # return cached html, if it exists for text, and if all pictures # are there, as well sub from_cache($) { my $text = shift; my $cached = $l2h_cache{$text}; if (defined($cached)) { while ($cached =~ m/SRC="(.*?)"/g) { unless (-e "$docu_rdir$1") { return undef; } } return $cached; } return undef; } 1; require "$T2H_HOME/T2h_l2h.pm" if ($0 =~ /\.pl$/ && -e "$T2H_HOME/T2h_l2h.pm" && -r "$T2H_HOME/T2h_l2h.pm"); } { package Texi2HTML::LaTeX2HTML::Config; # latex2html variables # These variables are not used. They are here for information only, and # an example of config file for latex2html file is included. my $ADDRESS; my $ANTI_ALIAS; my $ANTI_ALIAS_TEXT; my $ASCII_MODE; my $AUTO_LINK; my $AUTO_PREFIX; my $CHILDLINE; my $DEBUG; my $DESTDIR; my $DVIPS = 'dvips'; my $ERROR; my $EXTERNAL_FILE; my $EXTERNAL_IMAGES; my $EXTERNAL_UP_LINK; my $EXTERNAL_UP_TITLE; my $FIGURE_SCALE_FACTOR; my $HTML_VERSION; my $IMAGES_ONLY; my $INFO; my $LINE_WIDTH; my $LOCAL_ICONS; my $LONG_TITLES; my $MATH_SCALE_FACTOR; my $MAX_LINK_DEPTH; my $MAX_SPLIT_DEPTH; my $NETSCAPE_HTML; my $NOLATEX; my $NO_FOOTNODE; my $NO_IMAGES; my $NO_NAVIGATION; my $NO_SIMPLE_MATH; my $NO_SUBDIR; my $PAPERSIZE; my $PREFIX; my $PS_IMAGES; my $REUSE; my $SCALABLE_FONTS; my $SHORTEXTN; my $SHORT_INDEX; my $SHOW_SECTION_NUMBERS; my $SPLIT; my $TEXDEFS; my $TITLE; my $TITLES_LANGUAGE; my $TMP; my $VERBOSE; my $WORDS_IN_NAVIGATION_PANEL_TITLES; my $WORDS_IN_PAGE; # @T2H_L2H_INIT@ ###################################################################### # from here on, its l2h init stuff # ## initialization for latex2html as for Singular manual generation ## obachman 3/99 # # Options controlling Titles, File-Names, Tracing and Sectioning # $TITLE = ''; $SHORTEXTN = 0; $LONG_TITLES = 0; #$DESTDIR = ''; $NO_SUBDIR = 1; #$PREFIX = ''; $AUTO_PREFIX = 0; $AUTO_LINK = 0; $SPLIT = 0; $MAX_LINK_DEPTH = 0; #$TMP = ''; $DEBUG = 0; $VERBOSE = 1; # # Options controlling Extensions and Special Features # #$HTML_VERSION = "3.2"; # set by command line $TEXDEFS = 1; # we absolutely need that $EXTERNAL_FILE = ''; $SCALABLE_FONTS = 1; $NO_SIMPLE_MATH = 1; $LOCAL_ICONS = 1; $SHORT_INDEX = 0; $NO_FOOTNODE = 1; $ADDRESS = ''; $INFO = ''; # # Switches controlling Image Generation # $ASCII_MODE = 0; $NOLATEX = 0; $EXTERNAL_IMAGES = 0; $PS_IMAGES = 0; $NO_IMAGES = 0; $IMAGES_ONLY = 0; $REUSE = 2; $ANTI_ALIAS = 1; $ANTI_ALIAS_TEXT = 1; # #Switches controlling Navigation Panels # $NO_NAVIGATION = 1; $ADDRESS = ''; $INFO = 0; # 0 = do not make a "About this document..." section # #Switches for Linking to other documents # # currently -- we don't care $MAX_SPLIT_DEPTH = 0; # Stop making separate files at this depth $MAX_LINK_DEPTH = 0; # Stop showing child nodes at this depth $NOLATEX = 0; # 1 = do not pass unknown environments to Latex $EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document $ASCII_MODE = 0; # 1 = do not use any icons or internal images # 1 = use links to external postscript images rather than inlined bitmap # images. $PS_IMAGES = 0; $SHOW_SECTION_NUMBERS = 0; ### Other global variables ############################################### # put dvips stderr on stdout since latex2html is alread very verbose $DVIPS = "$DVIPS ".' 2>&1'; $CHILDLINE = ""; # This is the line width measured in pixels and it is used to right justify # equations and equation arrays; $LINE_WIDTH = 500; # Used in conjunction with AUTO_NAVIGATION $WORDS_IN_PAGE = 300; # The value of this variable determines how many words to use in each # title that is added to the navigation panel (see below) # $WORDS_IN_NAVIGATION_PANEL_TITLES = 0; # This number will determine the size of the equations, special characters, # and anything which will be converted into an inlined image # *except* "image generating environments" such as "figure", "table" # or "minipage". # Effective values are those greater than 0. # Sensible values are between 0.1 - 4. $MATH_SCALE_FACTOR = 1.5; # This number will determine the size of # image generating environments such as "figure", "table" or "minipage". # Effective values are those greater than 0. # Sensible values are between 0.1 - 4. $FIGURE_SCALE_FACTOR = 1.6; # If both of the following two variables are set then the "Up" button # of the navigation panel in the first node/page of a converted document # will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set # to some text which describes this external link. $EXTERNAL_UP_LINK = ""; $EXTERNAL_UP_TITLE = ""; # If this is set then the resulting HTML will look marginally better if viewed # with Netscape. $NETSCAPE_HTML = 1; # Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" # Paper sizes has no effect other than in the time it takes to create inlined # images and in whether large images can be created at all ie # - larger paper sizes *MAY* help with large image problems # - smaller paper sizes are quicker to handle $PAPERSIZE = "a4"; # Replace "english" with another language in order to tell LaTeX2HTML that you # want some generated section titles (eg "Table of Contents" or "References") # to appear in a different language. Currently only "english" and "french" # is supported but it is very easy to add your own. See the example in the # file "latex2html.config" $TITLES_LANGUAGE = "english"; 1; # This must be the last non-comment line # End File l2h.init ###################################################################### } package main; if (!defined(Texi2HTML::Config::get_conf('use_nls'))) { my $use_nls = ('yes' eq 'yes' or $0 =~ /\.pl$/); Texi2HTML::Config::set_conf('use_nls', $use_nls); } # prepare the gettext-like framework. To be noted that Locales::TextDomain # canot be used, since it cannot be used dynamically through a reuires. # Fortunately, Locales::TextDomain is a thin layer above Locales::Messages. my $strings_textdomain = 'texi2html' . '_document'; $strings_textdomain = 'texi2html_document' if ($strings_textdomain eq '@'.'PACKAGE@' . '_document'); my $messages_textdomain = 'texi2html'; $messages_textdomain = 'texi2html' if ($messages_textdomain eq '@'.'PACKAGE@'); #my $messages_textdomain = 'texinfo'; if (Texi2HTML::Config::get_conf('use_nls')) { if ($0 =~ /\.pl$/) { # use in-source libintl when testing unshift @INC, "$T2H_HOME/lib/libintl-perl/lib"; } elsif ($ENV{T2H_SOURCE_LIBINTL}) { unshift @INC, $ENV{T2H_SOURCE_LIBINTL}; } elsif ('no' ne 'yes') { unshift @INC, "$pkgdatadir/lib/libintl-perl/lib"; } else { eval { require Locale::Messages; }; if ($@) { unshift @INC, "$pkgdatadir/lib/libintl-perl/lib"; } } # gettext-like translations #require Locale::TextDomain; require Locale::Messages; # we want a reliable way to switch locale, so we don't use the system # gettext. Locale::Messages->select_package ('gettext_pp'); if ($0 =~ /\.pl$/) { # in case of out of source build, the locales directory should # be two levels below. $T2H_HOME is in srcdir. foreach my $locales_dir ("$T2H_HOME/locales", "../../locales") { if (-d $locales_dir) { Locale::Messages::bindtextdomain ($strings_textdomain, $locales_dir); last; } } } else { # match where gettext installs Locale::Messages::bindtextdomain ($strings_textdomain, "$datadir/locale"); } # simply bind error messages to the installation directory. # Messages should be untranslated for tests. Locale::Messages::bindtextdomain ($messages_textdomain, "$datadir/locale"); } else { unshift @INC, "$pkgdatadir/lib/libintl-perl/lib"; require Locale::Messages; } sub __($) { my $msgid = shift; return Locale::Messages::dgettext($messages_textdomain, $msgid); } sub __p($$) { my $context = shift; my $msgid = shift; return Locale::Messages::dpgettext($messages_textdomain, $context, $msgid); } sub N__($) { return $_[0]; } # # flush stdout and stderr after every write # select(STDERR); $| = 1; select(STDOUT); $| = 1; my $I = \&Texi2HTML::I18n::get_string; ######################################################################## # # Global variable initialization # ######################################################################## # # pre-defined indices # %index_prefix_to_name = (); %index_names = ( 'cp' => { 'prefixes' => {'cp' => 0,'c' => 0}}, 'fn' => { 'prefixes' => {'fn' => 1, 'f' => 1}}, 'vr' => { 'prefixes' => {'vr' => 1, 'v' => 1}}, 'ky' => { 'prefixes' => {'ky' => 1, 'k' => 1}}, 'pg' => { 'prefixes' => {'pg' => 1, 'p' => 1}}, 'tp' => { 'prefixes' => {'tp' => 1, 't' => 1}} ); foreach my $name(keys(%index_names)) { foreach my $prefix (keys %{$index_names{$name}->{'prefixes'}}) { $forbidden_index_name{$prefix} = 1; $index_prefix_to_name{$prefix} = $name; } } foreach my $other_forbidden_index_name ('info','ps','pdf','htm', 'log','aux','dvi','texi','txi','texinfo','tex','bib') { $forbidden_index_name{$other_forbidden_index_name} = 1; } # commands with ---, -- '' and `` preserved # usefull with the old interface %code_style_map = ( 'code' => 1, 'command' => 1, 'env' => 1, 'file' => 1, 'kbd' => 1, 'option' => 1, 'samp' => 1, 'verb' => 1, ); my @element_directions = ('Up', 'Forward', 'Back', 'Next', 'Prev', 'SectionNext', 'SectionPrev', 'SectionUp', 'FastForward', 'FastBack', 'This', 'NodeUp', 'NodePrev', 'NodeNext', 'Following', 'NextFile', 'PrevFile', 'ToplevelNext', 'ToplevelPrev'); $::simple_map_ref = \%Texi2HTML::Config::simple_map; $::simple_map_math_ref = \%Texi2HTML::Config::simple_map_math; #$::simple_map_pre_ref = \%Texi2HTML::Config::simple_map_pre; $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; $::style_map_ref = \%Texi2HTML::Config::style_map; $::style_map_pre_ref = \%Texi2HTML::Config::style_map_pre; $::style_map_math_ref = \%Texi2HTML::Config::style_map_math; $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; $::things_map_ref = \%Texi2HTML::Config::things_map; $::pre_map_ref = \%Texi2HTML::Config::pre_map; $::texi_map_ref = \%Texi2HTML::Config::texi_map; #print STDERR "MAPS: $::simple_map_ref $::simple_map_pre_ref $::simple_map_texi_ref $::style_map_ref $::style_map_pre_ref $::style_map_texi_ref $::things_map_ref $::pre_map_ref $::texi_map_ref\n"; # delete from hash if we are using the new interface foreach my $code (keys(%code_style_map)) { delete ($code_style_map{$code}) if (ref($::style_map_ref->{$code}) eq 'HASH'); } # no paragraph in these commands my %no_paragraph_macro = ( 'xref' => 1, 'ref' => 1, 'pxref' => 1, 'inforef' => 1, 'anchor' => 1, ); # # texinfo section names to level # my %reference_sec2level = ( 'top', 0, 'chapter', 1, 'unnumbered', 1, 'chapheading', 1, 'appendix', 1, 'section', 2, 'unnumberedsec', 2, 'heading', 2, 'appendixsec', 2, 'subsection', 3, 'unnumberedsubsec', 3, 'subheading', 3, 'appendixsubsec', 3, 'subsubsection', 4, 'unnumberedsubsubsec', 4, 'subsubheading', 4, 'appendixsubsubsec', 4, ); # the reverse mapping. There is an entry for each sectioning command. # The value is a ref on an array containing at each index the corresponding # sectioning command name. my %level2sec; { my $sections = [ ]; my $appendices = [ ]; my $unnumbered = [ ]; my $headings = [ ]; foreach my $command (keys (%reference_sec2level)) { if ($command =~ /^appendix/) { $level2sec{$command} = $appendices; } elsif ($command =~ /^unnumbered/ or $command eq 'top') { $level2sec{$command} = $unnumbered; } elsif ($command =~ /section$/ or $command eq 'chapter') { $level2sec{$command} = $sections; } else { $level2sec{$command} = $headings; } $level2sec{$command}->[$reference_sec2level{$command}] = $command; } } # out of the main hierarchy $reference_sec2level{'part'} = 0; # this are synonyms $reference_sec2level{'appendixsection'} = 2; # sec2level{'majorheading'} is also 1 and not 0 $reference_sec2level{'majorheading'} = 1; $reference_sec2level{'chapheading'} = 1; $reference_sec2level{'centerchap'} = 1; sub stop_paragraph_command($) { my $command = shift; return 1 if ($Texi2HTML::Config::stop_paragraph_command{$command} or defined($reference_sec2level{$command})); } sub set_no_line_macro($$) { my $macro = shift; my $value = shift; $Texi2HTML::Config::no_paragraph_commands{$macro} = $value unless defined($Texi2HTML::Config::no_paragraph_commands{$macro}); } # those macros aren't considered as beginning a paragraph foreach my $no_line_macro ('alias', 'macro', 'unmacro', 'rmacro', 'titlefont', 'include', 'copying', 'end copying', 'tab', 'item', 'itemx', '*', 'float', 'end float', 'caption', 'shortcaption', 'cindex', 'image') { set_no_line_macro($no_line_macro, 1); } foreach my $key (keys(%Texi2HTML::Config::misc_command), keys(%reference_sec2level)) { set_no_line_macro($key, 1); } # a hash associating a format @thing / @end thing with the type of the format # 'complex_format' 'simple_format' 'deff' 'list' 'menu' 'paragraph_format' my %format_type = (); foreach my $simple_format (keys(%Texi2HTML::Config::format_map)) { $format_type{$simple_format} = 'simple_format'; } foreach my $paragraph_style (keys(%Texi2HTML::Config::paragraph_style)) { $format_type{$paragraph_style} = 'paragraph_format'; } # FIXME $complex_format_map obsoleted in nov 2009 foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map), keys(%Texi2HTML::Config::complex_format_map)) { $format_type{$complex_format} = 'complex_format'; } foreach my $table (('table', 'ftable', 'vtable')) { $format_type{$table} = 'table'; } $format_type{'multitable'} = 'multitable'; foreach my $def_format (keys(%Texi2HTML::Config::def_map)) { $format_type{$def_format} = 'deff'; } $format_type{'itemize'} = 'list'; $format_type{'enumerate'} = 'list'; $format_type{'menu'} = 'menu'; $format_type{'detailmenu'} = 'menu'; $format_type{'direntry'} = 'menu'; $format_type{'cartouche'} = 'cartouche'; $format_type{'float'} = 'float'; $format_type{'quotation'} = 'quotation'; $format_type{'smallquotation'} = 'quotation'; $format_type{'group'} = 'group'; my @special_regions = ('titlepage', 'copying', 'documentdescription'); foreach my $region (@special_regions) { $format_type{$region} = 'region'; } foreach my $key (keys(%format_type)) { set_no_line_macro($key, 1); set_no_line_macro("end $key", 1); } foreach my $macro (keys(%Texi2HTML::Config::format_in_paragraph)) { set_no_line_macro($macro, 1); set_no_line_macro("end $macro", 1); } # fake format at the bottom of the stack $format_type{'noformat'} = ''; # fake formats are formats used internally within other formats # we associate them with a real format, for the error messages my %fake_format = ( 'line' => 'table', 'term' => 'table', 'item' => 'list or table', 'row' => 'multitable row', 'cell' => 'multitable cell', 'deff_item' => 'definition command', 'menu_comment' => 'menu', 'menu_description' => 'menu', ); foreach my $key (keys(%fake_format)) { $format_type{$key} = 'fake'; } # raw formats which are expanded especially my @raw_regions = ('html', 'tex', 'xml', 'docbook'); foreach my $format (keys(%Texi2HTML::Config::texi_formats_map)) { push @raw_regions, $format if ($Texi2HTML::Config::texi_formats_map{$format} eq 'raw'); } # The css formats are associated with complex format commands, and associated # with the 'pre_style' key # FIXME $complex_format_map obsoleted in nov 2009 foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map)) { next if (defined($Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'})); $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = ''; $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"})); } # The css formats are associated with complex format commands, and associated # with the 'pre_style' key foreach my $complex_format (keys(%Texi2HTML::Config::complex_format_map)) { next if (defined($Texi2HTML::Config::complex_format_map{$complex_format}->{'pre_style'})); $Texi2HTML::Config::complex_format_map{$complex_format}->{'pre_style'} = ''; $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"})); } #+++############################################################################ # # # Argument parsing, initialisation # # # #---############################################################################ # shorthand for Texi2HTML::Config::VERBOSE my $T2H_VERBOSE; my $T2H_DEBUG; sub line_warn($$); sub document_warn($); sub file_line_warn($$;$); sub cmdline_warn ($); my $T2H_FAILURE_TEXT = sprintf(__("Try `%s --help' for more information.\n"), $real_command_name); #print STDERR "" . gdt('test i18n: \' , \a \\ %% %{unknown}a %known % %{known} \\', { 'known' => 'a known string', 'no' => 'nope'}); exit 0; # file: file name to locate. It can be a file path. # all_files: if true collect all the files with that name, otherwise stop # at first match. # directories: a reference on a array containing a list of directories to # search the file in. default is # @Texi2HTML::Config::CONF_DIRS, @program_config_dirs. sub locate_init_file($;$$) { my $file = shift; my $all_files = shift; my $directories = shift; if (!defined($directories)) { if ($all_files) { $directories = [ @program_config_dirs ]; } else { $directories = [ @Texi2HTML::Config::CONF_DIRS, @program_init_dirs ]; } } if ($file =~ /^\//) { return $file if (-e $file and -r $file); } else { my @files; foreach my $dir (@$directories) { next unless (-d "$dir"); if ($all_files) { push (@files, "$dir/$file") if (-e "$dir/$file" and -r "$dir/$file"); } else { return "$dir/$file" if (-e "$dir/$file" and -r "$dir/$file"); } } return @files if ($all_files); } return undef; } # called on -init-file sub load_init_file { # First argument is option shift; # second argument is value of options my $init_file = shift; my $file; if ($file = locate_init_file($init_file)) { print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE); # require the file in the Texi2HTML::Config namespace return (Texi2HTML::Config::load($file)); } else { document_error ("Can't read init file $init_file"); return 0; } } sub set_date($) { my $language = shift; if (!$Texi2HTML::Config::TEST) { print STDERR "# Setting date in $language\n" if ($T2H_DEBUG); $Texi2HTML::THISDOC{'today'} = Texi2HTML::I18n::pretty_date($language); # like "20 September 1993"; } else { $Texi2HTML::THISDOC{'today'} = 'a sunny day'; } $Texi2HTML::THISDOC{'today'} = $Texi2HTML::Config::DATE if (defined($Texi2HTML::Config::DATE)); $::things_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; $::pre_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; $::texi_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; } sub warn_unknown_language($;$) { my $lang = shift; my $line_nr = shift; my $lang_code = $lang; my $region_code; if ($lang =~ /^([a-z]+)_([A-Z]+)/) { $lang_code = $1; $region_code = $2; } if (! $Texi2HTML::Config::language_codes{$lang_code}) { msg_warn(sprintf(__("%s is not a valid language code"), $lang_code), $line_nr); } if (defined($region_code) and ! $Texi2HTML::Config::region_codes{$region_code}) { msg_warn(sprintf(__("%s is not a valid region code"), $region_code), $line_nr); } } # Called on --document-language, at the beginning of each pass and # when a @documentlanguage appears sub set_document_language ($$;$) { my $lang = shift; my $silent = shift; my $line_nr = shift; my @langs = ($lang); # my $lang_code = $lang; # my $region_code; my $main_lang; if ($lang =~ /^([a-z]+)_([A-Z]+)/) { $main_lang = $1; # $region_code = $2; # $lang_code = $main_lang; push @langs, $main_lang; } # if (!$silent) # { # if (! $Texi2HTML::Config::language_codes{$lang_code}) # { # i18n # msg_warn("$lang_code is not a valid language code.", $line_nr); # } # if (defined($region_code) and ! $Texi2HTML::Config::region_codes{$region_code}) # { # i18n # msg_warn("$region_code is not a valid region code.", $line_nr); # } # } # Always succeed if using a gettext-like environment if (!$Texi2HTML::Config::I18N_PERL_HASH) { set_date($lang); return 1; } my @files = locate_init_file("$i18n_dir/$lang.thl", 1); if (! scalar(@files) and defined($main_lang)) { @files = locate_init_file("$i18n_dir/$main_lang.thl", 1); } foreach my $file (@files) { Texi2HTML::Config::load($file); } foreach my $language (@langs) { if (Texi2HTML::I18n::set_language($language)) { print STDERR "# using '$language' as document language\n" if ($T2H_VERBOSE); # since it may be different from get_conf('documentlanguage'), # we record it. # Currently this is not used anywhere, not sure what the value # really corresponds with. $Texi2HTML::THISDOC{'current_language'} = $language; set_date($language); return 1; } } return 0; } # manage footnote style sub set_footnote_style($$;$) { my $value = shift; my $from_command_line = shift; my $line_nr = shift; my $command = 'footnotestyle'; if ($value eq 'end' or $value eq 'separate') { Texi2HTML::Config::set_conf($command, $value, !$from_command_line); } elsif ($from_command_line) { die sprintf(__("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"), $real_command_name, $value); # the T2H_FAILURE_TEXT is output by getOption, seems to catch die } else { line_error (sprintf(__("\@%s arg must be `separate' or `end', not `%s'"), $command, $value), $line_nr); } } # find the encoding alias. # with encoding support (USE_UNICODE), may return undef if no alias was found sub encoding_alias($;$$) { my $encoding = shift; my $line_nr = shift; my $context_string = shift; return undef if (!defined($encoding) or $encoding eq ''); if ($Texi2HTML::Config::USE_UNICODE) { my $result_encoding = Encode::resolve_alias($encoding); if (! $result_encoding) { msg_warn(sprintf(__("unrecognized encoding name `%s'"), $encoding), $line_nr, $context_string); return undef; } if (defined($Texi2HTML::Config::t2h_encoding_aliases{$result_encoding})) { $result_encoding = $Texi2HTML::Config::t2h_encoding_aliases{$result_encoding}; } print STDERR "# Using encoding $result_encoding\n" if ($T2H_VERBOSE); return $result_encoding; } else { if (exists($Texi2HTML::Config::t2h_encoding_aliases{$encoding})) { $encoding = $Texi2HTML::Config::t2h_encoding_aliases{$encoding}; document_warn (__("Document encoding is utf8, but there is no unicode support")) if ($encoding eq 'utf-8'); return $encoding; } msg_warn(sprintf(__("Encoding %s certainly poorly supported"), $encoding), $line_nr); return $encoding; } } # libintl converts between encodings but doesn't decode them into the # perl internal format. sub encode_i18n_string($$) { my $string = shift; my $encoding = shift; if ($encoding ne 'us-ascii' and $Texi2HTML::Config::USE_UNICODE and Encode::resolve_alias($encoding)) { return Encode::decode($encoding, $string); } return $string; } sub gdt($;$$) { my $message = shift; my $context = shift; my $state = shift; # FIXME this should be done only once, for @documentencoding my $encoding = lc(Texi2HTML::Config::get_conf('DOCUMENT_ENCODING')); if (defined($encoding) and $encoding ne '' and exists($Texi2HTML::Config::t2h_encoding_aliases{$encoding})) { $encoding = $Texi2HTML::Config::t2h_encoding_aliases{$encoding}; } $encoding = 'us-ascii' if (!defined($encoding) or $encoding eq ''); return &$I($message, $context, $state) if ($Texi2HTML::Config::I18N_PERL_HASH); # if set, use substitute_text instead of substitute_line my $allow_paragraph = $state->{'allow_paragraph'}; # if duplicate is passed, it means that we are in the text and so should # use the main state if (defined($state) and $state->{'duplicate'} and defined($Texi2HTML::THISDOC{'state'})) { $state = main::duplicate_formatting_state($Texi2HTML::THISDOC{'state'}); } my $result; # taken from libintl perl, copyright Guido. sub __expand. Overall not # enough code taken form Guido right now to be copyrightable. my $re = join '|', map { quotemeta $_ } keys %$context if (defined($context) and ref($context)); if (Texi2HTML::Config::get_conf('use_nls')) { my $saved_LANGUAGE = $ENV{'LANGUAGE'}; Locale::Messages::textdomain($strings_textdomain); Locale::Messages::bind_textdomain_codeset($strings_textdomain, $encoding) if ($encoding ne 'us-ascii'); Locale::Messages::bind_textdomain_filter($strings_textdomain, \&encode_i18n_string, $encoding); my $lang = Texi2HTML::Config::get_conf('documentlanguage'); my @langs = ($lang); if ($lang =~ /^([a-z]+)_([A-Z]+)/) { my $main_lang = $1; my $region_code = $2; push @langs, $main_lang; } my $locales = ''; foreach my $language (@langs) { $locales .= "$language.$encoding:"; #$locales .= "$language:"; # always try us-ascii, the charset should always be a subset of # all charset, and should resort to @-commands if needed for non # ascii characters if ($encoding ne 'us-ascii') { $locales .= "$language.us-ascii:"; } } $locales =~ s/:$//; #print STDERR "$locales\n"; Locale::Messages::nl_putenv("LANGUAGE=$locales"); if (!defined($context) or ref($context)) { $result = Locale::Messages::gettext($message); } else { $result = Locale::Messages::pgettext($context, $message); } Locale::Messages::textdomain($messages_textdomain); # old perl complains 'Use of uninitialized value in scalar assignment' if (!defined($saved_LANGUAGE)) { delete ($ENV{'LANGUAGE'}); } else { $ENV{'LANGUAGE'} = $saved_LANGUAGE; } } # now perform the argument substitutions if ($state->{'keep_texi'}) { # next line taken from libintl perl, copyright Guido. sub __expand $result =~ s/\{($re)\}/defined $context->{$1} ? $context->{$1} : "{$1}"/ge if (defined($re)); return $result; } if (defined($re)) { # next line taken from libintl perl, copyright Guido. sub __expand $result =~ s/\{($re)\}/\@internal_translation_open_brace\{\}$1\@internal_translation_close_brace\{\}/g; foreach my $map (\%Texi2HTML::Config::things_map, \%Texi2HTML::Config::pre_map, \%Texi2HTML::Config::texi_map, \%Texi2HTML::Config::simple_format_texi_map) { $map->{'internal_translation_open_brace'} = '{'; $map->{'internal_translation_close_brace'} = '}'; } } if ($allow_paragraph) { delete $state->{'allow_paragraph'}; $result = substitute_text ($state, undef, __("translation"), ($result)); } else { $result = substitute_line ($result, __("translation"), $state); } if (defined($re)) { $result =~ s/\{($re)\}/defined $context->{$1} ? $context->{$1} : "{$1}"/ge; foreach my $map (\%Texi2HTML::Config::things_map, \%Texi2HTML::Config::pre_map, \%Texi2HTML::Config::texi_map, \%Texi2HTML::Config::simple_format_texi_map) { delete $map->{'internal_translation_open_brace'}; delete $map->{'internal_translation_close_brace'}; } } return $result; } my %nodes; # nodes hash. The key is the texi node name my %cross_reference_nodes; # normalized node names arrays # # %value hold texinfo variables, see also -D, -U, @set and @clear. # we predefine html (the output format) and texi2html (the translator) # it is initialized with %value_initial at the beginning of the # document parsing and filled and emptied as @set and @clear are # encountered my %value_initial = ( 'html' => 1, 'texi2html' => $THISVERSION, ); # # _foo: internal variables to track @foo # foreach my $key ('_author', '_title', '_subtitle', '_shorttitlepage', '_settitle', '_titlefont') { $value_initial{$key} = ''; # prevent -w warnings } sub unicode_to_protected($) { my $text = shift; my $result = ''; while ($text ne '') { if ($text =~ s/^([A-Za-z0-9]+)//o) { $result .= $1; } elsif ($text =~ s/^ //o) { $result .= '-'; } elsif ($text =~ s/^(.)//o) { my $char = $1; if (exists($Texi2HTML::Config::ascii_character_map{$char})) { $result .= '_' . lc($Texi2HTML::Config::ascii_character_map{$char}); } else { if (ord($char) <= hex(0xFFFF)) { $result .= '_' . lc(sprintf("%04x",ord($char))); } else { $result .= '__' . lc(sprintf("%06x",ord($char))); } } } else { print STDERR "Bug: unknown character in a cross ref (likely in infinite loop)\n"; print STDERR "Text: !!$text!!\n"; sleep 1; } } return $result; } sub unicode_to_transliterate($) { my $text = shift; if (chomp($text)) { print STDERR "Strange: end of line to transliterate: $text\n"; } my $result = ''; while ($text ne '') { if ($text =~ s/^([A-Za-z0-9 ]+)//o) { $result .= $1; } elsif ($text =~ s/^(.)//o) { my $char = $1; if (exists($Texi2HTML::Config::ascii_character_map{$char})) { $result .= $char; } elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($char)))})) { $result .= $Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($char)))}; } elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::unicode_diacritical{uc(sprintf("%04x",ord($char)))})) { $result .= ''; } # in this case, we want to avoid calling unidecode, as we are sure # that there is no useful transliteration of the unicode character # instead we want to keep it as is. # This is the case, for example, for @exclamdown, is corresponds # with x00a1, but unidecode transliterates it to a !, we want # to avoid that and keep x00a1. elsif (ord($char) <= hex(0xFFFF) and exists($Texi2HTML::Config::no_transliterate_map{uc(sprintf("%04x",ord($char)))})) { $result .= $char; } else { if ($Texi2HTML::Config::USE_UNIDECODE) { $result .= unidecode($char); } else { $result .= $char; } } } else { print STDERR "Bug: unknown character in cross ref transliteration (likely in infinite loop)\n"; print STDERR "Text: !!$text!!\n"; sleep 1; } } return $result; } # used both for command line and @-command argument checking sub set_paragraphindent($$;$$) { my $value = shift; my $from_command_line = shift; my $line_nr = shift; my $pass = shift; my $command = 'paragraphindent'; if ($value =~ /^([0-9]+)$/ or $value eq 'none' or $value eq 'asis') { Texi2HTML::Config::set_conf($command, $value, !$from_command_line); } elsif ($from_command_line) { die sprintf(__("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"), $real_command_name, $value); } elsif ($pass == 1) { line_error (sprintf(__("\@paragraphindent arg must be numeric/`none'/`asis', not `%s'"), $value), $line_nr); } } # T2H_OPTIONS is a hash whose keys are the (long) names of valid # command-line options and whose values are a hash with the following keys: # type ==> one of !|=i|:i|=s|:s (see Getopt::Long for more info) # linkage ==> ref to scalar, array, or subroutine (see Getopt::Long for more info) # verbose ==> short description of option (displayed by -h) # noHelp ==> if 1 -> for "not so important options": only print description on -h 1 # 2 -> for obsolete options: only print description on -h 2 my $T2H_OPTIONS; $T2H_OPTIONS -> {'debug'} = { type => '=i', linkage => \$Texi2HTML::Config::DEBUG, verbose => 'output HTML with debuging information', }; $T2H_OPTIONS -> {'doctype'} = { type => '=s', linkage => sub {Texi2HTML::Config::set_conf('doctype', $_[1]);}, verbose => 'document type which is output in header of HTML files', noHelp => 1 }; $T2H_OPTIONS -> {'frameset-doctype'} = { type => '=s', linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE, verbose => 'document type for HTML frameset documents', noHelp => 1 }; $T2H_OPTIONS -> {'test'} = { type => '!', linkage => \$Texi2HTML::Config::TEST, verbose => 'use predefined information to avoid differences with reference files', noHelp => 1 }; $T2H_OPTIONS -> {'dump-texi'} = { type => '!', linkage => \$Texi2HTML::Config::DUMP_TEXI, verbose => 'dump the output of first pass into a file with extension passfirst and exit', noHelp => 1 }; $T2H_OPTIONS -> {'macro-expand|E'} = { type => '=s', linkage => \$Texi2HTML::Config::MACRO_EXPAND, verbose => 'output macro expanded source in ', }; $T2H_OPTIONS -> {'ifhtml'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('html', $_[1]); }, verbose => "expand ifhtml and html sections", }; $T2H_OPTIONS -> {'ifinfo'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('info', $_[1]); }, verbose => "expand ifinfo", }; $T2H_OPTIONS -> {'ifxml'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('xml', $_[1]); }, verbose => "expand ifxml and xml sections", }; $T2H_OPTIONS -> {'ifdocbook'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('docbook', $_[1]); }, verbose => "expand ifdocbook and docbook sections", }; $T2H_OPTIONS -> {'iftex'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('tex', $_[1]); }, verbose => "expand iftex and tex sections", }; $T2H_OPTIONS -> {'ifplaintext'} = { type => '!', linkage => sub { Texi2HTML::Config::set_expansion('plaintext', $_[1]); }, verbose => "expand ifplaintext sections", }; $T2H_OPTIONS -> {'iso'} = { type => 'iso', linkage => sub {Texi2HTML::Config::t2h_default_set_iso_symbols ($_[1]);}, verbose => 'if set, entities are used for special symbols (like copyright, etc...) and quotes', noHelp => 1, }; $T2H_OPTIONS -> {'I'} = { type => '=s', linkage => \@Texi2HTML::Config::INCLUDE_DIRS, verbose => 'append $s to the @include search path', }; $T2H_OPTIONS -> {'conf-dir'} = { type => '=s', linkage => \@Texi2HTML::Config::CONF_DIRS, verbose => 'append $s to the init file directories', }; $T2H_OPTIONS -> {'P'} = { type => '=s', linkage => sub {unshift (@Texi2HTML::Config::PREPEND_DIRS, $_[1]);}, verbose => 'prepend $s to the @include search path', }; $T2H_OPTIONS -> {'top-file'} = { type => '=s', linkage => \$Texi2HTML::Config::TOP_FILE, verbose => 'use $s as top file, instead of .html', }; $T2H_OPTIONS -> {'toc-file'} = { type => '=s', linkage => \$Texi2HTML::Config::TOC_FILE, verbose => 'use $s as ToC file, instead of _toc.html', }; $T2H_OPTIONS -> {'frames'} = { type => '!', linkage => \$Texi2HTML::Config::FRAMES, verbose => 'output files which use HTML 4.0 frames (experimental)', noHelp => 1, }; $T2H_OPTIONS -> {'menu'} = { type => '!', linkage => \$Texi2HTML::Config::SHOW_MENU, verbose => 'output Texinfo menus', }; $T2H_OPTIONS -> {'number-sections'} = { type => '!', linkage => \$Texi2HTML::Config::NUMBER_SECTIONS, verbose => 'output chapter and sectioning numbers.', }; $T2H_OPTIONS -> {'number-footnotes'} = { type => '!', linkage => \$Texi2HTML::Config::NUMBER_FOOTNOTES, verbose => 'output footnote numbers.', }; $T2H_OPTIONS -> {'use-nodes'} = { type => '!', linkage => \$Texi2HTML::Config::USE_NODES, verbose => 'use nodes for sectioning', }; $T2H_OPTIONS -> {'node-files'} = { type => '!', linkage => \$Texi2HTML::Config::NODE_FILES, verbose => 'produce one file per node for cross references' }; $T2H_OPTIONS -> {'footnote-style|s'} = { type => '=s', linkage => sub {set_footnote_style ($_[1], 1);}, verbose => 'output footnotes separate|end', }; $T2H_OPTIONS -> {'toc-links'} = { type => '!', linkage => \$Texi2HTML::Config::TOC_LINKS, verbose => 'create links from headings to toc entries' }; $T2H_OPTIONS -> {'split'} = { type => '=s', linkage => \$Texi2HTML::Config::SPLIT, verbose => 'split document on section|chapter|node else no splitting', }; $T2H_OPTIONS -> {'no-split'} = { type => '!', linkage => sub {$Texi2HTML::Config::SPLIT = ''; $Texi2HTML::Config::SPLIT_SIZE = undef;}, verbose => 'no splitting of document', noHelp => 1, }; $T2H_OPTIONS -> {'headers'} = { type => '!', linkage => sub { Texi2HTML::Config::set_conf('headers', $_[1]); Texi2HTML::Config::t2h_default_load_format('plaintext', 1) if (!$_[1] and defined($Texi2HTML::Config::OUTPUT_FORMAT) and $Texi2HTML::Config::OUTPUT_FORMAT eq 'info'); }, verbose => 'output navigation headers for each section', }; $T2H_OPTIONS -> {'subdir'} = { type => '=s', linkage => \$Texi2HTML::Config::SUBDIR, verbose => 'put files in directory $s, not $cwd', noHelp => 1, }; $T2H_OPTIONS -> {'short-ext'} = { type => '!', linkage => \$Texi2HTML::Config::SHORTEXTN, verbose => 'use "htm" extension for output HTML files', }; $T2H_OPTIONS -> {'prefix'} = { type => '=s', linkage => \$Texi2HTML::Config::PREFIX, verbose => 'use as prefix for output files, instead of ', }; $T2H_OPTIONS -> {'output|out|o'} = { type => '=s', linkage => \$Texi2HTML::Config::OUT, verbose => 'output goes to $s (directory if split)', }; $T2H_OPTIONS -> {'no-validate|no-pointer-validate'} = { type => '', linkage => sub {Texi2HTML::Config::set_conf('novalidate',$_[1])}, verbose => 'suppress node cross-reference validation', }; $T2H_OPTIONS -> {'no-warn'} = { type => '', linkage => \$Texi2HTML::Config::NO_WARN, verbose => 'suppress warnings (but not errors).' }; $T2H_OPTIONS -> {'short-ref'} = { type => '!', linkage => \$Texi2HTML::Config::SHORT_REF, verbose => 'if set, references are without section numbers', }; $T2H_OPTIONS -> {'idx-sum'} = { type => '!', linkage => \$Texi2HTML::Config::IDX_SUMMARY, verbose => 'if set, also output index summary', noHelp => 1, }; $T2H_OPTIONS -> {'def-table'} = { type => '!', linkage => \$Texi2HTML::Config::DEF_TABLE, verbose => 'if set, \@def.. are converted using tables.', noHelp => 1, }; $T2H_OPTIONS -> {'verbose'} = 0; $T2H_OPTIONS -> {'verbose|v'} = { type => '!', linkage=> \$Texi2HTML::Config::VERBOSE, verbose => 'print progress info to stdout', }; $T2H_OPTIONS -> {'document-language'} = { type => '=s', linkage => sub { warn_unknown_language ($_[1]); Texi2HTML::Config::set_conf('documentlanguage', $_[1]) }, verbose => 'use $s as document language', }; $T2H_OPTIONS -> {'ignore-preamble-text'} = { type => '!', linkage => \$Texi2HTML::Config::IGNORE_PREAMBLE_TEXT, verbose => 'if set, ignore the text before @node and sectioning commands', noHelp => 1, }; $T2H_OPTIONS -> {'html-xref-prefix'} = { type => '=s', linkage => \$Texi2HTML::Config::EXTERNAL_DIR, verbose => '$s is the base dir for external manual references', noHelp => 1, }; $T2H_OPTIONS -> {'l2h'} = { type => '!', linkage => \$Texi2HTML::Config::L2H, verbose => 'if set, uses latex2html for @math and @tex', }; $T2H_OPTIONS -> {'l2h-l2h'} = { type => '=s', linkage => \$Texi2HTML::Config::L2H_L2H, verbose => 'program to use for latex2html translation', noHelp => 1, }; $T2H_OPTIONS -> {'l2h-skip'} = { type => '!', linkage => \$Texi2HTML::Config::L2H_SKIP, verbose => 'if set, tries to reuse previously latex2html output', noHelp => 1, }; $T2H_OPTIONS -> {'l2h-tmp'} = { type => '=s', linkage => \$Texi2HTML::Config::L2H_TMP, verbose => 'if set, uses $s as temporary latex2html directory', noHelp => 1, }; $T2H_OPTIONS -> {'l2h-file'} = { type => '=s', linkage => \$Texi2HTML::Config::L2H_FILE, verbose => 'if set, uses $s as latex2html init file', noHelp => 1, }; $T2H_OPTIONS -> {'l2h-clean'} = { type => '!', linkage => \$Texi2HTML::Config::L2H_CLEAN, verbose => 'if set, do not keep intermediate latex2html files for later reuse', noHelp => 1, }; $T2H_OPTIONS -> {'D'} = { type => '=s', linkage => sub {$value_initial{$_[1]} = 1;}, verbose => 'equivalent to Texinfo "@set $s 1"', noHelp => 1, }; $T2H_OPTIONS -> {'U'} = { type => '=s', linkage => sub {delete $value_initial{$_[1]};}, verbose => 'equivalent to Texinfo "@clear $s"', noHelp => 1, }; $T2H_OPTIONS -> {'init-file'} = { type => '=s', linkage => \&load_init_file, verbose => 'load init file $s' }; $T2H_OPTIONS -> {'css-include'} = { type => '=s', linkage => \@Texi2HTML::Config::CSS_FILES, verbose => 'use css file $s' }; $T2H_OPTIONS -> {'css-ref'} = { type => '=s', linkage => \@Texi2HTML::Config::CSS_REFS, verbose => 'generate reference to the CSS URL $s' }; $T2H_OPTIONS -> {'transliterate-file-names'} = { type => '!', linkage=> \$Texi2HTML::Config::TRANSLITERATE_FILE_NAMES, verbose => 'produce file names in ASCII transliteration', }; $T2H_OPTIONS -> {'error-limit|e'} = { type => '=i', linkage => \$Texi2HTML::Config::ERROR_LIMIT, verbose => 'quit after NUM errors (default 1000).', }; $T2H_OPTIONS -> {'split-size'} = { type => '=s', linkage => \$Texi2HTML::Config::SPLIT_SIZE, verbose => 'split Info files at size s (default 300000).', }; $T2H_OPTIONS -> {'paragraph-indent|p'} = { type => '=s', linkage => sub {set_paragraphindent($_[1], 1);}, 'verbose' => "indent Info paragraphs by VAL spaces (default 3). If VAL is `none', do not indent; if VAL is `asis', preserve existing indentation.", }; $T2H_OPTIONS -> {'fill-column|f'} = { type => '=i', linkage => sub {Texi2HTML::Config::set_conf('fillcolumn',$_[1]);}, 'verbose' => "break Info lines at NUM characters (default 72).", }; $T2H_OPTIONS -> {'enable-encoding'} = { type => '', linkage => \$Texi2HTML::Config::ENABLE_ENCODING, verbose => 'override --disable-encoding (default in Info).', }; $T2H_OPTIONS -> {'disable-encoding'} = { type => '', linkage => sub {$Texi2HTML::Config::ENABLE_ENCODING = 0}, verbose => 'do not output accented and special characters in Info output based on @documentencoding.', }; $T2H_OPTIONS -> {'internal-links'} = { type => '=s', linkage => \$Texi2HTML::Config::INTERNAL_LINKS, verbose => 'produce list of internal links in FILE.' }; $T2H_OPTIONS -> {'force|F'} = { type => '!', linkage => \$Texi2HTML::Config::FORCE, verbose => 'preserve output even if errors.' }; $T2H_OPTIONS -> {'monolithic'} = { type => '!', linkage => \$Texi2HTML::Config::MONOLITHIC, verbose => 'output only one file including ToC, About...', noHelp => 1 }; $T2H_OPTIONS -> {'commands-in-node-names'} = { type => '!', verbose => 'Always set', noHelp => 1 }; $T2H_OPTIONS -> {'output-indent'} = { type => '=i', verbose => 'This option used to indent XML, it is ignored' }; $T2H_OPTIONS -> {'program'} = { type => '=s', linkage => sub {set_config_init_dirs_output($_[1]);}, 'verbose' => 'Call as $s, setting corresponding defaults' }; #$T2H_OPTIONS -> {'command'} = #{ # type => '=s', # linkage => \@Texi2HTML::Config::COMMANDS, # verbose => 'insert CMD in copy of input file' #}; foreach my $output_format (keys(%Texi2HTML::Config::output_format_names)) { next if (defined($Texi2HTML::Config::DEFAULT_OUTPUT_FORMAT) and $output_format eq $Texi2HTML::Config::DEFAULT_OUTPUT_FORMAT); $T2H_OPTIONS -> {$output_format} = { type => '', linkage => sub {Texi2HTML::Config::t2h_default_load_format($_[0], 1);}, verbose => "output $Texi2HTML::Config::output_format_names{$output_format} rather than $Texi2HTML::Config::output_format_names{$Texi2HTML::Config::DEFAULT_OUTPUT_FORMAT}.", } } $T2H_OPTIONS -> {$Texi2HTML::Config::DEFAULT_OUTPUT_FORMAT} = { type => '', linkage => sub {Texi2HTML::Config::t2h_default_load_format($_[0], 1);}, verbose => "output default format.", noHelp => 2 }; ## ## obsolete cmd line options ## my $T2H_OBSOLETE_OPTIONS; # actually a noop, since it is not used anywhere $T2H_OBSOLETE_OPTIONS -> {'invisible'} = { type => '=s', linkage => \$Texi2HTML::Config::INVISIBLE_MARK, verbose => 'use text in invisble anchor', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {'expand'} = { type => '=s', linkage => sub {Texi2HTML::Config::set_expansion($_[1], 1);}, verbose => 'Expand section of texinfo source', noHelp => 1, }; $T2H_OBSOLETE_OPTIONS -> {'no-expand'} = { type => '=s', linkage => sub {Texi2HTML::Config::set_expansion ($_[1], 0);}, verbose => 'Don\'t expand the given section of texinfo source', }; $T2H_OBSOLETE_OPTIONS -> {'noexpand'} = { type => '=s', linkage => $T2H_OBSOLETE_OPTIONS->{'no-expand'}->{'linkage'}, verbose => $T2H_OBSOLETE_OPTIONS->{'no-expand'}->{'verbose'}, noHelp => 1, }; $T2H_OBSOLETE_OPTIONS -> {'out-file'} = { type => '=s', linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, verbose => 'if set, all HTML output goes into file $s, obsoleted by "-output" with different semantics', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {'lang'} = { type => '=s', linkage => sub {Texi2HTML::Config::set_conf('documentlanguage', $_[1])}, verbose => 'obsolete, use "--document-language" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {'separated-footnotes'} = { type => '!', linkage => sub {my $style = 'separate'; $style = 'end' if !$_[1]; set_footnote_style ($style, 1);}, verbose => 'obsolete, use "--footnote-style" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {'Verbose'} = { type => '!', linkage=> \$Texi2HTML::Config::VERBOSE, verbose => 'obsolete, use "--verbose" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {init_file} = { type => '=s', linkage => \&load_init_file, verbose => 'obsolete, use "-init-file" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {l2h_clean} = { type => '!', linkage => \$Texi2HTML::Config::L2H_CLEAN, verbose => 'obsolete, use "-l2h-clean" instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {l2h_l2h} = { type => '=s', linkage => \$Texi2HTML::Config::L2H_L2H, verbose => 'obsolete, use "-l2h-l2h" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {l2h_skip} = { type => '!', linkage => \$Texi2HTML::Config::L2H_SKIP, verbose => 'obsolete, use "-l2h-skip" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {l2h_tmp} = { type => '=s', linkage => \$Texi2HTML::Config::L2H_TMP, verbose => 'obsolete, use "-l2h-tmp" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {out_file} = { type => '=s', linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, verbose => 'obsolete, use "-out-file" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {short_ref} = { type => '!', linkage => \$Texi2HTML::Config::SHORT_REF, verbose => 'obsolete, use "-short-ref" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {idx_sum} = { type => '!', linkage => \$Texi2HTML::Config::IDX_SUMMARY, verbose => 'obsolete, use "-idx-sum" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {def_table} = { type => '!', linkage => \$Texi2HTML::Config::DEF_TABLE, verbose => 'obsolete, use "-def-table" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {short_ext} = { type => '!', linkage => \$Texi2HTML::Config::SHORTEXTN, verbose => 'obsolete, use "-short-ext" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {sec_nav} = { type => '!', linkage => sub {Texi2HTML::Config::set_conf('headers', $_[1]);}, verbose => 'obsolete, use "-headers" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {'sec-nav'} = { type => '!', linkage => sub {Texi2HTML::Config::set_conf('headers', $_[1]);}, verbose => 'obsolete, use "--header" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {top_file} = { type => '=s', linkage => \$Texi2HTML::Config::TOP_FILE, verbose => 'obsolete, use "-top-file" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {toc_file} = { type => '=s', linkage => \$Texi2HTML::Config::TOC_FILE, verbose => 'obsolete, use "-toc-file" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {glossary} = { type => '!', linkage => \$Texi2HTML::Config::USE_GLOSSARY, verbose => "this does nothing", noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {check} = { type => '!', linkage => sub {exit 0;}, verbose => "exit without doing anything", noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {dump_texi} = { type => '!', linkage => \$Texi2HTML::Config::DUMP_TEXI, verbose => 'obsolete, use "-dump-texi" instead', noHelp => 1 }; $T2H_OBSOLETE_OPTIONS -> {frameset_doctype} = { type => '=s', linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE, verbose => 'obsolete, use "-frameset-doctype" instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} = { type => '!', linkage => sub {Texi2HTML::Config::set_conf('headers', 0);}, verbose => 'obsolete, use -nosec_nav', noHelp => 2, }; my $use_acc; # not used $T2H_OBSOLETE_OPTIONS -> {use_acc} = { type => '!', linkage => \$use_acc, verbose => 'obsolete, set to true unconditionnaly', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {expandinfo} = { type => '!', linkage => sub {push @Texi2HTML::Config::EXPAND, 'info';}, verbose => 'obsolete, use "--ifinfo" instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {expandtex} = { type => '!', linkage => sub {push @Texi2HTML::Config::EXPAND, 'tex';}, verbose => 'obsolete, use "--iftex" instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {split_node} = { type => '!', linkage => sub{$Texi2HTML::Config::SPLIT = 'section';}, verbose => 'obsolete, use "-split section" instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {split_chapter} = { type => '!', linkage => sub{$Texi2HTML::Config::SPLIT = 'chapter';}, verbose => 'obsolete, use "-split chapter" instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {no_verbose} = { type => '!', linkage => sub {$Texi2HTML::Config::VERBOSE = 0;}, verbose => 'obsolete, use -noverbose instead', noHelp => 2, }; $T2H_OBSOLETE_OPTIONS -> {output_file} = { type => '=s', linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, verbose => 'obsolete, use --out-file instead', noHelp => 2 }; $T2H_OBSOLETE_OPTIONS -> {section_navigation} = { type => '!', linkage => sub {Texi2HTML::Config::set_conf('headers', $_[1]);}, verbose => 'obsolete, use --sec-nav instead', noHelp => 2, }; # read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc # (this is obsolete). Obsoleted in 1.68 (March 20 2004). my @rc_files = (); push @rc_files, "$sysconfdir/texi2htmlrc" if defined($sysconfdir); push @rc_files, "$ENV{'HOME'}/.texi2htmlrc" if (defined($ENV{'HOME'})); foreach my $i (@rc_files) { if (-e $i and -r $i) { print STDERR "# reading initialization file from $i\n" if ($T2H_VERBOSE); print STDERR "Reading config from $i is obsolete, use texi2html/$conf_file_name instead\n"; Texi2HTML::Config::load($i); } } # read initialization files foreach my $file (locate_init_file($conf_file_name, 1)) { print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE); Texi2HTML::Config::load($file); } #+++############################################################################ # # # parse command-line options # # #---############################################################################ # options known by makeinfo (+version, help and if*) my @makeinfo_options = ('error-limit', 'document-language', 'force', 'help', 'no-validate', 'no-warn', 'verbose', 'docbook', 'html', 'xml', 'plaintext', 'macro-expand', 'headers', 'no-split', 'number-sections', 'output', 'disable-encoding', 'enable-encoding', 'fill-column', 'footnote-style', 'paragraph-indent', 'split-size', 'css-include', 'css-ref', 'internal-links', 'transliterate-file-names', 'output-indent', 'number-footnotes', 'D', 'I', 'P', 'U'); # always used, even though they are not in makeinfo in C. # dump-texi', 'debug', 'test' are for debugging. # split is in makeinfo in C, as --no-split. # 'conf-dir', 'init-file' options have to be taken into account for proper # functionning. my @basic_options = ('dump-texi', 'debug', 'test', 'conf-dir', 'init-file', 'split', 'program'); # --command=CMD insert CMD in copy of input file my $makeinfo_help = sprintf(__("Usage: %s [OPTION]... TEXINFO-FILE...\n"), $real_command_name) ."\n". __("Translate Texinfo source documentation to various other formats, by default Info files suitable for reading online with Emacs or standalone GNU Info.\n") ."\n"; $makeinfo_help .= sprintf(__("General options: --error-limit=NUM quit after NUM errors (default %d). --document-language=STR locale to use in translating Texinfo keywords for the output document (default C). --force preserve output even if errors. --help display this help and exit. --no-validate suppress node cross-reference validation. --no-warn suppress warnings (but not errors). -v, --verbose explain what is being done. --version display version information and exit.\n"), $Texi2HTML::Config::ERROR_LIMIT) ."\n"; $makeinfo_help .= __("Output format selection (default is to produce Info): --docbook output Docbook XML rather than Info. --html output HTML rather than Info. --xml output Texinfo XML rather than Info. --plaintext output plain text rather than Info.\n") ."\n"; $makeinfo_help .= __("General output options: -E, --macro-expand=FILE output macro-expanded source to FILE, ignoring any \@setfilename. --no-headers suppress node separators, Node: lines, and menus from Info output (thus producing plain text) or from HTML (thus producing shorter output); also, write to standard output by default. --no-split suppress the splitting of Info or HTML output, generate only one output file. --number-sections output chapter and sectioning numbers. -o, --output=FILE output to FILE (or directory if split HTML).\n") ."\n"; $makeinfo_help .= sprintf(__("Options for Info and plain text: --disable-encoding do not output accented and special characters in Info output based on \@documentencoding. --enable-encoding override --disable-encoding (default). --fill-column=NUM break Info lines at NUM characters (default %d). --footnote-style=STYLE output footnotes in Info according to STYLE: `separate' to put them in their own node; `end' to put them at the end of the node, in which they are defined (this is the default). --paragraph-indent=VAL indent Info paragraphs by VAL spaces (default %d). If VAL is `none', do not indent; if VAL is `asis', preserve existing indentation. --split-size=NUM split Info files at size NUM (default %d).\n"), $Texi2HTML::Config::FILLCOLUMN, $Texi2HTML::Config::PARAGRAPHINDENT, $Texi2HTML::Config::SPLIT_SIZE) ."\n"; $makeinfo_help .= __("Options for HTML: --css-include=FILE include FILE in HTML