[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[no subject]
From: |
Patrice Dumas |
Date: |
Mon, 20 Nov 2023 18:30:19 -0500 (EST) |
branch: master
commit da191054da51a26fdce95aaf7b501373df1dc28a
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Mon Nov 20 17:25:19 2023 +0100
* tp/Texinfo/XSLoader.pm (init): avoid undefined value in warning
message.
* tp/Texinfo/Convert/HTML.pm (register_opened_section_level)
(close_registered_sections_level): change variable names.
* tp/Texinfo/Convert/HTML.pm (close_registered_sections_level): return
a reference on an array, not an array. Update callers.
* tp/Texinfo/Convert/HTML.pm (_initialize_output_state): initialize
$self->{'pending_closes'} here.
* tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides),
tp/Texinfo/XS/convert/ConvertXS.xs
(html_register_opened_section_level)
(html_close_registered_sections_level),
tp/Texinfo/XS/convert/convert_html.c
(html_register_opened_section_level)
(html_close_registered_sections_level, html_finalize_output_state),
tp/Texinfo/XS/main/command_stack.c (clear_string_stack),
tp/Texinfo/XS/main/converter_types.h (CONVERTER): add
clear_string_stack. Implement register_opened_section_level and
close_registered_sections_level in C with an XS interface.
* tp/Texinfo/XS/main/command_stack.c (push_string_stack_string)
(top_string_stack): add const.
* tp/Texinfo/XS/convert/build_html_perl_state.c
(build_html_formatting_state): declare multiple_pass variables inside
the block.
* doc/texi2any_api.texi: updates.
---
ChangeLog | 35 +++++++++++++++++++
doc/texi2any_api.texi | 42 +++++++++++++++--------
tp/Texinfo/Convert/HTML.pm | 38 +++++++++++++--------
tp/Texinfo/XS/convert/ConvertXS.xs | 42 +++++++++++++++++++++++
tp/Texinfo/XS/convert/build_html_perl_state.c | 7 ++--
tp/Texinfo/XS/convert/convert_html.c | 49 ++++++++++++++++++++++++++-
tp/Texinfo/XS/convert/convert_html.h | 5 +++
tp/Texinfo/XS/main/command_stack.c | 11 ++++--
tp/Texinfo/XS/main/command_stack.h | 5 +--
tp/Texinfo/XS/main/converter_types.h | 1 +
tp/Texinfo/XSLoader.pm | 4 ++-
tp/init/book.pm | 3 +-
tp/t/init/t2h_singular.init | 3 +-
13 files changed, 205 insertions(+), 40 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f880a6d3fd..47dddb393f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2023-11-20 Patrice Dumas <pertusus@free.fr>
+
+ * tp/Texinfo/XSLoader.pm (init): avoid undefined value in warning
+ message.
+
+ * tp/Texinfo/Convert/HTML.pm (register_opened_section_level)
+ (close_registered_sections_level): change variable names.
+
+ * tp/Texinfo/Convert/HTML.pm (close_registered_sections_level): return
+ a reference on an array, not an array. Update callers.
+
+ * tp/Texinfo/Convert/HTML.pm (_initialize_output_state): initialize
+ $self->{'pending_closes'} here.
+
+ * tp/Texinfo/Convert/HTML.pm (%XS_conversion_overrides),
+ tp/Texinfo/XS/convert/ConvertXS.xs
+ (html_register_opened_section_level)
+ (html_close_registered_sections_level),
+ tp/Texinfo/XS/convert/convert_html.c
+ (html_register_opened_section_level)
+ (html_close_registered_sections_level, html_finalize_output_state),
+ tp/Texinfo/XS/main/command_stack.c (clear_string_stack),
+ tp/Texinfo/XS/main/converter_types.h (CONVERTER): add
+ clear_string_stack. Implement register_opened_section_level and
+ close_registered_sections_level in C with an XS interface.
+
+ * tp/Texinfo/XS/main/command_stack.c (push_string_stack_string)
+ (top_string_stack): add const.
+
+ * tp/Texinfo/XS/convert/build_html_perl_state.c
+ (build_html_formatting_state): declare multiple_pass variables inside
+ the block.
+
+ * doc/texi2any_api.texi: updates.
+
2023-11-20 Gavin Smith <gavinsmith0123@gmail.com>
XS build flags
diff --git a/doc/texi2any_api.texi b/doc/texi2any_api.texi
index 320c735962..865f684724 100644
--- a/doc/texi2any_api.texi
+++ b/doc/texi2any_api.texi
@@ -1496,8 +1496,7 @@ documentation, in particular a list of types and of
information in the elements
@node Output Units in User Defined Functions
@section Output Units in User Defined Functions
-Output units that are not part of the tree nor tree elements are
-formatted, both normal output units and special units (@pxref{Output
+Both normal output units and special units are formatted (@pxref{Output
Units}). The output units hold information on the document
structure (@pxref{Texinfo::Structuring METHODS,,,texi2any_internals}).
@@ -1509,14 +1508,20 @@ The following keys of output unit hashes can be
interesting:
special units.
@item unit_command
-Points to the associated @code{@@node} or sectioning @@-command depending
-on which of nodes or sectioning commands are the main components of
-output units. @xref{Output Units}. The corresponding sectioning
-and @code{@@node} @@-command elements have a @code{associated_unit}
-key directly in their hash that points to the associated output unit.
+For normal output units, points to the associated @code{@@node} or sectioning
+@@-command depending on which of nodes or sectioning commands are the main
+components of output units. @xref{Output Units}. The corresponding sectioning
+and @code{@@node} @@-command elements have an @code{associated_unit} key
+directly in their hash that points to the associated output unit.
@cindex @code{unit_command} element
@cindex @code{associated_unit} output unit
+For special units, points to a ``virtual'' tree element with type
+@code{special_unit_element} associated to the special element, that does not
+appear in the Texinfo tree but can be used as a target for directions
+to the special unit. This element has an @code{associated_unit} key
+that points to the associated output unit.
+
@item unit_contents
Array reference on tree elements associated to the output unit.
@@ -2975,7 +2980,7 @@ The function for registering opened section extent is
@defun @var{$converter}->register_opened_section_level ($level, $closing_text)
@var{$level} is the sectioning command level. It is typically
-obtained with @code{section->@{'structure'@}->@{'section_level'@}}
+obtained with @code{section->@{'extra'@}->@{'section_level'@}}
(@pxref{Texinfo Tree Elements in User Defined Functions}).
@var{$closing_text} is the text that should be output when the
section level @var{$level} is closed.
@@ -2984,18 +2989,22 @@ section level @var{$level} is closed.
The function for closing registered section extents is
@code{close_registered_sections_level}:
-@deftypefun {@var{@@closing_texts} =}
@var{$converter}->close_registered_sections_level (@var{$level})
+@deftypefun {@var{\@@closing_texts} =}
@var{$converter}->close_registered_sections_level (@var{$level})
@var{$level} is the sectioning command level. Opened section are closed
down to section level @var{$level}. The closing texts are returned in the
-@var{@@closing_texts} array in order.
+@var{\@@closing_texts} array reference in order.
@end deftypefun
Example of use:
@example
@group
-my $level = $opening_section->@{'structure'@}->@{'section_level'@};
-$result
- .= join('', $converter->close_registered_sections_level($level));
+my $level = $opening_section->@{'extra'@}->@{'section_level'@};
+my $closed_strings
+ = $converter->close_registered_sections_level($level);
+$result .= join('', @@@{$closed_strings@});
+
+# ....
+
$converter->register_opened_section_level($level, "</div>\n");
@end group
@end example
@@ -3362,7 +3371,10 @@ The string will be translated if needed.
Target @@-commands are @@-commands that are associated with an identifier
and can be linked to. They corresponds first to @@-commands with unique
identifier
used as labels, @code{@@node}, @code{@@anchor} and @code{@@float}. Sectioning
-commands, index entries and footnotes are also associated to targets.
+commands, index entries, footnotes are also associated to targets. The
+``virtual'' elements associated to special output units are also
+associated to targets leading to each special unit
+(@pxref{Output Units in User Defined Functions}).
To get the unique Texinfo tree element corresponding to a label, use
@code{label_command}:
@@ -4387,7 +4399,7 @@ Texinfo::Common::set_informative_command_value,
texi2any_internals}.
@xref{Texinfo::Common $level = section_level($section),,
Texinfo::Common::section_level, texi2any_internals}. This function would work
for sectioning commands too, but for sectioning commands,
-@code{section->@{'structure'@}->@{'section_level'@}} can also be used.
+@code{section->@{'extra'@}->@{'section_level'@}} can also be used.
@xref{Texinfo Tree Elements in User Defined Functions}.
@item sectioning commands
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index 4796a66d04..eb6e31dd10 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -122,6 +122,10 @@ my %XS_conversion_overrides = (
=> "Texinfo::Convert::ConvertXS::html_new_document_context",
"Texinfo::Convert::HTML::_pop_document_context"
=> "Texinfo::Convert::ConvertXS::html_pop_document_context",
+ "Texinfo::Convert::HTML::register_opened_section_level"
+ => "Texinfo::Convert::ConvertXS::html_register_opened_section_level",
+ "Texinfo::Convert::HTML::close_registered_sections_level"
+ => "Texinfo::Convert::ConvertXS::html_close_registered_sections_level",
"Texinfo::Convert::HTML::_XS_get_index_entries_sorted_by_letter"
=> "Texinfo::Convert::ConvertXS::get_index_entries_sorted_by_letter",
"Texinfo::Convert::HTML::_XS_html_merge_index_entries"
@@ -4189,11 +4193,11 @@ sub register_opened_section_level($$$)
{
my $self = shift;
my $level = shift;
- my $close = shift;
+ my $close_string = shift;
while (@{$self->{'pending_closes'}} < $level) {
push(@{$self->{'pending_closes'}}, "");
}
- push(@{$self->{'pending_closes'}}, $close);
+ push(@{$self->{'pending_closes'}}, $close_string);
}
sub close_registered_sections_level($$)
@@ -4204,13 +4208,12 @@ sub close_registered_sections_level($$)
cluck 'close_registered_sections_level $level not defined';
}
my @closed_elements;
- my $result = '';
while (@{$self->{'pending_closes'}} > $level) {
- my $close = pop @{$self->{'pending_closes'}};
- push(@closed_elements, $close)
- if ($close);
+ my $close_string = pop @{$self->{'pending_closes'}};
+ push(@closed_elements, $close_string)
+ if ($close_string ne "");
}
- return @closed_elements;
+ return \@closed_elements;
}
sub _convert_heading_command($$$$$)
@@ -4429,7 +4432,8 @@ sub _convert_heading_command($$$$$)
my $heading_id;
if ($opening_section) {
my $level = $opening_section->{'extra'}->{'section_level'};
- $result .= join('', $self->close_registered_sections_level($level));
+ my $closed_strings = $self->close_registered_sections_level($level);
+ $result .= join('', @{$closed_strings});
$self->register_opened_section_level($level, "</div>\n");
# use a specific class name to mark that this is the start of
@@ -7374,7 +7378,8 @@ sub _convert_special_unit_type($$$$)
my $result = '';
my $special_unit_variety = $element->{'special_unit_variety'};
- $result .= join('', $self->close_registered_sections_level(0));
+ my $closed_strings = $self->close_registered_sections_level(0);
+ $result .= join('', @{$closed_strings});
my $special_unit_body
.= &{$self->special_unit_body_formatting($special_unit_variety)}($self,
@@ -7449,12 +7454,15 @@ sub _convert_unit_type($$$$)
# if there is one unit it also means that there is no formatting
# of footnotes in a separate unit. And if footnotestyle is end
# the footnotes won't be done in format_element_footer either.
- $result .=
&{$self->formatting_function('format_footnotes_segment')}($self);
+ $result
+ .= &{$self->formatting_function('format_footnotes_segment')}($self);
$result .= $self->get_conf('DEFAULT_RULE') ."\n"
if ($self->get_conf('PROGRAM_NAME_IN_FOOTER')
and defined($self->get_conf('DEFAULT_RULE')));
- # do it here, as it is won't be done at end of page in
format_element_footer
- $result .= join('', $self->close_registered_sections_level(0));
+ # do it here, as it is won't be done at end of page in
+ # format_element_footer
+ my $closed_strings = $self->close_registered_sections_level(0);
+ $result .= join('', @{$closed_strings});
return $result;
}
}
@@ -7514,7 +7522,8 @@ sub _default_format_element_footer($$$$;$)
my $buttons;
if ($end_page) {
- $result .= join('', $self->close_registered_sections_level(0));
+ my $closed_strings = $self->close_registered_sections_level(0);
+ $result .= join('', @{$closed_strings});
# setup buttons for navigation footer
if (($is_top or $is_special)
@@ -8482,7 +8491,6 @@ sub converter_initialize($)
$self->{'document_context'} = [];
$self->{'multiple_pass'} = [];
- $self->{'pending_closes'} = [];
# TODO warn if the split specification is not one known? The main
# program warns if the specific command line option value is not known.
@@ -11039,6 +11047,8 @@ sub _initialize_output_state($$)
# other
$self->{'pending_footnotes'} = [];
+ # not used if conversion with XS
+ $self->{'pending_closes'} = [];
# to avoid infinite recursions when a section refers to itself, possibly
# indirectly
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 6427f69bc7..95c0c3499f 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -303,6 +303,48 @@ html_pop_document_context (SV *converter_in)
self->document_context_change++;
}
+void
+html_register_opened_section_level (SV *converter_in, int level, close_string)
+ char *close_string = (char *)SvPVutf8_nolen($arg);
+ PREINIT:
+ CONVERTER *self;
+ CODE:
+ self = get_sv_converter (converter_in,
+ "html_register_opened_section_level");
+ if (self)
+ {
+ html_register_opened_section_level (self, level, close_string);
+ }
+
+SV *
+html_close_registered_sections_level (SV *converter_in, int level)
+ PREINIT:
+ CONVERTER *self;
+ AV *closed_elements_av;
+ CODE:
+ self = get_sv_converter (converter_in,
+ "html_close_registered_sections_level");
+ closed_elements_av = newAV ();
+ if (self)
+ {
+ STRING_LIST *closed_elements
+ = html_close_registered_sections_level (self, level);
+
+ if (closed_elements->number > 0)
+ {
+ int i;
+ for (i = 0; i < closed_elements->number; i++)
+ {
+ SV *close_string_sv
+ = newSVpv_utf8 (closed_elements->list[i], 0);
+ av_push (closed_elements_av, close_string_sv);
+ }
+ }
+ destroy_strings_list (closed_elements);
+ }
+ RETVAL = newRV_noinc ((SV *) closed_elements_av);
+ OUTPUT:
+ RETVAL
void
html_merge_index_entries (SV *converter_in)
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index 6fb83f309b..1182359544 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -713,8 +713,6 @@ build_html_formatting_state (CONVERTER *converter, unsigned
long flags)
HV *hv;
SV **document_context_sv;
AV *document_context_av;
- SV **multiple_pass_sv;
- AV *multiple_pass_av;
SV **file_counters_sv;
HV *file_counters_hv;
/*
@@ -939,6 +937,9 @@ build_html_formatting_state (CONVERTER *converter, unsigned
long flags)
if (flags & HMSF_multiple_pass)
{
+ SV **multiple_pass_sv;
+ AV *multiple_pass_av;
+
FETCH(multiple_pass);
if (!multiple_pass_sv)
@@ -954,7 +955,7 @@ build_html_formatting_state (CONVERTER *converter, unsigned
long flags)
for (i = 0; i < converter->multiple_pass.top; i++)
{
- char *multiple_pass_str = converter->multiple_pass.stack[i];
+ const char *multiple_pass_str = converter->multiple_pass.stack[i];
av_push (multiple_pass_av, newSVpv_utf8(multiple_pass_str, 0));
}
}
diff --git a/tp/Texinfo/XS/convert/convert_html.c
b/tp/Texinfo/XS/convert/convert_html.c
index 7ca7995cbd..33101eb875 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -603,6 +603,40 @@ special_unit_info (CONVERTER *self, enum
special_unit_info_type type,
return self->special_unit_info[type][i];
}
+void
+html_register_opened_section_level (CONVERTER *self, int level,
+ const char *close_string)
+{
+ STRING_STACK *pending_closes = &self->pending_closes;
+
+ while (pending_closes->top < level)
+ {
+ push_string_stack_string (pending_closes, "");
+ }
+ push_string_stack_string (pending_closes, close_string);
+}
+
+STRING_LIST *
+html_close_registered_sections_level (CONVERTER *self, int level)
+{
+ STRING_LIST *closed_elements = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ STRING_STACK *pending_closes = &self->pending_closes;
+
+ memset (closed_elements, 0, sizeof (STRING_LIST));
+
+ while (pending_closes->top > level)
+ {
+ const char *close_string = top_string_stack (pending_closes);
+ if (strlen (close_string))
+ {
+ add_string (close_string, closed_elements);
+ }
+ pop_string_stack (pending_closes);
+ }
+
+ return closed_elements;
+}
+
OUTPUT_UNIT *
register_special_unit (CONVERTER *self, char *special_unit_variety)
{
@@ -3107,6 +3141,20 @@ html_finalize_output_state (CONVERTER *self)
clear_output_files_information (&self->output_files_information);
clear_output_unit_files (&self->output_unit_files);
+ /* should not be possible with default code, as
+ close_registered_sections_level(0)
+ is called at the end of processing or at the end of each file.
+ However, it could happen if the conversion functions are user
+ defined.
+ */
+ if (self->pending_closes.top > 0)
+ {
+ message_list_document_warn (&self->error_messages, self->conf,
+ "%zu registered opened sections not closed",
+ self->pending_closes.top);
+ clear_string_stack (&self->pending_closes);
+ }
+
html_pop_document_context (self);
/* could change to 0 in releases? */
@@ -3121,7 +3169,6 @@ html_finalize_output_state (CONVERTER *self)
if (self->ignore_notice)
fprintf (stderr, "BUG: ignore_notice: %d\n",
self->ignore_notice);
-
}
}
diff --git a/tp/Texinfo/XS/convert/convert_html.h
b/tp/Texinfo/XS/convert/convert_html.h
index 5ab0d9a3bf..2052f366d1 100644
--- a/tp/Texinfo/XS/convert/convert_html.h
+++ b/tp/Texinfo/XS/convert/convert_html.h
@@ -26,6 +26,11 @@ void html_new_document_context (CONVERTER *self,
enum command_id block_command);
void html_pop_document_context (CONVERTER *self);
+void html_register_opened_section_level (CONVERTER *self, int level,
+ const char *close_string);
+STRING_LIST *html_close_registered_sections_level (CONVERTER *self,
+ int level);
+
void html_merge_index_entries (CONVERTER *self);
void html_prepare_conversion_units (CONVERTER *self,
diff --git a/tp/Texinfo/XS/main/command_stack.c
b/tp/Texinfo/XS/main/command_stack.c
index be0e2660a7..7b398c863b 100644
--- a/tp/Texinfo/XS/main/command_stack.c
+++ b/tp/Texinfo/XS/main/command_stack.c
@@ -118,7 +118,7 @@ top_command_or_type (COMMAND_OR_TYPE_STACK *stack)
/* stack of strings */
void
-push_string_stack_string (STRING_STACK *stack, char *string)
+push_string_stack_string (STRING_STACK *stack, const char *string)
{
if (stack->top >= stack->space)
{
@@ -142,7 +142,7 @@ pop_string_stack (STRING_STACK *stack)
stack->top--;
}
-char *
+const char *
top_string_stack (STRING_STACK *stack)
{
if (stack->top == 0)
@@ -151,6 +151,13 @@ top_string_stack (STRING_STACK *stack)
return stack->stack[stack->top - 1];
}
+void
+clear_string_stack (STRING_STACK *stack)
+{
+ while (stack->top > 0)
+ pop_string_stack (stack);
+}
+
/* stack of integers */
void
diff --git a/tp/Texinfo/XS/main/command_stack.h
b/tp/Texinfo/XS/main/command_stack.h
index c36eb40af7..34586b6250 100644
--- a/tp/Texinfo/XS/main/command_stack.h
+++ b/tp/Texinfo/XS/main/command_stack.h
@@ -32,9 +32,10 @@ void push_command_or_type (COMMAND_OR_TYPE_STACK *stack,
enum command_id cmd,
void pop_command_or_type (COMMAND_OR_TYPE_STACK *stack);
COMMAND_OR_TYPE *top_command_or_type (COMMAND_OR_TYPE_STACK *stack);
-void push_string_stack_string (STRING_STACK *stack, char *string);
+void push_string_stack_string (STRING_STACK *stack, const char *string);
void pop_string_stack (STRING_STACK *stack);
-char *top_string_stack (STRING_STACK *stack);
+const char *top_string_stack (STRING_STACK *stack);
+void clear_string_stack (STRING_STACK *stack);
void push_integer_stack_integer (INTEGER_STACK *stack, int value);
int pop_integer_stack (INTEGER_STACK *stack);
diff --git a/tp/Texinfo/XS/main/converter_types.h
b/tp/Texinfo/XS/main/converter_types.h
index 8de47b7269..20315fa82a 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -500,6 +500,7 @@ typedef struct CONVERTER {
const OUTPUT_UNIT *current_output_unit;
HTML_DOCUMENT_CONTEXT_STACK html_document_context;
STRING_STACK multiple_pass;
+ STRING_STACK pending_closes;
char *current_filename;
/* state common with perl converter, not transmitted to perl */
int use_unicode_text;
diff --git a/tp/Texinfo/XSLoader.pm b/tp/Texinfo/XSLoader.pm
index 3c088a81fc..31f15d773d 100644
--- a/tp/Texinfo/XSLoader.pm
+++ b/tp/Texinfo/XSLoader.pm
@@ -229,7 +229,9 @@ sub init {
die "unset the TEXINFO_XS environment variable to use the "
."pure Perl modules\n";
} elsif ($TEXINFO_XS eq 'warn' or $TEXINFO_XS eq 'debug') {
- warn "falling back to pure Perl module $fallback_module\n";
+ if (defined($fallback_module)) {
+ warn "falling back to pure Perl module $fallback_module\n";
+ }
}
if (!defined $fallback_module) {
warn "no fallback module for $module\n";
diff --git a/tp/init/book.pm b/tp/init/book.pm
index d91ff824b8..4cac93eb81 100644
--- a/tp/init/book.pm
+++ b/tp/init/book.pm
@@ -370,7 +370,8 @@ sub book_convert_heading_command($$$$$)
my $heading_id;
if ($opening_section) {
my $level = $opening_section->{'extra'}->{'section_level'};
- $result .= join('', $self->close_registered_sections_level($level));
+ my $closed_strings = $self->close_registered_sections_level($level);
+ $result .= join('', @{$closed_strings});
$self->register_opened_section_level($level, "</div>\n");
# use a specific class name to mark that this is the start of
diff --git a/tp/t/init/t2h_singular.init b/tp/t/init/t2h_singular.init
index 4af597d6b6..69d37ca803 100644
--- a/tp/t/init/t2h_singular.init
+++ b/tp/t/init/t2h_singular.init
@@ -94,7 +94,8 @@ sub singular_format_footer($$$$)
$result .= $self->get_conf('DEFAULT_RULE')."\n"
if (defined($self->get_conf('DEFAULT_RULE')));
if ($end_page) {
- $result .= join('', $self->close_registered_sections_level(0));
+ my $closed_strings = $self->close_registered_sections_level(0);
+ $result .= join('', @{$closed_strings});
$result .=
&{$self->formatting_function('format_navigation_panel')}($self,
$buttons, undef, $output_unit);
}