if ($self->in_preformatted()) {
$result .= ''.$heading.''."\n";
} else {
# if the level was changed, set the command name right
if ($cmdname ne 'node'
and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
$cmdname
= $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
}
$result .= &{$self->{'format_heading_text'}}($self, $cmdname, $heading,
$heading_level +$self->get_conf('CHAPTER_HEADER_LEVEL') -1, $command);
}
}
$result .= $content if (defined($content));
my $table_of_contents_was_output = 0.;
if ($self->get_conf('CONTENTS_OUTPUT_LOCATION') eq 'after_top'
and $cmdname eq 'top'
and $self->{'structuring'} and $self->{'structuring'}->{'sectioning_root'}
and scalar(@{$self->{'structuring'}->{'sections_list'}}) > 1) {
foreach my $content_command_name ('contents', 'shortcontents') {
if ($self->get_conf($content_command_name)) {
my $contents_text
= $self->_contents_inline_element($content_command_name, undef);
if ($contents_text ne '') {
$result .= $contents_text;
#$result .= $contents_text . $self->get_conf('DEFAULT_RULE')."\n";
$table_of_contents_was_output = 1;
}
}
}
}
if (not $table_of_contents_was_output
and $self->get_conf('FORMAT_MENU') eq 'sectiontoc'
and $sectioning_commands{$cmdname}
and ($cmdname ne 'top'
or (not ($self->_has_contents_or_shortcontents()
and $self->get_conf('CONTENTS_OUTPUT_LOCATION')
eq 'inline')))) {
$result .= _mini_toc($self, $command);
}
return $result;
}
foreach my $command (keys(%sectioning_commands), 'node') {
$default_commands_conversion{$command} = \&_convert_heading_command;
}
sub _convert_raw_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($cmdname eq $self->{'output_format'}) {
return $content;
}
$self->line_warn(sprintf(__("raw format %s is not converted"),
$cmdname), $command->{'line_nr'});
return $self->protect_text($content);
}
foreach my $command (keys(%format_raw_commands)) {
$default_commands_conversion{$command} = \&_convert_raw_command;
}
sub _convert_inline_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $format_arg = shift @$args;
my $format;
if (defined($format_arg)) {
$format = $format_arg->{'monospacetext'};
}
return '' if (!defined($format) or $format eq '');
my $arg_index = undef;
if ($inline_format_commands{$cmdname}) {
if ($cmdname eq 'inlinefmtifelse'
and ! $self->{'expanded_formats_hash'}->{$format}) {
$arg_index = 1;
} elsif ($self->{'expanded_formats_hash'}->{$format}) {
$arg_index = 0;
}
} elsif (defined($command->{'extra'}->{'expand_index'})) {
$arg_index = 0;
}
if (defined($arg_index) and $arg_index < scalar(@$args)) {
my $text_arg = $args->[$arg_index];
if ($text_arg) {
if ($text_arg->{'normal'}) {
return $text_arg->{'normal'};
} elsif ($text_arg->{'raw'}) {
return $text_arg->{'raw'};
}
}
}
return '';
}
foreach my $command (keys(%inline_commands)) {
$default_commands_conversion{$command} = \&_convert_inline_command;
}
sub _indent_with_table ($)
{
my $content = shift;
return '
\n";
}
my $html_menu_entry_index = 0;
sub _convert_preformatted_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
my $extra_classes;
# this is mainly for classes as there are purprosely no classes
# for small*
my $main_cmdname;
if ($small_alias{$cmdname}) {
$main_cmdname = $small_alias{$cmdname};
} else {
$main_cmdname = $cmdname;
}
if ($cmdname eq 'menu') {
$html_menu_entry_index = 0;
} elsif ($cmdname eq 'example') {
if ($command->{'args'}) {
$extra_classes = [];
for my $example_arg (@{$command->{'args'}}) {
# convert or remove all @-commands, using simple ascii and unicode
# characters
my $converted_arg = Texinfo::Convert::NodeNameNormalization::convert($example_arg);
if ($converted_arg ne '') {
push @$extra_classes, $converted_arg;
}
}
}
} elsif ($main_cmdname eq 'lisp') {
$main_cmdname = 'example';
$extra_classes = ['lisp'];
}
if ($content ne '' and !$self->in_string()) {
if ($self->get_conf('COMPLEX_FORMAT_IN_TABLE')) {
if ($indented_preformatted_commands{$cmdname}) {
return _indent_with_table ($content);
} else {
return $content."\n";
}
} else {
return $self->_attribute_class('div', $main_cmdname, $extra_classes).">\n".$content.''."\n";
}
} else {
return $content;
}
}
foreach my $preformatted_command (keys(%preformatted_commands)) {
$default_commands_conversion{$preformatted_command}
= \&_convert_preformatted_command;
}
sub _convert_indented_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
# no class for @small* variants
$cmdname = $small_alias{$cmdname}
if $small_alias{$cmdname};
if ($content ne '' and !$self->in_string()) {
if ($self->get_conf('COMPLEX_FORMAT_IN_TABLE')) {
return _indent_with_table ($content);
} else {
return $self->_attribute_class('blockquote', $cmdname).">\n"
.$content.''."\n";
}
} else {
return $content;
}
}
$default_commands_conversion{'indentedblock'} = \&_convert_indented_command;
sub _convert_verbatim_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if (!$self->in_string) {
return $self->_attribute_class('pre', $cmdname).'>'
.$content . '';
} else {
return $content;
}
}
$default_commands_conversion{'verbatim'} = \&_convert_verbatim_command;
sub _convert_displaymath_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string) {
return $content;
}
my $result = '';
$result .= $self->_attribute_class('div', 'displaymath').'>';
if ($self->get_conf('HTML_MATH')
and $self->get_conf('HTML_MATH') eq 'mathjax') {
$self->{'element_math'} = 1;
$result .= $self->_attribute_class('em', 'tex2jax_process').'>'
."\\[$content\\]".'';
} else {
$result .= $self->_attribute_class('em').'>'."$content".'';
}
$result .= '';
return $result;
}
$default_commands_conversion{'displaymath'} = \&_convert_displaymath_command;
sub _convert_verbatiminclude_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $verbatim_include_verbatim
= $self->Texinfo::Common::expand_verbatiminclude($command);
if (defined($verbatim_include_verbatim)) {
return $self->convert_tree($verbatim_include_verbatim);
} else {
return '';
}
}
$default_commands_conversion{'verbatiminclude'}
= \&_convert_verbatiminclude_command;
sub _convert_command_noop($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
return $content;
}
$default_commands_conversion{'raggedright'} = \&_convert_command_noop;
$default_commands_conversion{'flushleft'} = \&_convert_command_noop;
$default_commands_conversion{'flushright'} = \&_convert_command_noop;
$default_commands_conversion{'group'} = \&_convert_command_noop;
sub _convert_sp_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
if (defined($command->{'extra'}->{'misc_args'}->[0])) {
my $sp_nr = $command->{'extra'}->{'misc_args'}->[0];
if ($self->in_preformatted() or $self->in_string()) {
return "\n" x $sp_nr;
} else {
return "
\n" x $sp_nr;
}
}
}
$default_commands_conversion{'sp'} = \&_convert_sp_command;
sub _convert_exdent_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
# FIXME do something better with css and span?
my $preformatted = $self->in_preformatted();
if ($self->in_preformatted() or $self->in_string()) {
return $self->_convert_preformatted_type($cmdname, $command,
$args->[0]->{'normal'} ."\n");
} else {
# ignore alignment information
return "".$args->[0]->{'normal'} ."\n
";
}
}
$default_commands_conversion{'exdent'} = \&_convert_exdent_command;
sub _convert_center_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
if ($self->in_string()) {
return $self->_convert_preformatted_type($cmdname, $command,
$args->[0]->{'normal'}."\n");
} else {
return "".$args->[0]->{'normal'}."\n
";
}
}
$default_commands_conversion{'center'} = \&_convert_center_command;
sub _convert_author_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
return '' if (!$args->[0] or !$command->{'extra'}->{'titlepage'});
if (!$self->in_string()) {
return "$args->[0]->{'normal'}
\n";
} else {
return $args->[0]->{'normal'}."\n";
}
}
$default_commands_conversion{'author'} = \&_convert_author_command;
sub _convert_title_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
return '' if (!$args->[0]);
if (!$self->in_string()) {
return "$args->[0]->{'normal'}
\n";
} else {
return $args->[0]->{'normal'};
}
}
$default_commands_conversion{'title'} = \&_convert_title_command;
sub _convert_subtitle_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
return '' if (!$args->[0]);
if (!$self->in_string()) {
return "$args->[0]->{'normal'}
\n";
} else {
return $args->[0]->{'normal'};
}
}
$default_commands_conversion{'subtitle'} = \&_convert_subtitle_command;
sub _convert_insertcopying_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
if ($self->{'extra'} and $self->{'extra'}->{'copying'}) {
return $self->convert_tree({'contents'
=> $self->{'extra'}->{'copying'}->{'contents'}});
}
return '';
}
$default_commands_conversion{'insertcopying'}
= \&_convert_insertcopying_command;
sub _convert_listoffloats_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
if (!$self->in_string()
and $command->{'extra'} and $command->{'extra'}->{'type'}
and defined($command->{'extra'}->{'type'}->{'normalized'})
and $self->{'floats'}
and $self->{'floats'}->{$command->{'extra'}->{'type'}->{'normalized'}}
and @{$self->{'floats'}->{$command->{'extra'}->{'type'}->{'normalized'}}}) {
my $listoffloats_name = $command->{'extra'}->{'type'}->{'normalized'};
my $result = $self->_attribute_class('dl', 'listoffloats').">\n" ;
foreach my $float (@{$self->{'floats'}->{$listoffloats_name}}) {
my $float_href = $self->command_href($float);
next if (!$float_href);
$result .= '';
my $float_text = $self->command_text($float);
if (defined($float_text) and $float_text ne '') {
if ($float_href) {
$result .= "$float_text";
} else {
$result .= $float_text;
}
}
$result .= '';
my $caption;
if ($float->{'extra'}->{'shortcaption'}) {
$caption = $float->{'extra'}->{'shortcaption'};
} elsif ($float->{'extra'}->{'caption'}) {
$caption = $float->{'extra'}->{'caption'};
}
my $caption_text;
if ($caption) {
$caption_text = $self->convert_tree_new_formatting_context(
$caption->{'args'}->[0], $cmdname, 'listoffloats');
} else {
$caption_text = '';
}
$result .= ''.$caption_text.''."\n";
}
return $result . "\n";
} else {
return '';
}
}
$default_commands_conversion{'listoffloats'} = \&_convert_listoffloats_command;
sub _in_preformatted_in_menu($)
{
my $self = shift;
return 1 if ($self->get_conf('SIMPLE_MENU'));
my @pre_classes = $self->preformatted_classes_stack();
foreach my $pre_class (@pre_classes) {
return 1 if ($preformatted_commands{$pre_class});
}
return 0;
}
sub _convert_menu_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
return $content if ($cmdname eq 'detailmenu');
$html_menu_entry_index = 0;
if ($content !~ /\S/) {
return '';
}
# This can probably only happen with incorrect input,
# for instance menu in copying
# FIXME check?
if ($self->in_string()) {
return $content;
}
my $begin_row = '';
my $end_row = '';
if ($self->_in_preformatted_in_menu()) {
$begin_row = '';
$end_row = ' |
';
}
return $self->_attribute_class('table', 'menu')
." border=\"0\" cellspacing=\"0\">${begin_row}\n"
. $content . "${end_row}\n";
}
$default_commands_conversion{'menu'} = \&_convert_menu_command;
$default_commands_conversion{'detailmenu'} = \&_convert_menu_command;
sub _convert_float_command($$$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $content = shift;
my ($caption, $prepended) = Texinfo::Common::float_name_caption($self,
$command);
my $caption_text = '';
my $prepended_text;
if ($self->in_string()) {
if ($prepended) {
$prepended_text = $self->convert_tree_new_formatting_context(
$prepended, 'float prepended');
} else {
$prepended_text = '';
}
if ($caption) {
$caption_text = $self->convert_tree_new_formatting_context(
{'contents' => $caption->{'args'}->[0]->{'contents'}},
'float caption');
}
return $prepended.$content.$caption_text;
}
my $id = $self->command_id($command);
my $label;
if (defined($id) and $id ne '') {
$label = "";
} else {
$label = '';
}
if ($prepended) {
if ($caption) {
# prepend the prepended tree to the first paragraph
my @caption_original_contents = @{$caption->{'args'}->[0]->{'contents'}};
my @caption_contents;
my $new_paragraph;
while (@caption_original_contents) {
my $content = shift @caption_original_contents;
if ($content->{'type'} and $content->{'type'} eq 'paragraph') {
%{$new_paragraph} = %{$content};
$new_paragraph->{'contents'} = [@{$content->{'contents'}}];
unshift (@{$new_paragraph->{'contents'}}, {'cmdname' => 'strong',
'args' => [{'type' => 'brace_command_arg',
'contents' => [$prepended]}]});
push @caption_contents, $new_paragraph;
last;
} else {
push @caption_contents, $content;
}
}
push @caption_contents, @caption_original_contents;
if ($new_paragraph) {
$caption_text = $self->convert_tree_new_formatting_context(
{'contents' => \@caption_contents}, 'float caption');
$prepended_text = '';
}
}
if ($caption_text eq '') {
$prepended_text = $self->convert_tree_new_formatting_context(
$prepended, 'float prepended');
if ($prepended_text ne '') {
$prepended_text = ''.$prepended_text.'
';
}
}
} else {
$prepended_text = '';
}
if ($caption and $caption_text eq '') {
$caption_text = $self->convert_tree_new_formatting_context(
$caption->{'args'}->[0], 'float caption');
}
if ($prepended_text.$caption_text ne '') {
$prepended_text = $self->_attribute_class('div','float-caption'). '>'
. $prepended_text;
$caption_text .= '';
}
return $self->_attribute_class('div','float'). '>' .$label."\n".$content.
$prepended_text.$caption_text . '';
}
$default_commands_conversion{'float'} = \&_convert_float_command;
sub _convert_quotation_command($$$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $content = shift;
#$cmdname = $small_alias{$cmdname}
# if $small_alias{$cmdname};
my $attribution = '';
if ($command->{'extra'} and $command->{'extra'}->{'authors'}) {
foreach my $author (@{$command->{'extra'}->{'authors'}}) {
my $centered_author = $self->gdt("\@center --- \@emph{{author}}\n",
{'author' => $author->{'args'}->[0]->{'contents'}});
$centered_author->{'parent'} = $command;
$attribution .= $self->convert_tree($centered_author);
}
}
if (!$self->in_string()) {
return "\n" . $content . "
\n" . $attribution;
} else {
return $content.$attribution;
}
}
$default_commands_conversion{'quotation'} = \&_convert_quotation_command;
sub _convert_cartouche_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($content =~ /\S/ and !$self->in_string()) {
return $self->_attribute_class('table', 'cartouche')
." border=\"1\">\n". $content ." |
\n";
}
return $content;
}
$default_commands_conversion{'cartouche'} = \&_convert_cartouche_command;
sub _convert_itemize_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string()) {
return $content;
}
if ($command->{'extra'}->{'command_as_argument'}
and $command->{'extra'}->{'command_as_argument'}->{'cmdname'} eq 'bullet') {
return "\n";
} else {
return $self->_attribute_class('ul',$NO_BULLET_LIST_CLASS).">\n"
. $content . "\n";
}
}
$default_commands_conversion{'itemize'} = \&_convert_itemize_command;
sub _convert_enumerate_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string()) {
return $content;
}
if ($content eq '') {
return '';
}
my $specification = $command->{'extra'}->{'enumerate_specification'};
if (defined $specification) {
my ($start, $type);
if ($specification =~ /^\d*$/ and $specification ne '1') {
$start = $specification;
} elsif ($specification =~ /^[A-Z]$/) {
$start = 1 + ord($specification) - ord('A');
$type = 'A';
} elsif ($specification =~ /^[a-z]$/) {
$start = 1 + ord($specification) - ord('a');
$type = 'a';
}
if (defined $type and defined $start) {
return "\n" . $content . "
\n";
} elsif (defined $start) {
return "\n" . $content . "
\n";
}
}
return "\n" . $content . "
\n";
}
$default_commands_conversion{'enumerate'} = \&_convert_enumerate_command;
sub _convert_multitable_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string()) {
return $content;
}
if ($content =~ /\S/) {
return "\n";
} else {
return '';
}
}
$default_commands_conversion{'multitable'} = \&_convert_multitable_command;
sub _convert_xtable_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string()) {
return $content;
}
if ($content ne '') {
return "\n" . $content . "
\n";
} else {
return '';
}
}
$default_commands_conversion{'table'} = \&_convert_xtable_command;
$default_commands_conversion{'ftable'} = \&_convert_xtable_command;
$default_commands_conversion{'vtable'} = \&_convert_xtable_command;
sub _convert_item_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
if ($self->in_string()) {
return $content;
}
if ($command->{'parent'}->{'cmdname'}
and $command->{'parent'}->{'cmdname'} eq 'itemize') {
my $prepend ;
my $itemize = $command->{'parent'};
if ($itemize->{'extra'}->{'command_as_argument'}
and $itemize->{'extra'}->{'command_as_argument'}->{'cmdname'} eq 'bullet') {
$prepend = '';
} else {
# Setting multiple expansion should not be needed, except in
# case of invalid constructs
$prepend = $self->convert_tree_new_formatting_context(
$itemize->{'args'}->[0],
$command->{'cmdname'}, 'item_prepended');
}
if ($content =~ /\S/) {
return '' . $prepend .' '. $content . '';
} else {
return '';
}
} elsif ($command->{'parent'}->{'cmdname'}
and $command->{'parent'}->{'cmdname'} eq 'enumerate') {
if ($content =~ /\S/) {
return '' . ' ' . $content . '';
} else {
return '';
}
} elsif ($command->{'parent'}->{'type'}
and $command->{'parent'}->{'type'} eq 'table_term') {
# FIXME instead use the code of Plaintext or DocBook.
my $args = $content;
if ($args->[0]) {
my $tree = $self->_table_item_content_tree($command,
[$args->[0]->{'tree'}]);
my $result = $self->convert_tree ($tree);
foreach my $command_name (reverse($self->commands_stack())) {
if ($preformatted_code_commands{$command_name}) {
$result = '' .$result. '';
last;
}
}
my $index_id = $self->command_id ($command);
my $anchor;
if (defined($index_id)) {
$anchor = $self->_get_copiable_anchor($index_id);
$index_id = " id='$index_id'";
} else {
$anchor = '';
$index_id = '';
}
return "$result$anchor\n";
} else {
return '';
}
} elsif ($command->{'parent'}->{'type'}
and $command->{'parent'}->{'type'} eq 'row') {
return $self->_convert_tab_command ($cmdname, $command, $content);
}
return '';
}
$default_commands_conversion{'item'} = \&_convert_item_command;
$default_commands_conversion{'headitem'} = \&_convert_item_command;
$default_commands_conversion{'itemx'} = \&_convert_item_command;
sub _convert_tab_command ($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = shift;
my $cell_nr = $command->{'extra'}->{'cell_number'};
my $row = $command->{'parent'};
my $row_cmdname = $row->{'contents'}->[0]->{'cmdname'};
my $multitable = $row->{'parent'}->{'parent'};
my $fractions = '';
my $cf = $multitable->{'extra'}->{'columnfractions'};
if ($cf) {
if (exists($cf->{'extra'}->{'misc_args'}->[$cell_nr-1])) {
my $fraction = sprintf('%d',
100*$cf->{'extra'}->{'misc_args'}->[$cell_nr-1]);
$fractions = " width=\"$fraction%\"";
}
}
$content =~ s/^\s*//;
$content =~ s/\s*$//;
if ($self->in_string()) {
return $content;
}
if ($row_cmdname eq 'headitem') {
return "" . $content . ' | ';
} else {
return "" . $content . ' | ';
}
}
$default_commands_conversion{'tab'} = \&_convert_tab_command;
sub _convert_xref_commands($$$$)
{
my $self = shift;
my $cmdname = shift;
my $root = shift;
my $args = shift;
my $tree;
my $name;
if ($cmdname ne 'inforef'
and defined($args->[2]->{'normal'}) and $args->[2]->{'normal'} ne '') {
$name = $args->[2]->{'normal'};
} elsif (defined($args->[1]->{'normal'}) and $args->[1]->{'normal'} ne '') {
$name = $args->[1]->{'normal'}
}
if ($cmdname eq 'inforef') {
$args->[3] = $args->[2];
$args->[2] = undef;
}
my $file_arg_tree;
my $file = '';
if (defined($args->[3]->{'monospacetext'})
and $args->[3]->{'monospacetext'} ne '') {
$file_arg_tree = $args->[3]->{'tree'};
$file = $args->[3]->{'monospacetext'};
}
my $book = '';
$book = $args->[4]->{'normal'} if (defined($args->[4]->{'normal'}));
# internal reference
if ($cmdname ne 'inforef' and $book eq '' and $file eq ''
and $root->{'extra'}->{'node_argument'}
and defined($root->{'extra'}->{'node_argument'}->{'normalized'})
and !$root->{'extra'}->{'node_argument'}->{'manual_content'}
and $self->{'labels'}
and $self->{'labels'}->{$root->{'extra'}->{'node_argument'}->{'normalized'}}) {
my $node
= $self->label_command($root->{'extra'}->{'node_argument'}->{'normalized'});
# This is the node if USE_NODES, otherwise this may be the sectioning
# command (if the sectioning command is really associated to the node)
my $command = $self->command_element_command($node);
$command = $node if (!$node->{'extra'}->{'associated_section'}
or $node->{'extra'}->{'associated_section'} ne $command);
my $href = $self->command_href($command, undef, $root);
if (!defined($name)) {
if ($self->get_conf('xrefautomaticsectiontitle') eq 'on'
and $node->{'extra'}->{'associated_section'}) {
$command = $node->{'extra'}->{'associated_section'};
$name = $self->command_text($command, 'text_nonumber');
} elsif ($node->{'cmdname'} eq 'float') {
if (!$self->get_conf('XREF_USE_FLOAT_LABEL')) {
$name = $self->command_text($command);
}
if (!defined($name) or $name eq '') {
if (defined($args->[0]->{'monospace'})) {
$name = $args->[0]->{'monospace'};
} else {
$name = '';
}
}
} elsif (!$self->get_conf('XREF_USE_NODE_NAME_ARG')
and (defined($self->get_conf('XREF_USE_NODE_NAME_ARG'))
or !$self->in_preformatted())) {
$name = $self->command_text($command, 'text_nonumber');
#die "$command $command->{'normalized'}" if (!defined($name));
} elsif (defined($args->[0]->{'monospace'})) {
$name = $args->[0]->{'monospace'};
} else {
$name = '';
}
}
my $reference = $name;
$reference = "$name" if ($href ne ''
and !$self->in_string());
# maybe use {'extra'}->{'node_argument'}?
my $is_section = ($command->{'cmdname'} ne 'node'
and $command->{'cmdname'} ne 'anchor'
and $command->{'cmdname'} ne 'float');
if ($cmdname eq 'pxref') {
$tree = $self->gdt('see {reference_name}',
{ 'reference_name' => {'type' => '_converted', 'text' => $reference} });
} elsif ($cmdname eq 'xref' or $cmdname eq 'inforef') {
$tree = $self->gdt('See {reference_name}',
{ 'reference_name' => {'type' => '_converted', 'text' => $reference} });
} elsif ($cmdname eq 'ref') {
$tree = $self->gdt('{reference_name}',
{ 'reference_name' => {'type' => '_converted', 'text' => $reference} });
}
} else {
# external reference
my $node_entry = {};
$node_entry->{'node_content'} = $root->{'extra'}->{'node_argument'}->{'node_content'}
if ($root->{'extra'}->{'node_argument'}
and $root->{'extra'}->{'node_argument'}->{'node_content'});
$node_entry->{'normalized'} = $root->{'extra'}->{'node_argument'}->{'normalized'}
if ($root->{'extra'}->{'node_argument'}
and exists($root->{'extra'}->{'node_argument'}->{'normalized'}));
# file argument takes precedence over the file in the node (file)node entry
if (defined($file_arg_tree) and $file ne '') {
$node_entry->{'manual_content'} = $file_arg_tree->{'contents'};
} elsif ($root->{'extra'}->{'node_argument'}
and $root->{'extra'}->{'node_argument'}->{'manual_content'}) {
$node_entry->{'manual_content'}
= $root->{'extra'}->{'node_argument'}->{'manual_content'};
my $file_with_node_tree = {'type' => '_code',
'contents' => [@{$node_entry->{'manual_content'}}]};
$file = $self->convert_tree($file_with_node_tree, 'node file in ref');
}
my $href = $self->command_href($node_entry, undef, $root);
if ($book eq '') {
if (!defined($name)) {
my $node_name = $self->command_text($node_entry);
$name = $node_name;
} elsif ($file ne '') {
$name = "($file)$name";
}
} elsif (!defined($name) and $node_entry->{'node_content'}) {
my $node_no_file_tree = {'type' => '_code',
'contents' => [@{$node_entry->{'node_content'}}]};
my $node_name = $self->convert_tree($node_no_file_tree, 'node in ref');
if (defined($node_name) and ($self->get_conf('KEEP_TOP_EXTERNAL_REF')
or $node_name ne 'Top')) {
$name = $node_name;
}
}
# not exactly sure when it happens. Something like @ref{(file),,,Manual}?
$name = $args->[0]->{'monospace'}
if (!defined($name)
# FIXME could it really be Top?
and ($self->get_conf('KEEP_TOP_EXTERNAL_REF')
or $args->[0]->{'monospace'} ne 'Top'));
$name = '' if (!defined($name));
my $reference = $name;
my $book_reference = '';
if (!$self->in_string() and $href ne '') {
# attribute to distiguish links to Texinfo manuals from other links
# and to provide manual name of target
my $attribute = '';
if ($file) {
$attribute = "data-manual=\"".$self->protect_text($file)."\" ";
}
if ($name ne '') {
$reference = "$name";
} elsif ($book ne '') {
$book_reference = "$book";
}
}
if ($cmdname eq 'pxref') {
if (($book ne '') and ($href ne '') and ($reference ne '')) {
$tree = $self->gdt('see {reference} in @cite{{book}}',
{ 'reference' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book_reference ne '') {
$tree = $self->gdt('see @cite{{book_reference}}',
{ 'book_reference' => {'type' => '_converted',
'text' => $book_reference }});
} elsif (($book ne '') and ($reference ne '')) {
$tree = $self->gdt('see `{section}\' in @cite{{book}}',
{ 'section' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book ne '') { # should seldom or even never happen
$tree = $self->gdt('see @cite{{book}}',
{'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($href ne '') {
$tree = $self->gdt('see {reference}',
{ 'reference' => {'type' => '_converted', 'text' => $reference} });
} elsif ($reference ne '') {
$tree = $self->gdt('see `{section}\'', {
'section' => {'type' => '_converted', 'text' => $reference} });
}
} elsif ($cmdname eq 'xref' or $cmdname eq 'inforef') {
if (($book ne '') and ($href ne '') and ($reference ne '')) {
$tree = $self->gdt('See {reference} in @cite{{book}}',
{ 'reference' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book_reference ne '') {
$tree = $self->gdt('See @cite{{book_reference}}',
{ 'book_reference' => {'type' => '_converted',
'text' => $book_reference }});
} elsif (($book ne '') and ($reference ne '')) {
$tree = $self->gdt('See `{section}\' in @cite{{book}}',
{ 'section' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book ne '') { # should seldom or even never happen
$tree = $self->gdt('See @cite{{book}}',
{'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($href ne '') {
$tree = $self->gdt('See {reference}',
{ 'reference' => {'type' => '_converted', 'text' => $reference} });
} elsif ($reference ne '') {
$tree = $self->gdt('See `{section}\'', {
'section' => {'type' => '_converted', 'text' => $reference} });
}
} else {
if (($book ne '') and ($href ne '') and ($reference ne '')) {
$tree = $self->gdt('{reference} in @cite{{book}}',
{ 'reference' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book_reference ne '') {
$tree = $self->gdt('@cite{{book_reference}}',
{ 'book_reference' => {'type' => '_converted',
'text' => $book_reference }});
} elsif (($book ne '') and ($reference ne '')) {
$tree = $self->gdt('`{section}\' in @cite{{book}}',
{ 'section' => {'type' => '_converted', 'text' => $reference},
'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($book ne '') { # should seldom or even never happen
$tree = $self->gdt('@cite{{book}}',
{'book' => {'type' => '_converted', 'text' => $book }});
} elsif ($href ne '') {
$tree = $self->gdt('{reference}',
{ 'reference' => {'type' => '_converted', 'text' => $reference} });
} elsif ($reference ne '') {
$tree = $self->gdt('`{section}\'', {
'section' => {'type' => '_converted', 'text' => $reference} });
}
}
if (!defined($tree)) {
# May happen if there is no argument
#die "external: $cmdname, ($args), '$name' '$file' '$book' '$href' '$reference'. tree undef";
return '';
}
}
return $self->convert_tree($tree);
}
foreach my $command(keys(%ref_commands)) {
$default_commands_conversion{$command} = \&_convert_xref_commands;
}
sub _convert_index_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $index_id = $self->command_id($command);
if (defined($index_id) and $index_id ne ''
and !@{$self->{'multiple_pass'}}
and !$self->in_string()) {
my $result = "";
$result .= "\n" unless ($self->in_preformatted());
return $result;
}
return '';
}
$default_commands_conversion{'cindex'} = \&_convert_index_command;
my %formatted_index_entries;
sub _convert_printindex_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $args = shift;
my $index_name;
if ($command->{'extra'} and $command->{'extra'}->{'misc_args'}
and defined($command->{'extra'}->{'misc_args'}->[0])) {
$index_name = $command->{'extra'}->{'misc_args'}->[0];
} else {
return '';
}
if (!$self->{'index_entries_by_letter'}
or !$self->{'index_entries_by_letter'}->{$index_name}
or !@{$self->{'index_entries_by_letter'}->{$index_name}}) {
return '';
}
#foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
# print STDERR "IIIIIII $letter_entry->{'letter'}\n";
# foreach my $index_entry (@{$letter_entry->{'entries'}}) {
# print STDERR " ".join('|', keys(%$index_entry))."||| $index_entry->{'key'}\n";
# }
#}
return '' if ($self->in_string());
$self->_new_document_context($cmdname);
my $result = '';
# First do the summary letters linking to the letters done below
my %letter_id;
my @non_alpha = ();
my @alpha = ();
# collect the links
my $symbol_idx = 0;
foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
my $letter = $letter_entry->{'letter'};
my $index_element_id = $self->_element_direction($self->{'current_element'},
'This', 'target');
if (!defined($index_element_id)) {
$index_element_id = $target_prefix;
}
my $is_symbol = $letter !~ /^[[:alpha:]]/;
my $identifier;
if ($is_symbol) {
$symbol_idx++;
$identifier = $index_element_id . "_${index_name}_symbol-$symbol_idx";
} else {
$identifier = $index_element_id . "_${index_name}_letter-${letter}";
}
$letter_id{$letter} = $identifier;
my $summary_letter_link = $self->_attribute_class('a', 'summary-letter')
." href=\"#$identifier\">".$self->protect_text($letter).'';
if ($is_symbol) {
push @non_alpha, $summary_letter_link;
} else {
push @alpha, $summary_letter_link;
}
}
# Format the summary letters
my $join = '';
my $non_alpha_text = '';
my $alpha_text = '';
$join = " \n
\n" if (@non_alpha and @alpha);
if (@non_alpha) {
$non_alpha_text = join("\n \n", @non_alpha) . "\n";
}
if (@alpha) {
$alpha_text = join("\n \n", @alpha) . "\n \n";
}
# format the summary
my $summary = ""
. $self->convert_tree($self->gdt('Jump to')) .": | " .
$non_alpha_text . $join . $alpha_text . " |
---|
\n";
$result .= $summary;
# now format the index entries
$result .= $self->_attribute_class('table', "index-$index_name")
." border=\"0\">\n" . " | "
. $self->convert_tree($self->gdt('Index Entry'))
. " | | "
. $self->convert_tree($self->gdt('Section'))
." |
\n" . " ".$self->get_conf('DEFAULT_RULE')
." |
\n";
foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
my $letter = $letter_entry->{'letter'};
my $entries_text = '';
foreach my $index_entry_ref (@{$letter_entry->{'entries'}}) {
# to avoid double error messages set ignore_notice if an entry was
# already formatted once, for example if there are multiple printindex.
my $already_formatted;
if (!$formatted_index_entries{$index_entry_ref}) {
$formatted_index_entries{$index_entry_ref} = 1;
} else {
$already_formatted = 1;
$self->{'ignore_notice'}++;
}
my $entry;
if ($index_entry_ref->{'in_code'}) {
$entry = $self->convert_tree({'type' => '_code',
'contents' => $index_entry_ref->{'content'}});
} else {
$entry = $self->convert_tree({'contents' => $index_entry_ref->{'content'}});
}
$entry .= $self->convert_index_subentries($index_entry_ref);
if ($already_formatted) {
$self->{'ignore_notice'}--;
}
next if ($entry !~ /\S/);
$entry = '' .$entry .'
' if ($index_entry_ref->{'in_code'});
my $entry_href = $self->command_href($index_entry_ref->{'command'});
my $associated_command;
if ($self->get_conf('NODE_NAME_IN_INDEX')) {
$associated_command = $index_entry_ref->{'node'};
if (!defined($associated_command)) {
$associated_command
= $self->command_node($index_entry_ref->{'command'});
}
}
if (!$associated_command) {
$associated_command
= $self->command_element_command($index_entry_ref->{'command'});
if (!$associated_command) {
# Use Top if not associated command found
$associated_command
= $self->element_command($self->global_element('Top'));
}
}
my ($associated_command_href, $associated_command_text);
if ($associated_command) {
$associated_command_href = $self->command_href($associated_command);
$associated_command_text = $self->command_text($associated_command);
}
$entries_text .= ' | '
. "$entry" .
$self->get_conf('INDEX_ENTRY_COLON') .
' | | ';
$entries_text .= "$associated_command_text"
if ($associated_command_href);
$entries_text .= " |
\n";
}
# a letter and associated indice entries
$result .= '' .
"".$self->protect_text($letter)
. " | | |
\n" . $entries_text .
" ".$self->get_conf('DEFAULT_RULE')." |
\n";
}
$result .= "\n";
pop @{$self->{'document_context'}};
return $result .$summary;
}
$default_commands_conversion{'printindex'} = \&_convert_printindex_command;
sub _contents_inline_element($$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
my $content = &{$self->{'format_contents'}}($self, $cmdname, $command);
if ($content) {
my $element_name = $contents_command_element_name{$cmdname};
my $special_element
= $self->special_element($element_name);
my $heading;
my $result = "command_id($special_element);
if ($id ne '') {
$result .= " id=\"$id\"";
}
$heading = $self->command_text($special_element);
} else {
# happens when called as convert() and not output()
#cluck "$cmdname special element not defined";
$heading
= $self->convert_tree ($self->get_conf('SPECIAL_ELEMENTS_NAME')->{$element_name});
}
$result .= ">\n";
my $class = $self->get_conf('SPECIAL_ELEMENTS_CLASS')->{$element_name};
$result .= &{$self->{'format_heading_text'}}($self, $class.'-heading',
$heading, $self->get_conf('CHAPTER_HEADER_LEVEL'))."\n";
$result .= $content . "
\n";
return $result;
}
return '';
}
sub _convert_informative_command($$$$)
{
my $self = shift;
my $cmdname = shift;
my $command = shift;
return '' if ($self->in_string());
$cmdname = 'shortcontents' if ($cmdname eq 'summarycontents');
$self->_informative_command($command);
if ($self->get_conf('CONTENTS_OUTPUT_LOCATION') eq 'inline'
and ($cmdname eq 'contents' or $cmdname eq 'shortcontents')
and $self->get_conf($cmdname)
and $self->{'structuring'} and $self->{'structuring'}->{'sectioning_root'}
and scalar(@{$self->{'structuring'}->{'sections_list'}}) > 1) {
return $self->_contents_inline_element($cmdname, $command);
}
if ($cmdname eq 'documentlanguage') {
$self->_translate_names();
}
return '';
}
foreach my $informative_command (@informative_global_commands) {
$default_commands_conversion{$informative_command}
= \&_convert_informative_command;
}
# associate same formatting function for @small* command
# as for the associated @-command
foreach my $small_command (keys(%small_alias)) {
$default_commands_conversion{$small_command}
= $default_commands_conversion{$small_alias{$small_command}};
}
# Keys are tree element types, values are function references to convert
# elements of that type. Can be overridden with
# Texinfo::Config::texinfo_types_conversion, setup by
# Texinfo::Config::texinfo_register_type_formatting()
my %default_types_conversion;
sub default_types_conversion($$)
{
my $self = shift;
my $type = shift;
return $default_types_conversion{$type};
}
# Ignored commands
foreach my $type ('empty_line_after_command', 'preamble',
'preamble_before_setfilename',
'empty_spaces_after_command', 'spaces_at_end',
'empty_spaces_before_argument', 'empty_spaces_before_paragraph',
'empty_spaces_after_close_brace') {
$default_types_conversion{$type} = undef;
}
my %paragraph_style = (
'center' => 'center',
'flushleft' => 'left',
'flushright' => 'right',
);
sub _quotation_arg_to_prepend($$)
{
my $self = shift;
my $command = shift;
if ($command->{'parent'} and $command->{'parent'}->{'cmdname'}
and ($command->{'parent'}->{'cmdname'} eq 'quotation'
or $command->{'parent'}->{'cmdname'} eq 'smallquotation')
and $command->{'parent'}->{'args'}
and $command->{'parent'}->{'args'}->[0]
and $command->{'parent'}->{'args'}->[0]->{'contents'}
and @{$command->{'parent'}->{'args'}->[0]->{'contents'}}) {
return $self->convert_tree($self->gdt('@b{{quotation_arg}:} ',
{'quotation_arg' =>
$command->{'parent'}->{'args'}->[0]->{'contents'}}));
}
return undef;
}
sub _convert_paragraph_type($$$$)
{
my $self = shift;
my $type = shift;
my $command = shift;
my $content = shift;
if ($self->paragraph_number() == 1) {
my $in_format = $self->top_format();
if ($in_format) {
# no first paragraph in those environment to avoid extra spacing
if ($in_format eq 'itemize'
or $in_format eq 'enumerate'
or $in_format eq 'multitable') {
return $content;
} else {
my $prepended = $self->_quotation_arg_to_prepend($command);
$content = $prepended.$content if (defined($prepended));
}
}
}
return $content if ($self->in_string());
if ($content =~ /\S/) {
my $align = $self->in_align();
if ($align and $paragraph_style{$align}) {
return "".$content."
";
} else {
return "".$content."
";
}
} else {
return '';
}
}
$default_types_conversion{'paragraph'} = \&_convert_paragraph_type;
sub _preformatted_class()
{
my $self = shift;
my $pre_class;
my @pre_classes = $self->preformatted_classes_stack();
foreach my $class (@pre_classes) {
# FIXME maybe add or $pre_class eq 'menu-preformatted' to override
# 'menu-preformatted' with 'menu-comment'?
$pre_class = $class unless ($pre_class
and $preformatted_code_commands{$pre_class}
and !($preformatted_code_commands{$class}
or $class eq 'menu-preformatted'));
}
return $pre_class;
}
sub _convert_preformatted_type($$$$)
{
my $self = shift;
my $type = shift;
my $command = shift;
my $content = shift;
if (!defined($content)) {
cluck "content undef in _convert_preformatted_type "
.Texinfo::Common::_print_current($command);
}
my $current = $command;
# !defined preformatted_number may happen if there is something before the
# first preformatted. For example an @exdent.
if ($self->preformatted_number() and $self->preformatted_number() == 1) {
my $prepended = $self->_quotation_arg_to_prepend($command);
$content = $prepended.$content if (defined($prepended));
}
return '' if ($content eq '');
return $content if ($type eq 'rawpreformatted');
my $pre_class = $self->_preformatted_class();
if ($self->top_format() eq 'multitable') {
$content =~ s/^\s*//;
$content =~ s/\s*$//;
}
# menu_entry_description is always in a preformatted container
# in the tree, as the whole menu is meant to be an
# environment where spaces and newlines are preserved.
#
# However, if not in preformatted block command (nor in SIMPLE_MENU),
# we don't preserve spaces and newlines in menu_entry_description,
# instead the whole menu_entry is in a table, so here, not
if ($command->{'parent'}->{'type'}
and $command->{'parent'}->{'type'} eq 'menu_entry_description'
and !$self->_in_preformatted_in_menu()) {
return $content;
}
if ($self->in_string()) {
return $content;
}
$content =~ s/^\n/\n\n/; # a newline immediately after a is ignored.
my $result = $self->_attribute_class('pre', $pre_class).">".$content."
";
# this may happen with lines without textual content
# between a def* and def*x.
if ($command->{'parent'}->{'cmdname'}
and $command->{'parent'}->{'cmdname'} =~ /^def/) {
$result = '
'.$result.'';
}
return $result;
}
$default_types_conversion{'preformatted'} = \&_convert_preformatted_type;
$default_types_conversion{'rawpreformatted'} = \&_convert_preformatted_type;
sub _convert_bracketed_type($$$$) {
my $self = shift;
my $type = shift;
my $command = shift;
my $content = shift;
#print STDERR "$self $type $command $content\n";