summaryrefslogtreecommitdiff
path: root/macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-11-09 03:02:50 +0000
committerNorbert Preining <norbert@preining.info>2022-11-09 03:02:50 +0000
commit5de83ec843cdc88e6adc42b1fe3f0ec48c52b7f3 (patch)
treeb49f7c180396c8ef389c8fd519370b6d03f4e100 /macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm
parent118cb5bbc5236bf86ca1088b9b3bae04c7b09beb (diff)
CTAN sync 202211090302
Diffstat (limited to 'macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm')
-rw-r--r--macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm1796
1 files changed, 992 insertions, 804 deletions
diff --git a/macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm b/macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm
index 7402eb9f99..949bba1b84 100644
--- a/macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm
+++ b/macros/texinfo/texinfo/tp/Texinfo/Convert/Plaintext.pm
@@ -1,6 +1,6 @@
# Plaintext.pm: output tree as text with filling.
#
-# Copyright 2010-2020 Free Software Foundation, Inc.
+# Copyright 2010-2022 Free Software Foundation, Inc.
#
# 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
@@ -16,6 +16,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Original author: Patrice Dumas <pertusus@free.fr>
+#
+# Names of methods overriden in Texinfo::Convert::Info begin with format_.
package Texinfo::Convert::Plaintext;
@@ -24,17 +26,24 @@ use 5.00405;
# See comment at start of HTML.pm
use if $] >= 5.012, feature => qw(unicode_strings);
+use if $] >= 5.014, re => '/a';
+
use strict;
-use Texinfo::Convert::Converter;
+# To check if there is no erroneous autovivification
+#no autovivification qw(fetch delete exists store strict);
+
+use Texinfo::Commands;
use Texinfo::Common;
use Texinfo::Convert::Texinfo;
-use Texinfo::Convert::Paragraph;
-
+use Texinfo::Convert::Utils;
use Texinfo::Convert::Text;
+use Texinfo::Convert::Utils;
+use Texinfo::Convert::Converter;
+use Texinfo::Convert::Paragraph;
require Exporter;
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+use vars qw($VERSION @ISA);
@ISA = qw(Texinfo::Convert::Converter);
# Some extra initialization for the first time this module is loaded.
@@ -51,69 +60,73 @@ sub import {
goto &Exporter::import;
}
-%EXPORT_TAGS = ( 'all' => [ qw(
- convert
- output
-) ] );
+$VERSION = '7.0';
-@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
-@EXPORT = qw(
-);
-
-$VERSION = '6.8';
+# commands that are of use for formatting.
+my %formatted_line_commands = %Texinfo::Common::formatted_line_commands;
+my %formatted_nobrace_commands = %Texinfo::Common::formatted_nobrace_commands;
+my %formattable_line_commands = %Texinfo::Common::formattable_line_commands;
+my %brace_commands = %Texinfo::Commands::brace_commands;
-# misc commands that are of use for formatting.
-my %formatting_misc_commands = %Texinfo::Convert::Text::formatting_misc_commands;
my $NO_NUMBER_FOOTNOTE_SYMBOL = '*';
+# documentlanguage is used through gdt().
my @informative_global_commands = ('paragraphindent', 'firstparagraphindent',
-'frenchspacing', 'documentencoding', 'footnotestyle', 'documentlanguage',
-'contents', 'shortcontents', 'summarycontents', 'deftypefnnewline');
+'frenchspacing', 'footnotestyle', 'documentlanguage', 'deftypefnnewline');
my %informative_commands;
foreach my $informative_command (@informative_global_commands) {
$informative_commands{$informative_command} = 1;
}
-my %no_brace_commands = %Texinfo::Common::no_brace_commands;
+# used to pass to Texinfo::Convert::Info
+sub get_informative_global_commands($)
+{
+ my $self = shift;
+ return @informative_global_commands;
+}
+
my %brace_no_arg_commands;
-foreach my $command (keys (%Texinfo::Common::brace_commands)) {
+foreach my $command (keys (%brace_commands)) {
$brace_no_arg_commands{$command} = 1
- if ($Texinfo::Common::brace_commands{$command} eq '0');
-}
-my %accent_commands = %Texinfo::Common::accent_commands;
-my %misc_commands = %Texinfo::Common::misc_commands;
-my %sectioning_commands = %Texinfo::Common::sectioning_commands;
-my %def_commands = %Texinfo::Common::def_commands;
-my %ref_commands = %Texinfo::Common::ref_commands;
-my %block_commands = %Texinfo::Common::block_commands;
-my %menu_commands = %Texinfo::Common::menu_commands;
-my %root_commands = %Texinfo::Common::root_commands;
-my %preformatted_commands = %Texinfo::Common::preformatted_commands;
-my %math_commands = %Texinfo::Common::math_commands;
+ if ($brace_commands{$command} eq 'noarg');
+}
+my %accent_commands = %Texinfo::Commands::accent_commands;
+my %line_commands = %Texinfo::Commands::line_commands;
+my %nobrace_commands = %Texinfo::Commands::nobrace_commands;
+my %sectioning_heading_commands = %Texinfo::Commands::sectioning_heading_commands;
+my %def_commands = %Texinfo::Commands::def_commands;
+my %ref_commands = %Texinfo::Commands::ref_commands;
+my %block_commands = %Texinfo::Commands::block_commands;
+my %root_commands = %Texinfo::Commands::root_commands;
+my %preformatted_commands = %Texinfo::Commands::preformatted_commands;
+my %math_commands = %Texinfo::Commands::math_commands;
+my %preformatted_code_commands = %Texinfo::Commands::preformatted_code_commands;
+my %default_index_commands = %Texinfo::Commands::default_index_commands;
+my %letter_no_arg_commands = %Texinfo::Commands::letter_no_arg_commands;
+
+my %nobrace_symbol_text = %Texinfo::Common::nobrace_symbol_text;
my %explained_commands = %Texinfo::Common::explained_commands;
my %inline_format_commands = %Texinfo::Common::inline_format_commands;
-my %inline_commands = %Texinfo::Common::inline_commands;
-my %item_container_commands = %Texinfo::Common::item_container_commands;
-my %raw_commands = %Texinfo::Common::raw_commands;
-my %format_raw_commands = %Texinfo::Common::format_raw_commands;
-my %code_style_commands = %Texinfo::Common::code_style_commands;
-my %regular_font_style_commands = %Texinfo::Common::regular_font_style_commands;
-my %preformatted_code_commands = %Texinfo::Common::preformatted_code_commands;
-my %default_index_commands = %Texinfo::Common::default_index_commands;
-my %letter_no_arg_commands = %Texinfo::Common::letter_no_arg_commands;
-
-foreach my $kept_command(keys (%informative_commands),
- keys (%default_index_commands),
- 'verbatiminclude', 'insertcopying',
- 'listoffloats', 'printindex', ) {
- $formatting_misc_commands{$kept_command} = 1;
+my %brace_code_commands = %Texinfo::Common::brace_code_commands;
+
+my @contents_commands = ('contents', 'shortcontents', 'summarycontents');
+
+foreach my $kept_command (keys (%informative_commands), @contents_commands,
+ keys (%default_index_commands), keys(%formattable_line_commands)) {
+ $formatted_line_commands{$kept_command} = 1;
+}
+
+# formatted/formattable @-commands not formatted in Plaintext/Info
+foreach my $non_formatted_line_command ('page', 'need', 'vskip',
+ 'author', 'subtitle', 'title') {
+ delete $formatted_line_commands{$non_formatted_line_command};
}
foreach my $def_command (keys(%def_commands)) {
- $formatting_misc_commands{$def_command} = 1 if ($misc_commands{$def_command});
+ $formatted_line_commands{$def_command} = 1 if ($line_commands{$def_command});
}
# There are 6 stacks that define the context.
@@ -152,6 +165,16 @@ foreach my $def_command (keys(%def_commands)) {
# paragraph number incremented with paragraphs, center, listoffloats
# and block commands except: html and such, group, raggedright, menu*, float
+my %menu_commands;
+
+my %format_raw_commands;
+foreach my $block_command (keys(%block_commands)) {
+ $menu_commands{$block_command} = 1
+ if ($block_commands{$block_command} eq 'menu');
+ $format_raw_commands{$block_command} = 1
+ if ($block_commands{$block_command} eq 'format_raw');
+}
+
my %default_preformatted_context_commands = (%preformatted_commands,
%format_raw_commands);
foreach my $preformatted_command ('verbatim', keys(%menu_commands)) {
@@ -165,13 +188,19 @@ foreach my $block_math_command (keys(%math_commands)) {
}
}
-my %ignored_misc_commands;
-foreach my $misc_command (keys(%misc_commands)) {
- $ignored_misc_commands{$misc_command} = 1
- unless ($formatting_misc_commands{$misc_command});
+my %ignored_line_commands;
+foreach my $line_command (keys(%line_commands)) {
+ $ignored_line_commands{$line_command} = 1
+ unless ($formatted_line_commands{$line_command});
+}
+
+my %ignored_nobrace_commands;
+foreach my $nobrace_command (keys(%nobrace_commands)) {
+ $ignored_nobrace_commands{$nobrace_command} = 1
+ unless ($formatted_nobrace_commands{$nobrace_command});
}
-my %ignored_commands = %ignored_misc_commands;
+my %ignored_commands = (%ignored_line_commands, %ignored_nobrace_commands);
foreach my $ignored_brace_commands ('caption', 'shortcaption',
'hyphenation', 'sortas') {
$ignored_commands{$ignored_brace_commands} = 1;
@@ -217,7 +246,7 @@ my %flush_commands = (
# used to determine the first line, in fact.
my %advance_paragraph_count_commands;
foreach my $command (keys(%block_commands)) {
- next if ($menu_commands{$command}
+ next if ($menu_commands{$command}
or $block_commands{$command} eq 'raw');
$advance_paragraph_count_commands{$command} = 1;
}
@@ -249,15 +278,15 @@ my %upper_case_commands = (
);
my %ignorable_space_types;
-foreach my $type ('empty_line_after_command',
- 'empty_spaces_after_command', 'spaces_at_end',
- 'empty_spaces_before_argument', 'empty_spaces_before_paragraph',
- 'empty_spaces_after_close_brace') {
+foreach my $type ('ignorable_spaces_after_command',
+ 'spaces_at_end',
+ 'spaces_before_paragraph',
+ 'spaces_after_close_brace') {
$ignorable_space_types{$type} = 1;
}
my %ignored_types;
-foreach my $type ('preamble',
+foreach my $type ('preamble_before_beginning',
'preamble_before_setfilename') {
$ignored_types{$type} = 1;
}
@@ -297,7 +326,7 @@ my %non_quoted_commands_when_nested;
# if @documentencoding utf-8 is used.
foreach my $quoted_command (@quoted_commands) {
$style_map{$quoted_command} = ["'", "'"];
- if ($code_style_commands{$quoted_command}) {
+ if ($brace_code_commands{$quoted_command}) {
$non_quoted_commands_when_nested{$quoted_command} = 1;
}
}
@@ -319,24 +348,23 @@ for my $index_style_command ('strong', 'emph', 'sub', 'sup', 'key') {
# in those commands, there is no addition of double space after a dot.
# math is special
my %no_punctation_munging_commands;
-foreach my $command ('var', 'cite', 'dmn', keys(%code_style_commands)) {
+foreach my $command ('var', 'cite', 'dmn', keys(%brace_code_commands)) {
$no_punctation_munging_commands{$command} = 1;
}
my %defaults = (
'ENABLE_ENCODING' => 1,
+ 'ASCII_PUNCTUATION' => 0,
'FORMAT_MENU' => 'nomenu',
#'EXTENSION' => 'info',
'EXTENSION' => 'txt',
#'USE_SETFILENAME_EXTENSION' => 1,
- 'INFO_SPECIAL_CHARS_WARNING' => 1,
-
- #'OUTFILE' => undef,
+ 'INFO_SPECIAL_CHARS_WARNING' => undef,
+ # different from the default, which is undef
'OUTFILE' => '-',
- 'SUBDIR' => undef,
'documentlanguage' => undef,
- 'output_format' => '',
+ 'converted_format' => '',
'USE_NODES' => 1,
);
@@ -364,23 +392,11 @@ sub push_top_formatter($$)
$self->{'formatters'}->[-1]->{'_top_formatter'} = 1;
}
-
-my %contents_commands = (
- 'contents' => 1,
- 'shortcontents' => 1,
- 'summarycontents' => 1,
-);
-
sub converter_defaults($$)
{
return %defaults;
}
-sub converter_global_commands($)
-{
- return @informative_global_commands;
-}
-
sub converter_initialize($)
{
my $self = shift;
@@ -401,6 +417,8 @@ sub converter_initialize($)
= %default_preformatted_context_commands;
$self->{'footnote_index'} = 0;
$self->{'pending_footnotes'} = [];
+ $self->{'index_entry_node_colon'} = {};
+ $self->{'index_entries_no_node'} = {};
foreach my $format (keys(%format_raw_commands)) {
$self->{'ignored_commands'}->{$format} = 1
@@ -409,17 +427,22 @@ sub converter_initialize($)
%{$self->{'style_map'}} = %style_map;
$self->{'convert_text_options'}
- = {Texinfo::Common::_convert_text_options($self)};
+ = {Texinfo::Convert::Text::copy_options_for_convert_text($self)};
+
+ if ($self->get_conf('ASCII_PUNCTUATION')) {
+ $self->{'convert_text_options'}->{'ascii_punctuation'} = 1;
+ # cache to avoid calling get_conf
+ $self->{'ascii_punctuation'} = 1;
+ } else {
+ $self->{'ascii_punctuation'} = 0;
+ }
- if ($self->get_conf('ENABLE_ENCODING') and $self->get_conf('OUTPUT_ENCODING_NAME')
+ if ($self->get_conf('ENABLE_ENCODING')
+ and $self->get_conf('OUTPUT_ENCODING_NAME')
and $self->get_conf('OUTPUT_ENCODING_NAME') eq 'utf-8') {
# cache this to avoid redoing calls to get_conf
$self->{'to_utf8'} = 1;
- if (!$self->{'extra'}->{'documentencoding'}) {
- # Do not use curly quotes or some other unnecessary non-ASCII characters
- # if '@documentencoding UTF-8' is not given.
- $self->{'convert_text_options'}->{'no_extra_unicode'} = 1;
- } else {
+ if (!$self->{'ascii_punctuation'}) {
foreach my $quoted_command (@quoted_commands) {
# Directed single quotes
$self->{'style_map'}->{$quoted_command} = ["\x{2018}", "\x{2019}"];
@@ -444,6 +467,26 @@ sub converter_initialize($)
$self->{'fillcolumn'} = $self->get_conf('FILLCOLUMN');
# else it's already set via the defaults
}
+
+ if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
+ $self->{'info_special_chars_quote'}
+ = $self->get_conf('INFO_SPECIAL_CHARS_QUOTE');
+ if (!defined($self->get_conf('INFO_SPECIAL_CHARS_WARNING'))) {
+ $self->set_conf('INFO_SPECIAL_CHARS_WARNING', 0);
+ }
+ } else {
+ $self->{'info_special_chars_quote'} = '';
+ if (!defined($self->get_conf('INFO_SPECIAL_CHARS_WARNING'))) {
+ $self->set_conf('INFO_SPECIAL_CHARS_WARNING', 1);
+ }
+ }
+ if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
+ $self->{'info_special_chars_warning'}
+ = $self->get_conf('INFO_SPECIAL_CHARS_WARNING');
+ } else {
+ $self->{'info_special_chars_warning'} = '';
+ }
+
# This needs to be here to take into account $self->{'fillcolumn'}.
$self->push_top_formatter('_Root_context');
# some caching to avoid calling get_conf
@@ -459,33 +502,33 @@ sub converter_initialize($)
return $self;
}
-sub _count_context_bug_message($$$)
+sub count_context_bug_message($$$)
{
my ($self, $precision, $element) = @_;
if (scalar(@{$self->{'count_context'}}) != 1) {
my $element_text;
if ($element) {
- $element_text
- = Texinfo::Structuring::_print_element_command_texi($element);
+ $element_text
+ = Texinfo::Structuring::root_or_external_element_cmd_texi($element);
} else {
$element_text = '';
}
- $self->_bug_message("Too much count_context ${precision}(".
+ $self->present_bug_message("Too much count_context ${precision}(".
scalar(@{$self->{'count_context'}}). "): ". $element_text, $element);
die;
}
}
-sub _convert_element($$)
+sub _convert_root_element($$)
{
my ($self, $element) = @_;
my $result = '';
$result .= $self->_convert($element);
- $self->_count_context_bug_message('', $element);
- $result .= $self->_footnotes($element);
- $self->_count_context_bug_message('footnotes ', $element);
+ $self->count_context_bug_message('', $element);
+ $result .= $self->process_footnotes($element);
+ $self->count_context_bug_message('footnotes ', $element);
return $result;
}
@@ -496,17 +539,19 @@ sub convert($$)
my $result = '';
- my $elements = Texinfo::Structuring::split_by_node($root);
+ my $tree_units = Texinfo::Structuring::split_by_node($root);
+ $self->{'seenmenus'} = {};
$self->{'empty_lines_count'} = 1;
- if (!defined($elements)) {
+ $self->{'index_entries_line_location'} = {};
+ if (!defined($tree_units)) {
$result = $self->_convert($root);
- $self->_count_context_bug_message('no element ');
- my $footnotes = $self->_footnotes();
- $self->_count_context_bug_message('no element footnotes ');
+ $self->count_context_bug_message('no element ');
+ my $footnotes = $self->process_footnotes();
+ $self->count_context_bug_message('no element footnotes ');
$result .= $footnotes;
} else {
- foreach my $node (@$elements) {
- my $node_text = _convert_element($self, $node);
+ foreach my $node_root_element (@$tree_units) {
+ my $node_text = _convert_root_element($self, $node_root_element);
$result .= $node_text;
}
}
@@ -514,14 +559,24 @@ sub convert($$)
return $result;
}
+# the initialization of module specific state is not done in output()
+# as output() is generic, so it needs to be done here
sub convert_tree($$)
{
my ($self, $root) = @_;
- $self->{'empty_lines_count'} = 1;
+ if (!defined($self->{'empty_lines_count'})) {
+ # setting to 1 ensures that nothing is done, as there is
+ # something done (a newline added) if equal to 0.
+ $self->{'empty_lines_count'} = 1;
+ }
+ $self->{'seenmenus'} = {}
+ if (!$self->{'seenmenus'});
+ $self->{'index_entries_line_location'} = {}
+ if (!$self->{'index_entries_line_location'});
my $result;
- if ($root->{'type'} and $root->{'type'} eq 'element') {
- $result = _convert_element($self, $root);
+ if ($root->{'type'} and $root->{'type'} eq 'unit') {
+ $result = _convert_root_element($self, $root);
} else {
$result = $self->_convert($root);
}
@@ -535,20 +590,18 @@ sub _protect_sentence_ends ($) {
my $text = shift;
# Avoid suppressing end of sentence, by inserting a control character
# in front of the full stop. The choice of BS for this is arbitrary.
- $text =~ s/(?<=[^[:upper:]])
+ $text =~ s/(?<=[^\p{Upper}])
(?=[$end_sentence][$after_punctuation]*(?:\s|$))
- /\x08/gx;
+ /\x08/xg;
# Also insert a control character at end of string, to protect a full stop
# that may follow later.
- #$text =~ s/(?<=[^[:upper:]][$after_punctuation]*)$/\x08/;
+ #$text =~ s/(?<=[^\p{Upper}\s][$after_punctuation]*)$/\x08/;
# Perl doesn't support "variable length lookbehind"
$text = reverse $text;
- $text =~ s/^(?=[$after_punctuation]*
- (?:[^[:upper:]\s]|[\x{202f}\x{00a0}]))
- /\x08/x;
+ $text =~ s/^(?=[$after_punctuation]*(?:[^\p{Upper}\s]))/\x08/;
$text = reverse $text;
return $text;
@@ -582,7 +635,7 @@ sub _process_text($$$)
}
if ($self->{'to_utf8'}
- and $self->{'extra'}->{'documentencoding'}) {
+ and !$self->{'ascii_punctuation'}) {
return Texinfo::Convert::Unicode::unicode_text($text,
$context->{'font_type_stack'}->[-1]->{'monospace'});
} elsif (!$context->{'font_type_stack'}->[-1]->{'monospace'}) {
@@ -595,8 +648,11 @@ sub new_formatter($$;$)
{
my ($self, $type, $conf) = @_;
- my $first_indent_length = $conf->{'first_indent_length'};
- delete $conf->{'first_indent_length'};
+ my $first_indent_length;
+ if ($conf) {
+ $first_indent_length = $conf->{'first_indent_length'};
+ delete $conf->{'first_indent_length'};
+ }
my $container;
my $container_conf = {
@@ -605,6 +661,9 @@ sub new_formatter($$;$)
};
$container_conf->{'frenchspacing'} = 1
if ($self->{'conf'}->{'frenchspacing'} eq 'on');
+ #if ($self->get_conf('frenchspacing') eq 'on');
+ # access 'conf' hash directly for efficiency
+
$container_conf->{'counter'}
= $self->{'text_element_context'}->[-1]->{'counter'}
if (defined($self->{'text_element_context'}->[-1]->{'counter'}));
@@ -655,7 +714,15 @@ sub new_formatter($$;$)
'font_type_stack' => [{}],
'w' => 0, 'type' => $type,
'frenchspacing_stack' => [$self->{'conf'}->{'frenchspacing'}],
- 'suppress_styles' => $conf->{'suppress_styles'}};
+ #'frenchspacing_stack' => [$self->get_conf('frenchspacing')],
+ # access 'conf' hash directly for efficiency
+ 'suppress_styles' => undef,
+ 'no_added_eol' => undef};
+ if ($conf) {
+ foreach my $configuration ('suppress_styles', 'no_added_eol') {
+ $formatter->{$configuration} = $conf->{$configuration};
+ }
+ }
if ($type eq 'unfilled') {
foreach my $context (reverse(@{$self->{'context'}})) {
@@ -675,6 +742,31 @@ sub new_formatter($$;$)
return $formatter;
}
+# intercept messages, in case some Texinfo is processed twice
+sub converter_line_warn($$$$)
+{
+ my $self = shift;
+ my $configuration_information = shift;
+ my $text = shift;
+ my $error_location_info = shift;
+
+ if (!$self->{'silent'}) {
+ $self->line_warn($configuration_information, $text, $error_location_info);
+ }
+}
+
+sub converter_line_error($$$$)
+{
+ my $self = shift;
+ my $configuration_information = shift;
+ my $text = shift;
+ my $error_location_info = shift;
+
+ if (!$self->{'silent'}) {
+ $self->line_error($configuration_information, $text, $error_location_info);
+ }
+}
+
sub convert_line($$;$)
{
my ($self, $converted, $conf) = @_;
@@ -687,7 +779,7 @@ sub convert_line($$;$)
return $text;
}
-sub convert_unfilled($$;$)
+sub _convert_unfilled($$;$)
{
my ($self, $converted, $conf) = @_;
my $formatter = $self->new_formatter('unfilled', $conf);
@@ -708,7 +800,7 @@ sub count_bytes($$)
$self->{'output_perl_encoding'});
}
-sub _add_text_count($$)
+sub add_text_to_count($$)
{
my ($self, $text) = @_;
if (!$self->{'count_context'}->[-1]->{'pending_text'}) {
@@ -725,8 +817,8 @@ sub _add_lines_count($$)
# Update $SELF->{'count_context'}->[-1]->{'bytes'} by counting the text that
# hasn't been counted yet. It is faster to count the text all together than
-# piece by piece in _add_text_count.
-sub _update_count_context($)
+# piece by piece in add_text_to_count.
+sub update_count_context($)
{
my $self = shift;
if ($self->{'count_context'}->[-1]->{'pending_text'}) {
@@ -738,33 +830,31 @@ sub _update_count_context($)
}
}
-# Save the line and byte offset of $ROOT.
-sub _add_location($$)
+# Save the line and byte offset of $ELEMENT.
+sub add_location($$)
{
- my ($self, $root) = @_;
+ my ($self, $element) = @_;
my $location = { 'lines' => $self->{'count_context'}->[-1]->{'lines'} };
push @{$self->{'count_context'}->[-1]->{'locations'}}, $location;
- if (!($root->{'extra'} and $root->{'extra'}->{'index_entry'})) {
- _update_count_context($self);
+ if (!($element->{'extra'} and $element->{'extra'}->{'index_entry'})) {
+ update_count_context($self);
$location->{'bytes'} = $self->{'count_context'}->[-1]->{'bytes'};
- $location->{'root'} = $root;
+ $location->{'root'} = $element;
} else {
- $location->{'index_entry'} = $root;
+ $location->{'index_entry'} = $element;
}
return $location;
}
-sub _add_image($$$$;$)
+sub add_image($$$$;$)
{
- my ($self, $root, $lines_count, $image_width, $no_align) = @_;
+ my ($self, $element, $lines_count, $image_width, $no_align) = @_;
push @{$self->{'count_context'}->[-1]->{'images'}}, {
'lines' => $self->{'count_context'}->[-1]->{'lines'},
'lines_count' => $lines_count,
'image_width' => $image_width,
'no_align' => $no_align,
- # may be used for debugging?
- #'_ref' => $root,
};
}
@@ -787,7 +877,7 @@ sub _update_locations_counts($$)
{
my ($self, $locations) = @_;
- _update_count_context($self);
+ update_count_context($self);
foreach my $location (@$locations) {
$location->{'bytes'} += $self->{'count_context'}->[-1]->{'bytes'}
if (defined($location->{'bytes'}));
@@ -800,7 +890,7 @@ sub _add_newline_if_needed($) {
my $self = shift;
if (defined($self->{'empty_lines_count'})
and $self->{'empty_lines_count'} == 0) {
- _add_text_count($self, "\n");
+ add_text_to_count($self, "\n");
_add_lines_count($self, 1);
$self->{'empty_lines_count'} = 1;
return "\n";
@@ -808,12 +898,40 @@ sub _add_newline_if_needed($) {
return '';
}
+sub _open_code($)
+{
+ my $formatter = shift;
+
+ if (!$formatter->{'font_type_stack'}->[-1]->{'monospace'}) {
+ push @{$formatter->{'font_type_stack'}}, {'monospace' => 1};
+ } else {
+ $formatter->{'font_type_stack'}->[-1]->{'monospace'}++;
+ }
+ push @{$formatter->{'frenchspacing_stack'}}, 'on';
+ set_space_protection($formatter->{'container'}, undef, undef, undef, 1);
+}
+
+sub _close_code($)
+{
+ my $formatter = shift;
+
+ $formatter->{'font_type_stack'}->[-1]->{'monospace'}--;
+ pop @{$formatter->{'font_type_stack'}}
+ if !$formatter->{'font_type_stack'}->[-1]->{'monospace'};
+ pop @{$formatter->{'frenchspacing_stack'}};
+ my $frenchspacing = 0;
+ $frenchspacing = 1 if ($formatter->{'frenchspacing_stack'}->[-1] eq 'on');
+ set_space_protection($formatter->{'container'}, undef,
+ undef, undef, $frenchspacing);
+}
+
my $footnote_indent = 3;
-sub _footnotes($;$)
+sub process_footnotes($;$)
{
my ($self, $element) = @_;
- $element = undef if ($element and $element->{'extra'}->{'no_node'});
+ $element = undef if ($element and (not defined ($element->{'extra'})
+ or not defined $element->{'extra'}->{'unit_command'}));
my $result = '';
if (scalar(@{$self->{'pending_footnotes'}})) {
@@ -821,33 +939,33 @@ sub _footnotes($;$)
if ($self->get_conf('footnotestyle') eq 'end' or !defined($element)) {
my $footnotes_header = " ---------- Footnotes ----------\n\n";
$result .= $footnotes_header;
- _add_text_count($self, $footnotes_header);
+ add_text_to_count($self, $footnotes_header);
_add_lines_count($self, 2);
$self->{'empty_lines_count'} = 1;
} else {
- my $node_contents = [@{$element->{'extra'}->{'node'}->{'extra'}->{'node_content'}},
+ my $node_contents = [@{$element->{'extra'}->{'unit_command'}->{'extra'}->{'node_content'}},
{'text' => '-Footnotes'}];
my $footnotes_node = {
'cmdname' => 'node',
- 'node_up' => $element->{'extra'}->{'node'},
+ 'structure' => {'node_up' => $element->{'extra'}->{'unit_command'}},
'extra' => {'node_content' => $node_contents }
};
- $result .= $self->_node($footnotes_node);
- $self->{'node'} = $footnotes_node;
+ $result .= $self->format_node($footnotes_node);
+ $self->{'current_node'} = $footnotes_node;
}
while (@{$self->{'pending_footnotes'}}) {
my $footnote = shift (@{$self->{'pending_footnotes'}});
# If nested within another footnote and footnotestyle is separate,
# the element here will be the parent element and not the footnote
- # element, while the pxref will point to the name with the
+ # element, while the pxref will point to the name with the
# footnote node taken into account. Not really problematic as
# nested footnotes are not right.
if ($element) {
- my $node_contents = [@{$element->{'extra'}->{'node'}->{'extra'}->{'node_content'}},
+ my $node_contents = [@{$element->{'extra'}->{'unit_command'}->{'extra'}->{'node_content'}},
{'text' => "-Footnote-$footnote->{'number'}"}];
- $self->_add_location({'cmdname' => 'anchor',
+ $self->add_location({'cmdname' => 'anchor',
'extra' => {'node_content' => $node_contents }
});
}
@@ -863,9 +981,9 @@ sub _footnotes($;$)
my $footnote_text = ' ' x $footnote_indent
. "($formatted_footnote_number) ";
$result .= $footnote_text;
- $self->{'text_element_context'}->[-1]->{'counter'} +=
+ $self->{'text_element_context'}->[-1]->{'counter'} +=
Texinfo::Convert::Unicode::string_width($footnote_text);
- _add_text_count($self, $footnote_text);
+ add_text_to_count($self, $footnote_text);
$self->{'empty_lines_count'} = 0;
$result .= $self->_convert($footnote->{'root'}->{'args'}->[0]);
@@ -922,7 +1040,7 @@ sub _align_lines($$$$$$)
}# else {
# Happens in Info with the special construct as, in that
# case, there are no lines! So no error...
- # $self->_bug_message("more than one image with lines on $image->{'lines'}");
+ # $self->present_bug_message("more than one image with lines on $image->{'lines'}");
# in that case, the $image->{'lines'} is not in sync with the
# lines count. So the second image will be treated as simple text.
#}
@@ -1021,7 +1139,7 @@ sub _align_environment($$$$)
{
my ($self, $result, $max, $align) = @_;
- _update_count_context($self);
+ update_count_context($self);
my $counts = pop @{$self->{'count_context'}};
my $bytes_count;
($result, $bytes_count) = $self->_align_lines($result, $max,
@@ -1034,42 +1152,45 @@ sub _align_environment($$$$)
return $result;
}
-sub _contents($$$)
+sub format_contents($$$)
{
my ($self, $section_root, $contents_or_shortcontents) = @_;
my $contents = 1 if ($contents_or_shortcontents eq 'contents');
# no sections
- return ('', 0) if (!$section_root or !$section_root->{'section_childs'});
- my $root_level = $section_root->{'section_childs'}->[0]->{'level'};
- foreach my $top_section(@{$section_root->{'section_childs'}}) {
- $root_level = $top_section->{'level'}
- if ($top_section->{'level'} < $root_level);
+ return ('', 0) if (!$section_root
+ or !$section_root->{'structure'}->{'section_childs'});
+ my $root_level = $section_root->{'structure'}->{'section_childs'}->[0]
+ ->{'structure'}->{'section_level'};
+ foreach my $top_section (@{$section_root->{'structure'}->{'section_childs'}}) {
+ $root_level = $top_section->{'structure'}->{'section_level'}
+ if ($top_section->{'structure'}->{'section_level'} < $root_level);
}
my $result = '';
my $lines_count = 0;
# This is done like that because the tree may not be well formed if
# there is a @part after a @chapter for example.
- foreach my $top_section (@{$section_root->{'section_childs'}}) {
+ foreach my $top_section (@{$section_root->{'structure'}->{'section_childs'}}) {
my $section = $top_section;
SECTION:
while ($section) {
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
my $section_title_tree;
- if (defined($section->{'number'})
+ if (defined($section->{'structure'}->{'section_number'})
and ($self->get_conf('NUMBER_SECTIONS')
or !defined($self->get_conf('NUMBER_SECTIONS')))) {
- if ($section->{'cmdname'} eq 'appendix' and $section->{'level'} == 1) {
+ if ($section->{'cmdname'} eq 'appendix'
+ and $section->{'structure'}->{'section_level'} == 1) {
$section_title_tree = $self->gdt('Appendix {number} {section_title}',
- {'number' => {'text' => $section->{'number'}},
- 'section_title'
+ {'number' => {'text' => $section->{'structure'}->{'section_number'}},
+ 'section_title'
=> {'contents' => $section->{'args'}->[0]->{'contents'}}});
} else {
$section_title_tree = $self->gdt('{number} {section_title}',
- {'number' => {'text' => $section->{'number'}},
- 'section_title'
+ {'number' => {'text' => $section->{'structure'}->{'section_number'}},
+ 'section_title'
=> {'contents' => $section->{'args'}->[0]->{'contents'}}});
}
} else {
@@ -1082,23 +1203,23 @@ sub _contents($$$)
my $text = $section_title;
chomp ($text);
$text .= "\n";
- my $repeat_count = 2 * ($section->{'level'} - ($root_level+1));
+ my $repeat_count = 2 * ($section->{'structure'}->{'section_level'} - ($root_level+1));
($result .= (' ' x $repeat_count)) if $repeat_count > 0;
$result .= $text;
$lines_count++;
- if ($section->{'section_childs'}
- and ($contents or $section->{'level'} < $root_level+1)) {
- $section = $section->{'section_childs'}->[0];
- } elsif ($section->{'section_next'}) {
+ if ($section->{'structure'}->{'section_childs'}
+ and ($contents or $section->{'structure'}->{'section_level'} < $root_level+1)) {
+ $section = $section->{'structure'}->{'section_childs'}->[0];
+ } elsif ($section->{'structure'}->{'section_next'}) {
last if ($section eq $top_section);
- $section = $section->{'section_next'};
+ $section = $section->{'structure'}->{'section_next'};
} else {
last if ($section eq $top_section);
- while ($section->{'section_up'}) {
- $section = $section->{'section_up'};
+ while ($section->{'structure'}->{'section_up'}) {
+ $section = $section->{'structure'}->{'section_up'};
last SECTION if ($section eq $top_section);
- if ($section->{'section_next'}) {
- $section = $section->{'section_next'};
+ if ($section->{'structure'}->{'section_next'}) {
+ $section = $section->{'structure'}->{'section_next'};
last;
}
}
@@ -1114,10 +1235,10 @@ sub _menu($$)
if ($menu_command->{'cmdname'} eq 'menu') {
my $result = "* Menu:\n\n";
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
_add_lines_count($self, 2);
- if ($self->{'node'}) {
- $self->{'seenmenus'}->{$self->{'node'}} = 1;
+ if ($self->{'current_node'}) {
+ $self->{'seenmenus'}->{$self->{'current_node'}} = 1;
}
return $result;
} else {
@@ -1125,30 +1246,32 @@ sub _menu($$)
}
}
-sub _printindex($$)
+sub format_printindex($$)
{
my ($self, $printindex) = @_;
- return $self->_printindex_formatted($printindex);
+ return $self->process_printindex($printindex);
}
sub _normalize_top_node($)
{
- my $node = shift;
- return Texinfo::Common::normalize_top_node_name($node);
+ my $node_name = shift;
+ return Texinfo::Common::normalize_top_node_name($node_name);
}
# convert and cache a node name. $NODE is a node element.
-sub _node_line($$)
+sub node_line($$)
{
my ($self, $node) = @_;
+ $self->{'node_lines_text'} = {} if (!$self->{'node_lines_text'});
if (!$self->{'node_lines_text'}->{$node}) {
my $node_text = {'type' => '_code',
'contents' => $node->{'extra'}->{'node_content'}};
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
- $self->{'node_lines_text'}->{$node}->{'text'}
- = _normalize_top_node($self->convert_line($node_text,
- {'suppress_styles' => 1}));
- _update_count_context($self);
+ $self->{'node_lines_text'}->{$node}
+ = {'text' => _normalize_top_node($self->convert_line($node_text,
+ {'suppress_styles' => 1,
+ 'no_added_eol' => 1,}))};
+ update_count_context($self);
my $end_context = pop @{$self->{'count_context'}};
$self->{'node_lines_text'}->{$node}->{'count'}
= $end_context->{'bytes'};
@@ -1159,7 +1282,7 @@ sub _node_line($$)
my $index_length_to_node = 41;
-sub _printindex_formatted($$;$)
+sub process_printindex($$;$)
{
my ($self, $printindex, $in_info) = @_;
@@ -1173,47 +1296,41 @@ sub _printindex_formatted($$;$)
}
# this is not redone for each index, only once
- if (!defined($self->{'index_entries'}) and $self->{'parser'}) {
+ my $index_names = $self->{'indices_information'};
+ if (!defined($self->{'index_entries'}) and $index_names) {
- my $index_names = $self->{'parser'}->indices_information();
my $merged_index_entries
= Texinfo::Structuring::merge_indices($index_names);
- $self->{'index_entries'}
- = Texinfo::Structuring::sort_indices($self->{'parser'},
- $merged_index_entries, $index_names);
- $self->{'index_names'} = $index_names;
+ my $index_entries_sort_strings;
+ ($self->{'index_entries'}, $index_entries_sort_strings)
+ = Texinfo::Structuring::sort_indices($self, $self,
+ $merged_index_entries);
}
if (!$self->{'index_entries'} or !$self->{'index_entries'}->{$index_name}
or ! @{$self->{'index_entries'}->{$index_name}}) {
return '';
}
- my $result = '';
- $result .= _add_newline_if_needed($self);
- if ($in_info) {
- my $info_printindex_magic = "\x{00}\x{08}[index\x{00}\x{08}]\n";
- $result .= $info_printindex_magic;
- _add_text_count($self, $info_printindex_magic);
- _add_lines_count($self, 1);
- }
- my $heading = "* Menu:\n\n";
-
- $result .= $heading;
- _add_text_count($self, $heading);
- _add_lines_count($self, 2);
-
# first determine the line numbers for the spacing of their formatting
my %line_nrs;
my %entry_nodes;
my $max_index_line_nr_string_length = 0;
my %ignored_entries;
foreach my $entry (@{$self->{'index_entries'}->{$index_name}}) {
+ # FIXME format in a way instead of ignoring
+ if ($entry->{'entry_element'}->{'extra'}
+ and ($entry->{'entry_element'}->{'extra'}->{'seeentry'}
+ or $entry->{'entry_element'}->{'extra'}->{'seealso'})) {
+ $ignored_entries{$entry} = 1;
+ next;
+ }
my $line_nr;
- if (defined ($self->{'index_entries_line_location'}->{$entry->{'command'}})) {
- $line_nr = $self->{'index_entries_line_location'}->{$entry->{'command'}}->{'lines'};
+ if ($self->{'index_entries_line_location'}
+ and defined($self->{'index_entries_line_location'}->{$entry->{'entry_element'}})) {
+ $line_nr = $self->{'index_entries_line_location'}->{$entry->{'entry_element'}}->{'lines'};
# ignore index entries in special regions that haven't been seen
- } elsif ($entry->{'region'}) {
+ } elsif ($entry->{'entry_region'}) {
$ignored_entries{$entry} = 1;
next;
}
@@ -1221,10 +1338,12 @@ sub _printindex_formatted($$;$)
my $node;
# priority given to the location determined dynamically as the
# index entry may be in footnote.
- if (defined($self->{'index_entries_line_location'}->{$entry->{'command'}}->{'node'})) {
- $node = $self->{'index_entries_line_location'}->{$entry->{'command'}}->{'node'};
- } elsif (defined($entry->{'node'})) {
- $node = $entry->{'node'};
+ if ($self->{'index_entries_line_location'}
+ and $self->{'index_entries_line_location'}->{$entry->{'entry_element'}}
+ and defined($self->{'index_entries_line_location'}->{$entry->{'entry_element'}}->{'node'})) {
+ $node = $self->{'index_entries_line_location'}->{$entry->{'entry_element'}}->{'node'};
+ } elsif (defined($entry->{'entry_node'})) {
+ $node = $entry->{'entry_node'};
}
$entry_nodes{$entry} = $node;
if (!defined($node)) {
@@ -1242,36 +1361,65 @@ sub _printindex_formatted($$;$)
$line_nrs{$entry} = $line_nr;
}
+ return '' if (scalar(keys(%line_nrs)) == 0);
+
+ my $result = '';
+ $result .= _add_newline_if_needed($self);
+ if ($in_info) {
+ my $info_printindex_magic = "\x{00}\x{08}[index\x{00}\x{08}]\n";
+ $result .= $info_printindex_magic;
+ add_text_to_count($self, $info_printindex_magic);
+ _add_lines_count($self, 1);
+ }
+ my $heading = "* Menu:\n\n";
+
+ $result .= $heading;
+ add_text_to_count($self, $heading);
+ _add_lines_count($self, 2);
+
# this is used to count entries that are the same
my %entry_counts = ();
+ # Use the same line formatter for all the index entries. This is
+ # slightly faster than making a new one for each entry.
+ my $formatter = $self->new_formatter('line',
+ {'indent' => 0, 'suppress_styles' => 1,
+ 'no_added_eol' => 1});
+ push @{$self->{'formatters'}}, $formatter;
+
foreach my $entry (@{$self->{'index_entries'}->{$index_name}}) {
next if ($ignored_entries{$entry});
- my $entry_tree = {'contents' => $entry->{'content'}};
+ my $entry_tree = {'contents' => $entry->{'entry_content'}};
+ my $subentries_tree = $self->comma_index_subentries_tree($entry);
if ($entry->{'in_code'}) {
$entry_tree->{'type'} = '_code';
+ $subentries_tree->{'type'} = '_code'
+ if (defined($subentries_tree));
} else {
$entry_tree->{'type'} = 'frenchspacing';
+ $subentries_tree->{'type'} = 'frenchspacing'
+ if (defined($subentries_tree));
}
my $entry_text = '';
- my $formatter = $self->new_formatter('line',
- {'indent' => 0, 'suppress_styles' => 1});
- push @{$self->{'formatters'}}, $formatter;
$entry_text = $self->_convert($entry_tree);
- $entry_text .= $self->convert_index_subentries($entry);
+ $entry_text .= $self->_convert($subentries_tree)
+ if (defined($subentries_tree));
+
$entry_text .= _count_added($self, $formatter->{'container'},
Texinfo::Convert::Paragraph::end($formatter->{'container'}));
- pop @{$self->{'formatters'}};
-
next if ($entry_text !~ /\S/);
- # FIXME protect instead
+ # No need for protection, the Info readers should find the last : on
+ # the line. : in the node following the index entry node should be
+ # protected, however, as done below, such that : in the node are not
+ # mistaken as being part of the index entry.
if ($entry_text =~ /:/ and $self->get_conf('INDEX_SPECIAL_CHARS_WARNING')) {
- $self->line_warn (sprintf(__("Index entry in \@%s with : produces invalid Info: %s"),
- $entry->{'index_at_command'},
- Texinfo::Convert::Texinfo::convert($entry_tree)),
- $entry->{'command'}->{'line_nr'});
+ $self->converter_line_warn ($self,
+ sprintf(__("Index entry in \@%s with : produces invalid Info: %s"),
+ $entry->{'index_at_command'},
+ Texinfo::Convert::Texinfo::convert_to_texinfo($entry_tree)),
+ $entry->{'entry_element'}->{'source_info'});
}
my $entry_nr = '';
@@ -1280,18 +1428,17 @@ sub _printindex_formatted($$;$)
} else {
$entry_counts{$entry_text}++;
$entry_nr = ' <'.$entry_counts{$entry_text}.'>';
- _add_text_count($self, $entry_nr);
+ add_text_to_count($self, $entry_nr);
}
my $entry_line = "* $entry_text${entry_nr}: ";
- _add_text_count($self, "* ".": ");
- #_add_text_count($self, $entry_line);
+ add_text_to_count($self, "* ".": ");
my $line_width = Texinfo::Convert::Unicode::string_width($entry_line);
my $entry_line_addition = '';
if ($line_width < $index_length_to_node) {
my $spaces = ' ' x ($index_length_to_node - $line_width);
$entry_line_addition .= $spaces;
- _add_text_count($self, $spaces);
+ add_text_to_count($self, $spaces);
}
my $node = $entry_nodes{$entry};
@@ -1301,9 +1448,9 @@ sub _printindex_formatted($$;$)
if (!$self->{'outside_of_any_node_text'}) {
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
my $node_text = $self->gdt('(outside of any node)');
- $self->{'outside_of_any_node_text'}->{'text'}
- = $self->convert_line($node_text);
- _update_count_context($self);
+ $self->{'outside_of_any_node_text'}
+ = {'text' => $self->convert_line($node_text)};
+ update_count_context($self);
my $end_context = pop @{$self->{'count_context'}};
$self->{'outside_of_any_node_text'}->{'count'}
= $end_context->{'bytes'};
@@ -1315,17 +1462,40 @@ sub _printindex_formatted($$;$)
# done by the Parser.
# Warn, only once.
if (!$self->{'index_entries_no_node'}->{$entry}) {
- $self->line_warn(sprintf(__("entry for index `%s' outside of any node"),
- $index_name), $entry->{'command'}->{'line_nr'});
+ $self->converter_line_warn($self,
+ sprintf(__("entry for index `%s' outside of any node"),
+ $index_name), $entry->{'entry_element'}->{'source_info'});
$self->{'index_entries_no_node'}->{$entry} = 1;
}
} else {
- my ($node_line, $byte_count) = $self->_node_line($node);
- $entry_line_addition .= $node_line;
+ my ($node_line, $byte_count) = $self->node_line($node);
$self->{'count_context'}->[-1]->{'bytes'} += $byte_count;
+ # protect characters that need to be protected in menu node entry
+ # after menu entry name and also :, as the Info readers
+ # should consider text up to : to be part of the index entry.
+ if ($node_line =~ /([,\t:]|\.\s)/) {
+ my $warned_char = $1;
+ if ($self->{'info_special_chars_warning'}) {
+ # Warn only once
+ if (! $self->{'index_entry_node_colon'}->{$node_line}) {
+ $self->converter_line_warn($self, sprintf(__(
+ "node name with index entries should not contain `%s'"),
+ $warned_char),
+ $node->{'source_info'});
+ }
+ $self->{'index_entry_node_colon'}->{$node_line} = 1;
+ }
+ if ($self->{'info_special_chars_quote'}) {
+ my $pre_quote = "\x{7f}";
+ my $post_quote = $pre_quote;
+ $self->{'count_context'}->[-1]->{'bytes'} += 2;
+ $node_line = $pre_quote . $node_line . $post_quote;
+ }
+ }
+ $entry_line_addition .= $node_line;
}
$entry_line_addition .= '.';
- _add_text_count($self, '.');
+ add_text_to_count($self, '.');
$entry_line .= $entry_line_addition;
$result .= $entry_line;
@@ -1345,19 +1515,21 @@ sub _printindex_formatted($$;$)
. "$line_part\n";
}
_add_lines_count($self, 1);
- _add_text_count($self, $line_part);
+ add_text_to_count($self, $line_part);
$result .= $line_part;
}
+ pop @{$self->{'formatters'}};
+
$result .= "\n";
- _add_text_count($self, "\n");
+ add_text_to_count($self, "\n");
_add_lines_count($self, 1);
return $result;
}
-sub _node($$)
+sub format_node($$)
{
my $self = shift;
my $node = shift;
@@ -1366,10 +1538,10 @@ sub _node($$)
}
# no error in plaintext
-sub _error_outside_of_any_node($$)
+sub format_error_outside_of_any_node($$)
{
my $self = shift;
- my $root = shift;
+ my $element = shift;
}
sub _anchor($$)
@@ -1378,8 +1550,8 @@ sub _anchor($$)
my $anchor = shift;
if (!($self->{'multiple_pass'} or $self->{'in_copying_header'})) {
- $self->_add_location($anchor);
- $self->_error_outside_of_any_node($anchor);
+ $self->add_location($anchor);
+ $self->format_error_outside_of_any_node($anchor);
}
return '';
}
@@ -1398,80 +1570,45 @@ sub ensure_end_of_line($$)
}
$text .= "\n";
$self->{'text_element_context'}->[-1]->{'counter'} = 0;
- _add_text_count($self, "\n");
+ add_text_to_count($self, "\n");
_add_lines_count($self, 1);
return $text;
}
-sub _image_text($$$)
+sub image_formatted_text($$$$)
{
- my ($self, $root, $basefile) = @_;
-
- my $txt_file = $self->Texinfo::Common::locate_include_file($basefile.'.txt');
- if (!defined($txt_file)) {
- return undef;
- } else {
- my $filehandle = do { local *FH };
- if (open ($filehandle, $txt_file)) {
- my $enc = $root->{'extra'}->{'input_perl_encoding'};
- binmode($filehandle, ":encoding($enc)")
- if ($enc);
- my $result = '';
- my $max_width = 0;
- while (<$filehandle>) {
- my $width = Texinfo::Convert::Unicode::string_width($_);
- if ($width > $max_width) {
- $max_width = $width;
- }
- $result .= $_;
- }
- # remove last end of line
- chomp ($result);
- if (!close ($filehandle)) {
- $self->document_warn(sprintf(__("error on closing image text file %s: %s"),
- $txt_file, $!));
- }
- return ($result, $max_width);
- } else {
- $self->line_warn(sprintf(__("\@image file `%s' unreadable: %s"),
- $txt_file, $!), $root->{'line_nr'});
- }
- }
- return undef;
-}
-
-sub _image_formatted_text($$$$)
-{
- my ($self, $root, $basefile, $text) = @_;
+ my ($self, $element, $basefile, $text) = @_;
my $result;
if (defined($text)) {
$result = $text;
- } elsif (defined($root->{'args'}->[3])
- and @{$root->{'args'}->[3]->{'contents'}}) {
- $result = '[' .Texinfo::Convert::Text::convert(
- {'contents' => $root->{'args'}->[3]->{'contents'}},
+ } elsif (defined($element->{'args'}->[3])
+ and $element->{'args'}->[3]->{'contents'}
+ and @{$element->{'args'}->[3]->{'contents'}}) {
+ $result = '[' .Texinfo::Convert::Text::convert_to_text(
+ {'contents' => $element->{'args'}->[3]->{'contents'}},
$self->{'convert_text_options'}) .']';
} else {
- $self->line_warn(sprintf(__(
+ $self->converter_line_warn($self, sprintf(__(
"could not find \@image file `%s.txt' nor alternate text"),
- $basefile), $root->{'line_nr'});
+ $basefile), $element->{'source_info'});
$result = '['.$basefile.']';
}
return $result;
}
-sub _image($$)
+sub format_image($$)
{
- my ($self, $root) = @_;
+ my ($self, $element) = @_;
- if (defined($root->{'args'}->[0])
- and @{$root->{'args'}->[0]->{'contents'}}) {
- my $basefile = Texinfo::Convert::Text::convert(
- {'contents' => $root->{'args'}->[0]->{'contents'}},
+ if (defined($element->{'args'}->[0])
+ and $element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}) {
+ my $basefile = Texinfo::Convert::Text::convert_to_text(
+ {'contents' => $element->{'args'}->[0]->{'contents'}},
{'code' => 1, %{$self->{'convert_text_options'}}});
- my ($text, $width) = $self->_image_text($root, $basefile);
- my $result = $self->_image_formatted_text($root, $basefile, $text);
+ my ($text, $width) = $self->txt_image_text($element, $basefile);
+ my $result = $self->image_formatted_text($element, $basefile, $text);
my $lines_count = ($result =~ tr/\n/\n/);
if (!defined($width)) {
$width = Texinfo::Convert::Unicode::string_width($result);
@@ -1479,7 +1616,7 @@ sub _image($$)
# the last line is part of the image but do not have a new line,
# so 1 is added to $lines_count to have the number of lines of
# the image
- $self->_add_image($root, $lines_count+1, $width);
+ $self->add_image($element, $lines_count+1, $width);
return ($result, $lines_count);
}
return ('', 0);
@@ -1498,35 +1635,39 @@ sub _convert($$);
# Convert the Texinfo tree under $ROOT to plain text.
sub _convert($$)
{
- my ($self, $root) = @_;
+ my ($self, $element) = @_;
my $formatter = $self->{'formatters'}->[-1];
- if (($root->{'type'} and $self->{'ignored_types'}->{$root->{'type'}})
- or ($root->{'cmdname'}
- and ($self->{'ignored_commands'}->{$root->{'cmdname'}}
- or ($inline_commands{$root->{'cmdname'}}
- and $root->{'cmdname'} ne 'inlinefmtifelse'
- and (($inline_format_commands{$root->{'cmdname'}}
- and (!$root->{'extra'}->{'format'}
- or !$self->{'expanded_formats_hash'}->{$root->{'extra'}->{'format'}}))
- or (!$inline_format_commands{$root->{'cmdname'}}
- and !defined($root->{'extra'}->{'expand_index'}))))))) {
+ if (($element->{'type'} and $self->{'ignored_types'}->{$element->{'type'}})
+ or ($element->{'cmdname'}
+ and ($self->{'ignored_commands'}->{$element->{'cmdname'}}
+ or ($brace_commands{$element->{'cmdname'}}
+ and $brace_commands{$element->{'cmdname'}} eq 'inline'
+ and $element->{'cmdname'} ne 'inlinefmtifelse'
+ and (($inline_format_commands{$element->{'cmdname'}}
+ and (!$element->{'extra'}->{'format'}
+ or !$self->{'expanded_formats_hash'}->{$element->{'extra'}->{'format'}}))
+ or (!$inline_format_commands{$element->{'cmdname'}}
+ and !defined($element->{'extra'}->{'expand_index'}))))))) {
return '';
}
my $result = '';
- my $type = $root->{'type'};
- my $command = $root->{'cmdname'};
+ my $type = $element->{'type'};
+ my $command = $element->{'cmdname'};
# in ignorable spaces, keep only form feeds.
if ($type and $self->{'ignorable_space_types'}->{$type}
- and ($type ne 'empty_spaces_before_paragraph'
+ and ($type ne 'spaces_before_paragraph'
or $self->get_conf('paragraphindent') ne 'asis')) {
- if ($root->{'text'} =~ /\f/) {
- $result = _get_form_feeds($root->{'text'});
+ if ($type eq 'spaces_after_close_brace'
+ and $element->{'text'} =~ /\f/) {
+ # FIXME also in spaces_before_paragraph? Does not seems to be
+ # relevant to keep form feeds in other ignorable spaces.
+ $result = _get_form_feeds($element->{'text'});
}
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
return $result;
}
@@ -1534,15 +1675,15 @@ sub _convert($$)
# of text below to be sure that an empty line is always processed
# especially
if ($type and ($type eq 'empty_line'
- or $type eq 'after_description_line')) {
+ or $type eq 'after_menu_description_line')) {
delete $self->{'text_element_context'}->[-1]->{'counter'};
$self->{'empty_lines_count'}++;
if ($self->{'empty_lines_count'} <= 1
or $self->{'preformatted_context_commands'}->{$self->{'context'}->[-1]}) {
$result = "";
- if ($root->{'text'} =~ /\f/) {
- $result .= _get_form_feeds($root->{'text'});
- _add_text_count($self, $result);
+ if ($element->{'text'} =~ /\f/) {
+ $result .= _get_form_feeds($element->{'text'});
+ add_text_to_count($self, $result);
}
$result .= _count_added($self, $formatter->{'container'},
add_text($formatter->{'container'}, "\n"));
@@ -1553,49 +1694,48 @@ sub _convert($$)
}
# process text
- if (defined($root->{'text'})) {
+ if (defined($element->{'text'})) {
if (!$type or $type ne 'untranslated') {
if (!$formatter->{'_top_formatter'}) {
- if ($type and ($type eq 'raw'
- or $type eq 'last_raw_newline')) {
+ if ($type and $type eq 'raw') {
$result = _count_added($self, $formatter->{'container'},
- add_next($formatter->{'container'}, $root->{'text'}));
+ add_next($formatter->{'container'}, $element->{'text'}));
} else {
- my $text = _process_text($self, $root, $formatter);
+ my $text = _process_text($self, $element, $formatter);
$result = _count_added($self, $formatter->{'container'},
add_text ($formatter->{'container'}, $text));
}
return $result;
# the following is only possible if paragraphindent is set to asis
- } elsif ($type and $type eq 'empty_spaces_before_paragraph') {
- _add_text_count($self, $root->{'text'});
- return $root->{'text'};
+ } elsif ($type and $type eq 'spaces_before_paragraph') {
+ add_text_to_count($self, $element->{'text'});
+ return $element->{'text'};
# ignore text outside of any format, but warn if ignored text not empty
- } elsif ($root->{'text'} =~ /\S/) {
- $self->_bug_message("ignored text not empty `$root->{'text'}'", $root);
+ } elsif ($element->{'text'} =~ /\S/) {
+ $self->present_bug_message("ignored text not empty `$element->{'text'}'", $element);
return '';
} else {
# miscellaneous top-level whitespace - possibly after an @image
return _count_added($self, $formatter->{'container'},
- add_text($formatter->{'container'}, $root->{'text'}));
+ add_text($formatter->{'container'}, $element->{'text'}));
}
} else {
- my $tree = $self->gdt($root->{'text'});
+ my $tree = $self->gdt($element->{'text'});
my $converted = _convert($self, $tree);
return $converted;
}
}
- if ($root->{'extra'}) {
- if ($root->{'extra'}->{'missing_argument'}
- and (!$root->{'contents'} or !@{$root->{'contents'}})) {
+ if ($element->{'extra'}) {
+ if ($element->{'extra'}->{'missing_argument'}
+ and (!$element->{'contents'} or !@{$element->{'contents'}})) {
return '';
}
}
- if ($root->{'extra'} and $root->{'extra'}->{'index_entry'}
+ if ($element->{'extra'} and $element->{'extra'}->{'index_entry'}
and !$self->{'multiple_pass'} and !$self->{'in_copying_header'}) {
- my $location = $self->_add_location($root);
+ my $location = $self->add_location($element);
# remove a 'lines' from $location if at the very end of a node
# since it will lead to the next node otherwise.
if ($command and $command =~ /index/) {
@@ -1634,39 +1774,47 @@ sub _convert($$)
# in @insertcopying.
# This also covers the case of an index entry in a node added by a
# @footnote with footnotestyle separate.
- if ($self->{'node'}) {
- $location->{'node'} = $self->{'node'};
+ if ($self->{'current_node'}) {
+ $location->{'node'} = $self->{'current_node'};
}
- $self->{'index_entries_line_location'}->{$root} = $location;
+ $self->{'index_entries_line_location'}->{$element} = $location;
}
my $cell;
my $preformatted;
if ($command) {
my $unknown_command;
- if (defined($no_brace_commands{$command})) {
+ if (defined($nobrace_symbol_text{$command})) {
if ($command eq ':') {
remove_end_sentence($formatter->{'container'});
return '';
} elsif ($command eq '*') {
$result = _count_added($self, $formatter->{'container'},
- add_pending_word($formatter->{'container'}));
- $result .= _count_added($self, $formatter->{'container'},
- end_line($formatter->{'container'}));
+ add_pending_word($formatter->{'container'}));
+ # added eol in some line oriented constructs, such as @node, menu
+ # entry and therefore index entry would lead to end of line on
+ # node pointers line, in tag table, or on menu, all being invalid.
+ if ($formatter->{'no_added_eol'}) {
+ $result .= _count_added($self, $formatter->{'container'},
+ add_text($formatter->{'container'}, ' '));
+ } else {
+ $result .= _count_added($self, $formatter->{'container'},
+ end_line($formatter->{'container'}));
+ }
} elsif ($command eq '.' or $command eq '?' or $command eq '!') {
$result .= _count_added($self, $formatter->{'container'},
add_next($formatter->{'container'}, $command));
add_end_sentence($formatter->{'container'}, 1);
} elsif ($command eq ' ' or $command eq "\n" or $command eq "\t") {
$result .= _count_added($self, $formatter->{'container'},
- add_next($formatter->{'container'}, $no_brace_commands{$command}));
+ add_next($formatter->{'container'}, $nobrace_symbol_text{$command}));
} else {
$result .= _count_added($self, $formatter->{'container'},
- add_text($formatter->{'container'}, $no_brace_commands{$command}));
+ add_text($formatter->{'container'}, $nobrace_symbol_text{$command}));
}
return $result;
} elsif ($command eq 'today') {
- my $today = $self->Texinfo::Common::expand_today();
+ my $today = $self->Texinfo::Convert::Utils::expand_today();
unshift @{$self->{'current_contents'}->[-1]}, $today;
} elsif (exists($brace_no_arg_commands{$command})) {
my $text;
@@ -1675,7 +1823,7 @@ sub _convert($$)
# Don't use Unicode ellipsis character.
$text = '...';
} else {
- $text = Texinfo::Convert::Text::brace_no_arg_command($root,
+ $text = Texinfo::Convert::Text::brace_no_arg_command($element,
$self->{'convert_text_options'});
}
@@ -1729,18 +1877,18 @@ sub _convert($$)
$sc = 1;
}
my $accented_text
- = Texinfo::Convert::Text::text_accents($root, $encoding, $sc);
+ = Texinfo::Convert::Text::text_accents($element, $encoding, $sc);
$result .= _count_added($self, $formatter->{'container'},
add_text($formatter->{'container'}, $accented_text));
my $accented_text_original;
if ($formatter->{'upper_case'}) {
$accented_text_original
- = Texinfo::Convert::Text::text_accents($root, $encoding);
+ = Texinfo::Convert::Text::text_accents($element, $encoding);
}
if ($accented_text_original
- and $accented_text_original !~ /[[:upper:]]/
+ and $accented_text_original !~ /\p{Upper}/
or $formatter->{'var'}
or $formatter->{'font_type_stack'}->[-1]->{'monospace'}) {
allow_end_sentence($formatter->{'container'});
@@ -1753,14 +1901,15 @@ sub _convert($$)
if ($accented_text ne '');
return $result;
} elsif ($self->{'style_map'}->{$command}
- or ($root->{'type'} and $root->{'type'} eq 'definfoenclose_command')) {
- if ($code_style_commands{$command}) {
+ or ($element->{'type'} and $element->{'type'} eq 'definfoenclose_command')) {
+ if ($brace_code_commands{$command}) {
if (!$formatter->{'font_type_stack'}->[-1]->{'monospace'}) {
push @{$formatter->{'font_type_stack'}}, {'monospace' => 1};
} else {
$formatter->{'font_type_stack'}->[-1]->{'monospace'}++;
}
- } elsif ($regular_font_style_commands{$command}) {
+ } elsif ($brace_commands{$command}
+ and $brace_commands{$command} eq 'style_no_code') {
if ($formatter->{'font_type_stack'}->[-1]->{'monospace'}) {
push @{$formatter->{'font_type_stack'}}, {'monospace' => 0,
'normal' => 1};
@@ -1783,9 +1932,9 @@ sub _convert($$)
if ($formatter->{'w'} == 1);
}
my ($text_before, $text_after);
- if ($root->{'type'} and $root->{'type'} eq 'definfoenclose_command') {
- $text_before = $root->{'extra'}->{'begin'};
- $text_after = $root->{'extra'}->{'end'};
+ if ($element->{'type'} and $element->{'type'} eq 'definfoenclose_command') {
+ $text_before = $element->{'extra'}->{'begin'};
+ $text_after = $element->{'extra'}->{'end'};
} elsif ($non_quoted_commands_when_nested{$command}
and $formatter->{'font_type_stack'}->[-1]->{'code_command'}) {
$text_before = '';
@@ -1806,17 +1955,17 @@ sub _convert($$)
$result .= _count_added($self, $formatter->{'container'},
add_next($formatter->{'container'}, $text_before, 1))
if ($text_before ne '');
- if ($root->{'args'}) {
- $result .= _convert($self, $root->{'args'}->[0]);
+ if ($element->{'args'}) {
+ $result .= _convert($self, $element->{'args'}->[0]);
if ($command eq 'strong'
- and scalar (@{$root->{'args'}->[0]->{'contents'}})
- and $root->{'args'}->[0]->{'contents'}->[0]->{'text'}
- and $root->{'args'}->[0]->{'contents'}->[0]->{'text'} =~ /^Note\s/i
- and $self->{'output_format'}
- and $self->{'output_format'} eq 'info') {
- $self->line_warn(__(
+ and scalar (@{$element->{'args'}->[0]->{'contents'}})
+ and $element->{'args'}->[0]->{'contents'}->[0]->{'text'}
+ and $element->{'args'}->[0]->{'contents'}->[0]->{'text'} =~ /^Note\s/i
+ and $self->{'converted_format'}
+ and $self->{'converted_format'} eq 'info') {
+ $self->converter_line_warn($self, __(
"\@strong{Note...} produces a spurious cross-reference in Info; reword to avoid that"),
- $root->{'line_nr'});
+ $element->{'source_info'});
}
}
$result .= _count_added($self, $formatter->{'container'},
@@ -1827,12 +1976,13 @@ sub _convert($$)
set_space_protection($formatter->{'container'},0,undef)
if ($formatter->{'w'} == 0);
}
- if ($code_style_commands{$command}) {
+ if ($brace_code_commands{$command}) {
$formatter->{'font_type_stack'}->[-1]->{'monospace'}--;
allow_end_sentence($formatter->{'container'});
pop @{$formatter->{'font_type_stack'}}
if !$formatter->{'font_type_stack'}->[-1]->{'monospace'};
- } elsif ($regular_font_style_commands{$command}) {
+ } elsif ($brace_commands{$command}
+ and $brace_commands{$command} eq 'style_no_code') {
if ($formatter->{'font_type_stack'}->[-1]->{'normal'}) {
$formatter->{'font_type_stack'}->[-1]->{'normal'}--;
pop @{$formatter->{'font_type_stack'}}
@@ -1864,9 +2014,9 @@ sub _convert($$)
add_pending_word($formatter->{'container'}, 1));
# add an empty word so that following spaces aren't lost
add_next($formatter->{'container'},'');
- my ($image, $lines_count) = $self->_image($root);
+ my ($image, $lines_count) = $self->format_image($element);
_add_lines_count($self, $lines_count);
- _add_text_count($self, $image);
+ add_text_to_count($self, $image);
if ($image ne '' and $formatter->{'type'} ne 'paragraph') {
$self->{'empty_lines_count'} = 0;
}
@@ -1875,17 +2025,19 @@ sub _convert($$)
} elsif ($command eq 'email') {
# nothing is output for email, instead the command is substituted.
my @email_contents;
- if ($root->{'args'}) {
+ if ($element->{'args'}) {
my $name;
my $email;
- if (scalar (@{$root->{'args'}}) == 2
- and defined($root->{'args'}->[1])
- and @{$root->{'args'}->[1]->{'contents'}}) {
- $name = $root->{'args'}->[1]->{'contents'};
+ if (scalar (@{$element->{'args'}}) == 2
+ and defined($element->{'args'}->[1])
+ and $element->{'args'}->[1]->{'contents'}
+ and @{$element->{'args'}->[1]->{'contents'}}) {
+ $name = $element->{'args'}->[1]->{'contents'};
}
- if (defined($root->{'args'}->[0])
- and @{$root->{'args'}->[0]->{'contents'}}) {
- $email = $root->{'args'}->[0]->{'contents'};
+ if (defined($element->{'args'}->[0])
+ and $element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}) {
+ $email = $element->{'args'}->[0]->{'contents'};
}
my $prepended;
if ($name and $email) {
@@ -1903,21 +2055,24 @@ sub _convert($$)
}
return '';
} elsif ($command eq 'uref' or $command eq 'url') {
- if ($root->{'args'}) {
- if (scalar(@{$root->{'args'}}) == 3
- and defined($root->{'args'}->[2])
- and @{$root->{'args'}->[2]->{'contents'}}) {
+ if ($element->{'args'}) {
+ if (scalar(@{$element->{'args'}}) == 3
+ and defined($element->{'args'}->[2])
+ and $element->{'args'}->[2]->{'contents'}
+ and @{$element->{'args'}->[2]->{'contents'}}) {
unshift @{$self->{'current_contents'}->[-1]},
- {'contents' => $root->{'args'}->[2]->{'contents'}};
- } elsif (@{$root->{'args'}->[0]->{'contents'}}) {
+ {'contents' => $element->{'args'}->[2]->{'contents'}};
+ } elsif ($element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}) {
# no mangling of --- and similar in url.
my $url = {'type' => '_code',
- 'contents' => $root->{'args'}->[0]->{'contents'}};
- if (scalar(@{$root->{'args'}}) == 2
- and defined($root->{'args'}->[1])
- and @{$root->{'args'}->[1]->{'contents'}}) {
+ 'contents' => $element->{'args'}->[0]->{'contents'}};
+ if (scalar(@{$element->{'args'}}) == 2
+ and defined($element->{'args'}->[1])
+ and $element->{'args'}->[1]->{'contents'}
+ and @{$element->{'args'}->[1]->{'contents'}}) {
my $prepended = $self->gdt('{text} ({url})',
- {'text' => $root->{'args'}->[1]->{'contents'},
+ {'text' => $element->{'args'}->[1]->{'contents'},
'url' => $url });
unshift @{$self->{'current_contents'}->[-1]}, $prepended;
} else {
@@ -1925,11 +2080,11 @@ sub _convert($$)
{'url' => $url});
unshift @{$self->{'current_contents'}->[-1]}, $prepended
}
- } elsif (scalar(@{$root->{'args'}}) == 2
- and defined($root->{'args'}->[1])
- and @{$root->{'args'}->[1]->{'contents'}}) {
+ } elsif (scalar(@{$element->{'args'}}) == 2
+ and defined($element->{'args'}->[1])
+ and @{$element->{'args'}->[1]->{'contents'}}) {
unshift @{$self->{'current_contents'}->[-1]},
- {'contents' => $root->{'args'}->[1]->{'contents'}};
+ {'contents' => $element->{'args'}->[1]->{'contents'}};
}
}
return '';
@@ -1941,23 +2096,23 @@ sub _convert($$)
} else {
$formatted_footnote_number = $NO_NUMBER_FOOTNOTE_SYMBOL;
}
- push @{$self->{'pending_footnotes'}}, {'root' => $root,
+ push @{$self->{'pending_footnotes'}}, {'root' => $element,
'number' => $self->{'footnote_index'}}
unless ($self->{'multiple_pass'});
if (!$self->{'in_copying_header'}) {
- $self->_error_outside_of_any_node($root);
+ $self->format_error_outside_of_any_node($element);
}
$result .= _count_added($self, $formatter->{'container'},
add_next($formatter->{'container'},
"($formatted_footnote_number)", 1));
- if ($self->get_conf('footnotestyle') eq 'separate' and $self->{'node'}) {
+ if ($self->get_conf('footnotestyle') eq 'separate' and $self->{'current_node'}) {
$result .= _convert($self, {'contents' =>
[{'text' => ' ('},
{'cmdname' => 'pxref',
'args' => [
{'type' => 'brace_command_arg',
'contents' => [
- @{$self->{'node'}->{'extra'}->{'node_content'}},
+ @{$self->{'current_node'}->{'extra'}->{'node_content'}},
{'text' => "-Footnote-$self->{'footnote_index'}"}
]
}
@@ -1970,12 +2125,12 @@ sub _convert($$)
} elsif ($command eq 'anchor') {
$result = _count_added($self, $formatter->{'container'},
add_pending_word($formatter->{'container'}));
- $result .= $self->_anchor($root);
+ $result .= $self->_anchor($element);
return $result;
} elsif ($ref_commands{$command}) {
- if (scalar(@{$root->{'args'}})) {
+ if (scalar(@{$element->{'args'}})) {
my @args;
- for my $a (@{$root->{'args'}}) {
+ for my $a (@{$element->{'args'}}) {
if (defined $a->{'contents'} and @{$a->{'contents'}}) {
push @args, $a->{'contents'};
} else {
@@ -1988,9 +2143,9 @@ sub _convert($$)
# NOTE as a consequence, the line numbers appearing in case of errors
# correspond to the node lines numbers, and not the @ref.
my $node_content;
- if ($root->{'extra'}
- and $root->{'extra'}->{'label'}) {
- $node_content = $root->{'extra'}->{'label'}->{'extra'}->{'node_content'};
+ if ($element->{'extra'}
+ and $element->{'extra'}->{'label'}) {
+ $node_content = $element->{'extra'}->{'label'}->{'extra'}->{'node_content'};
} else {
$node_content = $args[0];
}
@@ -1998,13 +2153,13 @@ sub _convert($$)
# if it a reference to a float with a label, $arg[1] is
# set to '$type $number' or '$number' if there is no type.
if (! defined($args[1])
- and $root->{'extra'}
- and $root->{'extra'}->{'label'}
- and $root->{'extra'}->{'label'}->{'cmdname'}
- and $root->{'extra'}->{'label'}->{'cmdname'} eq 'float') {
- my $float = $root->{'extra'}->{'label'};
+ and $element->{'extra'}
+ and $element->{'extra'}->{'label'}
+ and $element->{'extra'}->{'label'}->{'cmdname'}
+ and $element->{'extra'}->{'label'}->{'cmdname'} eq 'float') {
+ my $float = $element->{'extra'}->{'label'};
- my $name = $self->_float_type_number($float);
+ my $name = $self->float_type_number($float);
$args[1] = $name->{'contents'};
}
if ($command eq 'inforef' and scalar(@args) == 3) {
@@ -2059,14 +2214,14 @@ sub _convert($$)
.get_pending($self->{'formatters'}->[-1]->{'container'});
my $quoting_required = 0;
if ($name_text_checked =~ /:/m) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(sprintf(__(
- "\@%s cross-reference name should not contain `:'"),
- $command), $root->{'line_nr'});
- }
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
- $quoting_required = 1;
- }
+ if ($self->{'info_special_chars_warning'}) {
+ $self->converter_line_warn($self, sprintf(__(
+ "\@%s cross-reference name should not contain `:'"),
+ $command), $element->{'source_info'});
+ }
+ if ($self->{'info_special_chars_quote'}) {
+ $quoting_required = 1;
+ }
}
my $pre_quote = $quoting_required ? "\x{7f}" : '';
my $post_quote = $pre_quote;
@@ -2077,100 +2232,91 @@ sub _convert($$)
_count_added($self,$self->{'formatters'}[-1]{'container'},
$pre_quote)
if $pre_quote;
+ }
- if ($file) {
- $result .= _convert($self, {'contents' => $file});
- }
- # node name
- $self->{'formatters'}->[-1]->{'suppress_styles'} = 1;
+ if ($file) {
+ $result .= _convert($self, {'contents' => $file});
+ }
- my $maybe_file
- = get_pending($self->{'formatters'}->[-1]->{'container'});
- my $node_text = _convert($self, {'type' => '_code',
- 'contents' => $node_content});
- delete $self->{'formatters'}->[-1]->{'suppress_styles'};
+ my $node_line_name;
+ # Get the node name to be output.
+ # Due to the way the paragraph formatter holds pending text, converting
+ # the node name with the current formatter does not yield all the
+ # converted text. To get the full node name (and no more), we
+ # can convert in a new context, using convert_line.
+ # However, it is slow to do this for every node. So in the most
+ # frequent case when the node name is a simple text element, use
+ # that text instead.
+ if (scalar(@{$node_content}) == 1
+ and defined($node_content->[0]->{'text'})) {
+ $node_line_name = $node_content->[0]->{'text'};
+ } else {
+ $self->{'silent'} = 0 if (!defined($self->{'silent'}));
+ $self->{'silent'}++;
+ push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
+
+ $node_line_name = $self->convert_line({'type' => '_code',
+ 'contents' => $node_content},
+ {'suppress_styles' => 1,
+ 'no_added_eol' => 1});
+ pop @{$self->{'count_context'}};
+ $self->{'silent'}--;
+ }
- my $node_text_checked = $node_text
- .get_pending($self->{'formatters'}->[-1]->{'container'});
- $maybe_file =~ s/^\s*//;
- $maybe_file = quotemeta $maybe_file;
- $node_text_checked =~ s/^\s*$maybe_file//;
- $quoting_required = 0;
- if ($node_text_checked =~ /([,\t\.])/m ) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(sprintf(__(
- "\@%s node name should not contain `%s'"), $command, $1),
- $root->{'line_nr'});
- }
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
- $quoting_required = 1;
- }
- }
- $pre_quote = $quoting_required ? "\x{7f}" : '';
- $post_quote = $pre_quote;
- if ($pre_quote) {
- $node_text =~ s/^(\s*)/$1$pre_quote/;
- _count_added($self,$self->{'formatters'}[-1]{'container'},
- $pre_quote);
- }
- $result .= $node_text;
- _count_added($self, $self->{'formatters'}[-1]{'container'},
- add_next($self->{'formatters'}->[-1]->{'container'}, $post_quote))
- if $post_quote;
- } else { # Label same as node specification
- if ($file) {
- $result .= _convert($self, {'contents' => $file});
- }
- $self->{'formatters'}->[-1]->{'suppress_styles'} = 1;
- my $node_text = _convert($self, {'type' => '_code',
- 'contents' => $node_content});
- delete $self->{'formatters'}->[-1]->{'suppress_styles'};
+ my $check_chars;
+ if ($name) {
+ $check_chars = quotemeta ",\t.";
+ } else {
+ $check_chars = quotemeta ":";
+ }
- my $node_text_checked = $node_text
- .get_pending($self->{'formatters'}->[-1]->{'container'});
- my $quoting_required = 0;
- if ($node_text_checked =~ /:/m) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(sprintf(__(
- "\@%s node name should not contain `:'"), $command),
- $root->{'line_nr'});
- }
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
- $quoting_required = 1;
- }
+ my $quoting_required = 0;
+ if ($node_line_name =~ /([$check_chars])/m) {
+ if ($self->{'info_special_chars_warning'}) {
+ $self->converter_line_warn($self, sprintf(__(
+ "\@%s node name should not contain `%s'"), $command, $1),
+ $element->{'source_info'});
}
- my $pre_quote = $quoting_required ? "\x{7f}" : '';
- my $post_quote = $pre_quote;
- $node_text .= _convert($self, {'contents' => [
- {'text' => "${post_quote}::"}]});
- _count_added($self,$self->{'formatters'}[-1]{'container'},
- $pre_quote)
- if $pre_quote;
- if ($pre_quote) {
- # This is needed to get a pending word. We could use
- # add_pending_word, but that would not include following
- # punctuation in the word.
- my $next = $self->{'current_contents'}->[-1]->[0];
- if ($next) {
- $node_text .= _convert($self, $next);
- shift @{$self->{'current_contents'}->[-1]};
- }
-
- $node_text =~ s/^(\s*)/$1$pre_quote/;
+ if ($self->{'info_special_chars_quote'}) {
+ $quoting_required = 1;
}
- $result .= $node_text;
}
- # we could use $formatter, but in case it was changed in _convert
- # we play it safe.
- my $pending = $result
- .get_pending($self->{'formatters'}->[-1]->{'container'});
- # If command is @xref, the punctuation must always follow the
- # command, for other commands it may be in the argument, hence the
- # use of $pending.
- # FIXME: is @xref really special here?
- if ($name and ($command eq 'xref'
- or ($pending !~ /[\.,]$/ and $pending !~ /::$/))) {
+ my $pre_quote = $quoting_required ? "\x{7f}" : '';
+ my $post_quote = $pre_quote;
+
+ # node name
+ my $node_text = '';
+ $node_text .= _count_added($self,
+ $self->{'formatters'}[-1]{'container'},
+ add_next($self->{'formatters'}->[-1]->{'container'}, $pre_quote))
+ if $pre_quote;
+
+ $self->{'formatters'}->[-1]->{'suppress_styles'} = 1;
+ $node_text .= _convert($self, {'type' => '_code',
+ 'contents' => $node_content});
+ delete $self->{'formatters'}->[-1]->{'suppress_styles'};
+
+ $node_text .= _count_added($self,
+ $self->{'formatters'}[-1]{'container'},
+ add_next($self->{'formatters'}->[-1]->{'container'}, $post_quote))
+ if $post_quote;
+
+ if (!$name) {
+ $node_text .= _count_added($self,
+ $self->{'formatters'}[-1]{'container'},
+ add_next($self->{'formatters'}->[-1]->{'container'}, '::'));
+ }
+
+ $result .= $node_text;
+
+ # Check if punctuation follows the ref command.
+ #
+ # FIXME: is @xref really special here? Original comment:
+ # "If command is @xref, the punctuation must always follow the
+ # command, for other commands it may be in the argument..."
+
+ if ($name) {
my $next = $self->{'current_contents'}->[-1]->[0];
if (!($next and $next->{'text'} and $next->{'text'} =~ /^[\.,]/)) {
if ($command eq 'xref') {
@@ -2178,12 +2324,13 @@ sub _convert($$)
my $text = $next->{'text'};
$text =~ s/^\s*//;
my $char = substr($text, 0, 1);
- $self->line_warn(sprintf(__(
- "`.' or `,' must follow \@xref, not %s"),
- $char), $root->{'line_nr'});
+ $self->converter_line_warn($self, sprintf(__(
+ "`.' or `,' must follow \@xref, not %s"),
+ $char), $element->{'source_info'});
} else {
- $self->line_warn(__("`.' or `,' must follow \@xref"),
- $root->{'line_nr'});
+ $self->converter_line_warn($self,
+ __("`.' or `,' must follow \@xref"),
+ $element->{'source_info'});
}
}
my @added = ({'text' => '.'});
@@ -2207,23 +2354,24 @@ sub _convert($$)
}
return '';
} elsif ($explained_commands{$command}) {
- if ($root->{'args'}
- and defined($root->{'args'}->[0])
- and @{$root->{'args'}->[0]->{'contents'}}) {
+ if ($element->{'args'}
+ and defined($element->{'args'}->[0])
+ and $element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}) {
# in abbr spaces never end a sentence.
my $argument;
if ($command eq 'abbr') {
$argument = {'type' => 'frenchspacing',
- 'contents' => $root->{'args'}->[0]->{'contents'}};
+ 'contents' => $element->{'args'}->[0]->{'contents'}};
} else {
- $argument = { 'contents' => $root->{'args'}->[0]->{'contents'}};
+ $argument = { 'contents' => $element->{'args'}->[0]->{'contents'}};
}
- if (scalar (@{$root->{'args'}}) == 2
- and defined($root->{'args'}->[-1])
- and @{$root->{'args'}->[-1]->{'contents'}}) {
+ if (scalar (@{$element->{'args'}}) == 2
+ and defined($element->{'args'}->[-1])
+ and @{$element->{'args'}->[-1]->{'contents'}}) {
my $prepended = $self->gdt('{abbr_or_acronym} ({explanation})',
{'abbr_or_acronym' => $argument,
- 'explanation' => $root->{'args'}->[-1]->{'contents'}});
+ 'explanation' => $element->{'args'}->[-1]->{'contents'}});
unshift @{$self->{'current_contents'}->[-1]}, $prepended;
return '';
} else {
@@ -2235,31 +2383,33 @@ sub _convert($$)
}
}
return '';
- } elsif ($inline_commands{$command}) {
+ } elsif ($brace_commands{$command}
+ and $brace_commands{$command} eq 'inline') {
my $arg_index = 1;
if ($command eq 'inlinefmtifelse'
- and (!$root->{'extra'}->{'format'}
- or !$self->{'expanded_formats_hash'}->{$root->{'extra'}->{'format'}})) {
+ and (!$element->{'extra'}->{'format'}
+ or !$self->{'expanded_formats_hash'}->{$element->{'extra'}->{'format'}})) {
$arg_index = 2;
}
- if (scalar(@{$root->{'args'}}) > $arg_index
- and defined($root->{'args'}->[$arg_index])
- and @{$root->{'args'}->[$arg_index]->{'contents'}}) {
- my $argument;
+ if (scalar(@{$element->{'args'}}) > $arg_index
+ and defined($element->{'args'}->[$arg_index])
+ and $element->{'args'}->[$arg_index]->{'contents'}
+ and @{$element->{'args'}->[$arg_index]->{'contents'}}) {
+ my $argument = {};
if ($command eq 'inlineraw') {
$argument->{'type'} = '_code';
}
- $argument->{'contents'} = $root->{'args'}->[$arg_index]->{'contents'};
+ $argument->{'contents'} = $element->{'args'}->[$arg_index]->{'contents'};
unshift @{$self->{'current_contents'}->[-1]}, ($argument);
}
return '';
# condition should actually be that the $command is inline
} elsif ($math_commands{$command} and not exists($block_commands{$command})) {
push @{$self->{'context'}}, $command;
- if ($root->{'args'}) {
+ if ($element->{'args'}) {
$result .= _convert($self, {'type' => 'frenchspacing',
'contents' => [{'type' => '_code',
- 'contents' => [$root->{'args'}->[0]]}]});
+ 'contents' => [$element->{'args'}->[0]]}]});
}
my $old_context = pop @{$self->{'context'}};
die if ($old_context ne $command);
@@ -2267,66 +2417,43 @@ sub _convert($$)
} elsif ($command eq 'titlefont') {
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
$result = $self->convert_line ({'type' => 'frenchspacing',
- 'contents' => [$root->{'args'}->[0]]});
+ 'contents' => [$element->{'args'}->[0]]});
pop @{$self->{'count_context'}};
- $result = Texinfo::Convert::Text::heading({'level' => 0,
- 'cmdname' => 'titlefont'}, $result, $self,
- $self->get_conf('NUMBER_SECTIONS'),
- ($self->{'format_context'}->[-1]->{'indent_level'}) * $indent_length);
+ $result = Texinfo::Convert::Text::text_heading(
+ {'structure' => {'section_level' => 0},
+ 'cmdname' => 'titlefont'},
+ $result, $self, $self->get_conf('NUMBER_SECTIONS'),
+ ($self->{'format_context'}->[-1]->{'indent_level'}) * $indent_length);
$result =~ s/\n$//; # final newline has its own tree element
$self->{'empty_lines_count'} = 0 unless ($result eq '');
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
_add_lines_count($self, 1);
return $result;
} elsif ($command eq 'U') {
my $arg;
- if ($root->{'args'}
- and $root->{'args'}->[0]
- and $root->{'args'}->[0]->{'contents'}
- and $root->{'args'}->[0]->{'contents'}->[0]
- and $root->{'args'}->[0]->{'contents'}->[0]->{'text'}) {
- $arg = $root->{'args'}->[0]->{'contents'}->[0]->{'text'};
+ if ($element->{'args'}
+ and $element->{'args'}->[0]
+ and $element->{'args'}->[0]->{'contents'}
+ and $element->{'args'}->[0]->{'contents'}->[0]
+ and $element->{'args'}->[0]->{'contents'}->[0]->{'text'}) {
+ $arg = $element->{'args'}->[0]->{'contents'}->[0]->{'text'};
}
if ($arg) {
# Syntactic checks on the value were already done in Parser.pm,
# but we have one more thing to test: since this is the one
# place where we might output actual UTF-8 binary bytes, we have
- # to check that chr(hex($arg)) is valid. Perl gives a warning
- # and will not output UTF-8 for Unicode non-characters such as
- # U+10FFFF. In this case, silently fall back to plain text, on
- # the theory that the user wants something.
+ # to check that it is possible. If not, silently fall back to
+ # plain text, on the theory that the user wants something.
my $res;
if ($self->{'to_utf8'}) {
- my $error = 0;
- # The warning about non-characters is only given when the code
- # point is attempted to be output, not just manipulated.
- # http://stackoverflow.com/questions/5127725/how-could-i-catch-an-unicode-non-character-warning
- #
- # Therefore, we have to try to output it within an eval.
- # Since opening /dev/null or a temporary file means
- # more system-dependent checks, use a string as our
- # filehandle.
- eval {
- use warnings FATAL => qw(all);
- my ($fh, $string);
- open($fh, ">", \$string) || die "open(U string eval) failed: $!";
- binmode($fh, ":utf8") || die "binmode(U string eval) failed: $!";
- print $fh chr(hex("$arg"));
- };
- if ($@) {
- warn "\@U chr(hex($arg)) eval failed: $@\n" if ($self->{'DEBUG'});
- $error = 1;
- } elsif (hex($arg) > 0x10FFFF) {
- # The check above appears not to work in older versions of perl,
- # so check the argument is not greater the maximum Unicode code
- # point.
- $error = 1;
- }
- if ($error) {
- $res = "U+$arg";
- } else {
+ my $possible_conversion
+ = Texinfo::Convert::Unicode::check_unicode_point_conversion($arg,
+ $self->{'DEBUG'});
+ if ($possible_conversion) {
$res = chr(hex($arg)); # ok to call chr
+ } else {
+ $res = "U+$arg";
}
} else {
$res = "U+$arg"; # not outputting UTF-8
@@ -2340,7 +2467,7 @@ sub _convert($$)
} elsif ($command eq 'value') {
my $expansion = $self->gdt('@{No value for `{value}\'@}',
- {'value' => $root->{'type'}});
+ {'value' => $element->{'extra'}->{'flag'}});
if ($formatter->{'_top_formatter'}) {
$expansion = {'type' => 'paragraph',
'contents' => [$expansion]};
@@ -2349,9 +2476,9 @@ sub _convert($$)
# unshift @{$self->{'current_contents'}->[-1]}, $expansion;
#return '';
return $result;
- } elsif ($root->{'args'} and $root->{'args'}->[0]
- and $root->{'args'}->[0]->{'type'}
- and $root->{'args'}->[0]->{'type'} eq 'brace_command_arg') {
+ } elsif ($element->{'args'} and $element->{'args'}->[0]
+ and $element->{'args'}->[0]->{'type'}
+ and $element->{'args'}->[0]->{'type'} eq 'brace_command_arg') {
# block commands
} elsif (exists($block_commands{$command})) {
# remark:
@@ -2372,7 +2499,8 @@ sub _convert($$)
push @{$self->{'context'}}, $command;
} elsif ($flush_commands{$command}) {
push @{$self->{'context'}}, $command;
- } elsif ($raw_commands{$command} or $block_math_commands{$command}) {
+ } elsif ($block_commands{$command} eq 'raw' # can only be @verbatim in practice
+ or $block_math_commands{$command}) {
if (!$self->{'formatters'}->[-1]->{'_top_formatter'}) {
# reuse the current formatter if not in top level
$result .= _count_added($self, $formatter->{'container'},
@@ -2411,28 +2539,28 @@ sub _convert($$)
}
if ($command eq 'quotation'
or $command eq 'smallquotation') {
- if ($root->{'args'} and $root->{'args'}->[0]
- and $root->{'args'}->[0]->{'contents'}
- and @{$root->{'args'}->[0]->{'contents'}}) {
+ if ($element->{'args'} and $element->{'args'}->[0]
+ and $element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}) {
my $prepended = $self->gdt('@b{{quotation_arg}:} ',
- {'quotation_arg' => $root->{'args'}->[0]->{'contents'}});
+ {'quotation_arg' => $element->{'args'}->[0]->{'contents'}});
$prepended->{'type'} = 'frenchspacing';
$result .= $self->convert_line($prepended);
- $self->{'text_element_context'}->[-1]->{'counter'} +=
+ $self->{'text_element_context'}->[-1]->{'counter'} +=
Texinfo::Convert::Unicode::string_width($result);
$self->{'empty_lines_count'} = 0 unless ($result eq '');
}
} elsif ($menu_commands{$command}) {
- $result .= $self->_menu($root);
+ $result .= $self->_menu($element);
} elsif ($command eq 'multitable') {
my $columnsize;
- if ($root->{'extra'}->{'columnfractions'}) {
- foreach my $fraction (@{$root->{'extra'}->{'columnfractions'}
+ if ($element->{'extra'}->{'columnfractions'}) {
+ foreach my $fraction (@{$element->{'extra'}->{'columnfractions'}
->{'extra'}->{'misc_args'}}) {
push @$columnsize, int($fraction * $self->{'text_element_context'}->[-1]->{'max'} +0.5);
}
- } elsif ($root->{'extra'}->{'prototypes'}) {
- foreach my $prototype (@{$root->{'extra'}->{'prototypes'}}) {
+ } elsif ($element->{'extra'}->{'prototypes'}) {
+ foreach my $prototype (@{$element->{'extra'}->{'prototypes'}}) {
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
my ($formatted_prototype) = $self->convert_line($prototype,
{'indent_length' => 0});
@@ -2447,29 +2575,30 @@ sub _convert($$)
$self->{'document_context'}->[-1]->{'in_multitable'}++;
} elsif ($command eq 'float') {
$result .= _add_newline_if_needed($self);
- if ($root->{'extra'} and $root->{'extra'}->{'node_content'}) {
- $result .= $self->_anchor($root);
+ if ($element->{'extra'} and $element->{'extra'}->{'node_content'}) {
+ $result .= $self->_anchor($element);
}
}
} elsif ($command eq 'node') {
- $self->{'node'} = $root;
- $result .= $self->_node($root);
+ $self->{'current_node'} = $element;
+ $result .= $self->format_node($element);
$self->{'format_context'}->[-1]->{'paragraph_count'} = 0;
- } elsif ($sectioning_commands{$command}) {
+ } elsif ($sectioning_heading_commands{$command}) {
# use settitle for empty @top
# ignore @part
my $contents;
- if ($root->{'args'}->[0]->{'contents'}
- and @{$root->{'args'}->[0]->{'contents'}}
+ if ($element->{'args'}->[0]->{'contents'}
+ and @{$element->{'args'}->[0]->{'contents'}}
and $command ne 'part') {
- $contents = $root->{'args'}->[0]->{'contents'};
+ $contents = $element->{'args'}->[0]->{'contents'};
} elsif ($command eq 'top'
- and $self->{'extra'}->{'settitle'}
- and $self->{'extra'}->{'settitle'}->{'args'}
- and @{$self->{'extra'}->{'settitle'}->{'args'}}
- and $self->{'extra'}->{'settitle'}->{'args'}->[0]->{'contents'}
- and @{$self->{'extra'}->{'settitle'}->{'args'}->[0]->{'contents'}}) {
- $contents = $self->{'extra'}->{'settitle'}->{'args'}->[0]->{'contents'};
+ and $self->{'global_commands'}->{'settitle'}
+ and $self->{'global_commands'}->{'settitle'}->{'args'}
+ and @{$self->{'global_commands'}->{'settitle'}->{'args'}}
+ and $self->{'global_commands'}->{'settitle'}->{'args'}->[0]->{'contents'}
+ and @{$self->{'global_commands'}->{'settitle'}->{'args'}->[0]->{'contents'}}) {
+ $contents =
+ $self->{'global_commands'}->{'settitle'}->{'args'}->[0]->{'contents'};
}
if ($contents) {
@@ -2480,13 +2609,13 @@ sub _convert($$)
# @* leads to an end of line, underlying appears on the line below
# over one line
my $heading_underlined =
- Texinfo::Convert::Text::heading($root, $heading, $self,
+ Texinfo::Convert::Text::text_heading($element, $heading, $self,
$self->get_conf('NUMBER_SECTIONS'),
($self->{'format_context'}->[-1]->{'indent_level'})
* $indent_length);
$result .= _add_newline_if_needed($self);
$self->{'empty_lines_count'} = 0 unless ($heading_underlined eq '');
- _add_text_count($self, $heading_underlined);
+ add_text_to_count($self, $heading_underlined);
$result .= $heading_underlined;
if ($heading_underlined ne '') {
_add_lines_count($self, 2);
@@ -2495,17 +2624,17 @@ sub _convert($$)
}
$self->{'format_context'}->[-1]->{'paragraph_count'} = 0;
} elsif (($command eq 'item' or $command eq 'itemx')
- and $root->{'args'} and $root->{'args'}->[0]
- and $root->{'args'}->[0]->{'type'}
- and $root->{'args'}->[0]->{'type'} eq 'line_arg') {
- if ($root->{'args'} and @{$root->{'args'}}
- and $root->{'args'}->[0]->{'contents'}) {
+ and $element->{'args'} and $element->{'args'}->[0]
+ and $element->{'args'}->[0]->{'type'}
+ and $element->{'args'}->[0]->{'type'} eq 'line_arg') {
+ if ($element->{'args'} and @{$element->{'args'}}
+ and $element->{'args'}->[0]->{'contents'}) {
- my $converted_tree = $self->_table_item_content_tree($root,
- $root->{'args'}->[0]->{'contents'});
+ my $table_item_tree = $self->table_item_content_tree($element,
+ $element->{'args'}->[0]->{'contents'});
- $converted_tree->{'type'} = 'frenchspacing';
- $result = $self->convert_line($converted_tree,
+ $table_item_tree->{'type'} = 'frenchspacing';
+ $result = $self->convert_line($table_item_tree,
{'indent_level'
=> $self->{'format_context'}->[-1]->{'indent_level'} -1});
if ($result ne '') {
@@ -2513,38 +2642,39 @@ sub _convert($$)
$self->{'empty_lines_count'} = 0;
}
}
- } elsif ($command eq 'item' and $root->{'parent'}->{'cmdname'}
- and $item_container_commands{$root->{'parent'}->{'cmdname'}}) {
+ } elsif ($command eq 'item' and $element->{'parent'}->{'cmdname'}
+ and $block_commands{$element->{'parent'}->{'cmdname'}}
+ and $block_commands{$element->{'parent'}->{'cmdname'}} eq 'item_container') {
$self->{'format_context'}->[-1]->{'paragraph_count'} = 0;
my $line = $self->new_formatter('line',
{'indent_length' =>
($self->{'format_context'}->[-1]->{'indent_level'} -1)
* $indent_length
- + $item_indent_format_length{$root->{'parent'}->{'cmdname'}}});
+ + $item_indent_format_length{$element->{'parent'}->{'cmdname'}}});
push @{$self->{'formatters'}}, $line;
- if ($root->{'parent'}->{'cmdname'} eq 'enumerate') {
+ if ($element->{'parent'}->{'cmdname'} eq 'enumerate') {
$result = _count_added($self, $line->{'container'},
add_next($line->{'container'},
Texinfo::Common::enumerate_item_representation(
- $root->{'parent'}->{'extra'}->{'enumerate_specification'},
- $root->{'extra'}->{'item_number'}) . '. '));
- } elsif ($root->{'parent'}->{'args'}
- and $root->{'parent'}->{'args'}->[0]) {
+ $element->{'parent'}->{'extra'}->{'enumerate_specification'},
+ $element->{'extra'}->{'item_number'}) . '. '));
+ } elsif ($element->{'parent'}->{'args'}
+ and $element->{'parent'}->{'args'}->[0]) {
# this is the text prepended to items.
- $result = _convert($self, $root->{'parent'}->{'args'}->[0]);
+ $result = _convert($self, $element->{'parent'}->{'args'}->[0]);
$result .= _convert($self, { 'text' => ' ' });
}
$result .= _count_added($self, $line->{'container'},
Texinfo::Convert::Paragraph::end($line->{'container'}));
pop @{$self->{'formatters'}};
- $self->{'text_element_context'}->[-1]->{'counter'} +=
+ $self->{'text_element_context'}->[-1]->{'counter'} +=
Texinfo::Convert::Unicode::string_width($result);
$self->{'empty_lines_count'} = 0 unless ($result eq '');
# open a multitable cell
} elsif ($command eq 'headitem' or $command eq 'item'
or $command eq 'tab') {
- my $cell_width = $self->{'format_context'}->[-1]->{'columns_size'}->[$root->{'extra'}->{'cell_number'}-1];
+ my $cell_width = $self->{'format_context'}->[-1]->{'columns_size'}->[$element->{'extra'}->{'cell_number'}-1];
$self->{'format_context'}->[-1]->{'item_command'} = $command
if ($command ne 'tab');
die if (!defined($cell_width));
@@ -2565,13 +2695,13 @@ sub _convert($$)
'locations' => []};
$result = $self->convert_line (
{'type' => 'frenchspacing',
- 'contents' => $root->{'args'}->[0]->{'contents'}},
+ 'contents' => $element->{'args'}->[0]->{'contents'}},
{'indent_length' => 0});
if ($result ne '') {
$result = $self->ensure_end_of_line($result);
$result = $self->_align_environment ($result,
- $self->{'text_element_context'}->[-1]->{'max'}, 'center');
+ $self->{'text_element_context'}->[-1]->{'max'}, 'center');
$self->{'empty_lines_count'} = 0;
} else {
# it has to be done here, as it is done in _align_environment above
@@ -2581,11 +2711,11 @@ sub _convert($$)
return $result;
} elsif ($command eq 'exdent') {
if ($self->{'preformatted_context_commands'}->{$self->{'context'}->[-1]}) {
- $result = $self->convert_unfilled({'contents' => $root->{'args'}->[0]->{'contents'}},
+ $result = $self->_convert_unfilled({'contents' => $element->{'args'}->[0]->{'contents'}},
{'indent_level'
=> $self->{'format_context'}->[-1]->{'indent_level'} -1});
} else {
- $result = $self->convert_line({'contents' => $root->{'args'}->[0]->{'contents'}},
+ $result = $self->convert_line({'contents' => $element->{'args'}->[0]->{'contents'}},
{'indent_level'
=> $self->{'format_context'}->[-1]->{'indent_level'} -1});
}
@@ -2595,26 +2725,28 @@ sub _convert($$)
}
return $result;
} elsif ($command eq 'verbatiminclude') {
- my $expansion = $self->Texinfo::Common::expand_verbatiminclude($root);
+ my $expansion = Texinfo::Convert::Utils::expand_verbatiminclude($self,
+ $self, $element);
unshift @{$self->{'current_contents'}->[-1]}, $expansion
if ($expansion);
return '';
} elsif ($command eq 'insertcopying') {
- if ($self->{'extra'} and $self->{'extra'}->{'copying'}) {
+ if ($self->{'global_commands'}
+ and $self->{'global_commands'}->{'copying'}) {
unshift @{$self->{'current_contents'}->[-1]},
- {'contents' => $self->{'extra'}->{'copying'}->{'contents'}};
+ {'contents' => $self->{'global_commands'}->{'copying'}->{'contents'}};
}
return '';
} elsif ($command eq 'printindex') {
- $result = $self->_printindex($root);
+ $result = $self->format_printindex($element);
return $result;
} elsif ($command eq 'listoffloats') {
my $lines_count = 0;
- if ($root->{'extra'} and $root->{'extra'}->{'type'}
- and defined($root->{'extra'}->{'type'}->{'normalized'})
+ if ($element->{'extra'} and $element->{'extra'}->{'type'}
+ and defined($element->{'extra'}->{'type'}->{'normalized'})
and $self->{'floats'}
- and $self->{'floats'}->{$root->{'extra'}->{'type'}->{'normalized'}}
- and @{$self->{'floats'}->{$root->{'extra'}->{'type'}->{'normalized'}}}) {
+ and $self->{'floats'}->{$element->{'extra'}->{'type'}->{'normalized'}}
+ and @{$self->{'floats'}->{$element->{'extra'}->{'type'}->{'normalized'}}}) {
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0};
if (!$self->{'empty_lines_count'}) {
$result .= "\n";
@@ -2622,12 +2754,12 @@ sub _convert($$)
}
$result .= "* Menu:\n\n";
$lines_count += 2;
- foreach my $float (@{$self->{'floats'}->{$root->{'extra'}->{'type'}->{'normalized'}}}) {
+ foreach my $float (@{$self->{'floats'}->{$element->{'extra'}->{'type'}->{'normalized'}}}) {
next if !$float->{'args'} or !$float->{'args'}->[1]
or !@{$float->{'args'}->[1]->{'contents'}};
my $float_label_text = $self->convert_line({'type' => '_code',
'contents' => $float->{'args'}->[1]->{'contents'}});
- my $float_entry = $self->_float_type_number($float);
+ my $float_entry = $self->float_type_number($float);
my $float_entry_text = ':';
if (defined($float_entry)) {
$float_entry->{'type'} = 'frenchspacing';
@@ -2687,15 +2819,15 @@ sub _convert($$)
pop @{$self->{'count_context'}};
}
$self->{'format_context'}->[-1]->{'paragraph_count'}++;
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
_add_lines_count($self, $lines_count);
return $result;
} elsif ($command eq 'sp') {
- if ($root->{'extra'}->{'misc_args'}->[0]) {
+ if ($element->{'extra'}->{'misc_args'}->[0]) {
$result = _count_added($self, $formatter->{'container'},
add_pending_word($formatter->{'container'}));
# this useless copy avoids perl changing the type to integer!
- my $sp_nr = $root->{'extra'}->{'misc_args'}->[0];
+ my $sp_nr = $element->{'extra'}->{'misc_args'}->[0];
for (my $i = 0; $i < $sp_nr; $i++) {
$result .= _count_added($self, $formatter->{'container'},
end_line($formatter->{'container'}));
@@ -2710,10 +2842,10 @@ sub _convert($$)
and $self->{'structuring'}->{'sectioning_root'}) {
my $lines_count;
($result, $lines_count)
- = $self->_contents($self->{'structuring'}->{'sectioning_root'},
+ = $self->format_contents($self->{'structuring'}->{'sectioning_root'},
'contents');
_add_lines_count($self, $lines_count);
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
}
return $result;
} elsif ($command eq 'shortcontents'
@@ -2722,25 +2854,25 @@ sub _convert($$)
and $self->{'structuring'}->{'sectioning_root'}) {
my $lines_count;
($result, $lines_count)
- = $self->_contents($self->{'structuring'}->{'sectioning_root'},
+ = $self->format_contents($self->{'structuring'}->{'sectioning_root'},
'shortcontents');
_add_lines_count($self, $lines_count);
- _add_text_count($self, $result);
+ add_text_to_count($self, $result);
}
return $result;
# all the @-commands that have an information for the formatting, like
# @paragraphindent, @frenchspacing...
} elsif ($informative_commands{$command}) {
- $self->_informative_command($root);
+ Texinfo::Common::set_informative_command_value($self, $element);
return '';
} else {
$unknown_command = 1;
}
if ($unknown_command
- and !($root->{'extra'}
- and ($root->{'extra'}->{'index_entry'}
- or $root->{'extra'}->{'seeentry'}
- or $root->{'extra'}->{'seealso'}))
+ and !($element->{'extra'}
+ and ($element->{'extra'}->{'index_entry'}
+ or $element->{'extra'}->{'seeentry'}
+ or $element->{'extra'}->{'seealso'}))
# commands like def*x are not processed above, since only the def_line
# associated is processed. If they have no name and no category they
# are not considered as index entries either so they have a specific
@@ -2754,16 +2886,16 @@ sub _convert($$)
# open 'type' constructs.
my $paragraph;
- if ($root->{'type'}) {
- if ($root->{'type'} eq 'paragraph') {
+ if ($element->{'type'}) {
+ if ($element->{'type'} eq 'paragraph') {
$self->{'empty_lines_count'} = 0;
- my $conf;
+ my $conf = {};
# indent. Not first paragraph.
if ($self->{'format_context'}->[-1]->{'cmdname'} eq '_top_format'
and $self->get_conf('paragraphindent') ne 'asis'
and $self->get_conf('paragraphindent')
- and (($root->{'extra'} and $root->{'extra'}->{'indent'})
- or (!($root->{'extra'} and $root->{'extra'}->{'noindent'})
+ and (($element->{'extra'} and $element->{'extra'}->{'indent'})
+ or (!($element->{'extra'} and $element->{'extra'}->{'noindent'})
and ($self->{'format_context'}->[-1]->{'paragraph_count'}
or $self->get_conf('firstparagraphindent') eq 'insert')
and !$self->{'text_element_context'}->[-1]->{'counter'}))) {
@@ -2778,13 +2910,13 @@ sub _convert($$)
push @{$self->{'count_context'}}, {'lines' => 0, 'bytes' => 0,
'locations' => []};
}
- } elsif ($root->{'type'} eq 'preformatted'
- or $root->{'type'} eq 'rawpreformatted') {
+ } elsif ($element->{'type'} eq 'preformatted'
+ or $element->{'type'} eq 'rawpreformatted') {
# if in a description reuse the main menu unfilled, to keep things
# simpler and avoid having to do a separate count.
- if ($root->{'type'} eq 'rawpreformatted'
- or !$root->{'parent'}->{'type'}
- or $root->{'parent'}->{'type'} ne 'menu_entry_description') {
+ if ($element->{'type'} eq 'rawpreformatted'
+ or !$element->{'parent'}->{'type'}
+ or $element->{'parent'}->{'type'} ne 'menu_entry_description') {
$preformatted = $self->new_formatter('unfilled');
push @{$self->{'formatters'}}, $preformatted;
if ($self->{'context'}->[-1] eq 'flushright') {
@@ -2792,173 +2924,216 @@ sub _convert($$)
'locations' => []};
}
}
- } elsif ($root->{'type'} eq 'def_line') {
- if ($root->{'extra'} and $root->{'extra'}->{'def_parsed_hash'}
- and %{$root->{'extra'}->{'def_parsed_hash'}}) {
- my $arguments = Texinfo::Common::definition_arguments_content($root);
+ } elsif ($element->{'type'} eq 'def_line') {
+ if ($element->{'extra'} and $element->{'extra'}->{'def_parsed_hash'}
+ and %{$element->{'extra'}->{'def_parsed_hash'}}) {
+ my $arguments = Texinfo::Convert::Utils::definition_arguments_content($element);
my $tree;
my $command;
- if ($Texinfo::Common::def_aliases{$root->{'extra'}->{'def_command'}}) {
- $command = $Texinfo::Common::def_aliases{$root->{'extra'}->{'def_command'}};
+ if ($Texinfo::Common::def_aliases{$element->{'extra'}->{'def_command'}}) {
+ $command = $Texinfo::Common::def_aliases{$element->{'extra'}->{'def_command'}};
} else {
- $command = $root->{'extra'}->{'def_command'};
+ $command = $element->{'extra'}->{'def_command'};
}
my $name;
- if ($root->{'extra'}->{'def_parsed_hash'}->{'name'}) {
- $name = $root->{'extra'}->{'def_parsed_hash'}->{'name'};
+ if ($element->{'extra'}->{'def_parsed_hash'}->{'name'}) {
+ $name = $element->{'extra'}->{'def_parsed_hash'}->{'name'};
} else {
$name = '';
}
+
+ my $omit_def_space = $element->{'extra'}->{'omit_def_name_space'};
if ($command eq 'deffn'
or $command eq 'defvr'
or $command eq 'deftp'
or (($command eq 'deftypefn'
or $command eq 'deftypevr')
- and !$root->{'extra'}->{'def_parsed_hash'}->{'type'})) {
+ and !$element->{'extra'}->{'def_parsed_hash'}->{'type'})) {
if ($arguments) {
- $tree = $self->gdt("\@tie{}-- {category}: {name} {arguments}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ my $strings = {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'arguments' => $arguments});
+ 'arguments' => $arguments};
+ if ($omit_def_space) {
+ $tree = $self->gdt('@tie{}-- {category}: {name}{arguments}', $strings);
+ } else {
+ $tree = $self->gdt('@tie{}-- {category}: {name} {arguments}', $strings);
+ }
} else {
- $tree = $self->gdt("\@tie{}-- {category}: {name}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ $tree = $self->gdt('@tie{}-- {category}: {name}', {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name});
}
} elsif ($command eq 'deftypefn'
or $command eq 'deftypevr') {
if ($arguments) {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
'arguments' => $arguments};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree = $self->gdt("\@tie{}-- {category}:\@*{type}\@*{name} {arguments}",
- $strings);
+ if ($self->get_conf('deftypefnnewline') eq 'on'
+ and $command eq 'deftypefn') {
+ if ($omit_def_space) {
+ $tree = $self->gdt('@tie{}-- {category}:@*{type}@*{name}{arguments}',
+ $strings);
+ } else {
+ $tree = $self->gdt('@tie{}-- {category}:@*{type}@*{name} {arguments}',
+ $strings);
+ }
} else {
- $tree = $self->gdt("\@tie{}-- {category}: {type} {name} {arguments}",
- $strings);
+ if ($omit_def_space) {
+ $tree = $self->gdt('@tie{}-- {category}: {type} {name}{arguments}',
+ $strings);
+ } else {
+ $tree = $self->gdt('@tie{}-- {category}: {type} {name} {arguments}',
+ $strings);
+ }
}
} else {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
'name' => $name};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree = $self->gdt("\@tie{}-- {category}:\@*{type}\@*{name}",
+ if ($self->get_conf('deftypefnnewline') eq 'on'
+ and $command eq 'deftypefn') {
+ $tree = $self->gdt('@tie{}-- {category}:@*{type}@*{name}',
$strings);
} else {
- $tree = $self->gdt("\@tie{}-- {category}: {type} {name}",
+ $tree = $self->gdt('@tie{}-- {category}: {type} {name}',
$strings);
}
}
} elsif ($command eq 'defcv'
or ($command eq 'deftypecv'
- and !$root->{'extra'}->{'def_parsed_hash'}->{'type'})) {
+ and !$element->{'extra'}->{'def_parsed_hash'}->{'type'})) {
if ($arguments) {
- $tree = $self->gdt("\@tie{}-- {category} of {class}: {name} {arguments}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ my $strings = {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'arguments' => $arguments});
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'arguments' => $arguments};
+ if ($omit_def_space) {
+ $tree = $self->gdt('@tie{}-- {category} of {class}: {name}{arguments}',
+ $strings);
+ } else {
+ $tree = $self->gdt('@tie{}-- {category} of {class}: {name} {arguments}',
+ $strings);
+ }
} else {
- $tree = $self->gdt("\@tie{}-- {category} of {class}: {name}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
+ $tree = $self->gdt('@tie{}-- {category} of {class}: {name}', {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
'name' => $name});
}
} elsif ($command eq 'defop'
or ($command eq 'deftypeop'
- and !$root->{'extra'}->{'def_parsed_hash'}->{'type'})) {
+ and !$element->{'extra'}->{'def_parsed_hash'}->{'type'})) {
if ($arguments) {
- $tree = $self->gdt("\@tie{}-- {category} on {class}: {name} {arguments}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ my $strings = {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'arguments' => $arguments});
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'arguments' => $arguments};
+ if ($omit_def_space) {
+ $tree = $self->gdt('@tie{}-- {category} on {class}: {name}{arguments}',
+ $strings);
+ } else {
+ $tree = $self->gdt('@tie{}-- {category} on {class}: {name} {arguments}',
+ $strings);
+ }
} else {
- $tree = $self->gdt("\@tie{}-- {category} on {class}: {name}", {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
+ $tree = $self->gdt('@tie{}-- {category} on {class}: {name}', {
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
'name' => $name});
}
} elsif ($command eq 'deftypeop') {
if ($arguments) {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
'arguments' => $arguments};
if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("\@tie{}-- {category} on {class}:\@*{type}\@*{name} {arguments}",
- $strings);
+ if ($omit_def_space) {
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}:@*{type}@*{name}{arguments}',
+ $strings);
+ } else {
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}:@*{type}@*{name} {arguments}',
+ $strings);
+ }
} else {
- $tree
- = $self->gdt("\@tie{}-- {category} on {class}: {type} {name} {arguments}",
- $strings);
+ if ($omit_def_space) {
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}: {type} {name}{arguments}',
+ $strings);
+ } else {
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}: {type} {name} {arguments}',
+ $strings);
+ }
}
} else {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
'name' => $name};
if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("\@tie{}-- {category} on {class}:\@*{type}\@*{name}",
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}:@*{type}@*{name}',
$strings);
} else {
- $tree
- = $self->gdt("\@tie{}-- {category} on {class}: {type} {name}",
+ $tree
+ = $self->gdt('@tie{}-- {category} on {class}: {type} {name}',
$strings);
}
}
} elsif ($command eq 'deftypecv') {
if ($arguments) {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
'name' => $name,
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
'arguments' => $arguments};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("\@tie{}-- {category} of {class}:\@*{type}\@*{name} {arguments}",
+ if ($omit_def_space) {
+ $tree
+ = $self->gdt('@tie{}-- {category} of {class}: {type} {name}{arguments}',
$strings);
} else {
- $tree
- = $self->gdt("\@tie{}-- {category} of {class}: {type} {name} {arguments}",
+ $tree
+ = $self->gdt('@tie{}-- {category} of {class}: {type} {name} {arguments}',
$strings);
}
} else {
my $strings = {
- 'category' => $root->{'extra'}->{'def_parsed_hash'}->{'category'},
- 'type' => $root->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'class' => $root->{'extra'}->{'def_parsed_hash'}->{'class'},
+ 'category' => $element->{'extra'}->{'def_parsed_hash'}->{'category'},
+ 'type' => $element->{'extra'}->{'def_parsed_hash'}->{'type'},
+ 'class' => $element->{'extra'}->{'def_parsed_hash'}->{'class'},
'name' => $name};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("\@tie{}-- {category} of {class}:\@*{type}\@*{name}",
- $strings);
- } else {
- $tree
- = $self->gdt("\@tie{}-- {category} of {class}: {type} {name}",
+ $tree
+ = $self->gdt('@tie{}-- {category} of {class}: {type} {name}',
$strings);
- }
}
}
my $def_paragraph = $self->new_formatter('paragraph',
- { 'indent_length' => ($self->{'format_context'}->[-1]->{'indent_level'} -1) *$indent_length,
- 'indent_length_next' => (1+$self->{'format_context'}->[-1]->{'indent_level'})*$indent_length,
+ { 'indent_length' => ($self->{'format_context'}->[-1]->{'indent_level'} -1)
+ * $indent_length,
+ 'indent_length_next' => (1+$self->{'format_context'}->[-1]->{'indent_level'})
+ * $indent_length,
'suppress_styles' => 1
});
push @{$self->{'formatters'}}, $def_paragraph;
+ # FIXME the whole line is formatted in code here. In other formats,
+ # the category is normal text
$result .= _convert($self, {'type' => '_code', 'contents' => [$tree]});
$result .= _count_added($self, $def_paragraph->{'container'},
Texinfo::Convert::Paragraph::end($def_paragraph->{'container'}));
@@ -2967,12 +3142,13 @@ sub _convert($$)
delete $self->{'text_element_context'}->[-1]->{'counter'};
$self->{'empty_lines_count'} = 0;
}
- } elsif ($root->{'type'} eq 'menu_entry') {
+ } elsif ($element->{'type'} eq 'menu_entry') {
my $entry_name_seen = 0;
- foreach my $arg (@{$root->{'args'}}) {
+ foreach my $arg (@{$element->{'args'}}) {
my ($pre_quote, $post_quote);
if ($arg->{'type'} eq 'menu_entry_node') {
$self->{'formatters'}->[-1]->{'suppress_styles'} = 1;
+ $self->{'formatters'}->[-1]->{'no_added_eol'} = 1;
# Flush a leading space
$result .= _count_added($self, $formatter->{'container'},
@@ -2984,33 +3160,36 @@ sub _convert($$)
$node_text .= _count_added($self, $formatter->{'container'},
add_pending_word($formatter->{'container'}, 1));
delete $self->{'formatters'}->[-1]->{'suppress_styles'};
+ delete $self->{'formatters'}->[-1]->{'no_added_eol'};
$pre_quote = $post_quote = '';
if ($entry_name_seen) {
if ($node_text =~ /([,\t]|\.\s)/) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(sprintf(__(
+ if ($self->{'info_special_chars_warning'}) {
+ $self->converter_line_warn($self, sprintf(__(
"menu entry node name should not contain `%s'"), $1),
- $root->{'line_nr'});
+ $element->{'source_info'});
+ }
+ if ($self->{'info_special_chars_quote'}) {
+ $pre_quote = $post_quote = "\x{7f}";
}
- }
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
- $pre_quote = $post_quote = "\x{7f}";
}
} else {
if ($node_text =~ /:/) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(__(
+ if ($self->{'info_special_chars_warning'}) {
+ $self->converter_line_warn($self, __(
"menu entry node name should not contain `:'"),
- $root->{'line_nr'});
+ $element->{'source_info'});
}
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
+ if ($self->{'info_special_chars_quote'}) {
$pre_quote = $post_quote = "\x{7f}";
}
}
}
$result .= $pre_quote . $node_text . $post_quote;
} elsif ($arg->{'type'} eq 'menu_entry_name') {
+ $self->{'formatters'}->[-1]->{'no_added_eol'} = 1;
my $entry_name = _convert($self, $arg);
+ delete $self->{'formatters'}->[-1]->{'no_added_eol'};
my $formatter = $self->{'formatters'}->[-1];
$entry_name .= _count_added($self,
$formatter->{'container'},
@@ -3018,12 +3197,12 @@ sub _convert($$)
$entry_name_seen = 1;
$pre_quote = $post_quote = '';
if ($entry_name =~ /:/) {
- if ($self->get_conf('INFO_SPECIAL_CHARS_WARNING')) {
- $self->line_warn(__(
+ if ($self->{'info_special_chars_warning'}) {
+ $self->converter_line_warn($self, __(
"menu entry name should not contain `:'"),
- $root->{'line_nr'});
+ $element->{'source_info'});
}
- if ($self->get_conf('INFO_SPECIAL_CHARS_QUOTE')) {
+ if ($self->{'info_special_chars_quote'}) {
$pre_quote = $post_quote = "\x{7f}";
}
}
@@ -3037,8 +3216,8 @@ sub _convert($$)
# have been processed yet, and we need to output any pending spaces
# before 'end_line' throws them away. The argument to 'add_pending_word'
# does this.
- if ($root->{'parent'}->{'type'}
- and $root->{'parent'}->{'type'} eq 'preformatted') {
+ if ($element->{'parent'}->{'type'}
+ and $element->{'parent'}->{'type'} eq 'preformatted') {
$result .= _count_added($self,
$formatter->{'container'},
add_pending_word($formatter->{'container'}, 1));
@@ -3050,28 +3229,22 @@ sub _convert($$)
$result = $self->ensure_end_of_line($result) ;
}
- } elsif ($root->{'type'} eq 'frenchspacing') {
- push @{$formatter->{'frenchspacing_stack'}}, 'on';
- set_space_protection($formatter->{'container'}, undef, undef, undef, 1);
- } elsif ($root->{'type'} eq '_code') {
- if (!$formatter->{'font_type_stack'}->[-1]->{'monospace'}) {
- push @{$formatter->{'font_type_stack'}}, {'monospace' => 1};
- } else {
- $formatter->{'font_type_stack'}->[-1]->{'monospace'}++;
- }
+ } elsif ($element->{'type'} eq 'frenchspacing') {
push @{$formatter->{'frenchspacing_stack'}}, 'on';
set_space_protection($formatter->{'container'}, undef, undef, undef, 1);
- } elsif ($root->{'type'} eq 'bracketed') {
+ } elsif ($element->{'type'} eq '_code') {
+ _open_code($formatter);
+ } elsif ($element->{'type'} eq 'bracketed') {
$result .= _count_added($self, $formatter->{'container'},
add_text($formatter->{'container'}, '{'));
}
}
# The processing of contents is done here.
- if ($root->{'contents'}) {
- my @contents = @{$root->{'contents'}};
+ if ($element->{'contents'}) {
+ my @contents = @{$element->{'contents'}};
push @{$self->{'current_contents'}}, \@contents;
- push @{$self->{'current_roots'}}, $root;
+ push @{$self->{'current_roots'}}, $element;
while (@contents) {
my $content = shift @contents;
my $text = _convert($self, $content);
@@ -3084,26 +3257,19 @@ sub _convert($$)
}
# now closing. First, close types.
- if ($root->{'type'}) {
- if ($root->{'type'} eq 'frenchspacing') {
+ if ($element->{'type'}) {
+ if ($element->{'type'} eq 'frenchspacing') {
pop @{$formatter->{'frenchspacing_stack'}};
my $frenchspacing = 0;
$frenchspacing = 1 if ($formatter->{'frenchspacing_stack'}->[-1] eq 'on');
set_space_protection($formatter->{'container'}, undef,
undef, undef, $frenchspacing);
- } elsif ($root->{'type'} eq '_code') {
- $formatter->{'font_type_stack'}->[-1]->{'monospace'}--;
- pop @{$formatter->{'font_type_stack'}}
- if !$formatter->{'font_type_stack'}->[-1]->{'monospace'};
- pop @{$formatter->{'frenchspacing_stack'}};
- my $frenchspacing = 0;
- $frenchspacing = 1 if ($formatter->{'frenchspacing_stack'}->[-1] eq 'on');
- set_space_protection($formatter->{'container'}, undef,
- undef, undef, $frenchspacing);
- } elsif ($root->{'type'} eq 'bracketed') {
+ } elsif ($element->{'type'} eq '_code') {
+ _close_code($formatter);
+ } elsif ($element->{'type'} eq 'bracketed') {
$result .= _count_added($self, $formatter->{'container'},
add_text($formatter->{'container'}, '}'));
- } elsif ($root->{'type'} eq 'row') {
+ } elsif ($element->{'type'} eq 'row') {
my @cell_beginnings;
my @cell_lines;
my $cell_beginning = 0;
@@ -3122,11 +3288,13 @@ sub _convert($$)
}
$cell_idx = 0;
- my $cell_updated_locations;
+ my $cell_updated_locations = [];
my @row_locations;
foreach my $cell_locations (@{$self->{'format_context'}->[-1]->{'row_counts'}}) {
foreach my $location (@{$cell_locations->{'locations'}}) {
next unless (defined($location->{'bytes'}) and defined($location->{'lines'}));
+ $cell_updated_locations->[$cell_idx] = {}
+ if (!$cell_updated_locations->[$cell_idx]);
push @{$cell_updated_locations->[$cell_idx]->{$location->{'lines'}}},
$location;
$max_lines = $location->{'lines'}+1
@@ -3148,7 +3316,8 @@ sub _convert($$)
my $last_cell = 0;
for (my $cell_idx = 0; $cell_idx < $max_cell; $cell_idx++) {
$last_cell = $cell_idx+1 if (defined($cell_lines[$cell_idx]->[$line_idx])
- or defined($cell_updated_locations->[$cell_idx]->{$line_idx}));
+ or ($cell_updated_locations->[$cell_idx]
+ and defined($cell_updated_locations->[$cell_idx]->{$line_idx})));
}
for (my $cell_idx = 0; $cell_idx < $last_cell; $cell_idx++) {
@@ -3163,7 +3332,8 @@ sub _convert($$)
$bytes_count += count_bytes($self, $cell_text);
$line_width += Texinfo::Convert::Unicode::string_width($cell_text);
}
- if (defined($cell_updated_locations->[$cell_idx]->{$line_idx})) {
+ if ($cell_updated_locations->[$cell_idx]
+ and defined($cell_updated_locations->[$cell_idx]->{$line_idx})) {
foreach my $location (@{$cell_updated_locations->[$cell_idx]->{$line_idx}}) {
$location->{'bytes'} = $bytes_count;
}
@@ -3209,7 +3379,7 @@ sub _convert($$)
$self->{'format_context'}->[-1]->{'row_counts'} = [];
$self->{'format_context'}->[-1]->{'row_empty_lines_count'}
= $self->{'empty_lines_count'};
- } elsif ($root->{'type'} eq 'text_root') {
+ } elsif ($element->{'type'} eq 'before_node_section') {
$self->{'text_before_first_node'} = $result;
}
}
@@ -3242,19 +3412,21 @@ sub _convert($$)
# close commands
if ($command) {
if ($command eq 'float') {
- if ($root->{'extra'}
- and ($root->{'extra'}->{'type'}->{'normalized'} ne ''
- or defined($root->{'number'})
- or $root->{'extra'}->{'caption'} or $root->{'extra'}->{'shortcaption'})) {
+ if ($element->{'extra'}
+ and (($element->{'extra'}->{'type'}
+ and $element->{'extra'}->{'type'}->{'normalized'} ne '')
+ or ($element->{'structure'}
+ and defined($element->{'structure'}->{'float_number'}))
+ or $element->{'extra'}->{'caption'} or $element->{'extra'}->{'shortcaption'})) {
$result .= _add_newline_if_needed($self);
- my ($caption, $prepended) = Texinfo::Common::float_name_caption($self,
- $root);
+ my ($caption, $prepended)
+ = Texinfo::Convert::Converter::float_name_caption($self, $element);
if ($prepended) {
$prepended->{'type'} = 'frenchspacing';
my $float_number = $self->convert_line ($prepended);
$result .= $float_number;
- $self->{'text_element_context'}->[-1]->{'counter'} +=
+ $self->{'text_element_context'}->[-1]->{'counter'} +=
Texinfo::Convert::Unicode::string_width($float_number);
$self->{'empty_lines_count'} = 0;
}
@@ -3266,8 +3438,8 @@ sub _convert($$)
}
} elsif (($command eq 'quotation'
or $command eq 'smallquotation')
- and $root->{'extra'} and $root->{'extra'}->{'authors'}) {
- foreach my $author (@{$root->{'extra'}->{'authors'}}) {
+ and $element->{'extra'} and $element->{'extra'}->{'authors'}) {
+ foreach my $author (@{$element->{'extra'}->{'authors'}}) {
$result .= _convert($self,
$self->gdt("\@center --- \@emph{{author}}\n",
{'author' => $author->{'args'}->[0]->{'contents'}}));
@@ -3275,10 +3447,10 @@ sub _convert($$)
} elsif (($command eq 'multitable')) {
$self->{'document_context'}->[-1]->{'in_multitable'}--;
} elsif ($root_commands{$command}
- and $sectioning_commands{$command}
+ and $sectioning_heading_commands{$command}
and $command ne 'part') {
# add menu if missing
- my $node = $self->{'node'};
+ my $node = $self->{'current_node'};
my $automatic_directions;
if ($node and defined($node->{'extra'}->{'nodes_manuals'})) {
$automatic_directions =
@@ -3287,7 +3459,7 @@ sub _convert($$)
if ($node and $automatic_directions
and !$self->{'seenmenus'}->{$node}) {
$self->{'seenmenus'}->{$node} = 1;
- my $menu_node = Texinfo::Structuring::new_complete_node_menu(undef, $node);
+ my $menu_node = Texinfo::Structuring::new_complete_node_menu($node);
if ($menu_node) {
my $menu_text = $self->_convert($menu_node);
if ($menu_text) {
@@ -3322,7 +3494,7 @@ sub _convert($$)
pop @{$self->{'format_context'}};
pop @{$self->{'text_element_context'}};
push @{$self->{'format_context'}->[-1]->{'row'}}, $result;
- _update_count_context($self);
+ update_count_context($self);
my $cell_counts = pop @{$self->{'count_context'}};
push @{$self->{'format_context'}->[-1]->{'row_counts'}}, $cell_counts;
$result = '';
@@ -3338,7 +3510,6 @@ sub _convert($$)
1;
__END__
-# $Id$
# Automatically generated from maintain/template.pod
=head1 NAME
@@ -3347,13 +3518,18 @@ Texinfo::Convert::Plaintext - Convert Texinfo tree to Plaintext
=head1 SYNOPSIS
- my $converter
+ my $converter
= Texinfo::Convert::Plaintext->converter({'parser' => $parser});
$converter->output($tree);
$converter->convert($tree);
$converter->convert_tree($tree);
+=head1 NOTES
+
+The Texinfo Perl module main purpose is to be used in C<texi2any> to convert
+Texinfo to other formats. There is no promise of API stability.
+
=head1 DESCRIPTION
Texinfo::Convert::Plaintext converts a Texinfo tree to Plaintext.
@@ -3364,15 +3540,18 @@ Texinfo::Convert::Plaintext converts a Texinfo tree to Plaintext.
=item $converter = Texinfo::Convert::Plaintext->converter($options)
-Initialize converter from Texinfo to Plaintext.
+Initialize converter from Texinfo to Plaintext.
The I<$options> hash reference holds options for the converter. In
-this option hash reference a parser object may be associated with the
-I<parser> key. The other options should be configuration options
-described in the Texinfo manual. Those options, when appropriate,
-override the document content.
+this option hash reference a L<parser object|Texinfo::Parser>
+may be associated with the I<parser> key. The other options
+are Texinfo customization options and a few other options that can
+be passed to the converter. Most of the customization options are described in
+the Texinfo manual. Those customization options, when appropriate, override
+the document content. The parser should not be available directly anymore
+after getting the associated information.
-See L<Texinfo::Convert::Converter> for more informations.
+See L<Texinfo::Convert::Converter> for more information.
=item $converter->output($tree)
@@ -3381,12 +3560,11 @@ described in the Texinfo manual.
=item $result = $converter->convert($tree)
-Convert a Texinfo tree I<$tree> or tree portion and return
-the resulting output.
+Convert a Texinfo tree I<$tree> and return the resulting output.
=item $result = $converter->convert_tree($tree)
-Convert a Texinfo tree portion I<$tree> and return the resulting
+Convert a Texinfo tree portion I<$tree> and return the resulting
output. This function does not try to output a full document but only
portions. For a full document use C<convert>.
@@ -3396,4 +3574,14 @@ portions. For a full document use C<convert>.
Patrice Dumas, E<lt>pertusus@free.frE<gt>
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2010- Free Software Foundation, Inc. See the source file for
+all copyright years.
+
+This library 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 3 of the License, or (at
+your option) any later version.
+
=cut