version 1.3, 2017/03/28 23:22:20 |
version 1.4, 2017/03/30 05:36:04 |
|
|
#! /usr/local/bin/perl -- |
#!/bin/sh |
# perl |
if [ ! `which perl` ]; then |
'di '; |
echo "Perl is not installed. Error: texi2html is aborted." |
'ig 00 '; |
exit 1 |
# texi2html: generated by addformats.sh from texi2html.temp and formats/html.init formats/info.init formats/docbook.init formats/xml.init formats/plaintext.init |
fi |
# 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 |
if [ -x /usr/bin/texi2html ]; then |
#+############################################################################## |
/usr/bin/texi2html $* ; |
# |
elif [ -x /usr/local/bin/texi2html ]; then |
# texi2html: Program to transform Texinfo documents to HTML |
/usr/local/bin/texi2html $* ; |
# |
|
# Copyright (C) 1999-2010 Patrice Dumas <pertusus@free.fr>, |
|
# Derek Price <derek@ximbiot.com>, |
|
# Adrian Aichner <adrian@xemacs.org>, |
|
# & 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$ |
|
|
|
# FIXME. Change for texinfo, and also simplify. |
|
|
|
# Homepage: |
|
my $T2H_HOMEPAGE = "http://www.nongnu.org/texi2html/"; |
|
|
|
# Authors (appears in comments): |
|
my $T2H_AUTHORS = <<EOT; |
|
texi2html was written by: |
|
Lionel Cons <Lionel.Cons\@cern.ch> (original author) |
|
Karl Berry <karl\@freefriends.org> |
|
Olaf Bachmann <obachman\@mathematik.uni-kl.de> |
|
and many others. |
|
Maintained by: Many creative people. |
|
Send bugs and suggestions to <texi2html-bug\@nongnu.org> |
|
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 |
else |
{ |
perl ./texi2html.perl $* ; |
$sysconfdir = "/usr/local/etc"; |
fi |
} |
|
|
|
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 = "<li>" . &$anchor ($element->{'stocid'}, "$dest_for_stoc#$dest_target_for_stoc",$text); |
|
push(@result, $stoc_entry. "</li>\n"); |
|
} |
|
if (@result) |
|
{ |
|
unshift @result, html_default_attribute_class('ul', $ul_class) .">\n"; |
|
push @result, "</ul>\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 = "</li>\n$ind</ul>"; |
|
$line .= "</li>" if ($level == $current_level); |
|
push(@result, "$line\n"); |
|
} |
|
} |
|
else |
|
{ |
|
push(@result, "</li>\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 = "<li>" . &$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, "</li>\n$ind</ul>\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 .= "</$style>" 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. "</$element>\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, '<b>' . &$protect_text($letter) . '</b>', '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 <your_init_file> |
|
# |
|
# $Id$ |
|
|
|
###################################################################### |
|
# 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 <document name>.passtexi, the result of the second pass is put in |
|
# <document name>.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, <basename of document>.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, <basename of document>_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 <index name> |
|
# <document name>_<index name>.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 <document name>_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 <td></td> |
|
$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 <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 |
|
# 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$ |
|
|
|
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</title> |
|
|
|
$description |
|
<meta name="keywords" content="$longtitle"> |
|
<meta name="resource-type" content="document"> |
|
<meta name="distribution" content="global"> |
|
<meta name="Generator" content="$Texi2HTML::THISDOC{program}">$date |
|
$encoding |
|
${links}$css_text |
|
$EXTRA_HEAD |
|
</head> |
|
|
|
<body $Texi2HTML::THISDOC{'BODYTEXT'}> |
|
$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 = " <font size=\"-1\"> |
|
$program_string |
|
</font> |
|
<br>"; |
|
} |
|
print $fh <<EOT; |
|
<p> |
|
$program_text |
|
$PRE_BODY_CLOSE |
|
</p> |
|
</body> |
|
</html> |
|
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; |
|
<table border="0" cellpadding="0" cellspacing="0"> |
|
<tr valign="top"> |
|
<td align="left"> |
|
EOT |
|
} |
|
$result .= &$print_navigation($buttons, $VERTICAL_HEAD_NAVIGATION); |
|
if ($VERTICAL_HEAD_NAVIGATION) |
|
{ |
|
$result .= <<EOT; |
|
</td> |
|
<td align="left"> |
|
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; |
|
</td> |
|
</tr> |
|
</table> |
|
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{<img src="$icon" border="0" alt="$alt" align="middle">}; |
|
} |
|
|
|
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 .= "<tr>" unless $vertical; |
|
} |
|
else |
|
{ |
|
$result .= html_default_attribute_class('div', 'header').">\n<p>\n"; |
|
} |
|
for my $button (@$buttons) |
|
{ |
|
if ($HEADER_IN_TABLE) |
|
{ |
|
$result .= qq{<tr valign="top" align="left">\n} if $vertical; |
|
$result .= qq{<td valign="middle" align="left">}; |
|
} |
|
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 .= "</td>\n"; |
|
$result .= "</tr>\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 .= "</tr>" unless $vertical; |
|
$result .= "</table>\n"; |
|
} |
|
else |
|
{ |
|
$result .= "</p>\n</div>\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" <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. |
|
|
|
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 <<EOT; |
|
$FRAMESET_DOCTYPE |
|
<html> |
|
<head><title>$Texi2HTML::THISDOC{'fulltitle'}</title></head> |
|
<frameset cols="140,*"> |
|
<frame name="toc" src="$toc_file"> |
|
<frame name="main" src="$main_file"> |
|
</frameset> |
|
</html> |
|
EOT |
|
} |
|
|
|
sub HTML_DEFAULT_print_toc_frame |
|
{ |
|
my $fh = shift; |
|
my $stoc_lines = shift; |
|
&$print_page_head($fh); |
|
print $fh <<EOT; |
|
<h2>Content</h2> |
|
EOT |
|
print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines; |
|
print $fh "</body></html>\n"; |
|
} |
|
|
|
###################################################################### |
|
# About page |
|
# |
|
|
|
sub HTML_DEFAULT_about_body |
|
{ |
|
return undef if (!$HEADER_IN_TABLE); |
|
my $about = "<p>\n"; |
|
if (ref($PRE_ABOUT) eq 'CODE') |
|
{ |
|
$about .= &$PRE_ABOUT(); |
|
} |
|
else |
|
{ |
|
$about .= $PRE_ABOUT; |
|
} |
|
$about .= <<EOT; |
|
</p> |
|
<p> |
|
EOT |
|
$about .= gdt(' The buttons in the navigation panels have the following meaning:') . "\n"; |
|
$about .= <<EOT; |
|
</p> |
|
<table border="1"> |
|
<tr> |
|
EOT |
|
$about .= ' <th> ' . gdt('Button') . " </th>\n" . |
|
' <th> ' . gdt('Name') . " </th>\n" . |
|
' <th> ' . gdt('Go to') . " </th>\n" . |
|
' <th> ' . gdt('From 1.2.3 go to') . "</th>\n" . " </tr>\n"; |
|
|
|
for my $button (@SECTION_BUTTONS) |
|
{ |
|
next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY'; |
|
$about .= " <tr>\n <td align=\"center\">"; |
|
$about .= |
|
($ICONS && $ACTIVE_ICONS{$button} ? |
|
&$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) : |
|
' [' . $NAVIGATION_TEXT{$button} . '] '); |
|
$about .= "</td>\n"; |
|
$about .= <<EOT; |
|
<td align="center">$BUTTONS_NAME{$button}</td> |
|
<td>$BUTTONS_GOTO{$button}</td> |
|
<td>$BUTTONS_EXAMPLE{$button}</td> |
|
</tr> |
|
EOT |
|
} |
|
|
|
$about .= <<EOT; |
|
</table> |
|
|
|
<p> |
|
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 <strong> Example </strong> assumes that the current position |
|
# is at <strong> Subsubsection One-Two-Three </strong> of a document of |
|
# the following structure: |
|
$about .= <<EOT; |
|
</p> |
|
|
|
<ul> |
|
EOT |
|
$about .= ' <li> 1. ' . gdt('Section One') . "\n" . |
|
" <ul>\n" . |
|
' <li>1.1 ' . gdt('Subsection One-One') . "\n"; |
|
$about .= <<EOT; |
|
<ul> |
|
<li>...</li> |
|
</ul> |
|
</li> |
|
EOT |
|
$about .= ' <li>1.2 ' . gdt('Subsection One-Two') . "\n" . |
|
" <ul>\n" . |
|
' <li>1.2.1 ' . gdt('Subsubsection One-Two-One') . "</li>\n" . |
|
' <li>1.2.2 ' . gdt('Subsubsection One-Two-Two') . "</li>\n" . |
|
' <li>1.2.3 ' . gdt('Subsubsection One-Two-Three') . " \n" |
|
. |
|
' <strong><== ' . gdt('Current Position') . " </strong></li>\n" . |
|
' <li>1.2.4 ' . gdt('Subsubsection One-Two-Four') . "</li>\n" . |
|
" </ul>\n" . |
|
" </li>\n" . |
|
' <li>1.3 ' . gdt('Subsection One-Three') . "\n"; |
|
$about .= <<EOT; |
|
<ul> |
|
<li>...</li> |
|
</ul> |
|
</li> |
|
EOT |
|
$about .= ' <li>1.4 ' . gdt('Subsection One-Four') . "</li>\n"; |
|
$about .= <<EOT; |
|
</ul> |
|
</li> |
|
</ul> |
|
$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 = "<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 $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 <<EOT; |
|
my $result = <<EOT; |
|
$doctype |
|
<html> |
|
<!-- Created on $Texi2HTML::THISDOC{'today'} by $Texi2HTML::THISDOC{'program'} --> |
|
<!-- |
|
$Texi2HTML::THISDOC{'program_authors'} |
|
--> |
|
<head> |
|
<title>$longtitle</title> |
|
|
|
<meta name="description" content="$description"> |
|
<meta name="keywords" content="$longtitle"> |
|
<meta name="resource-type" content="document"> |
|
<meta name="distribution" content="global"> |
|
<meta name="Generator" content="$Texi2HTML::THISDOC{program}"> |
|
$encoding |
|
$css_text |
|
<meta http-equiv="Refresh" content="2; url=$Texi2HTML::HREF{'This'}"> |
|
$EXTRA_HEAD |
|
</head> |
|
|
|
<body $Texi2HTML::THISDOC{'BODYTEXT'}> |
|
$AFTER_BODY_OPEN |
|
<p>$string</p> |
|
</body> |
|
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 "<em>$text</em>"; |
|
} |
|
|
|
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 . '</div>' . $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 '<dt>' . &$anchor('', $href, $float_style) . '</dt><dd>' . $caption |
|
. '</dd>' . "\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 . "</dl>\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</a>"; |
|
} |
|
|
|
# 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 '<dd>' . $text . '</dd>';# unless $only_inter_item_commands; |
|
#return $text; # invalid without dd in ul |
|
} |
|
else |
|
{ |
|
return '<tr><td colspan="2">' . $text . '</td></tr>'; |
|
} |
|
} |
|
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 "<dl>\n" . $text . "</dl>\n"; |
|
} |
|
else |
|
{ |
|
return "<table width=\"100%\">\n" . $text . "</table>\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 = '<tr><td>'; |
|
$end_row = '</td></tr>'; |
|
} |
|
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}</table>\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 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 "<tr><td align=\"left\" valign=\"top\">$symbol$entry$MENU_ENTRY_COLON</td><td> </td>"; |
|
} |
|
|
|
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."<br>" if ($in_commands); |
|
if ($AVOID_MENU_REDUNDANCY) |
|
{ |
|
$text = '' if (html_simplify_text($element_text) eq html_simplify_text($text)); |
|
} |
|
return "<td align=\"left\" valign=\"top\">$text</td></tr>\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 .= '</tt>'; |
|
# $formatted_command = '<tt>' . $formatted_command; |
|
$text = '<tt>' . $text . '</tt>'; |
|
} |
|
$text .= "\n" . $index_label if (defined($index_label)); |
|
# return '<dt>' . $formatted_command . $text . '</dt>' . "\n"; |
|
return '<dt>' . $text . '</dt>' . "\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 '<dd>' . $text . '</dd>' . "\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 '<thead><tr>' . $text . '</tr></thead>' . "\n"; |
|
} |
|
return '<tr>' . $text . '</tr>' . "\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 <strong> is put before the space. |
|
$text =~ s/^\s*//; |
|
$text =~ s/\s*$//; |
|
|
|
if ($row_macro eq 'headitem') |
|
{ |
|
return "<th${fractions}>" . $text . '</th>'; |
|
} |
|
return "<td${fractions}>" . $text . '</td>'; |
|
} |
|
|
|
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 '<li>' . $prepend . $text . '</li>'; |
|
} |
|
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 "<ul>\n" . $text . "</ul>\n" if (($command eq 'bullet') or (($command eq '') and ($prepended eq ''))); |
|
return html_default_attribute_class('ul',$NO_BULLET_LIST_CLASS).">\n" . $text . "</ul>\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 = '<p>'; |
|
if ($align) |
|
{ |
|
$open = "<p align=\"$paragraph_style{$align}\">"; |
|
} |
|
return $open.$text.'</p>'; |
|
} |
|
|
|
# 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."</pre>"; |
|
} |
|
|
|
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</h$level>"; |
|
# 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 '<strong>'.$text.'</strong>'."\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) . '</pre>'; |
|
} |
|
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, '<h3>' . |
|
&$anchor($footnote_id, $document_file . "#$place_id", |
|
"($number_in_doc)") |
|
. "</h3>\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, "</div>\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 "<img src=\"$file\" alt=\"$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 = '<em>' . $arguments . '</em>'; |
|
} |
|
my $type_name = ''; |
|
$type_name = " <em>$type</em>" if ($type ne ''); |
|
$type_name .= ' <strong>' . $name . '</strong>' if ($name ne ''); |
|
$type_name .= $arguments; |
|
if (! $DEF_TABLE) |
|
{ |
|
return '<dt>'. $index_label. $category_prepared . ':' . $type_name . "</dt>\n"; |
|
} |
|
else |
|
{ |
|
return "<tr><td align=\"left\">" . $type_name . |
|
"</td><td align=\"right\">" . $category_prepared . $index_label . "</td></tr>\n"; |
|
} |
|
} |
|
|
|
# a cartouche |
|
sub html_default_cartouche($$) |
|
{ |
|
my $text = shift; |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
return html_default_attribute_class('table', 'cartouche')." border=\"1\"><tr><td>\n" . $text . "</td></tr></table>\n"; |
|
} |
|
return ''; |
|
} |
|
|
|
sub html_default_sp($$) |
|
{ |
|
my $number = shift; |
|
my $preformatted = shift; |
|
return "<br>\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 . "</$attribute>", 'explanation' => $explanation_text},{'duplicate'=>1}) |
|
} |
|
else |
|
{ |
|
return $opening . $acronym_text . "</$attribute>"; |
|
} |
|
} |
|
|
|
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 ."</blockquote>\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" . |
|
"<tr><td></td><th align=\"left\">" . gdt('Index Entry') . "</th><td> </td><th align=\"left\"> " . gdt('Section') . "</th></tr>\n" |
|
. "<tr><td colspan=\"4\"> $DEFAULT_RULE</td></tr>\n" . $text . |
|
"</table>\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 '<tr><th>' . &$anchor($id,'',&$normal_text($letter, 0, 0, 0, 0, 0, [])) . |
|
"</th><td></td><td></td></tr>\n" . $text . |
|
"<tr><td colspan=\"4\"> $DEFAULT_RULE</td></tr>\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 '<tr><td></td><td valign="top">' . &$anchor('', $text_href, $entry) |
|
. $INDEX_ENTRY_COLON . '</td><td> </td><td valign="top">' . &$anchor('', $element_href, $element_text) |
|
. "</td></tr>\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<br>\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 "<table><tr><th valign=\"top\">" . gdt('Jump to') .": </th><td>" . |
|
$nonalpha_text . $join . $alpha_text . "</td></tr></table>\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</$style>"; |
|
} |
|
$arg_text .= "<br>" 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 <pertusus@free.fr> |
|
# |
|
# 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 = <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 <pertusus@free.fr> |
|
# |
|
# 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 = '<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ |
|
<!ENTITY tex "TeX"> |
|
<!ENTITY latex "LaTeX"> |
|
]>'; |
|
@T2H_FORMAT_EXPAND = ('docbook'); |
|
@IMAGE_EXTENSIONS = ('eps', 'gif', 'jpg', 'jpeg', 'pdf', 'png', 'svg', 'txt'); |
|
$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'} = '<!-- /@w -->'; |
|
$style_map{'='}->{'function'} = \&docbook_macron; |
|
$style_map{'b'}->{'inline_attribute'} = 'emphasis role="bold"'; |
|
$style_map{'cite'}->{'inline_attribute'} = 'citetitle'; |
|
$style_map{'command'}->{'inline_attribute'} = 'command'; |
|
$style_map{'dfn'}->{'inline_attribute'} = 'firstterm'; |
|
$style_map{'emph'}->{'inline_attribute'} = 'emphasis'; |
|
$style_map{'env'}->{'inline_attribute'} = 'envar'; |
|
$style_map{'file'}->{'inline_attribute'} = 'filename'; |
|
$style_map{'i'}->{'inline_attribute'} = 'wordasword'; |
|
$style_map{'key'}->{'inline_attribute'} = 'keycap'; |
|
delete $style_map{'key'}->{'begin'}; |
|
delete $style_map{'key'}->{'end'}; |
|
$style_map{'option'}->{'inline_attribute'} = 'option'; |
|
$style_map{'t'}->{'inline_attribute'} = 'literal'; |
|
delete $style_map{'sansserif'}->{'inline_attribute'}; |
|
delete $style_map{'r'}->{'inline_attribute'}; |
|
$style_map{'indicateurl'}->{'inline_attribute'} = 'wordasword'; |
|
delete $style_map{'indicateurl'}->{'begin'}; |
|
delete $style_map{'indicateurl'}->{'end'}; |
|
$style_map{'var'}->{'inline_attribute'} = 'replaceable'; |
|
delete $style_map{'verb'}->{'inline_attribute'}; |
|
$style_map{'email'}->{'function'} = \&docbook_email; |
|
$style_map{'math'}->{'function'} = \&docbook_math; |
|
$style_map{'uref'}->{'function'} = \&docbook_uref; |
|
$style_map{'url'}->{'function'} = \&docbook_uref; |
|
$style_map{'titlefont'}->{'function'} = \&docbook_titlefont; |
|
#$style_map{'samp'}->{'function'} = \&docbook_samp; |
|
#delete $style_map{'samp'}->{'inline_attribute'}; |
|
$style_map{'samp'}->{'inline_attribute'} = 'literal'; |
|
$style_map{'samp'}->{'begin'} = '‘'; |
|
$style_map{'samp'}->{'end'} = '’'; |
|
|
|
$kept_footnote_function = $style_map{'footnote'}->{'function'}; |
|
$style_map{'footnote'}->{'function'} = \&docbook_footnote; |
|
|
|
foreach my $style (keys(%style_map)) |
|
{ |
|
delete ($style_map{$style}->{'quote'}); |
|
} |
|
|
|
#use Data::Dumper; |
|
%style_map_pre = (); |
|
t2h_default_copy_style_map (\%style_map, \%style_map_pre); |
|
|
|
$style_map_pre{'r'}->{'inline_attribute'} = 'lineannotation'; |
|
|
|
$colon_command_punctuation_characters{'.'} = '.'; |
|
$colon_command_punctuation_characters{':'} = ':'; |
|
$colon_command_punctuation_characters{'?'} = '?'; |
|
$colon_command_punctuation_characters{'!'} = '!'; |
|
|
|
$stop_paragraph_command{'titlefont'} = 0; |
|
|
|
# FIXME |
|
#$no_paragraph_commands{'anchor'} = 0; |
|
|
|
# FIXME |
|
delete $special_accents{'ringaccent'}; |
|
$special_accents{'ogonek'} = 'aeiuAEIU'; |
|
|
|
%simple_map = %default_simple_map; |
|
%simple_map_pre = %simple_map; |
|
|
|
# FIXME right? ł Ł |
|
$things_map{'l'} = '/l'; |
|
$things_map{'L'} = '/L'; |
|
$things_map{'TeX'} = '&tex;'; |
|
$things_map{'LaTeX'} = '&latex;'; |
|
$things_map{'enddots'} = '….'; |
|
$things_map{'minus'} = '−'; |
|
# FIXME ∗ |
|
$things_map{'point'} = '-!-'; |
|
# FIXME ≡ |
|
$things_map{'equiv'} = '=='; |
|
# FIXME no ‹ nor › |
|
$things_map{'guilsinglright'} = '>'; |
|
$things_map{'guilsinglleft'} = '<'; |
|
# The following is unneeded because normal_text is redefined. |
|
# FIXME it should certainly be better to leave those substitutions, |
|
# or even hardcodes them in normal_text. |
|
# t2h_remove_text_substitutions("'", 1, 0, 0, 1); |
|
# t2h_remove_text_substitutions('`', 1, 0, 0, 1); |
|
|
|
$things_map{'quotedblbase'} = '„'; |
|
$things_map{'quotesinglbase'} = '‚'; |
|
|
|
%pre_map = %things_map; |
|
|
|
#delete $inter_item_commands{'cindex'}; |
|
|
|
#$no_paragraph_commands{'cindex'} = 0; |
|
$no_paragraph_commands{'float'} = 0; |
|
|
|
%docbook_complex_format = ( |
|
'example' => 'screen', |
|
'smallexample' => 'screen', |
|
'display' => 'literallayout', |
|
'smalldisplay' => 'literallayout', |
|
'lisp' => 'programlisting', |
|
'smalllisp' => 'programlisting', |
|
'format' => 'abstract', |
|
'smallformat' => 'screen' |
|
); |
|
|
|
%docbook_sections = ( |
|
'top' => 'chapter', |
|
'part' => 'part', |
|
'chapter' => 'chapter', |
|
'unnumbered' => 'chapter', |
|
'centerchap' => 'chapter', |
|
'appendix' => 'appendix', |
|
'majorheading' => 'other', |
|
'chapheading' => 'other', |
|
'heading' => 'sect1', |
|
'subheading' => 'sect2', |
|
'subsubheading' => 'sect3', |
|
2 => 'sect1', |
|
3 => 'sect2', |
|
4 => 'sect3' |
|
); |
|
|
|
%def_format_docbook = ( |
|
'deffn' => [ ['function', 'name'] ], |
|
'defvr' => [ ['varname', 'name'] ], |
|
'deftypefn' => [ [ 'returnvalue', 'type' ], ['function', 'name'] ], |
|
'deftypeop' => [ ['returnvalue', 'type'], ['methodname', 'name'] ], |
|
'deftypevr' => [ ['returnvalue', 'type'], ['varname', 'name'] ], |
|
'defcv' => [ ['classname', 'class'], ['property', 'name'] ], |
|
'deftypecv' => [ ['returnvalue', 'type'], ['property', 'name'] ], |
|
'defop' => [ ['classname', 'class'], ['methodname', 'name'] ], |
|
'deftp' => [ ['structname', 'name'] ] |
|
); |
|
|
|
%def_argument_types_docbook = ( |
|
'param' => 'replaceable', |
|
'paramtype' => 'type', |
|
'delimiter' => '' |
|
); |
|
|
|
@docbook_special_quotation = ('note', 'caution', 'important', 'tip', 'warning'); |
|
|
|
$region_formats_kept{'copying'} = 1; |
|
|
|
%format_map = ( |
|
'group' => '', |
|
'raggedright' => '', |
|
'copying' => 'copying', |
|
); |
|
|
|
$print_Top = \&docbook_print_Top; |
|
$print_Top_footer = \&docbook_print_Top_footer; |
|
$print_page_head = \&docbook_print_page_head; |
|
$print_foot_navigation = \&docbook_noop; |
|
$contents = \&docbook_noop; |
|
$shortcontents = \&docbook_noop; |
|
$about_body = \&docbook_noop; |
|
$print_page_foot = \&docbook_print_page_foot; |
|
$end_section = \&docbook_end_section; |
|
$one_section = \&docbook_one_section; |
|
|
|
$acronym_like = \&docbook_acronym_like; |
|
$anchor_label = \&docbook_anchor_label; |
|
$begin_format_texi = \&docbook_begin_format_texi; |
|
$cartouche = \&docbook_cartouche; |
|
$cell = \&docbook_cell; |
|
$complex_format = \&docbook_complex_format; |
|
$def = \&docbook_def; |
|
$def_line = \&docbook_def_line; |
|
$def_item = \&docbook_def_item; |
|
$element_label = \&docbook_element_label; |
|
$external_ref = \&docbook_external_ref; |
|
$float = \&docbook_float; |
|
$foot_line_and_ref = \&docbook_foot_line_and_ref; |
|
$format = \&docbook_format; |
|
$format_list_item_texi = \&docbook_format_list_item_texi; |
|
$heading = \&docbook_heading; |
|
$image = \&docbook_image; |
|
$image_files = \&docbook_image_files; |
|
$index_entry_command = \&docbook_index_entry_command; |
|
$index_entry_label = \&docbook_index_entry_label; |
|
$index_summary = \&docbook_index_summary; |
|
$internal_ref = \&docbook_internal_ref; |
|
$insertcopying = \&docbook_insertcopying; |
|
$list_item = \&docbook_list_item; |
|
$misc_element_label = \&docbook_noop; |
|
$normal_text = \&docbook_normal_text; |
|
$paragraph = \&docbook_paragraph; |
|
$preformatted = \&docbook_preformatted; |
|
$printindex = \&docbook_printindex; |
|
$protect_text = \&xml_default_protect_text; |
|
$quotation = \&docbook_quotation; |
|
$quotation_prepend_text = \&docbook_quotation_prepend_text; |
|
$listoffloats = \&docbook_noop; |
|
$raw = \&docbook_raw; |
|
$row = \&docbook_row; |
|
$sp = \&docbook_sp; |
|
$style = \&docbook_style; |
|
$table_item = \&docbook_table_item; |
|
$table_line = \&docbook_table_line; |
|
$table_list = \&docbook_table_list; |
|
$misc_command_line = \&docbook_misc_commands; |
|
|
|
|
|
} |
|
|
|
sub docbook_footnote |
|
{ |
|
$docbook_in_footnote = 1; |
|
my $result = &$kept_footnote_function(@_); |
|
$docbook_in_footnote = 0; |
|
return $result; |
|
} |
|
|
|
sub docbook_macron($$) |
|
{ |
|
my $accent = shift; |
|
my $args = shift; |
|
return $args->[0] . "¯"; |
|
} |
|
|
|
sub docbook_samp($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
return "‘<literal>$args->[0]</literal>’"; |
|
} |
|
|
|
sub docbook_email($$) |
|
{ |
|
my $command = shift; |
|
my $args = shift; |
|
my $mail = shift @$args; |
|
my $text = shift @$args; |
|
$mail = main::normalise_space($mail); |
|
if (defined($text) and $text =~ /\S/) |
|
{ |
|
# FIXME normalise_space would be more legible. |
|
#return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.main::normalise_space($text).'</ulink>'; |
|
return docbook_add_id('ulink').' url="mailto:'.$mail.'">'.$text.'</ulink>'; |
|
} |
|
return docbook_add_id('email').">$mail</email>"; |
|
} |
|
|
|
sub docbook_uref($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
my $url = shift @$args; |
|
my $text = shift @$args; |
|
my $replacement = shift @$args; |
|
$url = main::normalise_space($url); |
|
$text = '' if (!defined($text)); |
|
$replacement = '' if (!defined($replacement)); |
|
$replacement = $text if ($replacement eq ''); |
|
$replacement = $url if ($replacement eq ''); |
|
$replacement = main::normalise_space($replacement); |
|
|
|
return docbook_add_id('ulink')." url=\"$url\">$replacement</ulink>"; |
|
} |
|
|
|
# FIXME |
|
sub docbook_titlefont($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
return "$args->[0]"; |
|
} |
|
|
|
# FIXME there ought to be something better... Like use tex4ht mathml |
|
# output or something like that |
|
sub docbook_math($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
my $text = shift @$args; |
|
return $text; |
|
} |
|
|
|
|
|
sub docbook_print_page_head($) |
|
{ |
|
my $fh = shift; |
|
my $language = get_conf('documentlanguage'); |
|
my $doctype = get_conf('doctype'); |
|
print $fh <<EOT; |
|
<?xml version="1.0"?> |
|
$doctype |
|
<book id="$Texi2HTML::THISDOC{file_base_name}.$EXTENSION" lang="$language"> |
|
EOT |
|
} |
|
|
|
sub docbook_print_page_foot($) |
|
{ |
|
my $fh = shift; |
|
print $fh "". docbook_close_section(); |
|
print $fh <<EOT; |
|
</book> |
|
EOT |
|
} |
|
|
|
sub docbook_print_Top($$$) |
|
{ |
|
my $fh = shift; |
|
my $has_top_heading = shift; |
|
my $element = shift; |
|
main::print_lines($fh, $Texi2HTML::THIS_SECTION); |
|
} |
|
|
|
sub docbook_element_tag($) |
|
{ |
|
my $element = shift; |
|
#print STDERR "$element->{'texi'}, $element->{'tag_level'}, $element->{'level'}\n"; |
|
return $docbook_sections{$element->{'tag_level'}} if (exists($docbook_sections{$element->{'tag_level'}})); |
|
return $docbook_sections{$element->{'level'}} if (exists($docbook_sections{$element->{'level'}})); |
|
} |
|
|
|
sub docbook_node_id($) |
|
{ |
|
my $node_texi = shift; |
|
my $node = main::substitute_line($node_texi, 'docbook node id', {'code_style' => 1, 'remove_texi' => 1}); |
|
$node =~ s/[\s\"]/-/g; |
|
return &$protect_text($node); |
|
} |
|
|
|
sub docbook_initialize_variables() |
|
{ |
|
$docbook_pending_node_id = undef; |
|
$docbook_current_section = undef; |
|
@docbook_multitable_stack = (); |
|
@docbook_table_stack = (); |
|
$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</bridgehead>\n"; |
|
} |
|
|
|
my $result = ''; |
|
|
|
# FIXME verify xreflabel |
|
if ($command ne 'node') |
|
{ |
|
# close previous section |
|
$result .= docbook_close_section(); |
|
my $title = $element->{'text_nonumber'}; |
|
my $label = ''; |
|
my $xreflabel = ''; |
|
if ($element->{'number'}) |
|
{ |
|
my $label_nr = $element->{'number'}; |
|
#$label_nr =~ s/\.$//; |
|
$label = $label_nr; |
|
} |
|
else |
|
{ |
|
my $xreftitle = $title; |
|
$xreflabel = " xreflabel=\"$xreftitle\""; |
|
} |
|
$result .= docbook_add_id(docbook_element_tag($element) . " label=\"${label}\"${xreflabel}"); |
|
$result .= ">\n<title>$title</title>\n"; |
|
$docbook_current_section = $element; |
|
} |
|
return $result; |
|
} |
|
|
|
sub docbook_element_label($$$$) |
|
{ |
|
my $id = shift; |
|
my $element = shift; |
|
my $command = shift; |
|
my $line = shift; |
|
|
|
if ($command eq 'node') |
|
{ |
|
$docbook_pending_node_id = docbook_node_id($element->{'texi'}); |
|
} |
|
return ''; |
|
} |
|
|
|
sub docbook_paragraph($$$$$$$$$$$$) |
|
{ |
|
my $text = shift; |
|
my $align = shift; |
|
my $indent = shift; |
|
my $paragraph_command = shift; |
|
my $paragraph_command_formatted = shift; |
|
my $paragraph_number = shift; |
|
my $format = shift; |
|
my $item_nr = shift; |
|
my $enumerate_style = shift; |
|
my $number = shift; |
|
my $command_stack_at_end = shift; |
|
my $command_stack_at_begin = shift; |
|
|
|
if (defined($paragraph_number) and defined($$paragraph_number)) |
|
{ |
|
$$paragraph_number++; |
|
} |
|
|
|
# no para in multitables, caption and shortcaptions. |
|
my $top_stack = ''; |
|
$top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin)); |
|
return $text if ($top_stack eq 'multitable' or $top_stack eq 'shortcaption' or $top_stack eq 'caption' or $top_stack eq 'documentdescription'); |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
#return docbook_add_id('para').">$text</para>"; |
|
return "<para>$text</para>"; |
|
} |
|
return $text; |
|
} |
|
|
|
|
|
sub docbook_def_line($$$$$$$$$$$$$$$) |
|
{ |
|
my $category_prepared = shift; |
|
my $name = shift; |
|
my $type = shift; |
|
my $arguments = shift; |
|
my $index_label = shift; |
|
my $arguments_array = shift; |
|
my $arguments_type_array = shift; |
|
my $unformatted_arguments_array = shift; |
|
my $command = shift; |
|
my $class_name = shift; |
|
my $category = shift; |
|
my $class = shift; |
|
my $style = shift; |
|
my $original_command = shift; |
|
|
|
my %unformatted_arguments = (); |
|
|
|
my @unformatted_args = @$unformatted_arguments_array; |
|
foreach my $type (@$arguments_type_array) |
|
{ |
|
my $unformatted_arg = shift @unformatted_args; |
|
$unformatted_arguments{$type} = $unformatted_arg; |
|
} |
|
# FIXME unformatted! |
|
my $result = "<synopsis role=\"$unformatted_arguments{'category'}\"><indexterm role=\"" |
|
.$main::index_prefix_to_name{$style}."\"><primary>$class_name</primary></indexterm>"; |
|
|
|
my %arguments = ( 'prepared_category' => $category_prepared, |
|
'category' => $category, |
|
'name' => $name, |
|
'type' => $type, |
|
'class' => $class |
|
); |
|
foreach my $type (keys(%arguments)) |
|
{ |
|
$arguments{$type} = '' if (!defined($arguments{$type})); |
|
} |
|
|
|
foreach my $mandatory_arg (@{$def_format_docbook{$command}}) |
|
{ |
|
my $elem = $mandatory_arg->[0]; |
|
#if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /^\s*\@code\{/) |
|
if ($elem eq 'returnvalue' and $unformatted_arguments{$mandatory_arg->[1]} =~ /\@code\{/) |
|
{ |
|
# FIXME unformatted |
|
my $arg_without_at_command = $unformatted_arguments{$mandatory_arg->[1]}; |
|
#$arg_without_at_command =~ s/\s*\@code\{//; |
|
#$arg_without_at_command =~ s/\}\s*$//; |
|
while ($arg_without_at_command =~ /\@code\{([^\{\}]*)\}/) |
|
{ |
|
$arg_without_at_command =~ s/\@code\{([^\{\}]*)\}/$1/; |
|
} |
|
$result .= "<$elem>$arg_without_at_command</$elem>"; |
|
} |
|
else |
|
{ |
|
$result .= "<$elem>$arguments{$mandatory_arg->[1]}</$elem>"; |
|
} |
|
} |
|
|
|
my @types = @$arguments_type_array; |
|
@unformatted_args = @$unformatted_arguments_array; |
|
foreach my $arg (@$arguments_array) |
|
{ |
|
my $type = shift @types; |
|
my $unformatted = shift @unformatted_args; |
|
if (exists ($def_argument_types_docbook{$type})) |
|
{ |
|
if ($def_argument_types_docbook{$type} and |
|
($type eq 'paramtype' or ($unformatted !~ /^\s*\@var\{/))) |
|
{ |
|
$result .= "<$def_argument_types_docbook{$type}>$arg</$def_argument_types_docbook{$type}>"; |
|
} |
|
else |
|
{ |
|
$result .= $arg; |
|
} |
|
} |
|
} |
|
|
|
$result .= "</synopsis>\n"; |
|
return $result; |
|
} |
|
|
|
# FIXME |
|
# @deffn |
|
# @c comment |
|
# @end deffn |
|
# leads to the creation of a <definitionitem> with a comment within, |
|
# while there should be no definitionitem |
|
sub docbook_def_item($) |
|
{ |
|
my $text = shift; |
|
my $only_inter_item_commands = shift; |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
return '<blockquote>' . $text . '</blockquote>' unless $only_inter_item_commands; |
|
return $text; |
|
} |
|
return ''; |
|
} |
|
|
|
sub docbook_def($) |
|
{ |
|
my $text = shift; |
|
return docbook_add_id('informalfigure').'>'.$text.'</informalfigure>'; |
|
} |
|
|
|
sub docbook_preformatted($$$$$$$$$$$$) |
|
{ |
|
my $text = shift; |
|
my $pre_style = shift; |
|
my $class = shift; |
|
my $leading_command = shift; |
|
my $leading_command_formatted = shift; |
|
my $preformatted_number = shift; |
|
my $format = shift; |
|
my $item_nr = shift; |
|
my $enumerate_style = shift; |
|
my $number = shift; |
|
my $command_stack_at_end = shift; |
|
my $command_stack_at_begin = shift; |
|
|
|
return $text; |
|
} |
|
|
|
sub docbook_misc_commands($$$$$) |
|
{ |
|
my $macro = shift; |
|
my $line = shift; |
|
my $args = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
#print STDERR "$macro $line"; |
|
#print STDERR "ARGS @$args\n" if defined ($args); |
|
my $result_text = undef; |
|
if ($macro eq 'c' or $macro eq 'comment' and scalar(@$args)) |
|
{ |
|
my $comment_line = $args->[0]; |
|
chomp ($comment_line); |
|
# makeinfo remove all the leading spaces |
|
$comment_line =~ s/^\s//; |
|
$result_text = &$comment ($comment_line); |
|
} |
|
elsif ($macro eq 'settitle') |
|
{ |
|
# FIXME to be formatted? Also maybe in line_command. And in html, it |
|
# is handled by heading _text |
|
my $arg = $args->[0]; |
|
$arg =~ s/^\s*//; |
|
chomp($arg); |
|
$result_text = "<title>$arg</title>\n"; |
|
} |
|
return ($macro, $line, $result_text); |
|
} |
|
|
|
sub docbook_foot_line_and_ref($$$$$$$) |
|
{ |
|
my $number_in_doc = shift; |
|
my $number_in_page = shift; |
|
my $footnote_id = shift; |
|
my $place_id = shift; |
|
my $document_file = shift; |
|
my $footnote_file = shift; |
|
my $lines = shift; |
|
my $state = shift; |
|
|
|
my $result = docbook_add_id('footnote').'>'; |
|
foreach my $line (@$lines) |
|
{ |
|
$result .= $line; |
|
} |
|
return ([], $result . '</footnote>'); |
|
} |
|
|
|
sub docbook_any_ref($$$) |
|
{ |
|
my $type = shift; |
|
my $args = shift; |
|
my $unformatted_args = shift; |
|
|
|
# FIXME? |
|
if ($type eq 'inforef') |
|
{ |
|
my $node_file = "($args->[2])$args->[0]"; |
|
if ($args->[1] ne '') |
|
{ |
|
return "*note $args->[1]: $node_file"; |
|
} |
|
else |
|
{ |
|
return "*note ${node_file}::"; |
|
} |
|
} |
|
else |
|
{ |
|
if (($args->[3] ne '') or ($args->[4] ne '')) |
|
{ |
|
return '' if ($args->[4] eq ''); |
|
my $section_name = $args->[2]; |
|
$section_name = $args->[0] if ($section_name eq ''); |
|
if ($type eq 'ref') |
|
{ |
|
return gdt('section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); |
|
} |
|
elsif ($type eq 'xref') |
|
{ |
|
return gdt('See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); |
|
} |
|
elsif ($type eq 'pxref') |
|
{ |
|
return gdt('see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}', { 'section_name' => $section_name, 'book' => $args->[4] },{'duplicate'=>1}); |
|
} |
|
} |
|
my $link = docbook_node_id($unformatted_args->[0]); |
|
my $title = $args->[2]; |
|
$title = $args->[1] if ($title eq ''); |
|
if ($title eq '') |
|
{ |
|
if ($type eq 'ref') |
|
{ |
|
return gdt('{ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"}); |
|
} |
|
elsif ($type eq 'pxref') |
|
{ |
|
return gdt('see {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"}); |
|
} |
|
elsif ($type eq 'xref') |
|
{ |
|
return gdt('See {ref}', {'ref' => docbook_add_id('xref')." linkend=\"$link\"></xref>"}); |
|
} |
|
} |
|
else |
|
{ |
|
if ($type eq 'ref') |
|
{ |
|
return gdt('{title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"}); |
|
} |
|
elsif ($type eq 'pxref') |
|
{ |
|
return gdt('see {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"},{'duplicate'=>1}); |
|
} |
|
elsif ($type eq 'xref') |
|
{ |
|
return gdt('See {title_ref}', {'title_ref' => docbook_add_id('link')." linkend=\"$link\">$title</link>"},{'duplicate'=>1}); |
|
} |
|
} |
|
} |
|
} |
|
|
|
sub docbook_external_ref($$$$$$$$$) |
|
{ |
|
my $type = shift; |
|
my $section = shift; |
|
my $book = shift; |
|
my $file = shift; |
|
my $href = shift; |
|
my $cross_ref = shift; |
|
my $args_texi = shift; |
|
my $formatted_args = shift; |
|
my $node = shift; |
|
|
|
return docbook_any_ref ($type, $formatted_args, $args_texi); |
|
} |
|
|
|
sub docbook_internal_ref($$$$$) |
|
{ |
|
my $type = shift; |
|
my $href = shift; |
|
my $short_name = shift; |
|
my $name = shift; |
|
my $is_section = shift; |
|
my $args_texi = shift; |
|
my $formatted_args = shift; |
|
|
|
return docbook_any_ref ($type, $formatted_args, $args_texi ); |
|
} |
|
|
|
sub docbook_index_entry_command($$$$$) |
|
{ |
|
my $command = shift; |
|
my $index_name = shift; |
|
my $label = shift; |
|
my $entry_texi = shift; |
|
my $entry_formatted = shift; |
|
|
|
return $label if (defined($label) and $label ne ''); |
|
return docbook_index_entry_label('','','',$main::index_prefix_to_name{$index_name}, '', '', $entry_formatted, {}); |
|
} |
|
|
|
sub docbook_index_entry_label($$$$$$$$$) |
|
{ |
|
my $identifier = shift; |
|
my $preformatted = shift; |
|
my $entry = shift; |
|
my $index_name = shift; |
|
my $index_command = shift; |
|
my $texi_entry = shift; |
|
my $formatted_entry = shift; |
|
my $in_region_not_in_output = shift; |
|
my $index_entry = shift; |
|
|
|
return "<indexterm role=\"${index_name}\"><primary>${formatted_entry}</primary></indexterm>"; |
|
} |
|
|
|
sub docbook_close_section() |
|
{ |
|
my $element = $docbook_current_section; |
|
|
|
if (!defined($element)) |
|
{ |
|
return ''; |
|
} |
|
|
|
my $result = ''; |
|
|
|
# there is a special case for a @chapter that is a child of @top |
|
# but should not be considered as is, since it is also toplevel. |
|
# @part, however may have other toplevel elements as children. |
|
return '' if ($element->{'child'} and (!$element->{'child'}->{'toplevel'} or $element->{'tag'} ne 'top')); |
|
$result .= '</'.docbook_element_tag($element).">\n"; |
|
|
|
my $current = $element; |
|
# the second condition is such that top is closed only if it has |
|
# sub-elements below chapter. |
|
# the third condition is such that elements with a next element are |
|
# only closed for the last element, except when the next element is |
|
# toplevel and below top, such that @top is closed before the first |
|
# @chapter if there are @section or the like below @top |
|
while ($current->{'sectionup'} and !($current->{'sectionup'}->{'tag'} eq 'top' and $current->{'toplevel'}) and (!$current->{'childnext'} or ($current->{'childnext'}->{'toplevel'} and $current->{'sectionup'}->{'tag'} eq 'top'))) |
|
{ |
|
$current = $current->{'sectionup'}; |
|
$result .= '</'.docbook_element_tag($current).">\n"; |
|
} |
|
return $result; |
|
} |
|
|
|
sub docbook_end_section($$$) |
|
{ |
|
my $fh = shift; |
|
my $end_foot_navigation = shift; |
|
my $element = shift; |
|
} |
|
|
|
sub docbook_print_Top_footer($$) |
|
{ |
|
my $fh = shift; |
|
my $end_page = shift; |
|
my $element = shift; |
|
} |
|
|
|
sub docbook_one_section($$) |
|
{ |
|
my $fh = shift; |
|
my $element = shift; |
|
main::print_lines($fh); |
|
&$print_page_foot($fh); |
|
} |
|
|
|
sub docbook_insertcopying($) |
|
{ |
|
my $text = shift; |
|
my $comment = shift; |
|
my $simple_text = shift; |
|
|
|
return $text; |
|
} |
|
|
|
sub docbook_acronym_like($$$$$$) |
|
{ |
|
my $command = shift; |
|
my $acronym_texi = shift; |
|
my $acronym_text = shift; |
|
my $with_explanation = shift; |
|
my $explanation_lines = shift; |
|
my $explanation_text = shift; |
|
my $explanation_simply_formatted = shift; |
|
|
|
$command = 'abbrev' if ($command eq 'abbr'); |
|
my $result = docbook_add_id($command).">$acronym_text</${command}>"; |
|
if ($with_explanation) |
|
{ |
|
$result .= " ($explanation_text)"; |
|
} |
|
return $result; |
|
} |
|
|
|
|
|
sub docbook_image_files($$$$) |
|
{ |
|
my $base = shift; |
|
my $extension = shift; |
|
my $texi_base = shift; |
|
my $texi_extension = shift; |
|
my @files = (); |
|
return @files if (!defined($base) or ($base eq '')); |
|
# FIXME should look at extension argument? makeinfo doesn't |
|
# push @files,"$base.$extension" if (defined($extension) and ($extension ne '')); |
|
foreach my $ext (@IMAGE_EXTENSIONS) |
|
{ |
|
push @files, ["$base.$ext", "$texi_base.$ext"]; |
|
} |
|
return @files; |
|
} |
|
|
|
|
|
sub docbook_image($$$$$$$$$$$$$$$$;$) |
|
{ |
|
my $file = shift; |
|
my $base = shift; |
|
my $preformatted = shift; |
|
my $file_name = shift; |
|
my $alt = shift; |
|
my $width = shift; |
|
my $height = shift; |
|
my $raw_alt = shift; |
|
my $extension = shift; |
|
my $working_dir = shift; |
|
my $file_path = shift; |
|
my $in_paragraph = shift; |
|
my $file_locations = shift; |
|
my $base_simple_format = shift; |
|
my $extension_simple_format = shift; |
|
my $file_name_simple_format = shift; |
|
my $line_nr = shift; |
|
|
|
# if (!defined($file_path) or $file_path eq '' or $file_path =~ /\.txt$/) |
|
# { |
|
# if (defined($extension) and $extension ne '') |
|
# { |
|
# $file = "$base.$extension"; |
|
# } |
|
# else |
|
# { |
|
# $file = "$base.jpg"; |
|
# $extension = 'jpg'; |
|
# } |
|
# main::line_warn ("no image file for $base, (using $file)"); |
|
# } |
|
my $txt_path; |
|
my @files = (); |
|
my @extensions = @IMAGE_EXTENSIONS; |
|
foreach my $file_location (@$file_locations) |
|
{ |
|
my ($file_located, $path, $file_simple_format) = @$file_location; |
|
my $extension = shift @extensions; |
|
if (defined($path)) |
|
{ |
|
if ($extension eq 'txt' and !defined($txt_path)) |
|
{ |
|
$txt_path = $path; |
|
} |
|
else |
|
{ |
|
push @files, [$file_located, uc($extension), $file_simple_format]; |
|
} |
|
} |
|
} |
|
push @files, ["$base.jpg", 'JPG', "$base_simple_format.jpg" ] unless (@files); |
|
|
|
my $begin = docbook_add_id('inlinemediaobject').'>'; |
|
my $end = '</inlinemediaobject>'; |
|
if ($preformatted or !$in_paragraph) |
|
{ |
|
$begin = docbook_add_id('informalfigure').'><mediaobject>'; |
|
$end = '</mediaobject></informalfigure>'; |
|
} |
|
my $result = $begin; |
|
foreach my $file_spec (@files) |
|
{ |
|
$result .= "<imageobject><imagedata fileref=\"$file_spec->[2]\" format=\"$file_spec->[1]\"></imagedata></imageobject>"; |
|
} |
|
if (defined($txt_path)) |
|
{ |
|
if (open(TXT, "<$txt_path")) |
|
{ |
|
if (defined($Texi2HTML::THISDOC{'IN_ENCODING'}) and $USE_UNICODE) |
|
{ |
|
binmode(TXT, ":encoding($Texi2HTML::THISDOC{'IN_ENCODING'})"); |
|
} |
|
$result.="<textobject><literallayout>"; |
|
while (my $img_txt = <TXT>) |
|
{ |
|
$result .= $img_txt; |
|
} |
|
$result .= '</literallayout></textobject>'; |
|
close(TXT); |
|
} |
|
else |
|
{ |
|
main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr); |
|
} |
|
} |
|
else |
|
{ |
|
main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr); |
|
} |
|
|
|
return "$result$end"; |
|
} |
|
|
|
sub docbook_format_list_item_texi($$$$) |
|
{ |
|
my $format = shift; |
|
my $line = shift; |
|
my $prepended = shift; |
|
my $command = shift; |
|
|
|
my $result_line = undef; |
|
|
|
if (defined($command) and $command ne '' and !exists $special_list_commands{$format}->{$command} and $format ne 'itemize') |
|
{ |
|
#@*table |
|
$line =~ s/^\s*//; |
|
$line =~ s/\s*$//; |
|
if (exists ($style_map{$command})) |
|
{ |
|
$result_line = "\@$command\{$line\}\n"; |
|
} |
|
elsif (exists ($things_map{$command})) |
|
{ |
|
$result_line = "\@$command\{\} $line\n"; |
|
} |
|
else |
|
{ |
|
$result_line = "\@$command $line\n"; |
|
} |
|
} |
|
|
|
return ($result_line, 0); |
|
} |
|
|
|
|
|
# row in multitable |
|
sub docbook_row($$;$$) |
|
{ |
|
my $text = shift; |
|
my $macro = shift; |
|
my $columnfractions = shift; |
|
my $prototype_row = shift; |
|
my $prototype_lengths = shift; |
|
my $column_number = shift; |
|
|
|
my $result = ''; |
|
if ($macro eq 'headitem') |
|
{ |
|
if ($docbook_multitable_stack[-1] != 0) |
|
{ |
|
$result .= "<thead>"; |
|
$result = "</tbody>" . $result if ($docbook_multitable_stack[-1] == 1); |
|
$docbook_multitable_stack[-1] = 0; |
|
} |
|
} |
|
elsif ($docbook_multitable_stack[-1] != 1) |
|
{ |
|
$result .= "<tbody>"; |
|
$result = "</thead>" . $result if ($docbook_multitable_stack[-1] == 0); |
|
$docbook_multitable_stack[-1] = 1; |
|
} |
|
$result .= "<row>$text</row>"; |
|
|
|
return $result; |
|
} |
|
|
|
# cell in multitable |
|
sub docbook_cell($$;$$) |
|
{ |
|
my $text = shift; |
|
my $row_macro = shift; |
|
my $columnfractions = shift; |
|
my $prototype_row = shift; |
|
my $prototype_lengths = shift; |
|
my $column_number = shift; |
|
|
|
return "<entry>" . $text . '</entry>'; |
|
} |
|
|
|
# if varlistentry_state is > 0 it means that a varlistentry is opened. |
|
# if varlistentry_state is == 2 it means that we are in a succession |
|
# of term |
|
# if varlistentry_state is == 1 it means that we are in the line |
|
# Having a listitem in a varlistentry is a must, so an empty |
|
# listitem is added if a varlistentry is closed and varlistentry_state == 2 |
|
# |
|
# varlistentry acceps only term and listitem, so inter_item_commands |
|
# are put in the next term, or, if at the end of the table in a last |
|
# listitem |
|
sub docbook_table_item($$$$$$) |
|
{ |
|
my $text = shift; |
|
my $index_label = shift; |
|
my $format = shift; |
|
my $command = shift; |
|
# my $formatted_command = shift; |
|
my $style_stack = shift; |
|
# my $text_formatted = shift; |
|
# my $text_formatted_leading_spaces = shift; |
|
# my $text_formatted_trailing_spaces = shift; |
|
my $item_cmd = shift; |
|
|
|
# $formatted_command = '' if (!defined($formatted_command)); |
|
|
|
# if (defined($text_formatted)) |
|
# { |
|
# $text_item = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces; |
|
# } |
|
# else |
|
# { |
|
# $text_item = $text; |
|
# } |
|
|
|
my $result = ''; |
|
my $prepended = ''; |
|
if (defined($docbook_table_stack[-1]->{'inter_item'})) |
|
{ |
|
#$formatted_command = $docbook_table_stack[-1]->{'inter_item'} . $formatted_command; |
|
$prepended = $docbook_table_stack[-1]->{'inter_item'}; |
|
delete $docbook_table_stack[-1]->{'inter_item'}; |
|
} |
|
if ($item_cmd eq 'item') |
|
{ |
|
if ($docbook_table_stack[-1]->{'varlistentry_state'} == 2) |
|
{ |
|
$result .= "<listitem><para><!-- empty table line --></para></listitem>"; |
|
} |
|
if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1) |
|
{ |
|
$result .= '</varlistentry>'; |
|
} |
|
$docbook_table_stack[-1]->{'varlistentry_state'} = 2; |
|
$result .= '<varlistentry>'; |
|
} |
|
$result .= '<term>'; |
|
$result .= $prepended . $text ."</term>\n"; |
|
return $result; |
|
} |
|
|
|
sub docbook_table_line($$$) |
|
{ |
|
my $text = shift; |
|
my $only_inter_item_commands = shift; |
|
my $before_items = shift; |
|
|
|
$only_inter_item_commands = '' if (!defined($only_inter_item_commands)); |
|
|
|
#print STDERR |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
if ($before_items) |
|
{ |
|
return $text; |
|
} |
|
|
|
if ($only_inter_item_commands) |
|
{ |
|
$docbook_table_stack[-1]->{'inter_item'} = $text; |
|
return ''; |
|
} |
|
else |
|
{ |
|
$docbook_table_stack[-1]->{'varlistentry_state'} = 1; |
|
return "<listitem>$text</listitem>"; |
|
} |
|
#return $text; |
|
} |
|
else |
|
{ |
|
return ''; |
|
} |
|
} |
|
|
|
sub docbook_list_item($$$$$$$$$) |
|
{ |
|
my $text = shift; |
|
my $format = shift; |
|
my $command = shift; |
|
my $formatted_command = shift; |
|
my $item_nr = shift; |
|
my $enumerate_style = shift; |
|
my $number = shift; |
|
my $prepended = shift; |
|
my $prepended_formatted = shift; |
|
my $only_inter_item_commands = shift; |
|
my $before_items = shift; |
|
|
|
$only_inter_item_commands = '' if (!defined($only_inter_item_commands)); |
|
|
|
#my $prep_t = 'UNDEF'; $prep_t = $prepended if (defined($prepended)); |
|
#$item_nr = 0 if (!defined($item_nr)); |
|
#print STDERR " $item_nr --> $prep_t|${text}!!!!!\n"; |
|
#return $text if ($only_inter_item_commands and $before_items); |
|
return $text if ($before_items); |
|
return '<listitem>' . $text . "</listitem>\n"; |
|
} |
|
|
|
sub docbook_table_list($$$$$$$$$) |
|
{ |
|
my $format_command = shift; |
|
my $text = shift; |
|
my $command = shift; |
|
my $formatted_command = shift; |
|
# enumerate |
|
my $item_nr = shift; |
|
my $enumerate_style = shift; |
|
# itemize |
|
my $prepended = shift; |
|
my $prepended_formatted = shift; |
|
# multitable |
|
my $columnfractions = shift; |
|
my $prototype_row = shift; |
|
my $prototype_lengths = shift; |
|
my $number = shift; |
|
|
|
my $result = "<$format_command>"; |
|
if ($format_command eq 'itemize') |
|
{ |
|
my $itemfunction; |
|
#$prepended_formatted =~ s/^\s*// if (defined($prepended_formatted)); |
|
$prepended =~ s/^\s*// if (defined($prepended)); |
|
#if (defined($formatted_command) and $formatted_command ne '') |
|
if (defined($command) and $command ne '') |
|
{ |
|
#$itemfunction = $formatted_command; |
|
$itemfunction = $command; |
|
#$itemfunction .= " $prepended_formatted" if (defined($prepended_formatted) and $prepended_formatted ne ''); |
|
$itemfunction .= " $prepended" if (defined($prepended) and $prepended ne ''); |
|
} |
|
#elsif (defined($prepended_formatted)) |
|
elsif (defined($prepended)) |
|
{ |
|
#$itemfunction = $prepended_formatted; |
|
$itemfunction = $prepended; |
|
} |
|
my $mark = ''; |
|
$mark = " mark=\"$itemfunction\"" if (defined($itemfunction) and $itemfunction ne ''); |
|
return docbook_add_id('itemizedlist')."${mark}>$text</itemizedlist>"; |
|
} |
|
elsif ($format_command eq 'enumerate') |
|
{ |
|
my $numeration='arabic'; |
|
if (defined($enumerate_style) and $enumerate_style ne '') |
|
{ |
|
if ($enumerate_style =~ /^[A-Z]/) |
|
{ |
|
$numeration = 'upperalpha'; |
|
} |
|
elsif ($enumerate_style =~ /^[a-z]/) |
|
{ |
|
$numeration = 'loweralpha'; |
|
} |
|
} |
|
return docbook_add_id('orderedlist') ." numeration=\"$numeration\">$text</orderedlist>"; |
|
} |
|
elsif ($format_command eq 'multitable') |
|
{ |
|
my $result = docbook_add_id('informaltable').'><tgroup cols="'.$number.'">'; |
|
my $fractions; |
|
my $multiply = 1; |
|
if (defined($columnfractions) and (ref($columnfractions) eq 'ARRAY') |
|
and scalar(@$columnfractions)) |
|
{ |
|
$fractions = [ @$columnfractions ]; |
|
$multiply = 100; |
|
} |
|
elsif (defined($prototype_lengths) and (ref($prototype_lengths) eq 'ARRAY') |
|
and scalar(@$prototype_lengths)) |
|
{ |
|
$fractions = [ @$prototype_lengths ]; |
|
} |
|
|
|
if (defined ($fractions)) |
|
{ |
|
foreach my $fraction (@$fractions) |
|
{ |
|
$result .= '<colspec colwidth="'.($fraction*$multiply).'*"></colspec>'; |
|
} |
|
} |
|
$text .= "</tbody>" if ($docbook_multitable_stack[-1] == 1); |
|
$text .= "</thead>" if ($docbook_multitable_stack[-1] == 0); |
|
pop @docbook_multitable_stack; |
|
return $result . "$text</tgroup></informaltable>"; |
|
} |
|
elsif ($format_command =~ /^(v|f)?table$/) |
|
{ |
|
$result = docbook_add_id('variablelist').'>'; |
|
if (defined($docbook_table_stack[-1]->{'inter_item'})) |
|
{ # there is a para in case there is only a comment, to avoid |
|
# an empty listitem |
|
$text .= "<listitem><para>$docbook_table_stack[-1]->{'inter_item'}</para></listitem>"; |
|
} |
|
elsif ($docbook_table_stack[-1]->{'varlistentry_state'} == 2) |
|
{ |
|
$text .= "<listitem><para><!-- empty table line --></para></listitem>"; |
|
} |
|
$text .= '</varlistentry>' if ($docbook_table_stack[-1]->{'varlistentry_state'} >= 1); |
|
pop @docbook_table_stack; |
|
return $result . "$text</variablelist>\n"; |
|
} |
|
} |
|
|
|
sub docbook_begin_format_texi($$$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $state = shift; |
|
|
|
push (@docbook_multitable_stack, -1) if ($command eq 'multitable'); |
|
push (@docbook_table_stack, {'varlistentry_state' => 0}) if ($command =~ /^(v|f)?table/); |
|
return $line; |
|
} |
|
|
|
# FIXME |
|
sub docbook_sp($$) |
|
{ |
|
my $number = shift; |
|
my $preformatted = shift; |
|
return ""; |
|
} |
|
|
|
sub docbook_index_summary($$) |
|
{ |
|
my $alpha = shift; |
|
my $nonalpha = shift; |
|
return ''; |
|
} |
|
|
|
sub docbook_printindex($$) |
|
{ |
|
my $name = shift; |
|
my $printindex = shift; |
|
return docbook_add_id('index')."></index>\n"; |
|
} |
|
|
|
sub docbook_complex_format($$) |
|
{ |
|
my $name = shift; |
|
my $text = shift; |
|
return '' if ($text eq ''); |
|
my $result = docbook_add_id($docbook_complex_format{$name}).'>' .$text."</$docbook_complex_format{$name}>"; |
|
return $result; |
|
} |
|
|
|
sub docbook_format($$) |
|
{ |
|
my $name = shift; |
|
my $element = shift; |
|
my $text = shift; |
|
return '' if ($text eq ''); |
|
return $text if ($format_map{$name} eq ''); |
|
if ($name eq 'copying') |
|
{ |
|
# FIXME is info in docbook 5.0 |
|
return "<bookinfo>\n<legalnotice>\n$text</legalnotice>\n</bookinfo>\n"; |
|
} |
|
return docbook_add_id($format_map{$name}).'>' .$text."</$format_map{$name}>"; |
|
} |
|
|
|
sub docbook_quotation_prepend_text($$) |
|
{ |
|
my $command = shift; |
|
my $argument_text = shift; |
|
|
|
return undef if (!defined($argument_text) or $argument_text =~ /^$/); |
|
|
|
chomp($argument_text); |
|
|
|
return undef if (grep {lc($argument_text) eq $_} @docbook_special_quotation); |
|
return gdt('@b{{quotation_arg}:} ', {'quotation_arg' => $argument_text}, {'keep_texi' => 1}); |
|
} |
|
|
|
|
|
sub docbook_quotation($$$$$) |
|
{ |
|
my $command = shift; |
|
my $text = shift; |
|
my $argument_text = shift; |
|
my $argument_text_texi = shift; |
|
my $authors = shift; |
|
|
|
$argument_text_texi = '' if (!defined($argument_text_texi)); |
|
chomp($argument_text_texi); |
|
my $docbook_command = 'blockquote'; |
|
if (grep {lc($argument_text_texi) eq $_} @docbook_special_quotation) |
|
{ |
|
$docbook_command = lc($argument_text_texi); |
|
} |
|
my $attribution = ''; |
|
if ($authors) |
|
{ |
|
foreach my $author (@$authors) |
|
{ |
|
$attribution .= $author->{'author_text'}; |
|
} |
|
$attribution = '<attribution>' .$attribution. '</attribution>' . "\n"; |
|
} |
|
return docbook_add_id($docbook_command).'>' .$attribution . $text . "</$docbook_command>\n"; |
|
} |
|
|
|
sub docbook_style($$$$$$$$$) |
|
{ |
|
my $style = shift; |
|
my $command = shift; |
|
my $text = shift; |
|
my $args = shift; |
|
my $no_close =shift; |
|
my $no_open = shift; |
|
my $line_nr = shift; |
|
my $state = shift; |
|
my $command_stack = shift; |
|
my $kept_line_nrs = shift; |
|
|
|
my $result = $text; |
|
if (exists($style->{'function'})) |
|
{ |
|
my $function = $style->{'function'}; |
|
$result = &$function($command, $args, $command_stack, $state, $line_nr, $kept_line_nrs); |
|
} |
|
elsif (exists($style->{'inline_attribute'})) |
|
{ |
|
my $element = $style->{'inline_attribute'}; |
|
my $attribute_text = ''; |
|
if ($element =~ /^(\w+)(\s+.*)/) |
|
{ |
|
$element = $1; |
|
$attribute_text = $2; |
|
} |
|
|
|
if ($no_open) |
|
{ |
|
$result = "<$element"; |
|
} |
|
else |
|
{ |
|
$result = docbook_add_id($element); |
|
} |
|
$result .= "$attribute_text>$text</$element>"; |
|
} |
|
if (exists($style->{'begin'}) and !$no_open) |
|
{ |
|
$result = $style->{'begin'} . $result; |
|
} |
|
if (exists($style->{'end'}) and !$no_close) |
|
{ |
|
$result .= $style->{'end'}; |
|
} |
|
return $result; |
|
} |
|
|
|
sub docbook_raw($$$) |
|
{ |
|
my $style = shift; |
|
my $text = shift; |
|
my $line_nr = shift; |
|
|
|
if ($style eq 'verbatim' or $style eq 'verbatiminclude') |
|
{ |
|
return docbook_add_id('screen').'>' . &$protect_text($text) . '</screen>'; |
|
} |
|
return '' unless (grep {$style eq $_} @EXPAND); |
|
if ($style eq 'docbook') |
|
{ |
|
chomp ($text); |
|
return $text; |
|
} |
|
else |
|
{ |
|
main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr); |
|
return &$protect_text($text); |
|
} |
|
} |
|
|
|
sub docbook_cartouche($$) |
|
{ |
|
my $text = shift; |
|
|
|
return $text; |
|
} |
|
|
|
sub docbook_anchor_label($$) |
|
{ |
|
my $id = shift; |
|
my $anchor_text = shift; |
|
# FIXME use docbook_node_id |
|
return '<anchor id="'. &$protect_text($anchor_text) . '"></anchor>'; |
|
} |
|
|
|
sub docbook_float($$$$$) |
|
{ |
|
my $text = shift; |
|
my $float = shift; |
|
my $caption = shift; |
|
my $shortcaption = shift; |
|
|
|
my $label_texi = $float->{'texi'}; |
|
return $text if (!defined($label_texi) or $label_texi eq ''); |
|
|
|
return docbook_anchor_label('',$label_texi) . $text; |
|
} |
|
|
|
sub docbook_normal_text($$$$$$$;$) |
|
{ |
|
my $text = shift; |
|
my $in_raw_text = shift; # remove_texi |
|
my $in_preformatted = shift; |
|
my $in_code = shift; |
|
my $in_math = shift; |
|
my $in_simple = shift; |
|
#print STDERR "Bug: in_raw_text in_simple $text\n" if ($in_raw_text and $in_simple); |
|
my $style_stack = shift; |
|
my $state = shift; |
|
|
|
#$text = uc($text) if (in_cmd($style_stack, 'sc')); |
|
$text = &$protect_text($text) unless($in_raw_text); |
|
if (! $in_code and !$in_preformatted) |
|
{ |
|
if (!$in_raw_text) |
|
{ |
|
$text =~ s/---/\&mdash\;/g; |
|
$text =~ s/--/\&ndash\;/g; |
|
$text =~ s/``/\&ldquo\;/g; |
|
$text =~ s/''/\&rdquo\;/g; |
|
} |
|
else |
|
{ |
|
#FIXME really do that ? It is done by makeinfo in html |
|
$text =~ s/``/"/g; |
|
$text =~ s/''/"/g; |
|
# FIXME really do that in raw text? |
|
$text =~ s/---/\x{1F}/g; |
|
$text =~ s/--/-/g; |
|
$text =~ s/\x{1F}/--/g; |
|
} |
|
} |
|
return $text; |
|
} |
|
|
|
sub docbook_noop |
|
{ |
|
return ''; |
|
} |
|
|
|
1; |
|
|
|
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 = '<!DOCTYPE texinfo PUBLIC "-//GNU//DTD TexinfoML V4.12//EN" "http://www.gnu.org/software/texinfo/dtd/4.12/texinfo.dtd">'; |
|
$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>"; |
|
$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'} = '<!-- /@w -->'; |
|
$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 = "<email><emailaddress>$mail</emailaddress>"; |
|
if (defined($text) and $text =~ /\S/) |
|
{ |
|
$result .= "<emailname>".main::normalise_space($text)."</emailname>"; |
|
} |
|
return $result . '</email>'; |
|
} |
|
|
|
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 = "<uref><urefurl>$url</urefurl>"; |
|
$result .= "<urefdesc>$text</urefdesc>" if ($text ne ''); |
|
$result .= "<urefreplacement>$replacement</urefreplacement>" if ($replacement ne ''); |
|
return $result.'</uref>'; |
|
} |
|
|
|
|
|
sub xml_titlefont($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
return "<titlefont>$args->[0]</titlefont>"; |
|
} |
|
|
|
sub xml_math($$) |
|
{ |
|
shift; |
|
my $args = shift; |
|
my $text = shift @$args; |
|
return "<math>$text</math>"; |
|
} |
|
|
|
|
|
sub xml_menu_description($$$) |
|
{ |
|
my $text = shift; |
|
my $state = shift; |
|
my $element_text = shift; |
|
return "<menucomment>$text</menucomment>\n</menuentry>"; |
|
} |
|
|
|
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 "<menuentry>\n<menunode>$menunode_normalized</menunode>\n<menutitle>$menutitle</menutitle>\n"; |
|
} |
|
|
|
sub xml_print_page_head($) |
|
{ |
|
my $fh = shift; |
|
my $setfilename = ''; |
|
$setfilename = "<setfilename>$Texi2HTML::THISDOC{file_base_name}.$EXTENSION</setfilename>" |
|
unless (defined($Texi2HTML::THISDOC{'setfilename'}) and $Texi2HTML::THISDOC{'setfilename'} ne ''); |
|
my $language = get_conf('documentlanguage'); |
|
my $doctype = get_conf('doctype'); |
|
print $fh <<EOT; |
|
<?xml version="1.0"?> |
|
$doctype |
|
<texinfo xml:lang="$language"> |
|
$setfilename |
|
EOT |
|
} |
|
|
|
sub xml_print_page_foot($) |
|
{ |
|
my $fh = shift; |
|
print $fh "". xml_close_section(); |
|
print $fh <<EOT; |
|
</texinfo> |
|
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</${command}>\n"; |
|
} |
|
elsif (defined($command) and $command eq 'node') |
|
{ |
|
#print STDERR "node $command $node_element->{'texi'}\n"; |
|
my $result = ''; |
|
$result .= xml_close_section(); |
|
$result .= "<node>\n"; |
|
$result .= "<nodename>$element->{'text'}</nodename>\n"; |
|
foreach my $direction('nodenext', 'nodeprev', 'nodeup') |
|
{ |
|
if ($element->{$direction}) |
|
{ |
|
$result .= "<${direction}>$element->{$direction}->{'text'}</${direction}>\n"; |
|
} |
|
} |
|
$result .= "</node>\n"; |
|
return $result; |
|
|
|
} |
|
else |
|
{ |
|
my $result = ''; |
|
$result .= xml_close_section(); |
|
$result .= "<".xml_element_tag($element).">\n<title>$element->{'text'}</title>\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 .= '</'.xml_element_tag($element).">\n"; |
|
|
|
my $current = $element; |
|
# the second condition is such that top is closed only if it has |
|
# sub-elements below chapter. |
|
# the third condition is such that elements with a next element are |
|
# only closed for the last element, except when the next element is |
|
# toplevel and below top, such that @top is closed before the first |
|
# @chapter if there are @section or the like below @top |
|
while ($current->{'sectionup'} and !($current->{'sectionup'}->{'tag'} eq 'top' and $current->{'toplevel'}) and (!$current->{'childnext'} or ($current->{'childnext'}->{'toplevel'} and $current->{'sectionup'}->{'tag'} eq 'top'))) |
|
{ |
|
$current = $current->{'sectionup'}; |
|
$result .= '</'.xml_element_tag($current).">\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 .= '</'.xml_element_tag($element).">\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 .= '</'.xml_element_tag($current).">\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: |
|
# <para><samp>first para second para</samp>.</para> |
|
# |
|
# But it leads to |
|
# <para><samp>first para |
|
# </samp></para> |
|
# <para><samp>second para</samp>. |
|
# </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 "<para>$text</para>"; |
|
} |
|
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}></${macro}>"; |
|
if ($macro eq 'set' or $macro eq 'clear') |
|
{ |
|
$result_text = "<${macro}value name=\"$value_name\">$value</${macro}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\"></${macro}>"; |
|
} |
|
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")."</${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")."</$xml_misc_elements_with_arg_map{$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</${macro}>\n"; |
|
} |
|
} |
|
return ($macro, $line, $result_text); |
|
} |
|
|
|
|
|
sub xml_anchor_label($$) |
|
{ |
|
my $id = shift; |
|
my $anchor_text = shift; |
|
return '<anchor name="'. &$protect_text($anchor_text) . '"></anchor>'; |
|
} |
|
|
|
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 "<indexterm index=\"${index_name}\">${formatted_entry_reference}</indexterm>"; |
|
} |
|
|
|
sub xml_listoffloats($$$) |
|
{ |
|
my $style_texi = shift; |
|
my $style = shift; |
|
my $float_entries = shift; |
|
# FIXME style, style_texi? Protected? |
|
return "<listoffloats type=\"$style\"></listoffloats>"; |
|
} |
|
|
|
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</${command}word>"; |
|
if ($with_explanation) |
|
{ |
|
$opening .= "<${command}desc>$explanation_text</${command}desc>"; |
|
} |
|
return $opening . "</${command}>"; |
|
} |
|
|
|
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 = '<footnote>'; |
|
foreach my $line (@$lines) |
|
{ |
|
$result .= $line; |
|
} |
|
return ([], $result . '</footnote>'); |
|
} |
|
|
|
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\"><alttext>$alt</alttext></$tag>"; |
|
} |
|
|
|
sub xml_sp($$) |
|
{ |
|
my $number = shift; |
|
my $preformatted = shift; |
|
return "<sp lines=\"$number\"></sp>\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 . "</$command>\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 '<item>' . $text . "</item>\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 .= "<thead>"; |
|
$result = "</tbody>" . $result if ($xml_multitable_stack[-1] == 1); |
|
$xml_multitable_stack[-1] = 0; |
|
} |
|
} |
|
elsif ($xml_multitable_stack[-1] != 1) |
|
{ |
|
$result .= "<tbody>"; |
|
$result = "</thead>" . $result if ($xml_multitable_stack[-1] == 0); |
|
$xml_multitable_stack[-1] = 1; |
|
} |
|
$result .= "<row>$text</row>"; |
|
|
|
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 "<entry>" . $text . '</entry>'; |
|
} |
|
|
|
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>$itemfunction</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 .= "<columnfraction>".($fraction*$multiply)."</columnfraction>\n"; |
|
} |
|
} |
|
$text .= "</tbody>" if ($xml_multitable_stack[-1] == 1); |
|
$text .= "</thead>" if ($xml_multitable_stack[-1] == 0); |
|
pop @xml_multitable_stack; |
|
} |
|
elsif ($format_command =~ /^(v|f)?table$/) |
|
{ |
|
$result = '<table>'; |
|
$text .= '</tableitem>' if ($xml_table_stack[-1] == 1); |
|
pop @xml_table_stack; |
|
return $result . "$text</table>\n"; |
|
} |
|
return $result . "$text</$format_command>\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 = "<definitionterm><indexterm index=\"" |
|
.$main::index_prefix_to_name{$style}."\">$class_name</indexterm>"; |
|
|
|
my %arguments = ( 'prepared_category' => $category_prepared, |
|
'category' => $category, |
|
'name' => $name, |
|
'type' => $type, |
|
'class' => $class |
|
); |
|
foreach my $type (keys(%arguments)) |
|
{ |
|
$arguments{$type} = '' if (!defined($arguments{$type})); |
|
} |
|
|
|
foreach my $mandatory_arg (@{$def_format_xml{$command}}) |
|
{ |
|
my $elem = $mandatory_arg->[0]; |
|
$result .= "<def$elem>$arguments{$mandatory_arg->[1]}</def$elem>"; |
|
} |
|
|
|
my $params = ''; |
|
my @types = @$arguments_type_array; |
|
foreach my $arg (@$arguments_array) |
|
{ |
|
my $type = shift @types; |
|
if (grep {$_ eq $type} ('param', 'paramtype', 'delimiter')) |
|
{ |
|
$result .= "<def$type>$arg</def$type>"; |
|
} |
|
} |
|
|
|
$result .= "</definitionterm>\n"; |
|
return $result; |
|
} |
|
|
|
# FIXME |
|
# @deffn |
|
# @c comment |
|
# @end deffn |
|
# leads to the creation of a <definitionitem> with a comment within, |
|
# while there should be no definitionitem |
|
sub xml_def_item($$) |
|
{ |
|
my $text = shift; |
|
my $only_inter_item_commands = shift; |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
return '<definitionitem>' . $text . '</definitionitem>' unless $only_inter_item_commands; |
|
return $text; |
|
} |
|
return ''; |
|
} |
|
|
|
sub xml_def($) |
|
{ |
|
my $text = shift; |
|
return '<definition>'.$text.'</definition>'; |
|
} |
|
|
|
sub xml_index_summary($$) |
|
{ |
|
my $alpha = shift; |
|
my $nonalpha = shift; |
|
return ''; |
|
} |
|
|
|
sub xml_printindex($$) |
|
{ |
|
my $name = shift; |
|
my $printindex = shift; |
|
return "<printindex>$name</printindex>\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 .= "<inforef><inforefnodename>$args->[0]</inforefnodename>"; |
|
$result .= "<inforefrefname>$args->[1]</inforefrefname>" if ($args->[1] ne ''); |
|
$result .= "<inforefinfoname>$args->[2]</inforefinfoname></inforef>" |
|
} |
|
else |
|
{ |
|
$result .= "<xref><xrefnodename>$args->[0]</xrefnodename>"; |
|
$result .= "<xrefinfoname>$args->[1]</xrefinfoname>" if ($args->[1] ne ''); |
|
$result .= "<xrefprinteddesc>$args->[2]</xrefprinteddesc>" if ($args->[2] ne ''); |
|
$result .= "<xrefinfofile>$args->[3]</xrefinfofile>" if ($args->[3] ne ''); |
|
$result .= "<xrefprintedname>$args->[4]</xrefprintedname>" if ($args->[4] ne ''); |
|
$result .= '</xref>'; |
|
} |
|
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 .= '</tableitem>' if ($xml_table_stack[-1] == 1); |
|
$xml_table_stack[-1] = 1; |
|
$result .= '<tableitem>'; |
|
} |
|
$result .= '<tableterm>'; |
|
#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 .= "<indexterm index=\"$main::index_prefix_to_name{$index_prefix}\">$formatted_index_entry</indexterm>"; |
|
$result .= "$index_label"; |
|
} |
|
$result .= $text ."</tableterm>\n"; |
|
return $result; |
|
} |
|
|
|
sub xml_table_line($) |
|
{ |
|
my $text = shift; |
|
my $only_inter_item_commands = shift; |
|
my $before_items = shift; |
|
|
|
if ($text =~ /\S/) |
|
{ |
|
return "<item>$text</item>" 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</$command>"; |
|
} |
|
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 = "<float name=\"$label_texi\">\n"; |
|
my $style = $float->{'style'}; |
|
$style = '' if (!defined($style)); |
|
$result .= "<floattype>$style</floattype>\n"; |
|
$result .= "<floatpos></floatpos>\n"; |
|
$result .= $text; |
|
return $result."</float>\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</$format>" if ($format eq 'center'); |
|
return $text; |
|
} |
|
|
|
sub xml_raw($$) |
|
{ |
|
my $style = shift; |
|
my $text = shift; |
|
|
|
if ($style eq 'verbatim' or $style eq 'verbatiminclude') |
|
{ |
|
return '<verbatim xml:space="preserve">' . &$protect_text($text) . '</verbatim>'; |
|
} |
|
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 "<cartouche>$text</cartouche>"; |
|
} |
|
|
|
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 <pertusus@free.fr> |
|
# |
|
# 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 = <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$ |
|
|
|
# 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 <<EOT; |
|
Note: 'Options' may be abbreviated. -- prefix may be replaced by a single -. |
|
'Type' specifications mean: |
|
<none>| ! 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 <pertusus@free.fr>, |
|
# Derek Price <derek@ximbiot.com>, |
|
# Adrian Aichner <adrian@xemacs.org>, |
|
# & 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->{<language>}->{<word>} = '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 <pertusus@free.fr>, |
|
# Derek Price <derek@ximbiot.com>, |
|
# Adrian Aichner <adrian@xemacs.org>, |
|
# & 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 = <<EOT; |
|
% This document was automatically generated by the l2h extenstion of texi2html |
|
% DO NOT EDIT !!! |
|
\\documentclass{article} |
|
\\usepackage{html} |
|
\\begin{document} |
|
EOT |
|
|
|
my $l2h_latex_closing = <<EOT; |
|
\\end{document} |
|
EOT |
|
|
|
my %l2h_to_latex = (); # associate a latex text with the index in the |
|
# html result array. |
|
my @l2h_to_latex = (); # array used to associate the index with |
|
# the original latex text. |
|
my $latex_count = 0; # number of latex texts really stored |
|
my $latex_converted_count = 0; # number of latex texts passed through latex2html |
|
my $to_latex_count = 0; # total number of latex texts processed |
|
my $cached_count = 0; # number of cached latex texts |
|
%l2h_cache = (); # the cache hash. Associate latex text with |
|
# html from the previous run |
|
my @l2h_from_html; # array of resulting html |
|
|
|
my %global_count = (); # associate a command name and the |
|
# corresponding counter to the index in the |
|
# html result array |
|
|
|
# set $status to 1, if l2h could be initalized properly, to 0 otherwise |
|
sub init() |
|
{ |
|
|
|
%l2h_to_latex = (); # associate a latex text with the index in the |
|
# html result array. |
|
@l2h_to_latex = (); # array used to associate the index with |
|
# the original latex text. |
|
$latex_count = 0; # number of latex texts really stored |
|
$latex_converted_count = 0; # number of latex texts passed through latex2html |
|
$to_latex_count = 0; # total number of latex texts processed |
|
$cached_count = 0; # number of cached latex texts |
|
%l2h_cache = (); # the cache hash. Associate latex text with |
|
# html from the previous run |
|
@l2h_from_html = (); # array of resulting html |
|
|
|
%global_count = (); # associate a command name and the |
|
# corresponding counter to the index in the |
|
# html result array |
|
$extract_error_count = 0; |
|
$invalid_counter_count = 0; |
|
%l2h_img = (); # associate src file to destination file |
|
# such that files are not copied twice |
|
$image_count = 1; |
|
|
|
$html_output_count = 0; # html text outputed in html result file |
|
$status = 0; |
|
return if ($Texi2HTML::Config::null_device_file{$Texi2HTML::THISDOC{'filename'}->{'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 "<!-- l2h_begin $l2h_name $count -->\n"; |
|
print L2H_LATEX "\\end{rawhtml}\n"; |
|
|
|
print L2H_LATEX "$text\n"; |
|
|
|
print L2H_LATEX "\\begin{rawhtml}\n"; |
|
print L2H_LATEX "<!-- l2h_end $l2h_name $count -->\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 = <L2H_HTML>) |
|
{ |
|
if ($h_line =~ /!-- l2h_begin $l2h_name ([0-9]+) --/) |
|
{ |
|
$count = $1; |
|
my $h_content = ''; |
|
my $h_end_found = 0; |
|
while ($h_line = <L2H_HTML>) |
|
{ |
|
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 ("<!-- l2h: ". __LINE__ . " undef count for ${style}_$counter -->") |
|
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 ("<!-- l2h: ". __LINE__ . " out of range count $count -->") |
|
if ($debug); |
|
return ''; |
|
} |
|
################################## end debug section (incorrect counts) |
|
|
|
# this seems to be a valid counter |
|
my $result = ''; |
|
$result = "<!-- l2h_begin $l2h_name $count -->" 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 .= "<!-- l2h: ". __LINE__ . " use texi2html -->" if ($debug); |
|
$result .= main::substitute_text({}, undef, 'error in l2h', $l2h_to_latex[$count]); |
|
} |
|
$result .= "<!-- l2h_end $l2h_name $count -->" 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 <file>', |
|
}; |
|
|
|
$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 <docname>.html', |
|
}; |
|
|
|
$T2H_OPTIONS -> {'toc-file'} = |
|
{ |
|
type => '=s', |
|
linkage => \$Texi2HTML::Config::TOC_FILE, |
|
verbose => 'use $s as ToC file, instead of <docname>_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 <docname>', |
|
}; |
|
|
|
$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 <s> 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 <style> output; |
|
read stdin if FILE is -. |
|
--css-ref=URL generate reference to a CSS file. |
|
--internal-links=FILE produce list of internal links in FILE. |
|
--transliterate-file-names |
|
produce file names in ASCII transliteration.\n") |
|
."\n"; |
|
# This is ignored, so remove it from help |
|
#Options for XML and Docbook: |
|
# --output-indent=VAL indent XML elements by VAL spaces (default 2). |
|
# If VAL is 0, ignorable whitespace is dropped. |
|
# |
|
$makeinfo_help .= __("Input file options: |
|
--commands-in-node-names allow \@ commands in node names. |
|
-D VAR define the variable VAR, as with \@set. |
|
-I DIR append DIR to the \@include search path. |
|
-P DIR prepend DIR to the \@include search path. |
|
-U VAR undefine the variable VAR, as with \@clear.\n") |
|
."\n"; |
|
$makeinfo_help .= __("Conditional processing in input: |
|
--ifdocbook process \@ifdocbook and \@docbook even if |
|
not generating Docbook. |
|
--ifhtml process \@ifhtml and \@html even if not generating HTML. |
|
--ifinfo process \@ifinfo even if not generating Info. |
|
--ifplaintext process \@ifplaintext even if not generating plain text. |
|
--iftex process \@iftex and \@tex; implies --no-split. |
|
--ifxml process \@ifxml and \@xml. |
|
--no-ifdocbook do not process \@ifdocbook and \@docbook text. |
|
--no-ifhtml do not process \@ifhtml and \@html text. |
|
--no-ifinfo do not process \@ifinfo text. |
|
--no-ifplaintext do not process \@ifplaintext text. |
|
--no-iftex do not process \@iftex and \@tex text. |
|
--no-ifxml do not process \@ifxml and \@xml text. |
|
|
|
Also, for the --no-ifFORMAT options, do process \@ifnotFORMAT text.\n") |
|
."\n"; |
|
$makeinfo_help .= __(" The defaults for the \@if... conditionals depend on the output format: |
|
if generating HTML, --ifhtml is on and the others are off; |
|
if generating Info, --ifinfo is on and the others are off; |
|
if generating plain text, --ifplaintext is on and the others are off; |
|
if generating XML, --ifxml is on and the others are off.\n") |
|
."\n"; |
|
$makeinfo_help .= __("Examples: |
|
makeinfo foo.texi write Info to foo's \@setfilename |
|
makeinfo --html foo.texi write HTML to \@setfilename |
|
makeinfo --xml foo.texi write Texinfo XML to \@setfilename |
|
makeinfo --docbook foo.texi write DocBook XML to \@setfilename |
|
makeinfo --no-headers foo.texi write plain text to standard output |
|
|
|
makeinfo --html --no-headers foo.texi write html without node lines, menus |
|
makeinfo --number-sections foo.texi write Info with numbered sections |
|
makeinfo --no-split foo.texi write one Info file however big\n") |
|
."\n"; |
|
$makeinfo_help .= __("Email bug reports to bug-texinfo\@gnu.org, |
|
general questions and discussion to help-texinfo\@gnu.org. |
|
Texinfo home page: http://www.gnu.org/software/texinfo/") ."\n"; |
|
|
|
# parsing like texi2html: |
|
|
|
|
|
my $T2H_USAGE_TEXT = <<EOT; |
|
Usage: texi2html [OPTIONS] TEXINFO-FILE |
|
Translates Texinfo source documentation to HTML. |
|
EOT |
|
|
|
|
|
my $options = new Getopt::MySimple; |
|
|
|
$T2H_OPTIONS -> {'help'} = 0; |
|
$T2H_OPTIONS -> {'help|h'} = |
|
{ |
|
type => ':i', |
|
default => '', |
|
linkage => sub {$options->helpOptions($_[1]); |
|
print "\nSend bugs and suggestions to <texi2html-bug\@nongnu.org>\n"; |
|
exit (0);}, |
|
verbose => "print help and exit" |
|
}; |
|
|
|
# this avoids getOptions defining twice 'help' and 'version'. |
|
$T2H_OBSOLETE_OPTIONS->{'help'} = 0; |
|
$T2H_OBSOLETE_OPTIONS->{'version'} = 0; |
|
$T2H_OBSOLETE_OPTIONS->{'verbose'} = 0; |
|
|
|
|
|
if ($real_command_name eq 'texi2html') |
|
{ |
|
# some older version of GetOpt::Long don't have |
|
# Getopt::Long::Configure("pass_through") |
|
eval {Getopt::Long::Configure("pass_through");}; |
|
my $Configure_failed = $@ && <<EOT; |
|
**WARNING: Parsing of obsolete command-line options could have failed. |
|
Consider to use only documented command-line options (run |
|
'texi2html --help 2' for a complete list) or upgrade to perl |
|
version 5.005 or higher. |
|
EOT |
|
if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n")) |
|
{ |
|
print STDERR "$Configure_failed" if $Configure_failed; |
|
die $T2H_FAILURE_TEXT; |
|
} |
|
if (@ARGV > 1) |
|
{ |
|
eval {Getopt::Long::Configure("no_pass_through");}; |
|
if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n")) |
|
{ |
|
print STDERR "$Configure_failed" if $Configure_failed; |
|
die $T2H_FAILURE_TEXT; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# changes how command lines are parsed, for example -init file.init |
|
# doesn't work anymore. |
|
Getopt::Long::Configure("gnu_getopt"); |
|
my $opts; |
|
my @types; |
|
foreach my $key (keys(%$T2H_OPTIONS)) |
|
{ |
|
next unless ($T2H_OPTIONS->{$key}); |
|
my $primary = $key; |
|
$primary =~ s/\|.*//; |
|
next if ($primary eq 'version' or $primary eq 'help'); |
|
next if ($real_command_name eq 'makeinfo' and ! grep {$primary eq $_} (@makeinfo_options, @basic_options) and $primary !~ /^if/); |
|
$opts->{$primary} = $T2H_OPTIONS->{$key}->{'linkage'} if defined($T2H_OPTIONS->{$key}->{'linkage'}); |
|
push @types, "$key$T2H_OPTIONS->{$key}->{'type'}"; |
|
} |
|
$opts->{'version'} = sub { |
|
print "$real_command_name (GNU texinfo) $THISVERSION\n\n"; |
|
|
|
printf __("Copyright (C) %s Free Software Foundation, Inc. |
|
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> |
|
This is free software: you are free to change and redistribute it. |
|
There is NO WARRANTY, to the extent permitted by law.\n"), '2008'; |
|
exit 0; |
|
}; |
|
$opts->{'help'} = sub { |
|
print "$makeinfo_help"; |
|
exit 0; |
|
}; |
|
push @types, ('version|V', 'help|h'); |
|
#foreach my $key (sort(keys(%$opts))) |
|
#{ |
|
# #print STDERR "$key, $opts->{$key}\n"; |
|
# print "$key\n"; |
|
#} |
|
#print STDERR "@types\n"; |
|
my $result_options = Getopt::Long::GetOptions ($opts, @types); |
|
} |
|
|
|
if (! $Texi2HTML::THISDOC{'format_from_command_line'} and defined($ENV{'TEXINFO_OUTPUT_FORMAT'}) and $ENV{'TEXINFO_OUTPUT_FORMAT'} ne '') |
|
{ |
|
if (! Texi2HTML::Config::t2h_default_load_format($ENV{'TEXINFO_OUTPUT_FORMAT'}, 0)) |
|
{ |
|
warn sprintf(__("%s: Ignoring unrecognized TEXINFO_OUTPUT_FORMAT value `%s'.\n"), $real_command_name, $ENV{'TEXINFO_OUTPUT_FORMAT'}); |
|
} |
|
} |
|
|
|
# $T2H_DEBUG and $T2H_VERBOSE are shorthands |
|
$T2H_DEBUG = $Texi2HTML::Config::DEBUG; |
|
$T2H_VERBOSE = $Texi2HTML::Config::VERBOSE; |
|
|
|
# |
|
# read texi2html extensions (if any) |
|
# It is obsolete (obsoleted by -init-file). we keep it for backward |
|
# compatibility. |
|
my $extensions = 'texi2html.ext'; # extensions in working directory |
|
if (-f $extensions) |
|
{ |
|
print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE; |
|
require($extensions); |
|
} |
|
my $progdir; |
|
($progdir = $0) =~ s/[^\/]+$//; |
|
if ($progdir && ($progdir ne './')) |
|
{ |
|
$extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory |
|
if (-f $extensions) |
|
{ |
|
print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE; |
|
require($extensions); |
|
} |
|
} |
|
|
|
|
|
#+++############################################################################ |
|
# # |
|
# evaluation of cmd line options |
|
# # |
|
#---############################################################################ |
|
|
|
# set the default 'args' entry to normal for each style hash (and each command |
|
# within) |
|
my $name_index = -1; |
|
my @hash_names = ('style_map', 'style_map_pre', 'style_map_texi', 'simple_format_style_map_texi'); |
|
foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi) |
|
{ |
|
$name_index++; |
|
my $name = $hash_names[$name_index]; # name associated with hash ref |
|
foreach my $style (keys(%{$hash})) |
|
{ |
|
next unless (ref($hash->{$style}) eq 'HASH'); |
|
$hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'})); |
|
die "Bug: args not defined, but existing, for $style in $name" if (!defined($hash->{$style}->{'args'})); |
|
#print STDERR "DEFAULT($name, $hash) add normal as arg for $style ($hash->{$style}), $hash->{$style}->{'args'}\n"; |
|
} |
|
} |
|
|
|
# setup hashes used for html manual cross references in texinfo |
|
my %cross_ref_texi_map = %Texi2HTML::Config::default_texi_map; |
|
my %cross_transliterate_texi_map = %cross_ref_texi_map; |
|
|
|
my %cross_ref_simple_map_texi = %Texi2HTML::Config::default_simple_map; |
|
$cross_ref_simple_map_texi{"*"} = ' '; |
|
|
|
my %cross_ref_style_map_texi = (); |
|
my %cross_transliterate_style_map_texi = (); |
|
Texi2HTML::Config::t2h_default_copy_style_map(\%Texi2HTML::Config::default_style_map_texi, \%cross_ref_style_map_texi); |
|
Texi2HTML::Config::t2h_default_copy_style_map(\%Texi2HTML::Config::default_style_map_texi, \%cross_transliterate_style_map_texi); |
|
|
|
|
|
|
|
# Fill in the %style_type hash, a hash associating style @-comand with |
|
# the type, 'accent', real 'style', 'simple_style', or 'special'. |
|
# 'simple_style' styles don't extend accross lines. |
|
my %style_type = (); |
|
my @simple_styles = ('ctrl', 'w', 'url','uref','indicateurl','email', |
|
'titlefont'); |
|
foreach my $style (keys(%Texi2HTML::Config::style_map)) |
|
{ |
|
if (exists $Texi2HTML::Config::command_type{$style}) |
|
{ |
|
$style_type{$style} = $Texi2HTML::Config::command_type{$style}; |
|
next; |
|
} |
|
if (ref($Texi2HTML::Config::style_map{$style} eq 'HASH')) |
|
{ |
|
$style_type{$style} = $Texi2HTML::Config::style_map{$style}->{'type'} |
|
if (exists($Texi2HTML::Config::style_map{$style}->{'type'})); |
|
} |
|
else |
|
{ |
|
$style_type{$style} = 'simple_style' if (grep {$_ eq $style} @simple_styles); |
|
} |
|
$style_type{$style} = 'style' unless (defined($style_type{$style})); |
|
} |
|
|
|
foreach my $accent (keys(%Texi2HTML::Config::unicode_accents), 'tieaccent', 'dotless') |
|
{ |
|
if (exists $Texi2HTML::Config::command_type{$accent}) |
|
{ |
|
$style_type{$accent} = $Texi2HTML::Config::command_type{$accent}; |
|
next; |
|
} |
|
$style_type{$accent} = 'accent'; |
|
} |
|
|
|
|
|
|
|
|
|
foreach my $special ('footnote', 'ref', 'xref', 'pxref', 'inforef', 'anchor', 'image', 'hyphenation') |
|
{ |
|
if (exists $Texi2HTML::Config::command_type{$special}) |
|
{ |
|
$style_type{$special} = $Texi2HTML::Config::command_type{$special}; |
|
next; |
|
} |
|
$style_type{$special} = 'special'; |
|
} |
|
|
|
# retro compatibility for $Texi2HTML::Config::EXPAND |
|
push (@Texi2HTML::Config::EXPAND, $Texi2HTML::Config::EXPAND) if ($Texi2HTML::Config::EXPAND); |
|
|
|
push (@Texi2HTML::Config::EXPAND, @Texi2HTML::Config::T2H_FORMAT_EXPAND); |
|
|
|
# correct %Texi2HTML::Config::texi_formats_map based on command line and init |
|
# variables |
|
$Texi2HTML::Config::texi_formats_map{'menu'} = 'normal' if ($Texi2HTML::Config::SHOW_MENU); |
|
|
|
foreach my $expanded (@Texi2HTML::Config::EXPAND) |
|
{ |
|
$Texi2HTML::Config::texi_formats_map{"if$expanded"} = 1 if (exists($Texi2HTML::Config::texi_formats_map{"if$expanded"})); |
|
next unless (exists($Texi2HTML::Config::texi_formats_map{$expanded})); |
|
if (grep {$_ eq $expanded} @raw_regions) |
|
{ |
|
$Texi2HTML::Config::texi_formats_map{$expanded} = 'raw'; |
|
} |
|
else |
|
{ |
|
$Texi2HTML::Config::texi_formats_map{$expanded} = 'normal'; |
|
} |
|
} |
|
|
|
# don't set set_no_line_macro for raw EXPAND formats |
|
foreach my $key (keys(%Texi2HTML::Config::texi_formats_map)) |
|
{ |
|
unless ($Texi2HTML::Config::texi_formats_map{$key} eq 'raw') |
|
{ |
|
set_no_line_macro($key, 1); |
|
set_no_line_macro("end $key", 1); |
|
} |
|
} |
|
|
|
# the remaining (not in @EXPAND) raw formats are set as 'raw' such that |
|
# they are propagated to formatting functions, but |
|
# they don't start paragraphs or preformatted. |
|
foreach my $raw (@raw_regions) |
|
{ |
|
if (!defined($Texi2HTML::Config::texi_formats_map{$raw})) |
|
{ |
|
$Texi2HTML::Config::texi_formats_map{$raw} = 'raw'; |
|
$Texi2HTML::Config::format_in_paragraph{$raw} = 1; |
|
set_no_line_macro($raw, 1); |
|
set_no_line_macro("end $raw", 1); |
|
} |
|
} |
|
|
|
# handle ifnot regions |
|
foreach my $region (keys (%Texi2HTML::Config::texi_formats_map)) |
|
{ |
|
next if ($region =~ /^ifnot/); |
|
if ($Texi2HTML::Config::texi_formats_map{$region} and $region =~ /^if(\w+)$/) |
|
{ |
|
$Texi2HTML::Config::texi_formats_map{"ifnot$1"} = 0; |
|
} |
|
} |
|
|
|
if ($T2H_VERBOSE) |
|
{ |
|
print STDERR "# Expanded: "; |
|
foreach my $text_macro (keys(%Texi2HTML::Config::texi_formats_map)) |
|
{ |
|
print STDERR "$text_macro " if ($Texi2HTML::Config::texi_formats_map{$text_macro}); |
|
} |
|
print STDERR "\n"; |
|
} |
|
|
|
# This is kept in that file although it is html formatting as it seems to |
|
# be rather obsolete |
|
$Texi2HTML::Config::INVISIBLE_MARK = '<img src="invisible.xbm" alt="">' if $Texi2HTML::Config::INVISIBLE_MARK eq 'xbm'; |
|
|
|
$T2H_DEBUG |= $DEBUG_TEXI if ($Texi2HTML::Config::DUMP_TEXI); |
|
|
|
# no user provided USE_UNICODE, use configure provided |
|
if (!defined($Texi2HTML::Config::USE_UNICODE)) |
|
{ |
|
$Texi2HTML::Config::USE_UNICODE = 'unknown'; |
|
} |
|
|
|
# no user provided nor configured, run time test |
|
if ($Texi2HTML::Config::USE_UNICODE eq 'unknown' or $Texi2HTML::Config::USE_UNICODE eq '@' .'USE_UNICODE@') |
|
{ |
|
eval { |
|
require Encode; |
|
require Unicode::Normalize; |
|
Encode->import('encode'); |
|
}; |
|
if ($@) |
|
{ |
|
$Texi2HTML::Config::USE_UNICODE = 0 |
|
} |
|
else |
|
{ |
|
$Texi2HTML::Config::USE_UNICODE = 1; |
|
} |
|
} |
|
|
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
require Encode; |
|
require Unicode::Normalize; |
|
Encode->import('encode'); |
|
|
|
# use EastAsianWidth if USE_UNICODE is set |
|
if ($0 =~ /\.pl$/) |
|
{ # use in-source EastAsianWidth when testing |
|
unshift @INC, "$T2H_HOME/lib/Unicode-EastAsianWidth/lib"; |
|
} |
|
elsif ($ENV{T2H_SOURCE_EASTASIANWIDTH}) |
|
{ |
|
unshift @INC, $ENV{T2H_SOURCE_EASTASIANWIDTH}; |
|
} |
|
elsif ('no' ne 'yes') |
|
{ |
|
unshift @INC, "$pkgdatadir/lib/Unicode-EastAsianWidth/lib"; |
|
} |
|
else |
|
{ |
|
eval { |
|
require Unicode::EastAsianWidth; |
|
}; |
|
if ($@) |
|
{ |
|
unshift @INC, "$pkgdatadir/lib/Unicode-EastAsianWidth/lib"; |
|
} |
|
} |
|
# unicode east asian character width tables. |
|
require Unicode::EastAsianWidth; |
|
} |
|
|
|
# no user provided USE_UNIDECODE, use configure provided |
|
if (!defined($Texi2HTML::Config::USE_UNIDECODE)) |
|
{ |
|
$Texi2HTML::Config::USE_UNIDECODE = 'unknown'; |
|
} |
|
|
|
# no user provided nor configured, run time test |
|
if ($Texi2HTML::Config::USE_UNIDECODE eq 'unknown' or $Texi2HTML::Config::USE_UNIDECODE eq '@' .'USE_UNIDECODE@') |
|
{ |
|
$Texi2HTML::Config::USE_UNIDECODE = 1; |
|
eval { |
|
require Text::Unidecode; |
|
Text::Unidecode->import('unidecode'); |
|
}; |
|
$Texi2HTML::Config::USE_UNIDECODE = 0 if ($@); |
|
} |
|
|
|
if ($Texi2HTML::Config::USE_UNIDECODE) |
|
{ |
|
require Text::Unidecode; |
|
Text::Unidecode->import('unidecode'); |
|
} |
|
|
|
print STDERR "# USE_UNICODE $Texi2HTML::Config::USE_UNICODE, USE_UNIDECODE $Texi2HTML::Config::USE_UNIDECODE \n" |
|
if ($T2H_VERBOSE); |
|
|
|
# Construct hashes used for cross references generation |
|
# Do it now as the user may have changed $USE_UNICODE |
|
|
|
foreach my $key (keys(%Texi2HTML::Config::unicode_map)) |
|
{ |
|
if ($Texi2HTML::Config::unicode_map{$key} ne '') |
|
{ |
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
my $char_nr = hex($Texi2HTML::Config::unicode_map{$key}); |
|
#$cross_ref_texi_map{$key} = chr(hex($Texi2HTML::Config::unicode_map{$key})); |
|
#$cross_ref_texi_map{$key} = pack("U0U*",hex($Texi2HTML::Config::unicode_map{$key})); |
|
if ($char_nr > 126 and $char_nr < 255) |
|
{ |
|
$cross_ref_texi_map{$key} = Encode::decode("iso-8859-1", chr($char_nr)); |
|
} |
|
else |
|
{ |
|
$cross_ref_texi_map{$key} = chr($char_nr); |
|
} |
|
# cross_transliterate_texi_map is only used if |
|
# USE_UNIDECODE is unset and TRANSLITERATE_FILE_NAMES is set |
|
if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}})) |
|
{ |
|
$cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}; |
|
} |
|
else |
|
{ |
|
$cross_transliterate_texi_map{$key} = $cross_ref_texi_map{$key}; |
|
} |
|
} |
|
else |
|
{ |
|
$cross_ref_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key}); |
|
# cross_transliterate_texi_map is used if TRANSLITERATE_FILE_NAMES is set |
|
if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}})) |
|
{ |
|
$cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}; |
|
} |
|
else |
|
{ |
|
$cross_transliterate_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key}); |
|
} |
|
} |
|
} |
|
} |
|
#if ($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::TRANSLITERATE_FILE_NAMES |
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES and ( |
|
($Texi2HTML::Config::USE_UNICODE and ! $Texi2HTML::Config::USE_UNIDECODE) |
|
or !$Texi2HTML::Config::USE_UNICODE)) |
|
{ |
|
foreach my $key (keys (%Texi2HTML::Config::transliterate_accent_map)) |
|
{ |
|
$Texi2HTML::Config::transliterate_map{$key} = $Texi2HTML::Config::transliterate_accent_map{$key}; |
|
} |
|
} |
|
|
|
foreach my $key (keys(%cross_ref_style_map_texi)) |
|
{ |
|
if ($style_type{$key} eq 'accent' |
|
and (ref($cross_ref_style_map_texi{$key}) eq 'HASH')) |
|
{ |
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
$cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_utf8_accent; |
|
} |
|
else |
|
{ |
|
$cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_nounicode_cross_manual_accent; |
|
} |
|
# this is only used if TRANSLITERATE_FILE_NAMES is set and USE_UNICODE |
|
# or USE_UNIDECODE is not set |
|
$cross_transliterate_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_transliterate_cross_manual_accent; |
|
} |
|
} |
|
|
|
if ($Texi2HTML::Config::L2H and defined($Texi2HTML::Config::OUTPUT_FORMAT) and $Texi2HTML::Config::OUTPUT_FORMAT eq 'html') |
|
{ |
|
push @Texi2HTML::Config::command_handler_init, \&Texi2HTML::LaTeX2HTML::init; |
|
push @Texi2HTML::Config::command_handler_process, \&Texi2HTML::LaTeX2HTML::latex2html; |
|
# do it here once to have something ready for special regions |
|
push @Texi2HTML::Config::command_handler_process, \&Texi2HTML::LaTeX2HTML::init_from_html; |
|
# do it here once more in case the file was modified (see mediawiki.init) |
|
push @Texi2HTML::Config::command_handler_output, \&Texi2HTML::LaTeX2HTML::init_from_html; |
|
push @Texi2HTML::Config::command_handler_finish, \&Texi2HTML::LaTeX2HTML::finish; |
|
$Texi2HTML::Config::command_handler{'math'} = |
|
{ 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, |
|
'expand' => \&Texi2HTML::LaTeX2HTML::do_tex |
|
}; |
|
$Texi2HTML::Config::command_handler{'tex'} = |
|
{ 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, |
|
'expand' => \&Texi2HTML::LaTeX2HTML::do_tex |
|
}; |
|
} |
|
|
|
if ($Texi2HTML::Config::ENABLE_ENCODING) |
|
{ |
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
Texi2HTML::Config::t2h_enable_encoding_load(); |
|
} |
|
else |
|
{ # FIXME: only warn if ENABLE_ENCODING is set on the command line |
|
#warn "** --enable-encoding requires utf-8 support\n"; |
|
} |
|
} |
|
|
|
# for all files. This won't be overriden by @documentencoding, this is not |
|
# what is done in general. |
|
Texi2HTML::Config::set_conf('IN_ENCODING', $Texi2HTML::Config::IN_ENCODING); |
|
Texi2HTML::Config::set_conf('DOCUMENT_ENCODING', $Texi2HTML::Config::DOCUMENT_ENCODING); |
|
|
|
# Backward compatibility for deprecated $Texi2HTML::Config::ENCODING |
|
$Texi2HTML::Config::ENCODING_NAME = $Texi2HTML::Config::ENCODING |
|
if (!defined($Texi2HTML::Config::ENCODING_NAME) and defined($Texi2HTML::Config::ENCODING)); |
|
|
|
# APA: There's got to be a better way: |
|
if ($Texi2HTML::Config::TEST) |
|
{ |
|
# to generate files similar to reference ones to be able to check for |
|
# real changes we use these dummy values if -test is given |
|
$THISPROG = 'texi2html'; |
|
setlocale( LC_ALL, "C" ); |
|
} |
|
|
|
$Texi2HTML::GLOBAL{'debug_l2h'} = 1 if ($T2H_DEBUG & $DEBUG_L2H); |
|
|
|
# parse texinfo cnf file for external manual specifications. This was |
|
# discussed on texinfo list but not in makeinfo for now. |
|
my @texinfo_htmlxref_files = locate_init_file ($texinfo_htmlxref, 1, \@texinfo_config_dirs); |
|
|
|
foreach my $file (@texinfo_htmlxref_files) |
|
{ |
|
print STDERR "html refs config file: $file\n" if ($T2H_DEBUG); |
|
unless (open (HTMLXREF, $file)) |
|
{ |
|
document_warn("Cannot open html refs config file ${file}: $!"); |
|
next; |
|
} |
|
my $line_nr = 0; |
|
my %variables; |
|
while (my $hline = <HTMLXREF>) |
|
{ |
|
my $line = $hline; |
|
$line_nr++; |
|
next if $hline =~ /^\s*#/; |
|
#$hline =~ s/[#]\s.*//; |
|
$hline =~ s/^\s*//; |
|
next if $hline =~ /^\s*$/; |
|
chomp ($hline); |
|
if ($hline =~ s/^(\w+)\s*=\s*//) |
|
{ |
|
# handle variables |
|
my $var = $1; |
|
my $re = join '|', map { quotemeta $_ } keys %variables; |
|
$hline =~ s/\$\{($re)\}/defined $variables{$1} ? $variables{$1} : "\${$1}"/ge; |
|
$variables{$var} = $hline; |
|
next; |
|
} |
|
my @htmlxref = split /\s+/, $hline; |
|
my $manual = shift @htmlxref; |
|
my $split_or_mono = shift @htmlxref; |
|
#print STDERR "$split_or_mono $Texi2HTML::Config::htmlxref_entries{$split_or_mono} $line_nr\n"; |
|
if (!defined($split_or_mono)) |
|
{ |
|
file_line_warn(__("Missing type"), $file, $line_nr); |
|
next; |
|
} |
|
elsif (!defined($Texi2HTML::Config::htmlxref_entries{$split_or_mono})) |
|
{ |
|
file_line_warn(sprintf(__("Unrecognized type: %s"), $split_or_mono), $file, $line_nr); |
|
next; |
|
} |
|
my $href = shift @htmlxref; |
|
next if (exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}) and exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'})); |
|
|
|
if (defined($href)) |
|
{ |
|
my $re = join '|', map { quotemeta $_ } keys %variables; |
|
$href =~ s/\$\{($re)\}/defined $variables{$1} ? $variables{$1} : "\${$1}"/ge; |
|
$href =~ s/\/*$// if ($split_or_mono ne 'mono'); |
|
$Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'} = $href; |
|
} |
|
else |
|
{ |
|
$Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split_or_mono} = {}; |
|
} |
|
} |
|
close (HTMLXREF); |
|
} |
|
|
|
if ($T2H_DEBUG) |
|
{ |
|
foreach my $manual (keys(%{$Texi2HTML::GLOBAL{'htmlxref'}})) |
|
{ |
|
foreach my $split (keys(%Texi2HTML::Config::htmlxref_entries)) |
|
{ |
|
my $href = 'NO'; |
|
next unless (exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split})); |
|
$href = $Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split}->{'href'} if |
|
exists($Texi2HTML::GLOBAL{'htmlxref'}->{$manual}->{$split}->{'href'}); |
|
print STDERR "$manual: $split, href: $href\n"; |
|
} |
|
} |
|
} |
|
|
|
# resulting files splitting |
|
if ($Texi2HTML::Config::SPLIT =~ /section/i) |
|
{ |
|
$Texi2HTML::Config::SPLIT = 'section'; |
|
} |
|
elsif ($Texi2HTML::Config::SPLIT =~ /node/i) |
|
{ |
|
$Texi2HTML::Config::SPLIT = 'node'; |
|
} |
|
elsif ($Texi2HTML::Config::SPLIT =~ /chapter/i) |
|
{ |
|
$Texi2HTML::Config::SPLIT = 'chapter'; |
|
} |
|
else |
|
{ |
|
$Texi2HTML::Config::SPLIT = ''; |
|
} |
|
|
|
$Texi2HTML::Config::SPLIT_INDEX = 0 unless $Texi2HTML::Config::SPLIT; |
|
$Texi2HTML::Config::NODE_FILENAMES = 1 if ((!defined($Texi2HTML::Config::NODE_FILENAMES) and $Texi2HTML::Config::SPLIT eq 'node') or $Texi2HTML::Config::NODE_FILES); |
|
|
|
# Something like backward compatibility. This would make sense to keep |
|
# it ad-infinitum since the meaning of --out and --subdir are different. |
|
if ($Texi2HTML::Config::SPLIT and defined($Texi2HTML::Config::SUBDIR) |
|
and ($Texi2HTML::Config::SUBDIR ne '') and |
|
(!defined($Texi2HTML::Config::OUT) or ($Texi2HTML::Config::OUT eq ''))) |
|
{ |
|
$Texi2HTML::Config::OUT = $Texi2HTML::Config::SUBDIR; |
|
} |
|
|
|
die "output to STDOUT and split or frames incompatible\n" |
|
if (($Texi2HTML::Config::SPLIT or $Texi2HTML::Config::FRAMES) and defined($Texi2HTML::Config::OUT) and $Texi2HTML::Config::OUT eq '-'); |
|
|
|
if ($Texi2HTML::Config::SPLIT and defined($Texi2HTML::Config::OUT) and ($Texi2HTML::Config::OUT eq '.')) |
|
{# This is to avoid trouble with latex2html |
|
$Texi2HTML::Config::OUT = ''; |
|
} |
|
|
|
@Texi2HTML::Config::INCLUDE_DIRS = split(/$quoted_path_separator/,join($path_separator,@Texi2HTML::Config::INCLUDE_DIRS)); |
|
@Texi2HTML::Config::PREPEND_DIRS = split(/$quoted_path_separator/,join($path_separator,@Texi2HTML::Config::PREPEND_DIRS)); |
|
|
|
my @include_dirs_orig = @Texi2HTML::Config::INCLUDE_DIRS; |
|
|
|
@Texi2HTML::Config::CONF_DIRS = split(/$quoted_path_separator/,join($path_separator,@Texi2HTML::Config::CONF_DIRS)); |
|
# extension |
|
$Texi2HTML::GLOBAL{'extension'} = $Texi2HTML::Config::EXTENSION; |
|
if ($Texi2HTML::Config::SHORTEXTN) |
|
{ |
|
$Texi2HTML::GLOBAL{'extension'} = "htm"; |
|
} |
|
|
|
my $global_pass; # track the phases of processing for debugging output purposes |
|
|
|
# |
|
# file name business |
|
# |
|
|
|
my @created_directories = (); |
|
|
|
my $docu_dir; # directory of the document |
|
my $docu_name; # basename of the document |
|
my $docu_rdir; # directory for the output |
|
my $docu_toc; # document's table of contents |
|
my $docu_stoc; # document's short toc |
|
my $docu_foot; # document's footnotes |
|
my $docu_about; # about this document |
|
my $docu_top; # document top |
|
my $docu_doc; # document (or document top of split) |
|
my $docu_frame; # main frame file |
|
my $docu_toc_frame; # toc frame file |
|
my $path_to_working_dir; # relative path leading to the working |
|
# directory from the document directory |
|
my $docu_doc_file; |
|
my $docu_toc_file; |
|
my $docu_stoc_file; |
|
my $docu_foot_file; |
|
my $docu_about_file; |
|
my $docu_top_file; |
|
my $docu_frame_file; |
|
my $docu_toc_frame_file; |
|
|
|
sub set_docu_names($$) |
|
{ |
|
my $docu_base_name = shift; |
|
my $file_nr = shift; |
|
if ($docu_base_name =~ /(.*\/)/) |
|
{ |
|
$docu_dir = $1; |
|
chop($docu_dir); |
|
$docu_name = $docu_base_name; |
|
$docu_name =~ s/.*\///; |
|
} |
|
else |
|
{ |
|
$docu_dir = '.'; |
|
$docu_name = $docu_base_name; |
|
} |
|
|
|
@Texi2HTML::Config::INCLUDE_DIRS = @include_dirs_orig; |
|
my @prependended_include_directories = ('.'); |
|
push @prependended_include_directories, $Texi2HTML::THISDOC{'input_directory'} if ($Texi2HTML::THISDOC{'input_directory'} ne '.'); |
|
# as Karl said, adding the destination directory is confusing. |
|
#push @prependended_include_directories, $docu_dir if ($docu_dir ne '.' and $docu_dir ne $Texi2HTML::THISDOC{'input_directory'}); |
|
unshift(@Texi2HTML::Config::INCLUDE_DIRS, @prependended_include_directories); |
|
unshift(@Texi2HTML::Config::INCLUDE_DIRS, @Texi2HTML::Config::PREPEND_DIRS); |
|
# AAAA |
|
if ($Texi2HTML::Config::PREFIX and ($file_nr == 0)) |
|
{ |
|
$docu_name = $Texi2HTML::Config::PREFIX; |
|
} |
|
elsif ($docu_name eq '-') |
|
{ |
|
$docu_name = $Texi2HTML::Config::STDIN_DOCU_NAME; |
|
} |
|
|
|
# subdir |
|
$docu_rdir = ''; |
|
my $null_output; |
|
if (defined($Texi2HTML::Config::OUT) and ($file_nr == 0) and $Texi2HTML::Config::null_device_file{$Texi2HTML::Config::OUT}) |
|
{ # this overrides the setting for this file. |
|
$Texi2HTML::THISDOC{'SPLIT'} = ''; |
|
$Texi2HTML::THISDOC{'SPLIT_SIZE'} = undef; |
|
$null_output = 1; |
|
$path_to_working_dir = $docu_rdir; |
|
} |
|
if (!$null_output) |
|
{ |
|
if (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
if (defined($Texi2HTML::Config::OUT) and ($file_nr == 0)) |
|
{ |
|
$docu_rdir = $Texi2HTML::Config::OUT; |
|
} |
|
else |
|
{ |
|
$docu_rdir = $docu_name; |
|
} |
|
if ($docu_rdir ne '') |
|
{ |
|
$docu_rdir =~ s|/*$||; |
|
$docu_rdir .= '/'; |
|
} |
|
} |
|
else |
|
{ |
|
my $out_file; |
|
# AAAA |
|
# even if the out file is not set by OUT, in case it is not the first |
|
# file, the out directory is still used. This is only used to determine |
|
# the directory, the out file itself is set below |
|
if (defined($Texi2HTML::Config::OUT) and $Texi2HTML::Config::OUT ne '') |
|
{ |
|
$out_file = $Texi2HTML::Config::OUT; |
|
} |
|
else |
|
{ |
|
$out_file = $docu_name; |
|
} |
|
|
|
if ($out_file =~ m|(.*)/|) |
|
{# there is a leading directories |
|
$docu_rdir = "$1/"; |
|
} |
|
} |
|
|
|
if ($docu_rdir ne '') |
|
{ |
|
unless (-d $docu_rdir) |
|
{ |
|
if ( mkdir($docu_rdir, oct(755))) |
|
{ |
|
print STDERR "# created directory $docu_rdir\n" if ($T2H_VERBOSE); |
|
push @created_directories, $docu_rdir; |
|
} |
|
else |
|
{ |
|
document_error (sprintf(__("Can't create directory `%s': %s"), $docu_rdir, $!), 1); |
|
} |
|
} |
|
print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE); |
|
} |
|
else |
|
{ |
|
print STDERR "# putting result files into current directory \n" if ($T2H_VERBOSE); |
|
} |
|
# We don't use "./" as $docu_rdir when $docu_rdir is the current directory |
|
# because it is problematic for latex2html. To test writability with -w, |
|
# however we need a real directory. |
|
my $result_rdir = $docu_rdir; |
|
$result_rdir = "." if ($docu_rdir eq ''); |
|
unless (-w $result_rdir) |
|
{ |
|
$docu_rdir = 'current directory' if ($docu_rdir eq ''); |
|
document_error ("$docu_rdir not writable", 1); |
|
} |
|
|
|
# relative path leading to the working directory from the document directory |
|
$path_to_working_dir = $docu_rdir; |
|
if ($docu_rdir ne '') |
|
{ |
|
my $cwd = cwd; |
|
my $docu_path = $docu_rdir; |
|
$docu_path = $cwd . '/' . $docu_path unless ($docu_path =~ /^\//); |
|
my @result = (); |
|
# this code simplify the paths. The cwd is absolute, while in the |
|
# document path there may be some .., a .. is removed with the |
|
# previous path element, such that something like |
|
# /cwd/directory/../somewhere/ |
|
# leads to |
|
# /cwd/somewhere/ |
|
# with directory/.. removed |
|
foreach my $element (split /\//, File::Spec->canonpath($docu_path)) |
|
{ |
|
if ($element eq '') |
|
{ |
|
push @result, ''; |
|
} |
|
elsif ($element eq '..') |
|
{ |
|
if (@result and ($result[-1] eq '')) |
|
{ |
|
print STDERR "Too much .. in absolute file name\n"; |
|
} |
|
elsif (@result and ($result[-1] ne '..')) |
|
{ |
|
pop @result; |
|
} |
|
else |
|
{ |
|
push @result, $element; |
|
} |
|
} |
|
else |
|
{ |
|
push @result, $element; |
|
} |
|
} |
|
$path_to_working_dir = File::Spec->abs2rel($cwd, join ('/', @result)); |
|
# this should not be needed given what canonpath does |
|
$path_to_working_dir =~ s:/*$::; |
|
$path_to_working_dir .= '/' unless($path_to_working_dir eq ''); |
|
} |
|
} |
|
|
|
my $docu_ext = $Texi2HTML::THISDOC{'extension'}; |
|
# out_dir is undocummented, should never be used, use destination_directory |
|
$Texi2HTML::THISDOC{'out_dir'} = $docu_rdir; |
|
|
|
$Texi2HTML::THISDOC{'destination_directory'} = $docu_rdir; |
|
$Texi2HTML::THISDOC{'file_base_name'} = $docu_name; |
|
|
|
$docu_doc = $docu_name . (defined($docu_ext) ? ".$docu_ext" : ""); # document's contents |
|
if (Texi2HTML::Config::get_conf('SPLIT') and $Texi2HTML::Config::NODE_FILENAMES) |
|
{ |
|
if (defined($Texi2HTML::Config::TOP_NODE_FILE)) |
|
{ |
|
$docu_doc = $Texi2HTML::Config::TOP_NODE_FILE; |
|
if (defined($Texi2HTML::Config::NODE_FILE_EXTENSION) and $Texi2HTML::Config::NODE_FILE_EXTENSION ne '') |
|
{ |
|
$docu_doc .= ".$Texi2HTML::Config::NODE_FILE_EXTENSION"; |
|
} |
|
} |
|
} |
|
if (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
# AAAA |
|
if (defined($Texi2HTML::Config::TOP_FILE) and ($Texi2HTML::Config::TOP_FILE ne '') and ($file_nr == 0)) |
|
{ |
|
$docu_top = $Texi2HTML::Config::TOP_FILE; |
|
} |
|
} |
|
else |
|
{ |
|
# AAAA |
|
if (defined($Texi2HTML::Config::OUT) and ($file_nr == 0)) |
|
{ |
|
my $out_file = $Texi2HTML::Config::OUT; |
|
if ($out_file eq '-') |
|
{ |
|
$Texi2HTML::THISDOC{'SPLIT'} = ''; |
|
$Texi2HTML::THISDOC{'SPLIT_SIZE'} = undef; |
|
} |
|
$out_file =~ s|.*/|| unless ($null_output); |
|
$docu_doc = $out_file if ($out_file !~ /^\s*$/); |
|
} |
|
} |
|
|
|
if (defined $Texi2HTML::Config::element_file_name) |
|
{ |
|
my $docu_doc_set = &$Texi2HTML::Config::element_file_name |
|
(undef, 'doc', $docu_name); |
|
$docu_doc = $docu_doc_set if (defined($docu_doc_set)); |
|
} |
|
$docu_top = $docu_doc if (!defined($docu_top)); |
|
|
|
if (Texi2HTML::Config::get_conf('SPLIT') or !$Texi2HTML::Config::MONOLITHIC) |
|
{ |
|
if (defined $Texi2HTML::Config::element_file_name) |
|
{ |
|
$docu_toc = &$Texi2HTML::Config::element_file_name |
|
(undef, 'toc', $docu_name); |
|
$docu_stoc = &$Texi2HTML::Config::element_file_name |
|
(undef, 'stoc', $docu_name); |
|
$docu_foot = &$Texi2HTML::Config::element_file_name |
|
(undef, 'foot', $docu_name); |
|
$docu_about = &$Texi2HTML::Config::element_file_name |
|
(undef, 'about', $docu_name); |
|
# $docu_top may be overwritten later. |
|
} |
|
if (!defined($docu_toc)) |
|
{ |
|
my $default_toc = "${docu_name}_toc"; |
|
$default_toc .= ".$docu_ext" if (defined($docu_ext)); |
|
# AAAA |
|
if (defined($Texi2HTML::Config::TOC_FILE) and ($Texi2HTML::Config::TOC_FILE ne '') and ($file_nr == 0)) |
|
{ |
|
$docu_toc = $Texi2HTML::Config::TOC_FILE; |
|
} |
|
else |
|
{ |
|
$docu_toc = $default_toc; |
|
} |
|
} |
|
if (!defined($docu_stoc)) |
|
{ |
|
$docu_stoc = "${docu_name}_ovr"; |
|
$docu_stoc .= ".$docu_ext" if (defined($docu_ext)); |
|
} |
|
if (!defined($docu_foot)) |
|
{ |
|
$docu_foot = "${docu_name}_fot"; |
|
$docu_foot .= ".$docu_ext" if (defined($docu_ext)); |
|
} |
|
if (!defined($docu_about)) |
|
{ |
|
$docu_about = "${docu_name}_abt"; |
|
$docu_about .= ".$docu_ext" if (defined($docu_ext)); |
|
} |
|
} |
|
else |
|
{ |
|
$docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_doc; |
|
} |
|
|
|
# Note that file extension has already been added here. |
|
if ($Texi2HTML::Config::FRAMES) |
|
{ |
|
if (defined $Texi2HTML::Config::element_file_name) |
|
{ |
|
$docu_frame = &$Texi2HTML::Config::element_file_name |
|
(undef, 'frame', $docu_name); |
|
$docu_toc_frame = &$Texi2HTML::Config::element_file_name |
|
(undef, 'toc_frame', $docu_name); |
|
} |
|
} |
|
|
|
if (!defined($docu_frame)) |
|
{ |
|
$docu_frame = "${docu_name}_frame"; |
|
$docu_frame .= ".$docu_ext" if (defined($docu_ext)); |
|
} |
|
if (!defined($docu_toc_frame)) |
|
{ |
|
$docu_toc_frame = "${docu_name}_toc_frame"; |
|
$docu_toc_frame .= ".$docu_ext" if (defined($docu_ext)); |
|
} |
|
|
|
if ($T2H_VERBOSE) |
|
{ |
|
print STDERR "# Files and directories:\n"; |
|
print STDERR "# rdir($docu_rdir) path_to_working_dir($path_to_working_dir)\n"; |
|
print STDERR "# doc($docu_doc) top($docu_top) toc($docu_toc) stoc($docu_stoc)\n"; |
|
print STDERR "# foot($docu_foot) about($docu_about) frame($docu_toc) toc_frame($docu_toc_frame)\n"; |
|
} |
|
|
|
$docu_doc_file = "$docu_rdir$docu_doc"; |
|
$docu_toc_file = "$docu_rdir$docu_toc"; |
|
$docu_stoc_file = "$docu_rdir$docu_stoc"; |
|
$docu_foot_file = "$docu_rdir$docu_foot"; |
|
$docu_about_file = "$docu_rdir$docu_about"; |
|
$docu_top_file = "$docu_rdir$docu_top"; |
|
$docu_frame_file = "$docu_rdir$docu_frame"; |
|
$docu_toc_frame_file = "$docu_rdir$docu_toc_frame"; |
|
|
|
# For use in init files |
|
$Texi2HTML::THISDOC{'filename'}->{'top'} = $docu_top; |
|
$Texi2HTML::THISDOC{'filename'}->{'foot'} = $docu_foot; |
|
$Texi2HTML::THISDOC{'filename'}->{'stoc'} = $docu_stoc; |
|
$Texi2HTML::THISDOC{'filename'}->{'about'} = $docu_about; |
|
$Texi2HTML::THISDOC{'filename'}->{'toc'} = $docu_toc; |
|
$Texi2HTML::THISDOC{'filename'}->{'toc_frame'} = $docu_toc_frame; |
|
$Texi2HTML::THISDOC{'filename'}->{'frame'} = $docu_frame; |
|
} |
|
|
|
sub var_to_str($) |
|
{ |
|
return 'UNDEF' if (!defined($_[0])); |
|
return $_[0]; |
|
} |
|
|
|
# |
|
# Common initializations |
|
# |
|
|
|
sub texinfo_initialization($) |
|
{ |
|
my $pass = shift; |
|
|
|
# set the translations now. This means at the beginning of each pass. |
|
# Do it silently, except during the last pass. |
|
my $lang = Texi2HTML::Config::get_conf('documentlanguage'); |
|
my $silent_lang = 1 if ($pass != 2); |
|
if (!set_document_language($lang, $silent_lang)) |
|
{ |
|
document_warn ("Translations for '$lang' not found. Using 'en'.") unless ($silent_lang); |
|
set_document_language('en', $silent_lang); |
|
} |
|
# All the initialization used the informations still there at the |
|
# end of the previous pass. |
|
# Now we reset everything, such that things are used when they happen. |
|
# also reset the @set/@clear values. |
|
%value = %value_initial; |
|
foreach my $init_mac ('everyheading', 'everyfooting', 'evenheading', |
|
'evenfooting', 'oddheading', 'oddfooting', 'headings', |
|
'allowcodebreaks', 'frenchspacing', 'exampleindent', |
|
'firstparagraphindent', 'paragraphindent', 'clickstyle', |
|
'novalidate', 'documentlanguage') |
|
{ |
|
Texi2HTML::Config::set_conf($init_mac, undef, 1); |
|
} |
|
} |
|
|
|
#+++########################################################################### |
|
# # |
|
# Pass texi: read source, handle variable, ignored text, # |
|
# # |
|
#---########################################################################### |
|
|
|
#my @lines = (); # whole document |
|
#my @lines_numbers = (); # line number, originating file associated with |
|
# whole document |
|
my $macros = undef; # macros. reference on a hash |
|
my %info_enclose = (); # macros defined with definfoenclose |
|
my @floats = (); # floats list |
|
my %floats = (); # floats by style |
|
|
|
sub initialise_state_texi($) |
|
{ |
|
my $state = shift; |
|
$state->{'texi'} = 1; # for substitute_text and close_stack: |
|
# 1 if pass_texi/scan_texi is to be used |
|
$state->{'macro_inside'} = 0 unless(defined($state->{'macro_inside'})); |
|
$state->{'ifvalue_inside'} = 0 unless(defined($state->{'ifvalue_inside'})); |
|
$state->{'arg_expansion'} = 0 unless(defined($state->{'arg_expansion'})); |
|
$state->{'files_stack'} = [] unless(defined($state->{'files_stack'})); |
|
} |
|
|
|
|
|
sub pass_texi($) |
|
{ |
|
my $input_file_name = shift; |
|
#my $texi_line_number = { 'file_name' => '', 'line_nr' => 0, 'macro' => '' }; |
|
|
|
my @lines = (); # whole document |
|
my @lines_numbers = (); # line number, originating file associated with |
|
# whole document |
|
my @first_lines = (); |
|
my $first_lines = 1; # is it the first lines |
|
my $state = {}; |
|
# holds the informations about the context |
|
# to pass it down to the functions |
|
my @command_line_lines = @Texi2HTML::Config::COMMANDS; |
|
initialise_state_texi($state); |
|
my $texi_line_number; |
|
($texi_line_number, $state->{'input_spool'}) = |
|
open_file($input_file_name, '', $state->{'files_stack'}); |
|
my @stack; |
|
my $text; |
|
my $cline; |
|
INPUT_LINE: while (1) |
|
{ |
|
($cline, $state->{'input_spool'}) = next_line($texi_line_number, $state->{'files_stack'}); |
|
last if (!defined($cline)); |
|
# |
|
# remove the lines preceding \input or an @-command |
|
# |
|
if ($first_lines) |
|
{ |
|
if ($cline =~ /^\\input/) |
|
{ |
|
push @first_lines, $cline; |
|
$first_lines = 0; |
|
next; |
|
} |
|
if ($cline =~ /^\s*\@/) |
|
{ |
|
$first_lines = 0; |
|
} |
|
else |
|
{ |
|
push @first_lines, $cline; |
|
next; |
|
} |
|
} |
|
#print STDERR "PASS_TEXI($texi_line_number->{'line_nr'})$cline"; |
|
my $chomped_line = $cline; |
|
if (scan_texi ($cline, \$text, \@stack, $state, $texi_line_number) and chomp($chomped_line)) |
|
{ |
|
#print STDERR "==> new page (line_nr $texi_line_number->{'line_nr'},$texi_line_number->{'file_name'},$texi_line_number->{'macro'})\n"; |
|
push (@lines_numbers, { 'file_name' => $texi_line_number->{'file_name'}, |
|
'line_nr' => $texi_line_number->{'line_nr'}, |
|
'macro' => $texi_line_number->{'macro'} }); |
|
} |
|
#dump_stack (\$text, \@stack, $state); |
|
if ($state->{'bye'}) |
|
{ |
|
#dump_stack(\$text, \@stack, $state); |
|
# close stack after bye |
|
#print STDERR "close stack after bye\n"; |
|
close_stack_texi(\$text, \@stack, $state, $texi_line_number); |
|
#dump_stack(\$text, \@stack, $state); |
|
} |
|
next if (@stack); |
|
$cline = $text; |
|
$text = ''; |
|
if (!defined($cline)) |
|
{ |
|
msg_debug ("\$cline undefined after scan_texi", $texi_line_number); |
|
next unless ($state->{'bye'}); |
|
} |
|
push @lines, split_lines($cline); |
|
last if ($state->{'bye'}); |
|
} |
|
# close stack at the end of pass texi |
|
#print STDERR "close stack at the end of pass texi\n"; |
|
close_stack_texi(\$text, \@stack, $state, $texi_line_number); |
|
push @lines, split_lines($text); |
|
print STDERR "# end of pass texi\n" if $T2H_VERBOSE; |
|
return (\@lines, \@first_lines, \@lines_numbers); |
|
} |
|
|
|
#+++########################################################################### |
|
# # |
|
# Pass structure: parse document structure # |
|
# # |
|
#---########################################################################### |
|
|
|
sub initialise_state_structure($) |
|
{ |
|
my $state = shift; |
|
$state->{'structure'} = 1; # for substitute_text and close_stack: |
|
# 1 if pass_structure/scan_structure is |
|
# to be used |
|
$state->{'menu'} = 0; # number of opened menus |
|
$state->{'detailmenu'} = 0; # number of opened detailed menus |
|
$state->{'direntry'} = 0; # number of opened direntry |
|
$state->{'sectionning_base'} = 0; # current base sectioning level |
|
$state->{'table_stack'} = [ "no table" ]; # a stack of opened tables/lists |
|
# seems to be only debug |
|
if (exists($state->{'region_lines'}) and !defined($state->{'region_lines'})) |
|
{ |
|
delete ($state->{'region_lines'}); |
|
print STDERR "Bug: state->{'region_lines'} exists but undef.\n"; |
|
} |
|
} |
|
# This is a virtual element for things appearing before @node and |
|
# sectioning commands |
|
my $element_before_anything; |
|
|
|
# |
|
# initial counters. Global variables for pass_structure. |
|
# |
|
my $document_idx_num; |
|
my $document_sec_num; |
|
my $document_head_num; |
|
my $document_anchor_num; |
|
|
|
# section to level hash taking into account raise and lower sections. |
|
# Reset at document beginning |
|
my %sec2level; |
|
# initial state for the special regions. |
|
my %region_initial_state; |
|
my %region_lines; |
|
my %region_line_nrs; |
|
|
|
# This is a place for index entries, anchors and so on appearing in |
|
# copying or documentdescription |
|
my $no_element_associated_place; |
|
|
|
|
|
my @nodes_list; # nodes in document reading order |
|
# each member is a reference on a hash |
|
my @sections_list; # sections in reading order |
|
# each member is a reference on a hash |
|
my @all_elements; # sectioning elements (nodes and sections) |
|
# in reading order. Each member is a reference |
|
# on a hash which also appears in %nodes, |
|
# @sections_list @nodes_list, @elements_list |
|
my @elements_list; # all the resulting elements in document order |
|
my %sections; # sections hash. The key is the section number |
|
my %headings; # headings hash. The key is the heading number |
|
my $section_top; # @top section |
|
my $element_top; # Top element |
|
my $node_top; # Top node |
|
my $node_first; # First node |
|
my $element_index; # element with first index |
|
my $element_chapter_index; # chapter with first index |
|
my $element_first; # first element |
|
my $element_last; # last element |
|
my %special_commands; # hash for the commands specially handled |
|
# by the user |
|
|
|
# element for content and shortcontent if on a separate page |
|
my %content_element; |
|
my %reference_content_element = |
|
( |
|
'contents' => { 'id' => $Texi2HTML::Config::misc_pages_targets{'Contents'}, |
|
'target' => $Texi2HTML::Config::misc_pages_targets{'Contents'}, |
|
'contents' => 1, 'texi' => '_contents' }, |
|
'shortcontents' => { |
|
'id' => $Texi2HTML::Config::misc_pages_targets{'Overview'}, |
|
'target' => $Texi2HTML::Config::misc_pages_targets{'Overview'}, |
|
'shortcontents' => 1, 'texi' => '_shortcontents' }, |
|
); |
|
|
|
# holds content elements located with @*contents commands |
|
my %all_content_elements; |
|
|
|
# common code for headings and sections |
|
sub new_section_heading($$$$) |
|
{ |
|
my $command = shift; |
|
my $name = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
$name = trim_comment_spaces ($name, "\@$command", $line_nr); |
|
$name = normalise_texi_space($name); |
|
$name = '' if (!defined($name)); |
|
# no increase if in @copying and the like. Also no increase if it is top |
|
# since top has number 0. |
|
my $docid; |
|
my $num; |
|
|
|
my $section_ref = { 'texi' => $name, |
|
'level' => $sec2level{$command}, |
|
'tag' => $command, |
|
}; |
|
return $section_ref; |
|
} |
|
|
|
sub scan_line_separators($$$;$) |
|
{ |
|
my $line = shift; |
|
my $separators = shift; |
|
my $context = shift; |
|
my $line_nr = shift; |
|
|
|
my @command_stack; |
|
my $result = ''; |
|
while (1) |
|
{ |
|
# macro_regexp |
|
if ($line =~ s/^([^{}\@$separators]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])// or $line =~ s/^([^{}\@$separators]*)\@([a-zA-Z][\w-]*)//) |
|
{ |
|
$result .= $1; |
|
my $command = $2; |
|
$command = $alias{$command} if (exists($alias{$command})); |
|
if (defined($Texi2HTML::Config::misc_command{$command})) |
|
{ |
|
if ($command ne 'c' and $command ne 'comment') |
|
{ # misc commands other than comments are kept as-is, only |
|
# comments are removed. |
|
my ($text, $args); |
|
($line, $text, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $command); |
|
$result .= "\@$command".$text; |
|
next; |
|
} |
|
else |
|
{ |
|
$line =~ s/.*//; |
|
return ($result, $line, undef); |
|
} |
|
} |
|
$result .= "\@$command"; |
|
if ($line =~ s/^{//) |
|
{ |
|
push @command_stack, $command; |
|
$result .= '{'; |
|
} |
|
if ($command eq 'verb') |
|
{ |
|
if ($line =~ s/^(.)//) |
|
{ |
|
my $char = $1; |
|
my $verb_char = quotemeta($char); |
|
if ($line =~ s/^(.*?${verb_char}\})//) |
|
{ |
|
$result .= $char.$1; |
|
} |
|
else |
|
{ |
|
$line =~ s/^(.*)//; |
|
$result .= $char . $1; |
|
return ($result, $line, undef); |
|
} |
|
} |
|
else |
|
{ |
|
return ($result, $line, undef); |
|
} |
|
pop @command_stack; |
|
} |
|
} |
|
elsif ($line =~ s/^([^\{\}$separators]*)([{}])//) |
|
{ |
|
$result .= $1 . $2; |
|
my $brace = $2; |
|
if (@command_stack and $brace eq '}') |
|
{ |
|
pop @command_stack; |
|
} |
|
} |
|
elsif ($separators ne '' and $line =~ s/^([^${separators}]*)([$separators])//) |
|
{ |
|
$result .= $1; |
|
my $separator = $2; |
|
if (@command_stack) |
|
{ |
|
$result .= $separator; |
|
} |
|
else |
|
{ |
|
return ($result, $line, $separator); |
|
} |
|
} |
|
else |
|
{ |
|
$result .= $line; |
|
$line = ''; |
|
return ($result, $line, undef); |
|
} |
|
} |
|
} |
|
|
|
sub trim_comment_spaces($$;$) |
|
{ |
|
my $line = shift; |
|
my $context = shift; |
|
my $line_nr = shift; |
|
|
|
if(!defined($line)) |
|
{ |
|
msg_debug("trim_comment_spaces: $context: line undef", $line_nr); |
|
return undef; |
|
} |
|
my ($arg, $remaining, $separator) = scan_line_separators ($line, '', $context, $line_nr); |
|
#msg_debug ("trim_comment_spaces: $context: arg undef. $line", $line_nr) if (!defined($arg)); |
|
#msg_debug ("trim_comment_spaces: $context: $arg !!! $line", $line_nr); |
|
return $arg if (!defined($arg)); |
|
return trim_around_spaces($arg); |
|
} |
|
|
|
# argument may be the number of arguments when the commas in the last |
|
# argument has no specific meaning. When it is undef it means that |
|
# all the arguments have to be parsed |
|
sub parse_line_arguments($$$;$) |
|
{ |
|
my $line = shift; |
|
my $arg_total_nr = shift; |
|
my $context = shift; |
|
my $line_nr = shift; |
|
|
|
my @args; |
|
my $arg_nr = 0; |
|
my $remaining = $line; |
|
|
|
while (!defined($arg_total_nr) or $arg_nr < $arg_total_nr -1) |
|
{ |
|
my ($arg, $separator); |
|
($arg, $remaining, $separator) = scan_line_separators($remaining, ',', $context, $line_nr); |
|
push @args, trim_around_spaces($arg) if (defined($arg)); |
|
return @args if (!defined($separator) or !defined($remaining) or !defined($arg)); |
|
$arg_nr++; |
|
} |
|
if (defined($arg_total_nr)) |
|
{ |
|
my ($last_arg, $separator); |
|
($last_arg, $remaining, $separator) = scan_line_separators($remaining, '', $context, $line_nr); |
|
push @args, trim_around_spaces($last_arg) if (defined($last_arg)); |
|
} |
|
return @args; |
|
} |
|
|
|
sub pass_structure($$) |
|
{ |
|
my $texi_lines = shift; |
|
my $lines_numbers = shift; |
|
|
|
my @doc_lines; # whole document |
|
my @doc_numbers; # whole document line numbers and file names |
|
|
|
my $state = {}; |
|
# holds the informations about the context |
|
# to pass it down to the functions |
|
initialise_state_structure($state); |
|
$state->{'heading_element'} = $element_before_anything; |
|
$state->{'current_element'} = $element_before_anything; |
|
$state->{'place'} = $element_before_anything->{'place'}; |
|
my @stack; |
|
my $text; |
|
my $line_nr; |
|
|
|
while (@$texi_lines or $state->{'in_deff_line'}) |
|
{ |
|
my $cline = shift @$texi_lines; |
|
my $chomped_line = $cline; |
|
if (@$texi_lines and !chomp($chomped_line)) |
|
{ |
|
$texi_lines->[0] = $cline . $texi_lines->[0]; |
|
next; |
|
} |
|
# !defined($cline) may happen if $state->{'in_deff_line'} is true |
|
# but there is no more line, in case the last end of line is |
|
# protected |
|
$line_nr = shift (@$lines_numbers) unless (!defined($cline)); |
|
|
|
if ($state->{'in_deff_line'}) |
|
{ # line stored in $state->{'in_deff_line'} was protected by @ |
|
# and can be concatenated with the next line |
|
if (defined($cline)) |
|
{ |
|
$cline = $state->{'in_deff_line'} . $cline; |
|
} |
|
else |
|
{# end of line protected at the very end of the file |
|
# in that case there is also no line_nr anymore. |
|
$cline = $state->{'in_deff_line'}; |
|
} |
|
delete $state->{'in_deff_line'}; |
|
} |
|
|
|
#print STDERR "PASS_STRUCTURE($line_nr->{'line_nr'}. raw:".var_to_str($state->{'raw'}).", verb:".var_to_str($state->{'verb'})."): $cline"; |
|
if (!$state->{'raw'} and !$state->{'verb'}) |
|
{ |
|
my $tag = ''; |
|
if ($cline =~ /^\s*\@(\w+)\b/) |
|
{ |
|
$tag = $1; |
|
} |
|
|
|
# |
|
# analyze the tag |
|
# |
|
if ($tag and $tag eq 'node' or (defined($sec2level{$tag}) and ($tag !~ /heading/)) or ($tag eq 'insertcopying' and $Texi2HTML::Config::INLINE_INSERTCOPYING)) |
|
{ |
|
my @added_lines = ($cline); |
|
my @added_numbers = ($line_nr); |
|
if ($tag eq 'node' or defined($sec2level{$tag})) |
|
{# in pass structure node shouldn't appear in formats |
|
close_stack_structure(\$text, \@stack, $state, $line_nr); |
|
if (exists($state->{'region_lines'})) |
|
{ |
|
push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($text); |
|
push @doc_lines, split_lines($text) if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}); |
|
$state->{'region_lines'}->{'number'} = 0; |
|
close_region($state); |
|
} |
|
else |
|
{ |
|
push @doc_lines, split_lines($text); |
|
} |
|
$text = ''; |
|
} |
|
if ($tag eq 'node') |
|
{ |
|
my $node_ref; |
|
my $auto_directions; |
|
my $node_line = $cline; |
|
$node_line =~ s/^\@node\s*//; |
|
my @node_res = parse_line_arguments($node_line, undef, '@node', $line_nr); |
|
@node_res = normalise_node_array (\@node_res); |
|
# even for empty nodes, @nodes_res has one element. |
|
#line_error (sprintf(__("Error scanning %s"), $cline), $line_nr) if (@node_res < 1); |
|
$auto_directions = 1 if (scalar(@node_res) == 1); |
|
if (@node_res > 4) |
|
{ |
|
line_warn(__("Superfluous arguments for node"), $line_nr); |
|
} |
|
my ($node, $node_next, $node_prev, $node_up) = @node_res; |
|
if (defined($node) and ($node ne '')) |
|
{ |
|
if (exists($nodes{$node}) and defined($nodes{$node}) |
|
and $nodes{$node}->{'seen'}) |
|
{ |
|
line_error (sprintf(__("Node `%s' previously defined %s"), $node, format_line_number($nodes{$node}->{'line_nr'})), $line_nr); |
|
next; |
|
} |
|
elsif ($node =~ /^\(.+\)/) |
|
{ |
|
line_error (sprintf(__("Syntax for an external node used for `%s'"), $node), $line_nr); |
|
next; |
|
} |
|
else |
|
{ |
|
if (exists($nodes{$node}) and defined($nodes{$node})) |
|
{ # node appeared in a menu |
|
$node_ref = $nodes{$node}; |
|
} |
|
else |
|
{ |
|
$node_ref = {}; |
|
$nodes{$node} = $node_ref; |
|
} |
|
$node_ref->{'node'} = 1; |
|
$node_ref->{'tag'} = 'node'; |
|
$node_ref->{'tag_level'} = 'node'; |
|
$node_ref->{'texi'} = $node; |
|
$node_ref->{'seen'} = 1; |
|
$node_ref->{'automatic_directions'} = $auto_directions; |
|
$node_ref->{'place'} = []; |
|
$node_ref->{'current_place'} = []; |
|
$node_ref->{'line_nr'} = $line_nr; |
|
merge_element_before_anything($node_ref); |
|
$node_ref->{'index_names'} = []; |
|
$state->{'place'} = $node_ref->{'current_place'}; |
|
$state->{'heading_element'} = $node_ref; |
|
$state->{'current_element'} = $node_ref; |
|
$state->{'node_ref'} = $node_ref; |
|
$state->{'menu_in_node'} = 0; |
|
# makeinfo treats differently case variants of |
|
# top in nodes and anchors and in refs commands and |
|
# refs from nodes. |
|
if ($node =~ /^top$/i) |
|
{ |
|
if (!defined($node_top)) |
|
{ |
|
$node_top = $node_ref; |
|
$node_top->{'texi'} = 'Top'; |
|
delete $nodes{$node}; |
|
$nodes{$node_top->{'texi'}} = $node_ref; |
|
} |
|
else |
|
{ # All the refs are going to point to the first Top |
|
line_warn ("Top node already exists", $line_nr); |
|
} |
|
} |
|
unless (@nodes_list) |
|
{ |
|
$node_first = $node_ref; |
|
} |
|
push (@nodes_list, $node_ref); |
|
push @all_elements, $node_ref; |
|
} |
|
} |
|
else |
|
{ |
|
line_error ("Empty node", $line_nr); |
|
next; |
|
} |
|
|
|
if (defined($node_next) and ($node_next ne '')) |
|
{ |
|
$node_ref->{'node_next'} = $node_next; |
|
} |
|
if (defined($node_prev) and ($node_prev ne '')) |
|
{ |
|
$node_ref->{'node_prev'} = $node_prev; |
|
} |
|
if (defined($node_up) and ($node_up ne '')) |
|
{ |
|
$node_ref->{'node_up'} = $node_up; |
|
} |
|
} |
|
elsif (defined($sec2level{$tag})) |
|
{ # section |
|
if ($cline =~ /^\@$tag\s*(.*)$/) |
|
{ |
|
my $name = $1; |
|
my $section_ref = new_section_heading($tag, $name, $state, $line_nr); |
|
$document_sec_num++ if ($tag ne 'top'); |
|
|
|
$section_ref->{'sec_num'} = $document_sec_num; |
|
$section_ref->{'id'} = "SEC$document_sec_num"; |
|
$section_ref->{'seen'} = 1; |
|
$section_ref->{'index_names'} = []; |
|
$section_ref->{'current_place'} = []; |
|
$section_ref->{'place'} = []; |
|
$section_ref->{'section'} = 1; |
|
$section_ref->{'line_nr'} = $line_nr; |
|
|
|
if ($tag eq 'top') |
|
{ |
|
$section_ref->{'number'} = ''; |
|
$section_ref->{'id'} = "SEC_Top"; |
|
$section_ref->{'sec_num'} = 0; |
|
if (defined($section_top)) |
|
{ |
|
line_error ("\@top already exists", $line_nr); |
|
$sections{0} = $section_ref; |
|
} |
|
else |
|
{ |
|
$sections{0.1} = $section_ref; |
|
} |
|
$section_top = $section_ref; |
|
} |
|
else |
|
{ |
|
$sections{$section_ref->{'sec_num'}} = $section_ref; |
|
} |
|
merge_element_before_anything($section_ref); |
|
if ($state->{'node_ref'}) |
|
{ |
|
$section_ref->{'node_ref'} = $state->{'node_ref'}; |
|
push @{$state->{'node_ref'}->{'sections'}}, $section_ref; |
|
} |
|
if ($state->{'node_ref'} and !exists($state->{'node_ref'}->{'with_section'})) |
|
{ |
|
my $node_ref = $state->{'node_ref'}; |
|
$section_ref->{'with_node'} = $node_ref; |
|
$section_ref->{'titlefont'} = $node_ref->{'titlefont'}; |
|
$node_ref->{'with_section'} = $section_ref; |
|
} |
|
if (! $name and $section_ref->{'level'}) |
|
{ |
|
line_warn (sprintf(__("\@%s requires an argument"), $tag), $line_nr); |
|
} |
|
push @sections_list, $section_ref; |
|
push @all_elements, $section_ref; |
|
$state->{'heading_element'} = $section_ref; |
|
$state->{'current_element'} = $section_ref; |
|
$state->{'place'} = $section_ref->{'current_place'}; |
|
################# debug |
|
my $node_ref = "NO NODE"; |
|
my $node_texi =''; |
|
if ($state->{'node_ref'}) |
|
{ |
|
$node_ref = $state->{'node_ref'}; |
|
$node_texi = $state->{'node_ref'}->{'texi'}; |
|
} |
|
print STDERR "# pass_structure node($node_ref)$node_texi, tag \@$tag($section_ref->{'level'}) ref $section_ref, num,id $section_ref->{'sec_num'},$section_ref->{'id'}\n $name\n" |
|
if $T2H_DEBUG & $DEBUG_ELEMENTS; |
|
################# end debug |
|
} |
|
} |
|
elsif ($cline =~ /^\@insertcopying\s*/) |
|
{ |
|
@added_lines = @{$region_lines{'copying'}}; |
|
@added_numbers = @{$region_line_nrs{'copying'}}; |
|
unshift (@$texi_lines, @added_lines); |
|
unshift (@$lines_numbers, @added_numbers); |
|
next; |
|
} |
|
if (exists($state->{'region_lines'})) |
|
{ |
|
push @{$region_lines{$state->{'region_lines'}->{'format'}}}, @added_lines; |
|
if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}) |
|
{ # the region is kept in the document in addition with |
|
# being put in the appropriate region_lines entry. |
|
push @doc_lines, @added_lines; |
|
push @doc_numbers, @added_numbers; |
|
} |
|
} |
|
else |
|
{ |
|
push @doc_lines, @added_lines; |
|
push @doc_numbers, @added_numbers; |
|
} |
|
next; |
|
} |
|
} |
|
if (scan_structure ($cline, \$text, \@stack, $state, $line_nr)) |
|
{ |
|
if (!exists($state->{'region_lines'}) or $Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}) |
|
{ |
|
push (@doc_numbers, $line_nr); |
|
} |
|
if (exists($state->{'region_lines'})) |
|
{ |
|
push @{$region_line_nrs{$state->{'region_lines'}->{'format'}}}, $line_nr unless ($state->{'region_lines'}->{'first_line'}); |
|
} |
|
} |
|
next if (scalar(@stack) or $state->{'in_deff_line'}); |
|
$cline = $text; |
|
$text = ''; |
|
next if (!defined($cline)); |
|
if ($state->{'region_lines'}) |
|
{ |
|
# the first line is like @copying, it is not put in the region |
|
# lines |
|
push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($cline) unless ($state->{'region_lines'}->{'first_line'}); |
|
delete $state->{'region_lines'}->{'first_line'}; |
|
push @doc_lines, split_lines($cline) if ($Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}); |
|
} |
|
else |
|
{ |
|
push @doc_lines, split_lines($cline); |
|
} |
|
} |
|
if (@stack) |
|
{# close stack at the end of pass structure |
|
close_stack_structure(\$text, \@stack, $state, $line_nr); |
|
if ($text) |
|
{ |
|
if (!exists($state->{'region_lines'}) or $Texi2HTML::Config::region_formats_kept{$state->{'region_lines'}->{'format'}}) |
|
{ |
|
push @doc_lines, split_lines($text); |
|
} |
|
if (exists($state->{'region_lines'})) |
|
{ |
|
push @{$region_lines{$state->{'region_lines'}->{'format'}}}, |
|
split_lines($text); |
|
} |
|
} |
|
} |
|
#line_warn ("Expected $state->{'region_lines'}->{'number'} \@end $state->{'region_lines'}->{'format'}", $line_nr) if (exists($state->{'region_lines'})); |
|
line_error (sprintf(__("Expected \@end %s"), $state->{'region_lines'}->{'format'}), $line_nr) if (exists($state->{'region_lines'})); |
|
print STDERR "# end of pass structure\n" if $T2H_VERBOSE; |
|
# To remove once they are handled |
|
#print STDERR "No node nor section, texi2html won't be able to place things rightly\n" if ($element_before_anything->{'place'} and @{$element_before_anything->{'place'}}); |
|
return (\@doc_lines, \@doc_numbers); |
|
} |
|
|
|
# split line at end of line and put each resulting line in an array |
|
# FIXME there must be a more perlish way to do it... Not a big deal |
|
# as long as it work |
|
sub split_lines($) |
|
{ |
|
my $line = shift; |
|
my @result = (); |
|
return @result if (!defined($line)); |
|
my $i = 0; |
|
while ($line ne '') |
|
{ |
|
$result[$i] = ''; |
|
$line =~ s/^(.*)//; |
|
$result[$i] .= $1; |
|
$result[$i] .= "\n" if ($line =~ s/^\n//); |
|
#print STDERR "$i: $result[$i]"; |
|
$i++; |
|
} |
|
return @result; |
|
} |
|
|
|
# handle @documentlanguage |
|
sub do_documentlanguage($$$$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $silent = shift; |
|
my $line_nr = shift; |
|
my $language_change_succes = 0; |
|
if ($line =~ s/\s+(\w+)\s*//) |
|
{ |
|
my $lang = $1; |
|
my $prev_lang = Texi2HTML::Config::get_conf('documentlanguage'); |
|
# This won't be done if the documentlanguage was set on the command line |
|
if (Texi2HTML::Config::set_conf('documentlanguage', $lang, 1)) |
|
{ |
|
warn_unknown_language ($lang, $line_nr) unless ($silent); |
|
$language_change_succes = set_document_language($lang, $silent, $line_nr); |
|
if (!$language_change_succes) |
|
{ # reset previous documentlanguage |
|
Texi2HTML::Config::set_conf('documentlanguage', $prev_lang, 1); |
|
line_warn (sprintf(__("Translations for `%s' not found. Reverting to `%s'"),$lang, $prev_lang), $line_nr) unless ($silent); |
|
} |
|
} |
|
# FIXME warn about stuff remaining on the line? |
|
} |
|
return $language_change_succes; |
|
} |
|
|
|
# actions that should be done in more than one pass. In fact most are not |
|
# to be done in pass_texi. The $pass argument is the number of the pass, |
|
# 0 for pass_texi, 1 for pass_structure, 2 for pass_text |
|
sub common_misc_commands($$$$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $pass = shift; |
|
my $line_nr = shift; |
|
|
|
# for error messages |
|
my $cline = $line; |
|
chomp($cline); |
|
$cline =~ s/^\s*//; |
|
|
|
# track variables |
|
if ($command eq 'set') |
|
{ |
|
if ($line =~ /^(\s+)($VARRE)(\s+)(.*)$/) |
|
{ |
|
$value{$2} = $4; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("%c%s requires a name"), ord('@'), $command), $line_nr) if (!$pass); |
|
} |
|
} |
|
elsif ($command eq 'clear') |
|
{ |
|
if ($line =~ /^(\s+)($VARRE)/) |
|
{ |
|
delete $value{$2}; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("%c%s requires a name"), ord('@'), $command), $line_nr) if (!$pass); |
|
} |
|
} |
|
elsif ($command eq 'clickstyle') |
|
{ |
|
if ($line =~ s/^\s+@([^\s\{\}\@]+)({})?\s*//) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
# FIXME warn about what remains on the line? |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s should only accept a \@-command as argument, not `%s'"), $command, $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'novalidate') |
|
{ |
|
Texi2HTML::Config::set_conf($command, 1, 1); |
|
} |
|
if ($pass) |
|
{ # these commands are only taken into account here in pass_structure 1 |
|
# and pass_text 2 |
|
if ($command eq 'setfilename') |
|
{ |
|
my $filename = trim_comment_spaces($line, "\@$command"); |
|
$filename = substitute_line($filename, "\@$command",{'code_style' => 1, 'remove_texi' => 1}); |
|
if ($filename ne '') |
|
{ |
|
Texi2HTML::Config::set_conf($command, $filename, 1); |
|
} |
|
} |
|
elsif ($command eq 'paragraphindent') |
|
{ |
|
if ($line =~ /\s+([\w\-]+)[^\w\-]/) |
|
{ |
|
set_paragraphindent ($1, 0, $line_nr, $pass); |
|
} |
|
else |
|
{ |
|
set_paragraphindent ($line, 0, $line_nr, $pass); |
|
} |
|
} |
|
elsif ($command eq 'firstparagraphindent') |
|
{ |
|
if (($line =~ /^\s+(none)[^\w\-]/) or ($line =~ /^\s+(insert)[^\w\-]/)) |
|
{ |
|
Texi2HTML::Config::set_conf($command, $1, 1); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@firstparagraphindent arg must be `none' or `insert', not `%s'"), $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'exampleindent') |
|
{ |
|
if ($line =~ /^\s+([0-9]+)/) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
elsif ($line =~ /^\s+(asis)[^\w\-]/) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@exampleindent arg must be numeric/`asis', not `%s'"), $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'frenchspacing') |
|
{ |
|
if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/)) |
|
{ |
|
Texi2HTML::Config::set_conf($command, $1, 1); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Expected \@%s on or off, not `%s'"), $command, $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'kbdinputstyle') |
|
{ |
|
if ($line =~ /\s+([a-z]+)/ and ($1 eq 'code' or $1 eq 'example' or $1 eq 'distinct')) |
|
{ |
|
Texi2HTML::Config::set_conf($command, $1, 1); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@kbdinputstyle arg must be `code'/`example'/`distinct', not `%s'"), $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif (grep {$command eq $_} ('everyheading', 'everyfooting', |
|
'evenheading', 'evenfooting', 'oddheading', 'oddfooting')) |
|
{ # FIXME have a _texi and without texi, and without texi, |
|
# and expand rightly @this*? And use @| to separate, and give |
|
# an array for user consumption? This should be done for each new |
|
# chapter, section, and page. What is a page is not necessarily |
|
# well defined in html, however... |
|
# @thisfile is the @include file. Should be in $line_nr. |
|
|
|
# Also if that command appears in the texi, the error message is |
|
# Unknown command `@evenheading' |
|
# It could be better. |
|
my $arg = $line; |
|
$arg =~ s/^\s+//; |
|
$Texi2HTML::THISDOC{$command} = $arg; |
|
} |
|
elsif ($command eq 'allowcodebreaks') |
|
{ |
|
if (($line =~ /^\s+(true)[^\w\-]/) or ($line =~ /^\s+(false)[^\w\-]/)) |
|
{ |
|
Texi2HTML::Config::set_conf($command, $1, 1); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@allowcodebreaks arg must be `true' or `false', not `%s'"), $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'headings') |
|
{ |
|
my $valid_arg = 0; |
|
foreach my $possible_arg (('off','on','single','double', |
|
'singleafter','doubleafter')) |
|
{ |
|
if ($line =~ /^\s+($possible_arg)[^\w\-]/) |
|
{ |
|
$valid_arg = 1; |
|
$Texi2HTML::THISDOC{$command} = $possible_arg; |
|
last; |
|
} |
|
} |
|
unless ($valid_arg) |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $command, $cline), $line_nr) if ($pass == 1); |
|
} |
|
} |
|
elsif ($command eq 'documentlanguage') |
|
{ |
|
if (do_documentlanguage($command, $line, $pass -1, $line_nr)) |
|
{ |
|
&$Texi2HTML::Config::translate_names(); |
|
set_special_names(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
sub misc_command_texi($$$$) |
|
{ |
|
my $line = shift; |
|
my $command = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $text; |
|
my $args; |
|
my $cline = $line; |
|
|
|
if (!$state->{'ignored'} and !$state->{'arg_expansion'}) |
|
{ |
|
if ($command eq 'documentencoding') |
|
{ # FIXME accept more characters, like @? |
|
if ($cline =~ s/^(\s+)([\w\-]+)//) |
|
{ |
|
my $encoding = $2; |
|
$Texi2HTML::THISDOC{'documentencoding'} = $encoding; |
|
line_warn(sprintf(__("Encoding %s is not a canonical texinfo encoding"), $encoding), $line_nr) |
|
if (!$Texi2HTML::Config::canonical_texinfo_encodings{lc($encoding)}); |
|
if (Texi2HTML::Config::set_conf('DOCUMENT_ENCODING', $Texi2HTML::THISDOC{'documentencoding'}, 1)) |
|
{ |
|
my $from_encoding; |
|
if (!defined($Texi2HTML::Config::IN_ENCODING)) |
|
{ |
|
$from_encoding = encoding_alias($encoding, $line_nr); |
|
Texi2HTML::Config::set_conf('IN_ENCODING', $from_encoding, 1) |
|
if (defined($from_encoding)); |
|
} |
|
if (defined($from_encoding) and $Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
foreach my $file (@{$state->{'files_stack'}}) |
|
{ |
|
binmode($file->{'fh'}, ":encoding($from_encoding)"); |
|
} |
|
} |
|
} |
|
#FIXME error if garbage remains on the line? |
|
} |
|
else |
|
{ |
|
line_error(sprintf(__("\@%s arg must be an encoding"), $command), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'alias') |
|
{ |
|
if ($line =~ /(\s+)([a-zA-Z][\w-]*)(\s*=\s*)([a-zA-Z][\w-]*)(\s*)/) |
|
{ |
|
$alias{$2} = $4; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s"), $command), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'definfoenclose') |
|
{ |
|
if ($cline =~ s/^\s+([a-z][\w\-]*)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//) |
|
{ |
|
$info_enclose{$1} = [ $2, $3 ]; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s"), $command), $line_nr); |
|
} # FIXME warn about garbage remaining on the line? |
|
} |
|
else |
|
{ |
|
if ($command eq 'setfilename' and $Texi2HTML::Config::USE_SETFILENAME) |
|
{ # a double setfillename is removed before calling misc_command_texi |
|
my $filename = trim_comment_spaces($line, "\@$command"); |
|
$filename = substitute_line($filename, "\@$command",{'code_style' => 1, 'remove_texi' => 1}, $line_nr); |
|
if ($filename ne '') |
|
{ |
|
Texi2HTML::Config::set_conf($command, $filename, 1); |
|
# remove extension |
|
$filename =~ s/\.[^\.]*$//; |
|
init_with_file_name ($filename) if ($filename ne ''); |
|
} |
|
} |
|
# in reality, do only set, clear and clickstyle. |
|
# though we should never go there for clickstyle... |
|
common_misc_commands($command, $line, 0, $line_nr); |
|
} |
|
} |
|
|
|
($line, $text, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $command); |
|
return ($line, $text); |
|
} |
|
|
|
sub new_content_element($) |
|
{ |
|
my $command = shift; |
|
$command = 'shortcontents' if ($command ne 'contents'); |
|
my $element; |
|
foreach my $key (keys(%{$reference_content_element{$command}})) |
|
{ |
|
$element->{$key} = $reference_content_element{$command}->{$key}; |
|
} |
|
return $element; |
|
} |
|
|
|
# handle misc commands and misc command args |
|
sub misc_command_structure($$$$) |
|
{ |
|
my $line = shift; |
|
my $command = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $text; |
|
my $args; |
|
# for error messages |
|
my $cline = $line; |
|
chomp $cline; |
|
$cline =~ s/^\s*//; |
|
|
|
if ($command eq 'lowersections') |
|
{ |
|
my ($sec, $level); |
|
while (($sec, $level) = each %sec2level) |
|
{ |
|
$sec2level{$sec} = $level + 1 if ($reference_sec2level{$sec} > 0); |
|
} |
|
$state->{'sectionning_base'}--; |
|
} |
|
elsif ($command eq 'raisesections') |
|
{ |
|
my ($sec, $level); |
|
while (($sec, $level) = each %sec2level) |
|
{ |
|
$sec2level{$sec} = $level - 1 if ($reference_sec2level{$sec} > 0); |
|
} |
|
$state->{'sectionning_base'}++; |
|
} |
|
elsif (($command eq 'contents') or ($command eq 'summarycontents') or ($command eq 'shortcontents')) |
|
{ |
|
if ($command ne 'contents') |
|
{ |
|
$command = 'shortcontents'; |
|
} |
|
Texi2HTML::Config::set_conf($command, 1, 1); |
|
my $new_content_element = new_content_element($command); |
|
push @{$state->{'place'}}, $new_content_element; |
|
push @{$all_content_elements{$command}}, $new_content_element; |
|
} |
|
elsif ($command eq 'dircategory') |
|
{ |
|
my $arg = trim_comment_spaces ($line, "\@$command"); |
|
$Texi2HTML::THISDOC{"${command}_texi"} = $arg; |
|
$Texi2HTML::THISDOC{$command} = substitute_line($arg, "\@$command"); |
|
} |
|
elsif (grep {$_ eq $command} ('settitle','shorttitlepage','title')) |
|
{ |
|
my $arg = trim_comment_spaces($line, "\@$command"); |
|
$Texi2HTML::THISDOC{$command . '_texi'} = $arg; |
|
$Texi2HTML::THISDOC{$command . '_line_nr'} = $line_nr; |
|
|
|
# FIXME backward compatibility. Obsoleted in nov 2009. |
|
$value{"_$command"} = $arg; |
|
if ($command eq 'title') |
|
{ # FIXME This was obsoleted in jun 2007 |
|
$Texi2HTML::THISDOC{"${command}s_texi"} = [ $arg ]; |
|
} |
|
} |
|
elsif (grep {$_ eq $command} ('author','subtitle')) |
|
{ |
|
my $arg = trim_comment_spaces($line, "\@$command"); |
|
$Texi2HTML::THISDOC{$command . '_texi'} .= $arg . "\n"; |
|
if ($state->{'region'} and $state->{'region'} eq 'titlepage') |
|
{ |
|
push @{$Texi2HTML::THISDOC{"${command}s_texi"}}, $arg; |
|
push @{$Texi2HTML::THISDOC{"${command}s_line_nr"}}, $line_nr; |
|
} |
|
#chomp($arg); |
|
|
|
# FIXME backward compatibility. Obsoleted in nov 2009. |
|
$value{"_$command"} .= $arg . "\n"; |
|
} |
|
elsif ($command eq 'synindex' || $command eq 'syncodeindex') |
|
{ |
|
if ($line =~ /^\s+(\w+)\s+(\w+)/) |
|
{ |
|
my $index_from = $1; |
|
my $index_to = $2; |
|
line_error (sprintf(__("Unknown from index `%s' in \@%s"), $index_from, $command), $line_nr) |
|
unless $index_names{$index_from}; |
|
line_error (sprintf(__("Unknown to index name `%s' in \@%s"), $index_to, $command), $line_nr) |
|
unless $index_names{$index_to}; |
|
if ($index_names{$index_from} and $index_names{$index_to}) |
|
{ |
|
my $in_code = 0; |
|
$in_code = 1 if ($command eq 'syncodeindex'); |
|
my $current_to = $index_to; |
|
while ($current_to ne $index_from and $Texi2HTML::THISDOC{'merged_index'}->{$current_to}) |
|
{ |
|
$current_to = $Texi2HTML::THISDOC{'merged_index'}->{$current_to}; |
|
} |
|
if ($current_to ne $index_from) |
|
{ |
|
foreach my $prefix (keys(%{$index_names{$index_from}->{'prefixes'}})) |
|
{ |
|
$index_names{$current_to}->{'prefixes'}->{$prefix} = $in_code; |
|
$index_prefix_to_name{$prefix} = $current_to; |
|
} |
|
$Texi2HTML::THISDOC{'merged_index'}->{$index_from} = $current_to; |
|
} |
|
push @{$Texi2HTML::THISDOC{$command}}, [$index_from,$index_to]; |
|
} |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $command, $cline), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'defindex' || $command eq 'defcodeindex') |
|
{ |
|
if ($line =~ /^\s+(\w+)\s*$/) |
|
{ |
|
my $name = $1; |
|
if ($forbidden_index_name{$name}) |
|
{ |
|
line_error(sprintf(__("Reserved index name %s"),$name), $line_nr); |
|
} |
|
else |
|
{ |
|
my $in_code = 0; |
|
$in_code = 1 if ($command eq 'defcodeindex'); |
|
# FIXME this leads to spurious error message in hello_nodes |
|
#if (defined($index_names{$name})) |
|
#{ |
|
# line_error(sprintf(__("Index `%s' already exists"),$name), $line_nr); |
|
#} |
|
$index_names{$name}->{'prefixes'}->{$name} = $in_code; |
|
$index_prefix_to_name{$name} = $name; |
|
push @{$Texi2HTML::THISDOC{$command}}, $name; |
|
} |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $command, $cline), $line_nr); |
|
} |
|
} |
|
elsif (grep {$_ eq $command} ('everyheadingmarks','everyfootingmarks', |
|
'evenheadingmarks','oddheadingmarks','evenfootingmarks','oddfootingmarks')) |
|
{ |
|
if (($line =~ /^\s+(top)[^\w\-]/) or ($line =~ /^\s+(bottom)[^\w\-]/)) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s arg must be `top' or `bottom', not `%s'"), $command, $cline), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'fonttextsize') |
|
{ |
|
if (($line =~ /^\s+(10)[^\w\-]/) or ($line =~ /^\s+(11)[^\w\-]/)) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Only \@%s 10 or 11 is supported, not `%s'"),$command, $cline), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'pagesizes') |
|
{ |
|
if ($line =~ /^\s+(.*)\s*$/) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
} |
|
elsif ($command eq 'footnotestyle') |
|
{ |
|
if ($line =~ /^\s+([a-z]+)[^\w\-]/) |
|
{ |
|
set_footnote_style ($1, 0, $line_nr); |
|
} |
|
else |
|
{ |
|
set_footnote_style ($line, 0, $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'setchapternewpage') |
|
{ |
|
if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/) |
|
or ($line =~ /^\s+(odd)[^\w\-]/)) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = $1; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s arg must be `on', `off' or `odd', not `%s'"), $command, $cline), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'setcontentsaftertitlepage' or $command eq 'setshortcontentsaftertitlepage') |
|
{ |
|
Texi2HTML::Config::set_conf($command, 1, 1); |
|
} |
|
elsif ($command eq 'need') |
|
{ # only a warning |
|
unless (($line =~ /^\s+([0-9]+(\.[0-9]*)?)[^\w\-]/) or |
|
($line =~ /^\s+(\.[0-9]+)[^\w\-]/)) |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $command, $cline), $line_nr); |
|
} |
|
} |
|
else |
|
{ |
|
common_misc_commands($command, $line, 1, $line_nr); |
|
} |
|
|
|
($text, $line, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $command); |
|
return ($text, $line); |
|
} |
|
|
|
sub set_special_names() |
|
{ |
|
$Texi2HTML::NAME{'About'} = gdt('About This Document'); |
|
$Texi2HTML::NAME{'Contents'} = gdt('Table of Contents'); |
|
$Texi2HTML::NAME{'Overview'} = gdt('Short Table of Contents'); |
|
$Texi2HTML::NAME{'Footnotes'} = gdt('Footnotes'); |
|
$Texi2HTML::NO_TEXI{'About'} = gdt('About This Document', {}, {'remove_texi' => 1} ); |
|
$Texi2HTML::NO_TEXI{'Contents'} = gdt('Table of Contents', {}, {'remove_texi' => 1} ); |
|
$Texi2HTML::NO_TEXI{'Overview'} = gdt('Short Table of Contents', {}, {'remove_texi' => 1} ); |
|
$Texi2HTML::NO_TEXI{'Footnotes'} = gdt('Footnotes', {}, {'remove_texi' => 1} ); |
|
$Texi2HTML::SIMPLE_TEXT{'About'} = gdt('About This Document', {}, {'simple_format' => 1}); |
|
$Texi2HTML::SIMPLE_TEXT{'Contents'} = gdt('Table of Contents',{}, {'simple_format' => 1}); |
|
$Texi2HTML::SIMPLE_TEXT{'Overview'} = gdt('Short Table of Contents', {}, {'simple_format' => 1}); |
|
$Texi2HTML::SIMPLE_TEXT{'Footnotes'} = gdt('Footnotes', {},{'simple_format' => 1}); |
|
} |
|
|
|
sub enter_author_command($$$$$$) |
|
{ |
|
my $command = shift; |
|
my $texi = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
$texi = trim_comment_spaces($texi, "\@$command"); |
|
if ($command eq 'author') |
|
{ |
|
my $top_format = top_stack($stack, 2); |
|
if (defined($top_format) and $format_type{$top_format->{'format'}} eq 'quotation') |
|
{ |
|
push @{$top_format->{'quote_authors'}}, {'author_texi' => $texi, 'author_text' => $text}; |
|
} |
|
elsif (!$state->{'region'} or $state->{'region'} ne 'titlepage') |
|
{ |
|
line_warn (sprintf(__("\@%s not meaningful outside `\@titlepage' and `\@quotation' environments"), $command), $line_nr); |
|
} |
|
} |
|
} |
|
|
|
# return the line after removing things according to misc_command map. |
|
# if the skipped command has an effect it is done here |
|
# this is used during pass_text |
|
sub misc_command_text($$$$$$) |
|
{ |
|
my $line = shift; |
|
my $command = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $text = shift; |
|
my $line_nr = shift; |
|
my ($skipped, $remaining, $args, $result); |
|
|
|
# The strange condition associated with 'keep_texi' is |
|
# there because for an argument appearing on an @itemize |
|
# line (we're in 'check_item'), meant to be prepended to an |
|
# @item we don't want to keep @c or @comment as otherwise it |
|
# eats the @item line. Other commands could do that too but |
|
# then the user deserves what he gets. |
|
if ($state->{'keep_texi'} and |
|
(!$state->{'check_item'} or ($command ne 'c' and $command ne 'comment'))) |
|
{ |
|
($remaining, $skipped, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $command); |
|
add_prev($text, $stack, "\@$command". $skipped); |
|
return $remaining; |
|
} |
|
|
|
($remaining, $skipped, $args) = &$Texi2HTML::Config::preserve_misc_command($line, $command); |
|
|
|
if ($state->{'remove_texi'}) |
|
{ |
|
($command, $line, $result) = &$Texi2HTML::Config::misc_command_line_texi($command, $line, $args, $stack, $state); |
|
} |
|
else |
|
{ |
|
($command, $line, $result) = &$Texi2HTML::Config::misc_command_line($command, $line, $args, $stack, $state); |
|
} |
|
|
|
enter_author_command ($command, $line, $result, $stack, $state, $line_nr); |
|
|
|
# for error messages |
|
my $cline = $line; |
|
$cline =~ s/^\s*//; |
|
chomp $cline; |
|
|
|
# if it is true the command args are kept so the user can modify how |
|
# they are skipped and handle them as unknown @-commands. Nowadays, it is |
|
# not that interesting since using misc_command_line above should do |
|
# about the same more simply. |
|
my $keep = $Texi2HTML::Config::misc_command{$command}->{'keep'}; |
|
|
|
if ($command eq 'sp') |
|
{ |
|
my $sp_number; |
|
if ($line =~ /^\s+(\d+)\s/) |
|
{ |
|
$sp_number = $1; |
|
} |
|
elsif ($line =~ /(\s*)$/) |
|
{ |
|
$sp_number = ''; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@sp requires a positive numeric argument, not `%s'"), $cline), $line_nr); |
|
} |
|
$sp_number = 1 if ($sp_number eq ''); |
|
if (!$state->{'remove_texi'}) |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::sp($sp_number, $state->{'preformatted'})); |
|
} |
|
} |
|
elsif($command eq 'verbatiminclude' and !$keep) |
|
{ |
|
if ($line =~ /\s+(.+)/) |
|
{ |
|
my $arg = $1; |
|
$arg = trim_around_spaces($arg); |
|
my $file_name = substitute_line($arg, "\@$command", {'code_style' => 1}); |
|
my $file = locate_include_file($file_name); |
|
if (defined($file)) |
|
{ |
|
if (!open(VERBINCLUDE, $file)) |
|
{ |
|
line_error (sprintf(__("Cannot read %s: %s"), $file, $!), $line_nr); |
|
} |
|
else |
|
{ |
|
my $verb_text = ''; |
|
while (my $verb_line = <VERBINCLUDE>) |
|
{ |
|
$verb_text .= $verb_line; |
|
} |
|
|
|
if ($state->{'remove_texi'}) |
|
{ |
|
add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi('verbatiminclude', $verb_text)); |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::raw('verbatiminclude', $verb_text, $line_nr)); |
|
} |
|
close VERBINCLUDE; |
|
} |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s: Cannot find %s"), $command, $file_name), $line_nr); |
|
} |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $command, $cline), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'indent' or $command eq 'noindent') |
|
{ |
|
$state->{'paragraph_indent'} = $command; |
|
} |
|
else |
|
{ |
|
common_misc_commands($command, $line, 2, $line_nr); |
|
} |
|
|
|
return ($skipped.$remaining, $result) if ($keep); |
|
return ($remaining, $result); |
|
} |
|
|
|
# merge the things appearing before the first @node or sectioning command |
|
# (held by element_before_anything) with the current element |
|
# do that only once. |
|
sub merge_element_before_anything($) |
|
{ |
|
my $element = shift; |
|
if (exists($element_before_anything->{'place'})) |
|
{ |
|
$element->{'current_place'} = $element_before_anything->{'place'}; |
|
delete $element_before_anything->{'place'}; |
|
foreach my $placed_thing (@{$element->{'current_place'}}) |
|
{ |
|
$placed_thing->{'element'} = $element if (exists($placed_thing->{'element'})); |
|
} |
|
} |
|
# this is certainly redundant with the above condition, but cleaner |
|
# that way |
|
if (exists($element_before_anything->{'titlefont'})) |
|
{ |
|
$element->{'titlefont'} = $element_before_anything->{'titlefont'}; |
|
delete $element_before_anything->{'titlefont'}; |
|
} |
|
} |
|
|
|
# find menu_prev, menu_up... for a node in menu |
|
sub menu_entry_texi($$$) |
|
{ |
|
my $node = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
return if ($state->{'direntry'}); |
|
my $node_menu_ref = {}; |
|
if (exists($nodes{$node})) |
|
{ |
|
$node_menu_ref = $nodes{$node}; |
|
} |
|
else |
|
{ |
|
$nodes{$node} = $node_menu_ref; |
|
$node_menu_ref->{'texi'} = $node; |
|
$node_menu_ref->{'external_node'} = 1 if ($node =~ /^\(.+\)/); |
|
} |
|
return if ($state->{'detailmenu'}); |
|
if ($state->{'node_ref'}) |
|
{ |
|
if ($node_menu_ref->{'menu_up'} and !$node_menu_ref->{'external_node'}) |
|
{ |
|
# This is not an error. This is used a lot in real life manuals |
|
#line_warn ("Double entry in menu for `$node' (also below `$node_menu_ref->{'menu_up'}->{'texi'}')", $line_nr); |
|
} |
|
$node_menu_ref->{'menu_up'} = $state->{'node_ref'}; |
|
$node_menu_ref->{'menu_up_hash'}->{$state->{'node_ref'}->{'texi'}} = 1; |
|
} |
|
if ($state->{'prev_menu_node'}) |
|
{ |
|
$node_menu_ref->{'menu_prev'} = $state->{'prev_menu_node'}; |
|
$state->{'prev_menu_node'}->{'menu_next'} = $node_menu_ref; |
|
} |
|
elsif ($state->{'node_ref'} and !$state->{'node_ref'}->{'menu_child'}) |
|
{ |
|
$state->{'node_ref'}->{'menu_child'} = $node_menu_ref; |
|
} |
|
$state->{'prev_menu_node'} = $node_menu_ref; |
|
} |
|
|
|
my @index_labels; # array corresponding with @?index commands |
|
# constructed during pass_structure, used to |
|
# put labels in pass_text |
|
my @unknown_index_index_entries; # array of index entries not associated |
|
# with any index |
|
|
|
sub sorted_line($) |
|
{ |
|
my $line = shift; |
|
$::texi_map_ref = \%Texi2HTML::Config::sorting_things_map; |
|
my $result = remove_texi($line); |
|
$::texi_map_ref = \%Texi2HTML::Config::texi_map; |
|
return $result; |
|
} |
|
|
|
sub prepare_indices() |
|
{ |
|
#print STDERR "Do splitting of index letters, once.\n"; |
|
|
|
foreach my $index_name(keys %{$Texi2HTML::THISDOC{'index_entries_array'}}) |
|
{ |
|
#print STDERR "$Texi2HTML::THISDOC{'index_entries_array'}->{$index_name}) letters\n"; |
|
my %letters_hash; |
|
foreach my $index_entry (@{$Texi2HTML::THISDOC{'index_entries_array'}->{$index_name}}) |
|
{ |
|
my $key = sorted_line($index_entry->{'texi'}); |
|
$index_entry->{'key'} = $key; |
|
my $letter = uc(substr($key, 0, 1)); |
|
push @{$letters_hash{$letter}}, $index_entry; |
|
} |
|
|
|
# use cmp if only letters or only symbols, otherwise symbols before |
|
# letters |
|
foreach my $letter (sort { |
|
((($a =~ /^[[:alpha:]]/ and $b =~ /^[[:alpha:]]/) or |
|
($a !~ /^[[:alpha:]]/ and $b !~ /^[[:alpha:]]/)) && $a cmp $b) |
|
|| ($a =~ /^[[:alpha:]]/ && 1) || -1 } (keys %letters_hash)) |
|
{ |
|
# FIXME sort without uc? |
|
# This sorts the entries for a given letter |
|
my @sorted_letter_entries = (sort {uc($a->{'key'}) cmp uc($b->{'key'})} (@{$letters_hash{$letter}})); |
|
|
|
push @{$Texi2HTML::THISDOC{'index_letters_array'}->{$index_name}}, { 'letter' => $letter, 'entries' => \@sorted_letter_entries }; |
|
} |
|
} |
|
|
|
# generate the keys for index sorting also for the entries not |
|
# associated with an index. |
|
foreach my $index_entry_without_index (@unknown_index_index_entries) |
|
{ |
|
my $key = sorted_line($index_entry_without_index->{'texi'}); |
|
$index_entry_without_index->{'key'} = $key; |
|
} |
|
Texi2HTML::Config::t2h_default_init_split_indices(); |
|
} |
|
|
|
# This function is used to construct link names from node names as |
|
# specified for texinfo |
|
sub cross_manual_links() |
|
{ |
|
my @all_index_entries; |
|
foreach my $index_name (sort(keys(%{$Texi2HTML::THISDOC{'index_entries_array'}}))) |
|
{ |
|
push @all_index_entries, @{$Texi2HTML::THISDOC{'index_entries_array'}->{$index_name}}; |
|
} |
|
print STDERR "# Doing ".scalar(keys(%nodes))." cross manual links ". |
|
scalar(@all_index_entries). " index entries\n" |
|
if ($T2H_DEBUG); |
|
$::simple_map_texi_ref = \%cross_ref_simple_map_texi; |
|
$::style_map_texi_ref = \%cross_ref_style_map_texi; |
|
$::texi_map_ref = \%cross_ref_texi_map; |
|
my $normal_text_kept = $Texi2HTML::Config::normal_text; |
|
$Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text; |
|
my $style_kept = $Texi2HTML::Config::style; |
|
$Texi2HTML::Config::style = \&Texi2HTML::Config::T2H_GPL_style; |
|
|
|
foreach my $key (keys(%nodes)) |
|
{ |
|
my $node = $nodes{$key}; |
|
#print STDERR "CROSS_MANUAL:$key,$node\n"; |
|
if (!defined($node->{'texi'})) |
|
{ |
|
###################### debug section |
|
foreach my $key (keys(%$node)) |
|
{ |
|
#print STDERR "$key:$node->{$key}!!!\n"; |
|
} |
|
###################### end debug section |
|
} |
|
else |
|
{ |
|
$node->{'cross_manual_target'} = remove_texi($node->{'texi'}); |
|
if ($node->{'cross_manual_target'} !~ /\S/) |
|
{ |
|
line_error (sprintf(__("Empty node name after expansion `%s'"), $node->{'texi'}), $node->{'line_nr'}); |
|
$node->{'cross_manual_target'} = 't_0'; |
|
$node->{'cross_manual_file'} = 't_0'; |
|
} |
|
elsif ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
$node->{'cross_manual_target'} = Unicode::Normalize::NFC($node->{'cross_manual_target'}); |
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES and $Texi2HTML::Config::USE_UNIDECODE) |
|
{ |
|
$node->{'cross_manual_file'} = |
|
unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_target'})); |
|
} |
|
$node->{'cross_manual_target'} = |
|
unicode_to_protected($node->{'cross_manual_target'}); |
|
} |
|
#print STDERR "CROSS_MANUAL_TARGET $node->{'cross_manual_target'}\n"; |
|
unless ($node->{'external_node'}) |
|
{ |
|
if (exists($cross_reference_nodes{$node->{'cross_manual_target'}})) |
|
{ |
|
my $other_node_array = $cross_reference_nodes{$node->{'cross_manual_target'}}; |
|
my $node_seen; |
|
foreach my $other_node (@{$other_node_array}) |
|
{ # find the first node seen for the error message |
|
$node_seen = $other_node; |
|
last if ($nodes{$other_node}->{'seen'}) |
|
} |
|
my $other_node_line_nr = $nodes{$node_seen}->{'line_nr'}; |
|
if (defined($other_node_line_nr)) |
|
{ |
|
msg_error ("Node equivalent with `$node->{'texi'}' already used `$node_seen' ".format_line_number($other_node_line_nr), $node->{'line_nr'}); |
|
} |
|
else |
|
{ |
|
msg_error ("Node equivalent with `$node->{'texi'}' already used `$node_seen'", $node->{'line_nr'}); |
|
} |
|
push @{$other_node_array}, $node->{'texi'}; |
|
} |
|
else |
|
{ |
|
push @{$cross_reference_nodes{$node->{'cross_manual_target'}}}, $node->{'texi'}; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES and |
|
(!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE)) |
|
{ |
|
$::style_map_texi_ref = \%cross_transliterate_style_map_texi; |
|
$::texi_map_ref = \%cross_transliterate_texi_map; |
|
$Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text_transliterate if (!$Texi2HTML::Config::USE_UNICODE); |
|
|
|
foreach my $key (keys(%nodes)) |
|
{ |
|
my $node = $nodes{$key}; |
|
#print STDERR "TRANSLITERATE:$key,$node\n"; |
|
if (defined($node->{'texi'})) |
|
{ |
|
$node->{'cross_manual_file'} = remove_texi($node->{'texi'}); |
|
if ($node->{'cross_manual_file'} !~ /\S/) |
|
{ |
|
$node->{'cross_manual_file'} = 't_0'; |
|
} |
|
elsif ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
$node->{'cross_manual_file'} = unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_file'})); |
|
} |
|
} |
|
} |
|
|
|
foreach my $entry (@all_index_entries, values(%sections), values(%headings)) |
|
{ |
|
#print STDERR "TRANSLITERATE($entry) $entry->{'texi'}\n"; |
|
$entry->{'cross'} = remove_texi($entry->{'texi'}); |
|
$entry->{'cross'} = unicode_to_protected(unicode_to_transliterate($entry->{'cross'})) if ($Texi2HTML::Config::USE_UNICODE); |
|
} |
|
} |
|
else |
|
{ |
|
foreach my $entry (@all_index_entries, values(%sections), values(%headings)) |
|
{ |
|
$entry->{'cross'} = remove_texi($entry->{'texi'}); |
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
$entry->{'cross'} = Unicode::Normalize::NFC($entry->{'cross'}); |
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES and $Texi2HTML::Config::USE_UNIDECODE) # USE_UNIDECODE is redundant |
|
{ |
|
$entry->{'cross'} = |
|
unicode_to_protected(unicode_to_transliterate($entry->{'cross'})); |
|
} |
|
else |
|
{ |
|
$entry->{'cross'} = |
|
unicode_to_protected($entry->{'cross'}); |
|
} |
|
} |
|
} |
|
} |
|
|
|
$Texi2HTML::Config::normal_text = $normal_text_kept; |
|
$Texi2HTML::Config::style = $style_kept; |
|
$::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; |
|
$::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; |
|
$::texi_map_ref = \%Texi2HTML::Config::texi_map; |
|
} |
|
|
|
# This function is used to construct a link name from a node name as |
|
# specified for texinfo |
|
sub cross_manual_line($;$) |
|
{ |
|
my $text = shift; |
|
my $transliterate = shift; |
|
#print STDERR "cross_manual_line $text\n"; |
|
#print STDERR "remove_texi text ". remove_texi($text)."\n\n\n"; |
|
if ($text !~ /\S/) |
|
{ |
|
# special case for empty node/ref |
|
return ('t_0', 't_0'); |
|
} |
|
$::simple_map_texi_ref = \%cross_ref_simple_map_texi; |
|
$::style_map_texi_ref = \%cross_ref_style_map_texi; |
|
$::texi_map_ref = \%cross_ref_texi_map; |
|
my $normal_text_kept = $Texi2HTML::Config::normal_text; |
|
$Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text; |
|
my $style_kept = $Texi2HTML::Config::style; |
|
$Texi2HTML::Config::style = \&Texi2HTML::Config::T2H_GPL_style; |
|
|
|
my ($cross_ref_target, $cross_ref_file); |
|
if ($Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
$cross_ref_target = Unicode::Normalize::NFC(remove_texi($text)); |
|
if ($transliterate and $Texi2HTML::Config::USE_UNIDECODE) |
|
{ |
|
$cross_ref_file = |
|
unicode_to_protected(unicode_to_transliterate($cross_ref_target)); |
|
} |
|
$cross_ref_target = unicode_to_protected($cross_ref_target); |
|
} |
|
else |
|
{ |
|
$cross_ref_target = remove_texi($text); |
|
} |
|
|
|
if ($transliterate and |
|
(!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE)) |
|
{ |
|
$::style_map_texi_ref = \%cross_transliterate_style_map_texi; |
|
$::texi_map_ref = \%cross_transliterate_texi_map; |
|
$Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text_transliterate if (!$Texi2HTML::Config::USE_UNICODE); |
|
$cross_ref_file = remove_texi($text); |
|
$cross_ref_file = unicode_to_protected(unicode_to_transliterate($cross_ref_file)) |
|
if ($Texi2HTML::Config::USE_UNICODE); |
|
} |
|
|
|
$Texi2HTML::Config::normal_text = $normal_text_kept; |
|
$Texi2HTML::Config::style = $style_kept; |
|
$::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; |
|
$::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; |
|
$::texi_map_ref = \%Texi2HTML::Config::texi_map; |
|
#print STDERR "\n\ncross_ref $cross_ref\n"; |
|
unless ($transliterate) |
|
{ |
|
return $cross_ref_target; |
|
} |
|
# print STDERR "$text|$cross_ref_target|$cross_ref_file\n"; |
|
return ($cross_ref_target, $cross_ref_file); |
|
} |
|
|
|
sub equivalent_nodes($) |
|
{ |
|
my $name = shift; |
|
#print STDERR "equivalent_nodes $name\n"; |
|
my $node = normalise_node($name); |
|
$name = cross_manual_line($node); |
|
#print STDERR "equivalent_nodes `$node' `$name'\n"; |
|
my @equivalent_nodes = (); |
|
if (exists($cross_reference_nodes{$name})) |
|
{ |
|
@equivalent_nodes = grep {$_ ne $node} @{$cross_reference_nodes{$name}}; |
|
} |
|
return @equivalent_nodes; |
|
} |
|
|
|
sub do_place_target_file($$$) |
|
{ |
|
my $place = shift; |
|
my $element = shift; |
|
my $context = shift; |
|
|
|
$place->{'file'} = $element->{'file'} unless defined($place->{'file'}); |
|
$place->{'target'} = $element->{'target'} unless defined($place->{'target'}); |
|
if (defined($Texi2HTML::Config::placed_target_file_name)) |
|
{ |
|
my ($target, $id, $file) = &$Texi2HTML::Config::placed_target_file_name($place,$element,$place->{'target'}, $place->{'id'}, $place->{'file'},$context); |
|
$place->{'target'} = $target if (defined($target)); |
|
$place->{'file'} = $file if (defined($file)); |
|
$place->{'id'} = $id if (defined($id)); |
|
} |
|
} |
|
|
|
sub do_node_target_file($$) |
|
{ |
|
my $node = shift; |
|
my $type_of_node = shift; |
|
my $node_file = &$Texi2HTML::Config::node_file_name($node,$type_of_node); |
|
$node->{'node_file'} = $node_file if (defined($node_file)); |
|
if (defined($Texi2HTML::Config::node_target_name)) |
|
{ |
|
my ($target,$id) = &$Texi2HTML::Config::node_target_name($node,$node->{'target'},$node->{'id'}, $type_of_node); |
|
$node->{'target'} = $target if (defined($target)); |
|
$node->{'id'} = $id if (defined($id)); |
|
} |
|
} |
|
|
|
sub do_element_targets($;$) |
|
{ |
|
my $element = shift; |
|
my $use_node_file = shift; |
|
my $is_top = ''; |
|
|
|
$is_top = 'top' if (defined($element_top) and ($element eq $element_top or (defined($element->{'with_node'}) and $element->{'with_node'} eq $element_top))); |
|
|
|
if ($Texi2HTML::Config::SPLIT_INDEX and Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
Texi2HTML::Config::t2h_default_associate_index_element($element, $is_top, $docu_name, $use_node_file); |
|
} |
|
|
|
if (defined($Texi2HTML::Config::element_file_name)) |
|
{ |
|
my $previous_file_name = $element->{'file'}; |
|
my $filename = |
|
&$Texi2HTML::Config::element_file_name ($element, $is_top, $docu_name); |
|
if (defined($filename)) |
|
{ |
|
foreach my $place (@{$element->{'place'}}) |
|
{ |
|
$place->{'file'} = $filename if (defined($place->{'file'}) and ($place->{'file'} eq $previous_file_name)); |
|
} |
|
$element->{'file'} = $filename; |
|
if ($is_top) |
|
{ # reset these variables, although they aren't used much, they may be |
|
# used in file name comparisons |
|
$docu_top = $filename; |
|
$docu_top_file = "$docu_rdir$docu_top"; |
|
} |
|
} |
|
} |
|
print STDERR "file !defined for element $element->{'texi'}\n" if (!defined($element->{'file'})); |
|
if (defined($Texi2HTML::Config::element_target_name)) |
|
{ |
|
my ($target,$id) = &$Texi2HTML::Config::element_target_name($element, $element->{'target'}, $element->{'id'}); |
|
$element->{'target'} = $target if (defined($target)); |
|
$element->{'id'} = $id if (defined($id)); |
|
} |
|
foreach my $place(@{$element->{'place'}}) |
|
{ |
|
do_place_target_file($place, $element, ''); |
|
} |
|
} |
|
|
|
sub add_t2h_element($$$) |
|
{ |
|
my $element = shift; |
|
my $elements_list = shift; |
|
my $prev_element = shift; |
|
|
|
push @$elements_list, $element; |
|
$element->{'element_ref'} = $element; |
|
$element->{'this'} = $element; |
|
|
|
if (defined($prev_element)) |
|
{ |
|
$element->{'back'} = $prev_element; |
|
$prev_element->{'forward'} = $element; |
|
} |
|
push @{$element->{'place'}}, $element; |
|
push @{$element->{'place'}}, @{$element->{'current_place'}}; |
|
return $element; |
|
} |
|
|
|
sub add_t2h_dependent_element ($$) |
|
{ |
|
my $element = shift; |
|
my $element_ref = shift; |
|
$element->{'element_ref'} = $element_ref; |
|
$element_index = $element_ref if ($element_index and ($element_index eq $element)); |
|
push @{$element_ref->{'place'}}, $element; |
|
push @{$element_ref->{'place'}}, @{$element->{'current_place'}}; |
|
} |
|
|
|
my %files = (); # keys are files. This is used to avoid reusing an already |
|
# used file name |
|
my @opened_files = (); # all the files opened by the program to remove |
|
# them if FORCE is not set and an error occured |
|
my %printed_indices = (); # value is true for an index name not empty and |
|
# printed |
|
# This is a virtual element used to have the right hrefs for index entries |
|
# and anchors in footnotes. |
|
my $footnote_element; |
|
|
|
# find next, prev, up, back, forward, fastback, fastforward |
|
# find element id and file |
|
# split index pages |
|
# associate placed items (items which have links to them) with the right |
|
# file and id |
|
# associate nodes with sections |
|
sub rearrange_elements() |
|
{ |
|
print STDERR "# find sections levels and toplevel\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
|
|
my $toplevel = 4; |
|
|
|
# correct level if raisesections or lowersections overflowed |
|
# and find toplevel level |
|
# use %sections and %headings to modify also the headings |
|
foreach my $section (values(%sections), values(%headings)) |
|
{ |
|
my $level = $section->{'level'}; |
|
if ($level > $MAX_LEVEL) |
|
{ |
|
$section->{'level'} = $MAX_LEVEL; |
|
} |
|
# second condition is for @top and @part |
|
elsif ($level < $MIN_LEVEL and ($reference_sec2level{$section->{'tag'}} >= $MIN_LEVEL)) |
|
{ |
|
$section->{'level'} = $MIN_LEVEL; |
|
} |
|
else |
|
{ |
|
$section->{'level'} = $level; |
|
} |
|
$section->{'toc_level'} = $section->{'level'}; |
|
# This is for top |
|
$section->{'toc_level'} = $MIN_LEVEL if ($section->{'level'} < $MIN_LEVEL); |
|
# find the new tag corresponding with the level of the section |
|
if ($section->{'tag'} !~ /heading/ and ($level ne $reference_sec2level{$section->{'tag'}})) |
|
{ |
|
$section->{'tag_level'} = $level2sec{$section->{'tag'}}->[$section->{'level'}]; |
|
} |
|
else |
|
{ |
|
$section->{'tag_level'} = $section->{'tag'}; |
|
} |
|
$toplevel = $section->{'level'} if (($section->{'level'} < $toplevel) and ($section->{'level'} > 0 and ($section->{'tag'} !~ /heading/))); |
|
print STDERR "# section level $level: $section->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
|
|
print STDERR "# find sections structure, construct section numbers (toplevel=$toplevel)\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
my $in_appendix = 0; |
|
# these arrays have an element per sectioning level. |
|
my @previous_numbers = (); # holds the number of the previous sections |
|
# at the same and upper levels |
|
my @previous_sections = (); # holds the ref of the previous sections |
|
my $previous_toplevel; |
|
my @pending_parts; # parts yet to be associated with the |
|
# following element |
|
|
|
foreach my $section (@sections_list) |
|
{ |
|
########################### debug |
|
print STDERR "BUG: node or section_ref defined for section $section->{'texi'}\n" |
|
if (exists($section->{'node'}) or exists($section->{'section_ref'})); |
|
print STDERR "Bug level undef for ($section) $section->{'texi'}\n" if (!defined($section->{'level'})); |
|
########################### end debug |
|
|
|
# associate with first node if it is a section appearing before |
|
# the first node |
|
$section->{'node_ref'} = $nodes_list[0] if ($nodes_list[0] and !$section->{'node_ref'}); |
|
|
|
# a part doesn't really make up an element, it is associated with the |
|
# next sectioning element instead. |
|
if ($section->{'tag'} eq 'part') |
|
{ |
|
push @pending_parts, $section; |
|
} |
|
elsif (@pending_parts) |
|
{ |
|
if ($section->{'tag'} ne 'top') |
|
{ |
|
foreach my $part (@pending_parts) |
|
{ |
|
$part->{'part_section_ref'} = $section; |
|
if (!$section->{'with_part'}) |
|
{ |
|
$section->{'with_part'} = $part; |
|
$part->{'part_with_section'} = $section; |
|
} |
|
# if a node is associated with the part, reassociate it with |
|
# the chapter |
|
if ($part->{'with_node'} and !$section->{'with_node'}) |
|
{ |
|
$section->{'with_node'} = $part->{'with_node'}; |
|
delete $part->{'with_node'}; |
|
$section->{'with_node'}->{'with_section'} = $section; |
|
} |
|
} |
|
} |
|
@pending_parts = (); |
|
} |
|
|
|
# we track the toplevel next and previous because there is no |
|
# strict child parent relationship between chapters and top. Indeed |
|
# a chapter may appear before @top, it may be better to consider them |
|
# on the same toplevel. |
|
if ($section->{'level'} <= $toplevel) |
|
{ |
|
$section->{'toplevel'} = 1; |
|
if (defined($previous_toplevel)) |
|
{ |
|
$previous_toplevel->{'toplevelnext'} = $section; |
|
$section->{'toplevelprev'} = $previous_toplevel; |
|
} |
|
# part is not used as previous_toplevel since toplevel directions |
|
# are used to move between chapters (and top) |
|
$previous_toplevel = $section if ($section->{'tag'} ne 'part'); |
|
# In fact this is only useful for toplevel elements appearing |
|
# before @top, the other have their sectionup reset up below |
|
# based on the sectioning commands hierarchy. |
|
if (defined($section_top) and $section ne $section_top) |
|
{ |
|
$section->{'sectionup'} = $section_top; |
|
} |
|
} |
|
# undef things under that section level |
|
my $section_level = $section->{'level'}; |
|
for (my $level = $section_level + 1; $level < $MAX_LEVEL + 1 ; $level++) |
|
{ |
|
$previous_numbers[$level] = undef unless ($section->{'tag'} =~ /unnumbered/ or $section->{'tag'} eq 'centerchap'); |
|
$previous_sections[$level] = undef; |
|
} |
|
my $number_set; |
|
# find number at the current level |
|
if ($section->{'tag'} =~ /appendix/ and !$in_appendix) |
|
{ |
|
$previous_numbers[$toplevel] = 'A'; |
|
$in_appendix = 1; |
|
$number_set = 1 if ($section->{'level'} <= $toplevel); |
|
$section->{'appendix_beginning'} = 1; |
|
} |
|
if (!defined($previous_numbers[$section->{'level'}]) and !$number_set) |
|
{ |
|
if ($section->{'tag'} =~ /unnumbered/ or $section->{'tag'} eq 'centerchap') |
|
{ |
|
$previous_numbers[$section->{'level'}] = undef; |
|
} |
|
else |
|
{ |
|
$previous_numbers[$section->{'level'}] = 1; |
|
} |
|
} |
|
elsif ($section->{'tag'} !~ /unnumbered/ and $section->{'tag'} ne 'centerchap' and !$number_set) |
|
{ |
|
$previous_numbers[$section->{'level'}]++; |
|
} |
|
# construct the section number |
|
$section->{'number'} = ''; |
|
|
|
unless ($section->{'tag'} =~ /unnumbered/ or $section->{'tag'} eq 'centerchap' or $section->{'tag'} eq 'top' or $section->{'tag'} eq 'part') |
|
{ |
|
my $level = $section->{'level'}; |
|
while ($level > $toplevel) |
|
{ |
|
my $number = $previous_numbers[$level]; |
|
$number = 0 if (!defined($number)); |
|
if ($section->{'number'}) |
|
{ |
|
$section->{'number'} = "$number.$section->{'number'}"; |
|
} |
|
else |
|
{ |
|
$section->{'number'} = $number; |
|
} |
|
$level--; |
|
} |
|
my $toplevel_number = $previous_numbers[$toplevel]; |
|
$toplevel_number = 0 if (!defined($toplevel_number)); |
|
|
|
if ($section->{'number'}) |
|
{ # not toplevel |
|
$section->{'number'} = "$toplevel_number.$section->{'number'}"; |
|
} |
|
else |
|
{ # toplevel |
|
$section->{'number'} = $toplevel_number; |
|
if ($section->{'tag'} =~ /appendix/) |
|
{# i18n |
|
$section->{'plain_number'} = $section->{'number'}; |
|
$section->{'number'} = "Appendix $section->{'number'}"; |
|
} |
|
} |
|
} |
|
$section->{'plain_number'} = $section->{'number'} if (!defined($section->{'plain_number'})); |
|
# find the previous section |
|
if (defined($previous_sections[$section->{'level'}])) |
|
{ |
|
my $prev_section = $previous_sections[$section->{'level'}]; |
|
$section->{'sectionprev'} = $prev_section; |
|
$prev_section->{'sectionnext'} = $section; |
|
} |
|
# find the up section |
|
my $level = $section->{'level'} - 1; |
|
while (!defined($previous_sections[$level]) and ($level >= 0)) |
|
{ |
|
$level--; |
|
} |
|
# The second conditions ensures that a @part is stopped by |
|
# the first @appendix command. |
|
if (defined($previous_sections[$level]) |
|
and !($section->{'appendix_beginning'} and $previous_sections[$level]->{'tag'} eq 'part' and $previous_sections[$level]->{'part_section_ref'} ne $section)) |
|
{ |
|
# toplevel elements have already their up set to the top element, |
|
# it is overwriten here for most cases -- this leads to a different |
|
# sectionup if there are parts, for instance. |
|
# as a side note, it is not touched upon if the element appears |
|
# before @top. |
|
$section->{'sectionup'} = $previous_sections[$level]; |
|
# 'child' is the first child. |
|
if (!$section->{'sectionup'}->{'child'}) |
|
{ |
|
$section->{'sectionup'}->{'child'} = $section; |
|
} |
|
else |
|
{ |
|
# 'childnext' is the next child of a an element. it may |
|
# be different from 'sectionnext' when the elemnt are not |
|
# at the same level, for example |
|
# @chapter chapter |
|
# @subsection subsection (certainly wrong) |
|
# @section section (not next of subsection, but childnext) |
|
$section->{'sectionup'}->{'section_childs'}->[-1]->{'childnext'} = $section if (defined($section->{'sectionup'}->{'section_childs'})); |
|
} |
|
push @{$section->{'sectionup'}->{'section_childs'}}, $section; |
|
} |
|
$previous_sections[$section->{'level'}] = $section; |
|
# This is what is used in the .init file. |
|
$section->{'up'} = $section->{'sectionup'}; |
|
# Not used but documented. |
|
$section->{'next'} = $section->{'sectionnext'}; |
|
$section->{'prev'} = $section->{'sectionprev'}; |
|
|
|
############################# debug |
|
my $up = "NO_UP"; |
|
$up = $section->{'sectionup'} if (defined($section->{'sectionup'})); |
|
print STDERR "# numbering section ($section->{'level'}): $section->{'number'}: (up: $up) $section->{'texi'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
############################# end debug |
|
} |
|
|
|
# at that point there are still some node structures that are not |
|
# in %nodes, (the external nodes, and unknown nodes in case |
|
# novalidate is true) so we cannot find the id. The consequence is that |
|
# some node equivalent with another node may not be catched during |
|
# that pass. We mark the nodes that have directions for unreferenced |
|
# nodes and make a second pass for these nodes afterwards. |
|
my @nodes_with_unknown_directions = (); |
|
|
|
my %node_directions = ( |
|
'node_prev' => 'nodeprev', |
|
'node_next' => 'nodenext', |
|
'node_up' => 'nodeup'); |
|
# handle nodes |
|
# the node_prev... are texinfo strings, find the associated node references |
|
print STDERR "# Resolve nodes directions\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
foreach my $node (@nodes_list) |
|
{ |
|
foreach my $direction (keys(%node_directions)) |
|
{ |
|
if (defined($node->{$direction})) |
|
{ |
|
if ($nodes{$node->{$direction}} and $nodes{$node->{$direction}}->{'seen'}) |
|
{ |
|
$node->{$node_directions{$direction}} = $nodes{$node->{$direction}}; |
|
} |
|
elsif (($node->{$direction} =~ /^\(.*\)/) or Texi2HTML::Config::get_conf('novalidate')) |
|
{ # ref to an external node |
|
if (exists($nodes{$node->{$direction}})) |
|
{ |
|
$node->{$node_directions{$direction}} = $nodes{$node->{$direction}}; |
|
} |
|
else |
|
{ |
|
my $node_ref = { 'texi' => $node->{$direction} }; |
|
$node_ref->{'external_node'} = 1 if ($node->{$direction} =~ /^\(.*\)/); |
|
$nodes{$node->{$direction}} = $node_ref; |
|
$node->{$node_directions{$direction}} = $node_ref; |
|
} |
|
} |
|
else |
|
{ |
|
push @nodes_with_unknown_directions, $node; |
|
} |
|
} |
|
} |
|
} |
|
|
|
# Find cross manual links as explained on the texinfo mailing list |
|
# The specification is such that cross manual links formatting should |
|
# be insensitive to the manual split |
|
cross_manual_links(); |
|
|
|
my %direction_texts = ( |
|
'node_prev' => 'Prev',, |
|
'node_next' => 'Next', |
|
'node_up' => 'Up' |
|
); |
|
# Now it is possible to find the unknown directions that are equivalent |
|
# (have same node id) than an existing node |
|
foreach my $node (@nodes_with_unknown_directions) |
|
{ |
|
foreach my $direction (keys(%node_directions)) |
|
{ |
|
if (defined($node->{$direction}) and !$node->{$node_directions{$direction}}) |
|
{ |
|
line_error (sprintf(__("%s reference to nonexistent `%s'"),$direction_texts{$direction}, $node->{$direction}), $node->{'line_nr'}); # for `$node->{'texi'}'" |
|
my @equivalent_nodes = equivalent_nodes($node->{$direction}); |
|
my $node_seen; |
|
foreach my $equivalent_node (@equivalent_nodes) |
|
{ |
|
if ($nodes{$equivalent_node}->{'seen'}) |
|
{ |
|
$node_seen = $equivalent_node; |
|
last; |
|
} |
|
} |
|
if (defined($node_seen)) |
|
{ |
|
document_warn ("---> but equivalent node `$node_seen' found"); |
|
$node->{$node_directions{$direction}} = $nodes{$node_seen}; |
|
} |
|
} |
|
} |
|
} |
|
|
|
# nodes are attached to the section preceding them if not already |
|
# associated with a section. |
|
# a @part should never have nodes associated, if it is associated |
|
# with a chapter, instead the chapter pointed on by part_section_ref is |
|
# used. |
|
my $current_section = $sections_list[0]; |
|
$current_section = $current_section->{'part_section_ref'} if ($current_section and $current_section->{'part_section_ref'}); |
|
foreach my $element (@all_elements) |
|
{ |
|
if ($element->{'node'}) |
|
{ |
|
if ($element->{'with_section'}) |
|
{ # the node is associated with a section |
|
$element->{'section_ref'} = $element->{'with_section'}; |
|
} |
|
elsif (defined($current_section)) |
|
{# node appearing after a section, but not before another section, |
|
# or appearing before any section |
|
$element->{'section_ref'} = $current_section; |
|
push @{$current_section->{'node_childs'}}, $element; |
|
} |
|
} |
|
else |
|
{ |
|
$current_section = $element; |
|
$current_section = $element->{'part_section_ref'} if ($element->{'part_section_ref'}); |
|
} |
|
} |
|
|
|
print STDERR "# Complete nodes next prev and up based on menus and sections\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
# set the default id based on the node number |
|
my $node_nr = 1; |
|
# find the node* directions |
|
# find the directions corresponding with sections |
|
# and set 'up' for the node |
|
foreach my $node (@nodes_list) |
|
{ |
|
# first a warning if the node and the equivalent nodes don't |
|
# appear in menus. |
|
# Don't warn for the top node, and the first node if there is no |
|
# top node. |
|
if ((($node_top and $node ne $node_top) or (!$node_top and $node ne $node_first)) and !$node->{'menu_up'} and $Texi2HTML::Config::SHOW_MENU) |
|
{ |
|
my @equivalent_nodes = equivalent_nodes($node->{'texi'}); |
|
my $found = 0; |
|
foreach my $equivalent_node (@equivalent_nodes) |
|
{ |
|
if (($nodes{$equivalent_node} eq $node_first) or $nodes{$equivalent_node}->{'menu_up'}) |
|
{ |
|
$found = 1; |
|
last; |
|
} |
|
} |
|
unless ($found) |
|
{ # makeinfo has also |
|
# "`%s' has no Up field (perhaps incorrect sectioning?)" |
|
# but it is not useful since the up will always be set if |
|
# the node appears in a menu so the following error message |
|
# is enough |
|
line_warn (sprintf(__("unreferenced node `%s'"), $node->{'texi'}), $node->{'line_nr'}); |
|
} |
|
} |
|
|
|
# use values deduced from menus to complete missing up, next, prev |
|
# or from sectioning commands if automatic sectioning |
|
if (!$node->{'nodeup'}) |
|
{ |
|
if (defined($node_top) and ($node eq $node_top) and $node->{'automatic_directions'}) |
|
{ # Top node has a special up, which is (dir) by default |
|
my $top_nodeup = $Texi2HTML::Config::TOP_NODE_UP; |
|
if (exists($nodes{$top_nodeup})) |
|
{ |
|
$node->{'nodeup'} = $nodes{$top_nodeup}; |
|
} |
|
else |
|
{ |
|
my $node_ref = { 'texi' => $top_nodeup }; |
|
$node_ref->{'external_node'} = 1; |
|
$nodes{$top_nodeup} = $node_ref; |
|
$node->{'nodeup'} = $node_ref; |
|
} |
|
} |
|
elsif ($node->{'automatic_directions'}) |
|
{ |
|
if ($node->{'with_section'}) |
|
{ |
|
# ignore the up if it is a @part. If the sectioning is |
|
# correct, the element is toplevel and will be handled |
|
# by the next condition. |
|
if ($node->{'with_section'}->{'sectionup'} and !$node->{'with_section'}->{'sectionup'}->{'part_section_ref'}) |
|
{ |
|
$node->{'nodeup'} = get_node($node->{'with_section'}->{'sectionup'}); |
|
} |
|
elsif ($node->{'with_section'}->{'toplevel'} and defined($section_top) and ($node->{'with_section'} ne $section_top)) |
|
{ |
|
$node->{'nodeup'} = get_node($section_top); |
|
} |
|
print STDERR "# Deducing from section node_up $node->{'nodeup'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS and defined($node->{'nodeup'})); |
|
} |
|
elsif ($node->{'menu_up'}) |
|
{ |
|
$node->{'nodeup'} = $node->{'menu_up'}; |
|
print STDERR "# Deducing from menu node_up $node->{'menu_up'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
} |
|
} |
|
|
|
if ($node->{'nodeup'} and !$node->{'nodeup'}->{'external_node'}) |
|
{ |
|
# We detect when the up node has no menu entry for that node, as |
|
# there may be infinite loops when finding following node (see below) |
|
unless (defined($node->{'menu_up_hash'}) and ($node->{'menu_up_hash'}->{$node->{'nodeup'}->{'texi'}})) |
|
{ |
|
line_error(sprintf(__("Node `%s' lacks menu item for `%s' despite being its Up target"), $node->{'nodeup'}->{'texi'}, $node->{'texi'}), $node->{'nodeup'}->{'line_nr'}) if ($Texi2HTML::Config::SHOW_MENU); |
|
push @{$node->{'up_not_in_menu'}}, $node->{'nodeup'}->{'texi'}; |
|
} |
|
} |
|
# check that the up is in one of the menus |
|
if ($Texi2HTML::Config::SHOW_MENU and $node->{'nodeup'} and $node->{'menu_up'}) |
|
{ |
|
my @equivalent_nodes = equivalent_nodes($node->{'nodeup'}->{'texi'}); |
|
my $found = 0; |
|
foreach my $equivalent_node ($node->{'nodeup'}->{'texi'}, @equivalent_nodes) |
|
{ |
|
if ($node->{'menu_up_hash'}->{$equivalent_node}) |
|
{ |
|
$found = 1; |
|
last; |
|
} |
|
} |
|
unless ($found) |
|
{ |
|
line_warn (sprintf(__("For `%s', up in menu `%s' and up `%s' don't match"), $node->{'texi'}, $node->{'menu_up'}->{'texi'}, $node->{'nodeup'}->{'texi'}), $node->{'line_nr'}); |
|
} |
|
|
|
} |
|
|
|
# Find next node if not already found |
|
if ($node->{'nodenext'}) |
|
{ |
|
# doing the following would be wrong: |
|
#$node->{'nodenext'}->{'nodeprev'} = $node if (!defined($node->{'nodenext'}->{'nodeprev'})); |
|
} |
|
elsif ($node->{'texi'} eq 'Top' and $node->{'automatic_directions'}) |
|
{ # special case as said in the texinfo manual |
|
if ($node->{'menu_child'}) |
|
{ |
|
$node->{'nodenext'} = $node->{'menu_child'}; |
|
$node->{'menu_child'}->{'nodeprev'} = $node; |
|
} |
|
} |
|
elsif ($node->{'automatic_directions'}) |
|
{ |
|
if (defined($node->{'with_section'})) |
|
{ |
|
my $next; |
|
my $warn_for_next_not_in_menu = 1; |
|
my $section = $node->{'with_section'}; |
|
if ($section->{'sectionnext'}) |
|
{ |
|
$next = get_node($section->{'sectionnext'}); |
|
} |
|
# we use toplevelnext, mostly for chapters associated with |
|
# @part. But we don't want to have the @top as prev for |
|
# a @chapter or the like |
|
elsif ($section->{'toplevelnext'} and $section->{'toplevelnext'} ne $section_top) |
|
{ |
|
$next = get_node($section->{'toplevelnext'}); |
|
} |
|
elsif ($Texi2HTML::Config::USE_UP_FOR_ADJACENT_NODES) |
|
{ # makeinfo don't do that. So this is conditionnal. |
|
# Also no warning, because it is expected that the |
|
# next found out with the up is not the next in menu. |
|
$warn_for_next_not_in_menu = 0; |
|
while (defined($section->{'sectionup'}) and !defined($section->{'sectionnext'})) |
|
{ |
|
$section = $section->{'sectionup'}; |
|
} |
|
if (defined($section->{'sectionnext'})) |
|
{ |
|
$next = get_node($section->{'sectionnext'}); |
|
} |
|
} |
|
if (defined($next) and $Texi2HTML::Config::SHOW_MENU and $warn_for_next_not_in_menu) |
|
{ |
|
line_warn (sprintf(__("No node following `%s' in menu, but `%s' follows in sectioning"), $node->{'texi'}, $next->{'texi'}), $node->{'line_nr'}) if (!defined($node->{'menu_next'})); |
|
line_warn (sprintf(__("Node following `%s' in menu `%s' and in sectioning `%s' differ"), $node->{'texi'}, $node->{'menu_next'}->{'texi'}, $next->{'texi'}), $node->{'line_nr'}) |
|
if (defined($node->{'menu_next'}) and $next ne $node->{'menu_next'}); |
|
} |
|
$node->{'nodenext'} = $next; |
|
} |
|
elsif ($node->{'menu_next'}) |
|
{ |
|
$node->{'nodenext'} = $node->{'menu_next'}; |
|
} |
|
} |
|
|
|
# Find prev node |
|
if ($node->{'nodeprev'}) |
|
{ |
|
# doing the following would be wrong: |
|
#$node->{'nodeprev'}->{'nodenext'} = $node if (!defined($node->{'nodeprev'}->{'nodenext'})); |
|
} |
|
elsif ($node->{'automatic_directions'}) |
|
{ |
|
if (defined($node->{'with_section'})) |
|
{ |
|
my $section = $node->{'with_section'}; |
|
if ($section->{'sectionprev'}) |
|
{ |
|
$node->{'nodeprev'} = get_node($section->{'sectionprev'}); |
|
} |
|
# we use toplevelprev, mostly for chapters associated with |
|
# @part. But we don't want to have the @top as prev for |
|
# a @chapter or the like |
|
elsif ($section->{'toplevelprev'} and $section->{'toplevelprev'} ne $section_top) |
|
{ |
|
$node->{'nodeprev'} = get_node($section->{'toplevelprev'}); |
|
} |
|
elsif ($Texi2HTML::Config::USE_UP_FOR_ADJACENT_NODES and defined($section->{'sectionup'})) |
|
{ # makeinfo don't do that |
|
$node->{'nodeprev'} = get_node($section->{'sectionup'}); |
|
} |
|
} |
|
elsif ($node->{'menu_prev'}) |
|
{ |
|
$node->{'nodeprev'} = $node->{'menu_prev'}; |
|
} |
|
# the prev node is the parent node |
|
elsif ($node->{'menu_up'} and ($node->{'menu_up'}->{'menu_child'} eq $node) and $Texi2HTML::Config::USE_UP_FOR_ADJACENT_NODES) |
|
{ |
|
$node->{'nodeprev'} = $node->{'menu_up'}; |
|
} |
|
} |
|
|
|
# the following node is the node following in node reading order |
|
# it is thus first the child, else the next, else the next following |
|
# the up |
|
if ($node->{'menu_child'}) |
|
{ |
|
$node->{'following'} = $node->{'menu_child'}; |
|
} |
|
elsif ($node->{'automatic_directions'} and defined($node->{'with_section'}) and defined($node->{'with_section'}->{'child'})) |
|
{ |
|
$node->{'following'} = get_node($node->{'with_section'}->{'child'}); |
|
} |
|
elsif (defined($node->{'nodenext'})) |
|
{ |
|
$node->{'following'} = $node->{'nodenext'}; |
|
} |
|
else |
|
{ |
|
my $up = $node->{'nodeup'}; |
|
# in order to avoid infinite recursion in case the up node is the |
|
# node itself we use the up node as following when there isn't |
|
# a correct menu structure, here and also below. |
|
$node->{'following'} = $up if (defined($up) and grep {$_ eq $up->{'texi'}} @{$node->{'up_not_in_menu'}}); |
|
while ((!defined($node->{'following'})) and (defined($up))) |
|
{ |
|
if (($node_top) and ($up eq $node_top)) |
|
{ # if we are at Top, Top is following |
|
$node->{'following'} = $node_top; |
|
$up = undef; |
|
} |
|
if (defined($up->{'nodenext'})) |
|
{ |
|
$node->{'following'} = $up->{'nodenext'}; |
|
} |
|
elsif (defined($up->{'nodeup'})) |
|
{ |
|
if (! grep { $_ eq $up->{'nodeup'}->{'texi'} } @{$node->{'up_not_in_menu'}}) |
|
{ |
|
$up = $up->{'nodeup'}; |
|
} |
|
else |
|
{ # in that case we can go into a infinite loop |
|
$node->{'following'} = $up->{'nodeup'}; |
|
} |
|
} |
|
else |
|
{ |
|
$up = undef; |
|
} |
|
} |
|
} |
|
# copy the direction of the associated section. |
|
if (defined($node->{'with_section'})) |
|
{ |
|
my $section = $node->{'with_section'}; |
|
foreach my $direction ('sectionnext', 'sectionprev', 'sectionup') |
|
{ |
|
$node->{$direction} = $section->{$direction} |
|
if (defined($section->{$direction})); |
|
} |
|
} |
|
# 'up' is used in .init files. It is almost sectionup, but not |
|
# exactly, it allows to have something relevant whether elements |
|
# are nodes or sections -- just like Back and Forward. So it |
|
# should certainly be kept. |
|
if (defined($node->{'sectionup'})) |
|
{ |
|
$node->{'up'} = $node->{'sectionup'}; |
|
} |
|
elsif (defined($node->{'nodeup'}) and |
|
(!$node_top or ($node ne $node_top))) |
|
{ |
|
$node->{'up'} = $node->{'nodeup'}; |
|
} |
|
# 'next' not used but documented. |
|
if (defined($node->{'sectionnext'})) |
|
{ |
|
$node->{'next'} = $node->{'sectionnext'}; |
|
} |
|
if (defined($node->{'sectionprev'})) |
|
{ |
|
$node->{'prev'} = $node->{'sectionprev'}; |
|
} |
|
|
|
# default id for nodes. Should be overriden later. |
|
$node->{'id'} = 'NOD' . $node_nr; |
|
$node_nr++; |
|
} |
|
|
|
# do node directions for sections. |
|
foreach my $section (@sections_list) |
|
{ |
|
# If the element is not a node, then all the node directions are copied |
|
# if there is an associated node |
|
if (defined($section->{'with_node'})) |
|
{ |
|
$section->{'nodenext'} = $section->{'with_node'}->{'nodenext'}; |
|
$section->{'nodeprev'} = $section->{'with_node'}->{'nodeprev'}; |
|
$section->{'menu_next'} = $section->{'with_node'}->{'menu_next'}; |
|
$section->{'menu_prev'} = $section->{'with_node'}->{'menu_prev'}; |
|
$section->{'menu_child'} = $section->{'with_node'}->{'menu_child'}; |
|
$section->{'menu_up'} = $section->{'with_node'}->{'menu_up'}; |
|
$section->{'nodeup'} = $section->{'with_node'}->{'nodeup'}; |
|
$section->{'following'} = $section->{'with_node'}->{'following'}; |
|
} |
|
} |
|
|
|
my $only_nodes = 0; |
|
my $only_sections = 0; |
|
|
|
# for legibility |
|
my $use_nodes = $Texi2HTML::Config::USE_NODES; |
|
my $use_sections = $Texi2HTML::Config::USE_SECTIONS; |
|
|
|
$only_nodes = 1 if ( |
|
(!scalar(@sections_list) and |
|
($use_nodes or (!$use_sections and !defined($use_nodes)))) |
|
or ($use_nodes and !$use_sections) |
|
); |
|
$only_sections = 1 if (!$only_nodes and !$use_nodes and ($use_sections or !defined($use_sections))); |
|
#print STDERR "USE_NODES $use_nodes, USE_SECTIONS $use_sections. only_nodes: $only_nodes, only_sections $only_sections\n"; |
|
|
|
my $prev_element; |
|
print STDERR "# Build the elements list only_nodes: $only_nodes, only_sections $only_sections\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
foreach my $element (@all_elements) |
|
{ |
|
if ($element->{'node'}) |
|
{ |
|
if ($element->{'section_ref'} and ($only_sections or (!$only_nodes and $element->{'with_section'}))) |
|
{ |
|
add_t2h_dependent_element ($element, $element->{'section_ref'}); |
|
#$element->{'toc_level'} = $element->{'section_ref'}->{'toc_level'}; |
|
} |
|
elsif (!$only_sections) |
|
{ |
|
$prev_element = add_t2h_element($element, \@elements_list, $prev_element); |
|
} |
|
else # $only_section and !$section_ref. This should only |
|
# happen when there are no sections |
|
{ |
|
#print STDERR "node $element->{'texi'} not associated with an element\n"; |
|
} |
|
} |
|
else |
|
{ |
|
my $part_element = $element->{'part_section_ref'}; |
|
if (($element->{'node_ref'} or ($part_element and $part_element->{'node_ref'})) and $only_nodes) |
|
{ |
|
my $element_with_node = $element; |
|
$element_with_node = $part_element if ($part_element); |
|
add_t2h_dependent_element ($element, $element_with_node->{'node_ref'}); |
|
} |
|
elsif (!$only_nodes) |
|
{ |
|
if ($part_element) |
|
{ |
|
add_t2h_dependent_element ($element, $part_element); |
|
} |
|
else |
|
{ |
|
$prev_element = add_t2h_element($element, \@elements_list, $prev_element); |
|
} |
|
} |
|
else |
|
{ # no node, and $only_nodes |
|
#print STDERR "$element->{'tag'} $element->{'texi'} not associated with an element\n"; |
|
} |
|
} |
|
} |
|
|
|
# find texi2html specific directions and elements that are not texinfo |
|
# language features. |
|
# |
|
# Maybe Config hooks should be used at that point (up to index |
|
# preparation) |
|
# |
|
# find first, last and top elements |
|
if (@elements_list) |
|
{ |
|
$element_first = $elements_list[0]; |
|
print STDERR "# element first: $element_first->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
# It is the last element before indices split, which may add new |
|
# elements |
|
$element_last = $elements_list[-1]; |
|
} |
|
else |
|
{ |
|
print STDERR "# \@elements_list is empty\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
print STDERR "# top node: $node_top->{'texi'}\n" if (defined($node_top) and |
|
($T2H_DEBUG & $DEBUG_ELEMENTS)); |
|
|
|
# Remark: there are many subtle distinctions among the elements that |
|
# have a flavor of being at top. First there are the texinfo top |
|
# elements (if present), namely $section_top for the @top element |
|
# and $node_top for the @node Top element (and both may be associated). |
|
|
|
# Then there is $element_top, set up just below. In addition to |
|
# $section_top and $node_top, the section associated with $node_top |
|
# and the first element may be used. $element_top is used to determine |
|
# file splitting and file names, since it is always associated with |
|
# $docu_top file. |
|
|
|
# The $element_top may have 'top' set, in case it is a node or @top. |
|
# In that case, special formatting is done, like using print_Top and |
|
# similar. |
|
|
|
# Similarly with element_top, some other nodes than $node_top may |
|
# get associated with the top node filename without being considered |
|
# as top otherwise (this is done below). |
|
|
|
if (defined($section_top) and $section_top->{'this'}) |
|
{ |
|
# element top is the element with @top. |
|
$element_top = $section_top; |
|
} |
|
elsif (defined($node_top) and $node_top->{'this'}) |
|
{ |
|
# otherwise top node may be the element_top |
|
$element_top = $node_top; |
|
} |
|
elsif (defined($node_top) and defined($node_top->{'with_section'}) and $node_top->{'with_section'}->{'this'}) |
|
{ |
|
# next, the element associated with the @node Top may be |
|
# the $element_top. In that case $element_top->{'top'} won't be set |
|
$element_top = $node_top->{'with_section'}; |
|
} |
|
elsif (defined($element_first)) |
|
{ |
|
# If there is no @top section no top node associated with an element, |
|
# first element is used |
|
$element_top = $element_first; |
|
} |
|
|
|
# Rather arbitrarily, 'top' is set for nodes as top elements |
|
# and @top. This triggers specific formatting, like calling |
|
# print_Top and similar things. |
|
if (defined($element_top)) |
|
{ |
|
$element_top->{'top'} = 1 if ($element_top->{'node'} or $element_top->{'tag'} eq 'top'); |
|
print STDERR "# element top: $element_top->{'texi'}\n" if ($element_top and |
|
($T2H_DEBUG & $DEBUG_ELEMENTS)); |
|
} |
|
|
|
print STDERR "# find fastback and fastforward\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
foreach my $element (@elements_list) |
|
{ # nodes are ignored here, although their associated sectioning |
|
# command may be taken into account. |
|
my $up = get_top($element); |
|
next unless (defined($up)); |
|
# take the opportunity to set the first chapter with index |
|
$element_chapter_index = $up if ($element_index and ($element_index eq $element)); |
|
# fastforward is the next element on same level than the upper parent |
|
# element. |
|
if (exists ($up->{'toplevelnext'})) |
|
{ |
|
$element->{'fastforward'} = $up->{'toplevelnext'} |
|
} |
|
# if the element isn't at the highest level, fastback is the |
|
# highest parent element |
|
if ($up and ($up ne $element)) |
|
{ |
|
$element->{'fastback'} = $up; |
|
} |
|
elsif ($element->{'toplevel'}) |
|
{ |
|
# the element is a top level element, we adjust the next |
|
# toplevel element fastback |
|
$element->{'fastforward'}->{'fastback'} = $element if ($element->{'fastforward'}); |
|
} |
|
} |
|
|
|
# set 'reference_element' which is used each time there is a cross ref |
|
# to that node (xref and menu entry), to do the href, and also the |
|
# element heading text. |
|
# It is the section associated with the node if there are only sections. |
|
# Since in the default case the target is the node target, even for |
|
# sections, this, in fact shouldn't lead to a different target, unless |
|
# the node and the section don't have the same file associated, which could |
|
# only happen with indices split. The heading text will be different, though. |
|
# The node name should also always be passed to the formatting functions |
|
# such that it is always possible for the formatting to chose the node |
|
# heading over the element heading selected using 'reference_element'. |
|
if ($only_sections) |
|
{ |
|
foreach my $node(@nodes_list) |
|
{ |
|
if ($node->{'with_section'}) |
|
{ |
|
$node->{'reference_element'} = $node->{'with_section'}; |
|
} |
|
} |
|
} |
|
# the symmetric is not done for sections, since there is no crossref |
|
# to sections in texinfo (only to anchors and nodes), so that when |
|
# there is a link to an element (in Toc, for instance), |
|
# there is no reason to want to have the node (though, once again, |
|
# the href is almost surely the same than what would be with the node, |
|
# the heading would be different). |
|
|
|
# end texi2html added directions |
|
|
|
# do human readable id |
|
print STDERR "# find float id\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
foreach my $float (@floats) |
|
{ |
|
$float->{'style_id'} = cross_manual_line($float->{'style_texi'}); |
|
my $float_style = { }; |
|
if (exists($floats{$float->{'style_id'}})) |
|
{ |
|
$float_style = $floats{$float->{'style_id'}}; |
|
} |
|
else |
|
{ |
|
$floats{$float->{'style_id'}} = $float_style; |
|
} |
|
push @{$float_style->{'floats'}}, $float; |
|
$float->{'absolute_nr'} = scalar(@{$float_style->{'floats'}}); |
|
my $up = get_top($float->{'element'}); |
|
if (defined($up) and (!defined($float_style->{'current_chapter'}) or ($up->{'texi'} ne $float_style->{'current_chapter'}))) |
|
{ |
|
$float_style->{'current_chapter'} = $up->{'texi'}; |
|
$float_style->{'nr_in_chapter'} = 1; |
|
} |
|
else |
|
{ |
|
$float_style->{'nr_in_chapter'}++; |
|
} |
|
if (defined($up) and $up->{'toplevel'} and $up->{'number'} ne '') |
|
{ |
|
$float->{'chapter_nr'} = $up->{'plain_number'}; |
|
$float->{'nr'} = $float->{'chapter_nr'} . "." . $float_style->{'nr_in_chapter'}; |
|
} |
|
else |
|
{ |
|
$float->{'nr'} = $float->{'absolute_nr'}; |
|
} |
|
} |
|
|
|
print STDERR "# do human-readable index entries id\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
if ($Texi2HTML::Config::NEW_CROSSREF_STYLE) |
|
{ |
|
foreach my $entry_region (sort(keys(%{$Texi2HTML::THISDOC{'index_entries_region_array'}}))) |
|
{ |
|
foreach my $index_entry (@{$Texi2HTML::THISDOC{'index_entries_region_array'}->{$entry_region}}) |
|
{ |
|
my $region = ''; |
|
$region = "$index_entry->{'region'}-" if (defined($index_entry->{'region'}) and $index_entry->{'region'} ne ''); |
|
my $index_id = "index-" . $region .$index_entry->{'cross'}; |
|
my $index = 1; |
|
# $index > 0 should prevent integer overflow, hopefully |
|
while (exists($cross_reference_nodes{$index_id}) and $index > 0) |
|
{ |
|
$index_id = "index-" . $region . $index_entry->{'cross'} . "-" .$index; |
|
$index++; |
|
} |
|
$index_entry->{'id'} = $index_id; |
|
$index_entry->{'target'} = $index_id; |
|
my $texi_entry = "index-".$region.$index_entry->{'texi'}; |
|
$texi_entry .= "-".$index if ($index > 1); |
|
push @{$cross_reference_nodes{$index_id}}, $texi_entry; |
|
} |
|
} |
|
} |
|
|
|
|
|
if ($Texi2HTML::Config::NEW_CROSSREF_STYLE) |
|
{ |
|
foreach my $key (keys(%nodes)) |
|
{ |
|
my $node = $nodes{$key}; |
|
next if ($node->{'external_node'}); |
|
$node->{'id'} = node_to_id($node->{'cross_manual_target'}); |
|
# FIXME if NEW_CROSSREF_STYLE false is it done for anchors? |
|
$node->{'target'} = $node->{'id'}; |
|
} |
|
} |
|
|
|
# use %sections and %headings to modify also the headings |
|
foreach my $section (values(%sections), values(%headings)) |
|
{ |
|
if ($Texi2HTML::Config::NEW_CROSSREF_STYLE and ($section->{'cross'} =~ /\S/)) |
|
{ |
|
my $section_cross = $section->{'cross'}; |
|
if (defined($section->{'region'})) |
|
{ # for headings appearing in special regions like @copying... |
|
$section_cross = "${target_prefix}-$section->{'region'}_$section_cross"; |
|
} |
|
$section->{'cross_manual_target'} = $section_cross; |
|
|
|
my $index = 1; |
|
# $index > 0 should prevent integer overflow, hopefully |
|
while (exists($cross_reference_nodes{$section->{'cross_manual_target'}}) and $index > 0) |
|
{ |
|
$section->{'cross_manual_target'} = $section_cross . "-" .$index; |
|
$index++; |
|
} |
|
my $texi_entry = $section->{'texi'}; |
|
$texi_entry .= "-".$index if ($index > 1); |
|
push @{$cross_reference_nodes{$section->{'cross_manual_target'}}}, $texi_entry; |
|
$section->{'id'} = node_to_id($section->{'cross_manual_target'}); |
|
} |
|
} |
|
# use the associated @part as target if there is an associated part. |
|
# do it separately to be sure that all the parts have an id. |
|
foreach my $section (values(%sections), values(%headings)) |
|
{ |
|
my $target = $section; |
|
$target = $section->{'with_part'} if ($section->{'with_part'}); |
|
if ($Texi2HTML::Config::USE_NODE_TARGET and $target->{'with_node'}) |
|
{ |
|
$section->{'target'} = $target->{'with_node'}->{'target'}; |
|
} |
|
else |
|
{ |
|
$section->{'target'} = $target->{'id'}; |
|
} |
|
} |
|
|
|
# construct human readable tocid |
|
foreach my $section (values(%sections)) |
|
{ |
|
if ($Texi2HTML::Config::NEW_CROSSREF_STYLE and ($section->{'cross'} =~ /\S/)) |
|
{ |
|
foreach my $toc_id (['tocid','toc'], ['stocid', 'stoc']) |
|
{ |
|
my $id_string = $toc_id->[0]; |
|
my $prefix_string = $toc_id->[1]; |
|
my $cross_string = '-' . $section->{'cross_manual_target'}; |
|
$section->{$id_string} = $prefix_string . $cross_string; |
|
my $index = 1; |
|
# $index > 0 should prevent integer overflow, hopefully |
|
while (exists($cross_reference_nodes{$section->{$id_string}}) and $index > 0) |
|
{ |
|
$section->{$id_string} = $prefix_string . "-" .$index .$cross_string; |
|
$index++; |
|
} |
|
my $texi_entry = $prefix_string.'-'.$section->{'texi'}; |
|
$texi_entry = $prefix_string .'-'.$index.'-'.$section->{'texi'} if ($index > 1); |
|
push @{$cross_reference_nodes{$section->{$id_string}}}, $texi_entry; |
|
} |
|
} |
|
} |
|
if (!$Texi2HTML::Config::NEW_CROSSREF_STYLE) |
|
{ |
|
my $tocnr = 1; |
|
foreach my $element (@elements_list) |
|
{ |
|
$element->{'tocid'} = 'TOC' . $tocnr; |
|
$tocnr++; |
|
} |
|
} |
|
|
|
# Set file names |
|
# Find node file names and file names for nodes considered as elements |
|
my $node_as_top; |
|
if ($node_top) |
|
{ |
|
$node_as_top = $node_top; |
|
} |
|
# following possibilities lead to some node being considered |
|
# as top for the purpose of setting the file node, but not as node_top |
|
elsif ($element_top->{'with_node'}) |
|
{ |
|
$node_as_top = $element_top->{'with_node'}; |
|
} |
|
else |
|
{ |
|
$node_as_top = $node_first; |
|
} |
|
if ($node_as_top) |
|
{ |
|
do_node_target_file($node_as_top, 'top'); |
|
} |
|
foreach my $key (keys(%nodes)) |
|
{ |
|
my $node = $nodes{$key}; |
|
next if (defined($node_as_top) and ($node eq $node_as_top)); |
|
do_node_target_file($node,''); |
|
} |
|
|
|
print STDERR "# split(".Texi2HTML::Config::get_conf('SPLIT').") and set files\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
# find document nr and document file for sections and nodes. |
|
# Split according to Texi2HTML::Config::SPLIT. |
|
# find file and id for placed elements (anchors, index entries, headings) |
|
if (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
$Texi2HTML::THISDOC{'split_level'} = $toplevel; |
|
my $doc_nr = -1; |
|
if (Texi2HTML::Config::get_conf('SPLIT') eq 'section') |
|
{ |
|
$Texi2HTML::THISDOC{'split_level'} = 2 if ($toplevel <= 2); |
|
} |
|
my $previous_file; |
|
my $previous_is_top = 0; |
|
foreach my $element (@elements_list) |
|
{ |
|
print STDERR "# Splitting (".Texi2HTML::Config::get_conf('SPLIT').":$Texi2HTML::THISDOC{'split_level'}) $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
my $new_file = 0; |
|
if ( |
|
(!defined($previous_file)) or |
|
(Texi2HTML::Config::get_conf('SPLIT') eq 'node') or |
|
( |
|
defined($element->{'level'}) and ($element->{'level'} <= $Texi2HTML::THISDOC{'split_level'}) |
|
) or |
|
( |
|
!defined($element->{'level'}) and defined($element->{'with_section'}) and ($element->{'with_section'}->{'level'} <= $Texi2HTML::THISDOC{'split_level'}) |
|
) or |
|
( # top file after another file |
|
(defined($previous_file) and ($element eq $element_top) |
|
and ($previous_file ne $docu_top)) |
|
) # element following top element is always considered to be |
|
# in a different file. |
|
or ($previous_is_top) |
|
) |
|
{ |
|
$new_file = 1; |
|
$doc_nr++; |
|
} |
|
$previous_is_top = 0 if ($previous_is_top); |
|
|
|
$element->{'doc_nr'} = $doc_nr; |
|
$element->{'file'} = "${docu_name}_$doc_nr" |
|
. (defined($Texi2HTML::THISDOC{'extension'}) ? ".$Texi2HTML::THISDOC{'extension'}" : ''); |
|
my $use_node_file = 0; |
|
if ($element eq $element_top) |
|
{ # the top element |
|
$element->{'file'} = $docu_top; |
|
$previous_is_top = 1; |
|
} |
|
elsif ($Texi2HTML::Config::NODE_FILENAMES) |
|
{ |
|
$use_node_file = 1; |
|
if ($new_file) |
|
{ |
|
my $node = get_node($element); |
|
if ($node and defined($node->{'node_file'})) |
|
{ |
|
$element->{'file'} = $node->{'node_file'}; |
|
} |
|
elsif ($element->{'cross'} =~ /\S/) |
|
{ # use the canonicalized/transliterated section file name. |
|
$element->{'file'} = $element->{'cross'} |
|
. (defined($Texi2HTML::THISDOC{'extension'}) ? ".$Texi2HTML::THISDOC{'extension'}" : ''); |
|
} |
|
# The remaining case is for sectioning elements with empty |
|
# headings and no node associated. They will have a name |
|
# with numbers, like "${docu_name}_$doc_nr", they may |
|
# collide with split indices names |
|
} |
|
else |
|
{ |
|
$element->{'file'} = $previous_file; |
|
} |
|
} |
|
$previous_file = $element->{'file'}; |
|
do_element_targets($element, $use_node_file); |
|
print STDERR "# [$doc_nr] add_file($use_node_file,$new_file,".var_to_str($previous_file).") $element->{'file'} for $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
add_file($element->{'file'}); |
|
} |
|
} |
|
else |
|
{ # not split |
|
add_file($docu_doc); |
|
foreach my $element(@elements_list) |
|
{ |
|
$element->{'file'} = $docu_doc; |
|
$element->{'doc_nr'} = 0; |
|
do_element_targets($element); |
|
} |
|
} |
|
# 'pathological' cases. No texinfo sectioning element at all or no |
|
# texi2html sectioning elements |
|
if (!@elements_list) |
|
{ |
|
if (@all_elements) |
|
{ |
|
# in fact this happens only if there is no top element, but still |
|
# sections, so only if USE_SECTIONS = 0 and there is no node. |
|
#document_warn ("No elements available for splitting") if (Texi2HTML::Config::get_conf('SPLIT')); |
|
foreach my $element (@all_elements) |
|
{ |
|
#print STDERR "# no \@elements_list. Processing $element->{'texi'}\n"; |
|
$element->{'file'} = $docu_doc; |
|
$element->{'doc_nr'} = 0; |
|
push @{$element->{'place'}}, @{$element->{'current_place'}}; |
|
do_element_targets($element,$Texi2HTML::Config::NODE_FILENAMES); |
|
print STDERR "# no \@elements_list, setting $element->{'file'} for $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
add_file($docu_doc); |
|
} |
|
else |
|
{ |
|
#document_warn ("No elements at all") if (Texi2HTML::Config::get_conf('SPLIT')); |
|
$element_before_anything->{'file'} = $docu_doc; |
|
$element_before_anything->{'doc_nr'} = 0; |
|
do_element_targets($element_before_anything,$Texi2HTML::Config::NODE_FILENAMES); |
|
print STDERR "# no element at all, setting $element_before_anything->{'file'} for $element_before_anything->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
} |
|
|
|
# correct the id and file for the things placed in footnotes |
|
foreach my $place(@{$footnote_element->{'place'}}) |
|
{ |
|
do_place_target_file ($place, $footnote_element, 'footnotes'); |
|
} |
|
# if setcontentsaftertitlepage is set, the contents should be associated |
|
# with the titlepage. That's what is done there. |
|
push @$no_element_associated_place, $content_element{'contents'} |
|
if (Texi2HTML::Config::get_conf('contents') and $Texi2HTML::THISDOC{'setcontentsaftertitlepage'}); |
|
push @$no_element_associated_place, $content_element{'shortcontents'} |
|
if (Texi2HTML::Config::get_conf('shortcontents') and $Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'}); |
|
# correct the id and file for the things placed in regions (copying...) |
|
foreach my $place(@$no_element_associated_place) |
|
{ |
|
#print STDERR "entry $place->{'entry'} texi $place->{'texi'}\n"; |
|
$place->{'element'} = $element_top if (exists($place->{'element'})); |
|
do_place_target_file ($place, $element_top, 'no_associated_element'); |
|
} |
|
|
|
# determine contents element and files |
|
foreach my $content_type(keys(%content_element)) |
|
{ |
|
# with set*aftertitlepage, there will always be a href to Contents |
|
# or Overview pointing to the top element, even if there is no |
|
# titlepage outputed. |
|
if (!scalar(@{$all_content_elements{$content_type}})) |
|
{ |
|
if ($Texi2HTML::Config::INLINE_CONTENTS) |
|
{ |
|
print STDERR "# No content $content_type\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
$content_element{$content_type} = undef; |
|
} |
|
} |
|
elsif ($Texi2HTML::Config::INLINE_CONTENTS and !Texi2HTML::Config::get_conf('set' . $content_type .'aftertitlepage')) |
|
{ # use the last element for references in case there is more than one |
|
$content_element{$content_type} = $all_content_elements{$content_type}->[-1]; |
|
} |
|
} |
|
my ($toc_file, $stoc_file); |
|
$toc_file = $docu_toc; |
|
$stoc_file = $docu_stoc; |
|
if ($Texi2HTML::Config::INLINE_CONTENTS) |
|
{ |
|
$toc_file = $content_element{'contents'}->{'file'} if (defined($content_element{'contents'})); |
|
$stoc_file = $content_element{'shortcontents'}->{'file'} if (defined($content_element{'shortcontents'})); |
|
} |
|
$Texi2HTML::THISDOC{'toc_file'} = $toc_file; |
|
$Texi2HTML::THISDOC{'stoc_file'} = $stoc_file; |
|
|
|
print STDERR "# find NextFile and PrevFile\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
foreach my $element (@elements_list) |
|
{ |
|
my $current_element = $element; |
|
my $file = $current_element->{'file'}; |
|
my $previous_file; |
|
while ($current_element->{'back'}) |
|
{ |
|
#print STDERR "Back $current_element->{'texi'}\n"; |
|
$current_element = $current_element->{'back'}; |
|
if ($current_element->{'file'} ne $file) |
|
{ |
|
$previous_file = $current_element->{'file'}; |
|
last; |
|
} |
|
} |
|
if (defined($previous_file)) |
|
{ |
|
while ($current_element->{'back'}) |
|
{ |
|
if ($current_element->{'back'}->{'file'} ne $previous_file) |
|
{ |
|
last; |
|
} |
|
$current_element = $current_element->{'back'}; |
|
} |
|
$element->{'prevfile'} = $current_element; |
|
} |
|
|
|
$current_element = $element; |
|
while ($current_element->{'forward'}) |
|
{ |
|
#print STDERR "Fwd $current_element->{'texi'}\n"; |
|
$current_element = $current_element->{'forward'}; |
|
if ($current_element->{'file'} ne $file) |
|
{ |
|
$element->{'nextfile'} = $current_element; |
|
} |
|
} |
|
} |
|
# convert directions in direction with first letter in all caps, to be |
|
# consistent with the convention used in the .init file. |
|
foreach my $element (@elements_list) |
|
{ |
|
foreach my $direction (@element_directions) |
|
{ |
|
my $direction_no_caps = $direction; |
|
$direction_no_caps =~ tr/A-Z/a-z/; |
|
$element->{$direction} = $element->{$direction_no_caps}; |
|
} |
|
} |
|
|
|
########################### debug prints |
|
foreach my $file (keys(%files)) |
|
{ |
|
last unless ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
print STDERR "$file: counter $files{$file}->{'counter'}\n"; |
|
} |
|
my $output_elements = \@elements_list; |
|
if (!scalar(@elements_list) and ($T2H_DEBUG & $DEBUG_ELEMENTS)) |
|
{ |
|
print STDERR "No elements_list, no texi2html elements\n"; |
|
$output_elements = \@all_elements; |
|
} |
|
foreach my $element ((@$output_elements, $footnote_element)) |
|
{ |
|
last unless ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
my $is_toplevel = 'not toplevel'; |
|
$is_toplevel = 'toplevel' if ($element->{'toplevel'}); |
|
print STDERR "$element "; |
|
if ($element->{'node'}) |
|
{ |
|
print STDERR "node($element->{'id'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n"; |
|
print STDERR " section_ref: $element->{'section_ref'}->{'texi'}\n" if (defined($element->{'section_ref'})); |
|
print STDERR " with_section: $element->{'with_section'}->{'texi'}\n" if (defined($element->{'with_section'})); |
|
} |
|
elsif ($element->{'footnote'}) |
|
{ |
|
print STDERR "footnotes($element->{'id'}, file $element->{'file'})\n"; |
|
} |
|
else |
|
{ |
|
my $number = "UNNUMBERED"; |
|
$number = $element->{'number'} if ($element->{'number'}); |
|
print STDERR "$number ($element->{'id'}, $is_toplevel, level $element->{'level'}-$element->{'toc_level'}, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n"; |
|
print STDERR " with_node: $element->{'with_node'}->{'texi'}\n" if (defined($element->{'with_node'})); |
|
print STDERR " node_ref: $element->{'node_ref'}->{'texi'}\n" if (defined($element->{'node_ref'})); |
|
} |
|
|
|
if (!$element->{'footnote'}) |
|
{ |
|
if (!defined($files{$element->{'file'}})) |
|
{ |
|
die "Bug: files{\$element->{'file'}} undef element $element->{'texi'}, file $element->{'file'}."; |
|
} |
|
print STDERR " file: $element->{'file'} $files{$element->{'file'}}, counter $files{$element->{'file'}}->{'counter'}\n"; |
|
} |
|
print STDERR " level: $element->{'level'}\n" if (defined($element->{'level'})); |
|
print STDERR " TOP($toplevel) " if ($element->{'top'}); |
|
print STDERR " u: $element->{'up'}->{'texi'}\n" if (defined($element->{'up'})); |
|
print STDERR " ch: $element->{'child'}->{'texi'}\n" if (defined($element->{'child'})); |
|
print STDERR " fb: $element->{'fastback'}->{'texi'}\n" if (defined($element->{'fastback'})); |
|
print STDERR " b: $element->{'back'}->{'texi'}\n" if (defined($element->{'back'})); |
|
print STDERR " p: $element->{'prev'}->{'texi'}\n" if (defined($element->{'prev'})); |
|
print STDERR " u: $element->{'sectionup'}->{'texi'}\n" if (defined($element->{'sectionup'})); |
|
print STDERR " n: $element->{'sectionnext'}->{'texi'}\n" if (defined($element->{'sectionnext'})); |
|
print STDERR " t_n: $element->{'toplevelnext'}->{'texi'}\n" if (defined($element->{'toplevelnext'})); |
|
print STDERR " t_p: $element->{'toplevelprev'}->{'texi'}\n" if (defined($element->{'toplevelprev'})); |
|
print STDERR " n_u: $element->{'nodeup'}->{'texi'}\n" if (defined($element->{'nodeup'})); |
|
print STDERR " f: $element->{'forward'}->{'texi'}\n" if (defined($element->{'forward'})); |
|
print STDERR " follow: $element->{'following'}->{'texi'}\n" if (defined($element->{'following'})); |
|
print STDERR " m_p: $element->{'menu_prev'}->{'texi'}\n" if (defined($element->{'menu_prev'})); |
|
print STDERR " m_n: $element->{'menu_next'}->{'texi'}\n" if (defined($element->{'menu_next'})); |
|
print STDERR " m_u: $element->{'menu_up'}->{'texi'}\n" if (defined($element->{'menu_up'})); |
|
print STDERR " m_ch: $element->{'menu_child'}->{'texi'}\n" if (defined($element->{'menu_child'})); |
|
print STDERR " ff: $element->{'fastforward'}->{'texi'}\n" if (defined($element->{'fastforward'})); |
|
print STDERR " n_f: $element->{'nextfile'}->{'texi'}\n" if (defined($element->{'nextfile'})); |
|
print STDERR " p_f: $element->{'prevfile'}->{'texi'}\n" if (defined($element->{'prevfile'})); |
|
my $section_childs = ''; |
|
if (defined($element->{'section_childs'})) |
|
{ |
|
foreach my $child (@{$element->{'section_childs'}}) |
|
{ |
|
$section_childs .= "$child->{'texi'}|"; |
|
} |
|
} |
|
print STDERR " s_chs: $section_childs\n" if ($section_childs ne ''); |
|
my $node_childs = ''; |
|
if (defined($element->{'node_childs'})) |
|
{ |
|
foreach my $child (@{$element->{'node_childs'}}) |
|
{ |
|
$node_childs .= "$child->{'texi'}|"; |
|
} |
|
} |
|
print STDERR " n_chs: $node_childs\n" if ($node_childs ne ''); |
|
|
|
if (defined($element->{'menu_up_hash'})) |
|
{ |
|
print STDERR " parent nodes:\n"; |
|
foreach my $menu_up (keys%{$element->{'menu_up_hash'}}) |
|
{ |
|
print STDERR " $menu_up ($element->{'menu_up_hash'}->{$menu_up})\n"; |
|
} |
|
} |
|
print STDERR " places: $element->{'place'}\n"; |
|
foreach my $place(@{$element->{'place'}}) |
|
{ |
|
if (!$place->{'entry'} and !$place->{'float'} and !$place->{'texi'} and !$place->{'contents'} and !$place->{'shortcontents'} and (!defined($place->{'command'} or $place->{'command'} ne 'printindex'))) |
|
{ |
|
print STDERR "BUG: unknown placed stuff ========\n"; |
|
foreach my $key (keys(%$place)) |
|
{ |
|
print STDERR "$key: $place->{$key}\n"; |
|
} |
|
print STDERR "==================================\n"; |
|
} |
|
elsif ($place->{'entry'}) |
|
{ |
|
print STDERR " index($place): $place->{'entry'} ($place->{'id'}, $place->{'file'})\n"; |
|
} |
|
elsif ($place->{'anchor'}) |
|
{ |
|
print STDERR " anchor: $place->{'texi'} ($place->{'id'}, $place->{'file'})\n"; |
|
} |
|
elsif ($place->{'float'}) |
|
{ |
|
if (defined($place->{'texi'})) |
|
{ |
|
print STDERR " float($place): $place->{'texi'} ($place->{'id'}, $place->{'file'})\n"; |
|
} |
|
else |
|
{ |
|
print STDERR " float($place): NO LABEL ($place->{'id'}, $place->{'file'})\n"; |
|
} |
|
} |
|
elsif ($place->{'contents'}) |
|
{ |
|
print STDERR " contents\n"; |
|
} |
|
elsif ($place->{'shortcontents'}) |
|
{ |
|
print STDERR " shortcontents\n"; |
|
} |
|
elsif (defined($place->{'command'}) and $place->{'command'} eq 'printindex') |
|
{ |
|
print STDERR " printindex $place->{'name'}\n"; |
|
} |
|
else |
|
{ |
|
print STDERR " heading: $place->{'texi'} ($place->{'id'}, $place->{'file'})\n"; |
|
} |
|
} |
|
} |
|
########################### end debug prints |
|
} |
|
|
|
sub add_file($) |
|
{ |
|
my $file = shift; |
|
if ($files{$file}) |
|
{ |
|
$files{$file}->{'counter'}++; |
|
} |
|
else |
|
{ |
|
$files{$file} = { |
|
'counter' => 1, |
|
'relative_foot_num' => 0, |
|
'foot_lines' => [] |
|
}; |
|
} |
|
} |
|
|
|
# find parent element which is a toplevel element |
|
sub get_top($) |
|
{ |
|
my $element = shift; |
|
if ($element->{'node'}) |
|
{ |
|
if (defined($element->{'section_ref'})) |
|
{ |
|
$element = $element->{'section_ref'}; |
|
} |
|
else |
|
{ |
|
return undef; |
|
} |
|
} |
|
return undef if ($element eq $element_before_anything); |
|
my $up = $element; |
|
while (!$up->{'toplevel'} and $up->{'tag'} ne 'top') |
|
{ |
|
if (!defined($up->{'sectionup'})) |
|
{ |
|
# If there is no section, it is normal not to have toplevel element, |
|
# and it is also the case if there is a low level element before |
|
# a top level element |
|
return undef; |
|
} |
|
$up = $up->{'sectionup'}; |
|
} |
|
return $up; |
|
} |
|
|
|
sub get_node($) |
|
{ |
|
my $element = shift; |
|
return undef if (!defined($element)); |
|
return $element if ($element->{'node'}); |
|
return $element->{'with_node'} if ($element->{'with_node'}); |
|
} |
|
|
|
sub do_section_names($$) |
|
{ |
|
my $number = shift; |
|
my $section = shift; |
|
my $texi = &$Texi2HTML::Config::heading_texi($section->{'tag'}, $section->{'texi'}, $section->{'number'}); |
|
$section->{'text'} = substitute_line($texi, "\@$section->{'tag'}", undef, $section->{'line_nr'}); |
|
# no need for translation since there is no line number it should never |
|
# appear in error messages. |
|
$section->{'text_nonumber'} = substitute_line($section->{'texi'}, "\@$section->{'tag'} no number"); |
|
# backward compatibility |
|
# Removed from doc in nov 2009 |
|
$section->{'name'} = $section->{'text_nonumber'}; |
|
$section->{'no_texi'} = remove_texi($texi); |
|
$section->{'simple_format'} = simple_format(undef,undef,"\@$section->{'tag'} simple_format", $texi); |
|
$section->{'heading_texi'} = $texi; |
|
} |
|
|
|
# get the html names from the texi for all elements |
|
sub do_names() |
|
{ |
|
print STDERR "# Doing ". scalar(keys(%nodes)) . " nodes, ". |
|
scalar(keys(%sections)) . " sections, " . |
|
scalar(keys(%headings)) . " headings in ". $#elements_list . |
|
" elements\n" if ($T2H_DEBUG); |
|
# for nodes and anchors we haven't any state defined |
|
# This seems right, however, as we don't want @refs or @footnotes |
|
# or @anchors within nodes, section commands or anchors. |
|
$global_pass = '2 node names'; |
|
foreach my $node (keys(%nodes)) |
|
{ |
|
my $texi = &$Texi2HTML::Config::heading_texi($nodes{$node}->{'tag'}, |
|
$nodes{$node}->{'texi'}, undef); |
|
my $command = 'node'; |
|
$command = $nodes{$node}->{'tag'} if ($nodes{$node}->{'tag'}); |
|
$nodes{$node}->{'text'} = substitute_line ($texi, "\@$command", {'code_style' => 1}, $nodes{$node}->{'line_nr'}); |
|
$nodes{$node}->{'text_nonumber'} = $nodes{$node}->{'text'}; |
|
# backward compatibility -> maybe used to have the name without code_style ? |
|
# Removed from doc in nov 2009 |
|
$nodes{$node}->{'name'} = substitute_line($texi, "\@$command name"); |
|
$nodes{$node}->{'no_texi'} = remove_texi($texi); |
|
$nodes{$node}->{'simple_format'} = simple_format(undef, undef, "\@$command simple_format", $texi); |
|
$nodes{$node}->{'heading_texi'} = $texi; |
|
|
|
################# debug |
|
# if $nodes{$node}->{'external_node'} and $nodes{$node}->{'seen'} |
|
# this is a bug, since there are checks that the node hasn't an |
|
# external node syntax. |
|
msg_debug ("$nodes{$node}->{'texi'} is external and was seen", $nodes{$node}->{'line_nr'}) if ($nodes{$node}->{'seen'} and $nodes{$node}->{'external_node'}); |
|
################# end debug |
|
} |
|
$global_pass = '2 section names'; |
|
foreach my $number (keys(%sections)) |
|
{ |
|
do_section_names($number, $sections{$number}); |
|
} |
|
$global_pass = '2 heading names'; |
|
foreach my $number (keys(%headings)) |
|
{ |
|
do_section_names($number, $headings{$number}); |
|
} |
|
print STDERR "# Names done\n" if ($T2H_DEBUG); |
|
} |
|
|
|
|
|
#+++############################################################################ |
|
# # |
|
# Stuff related to Index generation # |
|
# # |
|
#---############################################################################ |
|
|
|
# called during pass_structure |
|
sub enter_index_entry($$$$$) |
|
{ |
|
my $prefix = shift; |
|
my $line_nr = shift; |
|
my $entry = shift; |
|
my $command = shift; |
|
my $state = shift; |
|
|
|
my $heading_element = $state->{'heading_element'}; |
|
my $current_element = $state->{'current_element'}; |
|
my $place = $state->{'place'}; |
|
my $region = $state->{'region'}; |
|
|
|
my $index_name = $index_prefix_to_name{$prefix}; |
|
if (!defined($index_name)) |
|
{ |
|
line_error (sprintf(__("Unknown index `%s'"), $prefix), $line_nr); |
|
} |
|
if ($current_element eq $element_before_anything) |
|
{ |
|
#line_warn ("Index entry before document: \@${prefix}index $entry", $line_nr); |
|
line_error (sprintf(__("Entry for index `%s' outside of any node"), $index_name), $line_nr); |
|
} |
|
$entry = trim_comment_spaces ($entry, "index entry in \@$command", $line_nr); |
|
# beware that the texinfo could be non empty, but the no_texi be empty. |
|
# So the $no_texi should be used to determine whether the entry is |
|
# empty or not. |
|
my $no_texi = remove_texi($entry); |
|
|
|
my $id; |
|
# don't add a specific index target if the index entry is in a special |
|
# region like @copying or the like or the index is not defined |
|
if (!defined($region)) |
|
{ |
|
$region = 'document'; |
|
# No id if the index is unknown. |
|
$id = 'IDX' . ++$document_idx_num if (defined($index_name)); |
|
} |
|
my $target = $id; |
|
|
|
# entry will later be in @code for code-like index entry. texi stays |
|
# the same. |
|
my $index_entry = { |
|
'entry' => $entry, |
|
'texi' => $entry, |
|
'element' => $heading_element, |
|
'real_element' => $current_element, |
|
'prefix' => $prefix, |
|
'id' => $id, |
|
'target' => $target, |
|
'command' => $command, |
|
'region' => $state->{'region'}, |
|
'line_nr' => $line_nr, |
|
'index_name' => $index_name |
|
}; |
|
|
|
my $id_text = $id; |
|
$id_text = 'NO ID' if (!defined($id)); |
|
print STDERR "# in $region enter \@$command ${prefix}index($no_texi) [$entry] with id $id_text ($index_entry)\n" |
|
if ($T2H_DEBUG & $DEBUG_INDEX); |
|
|
|
$index_entry->{'entry'} = '@code{'.$index_entry->{'entry'}.'}' |
|
if (defined($index_name) and |
|
defined($index_names{$index_name}->{'prefixes'}) and |
|
$index_names{$index_name}->{'prefixes'}->{$prefix} |
|
and $no_texi =~ /\S/); |
|
|
|
push @$place, $index_entry; |
|
|
|
#msg_debug("enter_index_entry: region $region, index_entry $index_entry, \@$command, texi `$entry'", $line_nr); |
|
|
|
# don't add the index entry to the list of index entries used for index |
|
# entry formatting, if the index entry appears in a region like copying |
|
# currently this is only used for debugging purposes, since the |
|
# index entries lists are broken by region now. |
|
push @index_labels, $index_entry unless (defined($state->{'region'})); |
|
|
|
# these lists are used to retrieve index entries in pass 3 |
|
push @{$Texi2HTML::THISDOC{'index_entries'}->{$region}->{$entry}->{'entries'}}, $index_entry; |
|
if (defined($index_name)) |
|
{ |
|
# this is used for @printindex |
|
push @{$Texi2HTML::THISDOC{'index_entries_array'}->{$index_name}}, $index_entry; |
|
# this is used for targets |
|
push @{$Texi2HTML::THISDOC{'index_entries_region_array'}->{$region}}, $index_entry; |
|
} |
|
else |
|
{ |
|
push @unknown_index_index_entries, $index_entry; |
|
} |
|
} |
|
|
|
# these variables are global, so great care should be taken with |
|
# state->{'multiple_state'}, ->{'region'}, ->{'region_pass'} and |
|
# {'outside_document'}. |
|
my $global_head_num = 0; # heading index. it is global for the main doc, |
|
# and taken from the state if in multiple_pass. |
|
my $global_foot_num = 0; |
|
my $global_relative_foot_num = 0; |
|
my @foot_lines = (); # footnotes |
|
my $copying_comment = ''; # comment constructed from text between |
|
# @copying and @end copying with licence |
|
my %acronyms_like = (); # acronyms or similar commands associated texts |
|
# the key are the commands, the values are |
|
# hash references associating shorthands to |
|
# texts. |
|
|
|
# detailmenu number of opened detailed menus |
|
sub fill_state($) |
|
{ |
|
my $state = shift; |
|
foreach my $key ('preformatted', 'code_style', 'math_style', 'keep_texi', |
|
'keep_nr', 'detailmenu', 'direntry', 'sec_num', 'menu', 'multiple_pass') |
|
{ |
|
$state->{$key} = 0 unless exists($state->{$key}); |
|
} |
|
|
|
$state->{'paragraph_style'} = [ '' ] unless exists($state->{'paragraph_style'}); |
|
$state->{'preformatted_stack'} = [ '' ] unless exists($state->{'preformatted_stack'}); |
|
$state->{'command_stack'} = [] unless exists($state->{'command_stack'}); |
|
$state->{'quotation_stack'} = [] unless exists($state->{'quotation_stack'}); |
|
# if there is no $state->{'element'} the first element is used |
|
if ((!$state->{'element'} or $state->{'element'}->{'before_anything'}) and (@elements_list)) |
|
{ |
|
$state->{'element'} = $elements_list[0]; |
|
} |
|
# this is consistent with what is done in rearrange_elements |
|
$state->{'element'} = {'file' => $docu_doc, 'texi' => 'VIRTUAL ELEMENT'} if (!$state->{'element'}); |
|
} |
|
|
|
sub do_element_directions ($) |
|
{ |
|
my $this_element = shift; |
|
#print STDERR "Doing hrefs for $this_element->{'texi'} First "; |
|
$Texi2HTML::HREF{'First'} = href($element_first, $this_element->{'file'}); |
|
#print STDERR "Last "; |
|
$Texi2HTML::HREF{'Last'} = href($element_last, $this_element->{'file'}); |
|
#print STDERR "Index "; |
|
$Texi2HTML::HREF{'Index'} = href($element_chapter_index, $this_element->{'file'}) if (defined($element_chapter_index)); |
|
#print STDERR "Top "; |
|
$Texi2HTML::HREF{'Top'} = href($element_top, $this_element->{'file'}); |
|
if ($Texi2HTML::Config::INLINE_CONTENTS) |
|
{ |
|
$Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $this_element->{'file'}); |
|
$Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $this_element->{'file'}); |
|
} |
|
else |
|
{ |
|
$Texi2HTML::HREF{'Contents'} = file_target_href($Texi2HTML::THISDOC{'toc_file'}, $this_element->{'file'}, $content_element{'contents'}->{'target'}) if (@{$Texi2HTML::TOC_LINES} and defined($content_element{'contents'})); |
|
$Texi2HTML::HREF{'Overview'} = file_target_href($Texi2HTML::THISDOC{'stoc_file'}, $this_element->{'file'}, $content_element{'shortcontents'}->{'target'}) if (@{$Texi2HTML::OVERVIEW} and defined($content_element{'shortcontents'})); |
|
} |
|
if ($Texi2HTML::THISDOC{'do_about'}) |
|
{ |
|
$Texi2HTML::HREF{'About'} = file_target_href($docu_about, $this_element->{'file'}, $Texi2HTML::Config::misc_pages_targets{'About'}); |
|
} |
|
$Texi2HTML::HREF{'Footnotes'} = file_target_href($docu_foot, $this_element->{'file'}, $Texi2HTML::Config::misc_pages_targets{'Footnotes'}); |
|
foreach my $direction (@element_directions) |
|
{ |
|
my $elem = $this_element->{$direction}; |
|
$Texi2HTML::NODE{$direction} = undef; |
|
$Texi2HTML::HREF{$direction} = undef; |
|
$Texi2HTML::NAME{$direction} = undef; |
|
#print STDERR "$direction \n"; |
|
next unless (defined($elem)); |
|
if ($elem->{'node'} or $elem->{'external_node'} or !$elem->{'seen'}) |
|
{ |
|
$Texi2HTML::NODE{$direction} = $elem->{'text'}; |
|
} |
|
elsif ($elem->{'with_node'}) |
|
{ |
|
$Texi2HTML::NODE{$direction} = $elem->{'with_node'}->{'text'}; |
|
} |
|
if (!$elem->{'seen'}) |
|
{ |
|
$Texi2HTML::HREF{$direction} = do_external_href($elem->{'texi'}); |
|
} |
|
else |
|
{ |
|
$Texi2HTML::HREF{$direction} = href($elem, $this_element->{'file'}); |
|
} |
|
$Texi2HTML::NAME{$direction} = $elem->{'text'}; |
|
$Texi2HTML::NO_TEXI{$direction} = $elem->{'no_texi'}; |
|
$Texi2HTML::SIMPLE_TEXT{$direction} = $elem->{'simple_format'}; |
|
#print STDERR "$direction ($this_element->{'texi'}): \n NO_TEXI: $Texi2HTML::NO_TEXI{$direction}\n NAME $Texi2HTML::NAME{$direction}\n NODE $Texi2HTML::NODE{$direction}\n HREF $Texi2HTML::HREF{$direction}\n\n"; |
|
} |
|
#print STDERR "\nDone hrefs for $this_element->{'texi'}\n"; |
|
} |
|
|
|
sub open_out_file($) |
|
{ |
|
my $new_file = shift; |
|
my $do_page_head = 0; |
|
# if the filehandle is closed, with fileno undef, open_out |
|
# is called with the second argument true, which leads to opening |
|
# the file in append mode, to avoid overwriting the previous |
|
# file. |
|
if ($files{$new_file}->{'filehandle'} and defined(fileno($files{$new_file}->{'filehandle'}))) |
|
{ |
|
$Texi2HTML::THISDOC{'FH'} = $files{$new_file}->{'filehandle'}; |
|
} |
|
else |
|
{ |
|
my $known_file = 0; |
|
if ($files{$new_file}->{'filehandle'}) |
|
{ |
|
$known_file = 1; |
|
document_warn ("The file $new_file was already closed and is reopened"); |
|
} |
|
$Texi2HTML::THISDOC{'FH'} = open_out("$docu_rdir$new_file", $known_file); |
|
#print STDERR "OPEN $docu_rdir$file, $Texi2HTML::THISDOC{'FH'}". scalar($Texi2HTML::THISDOC{'FH'})."\n"; |
|
$files{$new_file}->{'filehandle'} = $Texi2HTML::THISDOC{'FH'}; |
|
$do_page_head = !$known_file; |
|
} |
|
return $do_page_head; |
|
} |
|
|
|
sub set_line_nr_in_stack($$$) |
|
{ |
|
my $state = shift; |
|
my $stack = shift; |
|
my $line_nr = shift; |
|
|
|
if ($state->{'keep_texi'} and defined($line_nr)) |
|
{ |
|
my $stack_index = $#$stack; |
|
while ($stack_index >= 0 and defined($stack->[$stack_index]->{'keep_line_nr'})) |
|
{ |
|
push @{$stack->[$stack_index]->{'keep_line_nr'}}, $line_nr; |
|
$stack_index --; |
|
} |
|
} |
|
} |
|
|
|
sub unref_file($) |
|
{ |
|
my $file = shift; |
|
$files{$file}->{'counter'}--; |
|
print STDERR "# Unref file $file, remaining counter $files{$file}->{'counter'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
|
|
} |
|
|
|
sub pass_text($$) |
|
{ |
|
my $doc_lines = shift; |
|
my $doc_numbers = shift; |
|
my %state; |
|
fill_state(\%state); |
|
my @stack; |
|
my $text = ''; |
|
my $doc_nr; |
|
my $in_doc = 0; |
|
my @text =(); |
|
my $one_section = 1 if (@elements_list <= 1); |
|
|
|
push_state(\%state); |
|
|
|
$global_pass = '3 prepare names'; |
|
set_special_names(); |
|
$footnote_element->{'text'} = $Texi2HTML::NAME{'Footnotes'}; |
|
# We set titlefont only if the titlefont appeared in the top element |
|
if (defined($element_top->{'titlefont'})) |
|
{ |
|
$Texi2HTML::THISDOC{'titlefont_texi'} = $element_top->{'titlefont'}; |
|
# backward compatibility nov 2009 |
|
$value{'_titlefont'} = $element_top->{'titlefont'}; |
|
} |
|
|
|
# prepare %Texi2HTML::THISDOC |
|
$Texi2HTML::THISDOC{'command_stack'} = $state{'command_stack'}; |
|
|
|
#foreach my $texi_cmd (('shorttitlepage', 'settitle', 'author', 'title', |
|
# 'subtitle')) |
|
#{ |
|
# $Texi2HTML::THISDOC{$texi_cmd . '_texi'} = $value{'_' . $texi_cmd}; |
|
#} |
|
$Texi2HTML::THISDOC{'top_texi'} = $section_top->{'texi'} if (defined($section_top)); |
|
|
|
$Texi2HTML::THISDOC{'fulltitle_texi'} = ''; |
|
foreach my $possible_fulltitle('settitle', 'title', 'shorttitlepage', 'top', 'titlefont') |
|
{ |
|
if (defined($Texi2HTML::THISDOC{$possible_fulltitle . '_texi'}) and $Texi2HTML::THISDOC{$possible_fulltitle . '_texi'} =~ /\S/) |
|
{ |
|
$Texi2HTML::THISDOC{'fulltitle_texi'} = $Texi2HTML::THISDOC{$possible_fulltitle . '_texi'}; |
|
last; |
|
} |
|
} |
|
$Texi2HTML::THISDOC{'simpletitle_texi'} = ''; |
|
foreach my $possible_simpletitle('settitle', 'shorttitlepage') |
|
{ |
|
if (defined($Texi2HTML::THISDOC{$possible_simpletitle . '_texi'}) and $Texi2HTML::THISDOC{$possible_simpletitle . '_texi'} =~ /\S/) |
|
{ |
|
$Texi2HTML::THISDOC{'simpletitle_texi'} = $Texi2HTML::THISDOC{$possible_simpletitle . '_texi'}; |
|
last; |
|
} |
|
} |
|
|
|
foreach my $doc_thing (('shorttitlepage', 'settitle', 'author', |
|
'titlefont', 'subtitle', 'title', 'fulltitle', 'simpletitle')) |
|
{ |
|
my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'}; |
|
$Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi, "\@$doc_thing", undef, $Texi2HTML::THISDOC{$doc_thing . '_line_nr'}); |
|
$Texi2HTML::THISDOC{$doc_thing . '_no_texi'} = |
|
remove_texi($thing_texi); |
|
$Texi2HTML::THISDOC{$doc_thing . '_simple_format'} = |
|
simple_format(undef, undef, "simple_format \@$doc_thing", $thing_texi); |
|
} |
|
|
|
|
|
# find the triplet (Top name, Top with texi removed, Top simply formatted) |
|
# the corresponding href is used a lot but these are only used because |
|
# they are used in LINKS_BUTTONS... |
|
|
|
my $element_top_Top = [undef,undef,undef]; |
|
my $node_top_Top = [undef,undef,undef]; |
|
# Preferred Top name is the element_top name if it is not the @node Top |
|
# the @node Top may also be used, but before fulltitle is tried |
|
if (defined($element_top)) |
|
{ |
|
if ($element_top->{'node'} and $element_top->{'texi'} =~ /^Top$/i) |
|
{ |
|
$node_top_Top = [ $element_top->{'text'}, $element_top->{'no_texi'}, $element_top->{'simple_format'} ]; |
|
} |
|
else |
|
{ |
|
$element_top_Top = [ $element_top->{'text'}, $element_top->{'no_texi'}, $element_top->{'simple_format'} ]; |
|
} |
|
} |
|
# FIXME remove fulltitle? |
|
foreach my $possible_top ( |
|
[substitute_line($Texi2HTML::Config::TOP_HEADING, '$TOP_HEADING'), |
|
remove_texi($Texi2HTML::Config::TOP_HEADING), |
|
simple_format(undef, undef, 'simple_format $TOP_HEADING', $Texi2HTML::Config::TOP_HEADING)], |
|
$element_top_Top, |
|
[$Texi2HTML::THISDOC{'fulltitle'}, |
|
$Texi2HTML::THISDOC{'fulltitle_no_texi'}, |
|
$Texi2HTML::THISDOC{'fulltitle_simple_format'}], |
|
$node_top_Top |
|
) |
|
{ |
|
if (defined($possible_top->[0]) and $possible_top->[0] =~ /\S/) |
|
{ |
|
($Texi2HTML::NAME{'Top'}, $Texi2HTML::NO_TEXI{'Top'}, $Texi2HTML::SIMPLE_TEXT{'Top'}) = @$possible_top; |
|
last; |
|
} |
|
} |
|
|
|
$Texi2HTML::THISDOC{'program'} = $THISPROG; |
|
$Texi2HTML::THISDOC{'program_homepage'} = $T2H_HOMEPAGE; |
|
$Texi2HTML::THISDOC{'program_authors'} = $T2H_AUTHORS; |
|
foreach my $command (('authors', 'subtitles', 'titles')) |
|
{ |
|
$Texi2HTML::THISDOC{$command} = []; |
|
my $i; |
|
for ($i = 0; $i < $#{$Texi2HTML::THISDOC{$command .'_texi'}} + 1; $i++) |
|
{ |
|
my $texi_line = $Texi2HTML::THISDOC{$command .'_texi'}->[$i]; |
|
my $command_line_nr = $Texi2HTML::THISDOC{$command .'_line_nr'}->[$i]; |
|
chomp ($texi_line); |
|
$Texi2HTML::THISDOC{$command}->[$i] = substitute_line($texi_line, "\@$command", undef, $command_line_nr); |
|
#print STDERR "$command:$i: $Texi2HTML::THISDOC{$command}->[$i]\n"; |
|
} |
|
} |
|
|
|
$Texi2HTML::THISDOC{'do_about'} = 1 unless (defined($Texi2HTML::THISDOC{'do_about'}) or $one_section or (not Texi2HTML::Config::get_conf('SPLIT') and not Texi2HTML::Config::get_conf('headers'))); |
|
|
|
$Texi2HTML::NAME{'First'} = $element_first->{'text'}; |
|
$Texi2HTML::NAME{'Last'} = $element_last->{'text'}; |
|
$Texi2HTML::NAME{'Index'} = $element_chapter_index->{'text'} if (defined($element_chapter_index)); |
|
$Texi2HTML::NAME{'Index'} = $Texi2HTML::Config::INDEX_CHAPTER if ($Texi2HTML::Config::INDEX_CHAPTER ne ''); |
|
|
|
$Texi2HTML::NO_TEXI{'First'} = $element_first->{'no_texi'}; |
|
$Texi2HTML::NO_TEXI{'Last'} = $element_last->{'no_texi'}; |
|
$Texi2HTML::NO_TEXI{'Index'} = $element_chapter_index->{'no_texi'} if (defined($element_chapter_index)); |
|
$Texi2HTML::SIMPLE_TEXT{'First'} = $element_first->{'simple_format'}; |
|
$Texi2HTML::SIMPLE_TEXT{'Last'} = $element_last->{'simple_format'}; |
|
$Texi2HTML::SIMPLE_TEXT{'Index'} = $element_chapter_index->{'simple_format'} if (defined($element_chapter_index)); |
|
|
|
# We do the regions formatting here, even if they never appear. |
|
# so we should be very carefull to take into accout 'outside_document' to |
|
# avoid messing with information that has to be set in the main document. |
|
# FIXME also the error messages will appear even though the corresponding |
|
# texinfo is never used. Since no state is passed to the do_special_region_lines |
|
# 'outside_document' will be true. Also 'multiple_pass' is equal to -1 |
|
# for this case. |
|
$global_pass = '3 prepare regions'; |
|
|
|
my ($region_text, $region_no_texi, $region_simple_format); |
|
($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('documentdescription'); |
|
&$Texi2HTML::Config::documentdescription($region_lines{'documentdescription'}, $region_text, $region_no_texi, $region_simple_format); |
|
|
|
# do copyright notice inserted in comment at the beginning of the files |
|
($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('copying'); |
|
$copying_comment = &$Texi2HTML::Config::copying_comment($region_lines{'copying'}, $region_text, $region_no_texi, $region_simple_format); |
|
|
|
$Texi2HTML::THISDOC{'copying_comment'} = $copying_comment; |
|
# must be after toc_body, but before titlepage |
|
foreach my $command ('contents', 'shortcontents') |
|
{ |
|
next if (!defined($content_element{$command})); |
|
my $toc_lines = &$Texi2HTML::Config::inline_contents(undef, $command, $content_element{$command}, \@sections_list); |
|
@{$Texi2HTML::THISDOC{'inline_contents'}->{$command}} = @$toc_lines if (defined($toc_lines)); |
|
} |
|
|
|
($region_text, $region_no_texi, $region_simple_format) = do_special_region_lines('titlepage'); |
|
|
|
&$Texi2HTML::Config::titlepage($region_lines{'titlepage'}, $region_text, $region_no_texi, $region_simple_format); |
|
|
|
$global_pass = '3'; |
|
&$Texi2HTML::Config::init_out(); |
|
|
|
# FIXME It is not clear whether it should be here or before |
|
# command_handler_output calls. After, it means that |
|
# command_handler_output may modify the initializations. Before |
|
# it allows to look at the values from the preceding pass. |
|
texinfo_initialization(2); |
|
|
|
foreach my $handler(@Texi2HTML::Config::command_handler_output) |
|
{ |
|
&$handler; |
|
} |
|
|
|
############################################################################ |
|
# print frame and frame toc file |
|
# |
|
if ( $Texi2HTML::Config::FRAMES ) |
|
{ |
|
my $FH = open_out($docu_frame_file); |
|
print STDERR "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE; |
|
&$Texi2HTML::Config::print_frame($FH, $docu_toc_frame_file, $docu_top_file); |
|
close_out($FH, $docu_frame_file); |
|
|
|
$FH = open_out($docu_toc_frame_file); |
|
print STDERR "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE; |
|
&$Texi2HTML::Config::print_toc_frame($FH, $Texi2HTML::OVERVIEW); |
|
close_out($FH, $docu_toc_frame_file); |
|
} |
|
|
|
|
|
|
|
############################################################################ |
|
# Start processing the document |
|
# |
|
|
|
#my $FH; |
|
my $line_nr; |
|
my $current_file; |
|
my $first_section = 0; # 1 if it is the first section of a page |
|
my $previous_is_top = 0; # 1 if it is the element following the top element |
|
|
|
my $cline; |
|
# this is true for the state that goes through the document |
|
$state{'inside_document'} = 1; |
|
while (@$doc_lines) |
|
{ |
|
$cline = shift @$doc_lines; |
|
my $chomped_line = $cline; |
|
if (!chomp($chomped_line) and @$doc_lines) |
|
{ # if the line has no end of line it is concatenated with the next |
|
# this shouldn't happen anymore. And will certainly mess up |
|
# line counting. Let it be a bug. |
|
msg_debug ("no end of line line passed in doc_line",$line_nr); |
|
$doc_lines->[0] = $cline . $doc_lines->[0]; |
|
next; |
|
} |
|
$line_nr = shift (@$doc_numbers); |
|
$Texi2HTML::THISDOC{'line_nr'} = $line_nr; |
|
print STDERR "BUG: line_nr not defined in pass_text. cline: $cline" if (!defined($cline)); |
|
#dump_stack(\$text, \@stack, \%state); |
|
|
|
# make sure the current state from here is $Texi2HTML::THIS_ELEMENT |
|
# in case it was set by the user. |
|
$state{'element'} = $Texi2HTML::THIS_ELEMENT if (defined($Texi2HTML::THIS_ELEMENT)); |
|
#print STDERR "PASS_TEXT($line_nr->{'line_nr'})$cline"; |
|
if (!$state{'raw'} and !$state{'verb'}) |
|
{ |
|
my $tag = ''; |
|
$tag = $1 if ($cline =~ /^\@(\w+)/); |
|
if ($tag eq 'setfilename' and $Texi2HTML::Config::IGNORE_BEFORE_SETFILENAME) |
|
{ |
|
if (defined($Texi2HTML::THIS_ELEMENT)) |
|
{ |
|
line_warn (sprintf(__("\@%s after the first element"), $tag), $line_nr); |
|
} |
|
else |
|
{ |
|
@{$Texi2HTML::THIS_SECTION} = (); |
|
} |
|
} |
|
|
|
if (($tag eq 'node') or (defined($sec2level{$tag}) and ($tag !~ /heading/))) |
|
{ |
|
# in pass text node and section shouldn't appear in formats |
|
#print STDERR "close_stack before \@$tag\n"; |
|
#print STDERR "text!$text%" if (! @stack); |
|
close_stack(\$text, \@stack, \%state, $line_nr); |
|
msg_debug ("text undef", $line_nr) if (!defined($text)); |
|
push @{$Texi2HTML::THIS_SECTION}, $text if ($text ne ''); |
|
$text = ''; |
|
|
|
$state{'sec_num'}++ if ($sec2level{$tag} and ($tag ne 'top')); |
|
my $new_element; |
|
my $current_element; |
|
|
|
# handle node and structuring elements |
|
$current_element = shift (@all_elements); |
|
########################## begin debug section |
|
if (!defined($current_element)) |
|
{ |
|
msg_debug ("No element left for $cline", $line_nr); |
|
} |
|
if ($current_element->{'node'}) |
|
{ |
|
print STDERR 'NODE ' . "$current_element->{'texi'}($current_element->{'file'})" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
print STDERR "($current_element->{'section_ref'}->{'texi'})" if ($current_element->{'section_ref'} and ($T2H_DEBUG & $DEBUG_ELEMENTS)); |
|
} |
|
else |
|
{ |
|
print STDERR 'SECTION ' . $current_element->{'texi'} if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
print STDERR ": $cline" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
########################## end debug section |
|
|
|
# The element begins a new section if there is no previous |
|
# or the reference element is not the same |
|
if (defined($current_element->{'element_ref'}) and (!$Texi2HTML::THIS_ELEMENT or ($current_element->{'element_ref'} ne $Texi2HTML::THIS_ELEMENT))) |
|
{ |
|
$new_element = $current_element->{'element_ref'}; |
|
|
|
########################### debug |
|
my $old = 'NO_OLD'; |
|
$old = $Texi2HTML::THIS_ELEMENT->{'texi'} if (defined($Texi2HTML::THIS_ELEMENT)); |
|
print STDERR "NEW: $new_element->{'texi'}, OLD: $old\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
########################### end debug |
|
# print the element that just finished |
|
if ($Texi2HTML::THIS_ELEMENT) |
|
{ |
|
finish_element($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, $new_element, $first_section); |
|
$first_section = 0; |
|
$previous_is_top = 0 if (!$Texi2HTML::THIS_ELEMENT->{'top'}); |
|
@{$Texi2HTML::THIS_SECTION} = (); |
|
} |
|
else |
|
{ |
|
print STDERR "# Writing elements:" if ($T2H_VERBOSE); |
|
if ($Texi2HTML::Config::IGNORE_PREAMBLE_TEXT) |
|
{ |
|
@{$Texi2HTML::THIS_SECTION} = (); |
|
} |
|
# remove empty for the first document lines |
|
shift @{$Texi2HTML::THIS_SECTION} while (@{$Texi2HTML::THIS_SECTION} and ($Texi2HTML::THIS_SECTION->[0] =~ /^\s*$/)); |
|
my $title = &$Texi2HTML::Config::print_title(); |
|
unshift @{$Texi2HTML::THIS_SECTION}, $title if (defined($title) and $title ne ''); |
|
} |
|
# begin new element |
|
$Texi2HTML::THIS_ELEMENT = $new_element; |
|
$state{'element'} = $Texi2HTML::THIS_ELEMENT; |
|
|
|
do_element_directions($Texi2HTML::THIS_ELEMENT); |
|
unref_file ($Texi2HTML::THIS_ELEMENT->{'file'}); |
|
#if (!defined($previous_file) or ($Texi2HTML::THIS_ELEMENT->{'file'} ne $previous_file)) |
|
if (!defined($current_file) or ($Texi2HTML::THIS_ELEMENT->{'file'} ne $current_file)) |
|
{ |
|
$current_file = $Texi2HTML::THIS_ELEMENT->{'file'}; |
|
print STDERR "\n" if ($T2H_VERBOSE and !$T2H_DEBUG); |
|
print STDERR "# Writing to $docu_rdir$current_file " if $T2H_VERBOSE; |
|
my $do_page_head = open_out_file($current_file); |
|
if ($Texi2HTML::THIS_ELEMENT->{'top'}) |
|
{ |
|
&$Texi2HTML::Config::print_Top_header($Texi2HTML::THISDOC{'FH'}, $do_page_head); |
|
$previous_is_top = 1; |
|
} |
|
else |
|
{ |
|
&$Texi2HTML::Config::print_page_head($Texi2HTML::THISDOC{'FH'}) if ($do_page_head); |
|
&$Texi2HTML::Config::print_chapter_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if Texi2HTML::Config::get_conf('SPLIT') eq 'chapter'; |
|
&$Texi2HTML::Config::print_section_header($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT) if Texi2HTML::Config::get_conf('SPLIT') eq 'section'; |
|
} |
|
$first_section = 1; |
|
} |
|
print STDERR "." if ($T2H_VERBOSE); |
|
print STDERR "\n" if ($T2H_DEBUG); |
|
} |
|
|
|
my $cmd_line = $cline; |
|
$cmd_line =~ s/\@$tag\s*//; |
|
|
|
######################## begin debug |
|
msg_debug ("Element $current_element current_element->{'tag_level'} not defined", $line_nr) |
|
if (!defined($current_element->{'tag_level'})); |
|
msg_debug ("Element $current_element $tag ne ".var_to_str($current_element->{'tag'}), $line_nr) |
|
if ($tag ne 'node' and (!defined($current_element->{'tag'}) or $tag ne $current_element->{'tag'})); |
|
msg_debug ("Element $current_element ".var_to_str($current_element->{'tag'})." is not a node, but tag is a node", $line_nr) |
|
if ($tag eq 'node' and !$current_element->{'node'}); |
|
######################## end debug |
|
|
|
my $heading_formatted = &$Texi2HTML::Config::element_heading($current_element, $tag, $cmd_line, substitute_line($cmd_line, "\@$tag"), undef, $one_section, $current_element->{'this'}, $first_section, $current_element->{'top'}, $previous_is_top, $cline, $current_element->{'id'}, $new_element); |
|
push @{$Texi2HTML::THIS_SECTION}, $heading_formatted if (defined($heading_formatted) and ($heading_formatted ne '')); |
|
next; |
|
} |
|
} |
|
|
|
set_line_nr_in_stack(\%state, \@stack, $line_nr); |
|
scan_line($cline, \$text, \@stack, \%state, $line_nr); |
|
|
|
#print STDERR "after scan_line: $cline"; |
|
#dump_stack(\$text, \@stack, \%state); |
|
next if (@stack); |
|
if ($text ne '') |
|
{ |
|
push @{$Texi2HTML::THIS_SECTION}, $text; |
|
$text = ''; |
|
} |
|
} |
|
# close stack at the end of pass text |
|
close_stack(\$text, \@stack, \%state, $line_nr); |
|
if (defined($text)) |
|
{ |
|
push @{$Texi2HTML::THIS_SECTION}, $text; |
|
} |
|
print STDERR "\n" if ($T2H_VERBOSE); |
|
|
|
# if no sections, then simply print document as is |
|
if ($one_section) |
|
{ |
|
# may happen if there are 0 sections |
|
if (! defined($Texi2HTML::THISDOC{'FH'})) |
|
{ |
|
open_out_file($docu_doc); |
|
&$Texi2HTML::Config::print_page_head($Texi2HTML::THISDOC{'FH'}); |
|
shift @{$Texi2HTML::THIS_SECTION} while (@{$Texi2HTML::THIS_SECTION} and ($Texi2HTML::THIS_SECTION->[0] =~ /^\s*$/)); |
|
my $title = &$Texi2HTML::Config::print_title(); |
|
unshift @{$Texi2HTML::THIS_SECTION}, $title if (defined($title) and $title ne ''); |
|
} |
|
if (@foot_lines) |
|
{ |
|
&$Texi2HTML::Config::foot_section (\@foot_lines); |
|
push @{$Texi2HTML::THIS_SECTION}, @foot_lines; |
|
} |
|
print STDERR "# Write the section $Texi2HTML::THIS_ELEMENT->{'texi'}\n" if ($T2H_VERBOSE); |
|
&$Texi2HTML::Config::one_section($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT); |
|
close_out($Texi2HTML::THISDOC{'FH'}, $docu_doc_file); |
|
# no misc element is done |
|
return; |
|
} |
|
|
|
finish_element ($Texi2HTML::THISDOC{'FH'}, $Texi2HTML::THIS_ELEMENT, undef, $first_section); |
|
|
|
############################################################################ |
|
# Print ToC, Overview, Footnotes |
|
# |
|
foreach my $direction (@element_directions) |
|
{ |
|
$Texi2HTML::HREF{$direction} = undef; |
|
delete $Texi2HTML::HREF{$direction}; |
|
# it is better to undef in case the references to these hash entries |
|
# are used, as if deleted, the |
|
# references are still refering to the old, undeleted element |
|
# (we could do both) |
|
$Texi2HTML::NAME{$direction} = undef; |
|
$Texi2HTML::NO_TEXI{$direction} = undef; |
|
$Texi2HTML::SIMPLE_TEXT{$direction} = undef; |
|
$Texi2HTML::NODE{$direction} = undef; |
|
|
|
$Texi2HTML::THIS_ELEMENT = undef; |
|
} |
|
my $about_body; |
|
$about_body = &$Texi2HTML::Config::about_body() if (defined($Texi2HTML::Config::about_body)); |
|
# @foot_lines is emptied in finish_element if footnotestyle separate |
|
my %misc_page_infos = ( |
|
'Footnotes' => { 'file' => $docu_foot_file, |
|
'relative_file' => $docu_foot, |
|
'process' => $Texi2HTML::Config::print_Footnotes, |
|
'section' => \@foot_lines }, |
|
'Contents' => { 'file' => $docu_toc_file, |
|
'relative_file' => $docu_toc, |
|
'process' => $Texi2HTML::Config::print_Toc, |
|
'section' => $Texi2HTML::TOC_LINES }, |
|
'Overview' => { 'file' => $docu_stoc_file, |
|
'relative_file' => $docu_stoc, |
|
'process' => $Texi2HTML::Config::print_Overview, |
|
'section' => $Texi2HTML::OVERVIEW }, |
|
'About' => { 'file' => $docu_about_file, |
|
'relative_file' => $docu_about, |
|
'process' => $Texi2HTML::Config::print_About, |
|
'section' => [$about_body] } |
|
); |
|
$misc_page_infos{'Footnotes'}->{'do'} = 1 if (@foot_lines); |
|
$misc_page_infos{'Contents'}->{'do'} = 1 if |
|
(@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::Config::INLINE_CONTENTS and (!Texi2HTML::Config::get_conf('setcontentsaftertitlepage') or !$Texi2HTML::Config::USE_TITLEPAGE_FOR_TITLE)); |
|
$misc_page_infos{'Overview'}->{'do'} = 1 if |
|
(@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::Config::INLINE_CONTENTS and (!Texi2HTML::Config::get_conf('setshortcontentsaftertitlepage') or !$Texi2HTML::Config::USE_TITLEPAGE_FOR_TITLE)); |
|
$misc_page_infos{'About'}->{'do'} = 1 if ($about_body and $Texi2HTML::THISDOC{'do_about'}); |
|
|
|
foreach my $misc_page('Footnotes', 'Contents', 'Overview', 'About') |
|
{ |
|
next unless ($misc_page_infos{$misc_page}->{'do'}); |
|
my $file = $misc_page_infos{$misc_page}->{'file'}; |
|
my $relative_file = $misc_page_infos{$misc_page}->{'relative_file'}; |
|
print STDERR "# writing $misc_page in $file\n" if $T2H_VERBOSE; |
|
my $saved_FH; |
|
my $open_new = 0; |
|
if ($relative_file ne $docu_doc) |
|
{ |
|
$saved_FH = $Texi2HTML::THISDOC{'FH'}; |
|
# Use open_out_file not to overwrite a file that the user would have |
|
# created |
|
open_out_file ($relative_file); |
|
print STDERR "# Opening $file for $misc_page\n" if $T2H_VERBOSE; |
|
$open_new = 1; |
|
} |
|
else |
|
{ |
|
print STDERR "# writing $misc_page in current file\n" if $T2H_VERBOSE; |
|
} |
|
foreach my $href_page (keys(%misc_page_infos)) |
|
{ |
|
$Texi2HTML::HREF{$href_page} = file_target_href( |
|
$misc_page_infos{$href_page}->{'relative_file'}, $relative_file, |
|
$Texi2HTML::Config::misc_pages_targets{$href_page}) |
|
if ($misc_page_infos{$href_page}->{'do'}); |
|
} |
|
#print STDERR "Doing hrefs for $misc_page First "; |
|
$Texi2HTML::HREF{'First'} = href($element_first, $relative_file); |
|
#print STDERR "Last "; |
|
$Texi2HTML::HREF{'Last'} = href($element_last, $relative_file); |
|
#print STDERR "Index "; |
|
$Texi2HTML::HREF{'Index'} = href($element_chapter_index, $relative_file) if (defined($element_chapter_index)); |
|
#print STDERR "Top "; |
|
$Texi2HTML::HREF{'Top'} = href($element_top, $relative_file); |
|
if ($Texi2HTML::Config::INLINE_CONTENTS) |
|
{ |
|
$Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $relative_file); |
|
$Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $relative_file); |
|
} |
|
$Texi2HTML::HREF{$misc_page} = '#' . $Texi2HTML::Config::misc_pages_targets{$misc_page}; |
|
$Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{$misc_page}; |
|
$Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{$misc_page}; |
|
$Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{$misc_page}; |
|
$Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{$misc_page}; |
|
$Texi2HTML::THIS_SECTION = $misc_page_infos{$misc_page}->{'section'} |
|
if defined($misc_page_infos{$misc_page}->{'section'}); |
|
&{$misc_page_infos{$misc_page}->{'process'}}($Texi2HTML::THISDOC{'FH'}, $open_new, $misc_page); |
|
|
|
if ($open_new) |
|
{ |
|
close_out($Texi2HTML::THISDOC{'FH'}, $file); |
|
$Texi2HTML::THISDOC{'FH'} = $saved_FH; |
|
} |
|
} |
|
|
|
unless (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
&$Texi2HTML::Config::print_page_foot($Texi2HTML::THISDOC{'FH'}); |
|
# this leaves the possibility for external code to close the file |
|
# without erroring out |
|
close_out ($Texi2HTML::THISDOC{'FH'}, $docu_doc_file) if (fileno($Texi2HTML::THISDOC{'FH'})); |
|
} |
|
pop_state(); |
|
} |
|
|
|
# print section, close file if needed. |
|
sub finish_element($$$$) |
|
{ |
|
my $FH = shift; |
|
my $element = shift; |
|
my $new_element = shift; |
|
my $first_section = shift; |
|
#print STDERR "FINISH_ELEMENT($FH)($element->{'texi'})[$element->{'file'}] counter $files{$element->{'file'}}->{'counter'}\n"; |
|
|
|
# handle foot notes |
|
if (Texi2HTML::Config::get_conf('SPLIT') and scalar(@foot_lines) |
|
and (Texi2HTML::Config::get_conf('footnotestyle') eq 'end') |
|
and (! $new_element or |
|
($element and ($new_element->{'file'} ne $element->{'file'}))) |
|
) |
|
{ |
|
if ($files{$element->{'file'}}->{'counter'}) |
|
{# there are other elements in that page we are not on its foot |
|
$files{$element->{'file'}}->{'relative_foot_num'} |
|
= $global_relative_foot_num; |
|
push @{$files{$element->{'file'}}->{'foot_lines'}}, |
|
@foot_lines; |
|
} |
|
else |
|
{# we output the footnotes as we are at the file end |
|
unshift @foot_lines, @{$files{$element->{'file'}}->{'foot_lines'}}; |
|
&$Texi2HTML::Config::foot_section (\@foot_lines); |
|
push @{$Texi2HTML::THIS_SECTION}, @foot_lines; |
|
} |
|
if ($new_element) |
|
{ |
|
$global_relative_foot_num = |
|
$files{$new_element->{'file'}}->{'relative_foot_num'}; |
|
} |
|
@foot_lines = (); |
|
} |
|
|
|
if ($element->{'top'}) |
|
{ |
|
############### debug |
|
#print STDERR "TOP $element->{'texi'}, @{$Texi2HTML::THIS_SECTION}\n"; |
|
die "element->{'top'} $element ne element_top $element_top" if ($element ne $element_top); |
|
print STDERR "# Doing element top\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
print STDERR "[Top]" if ($T2H_VERBOSE); |
|
############### end debug |
|
|
|
&$Texi2HTML::Config::print_Top($FH, $element->{'titlefont'}, $element); |
|
my $end_page = 0; |
|
if (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ |
|
if ($files{$element->{'file'}}->{'counter'} == 0) |
|
{ |
|
$end_page = 1; |
|
} |
|
} |
|
&$Texi2HTML::Config::print_Top_footer($FH, $end_page, $element); |
|
close_out($FH, $docu_top_file) if ($end_page); |
|
} |
|
else |
|
{ |
|
print STDERR "# do element $element->{'texi'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
&$Texi2HTML::Config::print_section($FH, $first_section, 0, $element); |
|
################# debug |
|
my $new_elem_file = 'NO ELEM => no file'; |
|
$new_elem_file = $new_element->{'file'} if (defined($new_element)); |
|
print STDERR "# FILES new: $new_elem_file old(".fileno($FH)."): $element->{'file'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
################# end debug |
|
if (defined($new_element) and ($new_element->{'file'} ne $element->{'file'})) |
|
{ |
|
print STDERR "# End of section with change in file(".fileno($FH).") $element->{'file'} -> $new_element->{'file'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
if (!$files{$element->{'file'}}->{'counter'}) |
|
{ |
|
&$Texi2HTML::Config::print_chapter_footer($FH, $element) if (Texi2HTML::Config::get_conf('SPLIT') eq 'chapter'); |
|
&$Texi2HTML::Config::print_section_footer($FH, $element) if (Texi2HTML::Config::get_conf('SPLIT') eq 'section'); |
|
print STDERR "# Close file(".fileno($FH).") after $element->{'texi'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
&$Texi2HTML::Config::print_page_foot($FH); |
|
close_out($FH, "$docu_rdir$element->{'file'}"); |
|
} |
|
else |
|
{ |
|
print STDERR "# Counter $files{$element->{'file'}}->{'counter'} ne 0, file(".fileno($FH).") $element->{'file'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
} |
|
} |
|
elsif (!defined($new_element)) |
|
{ |
|
print STDERR "# End of last section, file(".fileno($FH).") $element->{'file'}, counter $files{$element->{'file'}}->{'counter'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
if (Texi2HTML::Config::get_conf('SPLIT')) |
|
{ # end of last splitted section |
|
&$Texi2HTML::Config::print_chapter_footer($FH, $element) if (Texi2HTML::Config::get_conf('SPLIT') eq 'chapter'); |
|
&$Texi2HTML::Config::print_section_footer($FH, $element) if (Texi2HTML::Config::get_conf('SPLIT') eq 'section'); |
|
&$Texi2HTML::Config::print_page_foot($FH); |
|
close_out($FH, "$docu_rdir$element->{'file'}"); |
|
} |
|
else |
|
{ # end of last unsplit section |
|
&$Texi2HTML::Config::end_section($FH, 1, $element); |
|
} |
|
} |
|
elsif ($new_element->{'top'}) |
|
{ |
|
print STDERR "# Section followed by Top, file(".fileno($FH).") counter $files{$element->{'file'}}->{'counter'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
&$Texi2HTML::Config::end_section($FH, 1, $element); |
|
} |
|
else |
|
{ # end of section followed by another one |
|
print STDERR "# Section followed by another one, file(".fileno($FH).") counter $files{$element->{'file'}}->{'counter'}\n" |
|
if ($T2H_DEBUG & $DEBUG_ELEMENTS); |
|
&$Texi2HTML::Config::end_section($FH, 0, $element); |
|
} |
|
} |
|
} |
|
|
|
# write to files with name the node name for cross manual references. |
|
sub do_node_files() |
|
{ |
|
foreach my $key (keys(%nodes)) |
|
{ |
|
my $node = $nodes{$key}; |
|
next unless ($node->{'node_file'}); |
|
my $redirection_file = $docu_doc; |
|
$redirection_file = $node->{'file'} if (Texi2HTML::Config::get_conf('SPLIT')); |
|
if (!$redirection_file) |
|
{ |
|
print STDERR "Bug: file for redirection for `$node->{'texi'}' don't exist\n" unless (Texi2HTML::Config::get_conf('novalidate') or !$node->{'seen'}); |
|
next; |
|
} |
|
next if ($redirection_file eq $node->{'node_file'}); |
|
my $file = "${docu_rdir}$node->{'node_file'}"; |
|
$Texi2HTML::NODE{'This'} = $node->{'text'}; |
|
$Texi2HTML::NO_TEXI{'This'} = $node->{'no_texi'}; |
|
$Texi2HTML::SIMPLE_TEXT{'This'} = $node->{'simple_format'}; |
|
$Texi2HTML::NAME{'This'} = $node->{'text'}; |
|
my $href_file = $node->{'file'}; |
|
if (!defined($href_file)) |
|
{ |
|
if (Texi2HTML::Config::get_conf('novalidate')) |
|
{ |
|
$href_file = ''; |
|
} |
|
else |
|
{ |
|
msg_debug ("Undefined file for `$node->{'texi'}' in do_node_files"); |
|
} |
|
} |
|
$Texi2HTML::HREF{'This'} = "$href_file#$node->{'id'}"; |
|
my $redirect = &$Texi2HTML::Config::print_redirection_page (); |
|
if (defined($redirect)) |
|
{ |
|
my $NODEFILE = open_out ($file); |
|
print $NODEFILE "$redirect"; |
|
close $NODEFILE || document_error ("Can't close $file: $!", 1); |
|
} |
|
} |
|
} |
|
|
|
#+++############################################################################ |
|
# # |
|
# Low level functions # |
|
# # |
|
#---############################################################################ |
|
|
|
sub locate_include_file($) |
|
{ |
|
my $file = shift; |
|
|
|
# APA: Don't implicitely search ., to conform with the docs! |
|
|
|
# if file begins with /, ./ or ../ don't search in -I (Karl) |
|
if ($file =~ m,^(/|\./|\.\./),) |
|
{ |
|
return "$file" if (-e "$file" && -r "$file"); |
|
return undef; |
|
} |
|
foreach my $dir (@Texi2HTML::Config::INCLUDE_DIRS) |
|
{ |
|
return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file"); |
|
} |
|
return undef; |
|
} |
|
|
|
sub open_file($$$) |
|
{ |
|
my $name = shift; |
|
# my $line_number = shift; |
|
my $macro = shift; |
|
my $files_stack = shift; |
|
|
|
my $line_number; |
|
my $input_spool; |
|
|
|
local *FH; |
|
if (open(*FH, "<$name")) |
|
{ |
|
my $in_encoding = Texi2HTML::Config::get_conf('IN_ENCODING'); |
|
if (defined($in_encoding) and $Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
binmode(*FH, ":encoding($in_encoding)"); |
|
} |
|
my $file = { 'fh' => *FH, |
|
'input_spool' => { 'spool' => [], |
|
'macro' => '' }, |
|
'name' => $name, |
|
'line_nr' => 0 }; |
|
unshift(@$files_stack, $file); |
|
$input_spool = $file->{'input_spool'}; |
|
$line_number->{'file_name'} = $name; |
|
$line_number->{'line_nr'} = 1; |
|
$line_number->{'macro'} = $macro; |
|
} |
|
else |
|
{ |
|
document_error ("Can't read file $name: $!", 1); |
|
} |
|
return ($line_number, $input_spool); |
|
} |
|
|
|
my %filehandles = (); |
|
|
|
sub open_out($;$) |
|
{ |
|
my $file = shift; |
|
my $append = shift; |
|
local *FILE; |
|
#print STDERR "open_out $file $Texi2HTML::THISDOC{'OUT_ENCODING'}\n"; |
|
if ($file eq '-') |
|
{ |
|
binmode(STDOUT, ":encoding($Texi2HTML::THISDOC{'OUT_ENCODING'})") if (defined($Texi2HTML::THISDOC{'OUT_ENCODING'}) and $Texi2HTML::Config::USE_UNICODE); |
|
return \*STDOUT; |
|
} |
|
|
|
my $mode = '>'; |
|
$mode = '>>' if ($append); |
|
unless (open(FILE, $mode, $file)) |
|
{ |
|
document_error ("could not open $file for writing: $!", 1); |
|
} |
|
push @opened_files, $file; |
|
if (defined($Texi2HTML::THISDOC{'OUT_ENCODING'}) and $Texi2HTML::Config::USE_UNICODE) |
|
{ |
|
if ($Texi2HTML::THISDOC{'OUT_ENCODING'} eq 'utf8' or $Texi2HTML::THISDOC{'OUT_ENCODING'} eq 'utf-8-strict') |
|
{ |
|
binmode(FILE, ':utf8'); |
|
} |
|
else |
|
{ |
|
binmode(FILE, ':bytes'); |
|
#binmode(FILE, ":encoding($Texi2HTML::THISDOC{'OUT_ENCODING'})"); |
|
} |
|
# FIXME is it useful when in utf8? |
|
binmode(FILE, ":encoding($Texi2HTML::THISDOC{'OUT_ENCODING'})"); |
|
} |
|
$file =~ s/^(\.[\/]+)*//; |
|
$filehandles{fileno(*FILE)} = $file; |
|
return *FILE; |
|
} |
|
|
|
sub close_out($$) |
|
{ |
|
my $FH = shift; |
|
my $file = shift; |
|
return if (defined($file) and $file eq '-'); |
|
$file =~ s/^(\.[\/]+)*//; |
|
my $fileno = fileno($FH); |
|
#print STDERR "close_out $file $fileno\n"; |
|
if (!defined($fileno)) |
|
{ |
|
msg_debug("fileno not defined for $file") |
|
} |
|
elsif (defined($filehandles{$fileno}) and $filehandles{$fileno} ne $file) |
|
{ |
|
#msg_debug("filehandles{$fileno} $filehandles{$fileno} and file $file different") |
|
} |
|
close ($FH) || document_error ("Error when closing $file: $!"); |
|
} |
|
|
|
sub next_line($$) |
|
{ |
|
my $line_number = shift; |
|
my $files_stack = shift; |
|
my $input_spool; |
|
while (@$files_stack) |
|
{ |
|
my $file = $files_stack->[0]; |
|
$line_number->{'file_name'} = $file->{'name'}; |
|
$input_spool = $file->{'input_spool'}; |
|
if (@{$input_spool->{'spool'}}) |
|
{ |
|
$line_number->{'macro'} = $file->{'input_spool'}->{'macro'}; |
|
$line_number->{'line_nr'} = $file->{'line_nr'}; |
|
my $line = shift(@{$input_spool->{'spool'}}); |
|
print STDERR "# unspooling $line" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
return($line, $input_spool); |
|
} |
|
else |
|
{ |
|
$file->{'input_spool'}->{'macro'} = ''; |
|
$line_number->{'macro'} = ''; |
|
} |
|
my $fh = $file->{'fh'}; |
|
no strict "refs"; |
|
my $line = <$fh>; |
|
use strict "refs"; |
|
my $chomped_line = $line; |
|
$file->{'line_nr'}++ if (defined($line) and chomp($chomped_line)); |
|
$line_number->{'line_nr'} = $file->{'line_nr'}; |
|
# do that right now, before any other treatement |
|
$line =~ s/\x{7F}.*\s*// if (defined($line)); |
|
return($line, $input_spool) if (defined($line)); |
|
no strict "refs"; |
|
close($fh); |
|
use strict "refs"; |
|
shift(@$files_stack); |
|
} |
|
return(undef, $input_spool); |
|
} |
|
|
|
sub check_die(;$) |
|
{ |
|
my $always_die = shift; |
|
|
|
if (!$Texi2HTML::Config::FORCE) |
|
{ |
|
if (@opened_files == 1) |
|
{ |
|
warn sprintf(__("%s: Removing output file `%s' due to errors; use --force to preserve.\n"), $real_command_name, $opened_files[0]); |
|
} |
|
elsif (@opened_files > 1) |
|
{ |
|
warn sprintf(__("%s: Removing output files due to errors; use --force to preserve.\n"), $real_command_name); |
|
} |
|
foreach my $file (@opened_files) |
|
{ |
|
unlink ($file); |
|
} |
|
foreach my $dir (@created_directories) |
|
{ |
|
rmdir ($dir); |
|
} |
|
} |
|
if ($always_die or !$Texi2HTML::Config::FORCE) |
|
{ |
|
exit (1); |
|
} |
|
} |
|
|
|
sub file_line_warn($$;$) |
|
{ |
|
return if ($Texi2HTML::Config::NO_WARN); |
|
my $text = shift; |
|
chomp($text); |
|
my $file = shift; |
|
my $line_nr = shift; |
|
|
|
if (!defined($line_nr)) |
|
{ |
|
warn "$file: $text\n"; |
|
} |
|
else |
|
{ |
|
warn "$file:$line_nr: $text\n"; |
|
} |
|
} |
|
|
|
sub document_warn ($) |
|
{ |
|
return if ($Texi2HTML::Config::NO_WARN); |
|
my $text = shift; |
|
chomp ($text); |
|
warn sprintf(__p("warning: warning_message", "warning: %s\n"), $text); |
|
} |
|
|
|
my $error_nrs = 0; |
|
sub check_errors() |
|
{ |
|
$error_nrs ++; |
|
die __("Too many errors! Gave up.\n") if ($error_nrs >= $Texi2HTML::Config::ERROR_LIMIT); |
|
} |
|
|
|
sub msg_debug($;$) |
|
{ |
|
my $text = shift; |
|
chomp ($text); |
|
my $line_number = shift; |
|
if (defined($line_number)) |
|
{ |
|
warn "!! $text " . format_line_number($line_number) . "\n"; |
|
} |
|
else |
|
{ |
|
warn "!! $text\n"; |
|
} |
|
} |
|
|
|
sub cmdline_warn ($) |
|
{ |
|
my $text = shift; |
|
#chomp ($text); |
|
warn sprintf(__p("command_name: warning_message", "%s: %s"), $real_command_name, $text); |
|
} |
|
|
|
# seems not to be used |
|
sub cmdline_error ($) |
|
{ |
|
my $text = shift; |
|
#chomp ($text); |
|
warn sprintf(__p("command_name: error_message", "%s: %s"), $real_command_name, $text); |
|
} |
|
|
|
sub document_error($;$) |
|
{ |
|
my $text = shift; |
|
chomp ($text); |
|
my $die = shift; |
|
warn ("$text\n"); |
|
check_die ($die); |
|
check_errors(); |
|
} |
|
|
|
# echo an error |
|
sub msg_error($;$) |
|
{ |
|
my $text = shift; |
|
my $line_number = shift; |
|
if (defined($line_number)) |
|
{ |
|
line_error ($text, $line_number); |
|
} |
|
else |
|
{ |
|
document_error ($text); |
|
} |
|
} |
|
|
|
# echo a warning |
|
sub msg_warn($;$$) |
|
{ |
|
my $text = shift; |
|
my $line_number = shift; |
|
my $context_string = shift; |
|
|
|
if (defined($line_number)) |
|
{ |
|
line_warn ($text, $line_number); |
|
} |
|
elsif (defined($context_string)) |
|
{ |
|
document_warn ("$text (in $context_string)"); |
|
} |
|
else |
|
{ |
|
document_warn ($text); |
|
} |
|
} |
|
|
|
# echo a warning associated with a line in the document |
|
sub line_warn($$) |
|
{ |
|
return if ($Texi2HTML::Config::NO_WARN); |
|
my $text = shift; |
|
chomp ($text); |
|
my $line_number = shift; |
|
return if (!defined($line_number)); |
|
my $file = $line_number->{'file_name'}; |
|
# otherwise out of source build fail since the file names are different |
|
$file =~ s/^.*\/// if ($Texi2HTML::Config::TEST); |
|
if ($line_number->{'macro'} ne '') |
|
{ |
|
warn sprintf(__("%s:%d: warning: %s (via \@%s)\n"), $file, $line_number->{'line_nr'}, $text, $line_number->{'macro'}); |
|
} |
|
else |
|
{ |
|
warn sprintf(__("%s:%d: warning: %s\n"), $file, $line_number->{'line_nr'}, $text); |
|
} |
|
} |
|
|
|
sub line_error($$) |
|
{ |
|
my $text = shift; |
|
chomp ($text); |
|
my $line_number = shift; |
|
if (defined($line_number)) |
|
{ |
|
my $file = $line_number->{'file_name'}; |
|
$file =~ s/^.*\/// if ($Texi2HTML::Config::TEST); |
|
my $macro_text = ''; |
|
$macro_text = " (via \@$line_number->{'macro'})" if ($line_number->{'macro'} ne ''); |
|
warn "$file:$line_number->{'line_nr'}: $text$macro_text\n"; |
|
check_die(); |
|
} |
|
check_errors(); |
|
} |
|
|
|
sub format_line_number(;$) |
|
{ |
|
my $line_number = shift; |
|
$line_number = $Texi2HTML::THISDOC{'line_nr'} if (!defined($line_number)); |
|
my $macro_text = ''; |
|
#$line_number = undef; |
|
return '' unless (defined($line_number)); |
|
my $print_filename = ($line_number->{'file_name'} ne $Texi2HTML::THISDOC{'input_file_name'}); |
|
if ($line_number->{'macro'} ne '') |
|
{ |
|
if ($print_filename) |
|
{ |
|
return sprintf(__("(in %s l. %d via \@%s)"), $line_number->{'file_name'}, $line_number->{'line_nr'}, $line_number->{'macro'}); |
|
} |
|
else |
|
{ |
|
return sprintf(__("(l. %d via \@%s)"), $line_number->{'line_nr'}, $line_number->{'macro'}); |
|
} |
|
} |
|
elsif ($print_filename) |
|
{ |
|
return sprintf(__("(in %s l. %d)"), $line_number->{'file_name'}, $line_number->{'line_nr'}); |
|
} |
|
else |
|
{ |
|
return sprintf(__("(l. %d)"), $line_number->{'line_nr'}); |
|
} |
|
} |
|
|
|
# to debug, dump the result of pass_texi and pass_structure in a file |
|
sub dump_texi($$;$$) |
|
{ |
|
my $lines = shift; |
|
my $pass = shift; |
|
my $numbers = shift; |
|
my $file = shift; |
|
$file = "$docu_rdir$docu_name" . ".pass$pass" if (!defined($file)); |
|
my $FH = open_out($file); |
|
print STDERR "# Dump texi\n" if ($T2H_VERBOSE); |
|
my $index = 0; |
|
foreach my $line (@$lines) |
|
{ |
|
my $number_information = ''; |
|
my $chomped_line = $line; |
|
# if defined, it means that an output of the file is asked for |
|
if (defined($numbers)) |
|
{ |
|
my $basefile = $numbers->[$index]->{'file_name'}; |
|
$basefile = 'no file' if (!defined($basefile)); |
|
$basefile =~ s|.*/||; |
|
my $macro_name = $numbers->[$index]->{'macro'}; |
|
$macro_name = '' if (!defined($macro_name)); |
|
my $line_number = $numbers->[$index]->{'line_nr'}; |
|
$line_number = '' if (!defined($line_number)); |
|
$number_information = "${basefile}($macro_name,$line_number) "; |
|
} |
|
print $FH "${number_information}$line"; |
|
$index++ if (chomp($chomped_line)); |
|
} |
|
close_out ($FH, $file); |
|
} |
|
|
|
|
|
# return next tag on the line |
|
sub next_tag($) |
|
{ |
|
my $line = shift; |
|
# macro_regexp |
|
if ($line =~ /^\s*\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])/o or $line =~ /^\s*\@([a-zA-Z][\w-]*)/) |
|
{ |
|
return ($1); |
|
} |
|
return ''; |
|
} |
|
|
|
sub next_end_tag($) |
|
{ |
|
my $line = shift; |
|
if ($line =~ /^\s*\@end\s+([a-zA-Z][\w-]*)/) |
|
{ |
|
return $1; |
|
} |
|
return ''; |
|
} |
|
|
|
sub next_tag_or_end_tag($) |
|
{ |
|
my $line = shift; |
|
my $next_tag = next_tag($line); |
|
return $next_tag if (defined($next_tag) and $next_tag ne ''); |
|
return next_end_tag($line); |
|
} |
|
|
|
sub top_stack($;$) |
|
{ |
|
my $stack = shift; |
|
my $ignore_para = shift; |
|
|
|
my $index = scalar (@$stack); |
|
return undef unless ($index); |
|
|
|
return $stack->[-1] unless ($ignore_para); |
|
if ($ignore_para == 1) |
|
{ |
|
if (exists($stack->[-1]->{'format'}) and ($stack->[-1]->{'format'} eq 'paragraph' or $stack->[-1]->{'format'} eq 'preformatted')) |
|
{ |
|
if (exists($stack->[-2])) |
|
{ |
|
return $stack->[-2]; |
|
} |
|
else |
|
{ |
|
return undef; |
|
} |
|
} |
|
else |
|
{ |
|
return $stack->[-1]; |
|
} |
|
} |
|
else |
|
{ |
|
while ($index and |
|
( |
|
(exists($stack->[$index-1]->{'format'}) |
|
and ($stack->[$index-1]->{'format'} eq 'paragraph' or $stack->[$index-1]->{'format'} eq 'preformatted')) |
|
or (exists($stack->[$index-1]->{'style'})) |
|
)) |
|
{ |
|
$index--; |
|
} |
|
} |
|
return undef unless ($index); |
|
return $stack->[$index-1]; |
|
} |
|
|
|
# return the next element with balanced {} |
|
sub next_bracketed($$$;$) |
|
{ |
|
my $line = shift; |
|
my $command = shift; |
|
my $line_nr = shift; |
|
my $report = shift; |
|
my $opened_braces = 0; |
|
my $result = ''; |
|
my $spaces; |
|
#print STDERR "next_bracketed $line"; |
|
if ($line =~ /^(\s*)$/) |
|
{ |
|
return ('','',$1); |
|
} |
|
while ($line !~ /^\s*$/) |
|
{ |
|
#print STDERR "next_bracketed($opened_braces): $result !!! $line"; |
|
if (!$opened_braces) |
|
{ # beginning of item |
|
$line =~ s/^(\s*)//; |
|
$spaces = $1; |
|
#if ($line =~ s/^([^\{\}\s]+)//) |
|
if ($line =~ s/^([^\{\}]+?)(\s+)/$2/ or $line =~ s/^([^\{\}]+?)$//) |
|
{ |
|
$result = $1; |
|
$result = trim_around_spaces($result); |
|
return ($result, $line, $spaces); |
|
} |
|
elsif ($line =~ s/^([^\{\}]+?)([\{\}])/$2/) |
|
{ |
|
$result = $1; |
|
} |
|
} |
|
elsif($line =~ s/^([^\{\}]+)//) |
|
{ |
|
$result .= $1; |
|
} |
|
if ($line =~ s/^([\{\}])//) |
|
{ |
|
my $brace = $1; |
|
$opened_braces++ if ($brace eq '{'); |
|
$opened_braces-- if ($brace eq '}'); |
|
|
|
if ($opened_braces < 0) |
|
{ |
|
line_error(sprintf(__("Too much '}' in \@%s"), $command), $line_nr) if ($report); |
|
$opened_braces = 0; |
|
#next; |
|
} |
|
$result .= $brace; |
|
return ($result, $line, $spaces) if ($opened_braces == 0); |
|
} |
|
} |
|
if ($opened_braces) |
|
{ |
|
line_error(sprintf(__("Missing `}' on \@%s line"), $command), $line_nr) if ($report); |
|
return ($result, '', $spaces); |
|
#return ($result . ( '}' x $opened_braces), '', $spaces); |
|
} |
|
msg_debug ("BUG: at the end of next_bracketed", $line_nr); |
|
return undef; |
|
} |
|
|
|
# def prams are also split at @-commands if not in brackets |
|
sub next_def_param($$$;$) |
|
{ |
|
my $line = shift; |
|
my $command = shift; |
|
my $line_nr = shift; |
|
my $report = shift; |
|
my ($item, $spaces); |
|
($item, $line, $spaces) = next_bracketed($line, $command, $line_nr, $report); |
|
return ($item, $line, $spaces) if (!defined($item)); |
|
if ($item =~ /^\{/) |
|
{ |
|
$item =~ s/^\{(.*)\}$/$1/; |
|
} |
|
else |
|
{ |
|
my $delimeter_quoted = quotemeta($Texi2HTML::Config::def_argument_separator_delimiters); |
|
if ($item =~ s/^([^\@$delimeter_quoted]+)//) |
|
{ |
|
$line = $item . $line; |
|
$item = $1; |
|
} |
|
elsif ($item =~ s/^([$delimeter_quoted])//) |
|
{ |
|
$line = $item . $line; |
|
$item = $1; |
|
} |
|
elsif ($item =~ s/^(\@[^\@\{]+)(\@)/$2/) |
|
{ |
|
$line = $item . $line; |
|
$item = $1; |
|
} |
|
} |
|
return ($item, $line, $spaces); |
|
} |
|
|
|
# do a href using file and id and taking care of ommitting file if it is |
|
# the same |
|
# element: structuring element to point to |
|
# file: current file |
|
sub href($$;$) |
|
{ |
|
my $element = shift; |
|
my $file = shift; |
|
my $line_nr = shift; |
|
return '' unless defined($element); |
|
my $href = ''; |
|
msg_debug("Bug: $element->{'texi'}, target undef", $line_nr) if (!defined($element->{'target'})); |
|
msg_debug("Bug: $element->{'texi'}, file undef", $line_nr) if (!defined($element->{'file'})); |
|
msg_debug("Bug: file undef in href", $line_nr) if (!defined($file)); |
|
$href .= $element->{'file'} if (defined($element->{'file'}) and $file ne $element->{'file'}); |
|
$href .= "#$element->{'target'}" if (defined($element->{'target'})); |
|
return $href; |
|
} |
|
|
|
sub file_target_href($$$) |
|
{ |
|
my $dest_file = shift; |
|
my $orig_file = shift; |
|
my $target = shift; |
|
my $href = ''; |
|
$href .= $dest_file if (defined($dest_file) and ($dest_file ne $orig_file)); |
|
$href .= "#$target" if (defined($target)); |
|
return $href; |
|
} |
|
|
|
sub trim_around_spaces($) |
|
{ |
|
my $text = shift; |
|
$text =~ s/^\s*//; |
|
$text =~ s/(\s)\s*$/$1/; |
|
if ($text =~ /(\@+)\s$/) |
|
{ |
|
my $arobases = $1; |
|
if ((length($arobases) % 2) == 0) |
|
{ |
|
$text =~ s/\s$//; |
|
} |
|
} |
|
else |
|
{ |
|
$text =~ s/\s$//; |
|
} |
|
return $text; |
|
} |
|
|
|
sub normalise_space($) |
|
{ |
|
return undef unless (defined ($_[0])); |
|
my $text = shift; |
|
$text =~ s/\s+/ /go; |
|
$text =~ s/ $//; |
|
$text =~ s/^ //; |
|
return $text; |
|
} |
|
|
|
|
|
sub normalise_texi_space($) |
|
{ |
|
return undef unless (defined ($_[0])); |
|
my $text = shift; |
|
$text = trim_around_spaces($text); |
|
$text =~ s/\s+/ /go; |
|
return $text; |
|
} |
|
|
|
sub normalise_node($) |
|
{ |
|
return undef unless (defined ($_[0])); |
|
my $text = shift; |
|
$text = normalise_texi_space($text); |
|
$text =~ s/^top$/Top/i; |
|
return $text; |
|
} |
|
|
|
sub normalise_node_array($) |
|
{ |
|
my $array = shift; |
|
my @result; |
|
foreach my $node (@$array) |
|
{ |
|
push @result, normalise_node($node); |
|
} |
|
return @result; |
|
} |
|
|
|
sub do_anchor_label($$$$) |
|
{ |
|
my $command = shift; |
|
#my $anchor = shift; |
|
my $args = shift; |
|
my $anchor = $args->[0]; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
#msg_debug("do_anchor_label $state->{'region'} m_p $state->{'multiple_pass'} remove $state->{'remove_texi'} `$anchor'", $line_nr); |
|
|
|
$anchor = normalise_node($anchor); |
|
if ((defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0) or $state->{'outside_document'}) |
|
{ |
|
# no warning when outside of document. |
|
line_warn(sprintf(__("Anchor `%s' ignored in %s expanded more than once"),$anchor, $state->{'region'}), $line_nr) unless ($state->{'outside_document'} or defined($state->{'expansion'})); |
|
return ''; |
|
} |
|
|
|
if (!exists($nodes{$anchor}) or !defined($nodes{$anchor}->{'id'})) |
|
{ |
|
msg_debug("Unknown anchor `$anchor'", $line_nr); |
|
} |
|
return &$Texi2HTML::Config::anchor_label($nodes{$anchor}->{'id'}, $anchor, $nodes{$anchor}, $state->{'expansion'}); |
|
} |
|
|
|
sub get_format_command($) |
|
{ |
|
my $format = shift; |
|
my $command = ''; |
|
my $format_name = ''; |
|
my $term = 0; |
|
my $item_nr; |
|
my $paragraph_number; |
|
my $enumerate_type; |
|
my $number; |
|
|
|
$command = $format->{'command'} if (defined($format->{'command'})); |
|
$format_name = $format->{'format'} if (defined($format->{'format'})); |
|
|
|
return ($format_name,$command,\$format->{'paragraph_number'},$term, |
|
$format->{'item_nr'}, $format->{'spec'}, $format->{'number'}, |
|
$format->{'stack_at_beginning'}); |
|
} |
|
|
|
sub do_paragraph($$;$) |
|
{ |
|
my $text = shift; |
|
my $state = shift; |
|
my $stack = shift; |
|
|
|
if (!defined ($state->{'paragraph_context'})) |
|
{ |
|
msg_debug ("paragraph_context undef", $Texi2HTML::THISDOC{'line_nr'}); |
|
dump_stack (undef, $stack, $state); |
|
} |
|
|
|
my ($format, $paragraph_command, $paragraph_number, $term, $item_nr, |
|
$enumerate_type, $number, $stack_at_beginning) |
|
= get_format_command ($state->{'paragraph_context'}); |
|
delete $state->{'paragraph_context'}; |
|
|
|
my $indent_style = ''; |
|
if (exists($state->{'paragraph_indent'})) |
|
{ |
|
$indent_style = $state->{'paragraph_indent'}; |
|
$state->{'paragraph_indent'} = undef; |
|
delete $state->{'paragraph_indent'}; |
|
} |
|
my $paragraph_command_formatted; |
|
$state->{'paragraph_nr'}--; |
|
(print STDERR "Bug text undef in do_paragraph", return '') unless defined($text); |
|
my $align = ''; |
|
$align = $state->{'paragraph_style'}->[-1] if ($state->{'paragraph_style'}->[-1]); |
|
|
|
if ($paragraph_command and !exists($Texi2HTML::Config::special_list_commands{$format}->{$paragraph_command})) |
|
{ |
|
$paragraph_command_formatted = substitute_line("\@$paragraph_command\{\}", "paragraph \@$format \@$paragraph_command", duplicate_formatting_state($state)); |
|
} |
|
return &$Texi2HTML::Config::paragraph($text, $align, $indent_style, $paragraph_command, $paragraph_command_formatted, $paragraph_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning); |
|
} |
|
|
|
sub do_preformatted($$;$) |
|
{ |
|
my $text = shift; |
|
my $state = shift; |
|
my $stack = shift; |
|
|
|
if (!defined ($state->{'preformatted_context'})) |
|
{ |
|
msg_debug ("preformatted_context undef", $Texi2HTML::THISDOC{'line_nr'}); |
|
dump_stack (undef, $stack, $state); |
|
} |
|
|
|
my ($format, $leading_command, $preformatted_number, $term, $item_nr, |
|
$enumerate_type, $number,$stack_at_beginning) |
|
= get_format_command($state->{'preformatted_context'}); |
|
delete ($state->{'preformatted_context'}); |
|
my $leading_command_formatted; |
|
my $pre_style = ''; |
|
my $class = ''; |
|
$pre_style = $state->{'preformatted_stack'}->[-1]->{'pre_style'} if ($state->{'preformatted_stack'}->[-1]->{'pre_style'}); |
|
$class = $state->{'preformatted_stack'}->[-1]->{'class'}; |
|
print STDERR "BUG: !state->{'preformatted_stack'}->[-1]->{'class'}\n" unless ($class); |
|
if (defined($leading_command) and $leading_command ne '' and !exists($Texi2HTML::Config::special_list_commands{$format}->{$leading_command})) |
|
{ |
|
$leading_command_formatted = substitute_line("\@$leading_command\{\}", "preformatted \@$format \@$leading_command", duplicate_formatting_state($state)); |
|
} |
|
return &$Texi2HTML::Config::preformatted($text, $pre_style, $class, $leading_command, $leading_command_formatted, $preformatted_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning); |
|
} |
|
|
|
sub do_external_href($) |
|
{ |
|
# node_id is a unique node identifier with only letters, digits, - and _ |
|
# node_xhtml_id is almost the same, but xhtml id can only begin with |
|
# letters, so a prefix has to be appended |
|
my $texi_node = shift; |
|
my $file = ''; |
|
my $node_file = ''; |
|
my $node_id = ''; |
|
my $node_xhtml_id = ''; |
|
|
|
#print STDERR "do_external_href $texi_node\n"; |
|
|
|
if ($texi_node =~ s/^\((.+?)\)//) |
|
{ |
|
$file = $1; |
|
} |
|
$texi_node = normalise_node($texi_node); |
|
if ($texi_node ne '') |
|
{ |
|
if (exists($nodes{$texi_node}) and ($nodes{$texi_node}->{'cross_manual_target'})) |
|
{ |
|
$node_id = $nodes{$texi_node}->{'cross_manual_target'}; |
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES) |
|
{ |
|
$node_file = $nodes{$texi_node}->{'cross_manual_file'}; |
|
} |
|
} |
|
else |
|
{ |
|
if ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES) |
|
{ |
|
($node_id, $node_file) = cross_manual_line($texi_node,1); |
|
} |
|
else |
|
{ |
|
$node_id = cross_manual_line($texi_node); |
|
} |
|
} |
|
$node_xhtml_id = node_to_id($node_id); |
|
$node_file = $node_id unless ($Texi2HTML::Config::TRANSLITERATE_FILE_NAMES); |
|
} |
|
return &$Texi2HTML::Config::external_href($texi_node, $node_file, |
|
$node_xhtml_id, $file); |
|
} |
|
|
|
# transform node for cross ref name to id suitable for xhtml: an xhtml id |
|
# must begin with a letter. |
|
sub node_to_id($) |
|
{ |
|
my $cross_ref_node_name = shift; |
|
$cross_ref_node_name =~ s/^([0-9_])/g_t$1/; |
|
return $cross_ref_node_name; |
|
} |
|
|
|
# return an empty string if the command is not a index command, the prefix |
|
# if it is one |
|
sub index_command_prefix($) |
|
{ |
|
my $command = shift; |
|
return $1 if ($command =~ /^(\w+?)index/ and ($1 ne 'print') and ($1 ne 'syncode') and ($1 ne 'syn') and ($1 ne 'def') and ($1 ne 'defcode')); |
|
return ''; |
|
} |
|
|
|
# return 1 if the following tag shouldn't begin a line |
|
sub no_line($) |
|
{ |
|
my $line = shift; |
|
my $next_tag = next_tag($line); |
|
return 1 if (($line =~ /^\s*$/) or $Texi2HTML::Config::no_paragraph_commands{$next_tag} or |
|
($Texi2HTML::Config::no_paragraph_commands{'cindex'} and (index_command_prefix($next_tag) ne '')) or |
|
(($line =~ /^\@end\s+(\w+)/) and $Texi2HTML::Config::no_paragraph_commands{"end $1"}) or |
|
($next_tag =~ /^special_(\w+)_(\d+)$/ and $Texi2HTML::Config::no_paragraph_commands{$1}) |
|
); |
|
return 0; |
|
} |
|
|
|
sub no_paragraph($$) |
|
{ |
|
my $state = shift; |
|
my $line = shift; |
|
return ($state->{'paragraph_context'} or $state->{'preformatted'} or $state->{'remove_texi'} or no_line($line) or $state->{'no_paragraph'}); |
|
} |
|
|
|
# We restart the preformatted format which was stopped |
|
# by the format if in preformatted, and start a paragraph |
|
# for the text following the end of the format, if needed |
|
sub begin_paragraph_after_command($$$$) |
|
{ |
|
my $state = shift; |
|
my $stack = shift; |
|
my $command = shift; |
|
my $text_following = shift; |
|
|
|
#if (($state->{'preformatted'} |
|
# and !$Texi2HTML::Config::format_in_paragraph{$command}) |
|
if ($state->{'preformatted'} |
|
or (!no_paragraph($state,$text_following))) |
|
{ |
|
begin_paragraph($stack, $state); |
|
} |
|
} |
|
|
|
# handle raw formatting, ignored regions... |
|
# called from scan_texi, so only in first pass. |
|
sub do_text_macro($$$$$) |
|
{ |
|
my $type = shift; |
|
my $line = shift; |
|
my $state = shift; |
|
my $stack = shift; |
|
my $line_nr = shift; |
|
my $value; |
|
#print STDERR "do_text_macro $type\n"; |
|
|
|
if ($Texi2HTML::Config::texi_formats_map{$type} eq 'raw') |
|
{ |
|
$state->{'raw'} = $type; |
|
#print STDERR "RAW\n"; |
|
if ($state->{'raw'}) |
|
{ |
|
push @$stack, { 'style' => $type, 'text' => '' }; |
|
} |
|
} |
|
elsif ($Texi2HTML::Config::texi_formats_map{$type} eq 'value') |
|
{ |
|
if (($line =~ s/(\s+)($VARRE)$//) or ($line =~ s/(\s+)($VARRE)(\s)//)) |
|
{ |
|
$value = $1 . $2; |
|
$value .= $3 if defined($3); |
|
if ($state->{'ignored'}) |
|
{ |
|
if ($type eq $state->{'ignored'}) |
|
{ |
|
$state->{'ifvalue_inside'}++; |
|
} |
|
# if 'ignored' we don't care about the command as long as |
|
# the nesting is correct |
|
return ($line,''); |
|
} |
|
my $open_ignored_ifvalue = 0; |
|
if ($type eq 'ifclear') |
|
{ |
|
if (defined($value{$2})) |
|
{ |
|
$open_ignored_ifvalue = 1; |
|
} |
|
else |
|
{ |
|
push @{$state->{'text_macro_stack'}}, $type; |
|
} |
|
} |
|
elsif ($type eq 'ifset') |
|
{ |
|
unless (defined($value{$2})) |
|
{ |
|
$open_ignored_ifvalue = 1; |
|
} |
|
else |
|
{ |
|
push @{$state->{'text_macro_stack'}}, $type; |
|
} |
|
} |
|
if ($open_ignored_ifvalue) |
|
{ |
|
$state->{'ignored'} = $type; |
|
$state->{'ifvalue'} = $type; |
|
$state->{'ifvalue_inside'} = 1; |
|
# We add at the top of the stack to be able to close all |
|
# opened comands when closing the ifset/ifclear (and ignore |
|
# everything that is in those commands) |
|
push @$stack, { 'style' => 'ifvalue', 'text' => '' }; |
|
} |
|
} |
|
else |
|
{ # we accept a lone @ifset or @ifclear if it is nested in an @if* |
|
if ($state->{'ifvalue'} and $type eq $state->{'ifvalue'}) |
|
{ |
|
$state->{'ifvalue_inside'}++; |
|
return ($line,''); |
|
} |
|
line_error (sprintf(__("%c%s requires a name"), ord('@'), $type), $line_nr) unless ($state->{'ignored'}); |
|
} |
|
} |
|
elsif (not $Texi2HTML::Config::texi_formats_map{$type}) |
|
{ # ignored text |
|
$state->{'ignored'} = $type; |
|
#print STDERR "IGNORED\n"; |
|
} |
|
else |
|
{ |
|
push @{$state->{'text_macro_stack'}}, $type unless($state->{'ignored'}) ; |
|
} |
|
my $text = "\@$type"; |
|
$text .= $value if defined($value); |
|
return ($line, $text); |
|
} |
|
|
|
# do regions handled specially, for example tex or math going through latex2html |
|
sub init_special($$) |
|
{ |
|
my $style = shift; |
|
my $text = shift; |
|
if (defined($Texi2HTML::Config::command_handler{$style}) and |
|
defined($Texi2HTML::Config::command_handler{$style}->{'init'})) |
|
{ |
|
$special_commands{$style}->{'count'} = 0 if (!defined($special_commands{$style})); |
|
if ($Texi2HTML::Config::command_handler{$style}->{'init'}($style,$text, |
|
$special_commands{$style}->{'count'} +1)) |
|
{ |
|
$special_commands{$style}->{'count'}++; |
|
return "\@special_${style}_".$special_commands{$style}->{'count'}."{}"; |
|
} |
|
return ''; |
|
} |
|
} |
|
|
|
sub reset_index_entries($) |
|
{ |
|
my $region = shift; |
|
if (defined($Texi2HTML::THISDOC{'index_entries'}->{$region})) |
|
{ |
|
foreach my $entry (values(%{$Texi2HTML::THISDOC{'index_entries'}->{$region}})) |
|
{ |
|
if (scalar(@{$entry->{'entries'}}) > 1) |
|
{ |
|
$entry->{'index'} = 0; |
|
} |
|
} |
|
} |
|
if (defined($Texi2HTML::THISDOC{'indices_numbers'}->{$region})) |
|
{ |
|
foreach my $index_name (keys(%{$Texi2HTML::THISDOC{'indices_numbers'}->{$region}})) |
|
{ |
|
$Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name} = undef; |
|
} |
|
} |
|
} |
|
|
|
# FIXME we cannot go through the commands too 'often'. The error messages |
|
# are duplicated and global stuff is changed. |
|
# -> identify what is global |
|
# -> use local state |
|
sub do_special_region_lines($;$$) |
|
{ |
|
my $region = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
# this case covers something like |
|
# @copying |
|
# @insertcopying |
|
# @end copying |
|
if (defined($state) and exists($state->{'region'}) and ($region eq $state->{'region'})) |
|
{ |
|
line_error(sprintf(__("Region %s inside region %s is not allowed"), $region, $state->{'region'}), $line_nr); |
|
return ('','', ''); |
|
} |
|
|
|
print STDERR "# do_special_region_lines for region $region ['multiple_pass','region_pass']: ($region_initial_state{$region}->{'multiple_pass'}, $region_initial_state{$region}->{'region_pass'})" if ($T2H_DEBUG); |
|
if (!defined($state)) |
|
{ |
|
$state = {}; |
|
fill_state($state); |
|
$state->{'outside_document'} = 1; |
|
print STDERR " outside document\n" if ($T2H_DEBUG); |
|
} |
|
elsif (!$state->{'outside_document'}) |
|
{ |
|
$region_initial_state{$region}->{'multiple_pass'}++; |
|
print STDERR " multiple pass $region_initial_state{$region}->{'multiple_pass'}\n" if ($T2H_DEBUG); |
|
} |
|
else |
|
{ |
|
print STDERR " in $state->{'region'}, outside document\n" if ($T2H_DEBUG); |
|
} |
|
|
|
return ('','','') unless @{$region_lines{$region}}; |
|
|
|
my @result; |
|
|
|
foreach my $context ('normal', 'remove_texi', 'simple_format') |
|
{ |
|
print STDERR "# $context\n" if ($T2H_DEBUG); |
|
my $new_state = duplicate_formatting_state($state); |
|
reset_index_entries($region); |
|
foreach my $key (keys(%{$region_initial_state{$region}})) |
|
{ |
|
$new_state->{$key} = $region_initial_state{$region}->{$key}; |
|
} |
|
$new_state->{'remove_texi'} = 1 if ($context eq 'remove_texi'); |
|
|
|
&$Texi2HTML::Config::begin_special_region($region,$new_state,$region_lines{$region}) |
|
if (defined($Texi2HTML::Config::begin_special_region)); |
|
|
|
|
|
my $line_numbers; |
|
my $context_string = "$region ($region_initial_state{$region}->{'multiple_pass'}, $region_initial_state{$region}->{'region_pass'})"; |
|
if ($context eq 'normal') |
|
{ # the line numbers are given only for the normal context, therefore |
|
# there will be error messages only in that case |
|
$line_numbers = [ @{$region_line_nrs{$region}} ]; |
|
} |
|
else |
|
{ |
|
$context_string = "$context $context_string"; |
|
} |
|
|
|
my $result; |
|
if ($context ne 'simple_format') |
|
{ |
|
$result = substitute_text($new_state, $line_numbers, |
|
$context_string, @{$region_lines{$region}}); |
|
} |
|
else |
|
{ |
|
$result = simple_format($new_state, $line_numbers, |
|
$context_string, @{$region_lines{$region}}); |
|
} |
|
$result = &$Texi2HTML::Config::end_special_region($region,$new_state,$result) |
|
if (defined($Texi2HTML::Config::end_special_region)); |
|
|
|
push @result, $result; |
|
$region_initial_state{$region}->{'region_pass'}++; |
|
} |
|
|
|
return @result; |
|
} |
|
|
|
sub do_insertcopying($$) |
|
{ |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my ($text, $comment, $simple_formatted) = do_special_region_lines('copying', $state, $line_nr); |
|
return &$Texi2HTML::Config::insertcopying($text, $comment, $simple_formatted); |
|
} |
|
|
|
sub get_deff_index($$$$) |
|
{ |
|
my $tag = shift; |
|
my $line = shift; |
|
my $line_nr = shift; |
|
my $warn = shift; |
|
|
|
$tag =~ s/x$//; |
|
my ($command, $style, $category, $name, $type, $class, $arguments, $args_array, $args_type_array); |
|
($command, $style, $category, $name, $type, $class, $arguments, $args_array, $args_type_array) = parse_def($tag, $line, $line_nr, $warn); |
|
$name = &$Texi2HTML::Config::definition_index_entry($name, $class, $style, $command); |
|
return ($style, '') if (!defined($name) or ($name =~ /^\s*$/)); |
|
return ($style, $name, $arguments); |
|
} |
|
|
|
sub parse_def($$$;$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $line_nr = shift; |
|
my $report = shift; |
|
|
|
my $format = $command; |
|
|
|
if (!ref ($Texi2HTML::Config::def_map{$command})) |
|
{ |
|
# substitute shortcuts for definition commands |
|
my $substituted = $Texi2HTML::Config::def_map{$command}; |
|
$substituted =~ s/(\w+)//; |
|
$format = $1; |
|
$line = $substituted . $line; |
|
} |
|
#print STDERR "PARSE_DEF($command,$format) $line"; |
|
my ($category, $name, $type, $class, $arguments); |
|
my @arguments = (); |
|
my @args = @{$Texi2HTML::Config::def_map{$format}}; |
|
my $style = shift @args; |
|
my @arg_types = (); |
|
while (@args and $args[0] ne 'arg' and $args[0] ne 'argtype') |
|
{ |
|
my $arg = shift @args; |
|
# backward compatibility, it was possible to have a { in front. |
|
$arg =~ s/^\{//; |
|
my ($item, $spaces); |
|
($item, $line, $spaces) = next_def_param($line, $command, $line_nr, $report); |
|
last if (!defined($item)); |
|
if ($arg eq 'category') |
|
{ |
|
$category = $item; |
|
} |
|
elsif ($arg eq 'name') |
|
{ |
|
$name = $item; |
|
} |
|
elsif ($arg eq 'type') |
|
{ |
|
$type = $item; |
|
} |
|
elsif ($arg eq 'class') |
|
{ |
|
$class = $item; |
|
} |
|
push @arg_types, $arg; |
|
push @arguments, $item; |
|
} |
|
my $line_remaining = $line; |
|
$line = ''; |
|
my $arg_and_type = 1; |
|
foreach my $arg (@args) |
|
{ |
|
if ($arg eq 'arg') |
|
{ |
|
$arg_and_type = 0; |
|
last; |
|
} |
|
elsif ($arg eq 'argtype') |
|
{ |
|
last; |
|
} |
|
} |
|
|
|
my $always_delimiter_quoted = quotemeta($Texi2HTML::Config::def_always_delimiters); |
|
my $in_type_delimiter_quoted = quotemeta($Texi2HTML::Config::def_in_type_delimiters); |
|
my $after_type = 0; |
|
while ($line_remaining !~ /^\s*$/) |
|
{ |
|
my ($item, $spaces); |
|
($item, $line_remaining,$spaces) = next_def_param($line_remaining, $command, $line_nr); |
|
if ($item =~ /^([$always_delimiter_quoted])/ or (!$arg_and_type and $item =~ /^([$in_type_delimiter_quoted].*)/)) |
|
{ |
|
$item = $1; |
|
push @arg_types, 'delimiter'; |
|
$after_type = 0; |
|
} |
|
elsif (!$arg_and_type or $item =~ /^\@/ or $after_type) |
|
{ |
|
push @arg_types, 'param'; |
|
$after_type = 0; |
|
} |
|
elsif ($item =~ /^([$in_type_delimiter_quoted])/) |
|
{ |
|
push @arg_types, 'delimiter'; |
|
} |
|
else |
|
{ |
|
push @arg_types, 'paramtype'; |
|
$after_type = 1; |
|
} |
|
$spaces = ' ' if ($spaces); |
|
$line .= $spaces . $item; |
|
push @arguments, $spaces .$item; |
|
} |
|
#print STDERR "PARSE_DEF (style $style, category $category, name $name, type $type, class $class, line $line)\n"; |
|
return ($format, $style, $category, $name, $type, $class, $line, \@arguments, \@arg_types); |
|
} |
|
|
|
sub begin_paragraph($$) |
|
{ |
|
my $stack = shift; |
|
my $state = shift; |
|
|
|
my $command = { }; |
|
my $top_format = top_format($stack); |
|
if (defined($top_format)) |
|
{ |
|
$command = $top_format; |
|
} |
|
$command->{'stack_at_beginning'} = [ @{$state->{'command_stack'}} ]; |
|
my $paragraph_or_preformatted = 'paragraph'; |
|
if ($state->{'preformatted'}) |
|
{ |
|
$paragraph_or_preformatted = 'preformatted'; |
|
$state->{'preformatted_context'} = $command; |
|
} |
|
else |
|
{ |
|
$state->{'paragraph_context'} = $command; |
|
$state->{'paragraph_nr'}++; |
|
} |
|
push @$stack, {'format' => $paragraph_or_preformatted, 'text' => '' }; |
|
# FIXME give line, and modify line? |
|
&$Texi2HTML::Config::begin_paragraph_texi($paragraph_or_preformatted, |
|
$state->{'paragraph_macros'}, $command, $state, $stack) |
|
if (defined($Texi2HTML::Config::begin_paragraph_texi)); |
|
# if there are macros which weren't closed when the previous |
|
# paragraph was closed we reopen them here |
|
push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'}; |
|
delete $state->{'paragraph_macros'}; |
|
} |
|
|
|
sub parse_format_command($$) |
|
{ |
|
my $line = shift; |
|
my $tag = shift; |
|
my $command = ''; |
|
|
|
my $orig_line = $line; |
|
# macro_regexp |
|
if ($line =~ s/^\s*\@([A-Za-z][\w-]*)(\{\})?\s*$//) |
|
{ |
|
$command = $1; |
|
$command = $alias{$command} if (exists($alias{$command})); |
|
} |
|
return ('', $command) if ($line =~ /^\s*$/); |
|
chomp $line; |
|
$line = substitute_text ({'keep_nr' => 1, 'keep_texi' => 1, 'check_item' => $tag}, undef, "parse_format_command", $line); |
|
return ($line, $command); |
|
} |
|
|
|
sub parse_enumerate($) |
|
{ |
|
my $line = shift; |
|
my $spec; |
|
if ($line =~ /^\s*(\w)\b/ and ($1 ne '_')) |
|
{ |
|
$spec = $1; |
|
$line =~ s/^\s*(\w)\s*//; |
|
} |
|
return ($line, $spec); |
|
} |
|
|
|
sub parse_multitable($$) |
|
{ |
|
my $line = shift; |
|
my $line_nr = shift; |
|
# first find the table width |
|
my $table_width = 0; |
|
my $fractions; |
|
my $elements; |
|
if ($line =~ s/^\s+\@columnfractions\s+//) |
|
{ |
|
@$fractions = split /\s+/, $line; |
|
$table_width = scalar(@$fractions); |
|
foreach my $fraction (@$fractions) |
|
{ |
|
unless ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/) |
|
{ |
|
line_error (sprintf(__("column fraction not a number: %s"), $fraction), $line_nr); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
my $element; |
|
my $line_orig = $line; |
|
while ($line !~ /^\s*$/) |
|
{ |
|
my $spaces; |
|
($element, $line, $spaces) = next_bracketed($line, 'multitable', $line_nr, 1); |
|
if ($element =~ /^\{/) |
|
{ |
|
$table_width++; |
|
$element =~ s/^\{//; |
|
$element =~ s/\}\s*$//; |
|
push @$elements, $element; |
|
} |
|
else |
|
{ |
|
line_warn (sprintf(__("ignoring stray text `%s' after \@multitable"), $element), $line_nr); |
|
} |
|
} |
|
} |
|
return ($table_width, $fractions, $elements); |
|
} |
|
|
|
sub end_format($$$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $format = shift; |
|
my $line_nr = shift; |
|
#msg_debug ("END FORMAT $format", $line_nr); |
|
#dump_stack($text, $stack, $state); |
|
#sleep 1; |
|
if ($format_type{$format} eq 'menu') |
|
{ |
|
$state->{$format}--; |
|
if ($state->{$format} < 0) |
|
{ # FIXME currently happens, see invalid/not_closed_in_menu.texi |
|
line_error(sprintf(__("Too many %s closed"), $format), $line_nr); |
|
#print STDERR "Bug, $format counter negative: $state->{$format}\n"; |
|
#dump_stack($text, $stack, $state); |
|
#exit 1; |
|
$state->{$format} = 0; |
|
} |
|
close_menu_comment($text, $stack, $state, "\@end $format", $line_nr); |
|
} |
|
|
|
if ($format_type{$format} eq 'list') |
|
{ # those functions return if they detect an inapropriate context |
|
add_item($text, $stack, $state, $line_nr); # handle lists |
|
} |
|
elsif ($format eq 'multitable') |
|
{ |
|
add_row($text, $stack, $state, $line_nr); # handle multitable |
|
} |
|
elsif ($format_type{$format} eq 'table') |
|
{ |
|
add_term($text, $stack, $state, $line_nr); # handle table |
|
add_line($text, $stack, $state, $line_nr); # handle table |
|
} |
|
|
|
#print STDERR "END_FORMAT\n"; |
|
#dump_stack($text, $stack, $state); |
|
|
|
# set to 1 if there is a mismatch between the closed format and format |
|
# opened before |
|
my $format_mismatch = 0; |
|
# set to 1 in normal menu context after an end menu or detailmenu |
|
my $begin_menu_comment_after_end_format = 0; |
|
|
|
my $format_ref = pop @$stack; |
|
|
|
######################### debug |
|
if (!defined($format_ref->{'text'})) |
|
{ |
|
push @$stack, $format_ref; |
|
print STDERR "Bug: text undef in end_format $format\n"; |
|
dump_stack($text, $stack, $state); |
|
pop @$stack; |
|
} |
|
######################### end debug |
|
|
|
if ($region_lines{$format}) |
|
{ |
|
######################### debug |
|
if ($format ne $state->{'region_lines'}->{'format'}) |
|
{ |
|
msg_debug ("Bug: mismatched region `$format' ne `$state->{'region_lines'}->{'format'}'"); |
|
} |
|
######################### end debug |
|
$state->{'region_lines'}->{'number'}--; |
|
if ($state->{'region_lines'}->{'number'} == 0) |
|
{ |
|
close_region($state); |
|
} |
|
} |
|
|
|
if ($format_type{$format} eq 'table' or $format_type{$format} eq 'list' or $format eq 'multitable') |
|
{ |
|
if ($format_ref->{'format'} ne $format) |
|
{ # for example vtable closing a table. Cannot be known |
|
# before if in a cell |
|
$format_mismatch = 1; |
|
line_error (sprintf(__("`\@end' expected `%s', but saw `%s'"), $format_ref->{'format'}, $format), $line_nr); |
|
|
|
} |
|
if (!$format_ref->{'empty_first'} and $format_ref->{'item_nr'} == 0) |
|
{ |
|
line_warn (sprintf(__("\@%s has text but no \@item"),$format_ref->{'format'}), $line_nr); |
|
} |
|
} |
|
|
|
if (defined($Texi2HTML::Config::def_map{$format})) |
|
{ |
|
close_stack($text, $stack, $state, $line_nr, 'deff_item') |
|
unless ($format_ref->{'format'} eq 'deff_item'); |
|
add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'}, $format_ref->{'only_inter_commands'}, $format_ref->{'orig_command'})); |
|
$format_ref = pop @$stack; # pop deff |
|
######################################### debug |
|
if (!defined($format_ref->{'format'}) or !defined($Texi2HTML::Config::def_map{$format_ref->{'format'}})) |
|
{ |
|
print STDERR "Bug: not a def* under deff_item\n"; |
|
push (@$stack, $format_ref); |
|
dump_stack($text, $stack, $state); |
|
pop @$stack; |
|
} |
|
######################################### end debug |
|
elsif ($format_ref->{'format'} ne $format) |
|
{ |
|
$format_mismatch = 1; |
|
line_error (sprintf(__("`\@end' expected `%s', but saw `%s'"), $format_ref->{'format'}, $format), $line_nr); |
|
} |
|
add_prev($text, $stack, &$Texi2HTML::Config::def($format_ref->{'text'}, $format_ref->{'orig_format'})); |
|
} |
|
elsif ($format eq 'float') |
|
{ |
|
unless (defined($state->{'float'})) |
|
{ |
|
msg_debug("state->{'float'} not defined in float", $line_nr); |
|
next; |
|
} |
|
my ($caption_lines, $shortcaption_lines) = &$Texi2HTML::Config::caption_shortcaption($state->{'float'}); |
|
my ($caption_text, $shortcaption_text); |
|
my $caption_state = duplicate_formatting_state($state); |
|
push @{$caption_state->{'command_stack'}}, 'caption'; |
|
$caption_text = substitute_text($caption_state, undef, '@caption in @end float', @$caption_lines) if (defined($caption_lines)); |
|
|
|
my $shortcaption_state = duplicate_formatting_state($state); |
|
push @{$shortcaption_state->{'command_stack'}}, 'shortcaption'; |
|
$shortcaption_text = substitute_text($shortcaption_state, undef, '@shortcaption in @end float', @$shortcaption_lines) if (defined($shortcaption_lines)); |
|
add_prev($text, $stack, &$Texi2HTML::Config::float($format_ref->{'text'}, $state->{'float'}, $caption_text, $shortcaption_text)); |
|
delete $state->{'float'}; |
|
} |
|
# FIXME $complex_format_map obsoleted in nov 2009 |
|
elsif ((exists ($Texi2HTML::Config::complex_format_map->{$format}) |
|
or exists ($Texi2HTML::Config::complex_format_map{$format})) |
|
and ($format_type{$format} ne 'menu' or $Texi2HTML::Config::SIMPLE_MENU)) |
|
{ |
|
$state->{'preformatted'}--; |
|
pop @{$state->{'preformatted_stack'}}; |
|
my $complex_format; |
|
if (exists ($Texi2HTML::Config::complex_format_map->{$format})) |
|
{ |
|
$complex_format = $Texi2HTML::Config::complex_format_map->{$format}; |
|
} |
|
else |
|
{ |
|
$complex_format = $Texi2HTML::Config::complex_format_map{$format}; |
|
} |
|
# debug |
|
if (!defined($complex_format->{'begin'})) |
|
{ |
|
msg_debug ("Bug undef $format_ref->{'format'}" . "->{'begin'} (for $format...)", $line_nr); |
|
dump_stack ($text, $stack, $state); |
|
} |
|
if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/) |
|
{ |
|
# discard empty fake formats |
|
} |
|
#print STDERR "before $format\n"; |
|
#dump_stack ($text, $stack, $state); |
|
else |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::complex_format($format_ref->{'format'}, $format_ref->{'text'})); |
|
} |
|
#print STDERR "after $format\n"; |
|
#dump_stack ($text, $stack, $state); |
|
} |
|
elsif ($format_type{$format} eq 'table' or $format_type{$format} eq 'list' or $format eq 'multitable') |
|
{ |
|
if (exists ($Texi2HTML::Config::format_map{$format})) |
|
{ # table or list has a simple format |
|
add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}, $state)); |
|
} |
|
else |
|
{ # table or list handler defined by the user |
|
add_prev($text, $stack, &$Texi2HTML::Config::table_list($format_ref->{'format'}, $format_ref->{'text'}, $format_ref->{'command'}, $format_ref->{'formatted_command'}, $format_ref->{'item_nr'}, $format_ref->{'spec'}, $format_ref->{'prepended'}, $format_ref->{'prepended_formatted'}, $format_ref->{'columnfractions'}, $format_ref->{'prototype_row'}, $format_ref->{'prototype_lengths'}, $format_ref->{'max_columns'})); |
|
} |
|
} |
|
elsif ($format_type{$format} eq 'quotation') |
|
{ |
|
my $quotation_args = pop @{$state->{'quotation_stack'}}; |
|
#add_prev($text, $stack, &$Texi2HTML::Config::quotation($format, $format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'text_texi'})); |
|
add_prev($text, $stack, &$Texi2HTML::Config::quotation($format, $format_ref->{'text'}, $format_ref->{'argument_text'}, $format_ref->{'argument_texi'}, $format_ref->{'quote_authors'})); |
|
} |
|
elsif ($Texi2HTML::Config::paragraph_style{$format}) |
|
{ |
|
if ($state->{'paragraph_style'}->[-1] eq $format) |
|
{ |
|
pop @{$state->{'paragraph_style'}}; |
|
} |
|
if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/) |
|
{ |
|
# discard empty fake formats |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command($format_ref->{'format'},$format_ref->{'text'})); |
|
} |
|
} |
|
elsif (exists($Texi2HTML::Config::format_map{$format})) |
|
{ |
|
if ($fake_format{$format_ref->{'format'}} and $format_ref->{'text'} =~ /^\s*$/) |
|
{ |
|
# discard empty fake formats |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'}, $state)); |
|
} |
|
} |
|
elsif ($format_type{$format} eq 'cartouche') |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::cartouche($format_ref->{'text'},$state->{'command_stack'})); |
|
} |
|
elsif ($format_type{$format} eq 'menu') |
|
{ |
|
# it should be short-circuited if $Texi2HTML::Config::SIMPLE_MENU |
|
if ($state->{'preformatted'}) |
|
{ |
|
# remove the fake complex style |
|
$state->{'preformatted'}--; |
|
pop @{$state->{'preformatted_stack'}}; |
|
} |
|
|
|
# backward compatibility with 1.78 jun 2007 |
|
if (defined($Texi2HTML::Config::menu)) |
|
{ |
|
if ($format eq 'menu') |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::menu($format_ref->{'text'})); |
|
} |
|
elsif ($format eq 'detailmenu') # detailmenu |
|
{ |
|
add_prev($text, $stack, $format_ref->{'text'}); |
|
} |
|
else # direntry |
|
{ |
|
} |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::menu_command($format, $format_ref->{'text'}, $state->{'preformatted'})); |
|
} |
|
$begin_menu_comment_after_end_format = 1; |
|
} |
|
else |
|
{ |
|
line_warn(sprintf(__("Unknown format %s"), $format), $line_nr); |
|
} |
|
|
|
# fake formats are not on the command_stack |
|
return 1 if ($fake_format{$format_ref->{'format'}}); |
|
# special case for center as it is at the bottom of the stack |
|
my $removed_from_stack; |
|
if ($format eq 'center') |
|
{ |
|
$removed_from_stack = shift @{$state->{'command_stack'}}; |
|
} |
|
else |
|
{ |
|
$removed_from_stack = pop @{$state->{'command_stack'}}; |
|
} |
|
if ($removed_from_stack ne $format and !$format_mismatch) |
|
{ |
|
#line_error ("Bug: removed_from_stack $removed_from_stack ne format $format", $line_nr); |
|
# it may not be a bug. Consider, for example a @code{in code |
|
# @end cartouche |
|
# The @code is closed when the paragraph is closed by |
|
# @end cartouche but not really closed since it might have been |
|
# a multiple paragraph @code. So it is not removed from |
|
# command_stack but still have disapeared from the stack! |
|
line_error(sprintf(__("mismatched \@end %s with \@%s"), $format, $removed_from_stack), $line_nr); |
|
} |
|
if ($begin_menu_comment_after_end_format and $state->{'menu'}) |
|
{ |
|
begin_format($text, $stack, $state, 'menu_comment', '', $line_nr); |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
sub push_complex_format_style($$$$) |
|
{ |
|
my $command = shift; |
|
my $complex_format = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $class = $command; |
|
|
|
if (!defined($state->{'preformatted_stack'})) |
|
{ |
|
msg_debug ("'preformatted_stack' not defined in push_complex_format_style", $line_nr); |
|
} |
|
|
|
$class = $complex_format->{'class'} if (defined($complex_format->{'class'})); |
|
my $format_style = {'pre_style' =>$complex_format->{'pre_style'}, 'class' => $class, 'command' => $command }; |
|
if (defined($complex_format->{'style'})) |
|
{ |
|
$format_style->{'style'} = $complex_format->{'style'}; |
|
} |
|
else |
|
{ |
|
if ($state->{'preformatted'} and defined($state->{'preformatted_stack'}->[-1]->{'style'})) |
|
{ |
|
$format_style->{'style'} = $state->{'preformatted_stack'}->[-1]->{'style'}; |
|
} |
|
my $index = scalar(@{$state->{'preformatted_stack'}}) -1; |
|
# since preformatted styles are not nested, the preformatted format |
|
# of the first format with style has to be used |
|
if ($index > 0) |
|
{ |
|
while ($index) |
|
{ |
|
if ($state->{'preformatted_stack'}->[$index]->{'style'}) |
|
{ |
|
$format_style->{'class'} = $state->{'preformatted_stack'}->[$index]->{'class'} if (defined($state->{'preformatted_stack'}->[$index]->{'class'})); |
|
last; |
|
} |
|
$index--; |
|
} |
|
} |
|
} |
|
$state->{'preformatted'}++; |
|
push @{$state->{'preformatted_stack'}}, $format_style; |
|
} |
|
|
|
sub prepare_state_multiple_pass($$) |
|
{ |
|
my $command = shift; |
|
my $state = shift; |
|
my $return_state = { |
|
'multiple_pass' => 1, |
|
'element' => $state->{'element'}, |
|
'outside_document' => $state->{'outside_document'}, |
|
'new_state' => 1 |
|
}; |
|
if (defined($command)) |
|
{ |
|
$return_state->{'expansion'} = $command; |
|
$return_state->{'command_stack'} = ["$command"]; |
|
} |
|
else |
|
{ |
|
msg_debug("prepare_state_multiple_pass command not defined"); |
|
} |
|
return $return_state; |
|
} |
|
|
|
sub begin_format($$$$$$); |
|
|
|
sub begin_format($$$$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $macro = shift; |
|
my $line = shift; |
|
my $line_nr = shift; |
|
#msg_debug ("BEGIN FORMAT $macro",$line_nr); |
|
|
|
my $in_term; |
|
my $top_format = top_stack($stack, 2); |
|
$in_term = 1 if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'term'); |
|
|
|
if ($format_type{$macro} eq 'menu') |
|
{ |
|
if ($state->{'menu'}) |
|
{ |
|
# there should not be any paragraph/preformatted to close |
|
# if the comment or the description were closed since they |
|
# close it |
|
if (! close_menu_comment($text, $stack, $state, "\@$macro", $line_nr) |
|
and !close_menu_description($text, $stack, $state, "\@$macro", $line_nr)) |
|
{ |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
} |
|
} |
|
else |
|
{ |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
} |
|
$state->{$macro}++; |
|
} |
|
elsif (!$in_term) |
|
{ |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
} |
|
|
|
# close def_item if this is a matching @def*x command |
|
if (defined($Texi2HTML::Config::def_map{$macro})) |
|
{ |
|
my $top_format = top_format($stack); |
|
if (defined($top_format) and ("$top_format->{'format'}x" eq $macro)) |
|
{ |
|
# this is a matching @DEFx command. |
|
my $deff_item = pop @$stack; |
|
add_prev($text, $stack, |
|
&$Texi2HTML::Config::def_item($deff_item->{'text'}, $deff_item->{'only_inter_commands'}, $deff_item->{'orig_command'})); |
|
#print STDERR "DEFx $macro\n"; |
|
} |
|
elsif ($macro =~ /x$/) |
|
{ |
|
my $base_def_command = $macro; |
|
$base_def_command =~ s/x$//; |
|
line_error(sprintf(__("Must be in `\@%s' environment to use `\@%s'"), $base_def_command, $macro), $line_nr); |
|
} |
|
} |
|
|
|
$line = &$Texi2HTML::Config::begin_format_texi($macro, $line, $state) |
|
unless($fake_format{$macro}); |
|
|
|
push (@{$state->{'command_stack'}}, $macro) unless ($fake_format{$macro}); |
|
if ($region_lines{$macro}) |
|
{ |
|
open_region($macro,$state); |
|
} |
|
# A deff like macro |
|
if (defined($Texi2HTML::Config::def_map{$macro})) |
|
{ |
|
my $top_format = top_format($stack); |
|
my $orig_command = $macro; |
|
if (defined($top_format) and ("$top_format->{'format'}x" eq $macro)) |
|
{ |
|
# this is a matching @DEFx command. |
|
# the @DEFx macro has been put at the top of the |
|
# command_stack, although there is no real format opening |
|
pop @{$state->{'command_stack'}}; |
|
$macro =~ s/x$//o; |
|
#print STDERR "DEFx $macro\n"; |
|
} |
|
else |
|
{ |
|
# a new @def. |
|
$macro =~ s/x$//o; |
|
# we remove what is on the stack and put it back, |
|
# to make sure that it is the form without x. |
|
pop @{$state->{'command_stack'}}; |
|
push @{$state->{'command_stack'}}, $macro; |
|
#print STDERR "DEF begin $macro\n"; |
|
$top_format = { 'format' => $macro, 'text' => '', 'orig_format' =>$orig_command}; |
|
push @$stack, $top_format; |
|
} |
|
#print STDERR "BEGIN_DEFF $macro\n"; |
|
#dump_stack ($text, $stack, $state); |
|
|
|
my ($command, $style, $category, $name, $type, $class, $args_array, $args_type_array); |
|
($command, $style, $category, $name, $type, $class, $line, $args_array, $args_type_array) = parse_def($macro, $line, $line_nr); |
|
my $class_name_texi = &$Texi2HTML::Config::definition_index_entry($name, $class, $style, $command); |
|
|
|
#print STDERR "AFTER parse_def $line"; |
|
my @formatted_args = (); |
|
my $arguments = ''; |
|
my %formatted_arguments = (); |
|
my @types = @$args_type_array; |
|
my $arg_nr = 0; |
|
my $previous_type; |
|
foreach my $arg (@$args_array) |
|
{ |
|
$arg_nr++; |
|
my $type = shift @types; |
|
my $substitution_state = duplicate_formatting_state($state); |
|
# all @def* arguments are in code_style |
|
$substitution_state->{'code_style'}++; |
|
push @formatted_args, substitute_line($arg, sprintf(__("\@%s (argument nr %d)"), $macro, $arg_nr), $substitution_state, $line_nr); |
|
if (grep {$_ eq $type} ('param', 'paramtype', 'delimiter')) |
|
{ |
|
$arguments .= $formatted_args[-1]; |
|
} |
|
else |
|
{ |
|
$formatted_arguments{$type} = $formatted_args[-1]; |
|
} |
|
|
|
$previous_type = $type; |
|
} |
|
$name = $formatted_arguments{'name'}; |
|
$category = $formatted_arguments{'category'}; |
|
$type = $formatted_arguments{'type'}; |
|
$class = $formatted_arguments{'class'}; |
|
|
|
$name = '' if (!defined($name)); |
|
$category = '' if (!defined($category)); |
|
|
|
my $class_category = &$Texi2HTML::Config::definition_category($category, $class, $style, $command); |
|
my $class_name = &$Texi2HTML::Config::definition_index_entry($name, $class, $style, $command); |
|
my ($index_entry, $formatted_index_entry, $index_label) = do_index_entry_label($macro, $state, $line_nr, $class_name_texi, $line); |
|
add_prev($text, $stack, &$Texi2HTML::Config::def_line($class_category, $name, $type, $arguments, $index_label, \@formatted_args, $args_type_array, $args_array, $command, $class_name, $category, $class, $style, $orig_command)); |
|
$line = ''; |
|
push @$stack, { 'format' => 'deff_item', 'text' => '', 'only_inter_commands' => 1, 'format_ref' => $top_format, 'orig_command' => $orig_command}; |
|
begin_paragraph_after_command($state, $stack, $macro, $line); |
|
} |
|
# FIXME $complex_format_map obsoleted in nov 2009 |
|
elsif ((exists ($Texi2HTML::Config::complex_format_map->{$macro}) |
|
or exists ($Texi2HTML::Config::complex_format_map{$macro})) |
|
and ($format_type{$macro} ne 'menu' or $Texi2HTML::Config::SIMPLE_MENU)) |
|
{ # handle menu if SIMPLE_MENU. see texi2html.init |
|
my $complex_format; |
|
if (exists ($Texi2HTML::Config::complex_format_map->{$macro})) |
|
{ |
|
$complex_format = $Texi2HTML::Config::complex_format_map->{$macro}; |
|
} |
|
else |
|
{ |
|
$complex_format = $Texi2HTML::Config::complex_format_map{$macro}; |
|
} |
|
my $format = { 'format' => $macro, 'text' => '', 'pre_style' => $complex_format->{'pre_style'} }; |
|
push_complex_format_style($macro, $complex_format, $state, $line_nr); |
|
push @$stack, $format; |
|
|
|
begin_paragraph($stack, $state); |
|
} |
|
elsif ($Texi2HTML::Config::paragraph_style{$macro}) |
|
{ |
|
|
|
push (@$stack, { 'format' => $macro, 'text' => '' }); |
|
begin_paragraph_after_command($state,$stack,$macro,$line) unless ($in_term); |
|
push @{$state->{'paragraph_style'}}, $macro; |
|
if ($macro eq 'center') |
|
{ |
|
# @center may be in a weird state with regard with |
|
# nesting, so we put it on the bottom of the stack |
|
pop @{$state->{'command_stack'}}; |
|
unshift @{$state->{'command_stack'}}, $macro; |
|
# for similar reasons, we may have a bad stack nesting |
|
# which results in } after a closing. |
|
# The following isn't really true anymore, I think: for example |
|
# @center @samp{something @center end of samp} |
|
# resulted to samp being kept in the 'command_stack' |
|
|
|
} |
|
} |
|
elsif ($format_type{$macro} eq 'list' or $format_type{$macro} eq 'table' or $macro eq 'multitable') |
|
{ |
|
my $format; |
|
#print STDERR "LIST_TABLE $macro\n"; |
|
#dump_stack($text, $stack, $state); |
|
if ($macro eq 'itemize' or $format_type{$macro} eq 'table') |
|
{ |
|
my $command; |
|
my $prepended; |
|
($prepended, $command) = parse_format_command($line,$macro); |
|
if (($command eq '') and ($macro ne 'itemize')) |
|
{ |
|
$command = 'asis'; |
|
line_error(sprintf(__("%s requires an argument: the formatter for %citem"), $macro, ord('@')), $line_nr); |
|
} |
|
my $prepended_formatted; |
|
$prepended_formatted = substitute_line($prepended, sprintf(__("prepended for \@%s"), $macro), prepare_state_multiple_pass('item', $state)) if (defined($prepended)); |
|
$format = { 'format' => $macro, 'text' => '', 'command' => $command, 'prepended' => $prepended, 'prepended_formatted' => $prepended_formatted }; |
|
$line = ''; |
|
} |
|
elsif ($macro eq 'enumerate') |
|
{ |
|
my $spec; |
|
($line, $spec) = parse_enumerate ($line); |
|
$spec = 1 if (!defined($spec)); |
|
$format = { 'format' => $macro, 'text' => '', 'spec' => $spec }; |
|
} |
|
elsif ($macro eq 'multitable') |
|
{ |
|
my ($max_columns, $fractions, $prototype_row) = parse_multitable ($line, $line_nr); |
|
if (!$max_columns) |
|
{ |
|
line_warn (__("empty multitable"), $line_nr); |
|
$max_columns = 0; |
|
} |
|
my @prototype_lengths = (); |
|
if (defined($prototype_row)) |
|
{ |
|
my $prototype_nr = 0; |
|
foreach my $prototype (@$prototype_row) |
|
{ |
|
$prototype_nr++; |
|
push @prototype_lengths, 2+Texi2HTML::Config::t2h_default_string_width(substitute_line($prototype, sprintf(__("\@columnfraction (argument nr %d)"), $prototype_nr), prepare_state_multiple_pass('columnfractions', $state))); |
|
} |
|
} |
|
$format = { 'format' => $macro, 'text' => '', 'max_columns' => $max_columns, 'columnfractions' => $fractions, 'prototype_row' => $prototype_row, 'prototype_lengths' => \@prototype_lengths, 'cell' => 1 }; |
|
} |
|
$format->{'first'} = 1; |
|
$format->{'item_nr'} = 0; |
|
$format->{'paragraph_number'} = 0; |
|
push @$stack, $format; |
|
if ($format_type{$macro} eq 'table') |
|
{ |
|
push @$stack, { 'format' => 'line', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1}; |
|
} |
|
elsif ($macro eq 'multitable') |
|
{ |
|
push @$stack, { 'format' => 'row', 'text' => '', 'format_ref' => $format, 'item_cmd' => $macro }; |
|
push @$stack, { 'format' => 'cell', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1}; |
|
} |
|
if ($format_type{$macro} eq 'list') |
|
{ |
|
push @$stack, { 'format' => 'item', 'text' => '', 'format_ref' => $format, 'only_inter_commands' => 1}; |
|
} |
|
begin_paragraph_after_command($state,$stack,$macro,$line) |
|
if ($macro ne 'multitable'); |
|
return '' unless ($macro eq 'enumerate'); |
|
} |
|
elsif ($macro eq 'float' or $format_type{$macro} eq 'quotation') |
|
{ |
|
push @$stack, {'format' => $macro, 'text' => '' }; |
|
if ($macro eq 'float') |
|
{ |
|
|
|
my @args = parse_line_arguments($line, 2, "\@$macro"); |
|
do_float_line ($macro, \@args, $state->{'style_stack'}, $state, $line_nr); |
|
} |
|
elsif ($format_type{$macro} eq 'quotation') |
|
{ |
|
my @args = parse_line_arguments($line, 1, "\@$macro", $line_nr); |
|
do_quotation_line ($macro, $stack->[-1], \@args, $state->{'style_stack'}, $state, $line_nr); |
|
|
|
} |
|
|
|
$line = ''; |
|
if ($state->{'preformatted'}) |
|
{ # inconditionally begin a preformatted section if needed |
|
begin_paragraph($stack, $state); |
|
} |
|
#dump_stack($text, $stack, $state); |
|
} |
|
# keep this one at the end as there are some other formats |
|
# which are also in format_map |
|
elsif (defined($Texi2HTML::Config::format_map{$macro}) or ($format_type{$macro} eq 'cartouche')) |
|
{ |
|
push @$stack, { 'format' => $macro, 'text' => '' }; |
|
$state->{'code_style'}++ if ($Texi2HTML::Config::format_code_style{$macro}); |
|
begin_paragraph_after_command($state,$stack,$macro,$line); |
|
} |
|
elsif ($format_type{$macro} eq 'menu') |
|
{ |
|
# if $Texi2HTML::Config::SIMPLE_MENU we won't get there |
|
# as the menu is a complex format in that case, so it |
|
# is handled above |
|
push @$stack, { 'format' => $macro, 'text' => '' }; |
|
if ($state->{'preformatted'}) |
|
{ |
|
# add a fake complex style in order to have a given pre style |
|
push_complex_format_style('menu', |
|
$Texi2HTML::Config::MENU_PRE_COMPLEX_FORMAT, $state, $line_nr); |
|
begin_paragraph_after_command($state,$stack,$macro,$line); |
|
} |
|
else |
|
{ |
|
begin_format($text, $stack, $state, 'menu_comment', $line, $line_nr); |
|
} |
|
} |
|
# this is useful for @center, and also if there was something on the |
|
# line after a format that isn't there anymore, like |
|
# @format @c |
|
# if @center line is empty we don't remove the end of line |
|
$line =~ s/^\s*// unless ($macro eq 'center' and $line =~ /^\s*$/); |
|
return $line; |
|
} |
|
|
|
sub do_text($;$) |
|
{ |
|
my $text = shift; |
|
my $state = shift; |
|
return $text if ($state->{'keep_texi'}); |
|
my $remove_texi = 1 if ($state->{'remove_texi'} and !$state->{'simple_format'}); |
|
my $preformatted_style = 0; |
|
if ($state->{'preformatted'}) |
|
{ |
|
$preformatted_style = $state->{'preformatted_stack'}->[-1]->{'style'}; |
|
} |
|
return (&$Texi2HTML::Config::normal_text($text, $remove_texi, $preformatted_style, $state->{'code_style'}, $state->{'math_style'}, $state->{'simple_format'},$state->{'command_stack'}, $state)); |
|
} |
|
|
|
sub end_simple_format($$$) |
|
{ |
|
my $command = shift; |
|
my $text = shift; |
|
my $state = shift; |
|
|
|
my $element = $Texi2HTML::Config::format_map{$command}; |
|
|
|
my $result = &$Texi2HTML::Config::format($command, $element, $text); |
|
$state->{'code_style'}-- if ($Texi2HTML::Config::format_code_style{$command}); |
|
return $result; |
|
} |
|
|
|
# only get there if not in SIMPLE_MENU and not in preformatted and |
|
# right in @menu |
|
sub close_menu_comment($$$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $reason = shift; |
|
my $line_nr = shift; |
|
|
|
my $top_format = top_stack($stack,2); |
|
if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'menu_comment') |
|
{ # this is needed to avoid empty menu-comments <tr>...<pre></pre> |
|
abort_empty_preformatted($stack, $state); |
|
|
|
close_paragraph($text, $stack, $state, $reason, $line_nr); |
|
end_format($text, $stack, $state, 'menu_comment', $line_nr); |
|
return 1; |
|
} |
|
} |
|
|
|
# never get there if in $SIMPLE_MENU |
|
# the last arg is used only if in description and an empty line may |
|
# stop it and begin a menu_comment |
|
sub close_menu_description($$$$$;$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $reason = shift; |
|
my $line_nr = shift; |
|
my $line = shift; |
|
|
|
my $top_format = top_stack($stack,1); |
|
if (!$state->{'preformatted'}) |
|
{ |
|
$top_format = top_stack($stack); |
|
} |
|
|
|
if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'menu_description' and (!defined($line) or $line =~ /^\s*$/) ) |
|
{ |
|
close_paragraph($text, $stack, $state, $reason, $line_nr) if ($state->{'preformatted'}); |
|
my $descr = pop(@$stack); |
|
add_prev($text, $stack, do_menu_description($descr, $state)); |
|
print STDERR "# close_menu: close description\n" if ($T2H_DEBUG & $DEBUG_MENU); |
|
$state->{'code_style'}-- if ($Texi2HTML::Config::format_code_style{'menu_description'}); |
|
return 1; |
|
} |
|
} |
|
|
|
# Format menu link |
|
# FIXME also pass node and name? |
|
sub do_menu_link($$$) |
|
{ |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $menu_entry = shift; |
|
|
|
my $file = $state->{'element'}->{'file'}; |
|
my $node_name = normalise_node($menu_entry->{'node'}); |
|
# normalise_node is used in fact to determine if name is empty. |
|
# It is not passed down to the function reference. |
|
my $name = normalise_node($menu_entry->{'name'}); |
|
|
|
# there is one substitution with spaces kept, and one with spaces |
|
# normalized. In every cases nodes are in code_style |
|
my $node_substitution_state = duplicate_formatting_state($state); |
|
my $name_substitution_state = duplicate_formatting_state($state); |
|
my $node_normalized_substitution_state = duplicate_formatting_state($state); |
|
$node_substitution_state->{'code_style'} = 1; |
|
$node_normalized_substitution_state->{'code_style'} = 1; |
|
$name_substitution_state->{'code_style'} = 1 if ($Texi2HTML::Config::format_code_style{'menu_name'}); |
|
my $node_formatted = substitute_line($menu_entry->{'node'}, __("node name in menu"), $node_substitution_state, $line_nr); |
|
my $node_normalized_formatted = substitute_line($node_name, __("normalized node name in menu"), $node_normalized_substitution_state); |
|
|
|
my $name_formatted; |
|
my $has_name = 0; |
|
if (defined($name) and $name ne '') |
|
{ |
|
$name_formatted = substitute_line($menu_entry->{'name'}, __("menu entry name"), $name_substitution_state, $line_nr); |
|
$has_name = 1; |
|
} |
|
else |
|
{ |
|
my $node_as_name = $menu_entry->{'node'}; |
|
$node_as_name =~ s/^\s*//; |
|
$name_formatted = substitute_line($node_as_name, __("node name in menu"), $name_substitution_state); |
|
} |
|
|
|
my $entry = ''; |
|
my $href; |
|
|
|
my $element; |
|
if ($state->{'direntry'}) |
|
{ |
|
$href = do_external_href($node_name); |
|
} |
|
else |
|
{ |
|
$element = $nodes{$node_name}; |
|
} |
|
|
|
# menu points to an unknown node |
|
if (defined($element) and !$element->{'seen'}) |
|
{ |
|
if ($menu_entry->{'node'} =~ /^\s*\(.*\)/o or Texi2HTML::Config::get_conf('novalidate')) |
|
{ |
|
# menu entry points to another info manual or invalid nodes |
|
# and novalidate is set |
|
#$href = $nodes{$node_name}->{'file'}; |
|
$href = do_external_href($node_name); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Menu reference to nonexistent node `%s'"), $node_name), $line_nr); |
|
# try to find an equivalent node |
|
my @equivalent_nodes = equivalent_nodes($node_name); |
|
my $node_seen; |
|
foreach my $equivalent_node (@equivalent_nodes) |
|
{ |
|
if ($nodes{$equivalent_node}->{'seen'}) |
|
{ |
|
$node_seen = $equivalent_node; |
|
last; |
|
} |
|
} |
|
if (defined($node_seen)) |
|
{ |
|
document_warn("---> but equivalent node `$node_seen' found"); |
|
$element = $nodes{$node_seen}; |
|
} |
|
} |
|
} |
|
|
|
# the original node or an equivalent node was seen |
|
if (defined($element) and $element->{'seen'}) |
|
{ |
|
if ($element->{'reference_element'}) |
|
{ |
|
$element = $element->{'reference_element'}; |
|
} |
|
|
|
#print STDERR "SUBHREF in menu for `$element->{'texi'}'\n"; |
|
$href = href($element, $file, $line_nr); |
|
if (! $element->{'node'}) |
|
{ |
|
$entry = $element->{'text'}; # this is the section/node name |
|
$entry = "$Texi2HTML::Config::MENU_SYMBOL $entry" if (($entry ne '') and (!defined($element->{'number'}) or ($element->{'number'} =~ /^\s*$/)) and $Texi2HTML::Config::UNNUMBERED_SYMBOL_IN_MENU); |
|
} |
|
} |
|
# save the element used for the href for the description |
|
$menu_entry->{'menu_reference_element'} = $element; |
|
|
|
return &$Texi2HTML::Config::menu_link($entry, $state, $href, $node_formatted, $name_formatted, $menu_entry->{'ending'}, $has_name, $state->{'command_stack'}, $state->{'preformatted'}, $node_normalized_formatted); |
|
} |
|
|
|
sub do_menu_description($$) |
|
{ |
|
my $descr = shift; |
|
my $state = shift; |
|
my $text = $descr->{'text'}; |
|
my $menu_entry = $descr->{'menu_entry'}; |
|
|
|
my $element = $menu_entry->{'menu_reference_element'}; |
|
|
|
############# debug |
|
# this is not a bug if element is not defined in direntry |
|
print STDERR "Bug: !defined(element) in do_menu_description\n" if (!defined($element) and ($state->{'menu'} or $state->{'detailmenu'})); |
|
############# end debug |
|
my $element_text = ''; |
|
$element_text = $element->{'text_nonumber'} if (defined($element)); |
|
|
|
return &$Texi2HTML::Config::menu_description($text, duplicate_formatting_state($state),$element_text, $state->{'command_stack'}, $state->{'preformatted'}); |
|
} |
|
|
|
sub do_xref($$$$) |
|
{ |
|
my $macro = shift; |
|
my $args = shift; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my $result = ''; |
|
my @args = @$args; |
|
|
|
my $j; |
|
for ($j = 0; $j <= $#$args; $j++) |
|
{ |
|
$args[$j] = normalise_texi_space($args[$j]); |
|
# print STDERR " ($j)$args[$j]\n"; |
|
} |
|
#print STDERR "DO_XREF: $macro\n"; |
|
if ($macro eq 'inforef') |
|
{ |
|
if ((@args < 1) or $args[0] eq '') |
|
{ |
|
line_error (sprintf(__("First argument to \@%s may not be empty"), $macro), $line_nr); |
|
return ''; |
|
} |
|
} |
|
|
|
my $node_texi = $args[0]; |
|
$node_texi = normalise_node($node_texi); |
|
|
|
#print STDERR "XREF: (@args)\n"; |
|
my $i; |
|
my $new_state = duplicate_formatting_state($state); |
|
$new_state->{'keep_texi'} = 0; |
|
$new_state->{'keep_nr'} = 0; |
|
|
|
my $remove_texi = $new_state->{'remove_texi'}; |
|
|
|
my @formatted_args; |
|
for ($i = 0; $i < 5; $i++) |
|
{ |
|
$args[$i] = '' if (!defined($args[$i])); |
|
my $in_file_style; |
|
$in_file_style = 1 if ($i == 2 and $macro eq 'inforef' or $i == 3 and $macro ne 'inforef'); |
|
$new_state->{'code_style'}++ if ($in_file_style or $i == 0); |
|
$new_state->{'remove_texi'} = 1 if ($in_file_style); |
|
$formatted_args[$i] = substitute_line($args[$i], sprintf(__("\@%s (argument nr %d)"), $macro, $i), $new_state, $line_nr); |
|
$new_state->{'code_style'}-- if ($in_file_style or $i == 0); |
|
$new_state->{'remove_texi'} = $remove_texi if ($in_file_style); |
|
} |
|
|
|
|
|
my ($file_texi, $file); |
|
if ($macro eq 'inforef') |
|
{ |
|
$file_texi = $args[2]; |
|
$file = $formatted_args[2]; |
|
} |
|
else |
|
{ |
|
$file_texi = $args[3]; |
|
$file = $formatted_args[3]; |
|
} |
|
# Remark: makeinfo has this odd error message if the file is empty: |
|
# warning (_("Empty file name for HTML cross reference in `%s'") |
|
# This seems to be spurious. |
|
|
|
# can be an argument or extracted from the node name |
|
my $file_arg_or_node_texi = $file_texi; |
|
my $file_arg_or_node = $file; |
|
|
|
my $node_name; |
|
# the file in parenthesis is removed from node_without_file_texi if needed |
|
my $node_without_file_texi = $node_texi; |
|
# node with file, like (file)node |
|
my $node_and_file_texi; |
|
# the file in parenthesis present with the node |
|
my ($file_of_node_texi, $file_of_node); |
|
if ($node_without_file_texi =~ s/^\(([^\)]+)\)\s*//) |
|
{ |
|
$file_of_node_texi = $1; |
|
$file_of_node = substitute_line($file_of_node_texi, sprintf(__p("\@*ref", "\@%s node file"), $macro), $new_state); |
|
$node_name = substitute_line($node_without_file_texi, sprintf(__p("\@*ref", "\@%s node name"), $macro), $new_state); |
|
$file_arg_or_node_texi = $file_of_node_texi if ($file_arg_or_node_texi eq ''); |
|
$file_arg_or_node = $file_of_node if ($file_arg_or_node eq ''); |
|
# the file argument takes precedence |
|
$node_and_file_texi = "($file_arg_or_node_texi)$node_without_file_texi"; |
|
} |
|
else |
|
{ |
|
# normalized node name |
|
$new_state->{'code_style'}++; |
|
$node_name = substitute_line($node_without_file_texi, sprintf(__p("\@*ref", "\@%s node name"), $macro), $new_state); |
|
$new_state->{'code_style'}--; |
|
if (defined ($file_texi) and $file_texi ne '') |
|
{ |
|
$node_and_file_texi = "($file_texi)$node_texi"; |
|
} |
|
} |
|
|
|
my $node_and_file; |
|
if (defined($node_and_file_texi)) |
|
{ |
|
$node_and_file = substitute_line($node_and_file_texi, sprintf(__p("\@*ref","\@%s node with file name"), $macro), $new_state); |
|
} |
|
else |
|
{ |
|
$node_and_file_texi = $node_texi; |
|
$node_and_file = $node_name; |
|
} |
|
|
|
my $cross_ref_texi = $args[1]; |
|
my $cross_ref = $formatted_args[1]; |
|
|
|
my ($manual_texi, $section_texi, $manual, $section); |
|
if ($macro ne 'inforef') |
|
{ |
|
$manual_texi = $args[4]; |
|
$section_texi = $args[2]; |
|
$manual = $formatted_args[4]; |
|
$section = $formatted_args[2]; |
|
} |
|
else |
|
{ |
|
$manual = $section = ''; |
|
} |
|
|
|
#print STDERR "XREF: (@args)\n"; |
|
|
|
if (($macro eq 'inforef') or ($file_arg_or_node_texi ne '') or ($manual_texi ne '')) |
|
{# external ref |
|
my $href = ''; |
|
if ($file_arg_or_node_texi ne '') |
|
{ |
|
$href = do_external_href($node_and_file_texi); |
|
} |
|
else |
|
{ |
|
$node_and_file = ''; |
|
} |
|
#my $section_or_node = ''; |
|
#if ($manual ne '') |
|
#{ |
|
# $section_or_node = $node_name; |
|
# if ($section ne '') |
|
# { |
|
# $section_or_node = $section; |
|
# } |
|
#} |
|
#$result = &$Texi2HTML::Config::external_ref($macro, $section_or_node, $manual, $node_and_file, $href, $cross_ref, \@args, \@formatted_args); |
|
$result = &$Texi2HTML::Config::external_ref($macro, $section, $manual, $file_arg_or_node, $href, $cross_ref, \@args, \@formatted_args, $node_name); |
|
} |
|
else |
|
{ |
|
my $element = $nodes{$node_without_file_texi}; |
|
if ($element and $element->{'seen'}) |
|
{ |
|
if ($element->{'reference_element'}) |
|
{ |
|
$element = $element->{'reference_element'}; |
|
} |
|
my $file = ''; |
|
if (defined($state->{'element'})) |
|
{ |
|
$file = $state->{'element'}->{'file'}; |
|
} |
|
else |
|
{ |
|
line_warn (sprintf(__("\@%s not in text (in anchor, node, section...)"), $macro), $line_nr); |
|
# if Texi2HTML::Config::SPLIT the file is '' which ensures |
|
# a href with the file name. if ! Texi2HTML::Config::SPLIT |
|
# the 2 file will be the same thus there won't be the file name |
|
$file = $element->{'file'} unless (Texi2HTML::Config::get_conf('SPLIT')); |
|
} |
|
#print STDERR "SUBHREF in ref to node `$node_texi'"; |
|
my $href = href($element, $file, $line_nr); |
|
my $section_or_cross_ref = $section; |
|
$section_or_cross_ref = $cross_ref if ($section eq ''); |
|
if ($element->{'float'} and $section_or_cross_ref eq '') |
|
{ |
|
my $style = substitute_line(&$Texi2HTML::Config::listoffloats_float_style($element->{'style_texi'}, $element), __("\@listoffloats \@float type")); |
|
$section_or_cross_ref = $style if (defined($style)); |
|
} |
|
my $name = $section_or_cross_ref; |
|
my $short_name = $section_or_cross_ref; |
|
if ($section_or_cross_ref eq '') |
|
{ |
|
# FIXME maybe one should use 'text' instead of 'text_nonumber' |
|
# However the real fix would be to have an internal_ref call |
|
# with more informations |
|
$name = $element->{'text_nonumber'}; |
|
$short_name = $node_name; |
|
} |
|
$result = &$Texi2HTML::Config::internal_ref ($macro, $href, $short_name, $name, $element->{'section'}, \@args, \@formatted_args, $element); |
|
} |
|
else |
|
{ |
|
if (($node_texi eq '') or (! Texi2HTML::Config::get_conf('novalidate'))) |
|
{ |
|
line_error (sprintf(__("\@%s reference to nonexistent node `%s'"), $macro, $node_texi), $line_nr); |
|
my $text = ''; |
|
for (my $i = 0; $i < @$args -1; $i++) |
|
{ |
|
$text .= $args->[$i] .','; |
|
} |
|
$text .= $args->[-1]; |
|
$result = "\@$macro"."{${text}}"; |
|
} |
|
else |
|
{ |
|
#$result = &$Texi2HTML::Config::external_ref($macro, '', '', $node_name, do_external_href($node_texi), $cross_ref, \@args, \@formatted_args); |
|
$result = &$Texi2HTML::Config::external_ref($macro, '', '', '', do_external_href($node_texi), $cross_ref, \@args, \@formatted_args, $node_name); |
|
} |
|
} |
|
} |
|
return $result; |
|
} |
|
|
|
sub do_acronym_like($$$$$) |
|
{ |
|
my $command = shift; |
|
my $args = shift; |
|
my $acronym_texi = shift @$args; |
|
my $explanation = shift @$args; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my $explanation_lines; |
|
my $explanation_text; |
|
my $explanation_simple_format; |
|
|
|
if (defined($explanation)) |
|
{ |
|
$explanation = trim_around_spaces($explanation); |
|
$explanation = undef if ($explanation eq ''); |
|
} |
|
$acronym_texi = trim_around_spaces($acronym_texi); |
|
|
|
return '' if ($acronym_texi eq ''); |
|
|
|
my $with_explanation = 0; |
|
my $normalized_text = cross_manual_line(normalise_node($acronym_texi)); |
|
if (defined($explanation)) |
|
{ |
|
$with_explanation = 1; |
|
$acronyms_like{$command}->{$normalized_text} = $explanation; |
|
} |
|
elsif (exists($acronyms_like{$command}->{$normalized_text})) |
|
{ |
|
$explanation = $acronyms_like{$command}->{$normalized_text}; |
|
} |
|
|
|
if (defined($explanation)) |
|
{ |
|
@$explanation_lines = map {$_ = $_."\n"} split (/\n/, $explanation); |
|
my $text = ''; |
|
foreach my $line(@$explanation_lines) |
|
{ |
|
$line .= ' ' if (chomp ($line)); |
|
$text .= $line |
|
} |
|
$text =~ s/ $//; |
|
$explanation_simple_format = simple_format($state, [ $line_nr ], "simple_format \@$command explanation", $text); |
|
$explanation_text = substitute_line($text, sprintf(__p("\@abbr or \@acronym", "\@%s explanation"), $command), duplicate_formatting_state($state), $line_nr); |
|
} |
|
return &$Texi2HTML::Config::acronym_like($command, $acronym_texi, substitute_line($acronym_texi, "\@$command", duplicate_formatting_state($state), $line_nr), |
|
$with_explanation, $explanation_lines, $explanation_text, $explanation_simple_format); |
|
} |
|
|
|
sub do_caption_shortcaption($$$$$$) |
|
{ |
|
my $command = shift; |
|
my $args = shift; |
|
my $text_texi = $args->[0]; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $kept_line_nrs = shift; |
|
|
|
if (!exists($state->{'float'})) |
|
{ |
|
line_error(sprintf(__("\@%s not meaningful outside `\@float' environment"), $command), $line_nr); |
|
return ''; |
|
} |
|
my $float = $state->{'float'}; |
|
my @texi_lines = map {$_ = $_."\n"} split (/\n/, $text_texi); |
|
$float->{"${command}_texi"} = \@texi_lines; |
|
if (defined($kept_line_nrs)) |
|
{ |
|
$float->{"${command}_keep_line_nr"} = [ @$kept_line_nrs ]; |
|
msg_debug ("Empty $kept_line_nrs", $line_nr) unless (@{$kept_line_nrs}); |
|
} |
|
else |
|
{ |
|
$float->{"${command}_keep_line_nr"} = [ $line_nr ]; |
|
msg_debug("do_caption_shortcaption $command, $float, kept_line_nrs not defined", $line_nr); |
|
} |
|
#print STDERR "GGGGGGG @$kept_line_nrs\n"; |
|
return &$Texi2HTML::Config::caption_shortcaption_command($command, |
|
substitute_text(prepare_state_multiple_pass($command, $state), $kept_line_nrs, "\@$command in do_caption_shortcaption", @texi_lines), \@texi_lines, $float); |
|
} |
|
|
|
# function called when a @float is encountered. Don't do any output |
|
# but prepare $state->{'float'} |
|
sub do_float_line($$$$$) |
|
{ |
|
my $command = shift; |
|
my $args = shift; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my @args = @$args; |
|
my $style_texi = shift @args; |
|
my $label_texi = shift @args; |
|
|
|
$style_texi = undef if (defined($style_texi) and $style_texi=~/^\s*$/); |
|
$label_texi = undef if (defined($label_texi) and $label_texi=~/^\s*$/); |
|
|
|
$style_texi = normalise_texi_space($style_texi) if (defined($style_texi)); |
|
|
|
if (defined($label_texi)) |
|
{ # the float is considered as a node as it may be a target for refs. |
|
# it was entered as a node in the pass_structure and the float |
|
# line was parsed at that time |
|
$state->{'float'} = $nodes{normalise_node($label_texi)}; |
|
#msg_debug("float: $state->{'float'}, $state->{'float'}->{'texi'}", $line_nr); |
|
} |
|
else |
|
{ # a float without label. It can't be the target for refs. |
|
$state->{'float'} = { 'float' => 1 }; |
|
if (defined($style_texi)) |
|
{ |
|
$state->{'float'}->{'style_texi'} = $style_texi; |
|
$state->{'float'}->{'style_id'} = |
|
cross_manual_line($state->{'float'}->{'style_texi'}); |
|
} |
|
#print STDERR "float: (no label) $state->{'float'}\n"; |
|
} |
|
$state->{'float'}->{'style'} = substitute_line($state->{'float'}->{'style_texi'}, __("\@float style"), undef, $line_nr); |
|
return ''; |
|
} |
|
|
|
sub do_quotation_line($$$$$$) |
|
{ |
|
my $command = shift; |
|
my $format_ref = shift; |
|
my $args = shift; |
|
my @args = @$args; |
|
my $text_texi = shift @args; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $text; |
|
|
|
$text_texi = undef if (defined($text_texi) and $text_texi=~ /^\s*$/); |
|
if (defined($text_texi)) |
|
{ |
|
$text_texi = trim_around_spaces($text_texi); |
|
$text = substitute_line($text_texi, sprintf(__p("\@*quotation", "\@%s argument"), $command), duplicate_formatting_state($state), $line_nr); |
|
#$text =~ s/\s*$//; |
|
} |
|
my $quotation_args = { 'text' => $text, 'text_texi' => $text_texi }; |
|
push @{$state->{'quotation_stack'}}, $quotation_args; |
|
$format_ref->{'argument_text'} = $text; |
|
$format_ref->{'argument_texi'} = $text_texi; |
|
$state->{'prepend_text'} = &$Texi2HTML::Config::quotation_prepend_text($command, $text_texi); |
|
return ''; |
|
} |
|
|
|
sub do_footnote($$$$$$) |
|
{ |
|
my $command = shift; |
|
my $args = shift; |
|
my $text = $args->[0]; |
|
my $style_stack = shift; |
|
my $doc_state = shift; |
|
my $line_nr = shift; |
|
my $kept_line_nrs = shift; |
|
|
|
$text .= "\n"; |
|
$text = &$Texi2HTML::Config::footnote_texi($text, $doc_state, $style_stack) |
|
if (defined($Texi2HTML::Config::footnote_texi)); |
|
|
|
my $foot_state = duplicate_state($doc_state); |
|
fill_state($foot_state); |
|
push @{$foot_state->{'command_stack'}}, 'footnote'; |
|
|
|
push_state($foot_state); |
|
|
|
my ($foot_num, $relative_foot_num); |
|
my $special_place; |
|
if (!defined($foot_state->{'expansion'}) and !defined($foot_state->{'region'})) |
|
{ |
|
$foot_num = \$global_foot_num; |
|
$relative_foot_num = \$global_relative_foot_num; |
|
} |
|
else |
|
{ |
|
$special_place = $foot_state->{'expansion'}; |
|
$special_place = $foot_state->{'region'} if (!defined($special_place)); |
|
$foot_num = \$doc_state->{'foot_num'}; |
|
$relative_foot_num = \$doc_state->{'relative_foot_num'}; |
|
} |
|
$$foot_num++; |
|
$$relative_foot_num++; |
|
|
|
my $docid = "DOCF$$foot_num"; |
|
my $footid = "FOOT$$foot_num"; |
|
if (defined($special_place)) |
|
{ |
|
$docid = $target_prefix . $special_place . "_$docid"; |
|
$footid = $target_prefix . $special_place . "_$footid"; |
|
} |
|
my $from_file = $docu_doc; |
|
if ($doc_state->{'element'}) |
|
{ |
|
$from_file = $doc_state->{'element'}->{'file'}; |
|
} |
|
|
|
if (Texi2HTML::Config::get_conf('footnotestyle') eq 'separate') |
|
{ |
|
$foot_state->{'element'} = $footnote_element; |
|
} |
|
|
|
$foot_state->{'footnote_number_in_doc'} = $$foot_num; |
|
$foot_state->{'footnote_number_in_page'} = $$relative_foot_num; |
|
$foot_state->{'footnote_footnote_id'} = $footid; |
|
$foot_state->{'footnote_place_id'} = $docid; |
|
$foot_state->{'footnote_document_file'} = $from_file; |
|
$foot_state->{'footnote_footnote_file'} = $foot_state->{'element'}->{'file'}; |
|
$foot_state->{'footnote_document_state'} = $doc_state; |
|
|
|
# FIXME use split_lines ? It seems to work like it is now ? |
|
msg_debug ("No line nnumbers in footnote", $line_nr) if (!defined($kept_line_nrs) or !@$kept_line_nrs); |
|
my @lines; |
|
if (defined($text)) |
|
{ |
|
@lines = substitute_text($foot_state, $kept_line_nrs, '@footnote', map {$_ = $_."\n"} split (/\n/, $text)); |
|
} |
|
my ($foot_lines, $foot_label) = &$Texi2HTML::Config::foot_line_and_ref($$foot_num, |
|
$$relative_foot_num, $footid, $docid, $from_file, $foot_state->{'element'}->{'file'}, \@lines, $doc_state); |
|
if ($doc_state->{'outside_document'} or (defined($doc_state->{'multiple_pass'}) and $doc_state->{'multiple_pass'} > 0)) |
|
{ |
|
#print STDERR "multiple_pass $doc_state->{'multiple_pass'}, 'outside_document' $doc_state->{'outside_document'}\n"; |
|
#print STDERR "REGION FOOTNOTE($$foot_num): $doc_state->{'region'} ($doc_state->{'region_pass'})\n"; |
|
$region_initial_state{$doc_state->{'region'}}->{'footnotes'}->{$$foot_num}->{$doc_state->{'region_pass'}} = $foot_lines if (defined($doc_state->{'region'})); |
|
} |
|
else |
|
{ |
|
#print STDERR "GLOBAL FOOTNOTE($$foot_num)\n"; |
|
push(@foot_lines, @{$foot_lines}); |
|
} |
|
pop_state(); |
|
return $foot_label; |
|
} |
|
|
|
sub do_image($$$$$) |
|
{ |
|
# replace images |
|
my $command = shift; |
|
my $args = shift; |
|
my $style_stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my @args; |
|
foreach my $arg (@$args) |
|
{ |
|
$arg = trim_around_spaces($arg) if (defined($arg)); |
|
push @args, $arg; |
|
} |
|
my $base = substitute_line($args[0], __("\@image base name"),{'code_style' => 1, 'remove_texi' => 1}); |
|
my $base_simple = substitute_line($args[0], __("\@image base name"), {'simple_format' => 1, 'code_style' => 1}); |
|
if ($base eq '') |
|
{ |
|
line_error ("\@image missing filename argument", $line_nr); |
|
return ''; |
|
} |
|
$args[4] = '' if (!defined($args[4])); |
|
$args[3] = '' if (!defined($args[3])); |
|
my $image; |
|
my $extension = substitute_line($args[4], __("\@image extension"), {'code_style' => 1, 'remove_texi' => 1}); |
|
my $extension_simple = substitute_line($args[4], __("\@image extension"), {'simple_format' => 1, 'code_style' => 1}); |
|
my ($file_name, $image_name, $simple_file_name); |
|
my @file_locations; |
|
my @file_names = &$Texi2HTML::Config::image_files($base,$extension,$args[0],$args[4]); |
|
# $image = locate_include_file("$base.$args[4]") if ($args[4] ne ''); |
|
foreach my $file (@file_names) |
|
{ |
|
my $simple_file = substitute_line($file->[1], __("\@image file name"), {'simple_format' => 1, 'code_style' => 1}); |
|
if ($image = locate_include_file($file->[0])) |
|
{ |
|
if (!defined($file_name)) |
|
{ |
|
$file_name = $file->[0]; |
|
$image_name = $image; |
|
$simple_file_name = $simple_file; |
|
} |
|
push @file_locations, [$file, $image, $simple_file]; |
|
} |
|
else |
|
{ |
|
push @file_locations, [$file, undef, $simple_file]; |
|
} |
|
} |
|
$image_name = '' if (!defined($image_name)); |
|
$simple_file_name = '' if (!defined($simple_file_name)); |
|
|
|
my $alt; |
|
if ($args[3] =~ /\S/) |
|
{ |
|
$alt = substitute_line($args[3], __("\@image alt text"), {'simple_format' => 1}, $line_nr); |
|
} |
|
return &$Texi2HTML::Config::image($path_to_working_dir . $image_name, |
|
$base, |
|
$state->{'preformatted'}, $file_name, $alt, $args[1], $args[2], |
|
$args[3], $extension, $path_to_working_dir, $image_name, |
|
$state->{'paragraph_context'}, \@file_locations, $base_simple, |
|
$extension_simple, $simple_file_name, $line_nr); |
|
} |
|
|
|
# usefull if we want to duplicate only the global state, nothing related with |
|
# formatting |
|
sub duplicate_state($) |
|
{ |
|
my $state = shift; |
|
my $new_state = { 'element' => $state->{'element'}, |
|
'multiple_pass' => $state->{'multiple_pass'}, |
|
'region_pass' => $state->{'region_pass'}, |
|
'region' => $state->{'region'}, |
|
'expansion' => $state->{'expansion'}, |
|
'sec_num' => $state->{'sec_num'}, |
|
'outside_document' => $state->{'outside_document'}, |
|
'inside_document' => $state->{'inside_document'}, |
|
'duplicated' => 1 |
|
}; |
|
return $new_state; |
|
} |
|
|
|
# duplicate global and formatting state. |
|
sub duplicate_formatting_state($) |
|
{ |
|
my $state = shift; |
|
my $new_state = duplicate_state($state); |
|
|
|
# Things passed here should be things that are not emptied/set to 0 by |
|
# any command. Also they shouldn't need anything to be on the |
|
# stack. This rules out paragraphs, for example. |
|
foreach my $format_key ('preformatted', 'code_style', 'keep_texi', |
|
'keep_nr', 'preformatted_stack') |
|
{ |
|
$new_state->{$format_key} = $state->{$format_key}; |
|
} |
|
# this is needed for preformatted |
|
my $command_stack = $state->{'command_stack'}; |
|
$command_stack = [] if (!defined($command_stack)); |
|
$new_state->{'command_stack'} = [ @$command_stack ]; |
|
$new_state->{'preformatted_context'} = {'stack_at_beginning' => [ @$command_stack ]}; |
|
$new_state->{'code_style'} = 0 if (!defined($new_state->{'code_style'})); |
|
return $new_state; |
|
} |
|
|
|
sub expand_macro($$$$$) |
|
{ |
|
my $name = shift; |
|
my $args = shift; |
|
my $end_line = shift; |
|
my $line_nr = shift; |
|
my $state = shift; |
|
|
|
# we dont expand macros when in ignored environment. |
|
return if ($state->{'ignored'}); |
|
|
|
die "Bug end_line not defined" if (!defined($end_line)); |
|
|
|
my $index = 0; |
|
foreach my $arg (@$args) |
|
{ # expand @macros in arguments. It is complicated because we must be |
|
# carefull not to expand macros in @ignore section or the like, and |
|
# still keep every single piece of text (including the @ignore macros). |
|
$args->[$index] = substitute_text({'texi' => 1, 'arg_expansion' => 1}, undef, "expand_macro in $name", split_lines($arg)); |
|
$index++; |
|
} |
|
# retrieve the macro definition |
|
my $macrobody = $macros->{$name}->{'body'}; |
|
my $formal_args = $macros->{$name}->{'args'}; |
|
my $args_index = $macros->{$name}->{'args_index'}; |
|
|
|
my $i; |
|
for ($i=0; $i<=$#$formal_args; $i++) |
|
{ |
|
$args->[$i] = "" unless (defined($args->[$i])); |
|
print STDERR "# arg($i): $args->[$i]\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
} |
|
line_error (sprintf(__("Macro `%s' called with too many args"), $name), $line_nr) if (defined($args->[$i + 1])); |
|
my $result = ''; |
|
while ($macrobody ne '') |
|
{ |
|
if ($macrobody =~ s/^([^\\]*)\\//o) |
|
{ |
|
$result .= $1 if defined($1); |
|
if ($macrobody =~ s/^\\//) |
|
{ |
|
$result .= '\\'; |
|
} |
|
elsif ($macrobody =~ s/^(\@end\sr?macro)$// or $macrobody =~ s/^(\@end\sr?macro\s)// or $macrobody =~ s/^(\@r?macro\s+\w+\s*.*)//) |
|
{ # \ protect @end macro |
|
$result .= $1; |
|
} |
|
elsif ($macrobody =~ s/^([^\\]*)\\//) |
|
{ |
|
my $arg = $1; |
|
if (defined($args_index->{$arg})) |
|
{ |
|
$result .= $args->[$args_index->{$arg}]; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\\ in macro expansion followed `%s' instead of parameter name or \\"), $arg), $macros->{$name}->{'line_nr'}); |
|
$result .= '\\' . $arg; |
|
} |
|
} |
|
next; |
|
} |
|
$result .= $macrobody; |
|
last; |
|
} |
|
my @result = split(/^/m, $result); |
|
# for a completly empty macro, $result = '', and the split leads |
|
# to an empty array, so add back an empty string |
|
@result = ('') if (!scalar(@result)); |
|
# Add the result of the macro expansion back to the input_spool. |
|
# Set the macro name if in the outer macro |
|
if ($state->{'arg_expansion'}) |
|
{ # in that case we are in substitute_text for an arg |
|
unshift @{$state->{'spool'}}, (@result, $end_line); |
|
} |
|
else |
|
{ |
|
#$result[-1].=$end_line; |
|
#foreach my $res (@result) |
|
#{ |
|
# print STDERR "RESULT:$res"; |
|
#} |
|
#print STDERR "#########end->$end_line"; |
|
my $last_line = $result[-1]; |
|
if (chomp($last_line)) |
|
{ |
|
push @result, $end_line; |
|
} |
|
else |
|
{ |
|
$result[-1] .= $end_line; |
|
} |
|
unshift @{$state->{'input_spool'}->{'spool'}}, (@result); #, $end_line); |
|
$state->{'input_spool'}->{'macro'} = $name if ($state->{'input_spool'}->{'macro'} eq ''); |
|
} |
|
if ($T2H_DEBUG & $DEBUG_MACROS) |
|
{ |
|
print STDERR "# macro expansion result:\n"; |
|
#print STDERR "$first_line"; |
|
foreach my $line (@result) |
|
{ |
|
print STDERR "$line"; |
|
} |
|
print STDERR "# macro expansion result end\n"; |
|
} |
|
} |
|
|
|
sub do_index_summary_file($$) |
|
{ |
|
my $name = shift; |
|
my $docu_name = shift; |
|
&$Texi2HTML::Config::index_summary_file_begin ($name, $printed_indices{$name}, $docu_name); |
|
print STDERR "# writing $name index summary for $docu_name\n" if $T2H_VERBOSE; |
|
|
|
foreach my $letter_entries (@{$Texi2HTML::THISDOC{'index_letters_array'}->{$name}}) |
|
{ |
|
foreach my $entry (@{$letter_entries->{'entries'}}) |
|
{ |
|
#my $entry = $entries->{$key}; |
|
my $indexed_element = $entry->{'element'}; |
|
my $entry_element = $indexed_element; |
|
$entry_element = $entry_element->{'element_ref'} if (defined($entry_element->{'element_ref'})); |
|
my $origin_href = $entry->{'file'}; |
|
#print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n"; |
|
if ($entry->{'target'}) |
|
{ |
|
$origin_href .= '#' . $entry->{'target'}; |
|
} |
|
else |
|
{ |
|
$origin_href .= '#' . $indexed_element->{'target'}; |
|
} |
|
&$Texi2HTML::Config::index_summary_file_entry ($name, |
|
$entry->{'key'}, $origin_href, |
|
substitute_line($entry->{'entry'}, "\@$entry->{'command'}"), $entry->{'entry'}, |
|
href($entry_element, ''), |
|
$entry_element->{'text'}, |
|
$printed_indices{$name}, |
|
$docu_name); |
|
} |
|
} |
|
&$Texi2HTML::Config::index_summary_file_end ($name, $printed_indices{$name}, $docu_name); |
|
} |
|
|
|
sub get_index_entry_infos($$;$) |
|
{ |
|
my $entry = shift; |
|
my $element = shift; |
|
my $line_nr = shift; |
|
my $index_heading_element = $entry->{'element'}; |
|
my $entry_heading_element = $index_heading_element; |
|
my $real_index_element = $entry->{'real_element'}; |
|
|
|
if (!defined($entry->{'real_element'})) |
|
{ |
|
print STDERR "BUG: entry->{'real_element'} not defined\n"; |
|
} |
|
# we always use the associated element_ref, instead of the original |
|
# element |
|
$entry_heading_element = $entry_heading_element->{'element_ref'} |
|
if (defined($entry_heading_element->{'element_ref'})); |
|
if ($entry->{'real_element'} eq $element_before_anything) |
|
{ |
|
$real_index_element = $element_top; |
|
} |
|
else |
|
{ |
|
$real_index_element = $entry->{'real_element'}->{'element_ref'}; |
|
if (!defined($real_index_element)) |
|
{ # happens when $USE_NODES = 0 and there are only sections, |
|
# and vice-versa |
|
$real_index_element = $entry->{'real_element'}; |
|
} |
|
} |
|
|
|
my $origin_href = ''; |
|
print STDERR "BUG: entry->{'file'} not defined for `$entry->{'entry'}'\n" |
|
if (!defined($entry->{'file'})); |
|
print STDERR "BUG: element->{'file'} not defined for `$entry->{'entry'}', `$element->{'texi'}'\n" |
|
if (!defined($element->{'file'})); |
|
$origin_href = $entry->{'file'} if ($entry->{'file'} ne $element->{'file'}); |
|
#print STDERR "$entry $entry->{'entry'}, real heading elem $index_heading_element->{'texi'}, section $entry_element->{'texi'}, real $index_heading_element->{'file'}, entry file $entry->{'file'}\n"; |
|
if (defined($entry->{'target'})) |
|
{ |
|
$origin_href .= '#' . $entry->{'target'}; |
|
} |
|
else |
|
{ # this means that the index entry is in a special region like @copying... |
|
$origin_href .= '#' . $index_heading_element->{'target'}; |
|
} |
|
#print STDERR "SUBHREF in index entry `$entry->{'entry'}' for `$entry_element->{'texi'}'\n"; |
|
return ($origin_href, |
|
$entry->{'file'}, |
|
$element->{'file'}, |
|
$entry->{'target'}, |
|
$index_heading_element->{'target'}, |
|
substitute_line($entry->{'entry'}, "\@$entry->{'command'} index infos"), |
|
href($entry_heading_element, $element->{'file'}, $line_nr), |
|
$entry_heading_element->{'text'}, |
|
(!$entry->{'seen_in_output'} and defined($entry->{'region'}))); |
|
} |
|
|
|
# remove texi commands, replacing with what seems adequate. see simple_map_texi |
|
# and texi_map. |
|
# Doesn't protect html |
|
sub remove_texi(@) |
|
{ |
|
return substitute_text ({ 'remove_texi' => 1}, undef, undef, @_); |
|
} |
|
|
|
# Same as remove texi but protect text and use special maps for @-commands |
|
sub simple_format($$$@) |
|
{ |
|
my $state = shift; |
|
my $line_nrs = shift; |
|
my $context = shift; |
|
if (!defined($state)) |
|
{ |
|
$state = {}; |
|
} |
|
else |
|
{ |
|
$state = duplicate_formatting_state($state); |
|
} |
|
$state->{'remove_texi'} = 1; |
|
$state->{'simple_format'} = 1; |
|
$::simple_map_texi_ref = \%Texi2HTML::Config::simple_format_simple_map_texi; |
|
$::style_map_texi_ref = \%Texi2HTML::Config::simple_format_style_map_texi; |
|
$::texi_map_ref = \%Texi2HTML::Config::simple_format_texi_map; |
|
my $text = substitute_text($state, $line_nrs, $context, @_); |
|
$::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; |
|
$::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; |
|
$::texi_map_ref = \%Texi2HTML::Config::texi_map; |
|
return $text; |
|
} |
|
|
|
sub index_entry_command_prefix($$$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $line_nr = shift; |
|
if ($command =~ /^(v|f)table$/) |
|
{ |
|
return $1; |
|
} |
|
elsif (defined($Texi2HTML::Config::def_map{$command})) |
|
{ |
|
my ($prefix, $entry, $argument) = get_deff_index($command, $line, undef, 0); |
|
return $prefix; |
|
} |
|
my $prefix = index_command_prefix($command); |
|
line_error(sprintf(__("No index prefix found for \@%s"),$command),$line_nr) if ($prefix eq ''); |
|
return $prefix; |
|
} |
|
|
|
sub enter_table_index_entry($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
if ($state->{'item'}) |
|
{ |
|
my $item_command = $state->{'item'}; |
|
delete $state->{'item'}; |
|
my $item = pop @$stack; |
|
if ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/) |
|
{ |
|
my $index = $1; |
|
enter_index_entry($index, $line_nr, |
|
$item->{'text'}, $state->{'table_stack'}->[-1], $state); |
|
} |
|
add_prev($text, $stack, "\@$item_command" . $item->{'text'}); |
|
} |
|
} |
|
|
|
sub end_macro($$$) |
|
{ |
|
my $state = shift; |
|
my $end_string = shift; |
|
my $remaining_on_the_line = shift; |
|
|
|
$state->{'macro_inside'}--; |
|
return (0, undef) if ($state->{'ignored'}); |
|
if ($state->{'macro_inside'}) |
|
{ |
|
$state->{'macro'}->{'body'} .= $end_string; |
|
return (0, undef); |
|
} |
|
my $macro_text = $state->{'macro'}->{'header'} . $state->{'macro'}->{'body'}.$end_string; |
|
chomp $state->{'macro'}->{'body'}; |
|
print STDERR "# end macro def. Body:\n$state->{'macro'}->{'body'}" |
|
if ($T2H_DEBUG & $DEBUG_MACROS); |
|
$macros->{$state->{'macro'}->{'name'}} = $state->{'macro'} unless ($state->{'arg_expansion'}); |
|
delete $state->{'macro'}; |
|
return (1, $macro_text.$remaining_on_the_line) if ($remaining_on_the_line =~ /^\s*$/); |
|
return (0, $macro_text); |
|
} |
|
|
|
sub close_macro_arg($$$) |
|
{ |
|
my $state = shift; |
|
my $current_line = shift; |
|
my $line_nr = shift; |
|
|
|
# balanced } ends the macro call, otherwise it is in the arg |
|
$state->{'macro_depth'}--; |
|
if ($state->{'macro_depth'} == 0) |
|
{ |
|
#print STDERR "BEFORE: $current_line"; |
|
print STDERR "# expanding macro $state->{'macro_name'}\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
#$current_line = |
|
expand_macro($state->{'macro_name'}, $state->{'macro_args'}, $current_line, $line_nr, $state); |
|
delete $state->{'macro_name'}; |
|
delete $state->{'macro_depth'}; |
|
delete $state->{'macro_args'}; |
|
#print STDERR "AFTER: $current_line"; |
|
#return $current_line; |
|
return 1; |
|
} |
|
else |
|
{ |
|
print STDERR "# macro call: closing }\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
add_text('}', \$state->{'macro_args'}->[-1]); |
|
return undef; |
|
} |
|
} |
|
|
|
sub close_style_texi($$$$;$) |
|
{ |
|
my $style = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $no_close = shift; |
|
|
|
$no_close = 0 if (!defined($no_close)); |
|
|
|
my $result; |
|
if (!defined($style->{'style'})) |
|
{ |
|
msg_debug("'style' not defined in close_style_texi ($no_close)"); |
|
foreach my $key (keys(%$style)) |
|
{ |
|
print STDERR " --> $key: ".var_to_str($style->{$key})."\n"; |
|
} |
|
} |
|
|
|
if (($style->{'style'} ne '') and exists($info_enclose{$style->{'style'}}) and !$state->{'arg_expansion'}) |
|
{ |
|
$result = $info_enclose{$style->{'style'}}->[0] . $style->{'text'} . $info_enclose{$style->{'style'}}->[1]; |
|
} |
|
elsif ($style->{'style'} ne '') |
|
{ |
|
$result = '@' . $style->{'style'} . '{' . $style->{'text'}; |
|
$result .= '}' unless ($no_close); |
|
} |
|
else |
|
{ |
|
$result = '{' . $style->{'text'}; |
|
# don't close { if we are closing stack as we are not |
|
# sure this is a { ... } construct. i.e. we are |
|
# not sure that the user properly closed the matching |
|
# brace, so we don't close it ourselves |
|
$result .= '}' unless ($no_close or $state->{'arg_expansion'}); |
|
} |
|
if ($state->{'ignored'}) |
|
{# ARG_EXPANSION |
|
print STDERR "# Popped `$style->{'style'}' in ifset/ifclear\n" if ($T2H_DEBUG); |
|
} |
|
else |
|
{ |
|
add_prev ($text, $stack, $result); |
|
} |
|
} |
|
|
|
sub close_ignored ($$) |
|
{ |
|
my $state = shift; |
|
my $stack = shift; |
|
if (($state->{'ifvalue_inside'}) and $state->{'ignored'} eq $state->{'ifvalue'}) |
|
{ |
|
if ($state->{'ifvalue_inside'} == 1) |
|
{# closing still opened @-commands with braces |
|
pop (@$stack) while (@$stack and $stack->[-1]->{'style'} ne 'ifvalue') |
|
} |
|
pop (@$stack); |
|
$state->{'ifvalue_inside'}--; |
|
} |
|
$state->{'ignored'} = undef; |
|
delete $state->{'ignored'}; |
|
# We are stil in the ignored ifset or ifclear section |
|
$state->{'ignored'} = $state->{'ifvalue'} if ($state->{'ifvalue_inside'}); |
|
#dump_stack($text, $stack, $state); |
|
} |
|
|
|
|
|
# Called in 2 contexts: |
|
# * in main document |
|
# * from substitute_text, called in turn from arg_expansion. In that case |
|
# 'texi' is true, and so is 'arg_expansion'. In that case constructs are |
|
# expanded but no action is performed. Therefore $line_nr is not of use. |
|
sub scan_texi($$$$;$) |
|
{ |
|
my $scanned_line = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
die "stack not an array ref" unless (ref($stack) eq "ARRAY"); |
|
my $cline = $scanned_line; |
|
|
|
while(1) |
|
{ |
|
# scan_texi |
|
#print STDERR "WHILE(t):$cline"; |
|
#print STDERR "ARG_EXPANSION: $state->{'arg_expansion'}\n" if ($state->{'arg_expansion'}); |
|
#dump_stack($text, $stack, $state); |
|
#print STDERR "ifvalue_inside $state->{'ifvalue_inside'}\n"; |
|
|
|
|
|
# first we handle special cases: |
|
# macro definition: $state->{'macro_inside'} |
|
# macro arguments: $state->{'macro_name'} |
|
# raw format: $state->{'raw'} |
|
# @verb: $state->{'verb'} |
|
# ignored: $state->{'ignored'} |
|
# and then the remaining text/macros. |
|
|
|
# in macro definition |
|
if ($state->{'macro_inside'}) |
|
{ |
|
if ($cline =~ s/^([^\\\@]*\\)//) |
|
{# protected character or @end macro |
|
$state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'}); |
|
if ($cline =~ s/^\\//) |
|
{ |
|
$state->{'macro'}->{'body'} .= '\\' unless ($state->{'ignored'}); |
|
next; |
|
} |
|
# I believe it is correct, although makeinfo don't do that. |
|
elsif ($cline =~ s/^(\@end\sr?macro)$//o or $cline =~ s/^(\@end\sr?macro\s)//o |
|
or $cline =~ s/^(\@r?macro\s+\w+\s*.*)//o) |
|
{ |
|
$state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'}); |
|
next; |
|
} |
|
} |
|
#if ($cline =~ s/^(.*?)\@end\sr?macro$//o or $cline =~ s/^(.*?)\@end\sr?macro\s+//o) |
|
if ($cline =~ s/^(\@end\sr?macro)$//o or $cline =~ s/^(\@end\sr?macro\s+)//o) |
|
{ |
|
my ($no_remaining, $result) = end_macro($state, $1, $cline); |
|
add_prev ($text, $stack, $result) if (defined($result)); |
|
return 1 if ($no_remaining); |
|
next; |
|
} |
|
|
|
elsif($cline =~ /^(\@r?macro\s+\w+\s*.*)/) |
|
{ |
|
$state->{'macro'}->{'body'} .= $cline unless ($state->{'ignored'}); |
|
$state->{'macro_inside'}++; |
|
#return; |
|
return 1; |
|
} |
|
elsif ($cline =~ s/^\@(.)//) |
|
{ |
|
$state->{'macro'}->{'body'} .= '@' . $1 unless ($state->{'ignored'}); |
|
next; |
|
} |
|
elsif ($cline =~ s/^\@//) |
|
{ |
|
$state->{'macro'}->{'body'} .= '@' unless ($state->{'ignored'}); |
|
next; |
|
} |
|
else |
|
{ |
|
$cline =~ s/([^\@\\]*)//; |
|
if ($state->{'ignored'}) |
|
{ |
|
return if ($cline =~ /^$/); |
|
next; |
|
} |
|
$state->{'macro'}->{'body'} .= $1 if (defined($1)); |
|
if ($cline =~ /^$/) |
|
{ |
|
$state->{'macro'}->{'body'} .= $cline; |
|
#return; |
|
return 1; |
|
} |
|
next; |
|
} |
|
} |
|
# in macro arguments parsing/expansion. Here \ { } and , if this is a |
|
# multi args macro have a signification, the remaining is passed |
|
# unmodified |
|
if (defined($state->{'macro_name'})) |
|
{ |
|
my $special_chars = quotemeta ('\{}'); |
|
my $multi_args = 0; |
|
my $formal_args = $macros->{$state->{'macro_name'}}->{'args'}; |
|
$multi_args = 1 if ($#$formal_args >= 1); |
|
$special_chars .= quotemeta(',') if ($multi_args); |
|
if ($state->{'macro_args'}->[-1] eq '') |
|
{# remove space at the very beginning |
|
$cline =~ s/^\s*//o; |
|
} |
|
if ($cline =~ s/^([^$special_chars]*)([$special_chars])//) |
|
{ |
|
$state->{'macro_args'}->[-1] .= $1 if defined($1); |
|
# \ protects any character in macro arguments |
|
if ($2 eq '\\') |
|
{ |
|
print STDERR "# macro call: protected char\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
if ($cline =~ s/^(.)//) |
|
{ |
|
$state->{'macro_args'}->[-1] .= $1; |
|
} |
|
else |
|
{ |
|
$state->{'macro_args'}->[-1] .= '\\'; |
|
} |
|
} |
|
elsif ($2 eq ',') |
|
{ # in texinfo 4.8.90 a comma in braces is protected |
|
if ($state->{'macro_depth'} > 1) |
|
{ |
|
$state->{'macro_args'}->[-1] .= ','; |
|
} |
|
else |
|
{ # separate args |
|
print STDERR "# macro call: new arg\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
$cline =~ s/^\s*//o; |
|
push @{$state->{'macro_args'}}, ''; |
|
} |
|
} |
|
elsif ($2 eq '}') |
|
{ |
|
#my $macro_result_line = close_macro_arg($state, $cline); |
|
return if (close_macro_arg($state, $cline, $line_nr)); |
|
#if (defined($macro_result_line)) |
|
#{ |
|
# $cline = $macro_result_line; |
|
# return; |
|
#} |
|
} |
|
elsif ($2 eq '{') |
|
{ |
|
print STDERR "# macro call: opening {\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
$state->{'macro_depth'}++; |
|
add_text('{', \$state->{'macro_args'}->[-1]); |
|
} |
|
next; |
|
} |
|
print STDERR "# macro call: end of line\n" if ($T2H_DEBUG & $DEBUG_MACROS); |
|
$state->{'macro_args'}->[-1] .= $cline; |
|
return; |
|
} |
|
# in a raw format, verbatim, tex or html |
|
if ($state->{'raw'}) |
|
{ |
|
my $tag = $state->{'raw'}; |
|
|
|
# debugging |
|
if (! @$stack or ($stack->[-1]->{'style'} ne $tag)) |
|
{ |
|
print STDERR "Bug: raw or special: $tag but not on top of stack\n"; |
|
print STDERR "line: $cline"; |
|
dump_stack($text, $stack, $state); |
|
exit 1; |
|
} |
|
|
|
# macro_regexp |
|
if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $tag)) |
|
{ |
|
$cline =~ s/^(.*?)(\@end\s$tag)//; |
|
# we add it even if 'ignored', it'll be discarded just below |
|
# with the @end |
|
add_prev ($text, $stack, $1); |
|
my $end = $2; |
|
my $style = pop @$stack; |
|
# if 'arg_expansion' and 'ignored' are both true text |
|
# is ignored. |
|
add_prev ($text, $stack, $style->{'text'} . $end) unless ($state->{'ignored'}); |
|
delete $state->{'raw'}; |
|
next; |
|
} |
|
else |
|
{# we add it even if 'ignored', it'll be discarded when there is |
|
# the @end |
|
add_prev ($text, $stack, $cline); |
|
last; |
|
} |
|
} |
|
|
|
# in a @verb{ .. } macro |
|
if (defined($state->{'verb'})) |
|
{ |
|
#dump_stack($text, $stack, $state); |
|
my $char = quotemeta($state->{'verb'}); |
|
#print STDERR "VERB $char\n"; |
|
if ($cline =~ s/^(.*?)$char\}/\}/) |
|
{# we add it even if 'ignored', it'll be discarded when closing |
|
add_prev($text, $stack, $1 . $state->{'verb'}); |
|
$stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; |
|
delete $state->{'verb'}; |
|
next; |
|
} |
|
else |
|
{# we add it even if 'ignored', it'll be discarded when closing |
|
add_prev($text, $stack, $cline); |
|
last; |
|
} |
|
} |
|
# In ignored region |
|
if ($state->{'ignored'}) |
|
{ |
|
#print STDERR "IGNORED(ifvalue($state->{'ifvalue_inside'})): $state->{'ignored'}\n"; |
|
if ($cline =~ /^.*?\@end(\s+)([a-zA-Z]\w+)/) |
|
{ |
|
if ($2 eq $state->{'ignored'}) |
|
{ |
|
$cline =~ s/^(.*?\@end)(\s+)([a-zA-Z]\w+)//; |
|
my $end_ignore = $1.$2.$3; |
|
close_ignored($state, $stack); |
|
#dump_stack($text, $stack, $state); |
|
# MACRO_ARG => keep ignored text |
|
if ($state->{'arg_expansion'}) |
|
{# this may not be very usefull as it'll be remove later |
|
add_prev ($text, $stack, $end_ignore); |
|
next; |
|
} |
|
return if ($cline =~ /^\s*$/o); |
|
next; |
|
} |
|
} |
|
add_prev ($text, $stack, $cline) if ($state->{'arg_expansion'}); |
|
# we could theoretically continue for ignored commands other |
|
# than ifset or ifclear, however it isn't usefull. |
|
return unless ($state->{'ifvalue_inside'} and ($state->{'ignored'} eq $state->{'ifvalue'})); |
|
} |
|
|
|
|
|
# an @end tag |
|
# macro_regexp |
|
if ($cline =~ s/^([^{}@]*)\@end(\s+)([a-zA-Z][\w-]*)//) |
|
{ |
|
my $leading_text = $1; |
|
my $space = $2; |
|
my $end_tag = $3; |
|
# when 'ignored' we don't open environments that aren't associated |
|
# with ignored regions, so we don't need to close them. |
|
next if ($state->{'ignored'});# ARG_EXPANSION |
|
add_prev($text, $stack, $leading_text); |
|
if (defined($state->{'text_macro_stack'}) |
|
and @{$state->{'text_macro_stack'}} |
|
and ($end_tag eq $state->{'text_macro_stack'}->[-1])) |
|
{ |
|
pop @{$state->{'text_macro_stack'}}; |
|
# we keep menu and titlepage for the following pass |
|
if (($Texi2HTML::Config::texi_formats_map{$end_tag} eq 'normal') or ($region_lines{$end_tag}) or $state->{'arg_expansion'}) |
|
{ |
|
add_prev($text, $stack, "\@end${space}$end_tag"); |
|
} |
|
else |
|
{ |
|
#print STDERR "End $end_tag\n"; |
|
#dump_stack($text, $stack, $state); |
|
return if ($cline =~ /^\s*$/); |
|
} |
|
} |
|
elsif ($Texi2HTML::Config::texi_formats_map{$end_tag}) |
|
{ |
|
line_error (sprintf(__("Unmatched `%c%s'"), ord('@'), 'end'), $line_nr); |
|
} |
|
else # a format that is not handled during the first pass |
|
{# ARG_EXPANSION |
|
add_prev($text, $stack, "\@end${space}$end_tag"); |
|
} |
|
next; |
|
} |
|
# macro_regexp |
|
elsif ($cline =~ s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)//o) |
|
{# ARG_EXPANSION |
|
add_prev($text, $stack, $1) unless $state->{'ignored'}; |
|
my $command = $2; |
|
# FIXME: if it is an alias, it is substituted below, in the |
|
# diverse add_prev and output of \@$command. Maybe it could be |
|
# kept and only substituted in the last passes? |
|
$command = $alias{$command} if (exists($alias{$command})); |
|
#print STDERR "MACRO $command\n"; |
|
# handle skipped @-commands |
|
$state->{'bye'} = 1 if ($command eq 'bye' and !$state->{'ignored'} and !$state->{'arg_expansion'}); |
|
# 'ignored' and 'arg_expansion' are handled in misc_command_texi |
|
# these are the commands in which the @value and @macro |
|
# and @-commands in general should not be expanded |
|
if (defined($Texi2HTML::Config::misc_command{$command}) and |
|
($command eq 'c' or $command eq 'comment' or $command eq 'set' |
|
or $command eq 'clear' or $command eq 'bye' or $command eq 'alias')) |
|
{ |
|
my $cmd_arg; |
|
($cline, $cmd_arg) = misc_command_texi($cline, $command, $state, |
|
$line_nr); |
|
add_prev ($text, $stack, "\@$command" . $cmd_arg) unless $state->{'ignored'}; |
|
} |
|
elsif ($command eq 'setfilename' or $command eq 'documentencoding' |
|
or $command eq 'definfoenclose' or $command eq 'include') |
|
{ # special commands whose arguments will have @macro and |
|
# @value expanded, and that are processed in this pass |
|
if ($state->{'ignored'} or ($line_nr->{'file_name'} ne $Texi2HTML::THISDOC{'input_file_name'} and $command eq 'setfilename')) |
|
{ # @setfilename is ignored in @include file as said in the manual |
|
$cline = ''; |
|
} |
|
elsif ($state->{'arg_expansion'}) |
|
{ |
|
add_prev($text, $stack, "\@$command" . $cline); |
|
return; |
|
} |
|
else |
|
{ |
|
$cline =~ s/^(\s+)//; |
|
my $space = $1; |
|
# not sure if it happpens at end of line, or with |
|
# special char following the @-command or only at end of file |
|
$space = '' if (!defined($space)); |
|
if (!$state->{'line_command'}) |
|
{ |
|
#print STDERR "LINE_COMMAND Start line_command $command, cline $cline"; |
|
$state->{'line_command'} = $command; |
|
push @$stack, { 'line_command' => $command, 'text' => $space }; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s not allowed in argument to \@%s"), $command, $state->{'line_command'}), $line_nr); |
|
#add_prev($text, $stack, "\@$command" . $space); |
|
add_prev($text, $stack, $space); |
|
} |
|
} |
|
} |
|
# pertusus: it seems that value substitution are performed after |
|
# macro argument expansions: if we have |
|
# @set comma , |
|
# and a call to a macro @macro {arg1 @value{comma} arg2} |
|
# the macro arg is arg1 , arg2 and the comma don't separate |
|
# args. Likewise it seems that the @value are not expanded |
|
# in macro definitions |
|
|
|
elsif ($command =~ /^r?macro$/) |
|
{ # in 'arg_expansion' (ie within another macro call arguments) |
|
# the macro is parsed as usual, but isn't registered in |
|
# end_macro. |
|
if ($cline =~ /^\s+(\w[\w-]*)\s*(.*)/) |
|
{ |
|
my $name = $1; |
|
my $args_def = $2; |
|
unless ($state->{'ignored'} or $state->{'arg_expansion'}) |
|
{ |
|
if (exists($macros->{$name})) |
|
{ |
|
#line_warn ("macro `$name' already defined " . |
|
# format_line_number($macros->{$name}->{'line_nr'}) . " redefined", $line_nr); |
|
line_warn (sprintf(__("macro `%s' previously defined"), $name), $line_nr); |
|
line_warn (sprintf(__("here is the previous definition of `%s'"), $name), $macros->{$name}->{'line_nr'}); |
|
} |
|
} |
|
$state->{'macro_inside'} = 1; |
|
|
|
next if ($state->{'ignored'}); |
|
my @args = (); |
|
if ($args_def =~ /^\s*{\s*(.*?)\s*}\s*/) |
|
{ |
|
@args = split(/\s*,\s*/ , $1) |
|
} |
|
# keep the context information of the definition |
|
my $macro = { 'name' => $name }; |
|
$macro->{'line_nr'} = { 'file_name' => $line_nr->{'file_name'}, |
|
'line_nr' => $line_nr->{'line_nr'}, 'macro' => $line_nr->{'macro'} } if (defined($line_nr)); |
|
$macro->{'args'} = \@args; |
|
$macro->{'header'} = "\@$command" .$cline; |
|
my $arg_index = 0; |
|
my $debug_msg = ''; |
|
foreach my $arg (@args) |
|
{ # when expanding macros, the argument index is retrieved |
|
# with args_index |
|
$macro->{'args_index'}->{$arg} = $arg_index; |
|
$debug_msg .= "$arg($arg_index) "; |
|
$arg_index++; |
|
} |
|
$macro->{'body'} = ''; |
|
$state->{'macro'} = $macro; |
|
print STDERR "# macro def $name: $debug_msg\n" |
|
if ($T2H_DEBUG & $DEBUG_MACROS); |
|
} |
|
else |
|
{# it means we have a macro without a name |
|
line_error (sprintf(__("Macro definition without macro name: %s"), $cline), $line_nr) |
|
unless ($state->{'ignored'}); |
|
} |
|
return 1; |
|
} |
|
elsif (defined($Texi2HTML::Config::texi_formats_map{$command})) |
|
{ |
|
my $tag; |
|
($cline, $tag) = do_text_macro($command, $cline, $state, $stack, $line_nr); |
|
# if it is a raw formatting command or a menu command |
|
# we must keep it for later, unless we are in an 'ignored'. |
|
# if in 'arg_expansion' we keep everything. |
|
my $command_kept; |
|
if ((($state->{'raw'} or ($Texi2HTML::Config::texi_formats_map{$command} eq 'normal') or (exists($region_lines{$command}))) and !$state->{'ignored'}) or $state->{'arg_expansion'}) |
|
{ |
|
add_prev($text, $stack, $tag); |
|
$command_kept = 1; |
|
} |
|
#dump_stack ($text, $stack, $state); |
|
next if $command_kept; |
|
return if ($cline =~ /^\s*$/); |
|
} |
|
elsif ($command eq 'value') |
|
{ |
|
if ($cline =~ s/^{($VARRE)}//) |
|
{ |
|
my $value = $1; |
|
if ($state->{'arg_expansion'}) |
|
{ |
|
add_prev($text, $stack, "\@$command" .'{'. $value .'}'); |
|
next; |
|
} |
|
next if ($state->{'ignored'}); |
|
my $expansion; |
|
if (defined($value{$value})) |
|
{ |
|
$expansion = $value{$value} |
|
} |
|
else |
|
{ |
|
$expansion = gdt('@{No value for `{value}\'@}', {'value' => $value}, {'keep_texi'=> 1}); |
|
line_warn (sprintf(__("undefined flag: %s"), $value), $line_nr); |
|
} |
|
$cline = $expansion . $cline; |
|
} |
|
else |
|
{ |
|
if ($state->{'arg_expansion'}) |
|
{ |
|
add_prev($text, $stack, "\@$command"); |
|
next; |
|
} |
|
next if ($state->{'ignored'}); |
|
line_error (__("Bad syntax for \@value"), $line_nr); |
|
} |
|
} |
|
elsif ($command eq 'unmacro') |
|
{ #FIXME with 'arg_expansion' should it be passed unmodified ? |
|
if ($state->{'ignored'}) |
|
{ |
|
$cline =~ s/^\s+(\w+)//; |
|
} |
|
else |
|
{ |
|
delete $macros->{$1} if ($cline =~ s/^\s+(\w+)//); |
|
} |
|
return if ($cline =~ /^\s*$/); |
|
$cline =~ s/^\s*//; |
|
} |
|
elsif (exists($macros->{$command})) |
|
{# it must be before the handling of {, otherwise it is considered |
|
# to be regular texinfo @-command. Maybe it could be placed higher |
|
# if we want user defined macros to override texinfo @-commands |
|
|
|
# in 'ignored' we parse macro defined args anyway as it removes |
|
# some text, but we don't expand the macro |
|
|
|
my $ref = $macros->{$command}->{'args'}; |
|
my $args_number = $#$ref +1; |
|
# we remove any space/new line before the argument |
|
if ($cline =~ s/^\s*{\s*//) |
|
{ # the macro has args |
|
$state->{'macro_args'} = [ "" ]; |
|
$state->{'macro_name'} = $command; |
|
$state->{'macro_depth'} = 1; |
|
} |
|
elsif (($args_number >= 2) or ($args_number <1)) |
|
{ # no brace -> no arg |
|
#$cline = |
|
#line_warn("\@$command defined with $args_number arguments should be invoked with {}", $line_nr); |
|
line_warn(sprintf(__("\@%s defined with zero or more than one argument should be invoked with {}"), $command), $line_nr); |
|
expand_macro ($command, [], $cline, $line_nr, $state); |
|
return; |
|
} |
|
else |
|
{ # macro with one arg on the line |
|
chomp $cline; |
|
#$cline = |
|
expand_macro ($command, [$cline], "\n", $line_nr, $state); |
|
return; |
|
} |
|
} |
|
elsif ($cline =~ s/^{//) |
|
{# we add nested commands in a stack. verb is also on the stack |
|
# but handled specifically. |
|
# we add it the comands even in 'ignored' as their result is |
|
# discarded when the closing brace appear, or the ifset or |
|
# iclear is closed. |
|
if ($command eq 'verb') |
|
{ |
|
if ($cline =~ /^$/) |
|
{ |
|
line_error (sprintf(__("\@%s without associated character"), $command), $line_nr); |
|
} |
|
else |
|
{ |
|
$cline =~ s/^(.)//; |
|
$state->{'verb'} = $1; |
|
} |
|
} |
|
if ($state->{'line_command'} and $command eq 'verb') |
|
{ # have to close it now to catch if it is not |
|
# closed at te end of the line. In subsequent passes this |
|
# is done in scan_line_separator. |
|
my $result; |
|
if (defined($state->{'verb'})) |
|
{ |
|
$result = '@verb{'.$state->{'verb'}; |
|
my $verb_char = quotemeta($state->{'verb'}); |
|
if ($cline =~ s/^(.*?${verb_char}\})//) |
|
{ |
|
$result .= $1; |
|
} |
|
else |
|
{ |
|
$cline =~ s/^(.*)//; |
|
$result .= $1; |
|
} |
|
delete $state->{'verb'}; |
|
} |
|
else |
|
{ |
|
$result = '@verb{' |
|
} |
|
add_prev($text, $stack, $result) unless($state->{'ignored'}); |
|
} |
|
else |
|
{ |
|
push (@$stack, { 'style' => $command, 'text' => '' }); |
|
} |
|
} |
|
else |
|
{ |
|
$cline = do_unknown(0, $command, $cline, $text, $stack, $state, $line_nr); |
|
} |
|
next; |
|
} |
|
#elsif(s/^([^{}@]*)\@(.)//o) |
|
elsif($cline =~ s/^([^{}@]*)\@([^\s\}\{\@]*)//o) |
|
{# ARG_EXPANSION |
|
# No need to warn here for @ followed by a character that |
|
# is not in any @-command and it is done later |
|
add_prev($text, $stack, $1) unless($state->{'ignored'}); |
|
$cline = do_unknown(0, $2, $cline, $text, $stack, $state, $line_nr); |
|
next; |
|
} |
|
elsif ($cline =~ s/^([^{}]*)([{}])//o) |
|
{ |
|
# in ignored section we cannot be sure that there is an @-command |
|
# already opened so we must discard the text. |
|
# ARG_EXPANSION |
|
add_prev($text, $stack, $1) unless($state->{'ignored'}); |
|
if ($2 eq '{') |
|
{ |
|
# this empty style is for a lone brace. |
|
# we add it even in 'ignored' as it is discarded when the closing |
|
# brace appear, or the ifset or iclear is closed. |
|
push @$stack, { 'style' => '', 'text' => '' }; |
|
} |
|
else |
|
{ |
|
if (@$stack) |
|
{ |
|
my $style = pop @$stack; |
|
close_style_texi($style, $text, $stack, $state); |
|
#print STDERR "MACRO end $style->{'style'} remaining: $cline"; |
|
next; |
|
} |
|
else |
|
{# ARG_EXPANSION |
|
# we warn in the last pass that there is a } without open |
|
add_prev ($text, $stack, '}') unless($state->{'ignored'}); |
|
} |
|
} |
|
} |
|
else |
|
{# ARG_EXPANSION |
|
#print STDERR "END_LINE $cline"; |
|
add_prev($text, $stack, $cline) unless($state->{'ignored'}); |
|
if ($state->{'line_command'}) |
|
{ |
|
if (!scalar(@$stack)) |
|
{ |
|
print STDERR "BUG: empty state for $state->{'line_command'}\n"; |
|
return; |
|
delete $state->{'line_command'}; |
|
} |
|
while (!defined($stack->[-1]->{'line_command'})) |
|
{ |
|
my $top = pop @$stack; |
|
# defer this to later? |
|
#line_error ("unclosed command in \@$state->{'line_command'}: $top->{'style'}"); |
|
add_prev($text, $stack, "\@$top->{'style'}".'{'.$top->{'text'}.'}'); |
|
} |
|
my $command = pop @$stack; |
|
###################### debug |
|
if (!defined($command) or !defined($command->{'text'}) or |
|
!defined($command->{'line_command'}) or ($command->{'line_command'} ne $state->{'line_command'})) |
|
{ |
|
msg_debug ("BUG: messed $state->{'line_command'} stack", $line_nr); |
|
delete $state->{'line_command'}; |
|
return; |
|
} |
|
###################### end debug |
|
else |
|
{ |
|
delete $state->{'line_command'}; |
|
my $macro = $command->{'line_command'}; |
|
# include are not kept |
|
if ($macro eq 'include') |
|
{ |
|
#if (s/^\s+([\/\w.+-]+)//o) |
|
if ($command->{'text'} =~ s/^(\s+)(.+)//o) |
|
{ |
|
my $file_name = $2; |
|
# FIXME scan_line_separators |
|
$file_name = trim_around_spaces($file_name); |
|
$file_name = substitute_line($file_name, "\@$macro", {'code_style' => 1, 'remove_texi' => 1}); |
|
my $file = locate_include_file($file_name); |
|
if (defined($file)) |
|
{ |
|
my ($line_nr_file, $input_spool_file) = open_file($file, $line_nr->{'macro'}, $state->{'files_stack'}); |
|
($line_nr, $state->{'input_spool'}) = ($line_nr_file, $input_spool_file) if (defined($line_nr_file)); |
|
print STDERR "# including $file\n" if $T2H_VERBOSE; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("\@%s: Cannot find %s"), $macro, $file_name), $line_nr); |
|
} |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $macro, $command->{'text'}), $line_nr); |
|
} |
|
return; |
|
} |
|
else |
|
{ # these are kept (setfilename, documentencoding, definfoenclose) |
|
if ($macro eq 'setfilename' and $Texi2HTML::Config::USE_SETFILENAME) |
|
{ |
|
if (defined(Texi2HTML::Config::get_conf ('setfilename'))) |
|
{ |
|
line_error (sprintf(__("\@%s already set"), $macro), $line_nr); |
|
# the line is removed, because we don't want to reset |
|
# get_conf('setfilename') between passes, and we don't want |
|
# the last one to be picked up |
|
$cline = "\n"; |
|
next; |
|
} |
|
} |
|
my $cmd_arg; |
|
($cline, $cmd_arg) = misc_command_texi($command->{'text'}, |
|
$macro, $state, $line_nr); |
|
add_prev ($text, $stack, "\@$macro" . $cmd_arg); |
|
next; |
|
} |
|
} |
|
} |
|
last; |
|
} |
|
} |
|
return undef if ($state->{'ignored'}); |
|
return 1; |
|
} # end scan_texi |
|
|
|
sub close_structure_command($$$$) |
|
{ |
|
my $cmd_ref = shift; |
|
my $state = shift; |
|
my $unclosed_commands = shift; |
|
my $line_nr = shift; |
|
my $result; |
|
|
|
#print STDERR "close_structure_command $cmd_ref->{'style'}\n"; |
|
# If the anchor is in @titlepage or @copying, it is nevertheless only |
|
# expanded once in pass_structure, during the @copying or @titlepage |
|
# expansion. |
|
# It is not true, however if INLINE_INSERTCOPYING is true. |
|
# See indices/index_special_region.texi tests. |
|
if ($cmd_ref->{'style'} eq 'anchor') |
|
{ |
|
my $anchor = $cmd_ref->{'text'}; |
|
$anchor = normalise_node($anchor); |
|
#print STDERR "Anchor $anchor\n"; |
|
if ($nodes{$anchor}) |
|
{# makeinfo error message are the following: |
|
# "Anchor `%s' and node `%s' map to the same file name" |
|
# "This @anchor command ignored; references to it will not work" |
|
# "Rename this anchor or use the `--no-split' option" |
|
# |
|
# "Anchors `%s' and `%s' map to the same file name" |
|
# "Anchor `%s' and node `%s' map to the same file name" |
|
# "@anchor command ignored; references to it will not work" |
|
# "Rename this anchor or use the `--no-split' option" |
|
line_error (sprintf(__("Anchor `%s' previously defined %s"), $anchor, format_line_number($nodes{$anchor}->{'line_nr'})), $line_nr); |
|
return ''; |
|
} |
|
elsif ($anchor =~ /^\(.+\)/) |
|
{ |
|
line_error (sprintf(__("Syntax for an external node used for `%s'"), $anchor), $line_nr); |
|
return ''; |
|
} |
|
$document_anchor_num++; |
|
$nodes{$anchor} = { 'anchor' => 1, 'seen' => 1, 'texi' => $anchor, 'id' => 'ANC' . $document_anchor_num, 'line_nr' => $line_nr, 'tag' => 'anchor'}; |
|
push @{$state->{'place'}}, $nodes{$anchor}; |
|
} |
|
elsif ($cmd_ref->{'style'} eq 'footnote') |
|
{ |
|
if (Texi2HTML::Config::get_conf('footnotestyle') eq 'separate') |
|
{ |
|
$state->{'heading_element'} = $state->{'footnote_heading_element'}; |
|
$state->{'place'} = $state->{'footnote_place'}; |
|
} |
|
} |
|
elsif ($cmd_ref->{'style'} eq 'caption' or $cmd_ref->{'style'} |
|
eq 'shortcaption' and $state->{'float'}) |
|
{ |
|
my @texi_lines = map {$_ = $_."\n"} split (/\n/, $cmd_ref->{'text'}); |
|
$state->{'float'}->{$cmd_ref->{'style'} . "_texi"} = \@texi_lines; |
|
} |
|
if (($cmd_ref->{'style'} eq 'titlefont') and ($cmd_ref->{'text'} =~ /\S/)) |
|
{ |
|
$state->{'heading_element'}->{'titlefont'} = $cmd_ref->{'text'} unless ((exists($state->{'region'}) and ($state->{'region'} eq 'titlepage')) or defined($state->{'heading_element'}->{'titlefont'})) ; |
|
} |
|
if (defined($Texi2HTML::Config::command_handler{$cmd_ref->{'style'}})) |
|
{ |
|
$result = init_special($cmd_ref->{'style'},$cmd_ref->{'text'}); |
|
if ($unclosed_commands) |
|
{ |
|
$result .= "\n"; # the end of line is eaten by init_special |
|
line_error(sprintf(__("No closing brace for specially handled command %s"), $cmd_ref->{'style'}),$line_nr); |
|
} |
|
} |
|
elsif ($cmd_ref->{'style'}) |
|
{ |
|
$result = '@' . $cmd_ref->{'style'} . '{' . $cmd_ref->{'text'}; |
|
$result .= '}' unless ($unclosed_commands); |
|
} |
|
else |
|
{ |
|
$result = '{' . $cmd_ref->{'text'}; |
|
# don't close { if we are closing stack as we are not |
|
# sure this is a licit { ... } construct. |
|
$result .= '}' unless ($unclosed_commands); |
|
} |
|
return $result; |
|
} |
|
|
|
sub end_format_structure($$$$$$) |
|
{ |
|
my $end_tag = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $remaining_on_line = shift; |
|
|
|
if (defined($state->{'text_macro_stack'}) |
|
and @{$state->{'text_macro_stack'}} |
|
and ($end_tag eq $state->{'text_macro_stack'}->[-1])) |
|
{ |
|
pop @{$state->{'text_macro_stack'}}; |
|
if (exists($region_lines{$end_tag})) |
|
{ # end a region_line macro, like documentdescription, copying |
|
print STDERR "Bug: end_tag $end_tag ne $state->{'region_lines'}->{'format'}\n" |
|
if ($end_tag ne $state->{'region_lines'}->{'format'}); |
|
print STDERR "Bug: end_tag $end_tag ne $state->{'region'}\n" |
|
if ($end_tag ne $state->{'region'}); |
|
$state->{'region_lines'}->{'number'}--; |
|
if ($state->{'region_lines'}->{'number'} == 0) |
|
{ |
|
close_region($state); |
|
} |
|
#dump_stack($text, $stack, $state); |
|
} |
|
if (($Texi2HTML::Config::texi_formats_map{$end_tag} eq 'normal') or $Texi2HTML::Config::region_formats_kept{$end_tag}) |
|
{ |
|
$state->{$end_tag}-- if ($Texi2HTML::Config::texi_formats_map{$end_tag} eq 'normal'); |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
} |
|
else |
|
{ |
|
#print STDERR "End $end_tag\n"; |
|
#dump_stack($text, $stack, $state); |
|
return 1 if ($remaining_on_line =~ /^\s*$/); |
|
} |
|
} |
|
elsif ($Texi2HTML::Config::texi_formats_map{$end_tag}) |
|
{ |
|
line_error (sprintf(__("Unmatched `%c%s'"), ord('@'), 'end'), $line_nr); |
|
#dump_stack($text, $stack, $state); |
|
} |
|
elsif ($end_tag eq 'detailmenu' or $end_tag eq 'direntry') |
|
{ |
|
$state->{$end_tag}-- if $state->{$end_tag}; |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
} |
|
else |
|
{ |
|
if ($end_tag eq 'float' and $state->{'float'}) |
|
{ |
|
delete $state->{'float'}; |
|
} |
|
elsif ($end_tag eq $state->{'table_stack'}->[-1]) |
|
{ |
|
enter_table_index_entry($text, $stack, $state, $line_nr); |
|
pop @{$state->{'table_stack'}}; |
|
} |
|
#add end tag |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
} |
|
return 0; |
|
} |
|
|
|
sub parse_menu_entry($) |
|
{ |
|
my $menu_line = shift; |
|
my ($node, $name, $ending, $remaining); |
|
|
|
return ($node, $name, $ending, $remaining) unless $menu_line =~ s/^\*//; |
|
|
|
my ($before_colon, $separator); |
|
($before_colon, $remaining, $separator) = scan_line_separators($menu_line, ':', 'menu entry'); |
|
if (defined($before_colon) and defined($separator)) |
|
{ |
|
if ($remaining =~ s/^://) |
|
{ |
|
$node = $before_colon; |
|
$ending = '::'; |
|
} |
|
elsif ($remaining =~ /\S/) |
|
{ |
|
my $after_colon; |
|
$ending = ""; |
|
($after_colon, $remaining, $separator) = scan_line_separators($remaining, '\t,\.', 'menu entry node'); |
|
# this certainly corresponds with an error in the node. |
|
# this is considered not to be a menu entry. |
|
return (undef, $name, $ending, $remaining) if (!defined($after_colon)); |
|
$node = $after_colon; |
|
|
|
while (1) |
|
{ |
|
if (!defined($separator) or (defined($separator) and $separator ne '.') or (defined($separator) and (!defined($remaining) or $remaining =~ /^\s/))) |
|
{ |
|
last; |
|
} |
|
$node .= $separator; |
|
my $after_dot; |
|
($after_dot, $remaining, $separator) = scan_line_separators($remaining, '\t,\.', 'menu entry node'); |
|
$after_dot = '' if (!defined($after_dot)); |
|
$node .= $after_dot; |
|
} |
|
$name = $before_colon; |
|
$ending = $separator if (defined($separator)); |
|
# only spaces after the :, this is not a menu entry: |
|
$node = undef if ($node !~ /\S/); |
|
} |
|
} |
|
# remaining may be defined even if $node isn't. |
|
#print STDERR "\nLLLL $menu_line"; |
|
#print STDERR " --> node:$node, name:$name, ending:$ending -> $remaining"; |
|
return ($node, $name, $ending, $remaining); |
|
} |
|
|
|
sub scan_structure($$$$;$) |
|
{ |
|
my $line = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
die "stack not an array ref" unless (ref($stack) eq "ARRAY"); |
|
my $cline = $line; |
|
#print STDERR "SCAN_STRUCTURE: $line"; |
|
#dump_stack ($text, $stack, $state); |
|
if (!$state->{'raw'} and (!exists($state->{'region_lines'}))) |
|
{ |
|
#if (!$state->{'verb'} and $state->{'menu'} and $cline =~ /^\*\s+/o) |
|
if (!$state->{'verb'} and $state->{'menu'}) |
|
{ |
|
# new menu entry |
|
my ($node, $name, $ending, $remaining) = parse_menu_entry($cline); |
|
if (defined($node)) |
|
{ |
|
menu_entry_texi(normalise_node($node), $state, $line_nr); |
|
} |
|
} |
|
} |
|
|
|
while(1) |
|
{ |
|
# scan structure |
|
#dump_stack($text, $stack, $state); |
|
#print STDERR "WHILE(s):$cline"; |
|
|
|
# as texinfo 4.5 |
|
# verbatim might begin at another position than beginning |
|
# of line, and end verbatim might too. To end a verbatim section |
|
# @end verbatim must have exactly one space between end and verbatim |
|
# things following end verbatim are not ignored. |
|
# |
|
# html might begin at another position than beginning |
|
# of line, but @end html must begin the line, and have |
|
# exactly one space. Things following end html are ignored. |
|
# tex and ignore works like html |
|
# |
|
# ifnothtml might begin at another position than beginning |
|
# of line, and @end ifnothtml might too, there might be more |
|
# than one space between @end and ifnothtml but nothing more on |
|
# the line. |
|
# @end itemize, @end ftable works like @end ifnothtml. |
|
# except that @item on the same line than @end vtable doesn't work |
|
# |
|
# text right after the itemize before an item is displayed. |
|
# @item might be somewhere in a line. |
|
# strangely @item on the same line than @end vtable doesn't work |
|
# there should be nothing else than a command following @itemize... |
|
# |
|
# see more examples in formatting directory |
|
|
|
if ($state->{'raw'}) |
|
{ |
|
my $tag = $state->{'raw'}; |
|
################# debug |
|
if (! @$stack or ($stack->[-1]->{'style'} ne $tag)) |
|
{ |
|
print STDERR "Bug: raw or special: $tag but not on top of stack\n"; |
|
print STDERR "line: $cline"; |
|
dump_stack($text, $stack, $state); |
|
exit 1; |
|
} |
|
################# end debug |
|
if ($tag eq 'macro') |
|
{ |
|
if ($cline =~ /^\s*\@macro\s+(\w[\w-]*)\s*(.*)/) |
|
{ |
|
$state->{$tag}++; |
|
} |
|
} |
|
# macro_regexp |
|
if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $tag)) |
|
{ |
|
$cline =~ s/^(.*?)(\@end\s$tag)//; |
|
add_prev ($text, $stack, $1); |
|
my $end_text = $2; |
|
if ($tag eq 'macro') |
|
{ |
|
$state->{$tag}--; |
|
if ($state->{$tag}) |
|
{ |
|
add_prev ($text, $stack, $end_text); |
|
next; |
|
} |
|
} |
|
delete $state->{'raw'}; |
|
my $style = pop @$stack; |
|
if (defined($Texi2HTML::Config::command_handler{$tag})) |
|
{ # replace the special region by what init_special give |
|
if ($style->{'text'} !~ /^\s*$/) |
|
{ |
|
add_prev ($text, $stack, init_special($style->{'style'}, $style->{'text'})); |
|
} |
|
} |
|
else |
|
{ |
|
add_prev ($text, $stack, $style->{'text'} . "\@end $tag"); |
|
} |
|
next; |
|
} |
|
else |
|
{ |
|
add_prev ($text, $stack, $cline); |
|
return if (defined($Texi2HTML::Config::command_handler{$tag})); |
|
last; |
|
} |
|
} |
|
|
|
if (defined($state->{'verb'})) |
|
{ |
|
my $char = quotemeta($state->{'verb'}); |
|
if ($cline =~ s/^(.*?)$char\}/\}/) |
|
{ |
|
add_prev($text, $stack, $1 . $state->{'verb'}); |
|
$stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; |
|
delete $state->{'verb'}; |
|
next; |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, $cline); |
|
last; |
|
} |
|
} |
|
|
|
# macro_regexp |
|
if ($cline =~ s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//) |
|
{ |
|
add_prev($text, $stack, $1); |
|
my $end_tag = $2; |
|
#print STDERR "END STRUCTURE $end_tag\n"; |
|
return if (end_format_structure($end_tag, $text, $stack, $state, $line_nr, $cline)); |
|
next; |
|
} |
|
# macro_regexp |
|
elsif ($cline =~ s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@]*)\@([a-zA-Z][\w-]*)//o) |
|
{ |
|
add_prev($text, $stack, $1); |
|
my $macro = $2; |
|
#print STDERR "MACRO $macro\n"; |
|
$macro = $alias{$macro} if (exists($alias{$macro})); |
|
if (defined($Texi2HTML::Config::deprecated_commands{$macro})) |
|
{ |
|
# makeinfo has |
|
# "%c%s is obsolete; use %c%s instead" |
|
if ($Texi2HTML::Config::deprecated_commands{$macro} eq '') |
|
{ |
|
line_warn(sprintf(__("%c%s is obsolete."), ord('@'), $macro), $line_nr); |
|
} |
|
else |
|
{ |
|
line_warn(sprintf(__("%c%s is obsolete; %s"),ord('@'), $macro, __($Texi2HTML::Config::deprecated_commands{$macro})), $line_nr); |
|
} |
|
} |
|
if (defined($Texi2HTML::Config::misc_command{$macro})) |
|
{ |
|
my $line; |
|
($cline, $line) = misc_command_structure($cline, $macro, $state, |
|
$line_nr); |
|
add_prev ($text, $stack, "\@$macro".$line); |
|
next; |
|
} |
|
elsif ($macro eq 'printindex' and ($cline =~ /^\s+(\w+)/)) |
|
{ |
|
my $index_name = $1; |
|
if (!exists($index_names{$index_name})) |
|
{ |
|
line_error (sprintf(__("Unknown index `%s' in \@printindex"),$index_name), $line_nr); |
|
} |
|
my $associated_element; |
|
if ($state->{'current_element'} eq $element_before_anything) |
|
{ |
|
line_warn (sprintf(__("Printindex before document beginning: \@printindex %s"), $index_name), $line_nr); |
|
} |
|
else |
|
{ |
|
# $element_index is the first element with index |
|
$element_index = $state->{'current_element'} unless (defined($element_index)); |
|
$associated_element = $state->{'current_element'}; |
|
} |
|
my $region = $state->{'region'}; |
|
$region = 'document' if (!defined($region)); |
|
# FIXME use 'index_name' instead of 'name' |
|
my $printindex = { 'associated_element' => $associated_element, 'name' => $index_name, 'region' => $region, 'command' => 'printindex' }; |
|
# prepare association of the index to the element by |
|
# putting it in the current place |
|
push @{$state->{'place'}}, $printindex; |
|
push @{$Texi2HTML::THISDOC{'indices'}->{$region}->{$index_name}}, $printindex; |
|
#print STDERR "PRINTINDEX add($printindex) region $region name $index_name, nr ".scalar(@{$Texi2HTML::THISDOC{'indices'}->{$region}->{$index_name}})."\n"; |
|
add_prev ($text, $stack, "\@$macro" . $cline); |
|
last; |
|
} |
|
elsif ($macro eq 'listoffloats') |
|
{ |
|
add_prev ($text, $stack, "\@$macro" . $cline); |
|
last; |
|
} |
|
elsif ($sec2level{$macro}) |
|
{ |
|
if ($cline =~ /^\s*(.*)$/) |
|
{ |
|
my $name = $1; |
|
my $heading_ref = new_section_heading($macro, $name, $state, $line_nr); |
|
if (exists($state->{'region_lines'}) and $state->{'region_lines'}->{'format'}) |
|
{ |
|
my $region = $state->{'region_lines'}->{'format'}; |
|
$state->{'region_lines'}->{'head_num'}++; |
|
my $num = $state->{'region_lines'}->{'head_num'}; |
|
$heading_ref->{'id'} = "${target_prefix}${region}_HEAD$num"; |
|
$heading_ref->{'sec_num'} = "${region}_$num"; |
|
$heading_ref->{'region'} = $region; |
|
$heading_ref->{'region_head_num'} = $num; |
|
} |
|
else |
|
{ |
|
$document_head_num++; |
|
$heading_ref->{'id'} = "HEAD$document_head_num"; |
|
$heading_ref->{'sec_num'} = $document_head_num; |
|
} |
|
# this is only used when there is a index entry after the |
|
# heading |
|
$heading_ref->{'target'} = $heading_ref->{'id'}; |
|
$heading_ref->{'heading'} = 1; |
|
$heading_ref->{'tag_level'} = $macro; |
|
$heading_ref->{'number'} = ''; |
|
|
|
$state->{'heading_element'} = $heading_ref; |
|
push @{$state->{'place'}}, $heading_ref; |
|
$headings{$heading_ref->{'sec_num'}} = $heading_ref; |
|
} |
|
add_prev ($text, $stack, "\@$macro" . $cline); |
|
last; |
|
} |
|
elsif (index_command_prefix($macro) ne '') |
|
{ # if we are already in a (v|f)table the construct is quite |
|
# wrong |
|
# FIXME should it be discarded? |
|
if ($state->{'item'}) |
|
{ |
|
line_error(sprintf(__("ignored \@%s already in an \@%s entry"), $macro, $state->{'item'}), $line_nr); |
|
next; |
|
} |
|
my $index_prefix = index_command_prefix($macro); |
|
enter_index_entry($index_prefix, $line_nr, $cline, $macro, $state); |
|
add_prev ($text, $stack, "\@$macro" . $cline); |
|
last; |
|
} |
|
elsif (defined($Texi2HTML::Config::texi_formats_map{$macro})) |
|
{ |
|
my $macro_kept; |
|
#print STDERR "TEXT_MACRO: $macro\n"; |
|
if ($Texi2HTML::Config::texi_formats_map{$macro} eq 'raw') |
|
{ |
|
$state->{'raw'} = $macro; |
|
$state->{$macro}++ if ($macro eq 'macro'); |
|
#print STDERR "RAW\n"; |
|
} |
|
elsif ($Texi2HTML::Config::texi_formats_map{$macro} eq 'normal') |
|
{ |
|
if ($macro eq 'menu') |
|
{ |
|
delete ($state->{'prev_menu_node'}); |
|
if (!$state->{'node_ref'}) |
|
{ |
|
line_error (sprintf(__("\@%s seen before first \@node"), $macro), $line_nr); |
|
line_error (__("perhaps your \@top node should be wrapped in \@ifnottex rather than \@ifinfo?"), $line_nr); |
|
} |
|
if ($state->{'menu_in_node'}) |
|
{ |
|
line_error (sprintf(__("Multiple \@%s"), $macro), $line_nr); |
|
} |
|
$state->{'menu_in_node'}++; |
|
} |
|
$state->{$macro}++; |
|
push @{$state->{'text_macro_stack'}}, $macro; |
|
#print STDERR "MENU (text_macro_stack: @{$state->{'text_macro_stack'}})\n"; |
|
} |
|
elsif (exists($region_lines{$macro})) |
|
{ |
|
if (exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} ne $macro)) |
|
{ |
|
line_error(sprintf(__("\@%s not allowed within %s"), $macro, $state->{'region_lines'}->{'format'}), $line_nr); |
|
next; |
|
} |
|
open_region ($macro, $state); |
|
if ($Texi2HTML::Config::region_formats_kept{$macro}) |
|
{ |
|
add_prev($text, $stack, "\@$macro"); |
|
$macro_kept = 1; |
|
$state->{'region_lines'}->{'first_line'} = 1; |
|
} |
|
push @{$state->{'text_macro_stack'}}, $macro; |
|
} |
|
# if it is a raw formatting command or a menu command |
|
# we must keep it for later |
|
if (($state->{'raw'} and (!defined($Texi2HTML::Config::command_handler{$macro}))) or ($Texi2HTML::Config::texi_formats_map{$macro} eq 'normal')) |
|
{ |
|
add_prev($text, $stack, "\@$macro"); |
|
$macro_kept = 1; |
|
} |
|
if ($state->{'raw'}) |
|
{ |
|
push @$stack, { 'style' => $macro, 'text' => '' }; |
|
} |
|
next if $macro_kept; |
|
#dump_stack ($text, $stack, $state); |
|
return if ($cline =~ /^\s*$/); |
|
} |
|
elsif ($macro eq 'detailmenu' or $macro eq 'direntry') |
|
{ |
|
if ($macro eq 'detailmenu' and !$state->{'node_ref'}) |
|
{ |
|
line_error (sprintf(__("\@%s seen before first \@node"), $macro), $line_nr); |
|
} |
|
add_prev ($text, $stack, "\@$macro" . $cline); |
|
$state->{$macro}++; |
|
last; |
|
} |
|
elsif ($macro eq 'float') |
|
{ |
|
my ($style_texi, $label_texi) = parse_line_arguments($cline, 2, "\@$macro", $line_nr); |
|
$style_texi = normalise_texi_space($style_texi); |
|
$label_texi = undef if (defined($label_texi) and ($label_texi =~ /^\s*$/)); |
|
if (defined($label_texi)) |
|
{ # The float may be a target for refs if it has a label |
|
my $error_with_label = 1; |
|
$label_texi = normalise_node($label_texi); |
|
if (exists($nodes{$label_texi}) and defined($nodes{$label_texi}) |
|
and $nodes{$label_texi}->{'seen'}) |
|
{ |
|
line_error (sprintf(__("Float label `%s' previously defined %s"), $label_texi, format_line_number($nodes{$label_texi}->{'line_nr'})), $line_nr); |
|
} |
|
elsif ($label_texi =~ /^\(.+\)/) |
|
{ |
|
line_error (sprintf(__("Syntax for an external node used for `%s'"), $label_texi), $line_nr); |
|
} |
|
else |
|
{ |
|
$error_with_label = 0; |
|
my $float = { }; |
|
if (exists($nodes{$label_texi}) and defined($nodes{$label_texi})) |
|
{ # float appeared in a menu |
|
$float = $nodes{$label_texi}; |
|
} |
|
else |
|
{ |
|
$nodes{$label_texi} = $float; |
|
} |
|
$float->{'float'} = 1; |
|
$float->{'tag'} = 'float'; |
|
$float->{'texi'} = $label_texi; |
|
$float->{'seen'} = 1; |
|
$float->{'id'} = $label_texi; |
|
$float->{'target'} = $label_texi; |
|
#print STDERR "FLOAT: $float $float->{'texi'}, place $state->{'place'}\n"; |
|
push @{$state->{'place'}}, $float; |
|
$float->{'element'} = $state->{'current_element'}; |
|
$state->{'float'} = $float; |
|
$float->{'style_texi'} = $style_texi; |
|
$float->{'line_nr'} = $line_nr; |
|
push @floats, $float; |
|
} |
|
|
|
if ($error_with_label) |
|
{ |
|
while ($cline =~ /,/) |
|
{ |
|
$cline =~ s/,.*$//; |
|
} |
|
} |
|
} |
|
add_prev($text, $stack, "\@$macro" . $cline); |
|
last; |
|
} |
|
elsif (defined($Texi2HTML::Config::def_map{$macro})) |
|
{ |
|
# @ may protect end of line in @def. We reconstruct lines here. |
|
# in the texinfo manual is said that spaces after @ collapse |
|
if ($cline =~ /(\@+)\s*$/) |
|
{ |
|
my $at_at_end_of_line = $1; |
|
if ((length($at_at_end_of_line) % 2) == 1) |
|
{ |
|
#print STDERR "Line continue $cline"; |
|
my $def_line = $cline; |
|
$def_line =~ s/\@\s*$//; |
|
chomp($def_line); |
|
$state->{'in_deff_line'} = "\@$macro" .$def_line; |
|
return; |
|
} |
|
} |
|
#We must enter the index entries |
|
my ($prefix, $entry, $argument) = get_deff_index($macro, $cline, $line_nr,1); |
|
# use deffn instead of deffnx for @-command record |
|
# associated with index entry |
|
my $idx_macro = $macro; |
|
$idx_macro =~ s/x$//; |
|
enter_index_entry($prefix, $line_nr, $entry, $idx_macro, $state) |
|
if ($prefix); |
|
$cline =~ s/(.*)//; |
|
add_prev($text, $stack, "\@$macro" . $1); |
|
} |
|
elsif ($macro =~ /^itemx?$/) |
|
{ |
|
enter_table_index_entry($text, $stack, $state, $line_nr); |
|
if ($state->{'table_stack'}->[-1] =~ /^(v|f)?table$/) |
|
{ |
|
$state->{'item'} = $macro; |
|
push @$stack, { 'format' => 'index_item', 'text' => '', 'command' => $macro }; |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, "\@$macro"); |
|
} |
|
} |
|
elsif ($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'list' or $macro eq 'multitable')) |
|
{ # We must enter the index entries of (v|f)table thus we track |
|
# in which table we are |
|
push @{$state->{'table_stack'}}, $macro; |
|
add_prev($text, $stack, "\@$macro"); |
|
} |
|
elsif ($cline =~ s/^{//) |
|
{ |
|
if ($macro eq 'verb') |
|
{ |
|
if ($cline =~ /^$/) |
|
{ |
|
# We already warned in pass texi |
|
} |
|
else |
|
{ |
|
$cline =~ s/^(.)//; |
|
$state->{'verb'} = $1; |
|
} |
|
} |
|
elsif ($macro eq 'footnote' and (Texi2HTML::Config::get_conf('footnotestyle') eq 'separate')) |
|
{ |
|
$state->{'footnote_heading_element'} = $state->{'heading_element'}; |
|
$state->{'footnote_place'} = $state->{'place'}; |
|
$state->{'heading_element'} = $footnote_element; |
|
$state->{'place'} = $footnote_element->{'place'}; |
|
} |
|
push (@$stack, { 'style' => $macro, 'text' => '' }); |
|
} |
|
else |
|
{ |
|
$cline = do_unknown (1, $macro, $cline, $text, $stack, $state, $line_nr); |
|
} |
|
next; |
|
} |
|
#elsif($cline =~ s/^([^{}@]*)\@(.)//o) |
|
elsif($cline =~ s/^([^{}@]*)\@([^\s\}\{\@]*)//o) |
|
{ |
|
add_prev($text, $stack, $1); |
|
$cline = do_unknown (1, $2, $cline, $text, $stack, $state, $line_nr); |
|
next; |
|
} |
|
elsif ($cline =~ s/^([^{}]*)([{}])//o) |
|
{ |
|
add_prev($text, $stack, $1); |
|
if ($2 eq '{') |
|
{ |
|
push @$stack, { 'style' => '', 'text' => '' }; |
|
} |
|
else |
|
{ |
|
if (@$stack) |
|
{ |
|
my $style = pop @$stack; |
|
my $result; |
|
add_prev ($text, $stack, |
|
close_structure_command($style, $state, 0, $line_nr)); |
|
next; |
|
} |
|
else |
|
{ |
|
# We warn in the last pass |
|
add_prev ($text, $stack, '}'); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, $cline); |
|
# in case of user mistake, with an @-command not closed on an @item line |
|
close_stack_structure($text, $stack, $state, $line_nr, 1) if ($state->{'item'}); |
|
enter_table_index_entry($text, $stack, $state, $line_nr); |
|
#print STDERR "END_LINE(s) $cline"; |
|
#dump_stack($text, $stack, $state); |
|
last; |
|
} |
|
} |
|
return 1; |
|
} # end scan_structure |
|
|
|
sub check_bad_end_argument ($$$) |
|
{ |
|
my $command = shift; |
|
my $line = shift; |
|
my $line_nr = shift; |
|
|
|
if ($line =~ /^(\S+)/) |
|
{ |
|
my $symbols = $1; |
|
line_error (sprintf(__("Bad argument `%s' to `\@%s', using `%s'"), "${command}${symbols}", 'end', $command), $line_nr); |
|
} |
|
} |
|
|
|
sub close_style_command($$$$$;$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $line = shift; |
|
# not the end of the style, but the paragraph the style is in is closed |
|
my $no_close = shift; |
|
|
|
my $style = pop @$stack; |
|
my $command = $style->{'style'}; |
|
my $result; |
|
if (!defined($command)) |
|
{ |
|
print STDERR "Bug: empty style in pass_text\n"; |
|
return ($result, $command); |
|
} |
|
if (ref($::style_map_ref->{$command}) eq 'HASH') |
|
{ |
|
push (@{$style->{'args'}}, $style->{'text'}); |
|
$style->{'fulltext'} .= $style->{'text'}; |
|
if (!defined($style->{'arg_nr'})) |
|
{ |
|
msg_debug("Bug: undefined 'arg_nr' for $command", $line_nr); |
|
} |
|
#print STDERR "DEBUG $command ($style->{'arg_nr'})\n"; |
|
#my $number = 0; |
|
#foreach my $arg(@{$style->{'args'}}) |
|
#{ |
|
# print STDERR " $number: $arg\n"; |
|
# $number++; |
|
#} |
|
#print STDERR "END DEBUG\n"; |
|
$style->{'text'} = $style->{'fulltext'}; |
|
$state->{'keep_texi'} = 0 if ( |
|
($::style_map_ref->{$command}->{'args'}->[$style->{'arg_nr'}] eq 'keep') |
|
and ($state->{'keep_nr'} == 1)); |
|
} |
|
if ($no_paragraph_macro{$command}) |
|
{ |
|
$state->{'no_paragraph'}--; |
|
pop @{$state->{'no_paragraph_stack'}}; |
|
} |
|
if ($::style_map_ref->{$command} and (defined($style_type{$command})) and ((!$no_close and ($style_type{$command} eq 'style')) or ($style_type{$command} eq 'accent'))) |
|
{ |
|
my $style_command = pop @{$state->{'command_stack'}}; |
|
if ($style_command ne $command) |
|
{ |
|
#line_warn ("Bug: $style_command on 'command_stack', not $command", $line_nr); |
|
# This can be a bug in case of bad nesting, see bad_style_nesting.texi |
|
line_warn("Bad nesting of \@$style_command and \@$command", $line_nr); |
|
push @{$state->{'command_stack'}}, $style_command; |
|
############################ debug |
|
if ($T2H_DEBUG) |
|
{ |
|
push @$stack, $style; |
|
print STDERR "Stacks before pop top:\n"; |
|
dump_stack($text, $stack, $state); |
|
pop @$stack; |
|
############################ end debug |
|
} |
|
} |
|
} |
|
if ($state->{'keep_texi'}) |
|
{ # don't expand @-commands in anchor, refs... |
|
close_arg ($command, $style->{'arg_nr'}, $state); |
|
$result = '@' . $command . '{' . $style->{'text'} . '}'; |
|
} |
|
elsif ($::things_map_ref->{$command}) |
|
{ |
|
$result = do_thing_command ($command, $style->{'text'}, $state, $line_nr); |
|
} |
|
else |
|
{ |
|
$result = do_style_command($command, $style->{'text'}, $state, $style->{'args'}, $line_nr, $style->{'no_open'}, $no_close, $style->{'keep_line_nr'}); |
|
if ($state->{'code_style'} < 0) |
|
{ |
|
msg_debug ("Bug: negative code_style: $state->{'code_style'}, line:$line", $line_nr); |
|
} |
|
if ($state->{'math_style'} < 0) |
|
{ |
|
msg_debug ("Bug: negative math_style: $state->{'math_style'}, line:$line", $line_nr); |
|
} |
|
} |
|
return ($result, $command); |
|
} |
|
|
|
sub top_stack_is_menu($) |
|
{ |
|
my $stack = shift; |
|
my $top_stack = top_stack($stack, 1); |
|
return 0 if (!$format_type{$top_stack->{'format'}} or $format_type{$top_stack->{'format'}} ne 'menu'); |
|
return 1; |
|
} |
|
|
|
|
|
sub scan_line($$$$;$) |
|
{ |
|
my $original_line = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
die "stack not an array ref" unless (ref($stack) eq "ARRAY"); |
|
my $cline = $original_line; |
|
#msg_debug("SCAN_LINE (@{$state->{'command_stack'}}): $original_line", $line_nr); |
|
#dump_stack($text, $stack, $state); |
|
my $new_menu_entry; # true if there is a new menu entry |
|
# my $menu_description_in_format; # true if we are in a menu description |
|
# # but in another format section (@table....) |
|
|
|
# this can happen currently with quotations |
|
if (defined($state->{'prepend_text'})) |
|
{ |
|
$cline = $state->{'prepend_text'} . $cline; |
|
$state->{'prepend_text'} = undef; |
|
delete $state->{'prepend_text'}; |
|
} |
|
|
|
if (!$state->{'raw'} and !$state->{'verb'} and ($state->{'menu'} or $state->{'direntry'})) |
|
{ # new menu entry |
|
my ($node, $name, $ending, $remaining) = parse_menu_entry($cline); |
|
if (defined($node)) |
|
{ |
|
$cline = $remaining; |
|
print STDERR "# Potential menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU); |
|
$new_menu_entry = 1; |
|
my $menu_entry = { 'name' => $name, 'node' => $node, 'ending' => $ending }; |
|
# in SIMPLE_MENU case we don't begin a description, description is |
|
# just some normal (preformatted) text |
|
if ($Texi2HTML::Config::SIMPLE_MENU) |
|
{ |
|
add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry)); |
|
#dump_stack($text, $stack, $state); |
|
} |
|
else |
|
{ |
|
# close description and comment, if they are opened. |
|
#dump_stack($text, $stack, $state); |
|
if (!close_menu_comment($text, $stack, $state, __("new menu entry"), $line_nr) |
|
and !close_menu_description($text, $stack, $state, __("new menu entry"), $line_nr) |
|
and $state->{'preformatted'}) |
|
{ |
|
close_paragraph($text, $stack, $state, __("new menu entry"), $line_nr); |
|
} |
|
print STDERR "# New menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU); |
|
#dump_stack($text, $stack, $state); |
|
my $fusionned_description = 0; |
|
# fusionned looks better in preformatted. But some formats |
|
# want to always distinguish link and description |
|
if ($Texi2HTML::Config::SEPARATE_DESCRIPTION or !$state->{'preformatted'}) |
|
{ |
|
add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry)); |
|
} |
|
else |
|
{ |
|
$fusionned_description = 1; |
|
} |
|
push @$stack, {'format' => 'menu_description', 'text' => '', 'menu_entry' => $menu_entry, 'fusionned_description' => $fusionned_description}; |
|
$state->{'code_style'}++ if ($Texi2HTML::Config::format_code_style{'menu_description'}); |
|
if ($fusionned_description) |
|
{ |
|
begin_paragraph($stack, $state) if $state->{'preformatted'}; |
|
add_prev ($text, $stack, do_menu_link($state, $line_nr, $menu_entry)); |
|
} |
|
} |
|
} |
|
# we may be in a menu entry description, we close it |
|
# if there is an empty line, so the last arg is $cline. |
|
# also if right in menu we always open a menu_comment, it |
|
# means that there was no menu entry seen since the menu beginning. |
|
if (!$new_menu_entry and (close_menu_description($text, $stack, $state, "end menu description", $line_nr, $cline) or ($stack->[-1]->{'format'} and $format_type{$stack->[-1]->{'format'}} and $format_type{$stack->[-1]->{'format'}} eq 'menu'))) |
|
{ |
|
if ($state->{'preformatted'}) |
|
{ |
|
begin_paragraph($stack, $state); |
|
} |
|
else |
|
{ |
|
# only start a menu_comment if right in menu and not in |
|
# a format below a menu because if not right |
|
# in a menu we have no way to distinguish a menu_comment |
|
# and some normal text in the format. |
|
# also it is not started in preformatted environment |
|
begin_format($text, $stack, $state, 'menu_comment', $cline, $line_nr) if ($stack->[-1]->{'format'} and $format_type{$stack->[-1]->{'format'}} and $format_type{$stack->[-1]->{'format'}} eq 'menu'); |
|
} |
|
} |
|
} |
|
|
|
unless ($state->{'raw'} or $state->{'verb'} or $state->{'keep_texi'}) |
|
{ |
|
# first the line commands are taken into account |
|
my $next_command = next_tag($cline); |
|
if (defined($next_command) and defined($Texi2HTML::Config::line_command_map{$next_command})) |
|
{ |
|
close_paragraph($text, $stack, $state, "\@$next_command", $line_nr, 1) if (stop_paragraph_command($next_command)); |
|
my $arg_texi = $cline; |
|
$arg_texi =~ s/^\s*\@$next_command\s*//; |
|
$arg_texi = trim_comment_spaces ($arg_texi, "\@$next_command", $line_nr); |
|
my $arg_line = substitute_line($arg_texi, "\@$next_command", duplicate_formatting_state($state)); |
|
add_prev ($text, $stack, &$Texi2HTML::Config::line_command($next_command, $arg_line, $arg_texi, $state)); |
|
enter_author_command ($next_command, $arg_texi, $arg_line, $stack, $state, $line_nr); |
|
return ''; |
|
} |
|
elsif (defined($next_command) and ($next_command eq 'contents') or ($next_command eq 'summarycontents') or ($next_command eq 'shortcontents')) |
|
{ |
|
my $element_tag = $next_command; |
|
$element_tag = 'shortcontents' if ($element_tag ne 'contents'); |
|
# at that point the content_element is defined for sure since |
|
# we already saw the tag |
|
if ($Texi2HTML::Config::INLINE_CONTENTS and !Texi2HTML::Config::get_conf('set' . $element_tag . 'aftertitlepage')) |
|
{ |
|
my $content_element = shift (@{$all_content_elements{$element_tag}}); |
|
my $toc_lines = &$Texi2HTML::Config::inline_contents($Texi2HTML::THISDOC{'FH'}, $element_tag, $content_element, \@sections_list); |
|
add_prev ($text, $stack, join('',@$toc_lines)) if (defined($toc_lines)); |
|
} |
|
return '' unless (exists($Texi2HTML::Config::misc_command{$next_command}) and $Texi2HTML::Config::misc_command{$next_command}->{'keep'}); |
|
} |
|
|
|
# The commands to ignore are ignored now in case after ignoring them |
|
# there is an empty line, to be able to stop the paragraph |
|
#my $leading_spaces = ''; |
|
|
|
while (1) |
|
{ |
|
my $next_tag = next_tag($cline); |
|
close_paragraph($text, $stack, $state, "\@$next_tag", $line_nr, 1) if (stop_paragraph_command($next_tag)); |
|
if (defined($next_tag) and defined($Texi2HTML::Config::misc_command{$next_tag}) and !$Texi2HTML::Config::misc_command{$next_tag}->{'keep'}) |
|
{ |
|
$cline =~ s/^(\s*)\@$next_tag//; |
|
#$leading_spaces .= $1; |
|
add_prev ($text, $stack, do_text($1, $state)); |
|
my $result; |
|
($cline, $result) = misc_command_text($cline, $next_tag, $stack, $state, $text, $line_nr); |
|
add_prev($text, $stack, $result) if (defined($result)); |
|
} |
|
else |
|
{ |
|
last; |
|
} |
|
} |
|
#add_prev ($text, $stack, $leading_spaces); |
|
return '' if (!defined($cline) or $cline eq ''); |
|
} |
|
my $top_stack = top_stack($stack); |
|
if (($top_stack->{'format'} and $top_stack->{'format'} eq 'menu_description') or $state->{'raw'} or $state->{'preformatted'} or $state->{'no_paragraph'} or $state->{'keep_texi'} or $state->{'remove_texi'}) |
|
{ # empty lines are left unmodified in these contexts. |
|
# it is also possible to be in preformatted within a menu_description |
|
if ($cline =~ /^\s*$/) |
|
{ |
|
if ($state->{'raw'}) |
|
{ |
|
print STDERR "#within raw $state->{'raw'}(empty line):$cline" if ($T2H_DEBUG & $DEBUG_FORMATS); |
|
add_prev($text, $stack, $cline); |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, do_text($cline,$state)); |
|
} |
|
return; |
|
} |
|
} |
|
else |
|
{ |
|
if ($cline =~ /^\s*$/) |
|
{ |
|
if ($state->{'paragraph_context'}) |
|
{ # An empty line ends a paragraph |
|
close_paragraph($text, $stack, $state, __("paragraph end"), $line_nr); |
|
} |
|
add_prev($text, $stack, &$Texi2HTML::Config::empty_line($cline,$state)); |
|
return 1; |
|
} |
|
else |
|
{ |
|
if (!no_paragraph($state,$cline)) |
|
{ # open a paragraph, unless the line begins with a macro that |
|
# shouldn't trigger a paragraph opening |
|
begin_paragraph($stack, $state); |
|
} |
|
} |
|
} |
|
# we flag specially deff_item and table line that contain only |
|
# inter_item_command, which typically is be @c, @comment, @*index, such |
|
# that the formatter can treat those specifically. |
|
my $top_format = top_stack($stack,2); |
|
if ($top_format->{'only_inter_commands'} and !$state->{'keep_texi'}) |
|
{ |
|
my $real_format = $top_format->{'format_ref'}->{'format'}; |
|
my $next_tag = next_tag($cline); |
|
$next_tag = '' if (!defined($next_tag)); |
|
my $next_end_tag = next_end_tag($cline); |
|
$next_end_tag = '' if (!defined($next_end_tag)); |
|
#msg_debug("$top_format->{'format'} $next_tag, end $next_end_tag :::$cline"); |
|
delete $top_format->{'only_inter_commands'} unless |
|
( |
|
$Texi2HTML::Config::inter_item_commands{$next_tag} or |
|
(index_command_prefix($next_tag) ne '' and $Texi2HTML::Config::inter_item_commands{'cindex'}) or |
|
($top_format->{'format'} eq 'deff_item' and "${real_format}x" eq $next_tag) or |
|
($top_format->{'format'} ne 'deff_item' and $next_tag =~ /^itemx?$/) or |
|
( $next_end_tag eq $real_format ) |
|
); |
|
#print STDERR "STILL $top_format->{'only_inter_commands'}\n" if ($top_format->{'only_inter_commands'}); |
|
} |
|
|
|
while(1) |
|
{ |
|
# scan_line |
|
#print STDERR "WHILE(l): $cline|"; |
|
#msg_debug("Dump stack in scan_line", $line_nr); |
|
#dump_stack($text, $stack, $state); |
|
# we're in a raw format (html, tex if !L2H, verbatim) |
|
if (defined($state->{'raw'})) |
|
{ |
|
(dump_stack($text, $stack, $state), die "Bug for raw ($state->{'raw'})") if (! @$stack or ! ($stack->[-1]->{'style'} eq $state->{'raw'})); |
|
if ($state->{'raw'} eq 'macro') |
|
{ |
|
if ($cline =~ /^\s*\@macro\s+(\w[\w-]*)\s*(.*)/) |
|
{ |
|
$state->{$state->{'raw'}}++; |
|
} |
|
} |
|
# macro_regexp |
|
if ($cline =~ /^(.*?)\@end\s([a-zA-Z][\w-]*)/o and ($2 eq $state->{'raw'})) |
|
# don't protect html, it is done by Texi2HTML::Config::raw if needed |
|
{ |
|
$cline =~ s/^(.*?)(\@end\s$state->{'raw'})//; |
|
my $remaining = $1; |
|
my $end_text = $2; |
|
if ($state->{'raw'} eq 'macro') |
|
{ |
|
$state->{$state->{'raw'}}--; |
|
if ($state->{$state->{'raw'}}) |
|
{ |
|
add_prev ($text, $stack, $remaining.$end_text); |
|
last; |
|
} |
|
} |
|
check_bad_end_argument ($state->{'raw'}, $cline, $line_nr); |
|
add_prev ($text, $stack, $remaining); |
|
my $style = pop @$stack; |
|
if ($style->{'text'} !~ /^\s*$/) |
|
{ |
|
if ($state->{'keep_texi'}) |
|
{ |
|
add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}"); |
|
} |
|
elsif ($state->{'remove_texi'}) |
|
{ |
|
add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi($style->{'style'}, $style->{'text'})); |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::raw($style->{'style'}, $style->{'text'}, $line_nr)); |
|
} |
|
} |
|
if (!$state->{'keep_texi'} and !$state->{'remove_texi'}) |
|
{ |
|
# reopen preformatted if it was interrupted by the raw format |
|
# if raw format is html the preformatted wasn't interrupted |
|
begin_paragraph($stack, $state) if ($state->{'preformatted'} and (!$Texi2HTML::Config::format_in_paragraph{$state->{'raw'}})); |
|
delete $state->{'raw'}; |
|
return if ($cline =~ /^\s*$/); |
|
} |
|
delete $state->{'raw'}; |
|
return if (($cline =~ /^\s*$/) and $state->{'remove_texi'}); |
|
next; |
|
} |
|
else |
|
{ |
|
print STDERR "#within raw $state->{'raw'}:$cline" if ($T2H_DEBUG & $DEBUG_FORMATS); |
|
add_prev ($text, $stack, $cline); |
|
last; |
|
} |
|
} |
|
|
|
# we are within a @verb |
|
if (defined($state->{'verb'})) |
|
{ |
|
my $char = quotemeta($state->{'verb'}); |
|
if ($cline =~ s/^(.*?)$char\}/\}/) |
|
{ |
|
if ($state->{'keep_texi'}) |
|
{ |
|
add_prev($text, $stack, $1 . $state->{'verb'}); |
|
$stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, do_text($1, $state)); |
|
} |
|
delete $state->{'verb'}; |
|
next; |
|
} |
|
else |
|
{ |
|
add_prev($text, $stack, $cline); |
|
last; |
|
} |
|
} |
|
|
|
# We handle now the end tags |
|
# macro_regexp |
|
if ($cline =~ s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//) |
|
{ |
|
my $end_tag = $2; |
|
my $prev_text = $1; |
|
if ($state->{'keep_texi'}) |
|
{ |
|
add_prev($text, $stack, $prev_text . "\@end $end_tag"); |
|
next; |
|
} |
|
elsif ($state->{'remove_texi'}) |
|
{ |
|
add_prev($text, $stack, $prev_text); |
|
next; |
|
} |
|
|
|
add_prev($text, $stack, do_text($prev_text, $state)); |
|
#print STDERR "END_MACRO $end_tag\n"; |
|
#dump_stack ($text, $stack, $state); |
|
|
|
# First we test if the stack is not empty. |
|
# Then we test if the end tag is a format tag. |
|
# We then close paragraphs and preformatted at top of the stack. |
|
# We handle the end tag (even when it was not the tag which appears |
|
# on the top of the stack; in that case we close anything |
|
# until that element) |
|
my $top_stack = top_stack($stack); |
|
if (!$top_stack) |
|
{ |
|
line_error (sprintf(__("Unmatched `%c%s'"), ord('@'), 'end'), $line_nr); |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
next; |
|
} |
|
|
|
if (!$format_type{$end_tag}) |
|
{ |
|
line_warn ("Unknown \@end $end_tag", $line_nr); |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
next; |
|
} |
|
check_bad_end_argument ($end_tag, $cline, $line_nr); |
|
if (!close_menu_description($text, $stack, $state, "\@end $end_tag", $line_nr)) |
|
{ |
|
close_paragraph($text, $stack, $state, "\@end $end_tag", $line_nr); |
|
} |
|
|
|
$top_stack = top_stack($stack); |
|
if (!$top_stack or (!defined($top_stack->{'format'}))) |
|
{ |
|
line_error (sprintf(__("Unmatched `%c%s'"), ord('@'), 'end'), $line_nr); |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
dump_stack ($text, $stack, $state) if ($T2H_DEBUG); |
|
next; |
|
} |
|
# Warn if the format on top of stack is not compatible with the |
|
# end tag, and find the end tag. |
|
unless ( |
|
($top_stack->{'format'} eq $end_tag) |
|
or |
|
( |
|
$format_type{$end_tag} eq 'menu' and |
|
$top_stack->{'format'} eq 'menu_comment' |
|
) or |
|
( |
|
$end_tag eq 'multitable' and $top_stack->{'format'} eq 'cell' |
|
) or |
|
( |
|
$format_type{$end_tag} eq 'list' and $top_stack->{'format'} eq 'item' |
|
) or |
|
( |
|
$format_type{$end_tag} eq 'table' |
|
and |
|
($top_stack->{'format'} eq 'term' or $top_stack->{'format'} eq 'line') |
|
) or |
|
( |
|
defined($Texi2HTML::Config::def_map{$end_tag}) and |
|
$top_stack->{'format'} eq 'deff_item' |
|
) |
|
) |
|
{ |
|
# this is not the right format. We try to close other |
|
# formats to find the format we are searching for. |
|
# First we close paragraphs, as with a wrong $end_format |
|
# they may not be closed properly. |
|
|
|
#print STDERR " MISMATCH got $top_stack->{'format'} waited \@end $end_tag($top_stack->{'format'})\n"; |
|
#dump_stack ($text, $stack, $state); |
|
close_paragraph($text, $stack, $state, "\@end $end_tag", $line_nr); |
|
$top_stack = top_stack($stack); |
|
if (!$top_stack or (!defined($top_stack->{'format'}))) |
|
{ |
|
line_error (sprintf(__("Unmatched `%c%s'"), ord('@'), 'end'), $line_nr); |
|
add_prev($text, $stack, "\@end $end_tag"); |
|
# at that point the dump_stack is not very useful, since |
|
# close_paragraph above may hide interesting info |
|
dump_stack ($text, $stack, $state) if ($T2H_DEBUG); |
|
next; |
|
} |
|
my $waited_format = $top_stack->{'format'}; |
|
$waited_format = $fake_format{$top_stack->{'format'}} if ($format_type{$top_stack->{'format'}} eq 'fake'); |
|
if ($end_tag ne $waited_format) |
|
{ |
|
line_error (sprintf(__("`\@end' expected `%s', but saw `%s'"), $waited_format, $end_tag), $line_nr); |
|
} |
|
else |
|
{ |
|
msg_debug ("\@end is $end_tag, was waiting for $top_stack->{'format'}", $line_nr); |
|
dump_stack ($text, $stack, $state); |
|
} |
|
close_stack($text, $stack, $state, $line_nr, $end_tag); |
|
# FIXME this is too complex |
|
# an empty preformatted may appear when closing things as |
|
# when closed, formats reopen the preformatted environment |
|
# in case there is some text following, but we know it isn't |
|
# the case here, thus we can close paragraphs. |
|
close_paragraph($text, $stack, $state, "\@end $end_tag"); |
|
my $new_top_stack = top_stack($stack); |
|
next unless ($new_top_stack and defined($new_top_stack->{'format'}) and (($new_top_stack->{'format'} eq $end_tag) |
|
or (($format_type{$new_top_stack->{'format'}} eq 'fake') and ($fake_format{$new_top_stack->{'format'}} eq $format_type{$end_tag})))); |
|
} |
|
# We should now be able to handle the format |
|
if (defined($format_type{$end_tag})) |
|
{# remove the space or new line following the @end command |
|
$cline =~ s/\s//; |
|
if (end_format($text, $stack, $state, $end_tag, $line_nr)) |
|
{ # if end_format is false, paragraph is already begun |
|
begin_paragraph_after_command($state,$stack,$end_tag,$cline); |
|
} |
|
} |
|
next; |
|
} |
|
# This is a macro |
|
#elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o) |
|
# macro_regexp |
|
elsif ($cline =~ s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/\\])//o or $cline =~ s/^([^{}@,]*)\@([a-zA-Z][\w-]*)//o) |
|
{ |
|
my $before_macro = $1; |
|
my $macro = $2; |
|
$macro = $alias{$macro} if (exists($alias{$macro})); |
|
my $punct; |
|
if (!$state->{'keep_texi'} and $macro eq ':' and $before_macro =~ /(.)$/ and $Texi2HTML::Config::colon_command_punctuation_characters{$1}) |
|
{ |
|
$before_macro =~ s/(.)$//; |
|
$punct = $1; |
|
} |
|
add_prev($text, $stack, do_text($before_macro, $state)); |
|
add_prev($text, $stack, &$Texi2HTML::Config::colon_command($punct)) if (defined($punct)); |
|
#print STDERR "MACRO $macro\n"; |
|
#print STDERR "LINE $cline"; |
|
#dump_stack ($text, $stack, $state); |
|
|
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr, 1) if (stop_paragraph_command($macro) and !$state->{'keep_texi'}); |
|
|
|
if ($macro eq 'listoffloats' or $macro eq 'printindex') |
|
{ |
|
if ($state->{'keep_texi'}) |
|
{ |
|
if ($cline =~ s/(.*)//o) |
|
{ |
|
add_prev($text, $stack, "\@$macro" . $1); |
|
} |
|
next; |
|
} |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
return undef if ($state->{'remove_texi'}); |
|
if ($macro eq 'listoffloats') |
|
{ |
|
# remove possible comments |
|
my $arg = normalise_texi_space(trim_comment_spaces ($cline, "\@$macro", $line_nr)); |
|
|
|
my $style_id = cross_manual_line($arg); |
|
my $style = substitute_line (&$Texi2HTML::Config::listoffloats_style($arg), __("\@listoffloats type"), undef, $line_nr); |
|
my $style_no_texi = remove_texi (&$Texi2HTML::Config::listoffloats_style($arg)); |
|
if (exists ($floats{$style_id})) |
|
{ |
|
my @listoffloats_entries = (); |
|
foreach my $float (@{$floats{$style_id}->{'floats'}}) |
|
{ |
|
my $float_style = substitute_line(&$Texi2HTML::Config::listoffloats_float_style($arg, $float), __("\@listoffloats \@float type")); |
|
my ($caption_lines, $caption_or_shortcaption) = &$Texi2HTML::Config::listoffloats_caption($float); |
|
# we set 'multiple_pass', and 'expansion' |
|
# such that index entries |
|
# and anchors are not handled one more time; |
|
# the caption has already been formatted, |
|
# and these have been handled at the right place |
|
# FIXME footnotes? |
|
my $caption = ''; |
|
$caption = substitute_text(prepare_state_multiple_pass($macro, $state), undef, "\@$caption_or_shortcaption in listoffloats", @$caption_lines) if (defined($caption_or_shortcaption)); |
|
push @listoffloats_entries, &$Texi2HTML::Config::listoffloats_entry($arg, $float, $float_style, $caption, href($float, $state->{'element'}->{'file'}, $line_nr)); |
|
} |
|
add_prev($text, $stack, &$Texi2HTML::Config::listoffloats($arg, $style, \@listoffloats_entries)); |
|
} |
|
else |
|
{ |
|
line_warn (sprintf(__("Requested float type `%s' not previously used"), $arg), $line_nr); |
|
} |
|
} |
|
elsif ($macro eq 'printindex' and $cline =~ s/\s+(\w+)\s*//) |
|
{ |
|
my $index_name = $1; |
|
my $region = $state->{'region'}; |
|
$region = 'document' if (!defined($region)); |
|
|
|
if (!defined($Texi2HTML::THISDOC{'indices'}->{$region})) |
|
{ |
|
msg_debug ("\@printindex $index_name THISDOC{'indices'}->{$region} not defined", $line_nr); |
|
} |
|
elsif (!defined($Texi2HTML::THISDOC{'indices'}->{$region}->{$index_name})) |
|
{ |
|
msg_debug ("\@printindex $index_name THISDOC{'indices'}->{$region}->{$index_name} not defined", $line_nr); |
|
} |
|
|
|
if (!defined($Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name})) |
|
{ |
|
$Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name} = -1; |
|
} |
|
$Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name}++; |
|
my $printindex = $Texi2HTML::THISDOC{'indices'}->{$region}->{$index_name}->[$Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name}]; |
|
if (!defined($printindex)) |
|
{ |
|
# this printindex hasn't been seen in the previous pass. |
|
# rint STDERR "Index $index_name not in sync, number $Texi2HTML::THISDOC{'indices_numbers'}->{$index_name} not defined\n"; |
|
line_warn("\@printindex $index_name expanded more than once may lead to wrong references", $line_nr); |
|
$printindex = $Texi2HTML::THISDOC{'indices'}->{$region}->{$index_name}->[-1]; |
|
} |
|
elsif ($printindex->{'name'} ne $index_name) |
|
{ |
|
print STDERR "BUG: THISDOC{'indices'} $printindex->{'name'} ne $index_name\n"; |
|
} |
|
#print STDERR "PRINTINDEX use($printindex) region $region, name $index_name number $Texi2HTML::THISDOC{'indices_numbers'}->{$region}->{$index_name}\n"; |
|
add_prev($text, $stack, &$Texi2HTML::Config::printindex($index_name, $printindex)); |
|
} |
|
else |
|
{ |
|
$cline =~ s/^\s*//; |
|
chomp ($cline); |
|
line_error (sprintf(__("Bad argument to \@%s: %s"), $macro, $cline), $line_nr); |
|
} |
|
begin_paragraph ($stack, $state) if ($state->{'preformatted'}); |
|
return undef; |
|
} |
|
if (defined($Texi2HTML::Config::misc_command{$macro})) |
|
{ |
|
# Handle the misc command |
|
my $result; |
|
($cline, $result) = misc_command_text($cline, $macro, $stack, $state, $text, $line_nr); |
|
add_prev($text, $stack, $result) if (defined($result)); |
|
return unless (defined($cline)); |
|
unless ($Texi2HTML::Config::misc_command{$macro}->{'keep'}) |
|
{ |
|
begin_paragraph($stack, $state) if |
|
(!no_paragraph($state,$cline)); |
|
next; |
|
} |
|
} |
|
# This is a @macroname{...} construct. We add it on top of stack |
|
# It will be handled when we encounter the '}' |
|
# There is a special case for def macros as @deffn{def} is licit |
|
if (!$Texi2HTML::Config::def_map{$macro} and $cline =~ s/^{//) #} |
|
{ |
|
if ($macro eq 'verb') |
|
{ |
|
if ($cline =~ /^$/) |
|
{ |
|
# Allready warned |
|
} |
|
else |
|
{ |
|
$cline =~ s/^(.)//; |
|
$state->{'verb'} = $1; |
|
} |
|
} |
|
# currently if remove_texi and anchor/ref/footnote |
|
# the text within the command is ignored |
|
# see t2h_remove_command in texi2html.init |
|
my $new_command_ref = { 'style' => $macro, 'text' => '', 'arg_nr' => 0, 'line_nr' => $line_nr }; |
|
push (@$stack, $new_command_ref); |
|
if ($no_paragraph_macro{$macro}) |
|
{ |
|
$state->{'no_paragraph'}++; |
|
push @{$state->{'no_paragraph_stack'}}, "\@$macro"; |
|
} |
|
open_arg($macro, 0, $state); |
|
if ($state->{'keep_texi'}) |
|
{ |
|
$new_command_ref->{'keep_line_nr'} = [ $line_nr ]; |
|
} |
|
my $real_style_command = 0; |
|
if (defined($style_type{$macro}) and (($style_type{$macro} eq 'style') or ($style_type{$macro} eq 'accent'))) |
|
{ |
|
push (@{$state->{'command_stack'}}, $macro); |
|
$real_style_command = 1; |
|
#print STDERR "# Stacked $macro (@{$state->{'command_stack'}})\n" if ($T2H_DEBUG); |
|
} |
|
# FIXME give line, and modify line? |
|
&$Texi2HTML::Config::begin_style_texi($macro, $state, $stack, $real_style_command, $state->{'remove_texi'}) |
|
if (defined($Texi2HTML::Config::begin_style_texi) |
|
and !($state->{'keep_texi'})); |
|
next; |
|
} |
|
|
|
# special case if we are checking itemize line. In that case |
|
# we want to make sure that there is no @item on the @itemize |
|
# line, otherwise it will be added on the front of another @item, |
|
# leading to an infinite loop... |
|
|
|
if ($state->{'check_item'} and ($macro =~ /^itemx?$/ or $macro eq 'headitem')) |
|
{ |
|
line_error(sprintf(__("\@%s not allowed in argument to \@%s"), $macro, $state->{'check_item'}), $line_nr); |
|
next; |
|
} |
|
|
|
# if we're keeping texi unmodified we can do it now |
|
if ($state->{'keep_texi'}) |
|
{ |
|
# We treat specially formats accepting {} on command line |
|
if ($macro eq 'multitable' or defined($Texi2HTML::Config::def_map{$macro}) or defined($sec2level{$macro}) or $macro eq 'macro') |
|
{ |
|
add_prev($text, $stack, "\@$macro" . $cline); |
|
$cline = ''; |
|
next; |
|
} |
|
|
|
add_prev($text, $stack, "\@$macro"); |
|
if ($Texi2HTML::Config::texi_formats_map{$macro} and $Texi2HTML::Config::texi_formats_map{$macro} eq 'raw') |
|
{ |
|
$state->{'raw'} = $macro; |
|
$state->{$macro}++ if ($macro eq 'macro'); |
|
push (@$stack, {'style' => $macro, 'text' => ''}); |
|
} |
|
next; |
|
} |
|
|
|
# If we are removing texi, the following macros are not removed |
|
# as is but modified. So they are collected first, as if we were |
|
# in normal text |
|
|
|
# a raw macro beginning |
|
if ($Texi2HTML::Config::texi_formats_map{$macro} and $Texi2HTML::Config::texi_formats_map{$macro} eq 'raw') |
|
{ |
|
if (!$Texi2HTML::Config::format_in_paragraph{$macro}) |
|
{ # close paragraph before verbatim (and tex if !L2H) |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
} |
|
$state->{'raw'} = $macro; |
|
push (@$stack, {'style' => $macro, 'text' => ''}); |
|
$state->{$macro}++ if ($macro eq 'macro'); |
|
return if ($cline =~ /^\s*$/ or ($macro eq 'macro')); |
|
next; |
|
} |
|
my $simple_macro = 1; |
|
# An accent macro |
|
if (exists($Texi2HTML::Config::accent_map{$macro})) |
|
{ |
|
# the command itself is not in the command stack, since with |
|
# braces, it is already popped when do_simple is called |
|
#push (@{$state->{'command_stack'}}, $macro); |
|
if ($macro =~ /^[a-zA-Z]/) |
|
{ |
|
$cline =~ s/^\s*//; |
|
} |
|
elsif ($cline =~ /^\s/) |
|
{ |
|
line_warn (sprintf(__("Accent command `\@%s' must not be followed by whitespace"), $macro), $line_nr); |
|
} |
|
if ($cline =~ /^\@/) |
|
{ |
|
line_error (sprintf(__("Use braces to give a command as an argument to \@%s"), $macro), $line_nr); |
|
} |
|
if ($cline =~ s/^(\S)//o) |
|
{ |
|
add_prev($text, $stack, do_style_command($macro, $1, $state, [ $1 ], $line_nr, undef, undef, undef)); |
|
} |
|
else |
|
{ # The accent is at end of line |
|
# FIXME warn? And test case? Maybe this is catched |
|
# above, by "Accent command `@%s' must not be followed by whitespace" |
|
# for commands with letter. |
|
add_prev($text, $stack, do_text($macro, $state)); |
|
} |
|
#pop @{$state->{'command_stack'}}; |
|
} |
|
# an @-command which should be like @command{}. We handle it... |
|
elsif ($::things_map_ref->{$macro}) |
|
{ |
|
line_error (sprintf(__("\@%s expected braces"), $macro), $line_nr); |
|
add_prev($text, $stack, do_thing_command($macro, '', $state, $line_nr)); |
|
} |
|
# an @-command like @command |
|
elsif (defined($::simple_map_ref->{$macro}) or ($state->{'math_style'} and defined($::simple_map_math_ref->{$macro}))) |
|
{ |
|
add_prev($text, $stack, do_simple_command($macro, $state, $line_nr)); |
|
} |
|
else |
|
{ |
|
$simple_macro = 0; |
|
} |
|
if ($simple_macro) |
|
{# if the macro didn't triggered a paragraph start it might now |
|
begin_paragraph($stack, $state) if |
|
($Texi2HTML::Config::no_paragraph_commands{$macro} and !no_paragraph($state,$cline)); |
|
next; |
|
} |
|
# the following macros are modified or ignored if we are |
|
# removing texi, and they are not handled like macros in normal text |
|
if ($state->{'remove_texi'}) |
|
{ |
|
# handle specially some macros |
|
if ((index_command_prefix($macro) ne '') or |
|
($macro eq 'itemize') or |
|
($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'quotation')) |
|
or ($macro eq 'multitable')) |
|
{ |
|
return; |
|
} |
|
elsif ($macro eq 'enumerate') |
|
{ |
|
my $spec; |
|
($cline, $spec) = parse_enumerate ($cline); |
|
return if ($cline =~ /^\s*$/); |
|
next; |
|
} |
|
elsif (defined($Texi2HTML::Config::def_map{$macro})) |
|
{ |
|
my ($command, $style, $category, $name, $type, $class, $arguments, $args_array); |
|
($command, $style, $category, $name, $type, $class, $arguments, $args_array) = parse_def($macro, $cline, $line_nr); |
|
# FIXME -- --- ''... lead to simple text in texi2html |
|
# while they are kept as is in html coments by makeinfo |
|
$category = remove_texi($category) if (defined($category)); |
|
$name = remove_texi($name) if (defined($name)); |
|
$type = remove_texi($type) if (defined($type)); |
|
$class = remove_texi($class) if (defined($class)); |
|
$arguments = remove_texi($arguments) if (defined($arguments)); |
|
chomp($arguments); |
|
add_prev($text, $stack, &$Texi2HTML::Config::def_line_no_texi($category, $name, $type, $arguments)); |
|
return; |
|
} |
|
elsif (defined($sec2level{$macro})) |
|
{ #FIXME there is certainly more intelligent stuff to do |
|
my $num; |
|
if ($state->{'region'}) |
|
{ |
|
$state->{'head_num'}++; |
|
$num = "$state->{'region'}_$state->{'head_num'}"; |
|
} |
|
else |
|
{ |
|
$num = $global_head_num; |
|
} |
|
my $heading_element = $headings{$num}; |
|
$cline = trim_comment_spaces ($cline, "\@$macro"); |
|
add_prev($text, $stack, &$Texi2HTML::Config::heading_no_texi($heading_element, $macro, $cline)); |
|
return; |
|
} |
|
|
|
# ignore other macros |
|
next; |
|
} |
|
|
|
# handle the other macros, we are in the context of normal text |
|
if (defined($sec2level{$macro})) |
|
{ |
|
#dump_stack($text, $stack, $state); |
|
my $num; |
|
if ($state->{'region'}) |
|
{ |
|
$state->{'head_num'}++; |
|
$num = "$state->{'region'}_$state->{'head_num'}"; |
|
} |
|
else |
|
{ |
|
$global_head_num++; |
|
$num = $global_head_num; |
|
} |
|
my $heading_element = $headings{$num}; |
|
$cline = trim_comment_spaces($cline, "\@$macro", $line_nr); |
|
add_prev($text, $stack, &$Texi2HTML::Config::element_label($heading_element->{'id'}, $heading_element, $macro, $cline)); |
|
add_prev($text, $stack, &$Texi2HTML::Config::heading($heading_element, $macro, $cline, substitute_line($cline, "\@$macro"), $state->{'preformatted'})); |
|
return; |
|
} |
|
|
|
if (index_command_prefix($macro) ne '') |
|
{ |
|
my $index_name = index_command_prefix($macro); |
|
my $entry_texi = trim_comment_spaces($cline, "\@$macro", $line_nr); |
|
chomp($entry_texi); |
|
# multiple_pass is not really necessary, since it may be the place |
|
# where it is expanded once. However, this ensures that things |
|
# that are ignored with multiple_pass are ignored. |
|
my $entry_text = substitute_line($entry_texi, "\@$macro", prepare_state_multiple_pass($macro, $state)); |
|
my ($index_entry, $formatted_index_entry, $index_label) = do_index_entry_label($macro,$state,$line_nr, $entry_texi); |
|
|
|
if (defined($index_entry)) |
|
{ |
|
msg_debug ("(bug?) Index out of sync `$index_entry->{'texi'}' ne `$entry_texi'", $line_nr) if ($index_entry->{'texi'} ne $entry_texi); |
|
} |
|
add_prev($text, $stack, &$Texi2HTML::Config::index_entry_command($macro, $index_name, $index_label, $entry_texi, $entry_text, $index_entry)); |
|
# it eats the end of line and therefore don't start |
|
# table entries nor close @center. These should be stopped |
|
# on the next line, though. |
|
return; |
|
} |
|
if ($macro eq 'insertcopying') |
|
{ |
|
#close_paragraph($text, $stack, $state, $line_nr); |
|
add_prev($text, $stack, do_insertcopying($state, $line_nr)); |
|
# reopen a preformatted format if it was interrupted by the macro |
|
begin_paragraph ($stack, $state) if ($state->{'preformatted'}); |
|
return; |
|
} |
|
if ($macro =~ /^itemx?$/o or ($macro eq 'headitem')) |
|
{ |
|
#print STDERR "ITEM: $cline"; |
|
#dump_stack($text, $stack, $state); |
|
abort_empty_preformatted($stack, $state); |
|
# FIXME let the user be able not to close the paragraph |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
|
|
#print STDERR "ITEM after close para: $cline"; |
|
#dump_stack($text, $stack, $state); |
|
# these functions return the format if in the right context |
|
my $in_list_enumerate; |
|
my $format; |
|
if ($format = add_item($text, $stack, $state, $line_nr)) |
|
{ # handle lists |
|
$in_list_enumerate = 1; |
|
if ($macro ne 'item') |
|
{ |
|
line_error (sprintf(__("\@%s not meaningful inside `\@%s' block"), $macro, $format->{'format'}), $line_nr); |
|
} |
|
} |
|
elsif ($format = add_term($text, $stack, $state, $line_nr)) |
|
{ # close table term |
|
} |
|
elsif ($format = add_line($text, $stack, $state, $line_nr)) |
|
{ # close table definition |
|
} |
|
if ($format) |
|
{ |
|
if ($macro eq 'headitem') |
|
{ |
|
line_error (sprintf(__("\@%s not meaningful inside `\@%s' block"), $macro, $format->{'format'}), $line_nr); |
|
} |
|
if (defined($Texi2HTML::Config::tab_item_texi)) |
|
{ |
|
my $resline = &$Texi2HTML::Config::tab_item_texi($macro, $state->{'command_stack'}, $stack, $state, $cline, $line_nr); |
|
$cline = $resline if (defined($resline)); |
|
} |
|
if ($in_list_enumerate) |
|
{ |
|
push (@$stack, { 'format' => 'item', 'text' => '', 'format_ref' => $format, 'item_cmd' => $macro }); |
|
begin_paragraph($stack, $state) if ($state->{'preformatted'} or !no_line($cline)); |
|
} |
|
else |
|
{# handle table @item term and restart another one |
|
# or after table text restart a term |
|
push (@$stack, { 'format' => 'term', 'text' => '', 'format_ref' => $format, 'item_cmd' => $macro }); |
|
} |
|
$format->{'texi_line'} = $cline; |
|
my ($line, $open_command) = &$Texi2HTML::Config::format_list_item_texi($format->{'format'}, $cline, $format->{'prepended'}, $format->{'command'}, $format->{'number'}); |
|
$cline = $line if (defined($line)); |
|
#if ($open_command) |
|
#{ |
|
# open_arg($format->{'command'},0, $state); |
|
# $format->{'command_opened'} = 1; |
|
#} |
|
$format->{'item_cmd'} = $macro; |
|
$format->{'texi_line_texi_formatted'} = $cline; |
|
next; |
|
} |
|
$format = add_row ($text, $stack, $state, $line_nr); # handle multitable |
|
if (!$format) |
|
{ # makeinfo has: |
|
# "@%s not meaningful inside `@%s' block" for menu/quotation... |
|
# and, if outside of any format |
|
# "%c%s found outside of an insertion block" |
|
# The following error message seems better. |
|
line_error (sprintf(__("\@%s outside of table or list"), $macro), $line_nr); |
|
} |
|
else |
|
{ |
|
push @$stack, {'format' => 'row', 'text' => '', 'item_cmd' => $macro, 'format_ref' => $format }; |
|
push @$stack, {'format' => 'cell', 'text' => '', 'format_ref' => $format}; |
|
$format->{'cell'} = 1; |
|
if ($format->{'max_columns'}) |
|
{ |
|
if (defined($Texi2HTML::Config::tab_item_texi)) |
|
{ |
|
my $resline = &$Texi2HTML::Config::tab_item_texi($macro, $state->{'command_stack'}, $stack, $state, $cline, $line_nr); |
|
$cline = $resline if (defined($resline)); |
|
} |
|
begin_paragraph_after_command($state,$stack,$macro,$cline); |
|
} |
|
else |
|
{ |
|
line_warn (sprintf(__("\@%s in empty multitable"), $macro), $line_nr); |
|
} |
|
} |
|
next; |
|
} |
|
|
|
if ($macro eq 'tab') |
|
{ |
|
abort_empty_preformatted($stack, $state); |
|
# FIXME let the user be able not to close the paragraph? |
|
close_paragraph($text, $stack, $state, "\@$macro", $line_nr); |
|
|
|
my $format = add_cell ($text, $stack, $state, $line_nr); |
|
if (!$format) |
|
{ |
|
line_error(__("ignoring \@tab outside of multitable"), $line_nr); |
|
} |
|
else |
|
{ |
|
push @$stack, {'format' => 'cell', 'text' => '', 'format_ref' => $format}; |
|
if (!$format->{'max_columns'}) |
|
{ |
|
line_warn (__("ignoring \@tab in empty multitable"), $line_nr); |
|
} |
|
elsif ($format->{'cell'} > $format->{'max_columns'}) |
|
{ |
|
line_error (sprintf(__("Too many columns in multitable item (max %d)"), $format->{'max_columns'}), $line_nr); |
|
} |
|
else |
|
{ |
|
if (defined($Texi2HTML::Config::tab_item_texi)) |
|
{ |
|
my $resline = &$Texi2HTML::Config::tab_item_texi($macro, $state->{'command_stack'}, $stack, $state, $cline, $line_nr); |
|
$cline = $resline if (defined($resline)); |
|
} |
|
} |
|
} |
|
begin_paragraph_after_command($state,$stack,$macro,$cline); |
|
next; |
|
} |
|
# Macro opening a format (table, list, deff, example...) |
|
if ($format_type{$macro} and ($format_type{$macro} ne 'fake')) |
|
{ |
|
my $ignore_center = 0; |
|
# @center is forbidden in @-command with braces, @*table |
|
# @item line, @multitable, or another @center |
|
if ($macro eq 'center' and @$stack) |
|
{ |
|
my $top_stack = top_stack($stack, 1); |
|
if (exists($top_stack->{'style'}) or (defined($top_stack->{'format'}) and ($top_stack->{'format'} eq 'term' or $top_stack->{'format'} eq 'cell')) or $state->{'preformatted'} or $state->{'paragraph_style'}->[-1] eq 'center') |
|
{ |
|
$ignore_center = 1; |
|
} |
|
#dump_stack ($text, $stack, $state); |
|
} |
|
if ($ignore_center) |
|
{ |
|
line_error(__("\@center should not appear in another format"), $line_nr); |
|
} |
|
else |
|
{ |
|
$cline = begin_format($text, $stack, $state, $macro, $cline, $line_nr); |
|
} |
|
# we keep the end of line for @center, and for formats |
|
# that have cmd_line opened and need to see the end of line |
|
next if (($macro eq 'center') or |
|
(defined($Texi2HTML::Config::def_map{$macro})) |
|
or ($macro eq 'float') or ($format_type{$macro} eq 'quotation')); |
|
return if ($cline =~ /^\s*$/); |
|
next; |
|
} |
|
$cline = do_unknown (2, $macro, $cline, $text, $stack, $state, $line_nr); |
|
next; |
|
} |
|
elsif($cline =~ s/^([^{}@,]*)\@([^\s\}\{\@]*)//o) |
|
{ # A macro with a character which shouldn't appear in macro name |
|
add_prev($text, $stack, do_text($1, $state)); |
|
$cline = do_unknown (2, $2, $cline, $text, $stack, $state, $line_nr); |
|
next; |
|
} |
|
# a brace |
|
elsif ($cline =~ s/^([^{},]*)([{}])//o) |
|
{ |
|
my $leading_text = $1; |
|
my $brace = $2; |
|
add_prev($text, $stack, do_text($leading_text, $state)); |
|
if (defined($brace) and ($brace eq '{')) #'}' |
|
{ |
|
add_prev($text, $stack, do_text('{',$state)); #} |
|
if ($state->{'math_style'}) |
|
{ |
|
$state->{'math_brace'}++; |
|
} |
|
else |
|
{ |
|
unless ($state->{'keep_texi'} or $state->{'remove_texi'}) |
|
{ |
|
line_error (sprintf(__("Misplaced %c"), ord('{')), $line_nr); |
|
} |
|
} |
|
} |
|
elsif (defined($brace) and ($brace eq '}') and |
|
(!@$stack or (!defined($stack->[-1]->{'style'})) |
|
# braces are allowed in math |
|
or $state->{'math_brace'})) |
|
{ |
|
if ($state->{'keep_texi'}) |
|
{ |
|
add_prev($text, $stack, '}'); |
|
} |
|
elsif($state->{'math_style'} and $state->{'math_brace'}) |
|
{ |
|
add_prev($text, $stack, do_text('}',$state)); |
|
$state->{'math_brace'}--; |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Misplaced %c"), ord('}')), $line_nr); |
|
#dump_stack($text, $stack, $state); |
|
} |
|
} |
|
else |
|
{ # A @-command{ ...} is closed |
|
my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, $cline); |
|
add_prev($text, $stack, $result); |
|
if ($Texi2HTML::Config::no_paragraph_commands{$command} |
|
and !$state->{'keep_texi'} and !no_paragraph($state,$cline)) |
|
{ |
|
begin_paragraph($stack, $state); |
|
} |
|
} |
|
} |
|
elsif ($cline =~ s/^([^,]*)[,]//o) |
|
{ |
|
add_prev($text, $stack, do_text($1, $state)); |
|
if (@$stack and defined($stack->[-1]->{'style'}) |
|
and (ref($::style_map_ref->{$stack->[-1]->{'style'}}) eq 'HASH')) |
|
{ |
|
my $macro = $stack->[-1]->{'style'}; |
|
my $style_args = $::style_map_ref->{$macro}->{'args'}; |
|
if (defined($style_args->[$stack->[-1]->{'arg_nr'} + 1])) |
|
{ |
|
push (@{$stack->[-1]->{'args'}}, $stack->[-1]->{'text'}); |
|
$stack->[-1]->{'fulltext'} .= $stack->[-1]->{'text'} . do_text(',', $state); |
|
$stack->[-1]->{'text'} = ''; |
|
close_arg ($macro, $stack->[-1]->{'arg_nr'}, $state); |
|
$stack->[-1]->{'arg_nr'}++; |
|
open_arg ($macro, $stack->[-1]->{'arg_nr'}, $state); |
|
next; |
|
} |
|
} |
|
add_prev($text, $stack, do_text(',', $state)); |
|
} |
|
else |
|
{ # no macro nor '}', but normal text |
|
add_prev($text, $stack, do_text($cline, $state)); |
|
# @center/line term is closed at the end of line. When a |
|
# @-command which |
|
# keeps the texi as is happens on the @center line, the @center |
|
# is closed at the end of line appearing after the @-command |
|
# closing (for example @ref, @footnote). |
|
last if ($state->{'keep_texi'}); |
|
#print STDERR "END_LINE(l):$cline!!!\n"; |
|
#dump_stack($text, $stack, $state); |
|
my $maybe_format_to_close = 1; |
|
my $in_table; |
|
while ($maybe_format_to_close) |
|
{ |
|
$maybe_format_to_close = 0; |
|
#my $top_format = top_stack($stack, 1); |
|
my $top_format = top_stack($stack, 2); |
|
# the stack cannot easily be used, because there may be |
|
# opened commands in paragraphs if the center is in a |
|
# style command, like |
|
# @b{ |
|
# bold |
|
# |
|
# @center centered bold |
|
# |
|
# } |
|
# |
|
# Therefore $state->{'paragraph_style'}->[-1] is used. |
|
# |
|
# The close_stack until 'center' is needed because |
|
# of constructs like |
|
# |
|
# @center something @table |
|
# |
|
# In that case what would be removed from the stack after |
|
# paragraph closing wold not be the @center. Such construct |
|
# is certainly incorrect, though. |
|
# |
|
# when 'closing_center' is true we don't retry to close |
|
# the @center line. |
|
if ($state->{'paragraph_style'}->[-1] eq 'center' |
|
and !$state->{'closing_center'} and !$state->{'keep_texi'}) |
|
{ |
|
$state->{'closing_center'} = 1; |
|
close_paragraph($text, $stack, $state, "\@center", $line_nr); |
|
close_stack($text, $stack, $state, $line_nr, 'center'); |
|
delete $state->{'closing_center'}; |
|
my $center = pop @$stack; |
|
add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command('center',$center->{'text'})); |
|
my $top_paragraph_style = pop @{$state->{'paragraph_style'}}; |
|
|
|
# center is at the bottom of the comand_stack because it |
|
# may be nested in many way |
|
my $bottom_command_stack = shift @{$state->{'command_stack'}}; |
|
print STDERR "Bug: closing center, top_paragraph_style: $top_paragraph_style, bottom_command_stack: $bottom_command_stack.\n" |
|
if ($bottom_command_stack ne 'center' or $top_paragraph_style ne 'center'); |
|
$maybe_format_to_close = 1; |
|
next; |
|
} |
|
|
|
# @item line is closed by end of line. In general there should |
|
# not be a paragraph in a term. However it may currently |
|
# happen in construct like |
|
# |
|
# @table @asis |
|
# @item @cindex index entry |
|
# some text still in term, and in paragraph |
|
# Not in term anymore |
|
# .... |
|
# |
|
if (defined($top_format->{'format'}) and $top_format->{'format'} eq 'term') |
|
{ |
|
#close_paragraph($text, $stack, $state, $line_nr) |
|
# if ($state->{'paragraph_context'}); |
|
close_stack($text, $stack, $state, $line_nr, 'term'); |
|
$in_table = add_term($text, $stack, $state, $line_nr); |
|
if ($in_table) |
|
{ |
|
$maybe_format_to_close = 1; |
|
next; |
|
} |
|
} |
|
} |
|
if ($in_table) |
|
{ |
|
push (@$stack, { 'format' => 'line', 'text' => '', 'only_inter_commands' => 1, 'format_ref' => $in_table }); |
|
begin_paragraph($stack, $state) if ($state->{'preformatted'}); |
|
} |
|
last; |
|
} |
|
} |
|
return 1; |
|
} # end scan_line |
|
|
|
sub open_arg($$$) |
|
{ |
|
my $macro = shift; |
|
my $arg_nr = shift; |
|
my $state = shift; |
|
if (ref($::style_map_ref->{$macro}) eq 'HASH') |
|
{ |
|
my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr]; |
|
if ($arg eq 'keep') |
|
{ |
|
$state->{'keep_nr'}++; |
|
$state->{'keep_texi'} = 1; |
|
} |
|
elsif (!$state->{'keep_texi'}) |
|
{ |
|
if ($arg eq 'code') |
|
{ |
|
$state->{'code_style'}++; |
|
} |
|
elsif ($arg eq 'math') |
|
{ |
|
$state->{'math_style'}++; |
|
$state->{'code_style'}++; |
|
if ($state->{'math_style'} == 1) |
|
{ |
|
$state->{'math_brace'} = 0; |
|
} |
|
} |
|
} |
|
} |
|
elsif ($code_style_map{$macro} and !$state->{'keep_texi'}) |
|
{ |
|
$state->{'code_style'}++; |
|
} |
|
} |
|
|
|
sub close_arg($$$) |
|
{ |
|
my $macro = shift; |
|
my $arg_nr = shift; |
|
my $state = shift; |
|
if (ref($::style_map_ref->{$macro}) eq 'HASH') |
|
{ |
|
my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr]; |
|
if ($arg eq 'keep') |
|
{ |
|
$state->{'keep_nr'}--; |
|
$state->{'keep_texi'} = 0 if ($state->{'keep_nr'} == 0); |
|
} |
|
elsif (!$state->{'keep_texi'}) |
|
{ |
|
if ($arg eq 'code') |
|
{ |
|
$state->{'code_style'}--; |
|
} |
|
elsif ($arg eq 'math') |
|
{ |
|
$state->{'math_style'}--; |
|
$state->{'code_style'}--; |
|
} |
|
} |
|
#print STDERR "c $arg_nr $macro $arg $state->{'code_style'}\n"; |
|
} |
|
elsif ($code_style_map{$macro} and !$state->{'keep_texi'}) |
|
{ |
|
$state->{'code_style'}--; |
|
} |
|
} |
|
|
|
# add a special style on the top of the stack. This is used for commands |
|
# that extend until the end of the line. Also add an entry in the @-command |
|
# hashes for this fakes style. |
|
#sub open_cmd_line($$$$$) |
|
#{ |
|
# my $command = shift; |
|
# my $stack = shift; |
|
# my $state = shift; |
|
# my $args = shift; |
|
# my $function = shift; |
|
# push @$stack, {'style' => 'cmd_line', 'text' => '', 'arg_nr' => 0}; |
|
# foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi) |
|
# { |
|
# $hash->{'cmd_line'}->{'args'} = $args; |
|
# $hash->{'cmd_line'}->{'function'} = $function; |
|
# } |
|
# $state->{'no_paragraph'}++; |
|
# push @{$state->{'no_paragraph_stack'}}, "\@$command line"; |
|
## $state->{'cmd_line'} = 1; |
|
# open_arg ('cmd_line', 0, $state); |
|
#} |
|
|
|
# finish @item line in @*table |
|
sub add_term($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my $top_format = top_stack($stack,2); |
|
|
|
return unless (defined($top_format->{'format'}) and $top_format->{'format'} eq 'term'); |
|
#print STDERR "ADD_TERM\n"; |
|
|
|
my $term = pop @$stack; |
|
my $format = $stack->[-1]; |
|
$format->{'paragraph_number'} = 0; |
|
chomp ($term->{'text'}); |
|
|
|
my ($index_label, $formatted_index_entry); |
|
if ($format->{'format'} =~ /^(f|v)/o) |
|
{ |
|
my $index_entry; |
|
($index_entry, $formatted_index_entry, $index_label) = do_index_entry_label($format->{'format'}, $state,$line_nr, $format->{'texi_line'}); |
|
print STDERR "Bug: no index entry for $term->{'text'}\n" unless defined($index_label); |
|
} |
|
|
|
my $item_result = &$Texi2HTML::Config::table_item($term->{'text'}, $index_label,$format->{'format'},$format->{'command'}, $state->{'command_stack'}, $term->{'item_cmd'}, $formatted_index_entry); |
|
add_prev($text, $stack, $item_result); |
|
return $format; |
|
} |
|
|
|
sub add_row($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my $top_format = top_stack($stack); |
|
# @center a @item |
|
# will lead to row not being closed since a close paragraph doesn't |
|
# end the center. |
|
return unless (defined($top_format->{'format'}) and $top_format->{'format'} eq 'cell'); |
|
my $cell = $top_format; |
|
my $format = $stack->[-3]; |
|
print STDERR "Bug under row cell row not a multitable\n" if (!defined($format->{'format'}) or $format->{'format'} ne 'multitable'); |
|
#print STDERR "ADD_ROW $format->{'item_nr'} first: $format->{'first'}\n"; |
|
# dump_stack($text, $stack, $state); |
|
|
|
$format->{'item_nr'}++ unless ($format->{'first'}); |
|
my $empty_first; |
|
if ($format->{'first'} and $format->{'cell'} == 1 and $stack->[-1]->{'text'} =~ /^\s*$/) |
|
{ |
|
$empty_first = 1; |
|
$format->{'empty_first'} = 1; |
|
} |
|
if ($format->{'cell'} > $format->{'max_columns'} or $empty_first) |
|
{ |
|
my $cell = pop @$stack; |
|
print STDERR "Bug: not a cell ($cell->{'format'}) in multitable\n" if ($cell->{'format'} ne 'cell'); |
|
} |
|
else |
|
{ |
|
add_cell($text, $stack, $state); |
|
} |
|
my $row = pop @$stack; |
|
print STDERR "Bug: not a row ($row->{'format'}) in multitable\n" if ($row->{'format'} ne 'row'); |
|
if ($format->{'max_columns'} and !$empty_first) |
|
{ |
|
# FIXME have the cell count in row and not in table. table could have |
|
# the whole structure, but cell count doesn't make much sense |
|
add_prev($text, $stack, &$Texi2HTML::Config::row($row->{'text'}, $row->{'item_cmd'}, $format->{'columnfractions'}, $format->{'prototype_row'}, $format->{'prototype_lengths'}, $format->{'max_columns'}, $cell->{'only_inter_commands'}, $format->{'first'})); |
|
} |
|
|
|
$format->{'first'} = 0 if ($format->{'first'}); |
|
|
|
return $format; |
|
} |
|
|
|
# FIXME remove and merge, too much double checks and code |
|
sub add_cell($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $top_format = top_stack($stack); |
|
|
|
#print STDERR "ADD_CELL\n"; |
|
return unless (defined($top_format) and $top_format->{'format'} eq 'cell'); |
|
# print STDERR "ADD_CELL, really\n"; |
|
|
|
my $cell = pop @$stack; |
|
my $row = top_stack($stack); |
|
print STDERR "Bug: top_stack of cell not a row\n" if (!defined($row->{'format'}) or ($row->{'format'} ne 'row')); |
|
my $format = $stack->[-2]; |
|
print STDERR "Bug under cell row not a multitable\n" if (!defined($format->{'format'}) or $format->{'format'} ne 'multitable'); |
|
|
|
if ($format->{'first'} and $format->{'cell'} == 1) |
|
{ |
|
line_warn(__("\@tab before \@item"), $line_nr); |
|
} |
|
|
|
if ($format->{'cell'} <= $format->{'max_columns'}) |
|
{ |
|
#print STDERR "ADD_CELL, really, really\n"; |
|
add_prev($text, $stack, &$Texi2HTML::Config::cell($cell->{'text'}, $row->{'item_cmd'}, $format->{'columnfractions'}, $format->{'prototype_row'}, $format->{'prototype_lengths'}, $format->{'max_columns'}, $cell->{'only_inter_commands'}, $format->{'first'})); |
|
} |
|
$format->{'cell'}++; |
|
$format->{'first'} = 0 if ($format->{'first'}); |
|
return $format; |
|
} |
|
|
|
sub add_line($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $top_stack = top_stack($stack); |
|
|
|
# if there is something like |
|
# @center centered @item new item |
|
# the item isn't opened since it is in @center, and center isn't closed |
|
# by an @item appearing here (unlike a paragraph). |
|
# the error message is '@item outside of table or list'. |
|
# texi2dvi also has issue, but makeinfo is happy, however it |
|
# produces bad nesting. |
|
return unless(defined($top_stack->{'format'}) and $top_stack->{'format'} eq 'line'); |
|
#print STDERR "ADD_LINE\n"; |
|
#dump_stack($text, $stack, $state); |
|
|
|
my $line = pop @$stack; |
|
my $format = $stack->[-1]; |
|
$format->{'paragraph_number'} = 0; |
|
if ($format->{'first'}) |
|
{ |
|
$format->{'first'} = 0; |
|
# we must have <dd> or <dt> following <dl> thus we do a |
|
# &$Texi2HTML::Config::table_line here too, although it could have |
|
# been a normal paragraph. |
|
if ($line->{'text'} =~ /\S/o) |
|
{ |
|
add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}, $line->{'only_inter_commands'}, 1)); |
|
$format->{'empty_first'} = 1 if ($line->{'only_inter_commands'}); |
|
} |
|
else |
|
{ |
|
$format->{'empty_first'} = 1; |
|
} |
|
} |
|
else |
|
{ |
|
$format->{'item_nr'}++; |
|
add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'}, $line->{'only_inter_commands'}, 0)); |
|
} |
|
return $format; |
|
} |
|
|
|
# finish @enumerate or @itemize @item |
|
sub add_item($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
my $top_stack = top_stack($stack); |
|
|
|
return unless (defined($top_stack->{'format'}) and $top_stack->{'format'} eq 'item'); |
|
#print STDERR "ADD_ITEM: \n"; |
|
#dump_stack($text, $stack, $state); |
|
# as in pre the end of line are kept, we must explicitely abort empty |
|
# preformatted, close_stack doesn't do that. |
|
my $item = pop @$stack; |
|
my $format = $stack->[-1]; |
|
#my $item_command = $item->{'format'}; |
|
my $item_command = $item->{'item_cmd'}; |
|
# first has no associated item, it is more like a 'title' |
|
$item_command = '' if ($format->{'first'}); |
|
|
|
# debug message if it is the first item (much like a title) although |
|
# there is an item command. |
|
msg_debug("First in $format->{'format'} but item_cmd defined $item->{'item_cmd'}",$line_nr) if ($format->{'first'} and defined($item->{'item_cmd'})); |
|
|
|
$format->{'paragraph_number'} = 0; |
|
|
|
#dump_stack ($text, $stack, $state); |
|
# the element following ol or ul must be li. Thus even though there |
|
# is no @item we put a normal item. |
|
# don't do an item if it is the first and it is empty |
|
if (!$format->{'first'} or ($item->{'text'} =~ /\S/o)) |
|
{ |
|
my $formatted_command; |
|
if (defined($format->{'command'}) and $format->{'command'} ne '')# and exists($::things_map_ref->{$format->{'command'}})) |
|
{ |
|
$formatted_command = substitute_line("\@$format->{'command'}\{\}", "\@item \@$format->{'command'}", duplicate_formatting_state($state)); |
|
$format->{'formatted_command'} = $formatted_command; |
|
} |
|
#chomp($item->{'text'}); |
|
add_prev($text, $stack, &$Texi2HTML::Config::list_item($item->{'text'},$format->{'format'},$format->{'command'}, $formatted_command, $format->{'item_nr'}, $format->{'spec'}, $format->{'number'}, $format->{'prepended'}, $format->{'prepended_formatted'}, $item->{'only_inter_commands'}, $format->{'first'},$item_command)); |
|
} |
|
else |
|
{ |
|
$format->{'empty_first'} = 1; |
|
} |
|
if ($format->{'first'}) |
|
{ |
|
$format->{'first'} = 0; |
|
} |
|
else |
|
{ |
|
$format->{'item_nr'}++; |
|
} |
|
|
|
if ($format->{'format'} eq 'enumerate') |
|
{ |
|
$format->{'number'} = ''; |
|
my $spec = $format->{'spec'}; |
|
if ($spec =~ /^[0-9]$/) |
|
{ |
|
$format->{'number'} = $spec + $format->{'item_nr'}; |
|
} |
|
else |
|
{ |
|
my $base_letter = ord('a'); |
|
$base_letter = ord('A') if (ucfirst($spec) eq $spec); |
|
|
|
my @letter_ords = decompose(ord($spec) - $base_letter + $format->{'item_nr'}, 26); |
|
foreach my $ord (@letter_ords) |
|
{# FIXME we go directly to 'ba' after 'z', and not 'aa' |
|
#because 'ba' is 1,0 and 'aa' is 0,0. |
|
$format->{'number'} = chr($base_letter + $ord) . $format->{'number'}; |
|
} |
|
} |
|
} |
|
|
|
return $format; |
|
} |
|
|
|
# format ``simple'' macros, that is macros without arg or style macros |
|
sub do_simple_command($$$) |
|
{ |
|
my $macro = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
#msg_debug ("DO_SIMPLE $macro $args $arg_nr (@$args)", $line_nr) if (defined($args)); |
|
if ($state->{'remove_texi'}) |
|
{ |
|
#print STDERR "DO_SIMPLE remove_texi $macro\n"; |
|
return $::simple_map_texi_ref->{$macro}; |
|
} |
|
else |
|
{ |
|
return &$Texi2HTML::Config::simple_command($macro, $state->{'preformatted'}, $state->{'math_style'}, $line_nr, $state); |
|
} |
|
} |
|
|
|
sub do_thing_command($$$$) |
|
{ |
|
my $macro = shift; |
|
my $text = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
if ($state->{'remove_texi'}) |
|
{ |
|
return $::texi_map_ref->{$macro}.$text; |
|
#print STDERR "DO_SIMPLE remove_texi texi_map $macro\n"; |
|
} |
|
else |
|
{ |
|
return &$Texi2HTML::Config::thing_command($macro, $text, $state->{'preformatted'}, $state->{'math_style'}, $line_nr, $state); |
|
} |
|
} |
|
|
|
sub do_style_command($$$$$$$$) |
|
{ |
|
my $macro = shift; |
|
my $text = shift; |
|
my $state = shift; |
|
my $args = shift; |
|
my $line_nr = shift; |
|
my $no_open = shift; |
|
my $no_close = shift; |
|
my $kept_line_nrs = shift; |
|
|
|
my $arg_nr = 0; |
|
$arg_nr = @$args - 1 if (defined($args)); |
|
|
|
if (defined($::style_map_ref->{$macro})) |
|
{ |
|
my $style; |
|
my $result; |
|
if ($state->{'remove_texi'}) |
|
{ |
|
#print STDERR "REMOVE $macro, $style_map_texi_ref->{$macro}, fun $style_map_texi_ref->{$macro}->{'function'} remove cmd " . \&Texi2HTML::Config::t2h_remove_command . " ascii acc " . \&t2h_default_accent; |
|
$style = $::style_map_texi_ref->{$macro}; |
|
} |
|
elsif ($state->{'math_style'} and defined($::style_map_math_ref->{$macro})) |
|
{ # FIXME we are still in math when the @math is closed here, since |
|
# close_arg that does 'math_style'-- is called below. |
|
$style = $::style_map_math_ref->{$macro}; |
|
} |
|
elsif ($state->{'preformatted'}) |
|
{ |
|
if ($macro eq 'kbd' and (Texi2HTML::Config::get_conf('kbdinputstyle') ne 'distinct')) |
|
{ |
|
$style = $::style_map_pre_ref->{'code'}; |
|
} |
|
else |
|
{ |
|
$style = $::style_map_pre_ref->{$macro}; |
|
} |
|
} |
|
else |
|
{ |
|
# kbd is in code_style, so it is 'code_style' > 1 |
|
if ($macro eq 'kbd' and ((Texi2HTML::Config::get_conf('kbdinputstyle') eq 'code') or ($state->{'code_style'} > 1 and Texi2HTML::Config::get_conf('kbdinputstyle') eq 'example'))) |
|
{ |
|
$style = $::style_map_ref->{'code'}; |
|
} |
|
else |
|
{ |
|
$style = $::style_map_ref->{$macro}; |
|
} |
|
} |
|
if ($macro eq 'dotless') |
|
{ |
|
if (scalar(@$args) ne 1) |
|
{ |
|
line_error(sprintf(__("%c%s expects a single character `i' or `j' as argument"), ord('@'), $macro), $line_nr); |
|
} |
|
elsif ($args->[0] ne 'i' and $args->[0] ne 'j') |
|
{ # FIXME an unformatted arg would have been better. Not a big deal. |
|
line_error (sprintf(__("%c%s expects `i' or `j' as argument, not `%s'"), ord('@'), $macro, $args->[0]), $line_nr); |
|
} |
|
} |
|
if (defined($style)) |
|
{ # known style |
|
$result = &$Texi2HTML::Config::style($style, $macro, $text, $args, $no_close, $no_open, $line_nr, $state, $state->{'command_stack'}, $kept_line_nrs); |
|
} |
|
if (!$no_close) |
|
{ |
|
close_arg($macro,$arg_nr, $state); |
|
} |
|
return $result; |
|
} |
|
elsif ($macro =~ /^special_(\w+)_(\d+)$/o) |
|
{ |
|
my $style = $1; |
|
my $count = $2; |
|
|
|
msg_debug ("Bug? text in \@$macro not empty", $line_nr) if ($text ne ''); |
|
if (defined($Texi2HTML::Config::command_handler{$style}) and |
|
defined($Texi2HTML::Config::command_handler{$style}->{'expand'})) |
|
{ |
|
my $struct_count = 1+ $special_commands{$style}->{'max'} - $special_commands{$style}->{'count'}; |
|
# may happen for text expanded more than once, for example |
|
# in invalid/tex_in_copying |
|
if (($count != $struct_count) and $T2H_DEBUG) |
|
{ |
|
msg_debug ("count $count in \@special $style and structure $struct_count differ", $line_nr); |
|
} |
|
$special_commands{$style}->{'count'}--; |
|
} |
|
my $result = $Texi2HTML::Config::command_handler{$style}->{'expand'} |
|
($style,$count,$state,$text); |
|
$result = '' if (!defined($result)); |
|
return $result; |
|
} |
|
# Unknown macro |
|
my $result = ''; |
|
my ($done, $result_text, $message) = &$Texi2HTML::Config::unknown_style($macro, $text,$state,$no_close, $no_open); |
|
if ($done) |
|
{ |
|
line_warn($message, $line_nr) if (defined($message)); |
|
if (defined($result_text)) |
|
{ |
|
$result = $result_text; |
|
} |
|
} |
|
else |
|
{ |
|
unless ($no_open) |
|
{ # we warn only if no_open is true, i.e. it is the first time we |
|
# close the macro for a multiline macro |
|
line_error (sprintf(__("Unknown command with braces `\@%s'"), $macro), $line_nr); |
|
$result = do_text("\@$macro") . "{"; |
|
} |
|
$result .= $text; |
|
$result .= '}' unless ($no_close); |
|
} |
|
return $result; |
|
} |
|
|
|
sub do_unknown($$$$$$$) |
|
{ |
|
my $pass = shift; |
|
my $macro = shift; |
|
my $line = shift; |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
#print STDERR "do_unknown[$pass]($macro) ::: $line"; |
|
|
|
my ($result_line, $result, $result_text, $message) = &$Texi2HTML::Config::unknown($macro, $line, $pass, $stack,$state); |
|
if ($result) |
|
{ |
|
add_prev ($text, $stack, $result_text) if (defined($result_text)); |
|
line_warn($message, $line_nr) if (defined($message)); |
|
# if $state->{'preformatted'}, assume that the preformatted is |
|
# already opened. Otherwise we may end up opening one each time |
|
# there is an unknown command. |
|
begin_paragraph_after_command($state, $stack, $macro, $result_line) |
|
if (!$state->{'preformatted'}); |
|
return $result_line; |
|
} |
|
elsif ($pass == 2) |
|
{ |
|
if ($Texi2HTML::Config::style_map{$macro}) |
|
{ |
|
line_error (sprintf(__("%c%s expected braces"), ord('@'), $macro), $line_nr); |
|
} |
|
else |
|
{ |
|
line_error (sprintf(__("Unknown command `%s'"), $macro), $line_nr); |
|
} |
|
add_prev ($text, $stack, do_text("\@$macro")); |
|
return $line; |
|
} |
|
elsif ($pass == 1) |
|
{ |
|
add_prev ($text, $stack, "\@$macro"); |
|
return $line; |
|
} |
|
elsif ($pass == 0) |
|
{ |
|
add_prev ($text, $stack, "\@$macro") unless($state->{'ignored'}); |
|
return $line; |
|
} |
|
} |
|
|
|
# used only during @macro processing |
|
sub add_text($@) |
|
{ |
|
my $string = shift; |
|
|
|
return if (!defined($string)); |
|
foreach my $scalar_ref (@_) |
|
{ |
|
next unless defined($scalar_ref); |
|
if (!defined($$scalar_ref)) |
|
{ |
|
$$scalar_ref = $string; |
|
} |
|
else |
|
{ |
|
$$scalar_ref .= $string; |
|
} |
|
return; |
|
} |
|
} |
|
|
|
sub add_prev ($$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $string = shift; |
|
|
|
unless (defined($text) and ref($text) eq "SCALAR") |
|
{ |
|
die "text not a SCALAR ref: " . ref($text) . ""; |
|
} |
|
|
|
return if (!defined($string)); |
|
if (@$stack) |
|
{ |
|
$stack->[-1]->{'text'} .= $string; |
|
return; |
|
} |
|
|
|
if (!defined($$text)) |
|
{ |
|
$$text = $string; |
|
} |
|
else |
|
{ |
|
$$text .= $string; |
|
} |
|
} |
|
|
|
sub close_stack_texi($$$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
|
|
|
|
return undef unless (@$stack or $state->{'raw'} or $state->{'macro'} or $state->{'macro_name'} or $state->{'ignored'}); |
|
|
|
if ($state->{'ignored'}) |
|
{ |
|
line_error (sprintf(__("Reached eof before matching \@end %s"), $state->{'ignored'}), $line_nr); |
|
close_ignored($state, $stack); |
|
} |
|
|
|
if ($state->{'macro'}) |
|
{ |
|
my ($no_remaining, $result) = end_macro($state, '@end macro', "\n"); |
|
add_prev ($text, $stack, $result) if (defined($result)); |
|
line_error (sprintf(__("%cend macro not found"), ord('@')), $line_nr); |
|
} |
|
elsif ($state->{'macro_name'}) |
|
{ |
|
#line_warn ("closing $state->{'macro_name'} ($state->{'macro_depth'} braces missing)", $line_nr); |
|
line_error (sprintf(__("\@%s missing close brace"), $state->{'macro_name'}), $line_nr); |
|
while ($state->{'macro_name'}) |
|
{ |
|
close_macro_arg($state, '', $line_nr); |
|
} |
|
} |
|
elsif ($state->{'verb'}) |
|
{ |
|
# warning in next pass |
|
#line_warn ("closing \@verb", $line_nr); |
|
$stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; |
|
delete $state->{'verb'}; |
|
} |
|
elsif ($state->{'raw'}) |
|
{ |
|
line_error (sprintf(__("Expected \@end %s"), $state->{'raw'}), $line_nr); |
|
my $style = pop @$stack; |
|
add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}"); |
|
delete $state->{'raw'}; |
|
} |
|
|
|
my $stack_level = $#$stack + 1; |
|
|
|
while ($stack_level--) |
|
{ |
|
my $style = pop(@$stack); |
|
# would be better in close_stack_structure |
|
#line_warn ("closing \@-command $style->{'style'}", $line_nr) if ($style->{'style'} ne ''); |
|
close_style_texi($style, $text, $stack, $state, 1); |
|
} |
|
#$stack = [ ]; |
|
} |
|
|
|
|
|
sub close_stack_structure($$$$;$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $close_only_item = shift; |
|
$close_only_item = 0 if (!defined($close_only_item)); |
|
|
|
return undef unless (@$stack or $state->{'raw'}); |
|
|
|
#print STDERR "close_stack_structure ($close_only_item)\n"; |
|
#dump_stack ($text, $stack, $state); |
|
my $stack_level = $#$stack + 1; |
|
my $string = ''; |
|
|
|
if ($state->{'verb'}) |
|
{ |
|
$stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; |
|
#$string .= $state->{'verb'}; |
|
} |
|
|
|
while ($stack_level--) |
|
{ |
|
last if ($close_only_item and defined($stack->[-1]->{'format'})); |
|
my $top_stack = pop @$stack; |
|
if ($top_stack->{'format'}) |
|
{ |
|
my $format = $top_stack->{'format'}; |
|
if ($format eq 'index_item') |
|
{ |
|
enter_table_index_entry($text, $stack, $state, $line_nr); |
|
} |
|
elsif (!defined($format_type{$format}) or ($format_type{$format} ne 'fake')) |
|
{ |
|
end_format_structure($format_type{$format}, $text, $stack, $state, $line_nr, "\n"); |
|
} |
|
} |
|
elsif (defined($top_stack->{'style'})) |
|
{ |
|
add_prev($text, $stack, |
|
close_structure_command($top_stack, $state, 1, $line_nr)); |
|
} |
|
} |
|
#$stack = [ ]; |
|
} |
|
|
|
# This is used in pass 2 and 3. |
|
sub open_region($$) |
|
{ |
|
my $command = shift; |
|
my $state = shift; |
|
if (!exists($state->{'region_lines'})) |
|
{ |
|
# FIXME 'format' is badly choosen 'region_name' would be much better |
|
$state->{'region_lines'}->{'format'} = $command; |
|
$state->{'region_lines'}->{'number'} = 1; |
|
$state->{'region_lines'}->{'kept_place'} = $state->{'place'}; |
|
$state->{'place'} = $no_element_associated_place; |
|
$state->{'region'} = $command; |
|
$state->{'multiple_pass'}++; |
|
$state->{'region_pass'} = 1; |
|
} |
|
else |
|
{ |
|
$state->{'region_lines'}->{'number'}++; |
|
} |
|
} |
|
|
|
# close region like @insertcopying, titlepage... |
|
# restore $state and delete the structure |
|
# This is used in pass 2 and 3. |
|
sub close_region($) |
|
{ |
|
my $state = shift; |
|
$state->{'place'} = $state->{'region_lines'}->{'kept_place'}; |
|
$state->{'multiple_pass'}--; |
|
delete $state->{'region_lines'}->{'number'}; |
|
delete $state->{'region_lines'}->{'format'}; |
|
delete $state->{'region_lines'}->{'kept_place'}; |
|
delete $state->{'region_lines'}; |
|
delete $state->{'region'}; |
|
delete $state->{'region_pass'}; |
|
} |
|
|
|
# close the stack, closing @-commands and formats left open. |
|
# if a $format is given if $format is encountered the closing stops |
|
sub close_stack($$$$;$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $format = shift; |
|
|
|
#print STDERR "sub_close_stack\n"; |
|
if (@$stack) |
|
{ |
|
my $stack_level = $#$stack + 1; |
|
|
|
#debugging |
|
#my $print_format = 'NO FORMAT'; |
|
#$print_format = $format if ($format); |
|
#msg_debug ("Close_stack: format $print_format", $line_nr); |
|
|
|
while ($stack_level--) |
|
{ |
|
if ($stack->[$stack_level]->{'format'}) |
|
{ |
|
my $stack_format = $stack->[$stack_level]->{'format'}; |
|
last if (defined($format) and $stack_format eq $format); |
|
# We silently close paragraphs, preformatted sections and fake formats |
|
if ($stack_format eq 'paragraph') |
|
{ |
|
my $paragraph = pop @$stack; |
|
add_prev ($text, $stack, do_paragraph($paragraph->{'text'}, $state, $stack)); |
|
} |
|
elsif ($stack_format eq 'preformatted') |
|
{ |
|
my $paragraph = pop @$stack; |
|
add_prev ($text, $stack, do_preformatted($paragraph->{'text'}, $state, $stack)); |
|
} |
|
else |
|
{ |
|
if ($fake_format{$stack_format}) |
|
{ |
|
warn "# Closing a fake format `$stack_format'\n" if ($T2H_VERBOSE); |
|
} |
|
elsif ($stack_format ne 'center') |
|
{ # we don't warn for center |
|
line_error (sprintf(__("No matching `%cend %s'"), ord('@'), $stack_format), $line_nr); |
|
#dump_stack ($text, $stack, $state); |
|
} |
|
if ($state->{'keep_texi'}) |
|
{ |
|
add_prev($text, $stack, "\@end $stack_format"); |
|
} |
|
elsif (!$state->{'remove_texi'}) |
|
{ |
|
end_format($text, $stack, $state, $stack_format, $line_nr) |
|
unless ($format_type{$stack_format} eq 'fake'); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
my $style = $stack->[$stack_level]->{'style'}; |
|
########################## debug |
|
if (!defined($style)) |
|
{ |
|
print STDERR "Bug: style not defined, on stack\n"; |
|
dump_stack ($text, $stack, $state); # bug |
|
} |
|
########################## end debug |
|
my $located_line_nr = $line_nr; |
|
# use the beginning of the @-command for the error message |
|
# line number if available. |
|
$located_line_nr = $stack->[$stack_level]->{'line_nr'} if (defined($stack->[$stack_level]->{'line_nr'})); |
|
line_error (sprintf(__("%c%s missing close brace"), ord('@'), $style), $located_line_nr); |
|
my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, ''); |
|
|
|
add_prev($text, $stack, $result) if (defined($result)); |
|
} |
|
} |
|
} |
|
|
|
# This tries to avoid cases where the command_stack is not empty |
|
# for a good reason, for example when doing a @def formatting the |
|
# outside command_stack is preserved. Also when expanding for |
|
# example @titleplage or @copying. |
|
# FIXME sort out which cases it is. |
|
return if ($format or (defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0) or $state->{'no_paragraph'}); |
|
|
|
# The pending style commands are cleared here; And are closed next. |
|
delete $state->{'paragraph_macros'}; |
|
# go through the command_stack and warn for each opened style format |
|
# and remove it. Those should be there because there is an opened style |
|
# that was stopped by a paragraph |
|
my @command_stack = @{$state->{'command_stack'}}; |
|
@{$state->{'command_stack'}} = (); |
|
while (@command_stack) |
|
{ |
|
my $latest_command = pop @command_stack; |
|
if (defined($style_type{$latest_command}) and $style_type{$latest_command} ne 'special') |
|
{ |
|
line_error (sprintf(__("%c%s missing close brace"), ord('@'), $latest_command), $line_nr); |
|
} |
|
else |
|
{ |
|
unshift @{$state->{'command_stack'}}, $latest_command; |
|
} |
|
} |
|
} |
|
|
|
# given a stack and a list of formats, return true if the stack contains |
|
# these formats, first on top |
|
sub stack_order($@) |
|
{ |
|
my $stack = shift; |
|
my $stack_level = $#$stack + 1; |
|
while (@_) |
|
{ |
|
my $format = shift; |
|
while ($stack_level--) |
|
{ |
|
if ($stack->[$stack_level]->{'format'}) |
|
{ |
|
if ($stack->[$stack_level]->{'format'} eq $format) |
|
{ |
|
$format = undef; |
|
last; |
|
} |
|
else |
|
{ |
|
return 0; |
|
} |
|
} |
|
} |
|
return 0 if ($format); |
|
} |
|
return 1; |
|
} |
|
|
|
sub top_format($) |
|
{ |
|
my $stack = shift; |
|
my $stack_level = $#$stack + 1; |
|
while ($stack_level--) |
|
{ |
|
if ($stack->[$stack_level]->{'format'} and !$fake_format{$stack->[$stack_level]->{'format'}}) |
|
{ |
|
return $stack->[$stack_level]; |
|
} |
|
} |
|
return undef; |
|
} |
|
|
|
sub close_paragraph($$$$;$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
my $reason = shift; |
|
my $line_nr = shift; |
|
my $no_preformatted_closing = shift; |
|
#print STDERR "CLOSE_PARAGRAPH\n"; |
|
#dump_stack($text, $stack, $state); |
|
|
|
# close until the first format, |
|
# duplicate stack of styles not closed |
|
my $new_stack; |
|
my $stack_level = $#$stack + 1; |
|
|
|
# In general close_paragraph is called because of a end of line, or |
|
# a format is opened or closed, or there is a @tab or @item and other |
|
# similar cases. In most cases there is a paragraph to be closed or |
|
# there are no style opened since most @-commands cause paragraph |
|
# opening and those that don't should not lead to a style opening. |
|
# |
|
# But in term or in @index (and maybe @node, @section, @ref), if |
|
# there is a command opened it won't be closed, since it is in |
|
# 'no_paragraph'. But @-commands that trigger close_paragraph should not |
|
# be called when in those no_paragraph settings. |
|
|
|
if ($state->{'no_paragraph'}) |
|
{ # This plays the role of "Multiline command %c%s used improperly" |
|
line_error(sprintf(__("%s should not appear in %s"), $reason, $state->{'no_paragraph_stack'}->[-1]), $line_nr); |
|
} |
|
|
|
while ($stack_level--) |
|
{ |
|
last if ($stack->[$stack_level]->{'format'}); |
|
my $style = $stack->[$stack_level]->{'style'}; |
|
|
|
# the !exists($style_type{$style}) condition catches the unknown |
|
# @-commands: by default they are considered as style commands |
|
if (!$state->{'no_paragraph'}) |
|
{ |
|
if (!exists($style_type{$style}) or $style_type{$style} eq 'style') |
|
{ |
|
unshift @$new_stack, { 'style' => $style, 'text' => '', 'no_open' => 1, 'arg_nr' => 0 }; |
|
} |
|
elsif (($style_type{$style} eq 'simple_style') or ($style_type{$style} eq 'accent')) |
|
{ |
|
} |
|
else |
|
{ |
|
# it shouldn't be possible to have 'special' styles, like |
|
# images, footnotes, xrefs, anchors, as |
|
# close_paragraph shouldn't be called with keep_texi |
|
# and when the arguments are expanded, there is a |
|
# substitute_line or similar with a new stack. |
|
msg_debug("BUG: special $style while closing paragraph", $line_nr); |
|
} |
|
} |
|
# if not in a paragraph, the command is simply closed, and not recorded |
|
# in new_stack. |
|
my ($result, $command) = close_style_command($text, $stack, $state, $line_nr, '', (!$state->{'no_paragraph'})); |
|
add_prev($text, $stack, $result) if (defined($result)); |
|
} |
|
|
|
if (!$state->{'paragraph_context'} and !$state->{'preformatted'} and defined($new_stack) and scalar(@$new_stack)) |
|
{ # in that case the $new_stack isn't recorded in $state->{'paragraph_macros'} |
|
# and therefore, it is lost |
|
msg_debug ("closing paragraph, but not in paragraph/preformatted, and new_stack not empty", $line_nr); |
|
dump_stack($text, $stack, $state); |
|
} |
|
my $top_stack = top_stack($stack); |
|
if ($top_stack and !defined($top_stack->{'format'})) |
|
{ #debug |
|
msg_debug("Bug: no format on top stack", $line_nr); |
|
dump_stack($text, $stack, $state); |
|
} |
|
if ($top_stack and ($top_stack->{'format'} eq 'paragraph')) |
|
{ |
|
my $paragraph = pop @$stack; |
|
add_prev($text, $stack, do_paragraph($paragraph->{'text'}, $state, $stack)); |
|
$state->{'paragraph_macros'} = $new_stack; |
|
return 1; |
|
} |
|
elsif ($top_stack and ($top_stack->{'format'} eq 'preformatted') and !$no_preformatted_closing) |
|
{ |
|
my $paragraph = pop @$stack; |
|
add_prev($text, $stack, do_preformatted($paragraph->{'text'}, $state, $stack)); |
|
$state->{'paragraph_macros'} = $new_stack; |
|
return 1; |
|
} |
|
return; |
|
} |
|
|
|
sub abort_empty_preformatted($$) |
|
{ |
|
my $stack = shift; |
|
my $state = shift; |
|
if (@$stack and $stack->[-1]->{'format'} |
|
and ($stack->[-1]->{'format'} eq 'preformatted') |
|
and ($stack->[-1]->{'text'} !~ /\S/)) |
|
{ |
|
if (defined($Texi2HTML::Config::empty_preformatted)) |
|
{ |
|
return if (&$Texi2HTML::Config::empty_preformatted($stack->[-1]->{'text'})); |
|
} |
|
pop @$stack; |
|
} |
|
} |
|
|
|
# for debugging |
|
sub dump_stack($$$) |
|
{ |
|
my $text = shift; |
|
my $stack = shift; |
|
my $state = shift; |
|
|
|
if (defined($$text)) |
|
{ |
|
print STDERR "text: $$text\n"; |
|
} |
|
else |
|
{ |
|
print STDERR "text: UNDEF\n"; |
|
} |
|
my $in_remove = 0; |
|
my $in_simple_format = 0; |
|
my $in_keep = 0; |
|
$in_keep = 1 if ($state->{'keep_texi'}); |
|
if (!$in_keep) |
|
{ |
|
$in_simple_format = 1 if ($state->{'simple_format'}); |
|
$in_remove = 1 if ($state->{'remove_texi'} and !$in_simple_format); |
|
} |
|
print STDERR "state[$state](k${in_keep}s${in_simple_format}r${in_remove}): "; |
|
foreach my $key (keys(%$state)) |
|
{ |
|
my $value = 'UNDEF'; |
|
$value = $state->{$key} if (defined($state->{$key})); |
|
print STDERR "$key: $value " if (!ref($value)); |
|
} |
|
print STDERR "\n"; |
|
my $stack_level = $#$stack + 1; |
|
while ($stack_level--) |
|
{ |
|
print STDERR " $stack_level-> "; |
|
foreach my $key (keys(%{$stack->[$stack_level]})) |
|
{ |
|
my $value = 'UNDEF'; |
|
$value = $stack->[$stack_level]->{$key} if |
|
(defined($stack->[$stack_level]->{$key})); |
|
print STDERR "$key: $value "; |
|
} |
|
print STDERR "\n"; |
|
} |
|
if (defined($state->{'command_stack'})) |
|
{ |
|
print STDERR "command_stack: "; |
|
foreach my $style (@{$state->{'command_stack'}}) |
|
{ |
|
print STDERR "($style) "; |
|
} |
|
print STDERR "\n"; |
|
} |
|
if (defined($state->{'region_lines'})) |
|
{ |
|
print STDERR "region_lines($state->{'region_lines'}->{'number'}): $state->{'region_lines'}->{'format'}\n"; |
|
} |
|
if (defined($state->{'paragraph_macros'})) |
|
{ |
|
print STDERR "paragraph_macros: "; |
|
foreach my $style (@{$state->{'paragraph_macros'}}) |
|
{ |
|
print STDERR "($style->{'style'})"; |
|
} |
|
print STDERR "\n"; |
|
} |
|
if (defined($state->{'preformatted_stack'})) |
|
{ |
|
print STDERR "preformatted_stack: "; |
|
foreach my $preformatted_style (@{$state->{'preformatted_stack'}}) |
|
{ |
|
if ($preformatted_style eq '') |
|
{ |
|
print STDERR "."; |
|
next; |
|
} |
|
my $pre_style = ''; |
|
$pre_style = $preformatted_style->{'pre_style'} if (exists $preformatted_style->{'pre_style'}); |
|
my $class = ''; |
|
$class = $preformatted_style->{'class'} if (exists $preformatted_style->{'class'}); |
|
my $style = ''; |
|
$style = $preformatted_style->{'style'} if (exists $preformatted_style->{'style'}); |
|
print STDERR "($pre_style, $class,$style)"; |
|
} |
|
print STDERR "\n"; |
|
} |
|
if (defined($state->{'text_macro_stack'}) and @{$state->{'text_macro_stack'}}) |
|
{ |
|
print STDERR "text_macro_stack: (@{$state->{'text_macro_stack'}})\n"; |
|
} |
|
} |
|
|
|
# for debugging |
|
sub print_elements($) |
|
{ |
|
my $elements = shift; |
|
foreach my $elem(@$elements) |
|
{ |
|
if ($elem->{'node'}) |
|
{ |
|
print STDERR "node-> $elem "; |
|
} |
|
else |
|
{ |
|
print STDERR "chap=> $elem "; |
|
} |
|
foreach my $key (keys(%$elem)) |
|
{ |
|
my $value = "UNDEF"; |
|
$value = $elem->{$key} if (defined($elem->{$key})); |
|
print STDERR "$key: $value "; |
|
} |
|
print STDERR "\n"; |
|
} |
|
} |
|
|
|
# for debugging |
|
sub context_string(;$$$) |
|
{ |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $message = shift; |
|
|
|
$state = $Texi2HTML::THISDOC{'state'} |
|
if (!defined($state) and defined($Texi2HTML::THISDOC{'state'})); |
|
$line_nr = $Texi2HTML::THISDOC{'line_nr'} |
|
if (!defined($line_nr) and defined($Texi2HTML::THISDOC{'line_nr'})); |
|
my $result = "Pass $global_pass"; |
|
my $line_info = ', no line information'; |
|
$line_info = ' ' .format_line_number($line_nr) if (defined($line_nr)); |
|
$result .= $line_info; |
|
if (!defined($state)) |
|
{ |
|
$result .= ', no state information'; |
|
} |
|
else |
|
{ |
|
$result .= ", context $state->{'context'}" if defined($state->{'context'}); |
|
my $expand = ''; |
|
if ($state->{'keep_texi'}) |
|
{ |
|
$expand .= ' no expansion'; |
|
} |
|
if ($state->{'remove_texi'}) |
|
{ |
|
$expand .= ' raw'; |
|
} |
|
if ($state->{'preformatted'}) |
|
{ |
|
$expand .= ' preformatted'; |
|
} |
|
if ($state->{'code_style'}) |
|
{ |
|
$expand .= " 'code'"; |
|
} |
|
if ($state->{'simple_format'}) |
|
{ |
|
$expand .= ' simple'; |
|
} |
|
$expand = ' normal' if (!$expand); |
|
$result .= ',' . $expand; |
|
if ($state->{'expansion'}) |
|
{ |
|
$result .= ", \@$state->{'expansion'}"; |
|
} |
|
if ($state->{'region'}) |
|
{ |
|
$result .= ", region $state->{'region'}"; |
|
} |
|
if ($state->{'outside_document'}) |
|
{ |
|
$result .= "; out"; |
|
} |
|
if ($state->{'inside_document'}) |
|
{ |
|
$result .= "; in"; |
|
} |
|
if ($state->{'multiple_pass'}) |
|
{ |
|
$result .= "; multiple $state->{'multiple_pass'}"; |
|
} |
|
if ($state->{'new_state'}) |
|
{ |
|
$result .= "; new"; |
|
} |
|
if ($state->{'duplicated'}) |
|
{ |
|
$result .= "; duplicated"; |
|
} |
|
} |
|
$result .= "(in @{$Texi2HTML::THISDOC{'command_stack'}})" |
|
if (defined ($Texi2HTML::THISDOC{'command_stack'}) and @{$Texi2HTML::THISDOC{'command_stack'}}); |
|
$result .= ' ' .$message if ($message); |
|
return $result; |
|
} |
|
|
|
|
|
my @states_stack = (); |
|
|
|
sub push_state($) |
|
{ |
|
my $new_state = shift; |
|
push @states_stack, $new_state; |
|
$Texi2HTML::THISDOC{'state'} = $new_state; |
|
} |
|
|
|
sub pop_state() |
|
{ |
|
pop @states_stack; |
|
if (@states_stack) |
|
{ |
|
$Texi2HTML::THISDOC{'state'} = $states_stack[-1]; |
|
} |
|
else |
|
{ |
|
$Texi2HTML::THISDOC{'state'} = undef; |
|
} |
|
} |
|
|
|
sub substitute_line($$;$$) |
|
{ |
|
my $line = shift; |
|
my $context_string = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
$state = {} if (!defined($state)); |
|
$state->{'no_paragraph'} = 1; |
|
|
|
if (($state->{'inside_document'} or $state->{'outside_document'}) and (!$state->{'duplicated'} and !$state->{'new_state'})) |
|
{ |
|
msg_debug("substitute_line with main state in: ".var_to_str($context_string), $line_nr); |
|
} |
|
push @{$state->{'no_paragraph_stack'}}, $context_string; |
|
# this is usefull when called from &$I, and also for image files |
|
return simple_format($state, [ $line_nr ], $context_string, $line) if ($state->{'simple_format'}); |
|
return substitute_text($state, [ $line_nr ], $context_string, $line); |
|
} |
|
|
|
sub substitute_text($$$@) |
|
{ |
|
my $state = shift; |
|
my $line_nrs = shift; |
|
my $context = shift; |
|
my @stack = (); |
|
my $text = ''; |
|
my $result = ''; |
|
my $line_nr; |
|
if ($state->{'structure'}) |
|
{ |
|
initialise_state_structure($state); |
|
} |
|
elsif ($state->{'texi'}) |
|
{ # only in arg_expansion |
|
initialise_state_texi($state); |
|
msg_bug("substitute_text, 'texi' true but not 'arg_expansion'") if (!$state->{'arg_expansion'}); |
|
} |
|
else |
|
{ |
|
#print STDERR "FILL_STATE substitute_text ($state->{'preformatted'}): @_\n"; |
|
if (($state->{'inside_document'} or $state->{'outside_document'}) and (!$state->{'duplicated'} and !$state->{'new_state'})) |
|
{ |
|
msg_debug("substitute_text with main state in: ".var_to_str($context), $line_nr); |
|
} |
|
fill_state($state); |
|
$state->{'context'} = $context; |
|
} |
|
$state->{'spool'} = []; |
|
#print STDERR "SUBST_TEXT ".var_to_str($context)."\n"; |
|
push_state($state); |
|
|
|
my $line_nrs_kept = $Texi2HTML::THISDOC{'line_nr'}; |
|
$Texi2HTML::THISDOC{'line_nr'} = undef; |
|
|
|
while (@_ or @{$state->{'spool'}} or $state->{'in_deff_line'}) |
|
{ |
|
my $line; |
|
if ($line_nrs and @{$line_nrs}) |
|
{ |
|
$line_nr = shift @{$line_nrs}; |
|
$Texi2HTML::THISDOC{'line_nr'} = $line_nr; |
|
} |
|
if (@{$state->{'spool'}}) |
|
{ |
|
$line = shift @{$state->{'spool'}}; |
|
} |
|
else |
|
{ |
|
$line = shift @_; |
|
} |
|
# msg_debug ("SUBSTITUTE_TEXT $line", $line_nr) if (defined($line_nr)); |
|
if ($state->{'in_deff_line'}) |
|
{ |
|
if (defined($line)) |
|
{ |
|
$line = $state->{'in_deff_line'} . $line; |
|
} |
|
else |
|
{ |
|
$line = $state->{'in_deff_line'}; |
|
} |
|
delete $state->{'in_deff_line'}; |
|
} |
|
else |
|
{ |
|
next unless (defined($line)); |
|
} |
|
#{ my $p_line = $line; chomp($p_line); print STDERR "SUBST_TEXT $p_line\n"; } |
|
if ($state->{'structure'}) |
|
{ |
|
scan_structure ($line, \$text, \@stack, $state); |
|
} |
|
elsif ($state->{'texi'}) |
|
{ |
|
scan_texi ($line, \$text, \@stack, $state); |
|
} |
|
else |
|
{ |
|
set_line_nr_in_stack($state, \@stack, $line_nr); |
|
scan_line($line, \$text, \@stack, $state, $line_nr); |
|
} |
|
next if (@stack); |
|
$result .= $text; |
|
$text = ''; |
|
} |
|
if ($line_nrs and @{$line_nrs}) |
|
{ |
|
$line_nr = shift @{$line_nrs}; |
|
$Texi2HTML::THISDOC{'line_nr'} = $line_nr; |
|
} |
|
# close stack in substitute_text |
|
if ($state->{'texi'}) |
|
{ |
|
close_stack_texi(\$text, \@stack, $state, $line_nr); |
|
} |
|
elsif ($state->{'structure'}) |
|
{ |
|
close_stack_structure(\$text, \@stack, $state, $line_nr); |
|
} |
|
else |
|
{ |
|
close_stack(\$text, \@stack, $state, $line_nr); |
|
} |
|
#print STDERR "SUBST_TEXT end\n"; |
|
pop_state(); |
|
$Texi2HTML::THISDOC{'line_nr'} = $line_nrs_kept; |
|
return $result . $text; |
|
} |
|
|
|
sub print_lines($;$) |
|
{ |
|
my ($fh, $lines) = @_; |
|
$lines = $Texi2HTML::THIS_SECTION unless $lines; |
|
my @cnt; |
|
my $cnt; |
|
for my $line (@$lines) |
|
{ |
|
print $fh $line; |
|
if (defined($Texi2HTML::Config::WORDS_IN_PAGE) and (Texi2HTML::Config::get_conf('SPLIT') eq 'node')) |
|
{ |
|
@cnt = split(/\W*\s+\W*/, $line); |
|
$cnt += scalar(@cnt); |
|
} |
|
} |
|
return $cnt; |
|
} |
|
|
|
sub do_index_entry_label($$$$;$) |
|
{ |
|
my $command = shift; |
|
my $state = shift; |
|
my $line_nr = shift; |
|
my $entry_texi = shift; |
|
# this is only needed for definitions since the whole line is parsed to |
|
# reuse get_deff_index. |
|
my $line = shift; |
|
|
|
my $prefix = index_entry_command_prefix($command, $line, $line_nr); |
|
my $index_name = $index_prefix_to_name{$prefix}; |
|
|
|
msg_debug("do_index_entry_label($command): Undefined entry_texi", $line_nr) |
|
if (!defined($entry_texi)); |
|
$entry_texi = trim_comment_spaces($entry_texi, "index label in \@$command", $line_nr); |
|
|
|
# index entries are not entered in special regions |
|
my $region = 'document'; |
|
$region = $state->{'region'} if (defined($state->{'region'})); |
|
|
|
my $entry; |
|
# Can be within a @caption expanded within a listoffloat. In that |
|
# case the 2 conditions on state are not set. |
|
if (defined($state->{'region'}) or !defined($state->{'expansion'})) |
|
{ |
|
# index entry on a line that is not searched for index entries, like |
|
# a @def* line |
|
if (!defined($Texi2HTML::THISDOC{'index_entries'}->{$region}) or !defined($Texi2HTML::THISDOC{'index_entries'}->{$region}->{$entry_texi})) |
|
{ |
|
line_warn(sprintf(__("Index entry not caught: `%s' in %s"), $entry_texi, $region), $line_nr); |
|
} |
|
else |
|
{ |
|
my $entry_ref = $Texi2HTML::THISDOC{'index_entries'}->{$region}->{$entry_texi}; |
|
# ============================ debug |
|
if (!defined($entry_ref->{'entries'})) |
|
{ |
|
msg_debug("BUG, not defined: {'index_entries'}->{$region}->{$entry_texi}->{'entries'}", $line_nr); |
|
} |
|
# ============================ end debug |
|
if (scalar(@{$entry_ref->{'entries'}}) > 1) |
|
{ |
|
if (!defined($entry_ref->{'index'})) |
|
{ |
|
$entry_ref->{'index'} = 0; |
|
} |
|
$entry = $entry_ref->{'entries'}->[$entry_ref->{'index'}]; |
|
$entry_ref->{'index'}++; |
|
} |
|
else |
|
{ |
|
$entry = $entry_ref->{'entries'}->[0]; |
|
} |
|
$entry->{'seen_in_output'} = 1 if (!$state->{'outside_document'}); |
|
############################################# debug |
|
# verify that the old way of getting index entries (in an array) is |
|
# synchronized with the document |
|
if (!$state->{'region'}) |
|
{ |
|
my $entry_from_array = shift @index_labels; |
|
if ($entry_from_array ne $entry) |
|
{ |
|
msg_debug ("entry `$entry->{'texi'}' ne entry_from_array `$entry_from_array->{'texi'}'", $line_nr); |
|
} |
|
if (!defined($entry_from_array)) |
|
{ |
|
mesg_debug ("Not enough index entries !", $line_nr); |
|
} |
|
} |
|
############################################# end debug |
|
} |
|
} |
|
|
|
if (!defined($entry)) |
|
{ |
|
# this can happen for listoffloats and caption without being a user |
|
# error. Well, in fact, it could be argued that it is indeed a user |
|
# error, putting an index entry in a snippet that can be expanded |
|
# more than once and is not strictly associated with a node/section. |
|
|
|
#print STDERR "Entry for index $index_name not gathered in usual places ($region)\n"; |
|
$entry = { |
|
'command' => $command, |
|
'texi' => $entry_texi, |
|
'entry' => $entry_texi, |
|
'prefix' => $prefix, |
|
'index_name' => $index_name, |
|
}; |
|
$entry->{'key'} = sorted_line($entry_texi); |
|
$entry->{'entry'} = '@code{'.$entry->{'entry'}.'}' |
|
if (defined($index_name) and |
|
defined($index_names{$index_name}->{'prefixes'}) and |
|
$index_names{$index_name}->{'prefixes'}->{$prefix} |
|
and $entry->{'key'} =~ /\S/); |
|
} |
|
|
|
###################################### debug |
|
else |
|
{ |
|
if ($entry->{'prefix'} ne $prefix) |
|
{ |
|
msg_debug ("prefix in entry $entry->{'prefix'} ne $prefix from $command", $line_nr); |
|
} |
|
} |
|
|
|
if ($command ne $entry->{'command'}) |
|
{ |
|
# happened with bad texinfo with a line like |
|
# @deffn func aaaa args @defvr c--ategory d--efvr_name |
|
# now this case is caught above by "Index entry not caught: |
|
msg_debug ("($region) Waiting for index cmd \@$entry->{'command'} got \@$command", $line_nr); |
|
} |
|
|
|
if ($entry->{'texi'} ne $entry_texi) |
|
{ |
|
msg_debug ("Waiting for index `$entry->{'texi'}', got `$entry_texi'", $line_nr); |
|
} |
|
|
|
my $id = 'no id'; |
|
$id = $entry->{'id'} if (defined($entry->{'id'})); |
|
print STDERR "(index($index_name) $command) [$entry->{'entry'}] $id\n" |
|
if ($T2H_DEBUG & $DEBUG_INDEX); |
|
###################################### end debug |
|
|
|
#return (undef,'','') if ($state->{'region'}); |
|
if ($entry->{'key'} =~ /^\s*$/) |
|
{ |
|
line_warn(sprintf(__("Empty index entry for \@%s"), $command), $entry->{'line_nr'}); |
|
} |
|
my $formatted_entry = substitute_line($entry->{'entry'}, "\@$command", prepare_state_multiple_pass("${command}_index", $state),$entry->{'line_nr'}); |
|
my $formatted_entry_reference = substitute_line($entry->{'texi'}, "\@$command", prepare_state_multiple_pass("${command}_index", $state)); |
|
return ($entry, $formatted_entry, &$Texi2HTML::Config::index_entry_label ($entry->{'id'}, $state->{'preformatted'}, $formatted_entry, |
|
$index_name, |
|
$command, $entry->{'texi'}, $formatted_entry_reference, |
|
(!$entry->{'seen_in_output'} and defined($entry->{'region'})),$entry)); |
|
} |
|
|
|
# decompose a decimal number on a given base. The algorithm looks like |
|
# the division with growing powers (division suivant les puissances |
|
# croissantes) ? |
|
sub decompose($$) |
|
{ |
|
my $number = shift; |
|
my $base = shift; |
|
my @result = (); |
|
|
|
return (0) if ($number == 0); |
|
my $power = 1; |
|
my $remaining = $number; |
|
|
|
while ($remaining) |
|
{ |
|
my $factor = $remaining % ($base ** $power); |
|
$remaining -= $factor; |
|
push (@result, $factor / ($base ** ($power - 1))); |
|
$power++; |
|
} |
|
return @result; |
|
} |
|
|
|
# process a css file |
|
sub process_css_file ($$) |
|
{ |
|
my $fh =shift; |
|
my $file = shift; |
|
my $in_rules = 0; |
|
my $in_comment = 0; |
|
my $in_import = 0; |
|
my $in_string = 0; |
|
my $rules = []; |
|
my $imports = []; |
|
my $line_nr = 0; |
|
while (my $line = <$fh>) |
|
{ |
|
$line_nr++; |
|
#print STDERR "Line: $line"; |
|
if ($in_rules) |
|
{ |
|
push @$rules, $line; |
|
next; |
|
} |
|
my $text = ''; |
|
while (1) |
|
{ |
|
#sleep 1; |
|
#print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $line"; |
|
if ($in_comment) |
|
{ |
|
if ($line =~ s/^(.*?\*\/)//) |
|
{ |
|
$text .= $1; |
|
$in_comment = 0; |
|
} |
|
else |
|
{ |
|
push @$imports, $text . $line; |
|
last; |
|
} |
|
} |
|
elsif (!$in_string and $line =~ s/^\///) |
|
{ # what do '\' do here ? |
|
if ($line =~ s/^\*//) |
|
{ |
|
$text .= '/*'; |
|
$in_comment = 1; |
|
} |
|
else |
|
{ |
|
push (@$imports, $text. "\n") if ($text ne ''); |
|
push (@$rules, '/' . $line); |
|
$in_rules = 1; |
|
last; |
|
} |
|
} |
|
elsif (!$in_string and $in_import and $line =~ s/^([\"\'])//) |
|
{ # strings outside of import start rules |
|
$text .= "$1"; |
|
$in_string = quotemeta("$1"); |
|
} |
|
elsif ($in_string and $line =~ s/^(\\$in_string)//) |
|
{ |
|
$text .= $1; |
|
} |
|
elsif ($in_string and $line =~ s/^($in_string)//) |
|
{ |
|
$text .= $1; |
|
$in_string = 0; |
|
} |
|
elsif ((! $in_string and !$in_import) and ($line =~ s/^([\\]?\@import)$// or $line =~ s/^([\\]?\@import\s+)//)) |
|
{ |
|
$text .= $1; |
|
$in_import = 1; |
|
} |
|
elsif (!$in_string and $in_import and $line =~ s/^\;//) |
|
{ |
|
$text .= ';'; |
|
$in_import = 0; |
|
} |
|
elsif (($in_import or $in_string) and $line =~ s/^(.)//) |
|
{ |
|
$text .= $1; |
|
} |
|
elsif (!$in_import and $line =~ s/^([^\s])//) |
|
{ |
|
push (@$imports, $text. "\n") if ($text ne ''); |
|
push (@$rules, $1 . $line); |
|
$in_rules = 1; |
|
last; |
|
} |
|
elsif ($line =~ s/^(\s)//) |
|
{ |
|
$text .= $1; |
|
} |
|
elsif ($line eq '') |
|
{ |
|
push (@$imports, $text); |
|
last; |
|
} |
|
} |
|
} |
|
#file_line_warn (__("string not closed in css file"), $file) if ($in_string); |
|
#file_line_warn (__("--css-file ended in comment"), $file) if ($in_comment); |
|
#file_line_warn (__("\@import not finished in css file"), $file) if ($in_import and !$in_comment and !$in_string); |
|
warn (sprintf(__("%s:%d: string not closed in css file"), $file, $line_nr)) if ($in_string); |
|
warn (sprintf(__("%s:%d: --css-file ended in comment"), $file, $line_nr)) if ($in_comment); |
|
warn (sprintf(__("%s:%d \@import not finished in css file"), $file, $line_nr)) if ($in_import and !$in_comment and !$in_string); |
|
return ($imports, $rules); |
|
} |
|
|
|
sub collect_all_css_files() |
|
{ |
|
my @css_import_lines; |
|
my @css_rule_lines; |
|
|
|
# process css files |
|
return ([],[]) if ($Texi2HTML::Config::NO_CSS); |
|
foreach my $file (@Texi2HTML::Config::CSS_FILES) |
|
{ |
|
my $css_file_fh; |
|
my $css_file; |
|
if ($file eq '-') |
|
{ |
|
$css_file_fh = \*STDIN; |
|
$css_file = '-'; |
|
} |
|
else |
|
{ |
|
$css_file = locate_include_file ($file); |
|
unless (defined($css_file)) |
|
{ |
|
document_warn ("css file $file not found"); |
|
next; |
|
} |
|
unless (open (CSSFILE, "$css_file")) |
|
{ |
|
warn (sprintf(__("%s: could not open --css-file %s: %s\n"), $real_command_name, $css_file, $!)); |
|
next; |
|
} |
|
$css_file_fh = \*CSSFILE; |
|
} |
|
my ($import_lines, $rules_lines); |
|
($import_lines, $rules_lines) = process_css_file ($css_file_fh, $css_file); |
|
push @css_import_lines, @$import_lines; |
|
push @css_rule_lines, @$rules_lines; |
|
} |
|
|
|
|
|
if ($T2H_DEBUG & $DEBUG_USER) |
|
{ |
|
if (@css_import_lines) |
|
{ |
|
print STDERR "# css import lines\n"; |
|
foreach my $line (@css_import_lines) |
|
{ |
|
print STDERR "$line"; |
|
} |
|
} |
|
if (@css_rule_lines) |
|
{ |
|
print STDERR "# css rule lines\n"; |
|
foreach my $line (@css_rule_lines) |
|
{ |
|
print STDERR "$line"; |
|
} |
|
} |
|
} |
|
return (\@css_import_lines, \@css_rule_lines); |
|
} |
|
|
|
sub init_with_file_name($) |
|
{ |
|
my $base_file = shift; |
|
set_docu_names($base_file, $Texi2HTML::THISDOC{'input_file_number'}); |
|
|
|
foreach my $handler(@Texi2HTML::Config::command_handler_init) |
|
{ |
|
&$handler; |
|
} |
|
} |
|
|
|
|
|
####################################################################### |
|
# |
|
# Main processing, process all the files given on the command line |
|
# |
|
####################################################################### |
|
|
|
my @input_files = @ARGV; |
|
# use STDIN if not a tty, like makeinfo does |
|
@input_files = ('-') if (!scalar(@input_files) and !-t STDIN); |
|
die sprintf(__("%s: missing file argument.\n"), $real_command_name) .$T2H_FAILURE_TEXT unless (scalar(@input_files) >= 1); |
|
|
|
my $file_number = 0; |
|
# main processing |
|
while(@input_files) |
|
{ |
|
my $input_file_arg = shift(@input_files); |
|
|
|
%Texi2HTML::THISDOC = (); |
|
$Texi2HTML::THIS_ELEMENT = undef; |
|
|
|
# Otherwise Texi2HTML::THISDOC wouldn't be set in case there was no call |
|
# to set_conf. |
|
foreach my $global_conf_vars('SPLIT', 'SPLIT_SIZE') |
|
{ |
|
$Texi2HTML::THISDOC{$global_conf_vars} = Texi2HTML::Config::get_conf($global_conf_vars); |
|
} |
|
|
|
foreach my $global_key (keys(%Texi2HTML::GLOBAL)) |
|
{ |
|
$Texi2HTML::THISDOC{$global_key} = $Texi2HTML::GLOBAL{$global_key}; |
|
} |
|
|
|
my $input_file_name; |
|
# try to concatenate with different suffixes. The last suffix is '' |
|
# such that the plain file name is checked. |
|
foreach my $suffix (@Texi2HTML::Config::INPUT_FILE_SUFFIXES) |
|
{ |
|
$input_file_name = $input_file_arg.$suffix if (-e $input_file_arg.$suffix); |
|
} |
|
# in case no file was found, still set the file name |
|
$input_file_name = $input_file_arg if (!defined($input_file_name)); |
|
|
|
$Texi2HTML::THISDOC{'input_file_name'} = $input_file_name; |
|
$Texi2HTML::THISDOC{'input_file_number'} = $file_number; |
|
$Texi2HTML::THISDOC{'input_directory'} = '.'; |
|
if ($input_file_name =~ /(.*\/)/) |
|
{ |
|
$Texi2HTML::THISDOC{'input_directory'} = $1; |
|
} |
|
|
|
my $input_file_base = $input_file_name; |
|
$input_file_base =~ s/\.te?x(i|info)?$//; |
|
|
|
@{$Texi2HTML::TOC_LINES} = (); # table of contents |
|
@{$Texi2HTML::OVERVIEW} = (); # short table of contents |
|
# this could be done here, but perl warns that |
|
# `"Texi2HTML::TITLEPAGE" used only once' and it is reset in |
|
# &$Texi2HTML::Config::titlepage anyway |
|
# $Texi2HTML::TITLEPAGE = undef; |
|
@{$Texi2HTML::THIS_SECTION} = (); |
|
|
|
# the reference to these hashes may be used before this point (for example |
|
# see makeinfo.init), so they should be kept as is and the values undef |
|
# but the key should not be deleted because the ref is on the key. |
|
foreach my $hash (\%Texi2HTML::HREF, \%Texi2HTML::NAME, \%Texi2HTML::NODE, |
|
\%Texi2HTML::NO_TEXI, \%Texi2HTML::SIMPLE_TEXT) |
|
{ |
|
foreach my $key (keys(%$hash)) |
|
{ |
|
$hash->{$key} = undef; |
|
} |
|
} |
|
|
|
%region_lines = (); |
|
%region_line_nrs = (); |
|
foreach my $region (@special_regions) |
|
{ |
|
$region_lines{$region} = []; |
|
$region_line_nrs{$region} = []; |
|
} |
|
|
|
@created_directories = (); |
|
|
|
$docu_dir = undef; # directory of the document |
|
$docu_name = undef; # basename of the document |
|
$docu_rdir = undef; # directory for the output |
|
$docu_toc = undef; # document's table of contents |
|
$docu_stoc = undef; # document's short toc |
|
$docu_foot = undef; # document's footnotes |
|
$docu_about = undef; # about this document |
|
$docu_top = undef; # document top |
|
$docu_doc = undef; # document (or document top of split) |
|
$docu_frame = undef; # main frame file |
|
$docu_toc_frame = undef; # toc frame file |
|
$path_to_working_dir = undef; # relative path leading to the working |
|
# directory from the document directory |
|
$docu_doc_file = undef; |
|
$docu_toc_file = undef; |
|
$docu_stoc_file = undef; |
|
$docu_foot_file = undef; |
|
$docu_about_file = undef; |
|
$docu_top_file = undef; |
|
$docu_frame_file = undef; |
|
$docu_toc_frame_file = undef; |
|
|
|
$global_pass = '0'; |
|
|
|
# done before any processing, this is not necessarily |
|
# the case with command_handler_init |
|
foreach my $handler(@Texi2HTML::Config::command_handler_setup) |
|
{ |
|
&$handler; |
|
} |
|
|
|
if (!$Texi2HTML::Config::USE_SETFILENAME) |
|
{ |
|
init_with_file_name ($input_file_base); |
|
} |
|
|
|
# FIXME when to do that? |
|
($Texi2HTML::THISDOC{'css_import_lines'}, $Texi2HTML::THISDOC{'css_rule_lines'}) |
|
= collect_all_css_files(); |
|
|
|
texinfo_initialization(0); |
|
|
|
print STDERR "# reading from $input_file_name\n" if $T2H_VERBOSE; |
|
|
|
$macros = undef; # macros. reference on a hash |
|
%info_enclose = (); # macros defined with definfoenclose |
|
@floats = (); # floats list |
|
%floats = (); # floats by style |
|
%nodes = (); # nodes hash. The key is the texi node name |
|
%cross_reference_nodes = (); # normalized node names arrays |
|
|
|
|
|
$global_pass = '1'; |
|
my ($texi_lines, $first_texi_lines, $lines_numbers) |
|
= pass_texi($input_file_name); |
|
|
|
if ($Texi2HTML::Config::USE_SETFILENAME and !defined($docu_name)) |
|
{ |
|
init_with_file_name ($input_file_base); |
|
} |
|
|
|
$global_pass = '1 expand macros'; |
|
Texi2HTML::Config::t2h_default_set_out_encoding(); |
|
dump_texi($texi_lines, 'texi', $lines_numbers) if ($T2H_DEBUG & $DEBUG_TEXI); |
|
if (defined($Texi2HTML::Config::MACRO_EXPAND)) |
|
{ |
|
my @texi_lines = (@$first_texi_lines, @$texi_lines); |
|
dump_texi(\@texi_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND); |
|
} |
|
|
|
%content_element = (); |
|
foreach my $command('contents', 'shortcontents') |
|
{ |
|
$all_content_elements{$command} = []; |
|
foreach my $key (keys(%{$reference_content_element{$command}})) |
|
{ |
|
$content_element{$command}->{$key} = $reference_content_element{$command}->{$key}; |
|
} |
|
} |
|
|
|
%sec2level = %reference_sec2level; |
|
|
|
$element_before_anything = |
|
{ |
|
'before_anything' => 1, |
|
'place' => [], |
|
'texi' => 'VIRTUAL ELEMENT BEFORE ANYTHING', |
|
}; |
|
|
|
|
|
$footnote_element = |
|
{ |
|
'id' => $Texi2HTML::Config::misc_pages_targets{'Footnotes'}, |
|
'target' => $Texi2HTML::Config::misc_pages_targets{'Footnotes'}, |
|
'file' => $docu_foot, |
|
'footnote' => 1, |
|
'place' => [], |
|
}; |
|
|
|
%region_initial_state = (); |
|
foreach my $region (@special_regions) |
|
{ |
|
$region_initial_state{$region} = { }; |
|
} |
|
|
|
# to determine if a command has to be processed the following are interesting |
|
# (and can be faked): |
|
# 'region': the name of the special region we are processing |
|
# 'region_pass': the number of passes in that specific region (both outside |
|
# of the main document, and in the main document) |
|
# 'multiple_pass': the number of pass in the formatting of the region in the |
|
# main document |
|
# It is set to 0 the first time the region is seen, before |
|
# it will be -1, for example when doing the |
|
# copying_comment, the titlepage... before starting with |
|
# the document itself. |
|
# 'outside_document': set to 1 if outside of the main document formatting |
|
|
|
foreach my $key (keys(%region_initial_state)) |
|
{ |
|
$region_initial_state{$key}->{'multiple_pass'} = -1; |
|
$region_initial_state{$key}->{'region_pass'} = 0; |
|
$region_initial_state{$key}->{'num_head'} = 0; |
|
$region_initial_state{$key}->{'foot_num'} = 0; |
|
$region_initial_state{$key}->{'relative_foot_num'} = 0; |
|
$region_initial_state{$key}->{'region'} = $key; |
|
} |
|
|
|
@opened_files = (); # all the files opened by the program to remove |
|
# them if FORCE is not set and an error occured |
|
|
|
texinfo_initialization(1); |
|
|
|
|
|
$no_element_associated_place = []; |
|
|
|
$document_idx_num = 0; |
|
$document_sec_num = 0; |
|
$document_head_num = 0; |
|
$document_anchor_num = 0; |
|
|
|
@nodes_list = (); # nodes in document reading order |
|
# each member is a reference on a hash |
|
@sections_list = (); # sections in reading order |
|
# each member is a reference on a hash |
|
@all_elements = (); # sectioning elements (nodes and sections) |
|
# in reading order. Each member is a reference |
|
# on a hash which also appears in %nodes, |
|
# @sections_list @nodes_list, @elements_list |
|
@elements_list = (); # all the resulting elements in document order |
|
%sections = (); # sections hash. The key is the section number |
|
%headings = (); # headings hash. The key is the heading number |
|
$section_top = undef; # @top section |
|
$element_top = undef; # Top element |
|
$node_top = undef; # Top node |
|
$node_first = undef; # First node |
|
$element_index = undef; # element with first index |
|
$element_chapter_index = undef; # chapter with first index |
|
$element_first = undef; # first element |
|
$element_last = undef; # last element |
|
%special_commands = (); # hash for the commands specially handled |
|
# by the user |
|
|
|
@index_labels = (); # array corresponding with @?index commands |
|
# constructed during pass_texi, used to |
|
# put labels in pass_text |
|
# right now it is only used for debugging |
|
# purposes. |
|
@unknown_index_index_entries = (); # holds index entries not associated |
|
# with any index |
|
%{$Texi2HTML::THISDOC{'index_entries_array'}} = (); # holds the index |
|
# entries in order of appearance in the document |
|
# for each index name. |
|
%{$Texi2HTML::THISDOC{'index_letters_array'}} = (); # holds the sorted |
|
# index letters for each index name. The sorted |
|
# letters hold the sorted index entries |
|
|
|
$global_pass = 2; |
|
my ($doc_lines, $doc_numbers) = pass_structure($texi_lines, $lines_numbers); |
|
|
|
foreach my $handler(@Texi2HTML::Config::command_handler_names) |
|
{ |
|
&$handler; |
|
} |
|
|
|
if ($T2H_DEBUG & $DEBUG_TEXI) |
|
{ |
|
dump_texi($doc_lines, 'first', $doc_numbers); |
|
if (defined($Texi2HTML::Config::MACRO_EXPAND and $Texi2HTML::Config::DUMP_TEXI)) |
|
{ |
|
my @all_doc_lines = (@$first_texi_lines, @$doc_lines); |
|
#push (@$doc_lines, "\@bye\n"); |
|
dump_texi(\@all_doc_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND . ".first"); |
|
} |
|
} |
|
next if ($Texi2HTML::Config::DUMP_TEXI); |
|
|
|
foreach my $style (keys(%special_commands)) |
|
{ |
|
$special_commands{$style}->{'max'} = $special_commands{$style}->{'count'}; |
|
} |
|
|
|
%files = (); # keys are files. This is used to avoid reusing an already |
|
# used file name |
|
%printed_indices = (); # value is true for an index name not empty and |
|
# printed |
|
$global_pass = '2 prepare indices'; |
|
prepare_indices(); |
|
$global_pass = '2 element directions'; |
|
rearrange_elements(); |
|
do_names(); |
|
|
|
$global_pass = '2-3 user functions'; |
|
#Texi2HTML::LaTeX2HTML::latex2html(); |
|
foreach my $handler(@Texi2HTML::Config::command_handler_process) |
|
{ |
|
&$handler; |
|
} |
|
|
|
# maybe do that later to have more elements ready? |
|
&$Texi2HTML::Config::toc_body(\@sections_list); |
|
|
|
&$Texi2HTML::Config::css_lines($Texi2HTML::THISDOC{'css_import_lines'}, |
|
$Texi2HTML::THISDOC{'css_rule_lines'}); |
|
|
|
|
|
$global_head_num = 0; # heading index. it is global for the main doc, |
|
# and taken from the state if in multiple_pass. |
|
$global_foot_num = 0; |
|
$global_relative_foot_num = 0; |
|
@foot_lines = (); # footnotes |
|
$copying_comment = ''; # comment constructed from text between |
|
# @copying and @end copying with licence |
|
%acronyms_like = (); # acronyms or similar commands associated texts |
|
# the key are the commands, the values are |
|
# hash references associating shorthands to |
|
# texts. |
|
@states_stack = (); |
|
|
|
pass_text($doc_lines, $doc_numbers); |
|
print STDERR "BUG: " . scalar(@index_labels) . " index entries pending\n" |
|
if (scalar(@index_labels)); |
|
foreach my $special (keys(%special_commands)) |
|
{ |
|
my $count = $special_commands{$special}->{'count'}; |
|
if (($count != 0) and $T2H_VERBOSE) |
|
{ |
|
document_warn ("$count special \@$special were not processed.\n"); |
|
} |
|
} |
|
if ($Texi2HTML::Config::IDX_SUMMARY) |
|
{ |
|
foreach my $entry (keys(%index_names)) |
|
{ |
|
do_index_summary_file($entry, $docu_name); |
|
} |
|
} |
|
if (defined($Texi2HTML::Config::INTERNAL_LINKS)) |
|
{ |
|
my $FH = open_out($Texi2HTML::Config::INTERNAL_LINKS); |
|
&$Texi2HTML::Config::internal_links($FH, \@elements_list, $Texi2HTML::THISDOC{'index_letters_array'}); |
|
close ($FH); |
|
} |
|
do_node_files() if ($Texi2HTML::Config::NODE_FILES); |
|
#l2h_FinishFromHtml() if ($Texi2HTML::Config::L2H); |
|
#l2h_Finish() if($Texi2HTML::Config::L2H); |
|
#Texi2HTML::LaTeX2HTML::finish(); |
|
foreach my $handler(@Texi2HTML::Config::command_handler_finish) |
|
{ |
|
&$handler; |
|
} |
|
&$Texi2HTML::Config::finish_out(); |
|
|
|
print STDERR "# File ($file_number) $input_file_name processed\n" if $T2H_VERBOSE; |
|
$file_number++; |
|
} |
|
print STDERR "# that's all folks\n" if $T2H_VERBOSE; |
|
exit(0); |
|
|
|
|
|
############################################################################## |
|
|
|
# These next few lines are legal in both Perl and nroff. |
|
|
|
.00 ; # finish .ig |
|
|
|
'di \" finish diversion--previous line must be blank |
|
.nr nl 0-1 \" fake up transition to first page again |
|
.nr % 0 \" start at page 1 |
|
'; __END__ ############# From here on it's a standard manual page ############ |
|
.so /usr/local/man/man1/texi2html.1 |
|