texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[no subject]


From: Patrice Dumas
Date: Sun, 24 Dec 2023 08:17:08 -0500 (EST)

branch: master
commit 4f2d905935fdb5cb0d65228d35c50eac3c5b9375
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Sun Dec 24 12:04:59 2023 +0100

    * tp/Texinfo/XS/convert/convert_html.c
    (html_special_unit_variety_direction_index, html_get_target): rename
    special_unit_variety_direction_index
    as html_special_unit_variety_direction_index and get_target as
    html_get_target.
    
    * tp/Texinfo/XS/convert/build_html_perl_state.c
    (build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
    (find_element_target_number, find_element_target)
    (register_added_target_number, html_get_target),
    tp/Texinfo/XS/main/converter_types.h (HTML_ADDED_TARGET_LIST): pass
    added targets as the target number instead of the target info pointer,
    as the list may be reallocated in the mean time.
    
    * tp/Texinfo/Convert/HTML.pm (_external_node_href),
    tp/Texinfo/XS/convert/convert_html.c (external_node_href): remove
    unused source_filename argument.
    
    * tp/Texinfo/Convert/HTML.pm (from_element_direction),
    tp/Texinfo/XS/convert/convert_html.c (from_element_direction): call
    _external_node_href directly for external node.
    
    * tp/Texinfo/Convert/HTML.pm (_internal_command_href, command_href)
    (command_tree, _internal_command_tree, _external_command_tree)
    (_internal_command_text, command_text),
    tp/Texinfo/XS/convert/convert_html.c (html_command_href)
    (html_internal_command_href, html_command_tree)
    (html_internal_command_tree, html_external_command_tree)
    (html_internal_command_text, html_command_text): split
    *internal_command* out of html_command_tree, html_command_text and
    command_text, for clearer code and to prepare to override these
    functions only.
    
    * tp/Texinfo/XS/convert/get_html_perl_info.c
    (find_index_entry_element, find_root_command, find_element_from_sv):
    add find_element_from_sv to get the C tree element based on perl
    element, for elements with targets.
    
    * tp/Texinfo/XS/convert/ConvertXS.xs (html_get_target)
    (html_command_id), tp/Texinfo/XS/convert/get_html_perl_info.c
    (get_output_units_descriptor_converter_sv): prepare overriding
    _get_target and command_id. Not set up as an override for now as all
    the functions accessing targets need to be overriden at once.
---
 ChangeLog                                     |  46 +++++
 tp/TODO                                       |   3 +
 tp/Texinfo/Convert/HTML.pm                    | 154 +++++++++------
 tp/Texinfo/XS/convert/ConvertXS.xs            |  58 ++++++
 tp/Texinfo/XS/convert/build_html_perl_state.c |   4 +-
 tp/Texinfo/XS/convert/build_html_perl_state.h |   1 +
 tp/Texinfo/XS/convert/convert_html.c          | 274 ++++++++++++++++----------
 tp/Texinfo/XS/convert/convert_html.h          |   6 +
 tp/Texinfo/XS/convert/get_html_perl_info.c    | 253 ++++++++++++++++++++++++
 tp/Texinfo/XS/convert/get_html_perl_info.h    |   4 +
 tp/Texinfo/XS/main/converter_types.h          |   4 +-
 11 files changed, 642 insertions(+), 165 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2a7ae2b7e5..bb817de547 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2023-12-24  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/XS/convert/convert_html.c
+       (html_special_unit_variety_direction_index, html_get_target): rename
+       special_unit_variety_direction_index
+       as html_special_unit_variety_direction_index and get_target as
+       html_get_target.
+
+       * tp/Texinfo/XS/convert/build_html_perl_state.c
+       (build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
+       (find_element_target_number, find_element_target)
+       (register_added_target_number, html_get_target),
+       tp/Texinfo/XS/main/converter_types.h (HTML_ADDED_TARGET_LIST): pass
+       added targets as the target number instead of the target info pointer,
+       as the list may be reallocated in the mean time.
+
+       * tp/Texinfo/Convert/HTML.pm (_external_node_href),
+       tp/Texinfo/XS/convert/convert_html.c (external_node_href): remove
+       unused source_filename argument.
+
+       * tp/Texinfo/Convert/HTML.pm (from_element_direction),
+       tp/Texinfo/XS/convert/convert_html.c (from_element_direction): call
+       _external_node_href directly for external node.
+
+       * tp/Texinfo/Convert/HTML.pm (_internal_command_href, command_href)
+       (command_tree, _internal_command_tree, _external_command_tree)
+       (_internal_command_text, command_text),
+       tp/Texinfo/XS/convert/convert_html.c (html_command_href)
+       (html_internal_command_href, html_command_tree)
+       (html_internal_command_tree, html_external_command_tree)
+       (html_internal_command_text, html_command_text): split
+       *internal_command* out of html_command_tree, html_command_text and
+       command_text, for clearer code and to prepare to override these
+       functions only.
+
+       * tp/Texinfo/XS/convert/get_html_perl_info.c
+       (find_index_entry_element, find_root_command, find_element_from_sv):
+       add find_element_from_sv to get the C tree element based on perl
+       element, for elements with targets.
+
+       * tp/Texinfo/XS/convert/ConvertXS.xs (html_get_target)
+       (html_command_id), tp/Texinfo/XS/convert/get_html_perl_info.c
+       (get_output_units_descriptor_converter_sv): prepare overriding
+       _get_target and command_id. Not set up as an override for now as all
+       the functions accessing targets need to be overriden at once.
+
 2023-12-24  Gavin Smith <gavinsmith0123@gmail.com>
 
        * tp/t/languages.t (appendix_translated): Check translated
diff --git a/tp/TODO b/tp/TODO
index 7b6eba669a..a87f233376 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -10,6 +10,9 @@ This is the todo list for texi2any
 Before next release
 ===================
 
+do not use TREE_ADDED_ELEMENTS is the tree is to be destroyed
+in the same function
+
 it is not documented that .info or .inf at the end of the @ref file name 
argument of the source cross reference command is ignored when doing the HTML 
cross ref.
 in HTML Cross-reference Link Basics:
 Any directory part in the file name argument of the source cross reference 
command is ignored. Thus, @xref{,,,../foo} and @xref{,,,foo} both use ‘foo’ as 
the manual name. This is because any such attempted hardwiring of the directory 
is very unlikely to be useful for all the output formats that use the manual 
name. 
diff --git a/tp/Texinfo/Convert/HTML.pm b/tp/Texinfo/Convert/HTML.pm
index d48319f7c9..1f884d733d 100644
--- a/tp/Texinfo/Convert/HTML.pm
+++ b/tp/Texinfo/Convert/HTML.pm
@@ -128,6 +128,11 @@ my %XS_conversion_overrides = (
   "Texinfo::Convert::HTML::_id_is_registered"
    => "Texinfo::Convert::ConvertXS::html_id_is_registered",
 
+#  "Texinfo::Convert::HTML::_get_target"
+#   => "Texinfo::Convert::ConvertXS::html_get_target",
+#  "Texinfo::Convert::HTML::command_id"
+#   => "Texinfo::Convert::ConvertXS::html_command_id",
+
   "Texinfo::Convert::HTML::_open_command_update_context"
    => "Texinfo::Convert::ConvertXS::html_open_command_update_context",
   "Texinfo::Convert::HTML::_convert_command_update_context",
@@ -1014,8 +1019,7 @@ sub command_node($$)
   return undef;
 }
 
-# Return string for linking to $COMMAND with <a href>
-sub command_href($$;$$$)
+sub _internal_command_href($$;$$$)
 {
   my $self = shift;
   my $command = shift;
@@ -1027,11 +1031,6 @@ sub command_href($$;$$$)
 
   $source_filename = $self->{'current_filename'} if 
(!defined($source_filename));
 
-  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
-    return $self->_external_node_href($command, $source_filename,
-                                      $source_command);
-  }
-
   my $target;
   if (defined($specified_target)) {
     $target = $specified_target;
@@ -1092,6 +1091,25 @@ sub command_href($$;$$$)
   return $href;
 }
 
+# Return string for linking to $COMMAND with <a href>
+sub command_href($$;$$$)
+{
+  my $self = shift;
+  my $command = shift;
+  my $source_filename = shift;
+  # for messages only
+  my $source_command = shift;
+  # to specify explicitly the target
+  my $specified_target = shift;
+
+  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
+    return _external_node_href($self, $command, $source_command);
+  }
+
+  return _internal_command_href($self, $command, $source_filename,
+                                $source_command, $specified_target);
+}
+
 my %contents_command_special_unit_variety = (
   'contents' => 'contents',
   'shortcontents' => 'shortcontents',
@@ -1193,28 +1211,12 @@ sub footnote_location_href($$;$$$)
   return $href;
 }
 
-sub command_tree($$;$)
+sub _internal_command_tree($$$)
 {
   my $self = shift;
   my $command = shift;
   my $no_number = shift;
 
-  if (!defined($command)) {
-    cluck "in command_tree command not defined";
-  }
-
-  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
-    my $node_content = $command->{'extra'}->{'node_content'};
-    my $tree = {'type' => '_code',
-          'contents' => [{'text' => '('},
-                         $command->{'extra'}->{'manual_content'},
-                         {'text' => ')'}]};
-    if ($node_content) {
-      push @{$tree->{'contents'}}, $node_content;
-    }
-    return $tree;
-  }
-
   my $target = $self->_get_target($command);
   if ($target) {
     if (!exists($target->{'tree'})) {
@@ -1276,6 +1278,39 @@ sub command_tree($$;$)
   return undef;
 }
 
+sub _external_command_tree($$)
+{
+  my $self = shift;
+  my $command = shift;
+
+  my $node_content = $command->{'extra'}->{'node_content'};
+  my $tree = {'type' => '_code',
+        'contents' => [{'text' => '('},
+                       $command->{'extra'}->{'manual_content'},
+                       {'text' => ')'}]};
+  if ($node_content) {
+    push @{$tree->{'contents'}}, $node_content;
+  }
+  return $tree;
+}
+
+sub command_tree($$;$)
+{
+  my $self = shift;
+  my $command = shift;
+  my $no_number = shift;
+
+  if (!defined($command)) {
+    cluck "in command_tree command not defined";
+  }
+
+  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
+    return _external_command_tree($self, $command);
+  }
+
+  return _internal_command_tree($self, $command, $no_number);
+}
+
 sub _push_referred_command_stack_command($$)
 {
   my $self = shift;
@@ -1297,42 +1332,18 @@ sub _command_is_in_referred_command_stack($$)
   return grep {$_ eq $command} @{$self->{'referred_command_stack'}};
 }
 
-# Return text to be used for a hyperlink to $COMMAND.
-# $TYPE refers to the type of value returned from this function:
-#  'text' - return text
-#  'text_nonumber' - return text, without the section/chapter number
-#  'string' - return simpler text that can be used in element attributes
-sub command_text($$;$)
+sub _internal_command_text($$$)
 {
   my $self = shift;
   my $command = shift;
   my $type = shift;
 
-  if (!defined($type)) {
-    $type = 'text';
-  }
-  if (!defined($command)) {
-    cluck "in command_text($type) command not defined";
-  }
-
-  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
-    my $tree = command_tree($self, $command);
-    if ($type eq 'string') {
-      $tree = {'type' => '_string',
-               'contents' => [$tree]};
-    }
-    my $result = $self->convert_tree_new_formatting_context(
-      # FIXME check if $document_global_context argument would be needed?
-          $tree, $command->{'cmdname'}, 'command_text-manual_content');
-    return $result;
-  }
-
   my $target = $self->_get_target($command);
   if ($target) {
     if (defined($target->{$type})) {
       return $target->{$type};
     }
-    my $command_tree = $self->command_tree($command);
+    my $command_tree = _internal_command_tree($self, $command, 0);
     return '' if (!defined($command_tree));
 
     my $explanation;
@@ -1391,6 +1402,41 @@ sub command_text($$;$)
   return undef;
 }
 
+# Return text to be used for a hyperlink to $COMMAND.
+# $TYPE refers to the type of value returned from this function:
+#  'text' - return text
+#  'text_nonumber' - return text, without the section/chapter number
+#  'string' - return simpler text that can be used in element attributes
+sub command_text($$;$)
+{
+  my $self = shift;
+  my $command = shift;
+  my $type = shift;
+
+  if (!defined($type)) {
+    $type = 'text';
+  }
+
+  if (!defined($command)) {
+    cluck "in command_text($type) command not defined";
+  }
+
+  if ($command->{'extra'} and $command->{'extra'}->{'manual_content'}) {
+    my $tree = _external_command_tree($self, $command);
+    if ($type eq 'string') {
+      $tree = {'type' => '_string',
+               'contents' => [$tree]};
+    }
+    my $result = $self->convert_tree_new_formatting_context(
+      # FIXME check if $document_global_context argument would be needed?
+          $tree, $command->{'cmdname'}, 'command_text-manual_content');
+    return $result;
+  }
+
+  return _internal_command_text($self, $command, $type);
+}
+
+
 # Return the element in the tree that $LABEL refers to.
 sub label_command($$)
 {
@@ -1563,7 +1609,7 @@ sub from_element_direction($$$;$$$)
       #print STDERR "FROM_ELEMENT_DIRECTION ext node $type $direction\n"
       #  if ($self->get_conf('DEBUG'));
       if ($type eq 'href') {
-        return $self->command_href($external_node_element, $source_filename,
+        return _external_node_href($self, $external_node_element,
                                    $source_command);
       } elsif ($type eq 'text' or $type eq 'node') {
         return $self->command_text($external_node_element);
@@ -10230,12 +10276,10 @@ sub _check_htmlxref_already_warned($$$)
   }
 }
 
-sub _external_node_href($$$;$)
+sub _external_node_href($$$)
 {
   my $self = shift;
   my $external_node = shift;
-  # unused
-  my $source_filename = shift;
   # for messages only
   my $source_command = shift;
 
@@ -12213,7 +12257,6 @@ sub output($$)
     foreach my $label (sort(keys (%{$self->{'identifiers_target'}}))) {
       my $target_element = $self->{'identifiers_target'}->{$label};
       my $label_element = Texinfo::Common::get_label_element($target_element);
-      my $target = $self->_get_target($target_element);
       # filename may not be defined in case of an @anchor or similar in
       # @titlepage, and @titlepage is not used.
       my $filename = $self->command_filename($target_element);
@@ -12228,6 +12271,7 @@ sub output($$)
           and defined($self->get_conf('TOP_NODE_FILE_TARGET'))) {
         $node_filename = $self->get_conf('TOP_NODE_FILE_TARGET');
       } else {
+        my $target = $self->_get_target($target_element);
         $node_filename = $target->{'node_filename'};
       }
 
diff --git a/tp/Texinfo/XS/convert/ConvertXS.xs 
b/tp/Texinfo/XS/convert/ConvertXS.xs
index 1cdfba435c..c7481f8e92 100644
--- a/tp/Texinfo/XS/convert/ConvertXS.xs
+++ b/tp/Texinfo/XS/convert/ConvertXS.xs
@@ -791,6 +791,64 @@ html_get_file_information (SV *converter_in, key, ...)
          PUSHs(sv_2mortal(found_sv));
          PUSHs(sv_2mortal(result_sv));
 
+SV *
+html_get_target (SV *converter_in, SV *element_sv)
+     PREINIT:
+         CONVERTER *self;
+         HV *html_target_hv = 0;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_get_target");
+         if (self)
+           {
+             int output_units_descriptor
+               = get_output_units_descriptor_converter_sv (converter_in);
+             ELEMENT *element;
+             element = find_element_from_sv (self, element_sv,
+                                             output_units_descriptor);
+             if (element)
+               {
+                 HTML_TARGET *target_info = html_get_target (self, element);
+                 if (target_info)
+                   html_target_hv = build_html_target (target_info);
+               }
+           }
+         if (html_target_hv)
+           {
+             RETVAL = newRV_noinc ((SV *) html_target_hv);
+           }
+         else
+           RETVAL = newSV (0);
+    OUTPUT:
+         RETVAL
+
+SV *
+html_command_id (SV *converter_in, SV *element_sv)
+     PREINIT:
+         CONVERTER *self;
+         char *id = 0;
+     CODE:
+         self = get_sv_converter (converter_in,
+                                  "html_command_id");
+         if (self)
+           {
+             int output_units_descriptor
+               = get_output_units_descriptor_converter_sv (converter_in);
+             ELEMENT *element;
+             element = find_element_from_sv (self, element_sv,
+                                             output_units_descriptor);
+             if (element)
+               id = html_command_id (self, element);
+           }
+         if (id)
+           {
+             RETVAL = newSVpv_utf8 (id, 0);
+           }
+         else
+           RETVAL = newSV (0);
+    OUTPUT:
+         RETVAL
+
 void
 html_register_opened_section_level (SV *converter_in, int level, close_string)
          char *close_string = (char *)SvPVutf8_nolen($arg);
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c 
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index bdde83acf4..2ccade9406 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -766,7 +766,9 @@ build_html_formatting_state (CONVERTER *converter, unsigned 
long flags)
       int j;
       for (j = 0; j < converter->added_targets.number; j++)
         {
-          HTML_TARGET *html_target = converter->added_targets.list[j];
+          size_t target_number = converter->added_targets.list[j];
+          HTML_TARGET *html_target
+            = &converter->html_targets.list[target_number -1];;
           add_html_element_target (targets_hv, html_target);
         }
       converter->added_targets.number = 0;
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.h 
b/tp/Texinfo/XS/convert/build_html_perl_state.h
index 9771ee5ef3..b3f8f4b0d9 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.h
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.h
@@ -12,6 +12,7 @@
 /* for NAMED_STRING_ELEMENT_LIST */
 #include "translations.h"
 
+HV *build_html_target (HTML_TARGET *html_target);
 void pass_html_element_targets (SV *converter_sv,
                                 HTML_TARGET_LIST *html_targets);
 void pass_html_special_targets (SV *converter_sv,
diff --git a/tp/Texinfo/XS/convert/convert_html.c 
b/tp/Texinfo/XS/convert/convert_html.c
index 8744d11471..1115689973 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -290,7 +290,7 @@ unit_is_top_output_unit (CONVERTER *self, const OUTPUT_UNIT 
*output_unit)
 }
 
 int
-special_unit_variety_direction_index (CONVERTER *self,
+html_special_unit_variety_direction_index (CONVERTER *self,
                                       char *special_unit_variety)
 {
   /* number is index +1 */
@@ -384,7 +384,7 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT 
*command,
                   char *special_unit_variety
                 = self->special_unit_varieties.list[cmd_variety_index.index];
                   int special_unit_direction_index
-                    = special_unit_variety_direction_index (self,
+                    = html_special_unit_variety_direction_index (self,
                                                 special_unit_variety);
                   const OUTPUT_UNIT *special_unit
                 = self->global_units_directions[special_unit_direction_index];
@@ -421,10 +421,13 @@ html_get_tree_root_element (CONVERTER *self, const 
ELEMENT *command,
     }
 }
 
-HTML_TARGET *
-find_element_target (const HTML_TARGET_LIST *targets, const ELEMENT *element)
+/* this number should be safe to use even after targets list has been
+   reallocated */
+size_t
+find_element_target_number (const HTML_TARGET_LIST *targets,
+                            const ELEMENT *element)
 {
-  int i;
+  size_t i;
 
   if (!targets->number)
     return 0;
@@ -433,11 +436,23 @@ find_element_target (const HTML_TARGET_LIST *targets, 
const ELEMENT *element)
     {
       HTML_TARGET *target = &targets->list[i];
       if (target->element == element)
-        return target;
+        return i + 1;
     }
   return 0;
 }
 
+/* becomes invalid if the targets list is reallocated */
+HTML_TARGET *
+find_element_target (const HTML_TARGET_LIST *targets, const ELEMENT *element)
+{
+  size_t i = find_element_target_number (targets, element);
+
+  if (i > 0)
+    return &targets->list[i - 1];
+
+  return 0;
+}
+
 
 char *
 format_translate_message (CONVERTER *self,
@@ -1900,7 +1915,7 @@ new_sectioning_command_target (CONVERTER *self, const 
ELEMENT *command)
   if (self->conf->DEBUG > 0)
     {
       char *command_name = element_command_name (command);
-      fprintf (stderr, "Register %s %s\n", command_name, target);
+      fprintf (stderr, "XS|Register %s %s\n", command_name, target);
     }
 
   HTML_TARGET *element_target
@@ -2838,20 +2853,23 @@ direction_string (CONVERTER *self, int direction,
 }
 
 static void
-register_added_target (HTML_ADDED_TARGET_LIST *added_targets,
-                       HTML_TARGET *target)
+register_added_target_number (HTML_ADDED_TARGET_LIST *added_targets,
+                              size_t target_number)
 {
   if (added_targets->number == added_targets->space)
     {
       added_targets->list = realloc (added_targets->list,
-                   sizeof (HTML_TARGET *) * (added_targets->space += 5));
+                   sizeof (size_t) * (added_targets->space += 5));
     }
-  added_targets->list[added_targets->number] = target;
+  added_targets->list[added_targets->number] = target_number;
   added_targets->number++;
 }
 
-static HTML_TARGET *
-get_target (CONVERTER *self, const ELEMENT *element)
+/* note that the returned pointer may be invalidated if the targets list
+   is reallocated.  Callers should make sure that the html target is
+   used before a reallocation is possible */
+HTML_TARGET *
+html_get_target (CONVERTER *self, const ELEMENT *element)
 {
   HTML_TARGET *result
    = find_element_target (&self->html_targets, element);
@@ -2862,11 +2880,15 @@ get_target (CONVERTER *self, const ELEMENT *element)
       && flags & CF_sectioning_heading
       && !(flags & CF_root))
     {
+      size_t target_number;
       new_sectioning_command_target (self, element);
 
-      result = find_element_target (&self->html_targets, element);
+      target_number = find_element_target_number (&self->html_targets, 
element);
+      result = &self->html_targets.list[target_number -1];
 
-      register_added_target (&self->added_targets, result);
+      /* register the number and not the target, as the list may be
+         reallocated before the modified state is passed to perl */
+      register_added_target_number (&self->added_targets, target_number);
       self->modified_state |= HMSF_added_target;
     }
   return result;
@@ -2874,7 +2896,7 @@ get_target (CONVERTER *self, const ELEMENT *element)
 
 char *html_command_id (CONVERTER *self, const ELEMENT *command)
 {
-  HTML_TARGET *target_info = get_target (self, command);
+  HTML_TARGET *target_info = html_get_target (self, command);
   if (target_info)
     return target_info->target;
   else
@@ -2958,7 +2980,6 @@ html_check_htmlxref_already_warned (CONVERTER *self, 
const char *manual_name,
 
 char *
 external_node_href (CONVERTER *self, const ELEMENT *external_node,
-                    const char *source_filename, /* unused */
                     const ELEMENT *source_command) /* for messages only */
 {
   TEXT result;
@@ -3262,7 +3283,7 @@ html_command_filename (CONVERTER *self, const ELEMENT 
*command)
 {
   HTML_TARGET *target_info;
 
-  target_info = get_target (self, command);
+  target_info = html_get_target (self, command);
 
   if (target_info)
     {
@@ -3303,7 +3324,7 @@ command_root_element_command (CONVERTER *self, const 
ELEMENT *command)
 {
   HTML_TARGET *target_info;
 
-  target_info = get_target (self, command);
+  target_info = html_get_target (self, command);
   if (target_info)
     {
       if (!target_info->root_element_command_set)
@@ -3334,31 +3355,25 @@ command_root_element_command (CONVERTER *self, const 
ELEMENT *command)
   return 0;
 }
 
-/* Return string for linking to $COMMAND with <a href> */
 /* return value to be freed */
-char *html_command_href (CONVERTER *self, const ELEMENT *command,
+char *
+html_internal_command_href (CONVERTER *self, const ELEMENT *command,
                          const char *source_filename,
                          const ELEMENT *source_command, /* for messages only */
             const char *specified_target) /* to specify explicitly the target 
*/
 {
+  HTML_TARGET *target_info;
   TEXT href;
   const char *filename_from;
-  HTML_TARGET *target_info;
   const char *target = 0;
   FILE_NUMBER_NAME *target_filename;
   int target_filename_to_be_freed = 0;
-  ELEMENT *manual_content = lookup_extra_element (command,
-                                                  "manual_content");
+
   if (source_filename)
     filename_from = source_filename;
   else
     filename_from = self->current_filename.filename;
 
-  if (manual_content)
-    {
-      return external_node_href (self, command, filename_from,
-                                 source_command);
-    }
 
   if (specified_target)
     target = specified_target;
@@ -3370,7 +3385,7 @@ char *html_command_href (CONVERTER *self, const ELEMENT 
*command,
                                                        "associated_node");
       if (associated_node)
         target_command = associated_node;
-      target_info = get_target (self, target_command);
+      target_info = html_get_target (self, target_command);
       if (target_info)
         target = target_info->target;
     }
@@ -3449,6 +3464,24 @@ char *html_command_href (CONVERTER *self, const ELEMENT 
*command,
   return href.text;
 }
 
+/* Return string for linking to $COMMAND with <a href> */
+/* return value to be freed */
+char *html_command_href (CONVERTER *self, const ELEMENT *command,
+                         const char *source_filename,
+                         const ELEMENT *source_command, /* for messages only */
+            const char *specified_target) /* to specify explicitly the target 
*/
+{
+  ELEMENT *manual_content = lookup_extra_element (command,
+                                                  "manual_content");
+  if (manual_content)
+    {
+      return external_node_href (self, command, source_command);
+    }
+
+  return html_internal_command_href (self, command, source_filename,
+                                     source_command, specified_target);
+}
+
 char *
 html_command_contents_target (CONVERTER *self, const ELEMENT *command,
                               enum command_id contents_or_shortcontents)
@@ -3458,7 +3491,7 @@ html_command_contents_target (CONVERTER *self, const 
ELEMENT *command,
   if (contents_or_shortcontents == CM_summarycontents)
     contents_or_shortcontents = CM_shortcontents;
 
-  target_info = get_target (self, command);
+  target_info = html_get_target (self, command);
   if (target_info)
     {
       if (contents_or_shortcontents == CM_shortcontents)
@@ -3516,7 +3549,7 @@ html_command_contents_href (CONVERTER *self, const 
ELEMENT *command,
           char *special_unit_variety
             = self->special_unit_varieties.list[cmd_variety_index.index];
           int special_unit_direction_index
-                = special_unit_variety_direction_index (self,
+                = html_special_unit_variety_direction_index (self,
                                            special_unit_variety);
           const OUTPUT_UNIT *special_unit
             = self->global_units_directions[special_unit_direction_index];
@@ -3656,43 +3689,13 @@ register_modified_shared_conversion_state_integer 
(CONVERTER *self,
 }
 
 TREE_ADDED_ELEMENTS *
-html_command_tree (CONVERTER *self, const ELEMENT *command, int no_number)
+html_internal_command_tree (CONVERTER *self, const ELEMENT *command,
+                            int no_number)
 {
   TREE_ADDED_ELEMENTS *tree;
   HTML_TARGET *target_info;
 
-  ELEMENT *manual_content = lookup_extra_element (command,
-                                                  "manual_content");
-  if (manual_content)
-    {
-      ELEMENT *root_code;
-      ELEMENT *open_p;
-      ELEMENT *close_p;
-
-      ELEMENT *node_content = lookup_extra_element (command,
-                                                    "node_content");
-
-      tree = new_tree_added_elements (tree_added_status_elements_added);
-
-      root_code = new_element_added (tree, ET__code);
-      open_p = new_element_added (tree, ET_NONE);
-      close_p = new_element_added (tree, ET_NONE);
-
-      text_append_n (&open_p->text, "(", 1);
-      text_append_n (&close_p->text, ")", 1);
-
-      add_to_element_contents (root_code, open_p);
-      add_to_contents_as_array (root_code, manual_content);
-      add_to_element_contents (root_code, close_p);
-      if (node_content)
-        add_to_contents_as_array (root_code, node_content);
-
-      tree->tree = root_code;
-      add_to_element_list (&self->tree_to_build, root_code);
-      return tree;
-    }
-
-  target_info = get_target (self, command);
+  target_info = html_get_target (self, command);
   if (target_info)
     {
       if (!target_info->tree.status)
@@ -3788,62 +3791,73 @@ html_command_tree (CONVERTER *self, const ELEMENT 
*command, int no_number)
   return 0;
 }
 
-/* return value to be freed by caller */
-char *
-html_command_text (CONVERTER *self, const ELEMENT *command,
-                   const enum html_text_type type)
+TREE_ADDED_ELEMENTS *
+html_external_command_tree (CONVERTER *self, const ELEMENT *command,
+                            ELEMENT *manual_content)
 {
-  char *result;
-  HTML_TARGET *target_info;
-  ELEMENT *tree_root;
-  ELEMENT *manual_content = lookup_extra_element (command,
-                                                  "manual_content");
-  if (manual_content)
-    {
-      TREE_ADDED_ELEMENTS *command_tree = html_command_tree (self, command, 0);
-      TREE_ADDED_ELEMENTS *string_tree = 0;
-      if (type == HTT_string)
-        {
-          ELEMENT *tree_root_string;
+  TREE_ADDED_ELEMENTS *tree;
 
-          string_tree
-            = new_tree_added_elements (tree_added_status_elements_added);
+  ELEMENT *root_code;
+  ELEMENT *open_p;
+  ELEMENT *close_p;
 
-          tree_root_string = new_element_added (string_tree, ET__string);
+  ELEMENT *node_content = lookup_extra_element (command,
+                                                "node_content");
 
-          add_to_contents_as_array (tree_root_string, command_tree->tree);
-          tree_root = tree_root_string;
-          add_to_element_list (&self->tree_to_build, tree_root);
-        }
-      else
-        tree_root = command_tree->tree;
+  tree = new_tree_added_elements (tree_added_status_elements_added);
 
-      result = convert_tree_new_formatting_context (self, tree_root,
-                                     element_command_name(command),
-                                     "command_text-manual_content", 0, 0);
+  root_code = new_element_added (tree, ET__code);
+  open_p = new_element_added (tree, ET_NONE);
+  close_p = new_element_added (tree, ET_NONE);
 
-      if (type == HTT_string)
-        {
-          remove_element_from_list (&self->tree_to_build, tree_root);
-          destroy_tree_added_elements (self, string_tree);
-        }
-      destroy_tree_added_elements (self, command_tree);
-      return result;
+  text_append_n (&open_p->text, "(", 1);
+  text_append_n (&close_p->text, ")", 1);
+
+  add_to_element_contents (root_code, open_p);
+  add_to_contents_as_array (root_code, manual_content);
+  add_to_element_contents (root_code, close_p);
+  if (node_content)
+    add_to_contents_as_array (root_code, node_content);
+
+  tree->tree = root_code;
+  add_to_element_list (&self->tree_to_build, root_code);
+  return tree;
+}
+
+TREE_ADDED_ELEMENTS *
+html_command_tree (CONVERTER *self, const ELEMENT *command, int no_number)
+{
+
+  ELEMENT *manual_content = lookup_extra_element (command,
+                                                  "manual_content");
+  if (manual_content)
+    {
+      return html_external_command_tree (self, command, manual_content);
     }
 
-  target_info = get_target (self, command);
+  return html_internal_command_tree (self, command, no_number);
+}
+
+/* return value to be freed by caller */
+char *
+html_internal_command_text (CONVERTER *self, const ELEMENT *command,
+                            const enum html_text_type type)
+{
+  HTML_TARGET *target_info = html_get_target (self, command);
+
   if (target_info)
     {
       if (target_info->command_text[type])
         return strdup (target_info->command_text[type]);
       else
         {
+          ELEMENT *tree_root;
           TREE_ADDED_ELEMENTS *string_tree = 0;
           char *explanation = 0;
           char *context_name;
           ELEMENT *selected_tree;
           TREE_ADDED_ELEMENTS *command_tree
-            = html_command_tree (self, command, 0);
+            = html_internal_command_tree (self, command, 0);
 
           if (!command_tree->tree)
             return strdup ("");
@@ -3927,6 +3941,52 @@ html_command_text (CONVERTER *self, const ELEMENT 
*command,
   return 0;
 }
 
+/* return value to be freed by caller */
+char *
+html_command_text (CONVERTER *self, const ELEMENT *command,
+                   const enum html_text_type type)
+{
+  char *result;
+  ELEMENT *manual_content = lookup_extra_element (command,
+                                                  "manual_content");
+  if (manual_content)
+    {
+      ELEMENT *tree_root;
+      TREE_ADDED_ELEMENTS *command_tree
+        = html_external_command_tree (self, command, manual_content);
+      TREE_ADDED_ELEMENTS *string_tree = 0;
+      if (type == HTT_string)
+        {
+          ELEMENT *tree_root_string;
+
+          string_tree
+            = new_tree_added_elements (tree_added_status_elements_added);
+
+          tree_root_string = new_element_added (string_tree, ET__string);
+
+          add_to_contents_as_array (tree_root_string, command_tree->tree);
+          tree_root = tree_root_string;
+          add_to_element_list (&self->tree_to_build, tree_root);
+        }
+      else
+        tree_root = command_tree->tree;
+
+      result = convert_tree_new_formatting_context (self, tree_root,
+                                     element_command_name(command),
+                                     "command_text-manual_content", 0, 0);
+
+      if (type == HTT_string)
+        {
+          remove_element_from_list (&self->tree_to_build, tree_root);
+          destroy_tree_added_elements (self, string_tree);
+        }
+      destroy_tree_added_elements (self, command_tree);
+      return result;
+    }
+
+  return html_internal_command_text (self, command, type);
+}
+
 /* return value to be freed by caller */
 char *
 from_element_direction (CONVERTER *self, int direction,
@@ -3983,8 +4043,8 @@ from_element_direction (CONVERTER *self, int direction,
         {
           ELEMENT *external_node_element = target_unit->unit_command;
           if (type == HTT_href)
-            return html_command_href (self, external_node_element,
-                                      filename_from, source_command, 0);
+            return external_node_href (self, external_node_element,
+                                       source_command);
           else if (type == HTT_text || type == HTT_node)
             return html_command_text (self, external_node_element, 0);
           else if (type == HTT_string)
@@ -4778,7 +4838,7 @@ html_prepare_output_units_global_targets (CONVERTER *self,
               const OUTPUT_UNIT *special_unit = units_list->list[j];
               char *special_unit_variety = special_unit->special_unit_variety;
               int special_unit_direction_index
-                = special_unit_variety_direction_index (self,
+                = html_special_unit_variety_direction_index (self,
                                                 special_unit_variety);
               self->global_units_directions[special_unit_direction_index]
                 = special_unit;
@@ -9141,7 +9201,7 @@ contents_inline_element (CONVERTER *self, const enum 
command_id cmd,
               char *special_unit_variety
                 = self->special_unit_varieties.list[cmd_variety_index.index];
               int special_unit_direction_index
-                    = special_unit_variety_direction_index (self,
+                    = html_special_unit_variety_direction_index (self,
                                                 special_unit_variety);
               const OUTPUT_UNIT *special_unit
                 = self->global_units_directions[special_unit_direction_index];
@@ -11716,7 +11776,7 @@ html_translate_names (CONVERTER *self)
     {
       char *special_unit_variety = special_unit_varieties->list[j];
       int special_unit_direction_index
-       = special_unit_variety_direction_index (self, special_unit_variety);
+       = html_special_unit_variety_direction_index (self, 
special_unit_variety);
       if (special_unit_direction_index >= 0)
         {
           const OUTPUT_UNIT *special_unit
diff --git a/tp/Texinfo/XS/convert/convert_html.h 
b/tp/Texinfo/XS/convert/convert_html.h
index 25243e4a56..88b50eb73d 100644
--- a/tp/Texinfo/XS/convert/convert_html.h
+++ b/tp/Texinfo/XS/convert/convert_html.h
@@ -82,6 +82,12 @@ void html_register_file_information (CONVERTER *self, const 
char *key,
 int html_get_file_information (CONVERTER *self, const char *key,
                                const char *filename, int *status);
 
+int html_special_unit_variety_direction_index (CONVERTER *self,
+                                        char *special_unit_variety);
+
+HTML_TARGET *html_get_target (CONVERTER *self, const ELEMENT *element);
+char *html_command_id (CONVERTER *self, const ELEMENT *command);
+
 void html_register_opened_section_level (CONVERTER *self, int level,
                                          const char *close_string);
 STRING_LIST *html_close_registered_sections_level (CONVERTER *self,
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.c 
b/tp/Texinfo/XS/convert/get_html_perl_info.c
index db31ca7d8a..3b6eb0fe24 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.c
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.c
@@ -38,8 +38,14 @@ FIXME add an initialization of translations?
 #endif
 */
 
+#include "command_ids.h"
 #include "converter_types.h"
 #include "utils.h"
+#include "targets.h"
+#include "builtin_commands.h"
+#include "debug.h"
+#include "convert_to_texinfo.h"
+#include "output_unit.h"
 #include "converter.h"
 #include "convert_html.h"
 #include "get_perl_info.h"
@@ -1128,3 +1134,250 @@ html_converter_prepare_output_sv (SV *converter_sv, 
CONVERTER *converter)
 
 #undef FETCH
 
+ELEMENT *
+find_index_entry_element (CONVERTER *converter, SV *index_entry_sv)
+{
+  AV *index_entry_av;
+  SV **index_name_sv;
+  char *index_name = 0;
+
+  dTHX;
+
+  if (!converter->document->index_names)
+    return 0;
+
+  index_entry_av = (AV *) SvRV (index_entry_sv);
+
+  index_name_sv = av_fetch (index_entry_av, 0, 0);
+  if (index_name_sv)
+    {
+      index_name = SvPVutf8_nolen (*index_name_sv);
+    }
+
+  if (index_name)
+    {
+      SV **number_sv = av_fetch (index_entry_av, 1, 0);
+      if (number_sv)
+        {
+          int entry_number = SvIV (*number_sv);
+          INDEX **index_names = converter->document->index_names;
+          INDEX *idx = indices_info_index_by_name (index_names, index_name);
+
+          if (idx)
+            {
+              INDEX_ENTRY *index_entry = &idx->index_entries[entry_number -1];
+              if (index_entry->entry_associated_element)
+                return index_entry->entry_associated_element;
+              else if (index_entry->entry_element)
+                return index_entry->entry_element;
+            }
+        }
+    }
+  return 0;
+}
+
+#define FETCH(key) key##_sv = hv_fetch (element_hv, #key, strlen(#key), 0);
+/* find C tree root element corresponding to perl tree element element_hv */
+ELEMENT *find_root_command (CONVERTER *converter, HV *element_hv,
+                            int output_units_descriptor)
+{
+  SV **associated_unit_sv;
+  ELEMENT *root;
+  size_t i;
+
+  dTHX;
+
+  FETCH(associated_unit)
+
+  if (associated_unit_sv)
+    {
+      /* find the associated ouput unit and then find the element
+         in unit contents */
+      HV *associated_unit_hv = (HV *) SvRV (*associated_unit_sv);
+      SV **unit_index_sv = hv_fetch (associated_unit_hv, "unit_index",
+                                     strlen ("unit_index"), 0);
+
+      if (unit_index_sv)
+        {
+          int unit_index = SvIV (*unit_index_sv);
+          const OUTPUT_UNIT_LIST *output_units
+           = retrieve_output_units (output_units_descriptor);
+
+          if (output_units && unit_index < output_units->number)
+            {
+              OUTPUT_UNIT *output_unit = output_units->list[unit_index];
+              size_t i;
+              for (i = 0; i < output_unit->unit_contents.number; i++)
+                {
+                  ELEMENT *content = output_unit->unit_contents.list[i];
+                  if (content->hv == element_hv)
+                    return content;
+                }
+            }
+        }
+    }
+
+  /* if there are no output units go through the root element children */
+  root = converter->document->tree;
+  for (i = 0; i < root->contents.number; i++)
+    {
+      ELEMENT *content = root->contents.list[i];
+      if (content->hv == element_hv)
+        return content;
+    }
+  return 0;
+}
+
+/* find C Texinfo tree element based on element_sv perl tree element.
+   Only for elements that can be targets of links. */
+ELEMENT *
+find_element_from_sv (CONVERTER *converter, SV *element_sv,
+                      int output_units_descriptor)
+{
+  enum command_id cmd = 0;
+  HV *element_hv;
+  SV **cmdname_sv;
+  SV **extra_sv;
+  SV **type_sv;
+
+  dTHX;
+
+  element_hv = (HV *) SvRV (element_sv);
+
+  FETCH(cmdname)
+
+  if (cmdname_sv)
+    {
+      char *cmdname = SvPVutf8_nolen (*cmdname_sv);
+      cmd = lookup_builtin_command (cmdname);
+
+      if (builtin_command_data[cmd].flags & CF_root
+          && cmd != CM_node)
+        {
+          ELEMENT *element = find_root_command (converter, element_hv,
+                                                output_units_descriptor);
+          if (element)
+            return element;
+        }
+    }
+
+  FETCH(extra)
+
+#define EXTRA(key) key##_sv = hv_fetch (extra_hv, #key, strlen(#key), 0);
+  if (extra_sv)
+    {
+      HV *extra_hv = (HV *) SvRV (*extra_sv);
+      SV **normalized_sv;
+      SV **global_command_number_sv;
+      SV **index_entry_sv;
+      SV **associated_index_entry_sv;
+
+      EXTRA(normalized)
+      if (normalized_sv)
+        {
+          char *normalized = SvPVutf8_nolen (*normalized_sv);
+          if (converter->document->identifiers_target)
+            {
+              ELEMENT *element_found
+                = find_identifier_target
+                      (converter->document->identifiers_target, normalized);
+         /* check the element found in case of multiple defined identifier */
+              if (element_found && element_hv == element_found->hv)
+                return element_found;
+            }
+        }
+
+      EXTRA(global_command_number)
+      if (global_command_number_sv)
+        {
+          int global_command_number = SvIV (*global_command_number_sv);
+          ELEMENT_LIST *global_cmd_list
+            = get_cmd_global_multi_command (
+                          converter->document->global_commands, cmd);
+
+          if (global_command_number > 0
+              && global_command_number - 1 < global_cmd_list->number)
+            return global_cmd_list->list[global_command_number - 1];
+        }
+
+      EXTRA(associated_index_entry)
+      if (associated_index_entry_sv)
+        {
+          ELEMENT *index_element = find_index_entry_element (converter,
+                                               *associated_index_entry_sv);
+          /* there should be no ambiguity, but we check nevertheless */
+          if (index_element && index_element->hv == element_hv)
+            return (index_element);
+        }
+
+      EXTRA(index_entry)
+      if (index_entry_sv)
+        {
+          ELEMENT *index_element = find_index_entry_element (converter,
+                                                          *index_entry_sv);
+          /* it is important to check if the index entry was reassociated */
+          if (index_element && index_element->hv == element_hv)
+            return (index_element);
+        }
+    }
+
+  FETCH(type)
+
+  if (type_sv)
+    {
+      char *type_name = SvPVutf8_nolen (*type_sv);
+      if (!strcmp (type_name, "special_unit_element"))
+        {
+          SV **associated_unit_sv;
+          FETCH(associated_unit)
+          if (associated_unit_sv)
+            {
+              HV *associated_unit_hv = (HV *) SvRV (*associated_unit_sv);
+              SV **special_unit_variety_hv
+                = hv_fetch (associated_unit_hv, "special_unit_variety",
+                            strlen ("special_unit_variety"), 0);
+              if (special_unit_variety_hv)
+                {
+                  char *special_unit_variety
+                    = SvPVutf8_nolen (*special_unit_variety_hv);
+                  int special_unit_direction_index
+                    = html_special_unit_variety_direction_index (converter,
+                                                special_unit_variety);
+                  const OUTPUT_UNIT *special_unit
+            = converter->global_units_directions[special_unit_direction_index];
+                  if (special_unit)
+                    return special_unit->unit_command;
+                }
+            }
+        }
+    }
+
+  return 0;
+}
+
+#undef EXTRA
+
+#undef FETCH
+
+/* Not sure if it is generic or HTML specific */
+int
+get_output_units_descriptor_converter_sv (SV *converter_in)
+{
+  HV *converter_hv;
+  SV **output_units_sv;
+
+  dTHX;
+
+  int output_units_descriptor = 0;
+
+  converter_hv = (HV *) SvRV (converter_in);
+
+  output_units_sv = hv_fetch (converter_hv, "document_units",
+                              strlen ("document_units"), 0);
+  if (output_units_sv && SvOK (*output_units_sv))
+    output_units_descriptor
+        = get_sv_output_units_descriptor (*output_units_sv,
+                     "html_command_id output units");
+
+  return output_units_descriptor;
+}
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.h 
b/tp/Texinfo/XS/convert/get_html_perl_info.h
index 0c224ed932..ee3b67a9a4 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.h
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.h
@@ -5,6 +5,8 @@
 #include "EXTERN.h"
 #include "perl.h"
 
+int get_output_units_descriptor_converter_sv (SV *converter_in);
+
 void html_converter_initialize_sv (SV *converter_sv,
                                   SV *default_formatting_references,
                                   SV *default_css_string_formatting_references,
@@ -19,4 +21,6 @@ void html_converter_initialize_sv (SV *converter_sv,
 
 void html_converter_prepare_output_sv (SV *converter_sv, CONVERTER *converter);
 
+ELEMENT *find_element_from_sv (CONVERTER *converter, SV *element_sv,
+                               int output_units_descriptor);
 #endif
diff --git a/tp/Texinfo/XS/main/converter_types.h 
b/tp/Texinfo/XS/main/converter_types.h
index 06416a386d..f658c01001 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -486,7 +486,7 @@ typedef struct STRING_WITH_LEN {
 typedef struct HTML_ADDED_TARGET_LIST {
     size_t space;
     size_t number;
-    HTML_TARGET **list;
+    size_t *list;
 } HTML_ADDED_TARGET_LIST;
 
 typedef struct CSS_SELECTOR_STYLE {
@@ -762,7 +762,7 @@ typedef struct CONVERTER {
     ELEMENT_LIST reset_target_commands; /* element targets that should have
                                            their texts reset after language
                                            change */
-    HTML_ADDED_TARGET_LIST added_targets; /* targets added */
+    HTML_ADDED_TARGET_LIST added_targets; /* target numbers of added targets */
     STRING_LIST shared_conversion_state_integer; /* modified */
     /* next 4 allow to switch from normal HTML formatting to css strings
        formatting */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]