[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[no subject]
From: |
Patrice Dumas |
Date: |
Mon, 4 Dec 2023 18:42:15 -0500 (EST) |
branch: master
commit 6f520a48677399dae24882903462ea878fa4f84c
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Tue Dec 5 00:39:24 2023 +0100
* tp/Texinfo/XS/main/converter_types.h (FILE_NUMBER_NAME): rename
CURRENT_FILE_INFO as FILE_NUMBER_NAME.
* tp/Texinfo/XS/convert/build_html_perl_state.c
(build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
(html_command_text, html_free_converter),
tp/Texinfo/XS/main/converter_types.h (CONVERTER): make
referred_command_stack a stack instead of a list.
* tp/Texinfo/XS/main/get_perl_info.c (converter_initialize): add and
use FETCH macro.
* tp/Texinfo/XS/convert/build_html_perl_state.c
(build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
(html_free_converter, get_shared_conversion_state_integer)
(register_modified_shared_conversion_state_integer),
tp/Texinfo/XS/main/converter_types.h (CONVERTER): add functions to
pass shared_conversion_state modified integers to perl.
* tp/Texinfo/XS/convert/convert_html.c (format_protect_text)
(url_protect_url_text, url_protect_file_text),
tp/Texinfo/XS/convert/call_html_perl_function.c
(call_formatting_function_format_protect_text): add.
* tp/Texinfo/XS/convert/convert_html.c (html_command_id):
add some const. Rename target as target_info.
* tp/Texinfo/XS/convert/convert_html.c (html_get_tree_root_element)
(new_sectioning_command_target, get_target): use
element_builtin_data_cmd and variables for the flags to get the
expected result even with user-defined @-commands.
* tp/Texinfo/XS/main/get_perl_info.c (converter_initialize),
tp/Texinfo/XS/main/converter_types.h (CONVERTER): add output_format
and pass from perl.
* tp/Texinfo/XS/convert/convert_html.c (external_node_href)
(htmlxref_split_type_names, htmlxref_entries)
(compare_htmlxref_manual, find_htmlxref_manual)
(check_htmlxref_already_warned, html_initialize_output_state)
(html_free_converter), tp/Texinfo/XS/convert/call_html_perl_function.c
(call_file_id_setting_external_target_split_name)
(call_file_id_setting_external_target_non_split_name),
tp/Texinfo/XS/main/converter_types.h (enum htmlxref_split_type)
(HTMLXREF_MANUAL, HTMLXREF_MANUAL_LIST)
(HTMLXREF_MANUAL_ELEMENT_WARNED, HTMLXREF_MANUAL_ELEMENT_WARNED_LIST)
(CONVERTER): get htmlxref from perl, add related functions, set
self->document_htmlxref_split_type, sort htmlxref information, add
functions to get and warn if htmlxref not found. Implement
external_node_href.
* tp/Texinfo/XS/convert/call_html_perl_function.c: use SvPVutf8 more.
* tp/Texinfo/XS/convert/convert_html.c (html_command_filename)
(command_root_element_command, html_command_href)
(html_command_contents_target, html_command_contents_href)
(mini_toc_internal, contents_inline_element, convert_contents_command)
(convert_heading_command),
tp/Texinfo/XS/convert/call_html_perl_function.c
(call_formatting_function_format_contents)
(call_formatting_function_format_separate_anchor)
(call_formatting_function_format_element_header)
tp/Texinfo/XS/convert/call_html_perl_function.h
(TARGET_DIRECTORY_FILENAME),: implement html_command_filename,
command_root_element_command, html_command_href,
html_command_contents_target, html_command_contents_href,
mini_toc_internal contents_inline_element . Add conversion functions
convert_contents_command and convert_heading_command. Add perl
functions call.
---
ChangeLog | 72 +
tp/Texinfo/XS/convert/build_html_perl_state.c | 48 +-
tp/Texinfo/XS/convert/call_html_perl_function.c | 453 ++-
tp/Texinfo/XS/convert/call_html_perl_function.h | 27 +-
tp/Texinfo/XS/convert/convert_html.c | 4495 +++++++++++++++--------
tp/Texinfo/XS/convert/convert_html.h | 1 +
tp/Texinfo/XS/convert/converter.c | 3 +-
tp/Texinfo/XS/convert/converter.h | 2 +-
tp/Texinfo/XS/convert/get_html_perl_info.c | 50 +
tp/Texinfo/XS/main/converter_types.h | 61 +-
tp/Texinfo/XS/main/get_perl_info.c | 43 +-
11 files changed, 3713 insertions(+), 1542 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 963ea76dae..89f121084f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+2023-12-04 Patrice Dumas <pertusus@free.fr>
+
+ * tp/Texinfo/XS/main/converter_types.h (FILE_NUMBER_NAME): rename
+ CURRENT_FILE_INFO as FILE_NUMBER_NAME.
+
+ * tp/Texinfo/XS/convert/build_html_perl_state.c
+ (build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
+ (html_command_text, html_free_converter),
+ tp/Texinfo/XS/main/converter_types.h (CONVERTER): make
+ referred_command_stack a stack instead of a list.
+
+ * tp/Texinfo/XS/main/get_perl_info.c (converter_initialize): add and
+ use FETCH macro.
+
+ * tp/Texinfo/XS/convert/build_html_perl_state.c
+ (build_html_formatting_state), tp/Texinfo/XS/convert/convert_html.c
+ (html_free_converter, get_shared_conversion_state_integer)
+ (register_modified_shared_conversion_state_integer),
+ tp/Texinfo/XS/main/converter_types.h (CONVERTER): add functions to
+ pass shared_conversion_state modified integers to perl.
+
+ * tp/Texinfo/XS/convert/convert_html.c (format_protect_text)
+ (url_protect_url_text, url_protect_file_text),
+ tp/Texinfo/XS/convert/call_html_perl_function.c
+ (call_formatting_function_format_protect_text): add.
+
+ * tp/Texinfo/XS/convert/convert_html.c (html_command_id):
+ add some const. Rename target as target_info.
+
+ * tp/Texinfo/XS/convert/convert_html.c (html_get_tree_root_element)
+ (new_sectioning_command_target, get_target): use
+ element_builtin_data_cmd and variables for the flags to get the
+ expected result even with user-defined @-commands.
+
+ * tp/Texinfo/XS/main/get_perl_info.c (converter_initialize),
+ tp/Texinfo/XS/main/converter_types.h (CONVERTER): add output_format
+ and pass from perl.
+
+ * tp/Texinfo/XS/convert/convert_html.c (external_node_href)
+ (htmlxref_split_type_names, htmlxref_entries)
+ (compare_htmlxref_manual, find_htmlxref_manual)
+ (check_htmlxref_already_warned, html_initialize_output_state)
+ (html_free_converter), tp/Texinfo/XS/convert/call_html_perl_function.c
+ (call_file_id_setting_external_target_split_name)
+ (call_file_id_setting_external_target_non_split_name),
+ tp/Texinfo/XS/main/converter_types.h (enum htmlxref_split_type)
+ (HTMLXREF_MANUAL, HTMLXREF_MANUAL_LIST)
+ (HTMLXREF_MANUAL_ELEMENT_WARNED, HTMLXREF_MANUAL_ELEMENT_WARNED_LIST)
+ (CONVERTER): get htmlxref from perl, add related functions, set
+ self->document_htmlxref_split_type, sort htmlxref information, add
+ functions to get and warn if htmlxref not found. Implement
+ external_node_href.
+
+ * tp/Texinfo/XS/convert/call_html_perl_function.c: use SvPVutf8 more.
+
+ * tp/Texinfo/XS/convert/convert_html.c (html_command_filename)
+ (command_root_element_command, html_command_href)
+ (html_command_contents_target, html_command_contents_href)
+ (mini_toc_internal, contents_inline_element, convert_contents_command)
+ (convert_heading_command),
+ tp/Texinfo/XS/convert/call_html_perl_function.c
+ (call_formatting_function_format_contents)
+ (call_formatting_function_format_separate_anchor)
+ (call_formatting_function_format_element_header)
+ tp/Texinfo/XS/convert/call_html_perl_function.h
+ (TARGET_DIRECTORY_FILENAME),: implement html_command_filename,
+ command_root_element_command, html_command_href,
+ html_command_contents_target, html_command_contents_href,
+ mini_toc_internal contents_inline_element . Add conversion functions
+ convert_contents_command and convert_heading_command. Add perl
+ functions call.
+
2023-12-04 Patrice Dumas <pertusus@free.fr>
* tp/maintain/setup_converters_code_tables.pl: add include
diff --git a/tp/Texinfo/XS/convert/build_html_perl_state.c
b/tp/Texinfo/XS/convert/build_html_perl_state.c
index 326031d3fc..6df4d70572 100644
--- a/tp/Texinfo/XS/convert/build_html_perl_state.c
+++ b/tp/Texinfo/XS/convert/build_html_perl_state.c
@@ -34,6 +34,7 @@
#include "converter_types.h"
/* for fatal HMSF_* */
#include "utils.h"
+#include "extra.h"
/* for debugging */
#include "debug.h"
#include "convert_to_texinfo.h"
@@ -776,9 +777,9 @@ build_html_formatting_state (CONVERTER *converter, unsigned
long flags)
av_clear (referred_command_stack_av);
}
- for (i = 0; i < converter->referred_command_stack.number; i++)
+ for (i = 0; i < converter->referred_command_stack.top; i++)
{
- ELEMENT *referred_e = converter->referred_command_stack.list[i];
+ const ELEMENT *referred_e =
converter->referred_command_stack.stack[i];
av_push (referred_command_stack_av,
newRV_inc ((SV *) referred_e->hv));
}
@@ -829,6 +830,49 @@ build_html_formatting_state (CONVERTER *converter,
unsigned long flags)
converter->added_targets.number = 0;
}
+ if (flags & HMSF_shared_conversion_state_integer)
+ {
+ int j;
+ SV **shared_conversion_state_sv;
+ HV *shared_conversion_state_hv;
+
+ FETCH(shared_conversion_state)
+
+ if (!shared_conversion_state_sv)
+ {
+ shared_conversion_state_hv = newHV ();
+ STORE("shared_conversion_state",
+ newRV_noinc ((SV *) shared_conversion_state_hv));
+ }
+ else
+ shared_conversion_state_hv
+ = (HV *) SvRV (*shared_conversion_state_sv);
+
+ for (j = 0; j < converter->shared_conversion_state_integer.number; j++)
+ {
+ const char *key = converter->shared_conversion_state_integer.list[j];
+ KEY_PAIR *k
+ = lookup_associated_info (
+ &converter->shared_conversion_state.integers, key);
+
+ SV **int_key_sv = hv_fetch (shared_conversion_state_hv,
+ key, strlen (key), 0);
+ if (!int_key_sv)
+ {
+ SV *int_value_sv = newSViv ((IV) k->integer);
+ SV *int_sv = newRV_noinc (int_value_sv);
+ hv_store (shared_conversion_state_hv, key,
+ strlen (key), int_sv, 0);
+ }
+ else
+ {
+ SV *int_value_sv = SvRV (*int_key_sv);
+ sv_setiv (int_value_sv, (IV) k->integer);
+ }
+ }
+ clear_strings_list (&converter->shared_conversion_state_integer);
+ }
+
/*
files_information_sv = hv_fetch (hv, "files_information",
strlen ("files_information"), 0);
diff --git a/tp/Texinfo/XS/convert/call_html_perl_function.c
b/tp/Texinfo/XS/convert/call_html_perl_function.c
index 9be480c296..35edb15597 100644
--- a/tp/Texinfo/XS/convert/call_html_perl_function.c
+++ b/tp/Texinfo/XS/convert/call_html_perl_function.c
@@ -510,6 +510,190 @@ call_file_id_setting_unit_file_name (CONVERTER *self,
OUTPUT_UNIT *output_unit,
return 0;
}
+TARGET_DIRECTORY_FILENAME *
+call_file_id_setting_external_target_split_name (CONVERTER *self,
+ const char *normalized, const ELEMENT *element,
+ const char *target, const char *directory,
+ const char *file_name)
+{
+ SV **file_id_setting_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ file_id_setting_sv = hv_fetch (self->hv, "file_id_setting",
+ strlen ("file_id_setting"), 0);
+ if (file_id_setting_sv)
+ {
+ SV **external_target_split_name_sv;
+ HV *file_id_setting_hv = (HV *)SvRV(*file_id_setting_sv);
+ external_target_split_name_sv = hv_fetch (file_id_setting_hv,
+ "external_target_split_name",
+ strlen ("external_target_split_name"), 0);
+
+ if (external_target_split_name_sv)
+ {
+ int count;
+ SV *target_sv;
+ SV *filename_sv;
+ SV *directory_sv;
+ TARGET_DIRECTORY_FILENAME *result = (TARGET_DIRECTORY_FILENAME *)
+ malloc (sizeof (TARGET_DIRECTORY_FILENAME));
+ memset (result, 0, sizeof (TARGET_DIRECTORY_FILENAME));
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 6);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (normalized, 0)));
+ PUSHs(sv_2mortal (newRV_inc (element->hv)));
+ /* FIXME encoding */
+ PUSHs(sv_2mortal (newSVpv (target, 0)));
+ PUSHs(sv_2mortal (newSVpv (directory, 0)));
+ PUSHs(sv_2mortal (newSVpv (file_name, 0)));
+ PUTBACK;
+
+ count = call_sv (*external_target_split_name_sv, G_ARRAY);
+
+ SPAGAIN;
+
+ if (count != 3)
+ croak("external_target_split_name should return 3 items\n");
+
+ filename_sv = POPs;
+ if (SvOK (filename_sv))
+ {
+ STRLEN len;
+ char *filename_ret = SvPV (filename_sv, len);
+ result->filename = strdup (filename_ret);
+ }
+ else
+ result->filename = strdup ("");
+
+ directory_sv = POPs;
+ if (SvOK (directory_sv))
+ {
+ STRLEN len;
+ char *directory_ret = SvPV (directory_sv, len);
+ result->directory = strdup (directory_ret);
+ }
+ else
+ result->directory = strdup ("");
+
+ target_sv = POPs;
+ if (SvOK (target_sv))
+ {
+ STRLEN len;
+ char *target_ret = SvPV (target_sv, len);
+ result->target = strdup (target_ret);
+ }
+ else
+ result->target = strdup ("");
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ return result;
+ }
+ }
+ return 0;
+}
+
+TARGET_FILENAME *
+call_file_id_setting_external_target_non_split_name (CONVERTER *self,
+ const char *normalized, const ELEMENT *element,
+ const char *target, const char *file)
+{
+ SV **file_id_setting_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ file_id_setting_sv = hv_fetch (self->hv, "file_id_setting",
+ strlen ("file_id_setting"), 0);
+ if (file_id_setting_sv)
+ {
+ SV **external_target_non_split_name_sv;
+ HV *file_id_setting_hv = (HV *)SvRV(*file_id_setting_sv);
+ external_target_non_split_name_sv = hv_fetch (file_id_setting_hv,
+ "external_target_non_split_name",
+ strlen ("external_target_non_split_name"), 0);
+
+ if (external_target_non_split_name_sv)
+ {
+ int count;
+ SV *target_sv;
+ SV *file_sv;
+ TARGET_FILENAME *result
+ = (TARGET_FILENAME *) malloc (sizeof (TARGET_FILENAME));
+ result->filename = 0;
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 5);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (normalized, 0)));
+ PUSHs(sv_2mortal (newRV_inc (element->hv)));
+ /* FIXME encoding */
+ PUSHs(sv_2mortal (newSVpv (target, 0)));
+ PUSHs(sv_2mortal (newSVpv (file, 0)));
+ PUTBACK;
+
+ count = call_sv (*external_target_non_split_name_sv, G_ARRAY);
+
+ SPAGAIN;
+
+ if (count != 2)
+ croak("external_target_non_split_name should return 2 items\n");
+
+ file_sv = POPs;
+ if (SvOK (file_sv))
+ {
+ STRLEN len;
+ char *file_ret = SvPV (file_sv, len);
+ result->filename = strdup (file_ret);
+ }
+
+ target_sv = POPs;
+ if (SvOK (target_sv))
+ {
+ STRLEN len;
+ char *target_ret = SvPV (target_sv, len);
+ result->target = strdup (target_ret);
+ }
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ return result;
+ }
+ }
+ return 0;
+}
+
+
+
+
+
+
char *
call_formatting_function_format_title_titlepage (CONVERTER *self)
{
@@ -554,8 +738,66 @@ call_formatting_function_format_title_titlepage (CONVERTER
*self)
croak("format_title_titlepage should return 1 item\n");
result_sv = POPs;
- /* FIXME encoding */
- result_ret = SvPV (result_sv, len);
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ get_shared_conversion_state (self);
+
+ return result;
+}
+
+char *
+call_formatting_function_format_protect_text (CONVERTER *self,
+ const char *text)
+{
+ int count;
+ char *result;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ formatting_reference_sv
+ = self->formatting_references[FR_format_protect_text].sv_reference;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self, self->modified_state);
+ self->modified_state = 0;
+ }
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 1);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv_utf8 (text, 0)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference_sv,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("format_protect_text should return 1 item\n");
+
+ result_sv = POPs;
+ result_ret = SvPVutf8 (result_sv, len);
result = strdup (result_ret);
PUTBACK;
@@ -612,8 +854,7 @@ call_formatting_function_format_footnotes_segment
(CONVERTER *self)
croak("format_footnotes_segment should return 1 item\n");
result_sv = POPs;
- /* FIXME encoding */
- result_ret = SvPV (result_sv, len);
+ result_ret = SvPVutf8 (result_sv, len);
result = strdup (result_ret);
PUTBACK;
@@ -670,8 +911,7 @@ call_formatting_function_format_footnotes_sequence
(CONVERTER *self)
croak("format_footnotes_sequence should return 1 item\n");
result_sv = POPs;
- /* FIXME encoding */
- result_ret = SvPV (result_sv, len);
+ result_ret = SvPVutf8 (result_sv, len);
result = strdup (result_ret);
PUTBACK;
@@ -737,8 +977,7 @@ call_formatting_function_format_end_file (CONVERTER *self,
char *filename,
croak("format_end_file should return 1 item\n");
result_sv = POPs;
- /* FIXME encoding */
- result_ret = SvPV (result_sv, len);
+ result_ret = SvPVutf8 (result_sv, len);
result = strdup (result_ret);
PUTBACK;
@@ -804,8 +1043,7 @@ call_formatting_function_format_begin_file (CONVERTER
*self, char *filename,
croak("format_begin_file should return 1 item\n");
result_sv = POPs;
- /* FIXME encoding */
- result_ret = SvPV (result_sv, len);
+ result_ret = SvPVutf8 (result_sv, len);
result = strdup (result_ret);
PUTBACK;
@@ -956,7 +1194,7 @@ call_formatting_function_format_heading_text (CONVERTER
*self,
const STRING_LIST *classes,
const char *text,
int level, const char *id,
- ELEMENT *element, const char *target)
+ const ELEMENT *element, const char *target)
{
int count;
char *result = 0;
@@ -1044,6 +1282,199 @@ call_formatting_function_format_heading_text (CONVERTER
*self,
return result;
}
+char *
+call_formatting_function_format_contents (CONVERTER *self,
+ const char *cmdname, const ELEMENT *command,
+ const char *filename)
+{
+ int count;
+ char *result = 0;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ formatting_reference_sv
+ = self->formatting_references[
+ FR_format_contents].sv_reference;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self, self->modified_state);
+ self->modified_state = 0;
+ }
+
+ build_tree_to_build (&self->tree_to_build);
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 4);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (cmdname, 0)));
+ PUSHs(sv_2mortal (newRV_inc (command->hv)));
+ PUSHs(sv_2mortal (newSVpv (filename, 0)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference_sv,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("format_contents should return 1 item\n");
+
+ result_sv = POPs;
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ get_shared_conversion_state (self);
+
+ return result;
+}
+
+char *
+call_formatting_function_format_separate_anchor (CONVERTER *self,
+ const char *id, const char *class)
+{
+ int count;
+ char *result = 0;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ formatting_reference_sv
+ = self->formatting_references[
+ FR_format_separate_anchor].sv_reference;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self, self->modified_state);
+ self->modified_state = 0;
+ }
+
+ build_tree_to_build (&self->tree_to_build);
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 4);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv_utf8 (id, 0)));
+ PUSHs(sv_2mortal (newSVpv_utf8 (class, 0)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference_sv,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("format_separate_anchor should return 1 item\n");
+
+ result_sv = POPs;
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ get_shared_conversion_state (self);
+
+ return result;
+}
+
+char *
+call_formatting_function_format_element_header (CONVERTER *self,
+ const char *cmdname, const ELEMENT *command,
+ const OUTPUT_UNIT *output_unit)
+{
+ int count;
+ char *result = 0;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference_sv;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ formatting_reference_sv
+ = self->formatting_references[
+ FR_format_element_header].sv_reference;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self, self->modified_state);
+ self->modified_state = 0;
+ }
+
+ build_tree_to_build (&self->tree_to_build);
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 4);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (cmdname, 0)));
+ PUSHs(sv_2mortal (newRV_inc (command->hv)));
+ PUSHs(sv_2mortal (newRV_inc (output_unit->hv)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference_sv,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("format_element_header should return 1 item\n");
+
+ result_sv = POPs;
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ get_shared_conversion_state (self);
+
+ return result;
+}
+
char *
call_formatting_function_format_element_footer (CONVERTER *self,
const enum output_unit_type unit_type,
diff --git a/tp/Texinfo/XS/convert/call_html_perl_function.h
b/tp/Texinfo/XS/convert/call_html_perl_function.h
index 76c2807c69..0a9cef509d 100644
--- a/tp/Texinfo/XS/convert/call_html_perl_function.h
+++ b/tp/Texinfo/XS/convert/call_html_perl_function.h
@@ -13,6 +13,12 @@ typedef struct FILE_NAME_PATH {
char *filepath;
} FILE_NAME_PATH;
+typedef struct TARGET_DIRECTORY_FILENAME {
+ char *filename;
+ char *directory;
+ char *target;
+} TARGET_DIRECTORY_FILENAME;
+
typedef struct TARGET_CONTENTS_FILENAME {
char *target;
char *filename;
@@ -37,8 +43,19 @@ TARGET_CONTENTS_FILENAME *
call_file_id_setting_sectioning_command_target_name
FILE_NAME_PATH *call_file_id_setting_unit_file_name (CONVERTER *self,
OUTPUT_UNIT *output_unit,
char *filename, char *filepath);
+TARGET_DIRECTORY_FILENAME *call_file_id_setting_external_target_split_name
+ (CONVERTER *self,
+ const char *normalized, const ELEMENT *element,
+ const char *target, const char *directory,
+ const char *file_name);
+TARGET_FILENAME *call_file_id_setting_external_target_non_split_name
+ (CONVERTER *self,
+ const char *normalized, const ELEMENT *element,
+ const char *target, const char *file);
char *call_formatting_function_format_title_titlepage (CONVERTER *self);
+char *call_formatting_function_format_protect_text (CONVERTER *self,
+ const char *text);
char *call_formatting_function_format_footnotes_sequence (CONVERTER *self);
char *call_formatting_function_format_footnotes_segment (CONVERTER *self);
char *call_formatting_function_format_end_file (CONVERTER *self,
@@ -56,7 +73,15 @@ char *call_formatting_function_format_heading_text
(CONVERTER *self,
const STRING_LIST *classes,
const char *text,
int level, const char *id,
- ELEMENT *element, const char *target);
+ const ELEMENT *element, const char *target);
+char *call_formatting_function_format_element_header (CONVERTER *self,
+ const char *cmdname, const ELEMENT *command,
+ const OUTPUT_UNIT *output_unit);
+char *call_formatting_function_format_contents (CONVERTER *self,
+ const char *cmdname, const ELEMENT *command,
+ const char *filename);
+char *call_formatting_function_format_separate_anchor (CONVERTER *self,
+ const char *id, const char *class);
char *call_formatting_function_format_element_footer (CONVERTER *self,
const enum output_unit_type unit_type,
const OUTPUT_UNIT *output_unit,
diff --git a/tp/Texinfo/XS/convert/convert_html.c
b/tp/Texinfo/XS/convert/convert_html.c
index 0ebcf71d4f..02626e9e65 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
+#include <ctype.h>
#include "global_commands_types.h"
#include "tree_types.h"
@@ -46,6 +47,8 @@
/* for OTXI_UNICODE_TEXT_CASES */
#include "unicode.h"
#include "manipulate_tree.h"
+/* for new_complete_menu_master_menu */
+#include "structuring.h"
#include "convert_html.h"
enum count_elements_in_filename_type {
@@ -131,6 +134,19 @@ const char *special_unit_info_type_names[SUI_type_heading
+ 1] =
#undef sui_type
};
+const char *htmlxref_split_type_names[htmlxref_split_type_chapter + 1] =
+{
+ "mono", "node", "section", "chapter"
+};
+
+enum htmlxref_split_type htmlxref_entries[htmlxref_split_type_chapter +
1][htmlxref_split_type_chapter + 1] = {
+ { htmlxref_split_type_mono, htmlxref_split_type_chapter,
htmlxref_split_type_section, htmlxref_split_type_node },
+ { htmlxref_split_type_node, htmlxref_split_type_section,
htmlxref_split_type_chapter, htmlxref_split_type_mono },
+ { htmlxref_split_type_section, htmlxref_split_type_chapter,
htmlxref_split_type_node, htmlxref_split_type_mono },
+ { htmlxref_split_type_chapter, htmlxref_split_type_section,
htmlxref_split_type_node, htmlxref_split_type_mono },
+};
+
+
TRANSLATED_SUI_ASSOCIATION translated_special_unit_info[] = {
{SUIT_type_heading, SUI_type_heading},
/* these special types end the list */
@@ -282,6 +298,9 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT
*command,
while (1)
{
+ enum command_id data_cmd = element_builtin_data_cmd (current);
+ unsigned long flags = builtin_command_data[data_cmd].flags;
+
if (current->type == ET_special_unit_element)
{
ROOT_AND_UNIT *result = malloc (sizeof (ROOT_AND_UNIT));
@@ -290,14 +309,14 @@ html_get_tree_root_element (CONVERTER *self, const
ELEMENT *command,
return result;
}
- if (current->cmd && (builtin_command_flags(current) & CF_root))
+ if (data_cmd && (flags & CF_root))
root_command = current;
- else if (current->cmd && (builtin_command_flags(current) & CF_block)
- && builtin_command_data[current->cmd].data == BLOCK_region)
+ else if (data_cmd && (flags & CF_block)
+ && builtin_command_data[data_cmd].data == BLOCK_region)
{
const OUTPUT_UNIT_LIST *output_units
= retrieve_output_units (self->document_units_descriptor);
- if (current->cmd == CM_copying
+ if (data_cmd == CM_copying
&& self->document->global_commands->insertcopying.number > 0)
{
const ELEMENT_LIST global_insertcopying
@@ -313,7 +332,7 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT
*command,
return cur_result;
}
}
- else if (current->cmd == CM_titlepage
+ else if (data_cmd == CM_titlepage
&& self->conf->USE_TITLEPAGE_FOR_TITLE > 0
&& self->conf->SHOW_TITLE > 0
&& output_units->number > 0)
@@ -330,7 +349,7 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT
*command,
return result;
}
else if (find_container
- && html_commands_data[current->cmd].flags & HF_special_variety)
+ && html_commands_data[data_cmd].flags & HF_special_variety)
{
int j;
for (j = 0; self->command_special_variety_name_index[j].cmd; j++)
@@ -338,7 +357,7 @@ html_get_tree_root_element (CONVERTER *self, const ELEMENT
*command,
/* @footnote and possibly @*contents when a separate element is set */
COMMAND_ID_INDEX cmd_variety_index
= self->command_special_variety_name_index[j];
- if (cmd_variety_index.cmd == current->cmd)
+ if (cmd_variety_index.cmd == data_cmd)
{
char *special_unit_variety
= self->special_unit_varieties.list[cmd_variety_index.index];
@@ -772,10 +791,11 @@ html_register_footnote (CONVERTER *self, const ELEMENT
*command,
{
HTML_PENDING_FOOTNOTE_STACK *stack;
HTML_PENDING_FOOTNOTE *pending_footnote;
+
KEY_PAIR *k = lookup_associated_info
(&self->shared_conversion_state.integers,
"in_skipped_node_top");
- if (k && k->integer == 1)
+ if (k && k->integer > 0)
return;
stack = &self->pending_footnotes;
@@ -1602,6 +1622,12 @@ new_sectioning_command_target (CONVERTER *self, const
ELEMENT *command)
TARGET_FILENAME *target_filename
= normalized_sectioning_command_filename (self, command);
+ /* should not be needed for a sectioning command, as it should not
+ be possible for that command to be a user-defined command,
+ but it is better to be consistent, and it may change in the future */
+ enum command_id data_cmd = element_builtin_data_cmd (command);
+ unsigned long flags = builtin_command_data[data_cmd].flags;
+
normalized_name = target_filename->target;
filename = target_filename->filename;
@@ -1624,7 +1650,7 @@ new_sectioning_command_target (CONVERTER *self, const
ELEMENT *command)
free (target_base);
if (strlen (target)
- && (builtin_command_flags(command) & CF_sectioning_heading))
+ && (flags & CF_sectioning_heading))
{
char *target_base_contents;
char *target_base_shortcontents;
@@ -1984,6 +2010,136 @@ html_default_format_protect_text (const char *text,
TEXT *result)
OTXI_CONVERT_TEXT ( , )
}
+void
+format_protect_text (CONVERTER *self, const char *text, TEXT *result)
+{
+ if (self->formatting_references[FR_format_protect_text].status
+ == FRS_status_default_set)
+ {
+ html_default_format_protect_text (text, result);
+ }
+ else
+ {
+ char *protected_text
+ = call_formatting_function_format_protect_text (self, text);
+ text_append (result, protected_text);
+ free (protected_text);
+ }
+}
+
+static const char *reserved_unreserved_percent = "-_.!~*'()$&+,/:;=?@[]#%";
+
+static char *
+url_protect_url_text (CONVERTER *self, const char *input_string)
+{
+ TEXT text;
+ TEXT result;
+ text_init (&text);
+ const char *p = input_string;
+
+ text_append (&text, "");
+
+ /* protect 'ligntly', do not protect unreserved and reserved characters
+ + the % itself */
+ while (*p)
+ {
+ if (isascii_alnum (*p) || isascii_alpha (*p) || isascii_digit (*p))
+ {
+ text_append_n (&text, p, 1);
+ p++;
+ }
+ else
+ {
+ int n = strspn (p, reserved_unreserved_percent);
+ if (n)
+ {
+ text_append_n (&text, p, n);
+ p += n;
+ }
+ else
+ {
+ int i;
+ int char_len = 1;
+ if (!isascii (*p))
+ {
+ /* Protect UTF-8 with continuation bytes. */
+ while ((p[char_len] & 0xC0) == 0x80)
+ char_len++;
+ }
+ for (i = 0; i < char_len; i++)
+ {
+ text_printf (&text, "%%%02x", *p);
+ p += 1;
+ }
+ }
+ }
+ }
+ text_init (&result);
+ format_protect_text (self, text.text, &result);
+ free (text.text);
+ return (result.text);
+}
+
+static const char *file_path_punct = "-_.~/:";
+
+/*
+ protect a file path used in an url. Characters appearing in file paths
+ are not protected. All the other characters that can be percent
+ protected are protected, including characters with specific meaning in url.
+ */
+/* TODO readd static when the function is used
+static
+*/
+char *
+url_protect_file_text (CONVERTER *self, const char *input_string)
+{
+ TEXT text;
+ TEXT result;
+ text_init (&text);
+ const char *p = input_string;
+
+ text_append (&text, "");
+
+ while (*p)
+ {
+ if (isascii_alnum (*p) || isascii_alpha (*p) || isascii_digit (*p))
+ {
+ text_append_n (&text, p, 1);
+ p++;
+ }
+ else
+ {
+ int n = strspn (p, file_path_punct);
+ if (n)
+ {
+ text_append_n (&text, p, n);
+ p += n;
+ }
+ else
+ {
+ int i;
+ int char_len = 1;
+ if (!isascii (*p))
+ {
+ /* Protect UTF-8 with continuation bytes. */
+ while ((p[char_len] & 0xC0) == 0x80)
+ char_len++;
+ }
+ for (i = 0; i < char_len; i++)
+ {
+ text_printf (&text, "%%%02x", *p);
+ p += 1;
+ }
+ }
+ }
+ }
+
+ text_init (&result);
+ format_protect_text (self, text.text, &result);
+ free (text.text);
+ return (result.text);
+}
+
static TREE_ADDED_ELEMENTS *
new_tree_added_elements ()
{
@@ -2168,7 +2324,7 @@ convert_tree_new_formatting_context (CONVERTER *self,
const ELEMENT *tree,
}
if (self->conf->DEBUG > 0)
- fprintf (stderr, "new_fmt_ctx %s%s\n", context_string_str.text,
+ fprintf (stderr, "XS|new_fmt_ctx %s%s\n", context_string_str.text,
multiple_pass_str);
xasprintf (&explanation, "new_fmt_ctx %s", context_string_str.text);
@@ -2210,9 +2366,12 @@ get_target (CONVERTER *self, const ELEMENT *element)
{
HTML_TARGET *result
= find_element_target (&self->html_targets, element);
- if (!result && element->cmd
- && builtin_command_flags(element) & CF_sectioning_heading
- && !(builtin_command_flags(element) & CF_root))
+ enum command_id data_cmd = element_builtin_data_cmd (element);
+ unsigned long flags = builtin_command_data[data_cmd].flags;
+
+ if (!result && data_cmd
+ && flags & CF_sectioning_heading
+ && !(flags & CF_root))
{
new_sectioning_command_target (self, element);
@@ -2224,1822 +2383,3129 @@ get_target (CONVERTER *self, const ELEMENT *element)
return result;
}
-char *html_command_id (CONVERTER *self, ELEMENT *command)
+char *html_command_id (CONVERTER *self, const ELEMENT *command)
{
- HTML_TARGET *target = get_target (self, command);
- if (target)
- return target->target;
+ HTML_TARGET *target_info = get_target (self, command);
+ if (target_info)
+ return target_info->target;
else
return 0;
}
-ELEMENT *
-new_element_added (TREE_ADDED_ELEMENTS *added_elements, enum element_type type)
+static int
+compare_htmlxref_manual (const void *a, const void *b)
{
- ELEMENT *new = new_element (type);
- add_to_element_list (&added_elements->added, new);
- return new;
+ const HTMLXREF_MANUAL *hxfm_a = (const HTMLXREF_MANUAL *) a;
+ const HTMLXREF_MANUAL *hxfm_b = (const HTMLXREF_MANUAL *) b;
+
+ return strcmp (hxfm_a->manual, hxfm_b->manual);
}
-TREE_ADDED_ELEMENTS *
-html_command_tree (CONVERTER *self, ELEMENT *command, int no_number)
+HTMLXREF_MANUAL *
+find_htmlxref_manual
+ (const HTMLXREF_MANUAL_LIST *htmlxref_manuals, const char *manual)
{
- TREE_ADDED_ELEMENTS *tree;
- HTML_TARGET *target;
+ HTMLXREF_MANUAL *result = 0;
+ static HTMLXREF_MANUAL searched_manual;
+ /* remove const with a cast, it is more efficient than duplicating */
+ searched_manual.manual = (char *) manual;
- ELEMENT *manual_content = lookup_extra_element (command,
- "manual_content");
- if (manual_content)
+ result = (HTMLXREF_MANUAL *) bsearch (&searched_manual,
+ htmlxref_manuals->list,
+ htmlxref_manuals->number, sizeof(HTMLXREF_MANUAL),
+ compare_htmlxref_manual);
+
+ return result;
+}
+
+size_t
+check_htmlxref_already_warned (CONVERTER *self, const char *manual_name,
+ const ELEMENT *source_command)
+{
+ size_t i;
+ HTMLXREF_MANUAL_ELEMENT_WARNED *htmlxref_warned;
+ HTMLXREF_MANUAL_ELEMENT_WARNED_LIST *htmlxref_warned_list
+ = &self->check_htmlxref_already_warned;
+
+ for (i = 0; i < htmlxref_warned_list->number; i++)
{
- ELEMENT *root_code;
- ELEMENT *open_p;
- ELEMENT *close_p;
+ htmlxref_warned = &htmlxref_warned_list->list[i];
+ if (!strcmp (htmlxref_warned->manual, manual_name)
+ && source_command == htmlxref_warned->element)
+ return i+1;
+ }
- ELEMENT *node_content = lookup_extra_element (command,
- "node_content");
+ if (htmlxref_warned_list->number >= htmlxref_warned_list->space)
+ {
+ htmlxref_warned_list->list
+ = realloc (htmlxref_warned_list->list,
+ (htmlxref_warned_list->space += 5) * sizeof (HTMLXREF_MANUAL_ELEMENT_WARNED));
+ }
+ htmlxref_warned = &htmlxref_warned_list->list[htmlxref_warned_list->number];
- tree = new_tree_added_elements ();
+ htmlxref_warned->element = source_command;
+ htmlxref_warned->manual = strdup (manual_name);
- root_code = new_element_added (tree, ET__code);
- open_p = new_element_added (tree, ET_NONE);
- close_p = new_element_added (tree, ET_NONE);
+ htmlxref_warned_list->number++;
+ return 0;
+}
- text_append_n (&open_p->text, "(", 1);
- text_append_n (&close_p->text, ")", 1);
+char *
+external_node_href (CONVERTER *self, const ELEMENT *external_node,
+ const char *source_filename, /* unused */
+ const ELEMENT *source_command) /* for messages only */
+{
+ TEXT result;
+ char *target;
+ char *target_filebase;
+ /* used if !target_split */
+ char *file = 0;
+ /* used if target_split */
+ char *directory = 0;
+ char *extension = 0;
+ int target_split = 0;
+ char *normalized = lookup_extra_string (external_node, "normalized");
+ ELEMENT *node_contents = lookup_extra_element (external_node,
"node_content");
+ ELEMENT *manual_content = lookup_extra_element (external_node,
+ "manual_content");
- 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);
+ TARGET_FILENAME *target_filename =
+ normalized_label_id_file (self, normalized, node_contents);
- tree->tree = root_code;
- add_to_element_list (&self->tree_to_build, root_code);
- return tree;
- }
+ /* undef if conversion is called through convert() */
+ if (self->conf->EXTERNAL_CROSSREF_SPLIT
+ && strlen (self->conf->EXTERNAL_CROSSREF_SPLIT))
+ /* initialize to EXTERNAL_CROSSREF_SPLIT */
+ target_split = 1;
- target = get_target (self, command);
- if (target)
+ if (self->conf->EXTERNAL_CROSSREF_EXTENSION)
+ extension = self->conf->EXTERNAL_CROSSREF_EXTENSION;
+ else if (self->conf->EXTENSION)
+ extension = self->conf->EXTENSION;
+
+ /* both to be freed before return */
+ target = target_filename->target;
+ target_filebase = target_filename->filename;
+ free (target_filename);
+
+ if (manual_content)
{
- if (!target->tree.status)
+ char *manual_name;
+ char *manual_base = 0;
+ char *p;
+ char *q = 0;
+ char *htmlxref_href = 0;
+ char saved;
+ enum htmlxref_split_type split_found = htmlxref_split_type_none;
+ int manual_len;
+ HTMLXREF_MANUAL *htmlxref_manual;
+ TEXT_OPTIONS *text_conv_options = copy_options_for_convert_text (self,
0);
+ text_conv_options->code_state = 1;
+
+ manual_name = convert_to_text (manual_content, text_conv_options);
+
+ free (text_conv_options);
+
+ if (self->conf->IGNORE_REF_TO_TOP_NODE_UP && !strlen (target))
{
- tree = &target->tree;
- tree->status = tree_added_status_normal;
- if (command->type == ET_special_unit_element)
+ char *top_node_up = self->conf->TOP_NODE_UP;
+ if (top_node_up)
{
- const char *special_unit_variety
- = command->associated_unit->special_unit_variety;
- ELEMENT *heading_tree = special_unit_info_tree (self,
- SUIT_type_heading, special_unit_variety);
- tree->tree = heading_tree;
+ char *parentheses_manual_name;
+ xasprintf (&parentheses_manual_name, "(%s)", manual_name);
+ if (!strcmp (top_node_up, parentheses_manual_name))
+ {
+ free (parentheses_manual_name);
+ free (manual_name);
+ free (target);
+ free (target_filebase);
+ return strdup ("");
+ }
}
- else if (command->cmd == CM_node || command->cmd == CM_anchor)
+ }
+ p = strrchr (manual_name, '/');
+ if (!p)
+ p = manual_name;
+ manual_len = strlen (manual_name);
+ if (manual_len >= 5
+ && !memcmp (manual_name +manual_len - 5, ".info", 5))
+ q = manual_name +manual_len - 5;
+ else if (manual_len >= 4
+ && !memcmp (manual_name +manual_len - 4, ".inf", 4))
+ q = manual_name +manual_len - 4;
+ if (q)
+ {
+ saved = *q;
+ *q = '\0';
+ }
+ manual_base = strdup (p);
+ if (q)
+ *q = saved;
+
+ htmlxref_manual = find_htmlxref_manual (&self->htmlxref, manual_base);
+
+ if (htmlxref_manual)
+ {
+ enum htmlxref_split_type *ordered_split_types
+ = htmlxref_entries[self->document_htmlxref_split_type];
+ int i;
+ for (i = 0; i < htmlxref_split_type_chapter +1; i++)
{
- ELEMENT *root_code = new_element_added (tree, ET__code);
- add_to_contents_as_array (root_code, command->args.list[0]);
- tree->tree = root_code;
- add_to_element_list (&self->tree_to_build, tree->tree);
+ enum htmlxref_split_type split_ordered = ordered_split_types[i];
+ if (htmlxref_manual->urlprefix[split_ordered])
+ {
+ split_found = split_ordered;
+ htmlxref_href = url_protect_url_text (self,
+ htmlxref_manual->urlprefix[split_ordered]);
+ break;
+ }
}
- else if (command->cmd == CM_float)
+ }
+ if (split_found != htmlxref_split_type_none)
+ {
+ if (split_found == htmlxref_split_type_mono)
+ target_split = 0;
+ else
+ target_split = 1;
+ }
+ else
+ { /* nothing specified for that manual, use default */
+ if (self->conf->CHECK_HTMLXREF > 0)
{
- tree->tree = float_type_number (self, command);
- tree->status = tree_added_status_new_tree;
- add_to_element_list (&self->tree_to_build, tree->tree);
+ if ((source_command != 0) &&
+ (source_command->source_info.line_nr != 0))
+ { /* check if already set and set if not */
+ if (!check_htmlxref_already_warned (self, manual_name,
+ source_command))
+ {
+ message_list_command_warn (&self->error_messages,
+ source_command,
+ "no htmlxref.cnf entry found for `%s'",
+ manual_name);
+ }
+ }
+ else
+ {
+ if (!check_htmlxref_already_warned (self, manual_name, 0))
+ {
+ message_list_document_warn (&self->error_messages,
+ self->conf,
+ "no htmlxref.cnf entry found for `%s'", manual_name);
+ }
+ }
}
- else if (command->args.number <= 0
- || command->args.list[0]->contents.number <= 0)
- { /* no argument, nothing to do */
- /* TODO check if possible */
- tree->status = tree_added_status_no_tree;
+ }
+ free (manual_name);
+
+ if (target_split)
+ {
+ char *directory_part;
+ if (htmlxref_href)
+ {
+ directory_part = htmlxref_href;
}
else
{
- char *section_number
- = lookup_extra_string (command, "section_number");
- if (section_number && !self->conf->NUMBER_SECTIONS == 0)
+ TEXT dir_path;
+ char *url_encoded_path;
+ text_init (&dir_path);
+ if (self->conf->EXTERNAL_DIR)
{
- NAMED_STRING_ELEMENT_LIST *replaced_substrings
- = new_named_string_element_list ();
- ELEMENT *e_number = new_element (ET_NONE);
- ELEMENT *section_title_copy
- = copy_tree (command->args.list[0]);
-
- add_element_to_named_string_element_list (
- replaced_substrings, "section_title",
- section_title_copy);
- text_append (&e_number->text, section_number);
- add_element_to_named_string_element_list (
- replaced_substrings, "number", e_number);
-
- if (command->cmd == CM_appendix)
- {
- int status;
- int section_level = lookup_extra_integer (command,
- "section_level", &status);
- if (section_level == 1)
- {
- tree->tree
- = gdt_tree ("Appendix {number} {section_title}",
- self->document, self->conf,
- replaced_substrings, 0, 0);
- }
- }
- if (!tree->tree)
- /* TRANSLATORS: numbered section title */
- tree->tree = gdt_tree ("{number} {section_title}",
- self->document, self->conf,
- replaced_substrings, 0, 0);
+ text_printf (&dir_path, "%s/%s", self->conf->EXTERNAL_DIR,
+ manual_base);
+ }
+ else if (self->conf->SPLIT && strlen (self->conf->SPLIT))
+ {
+ text_append_n (&dir_path, "../", 3);
+ text_append (&dir_path, manual_base);
+ }
+ if (self->output_format && strlen (self->output_format))
+ {
+ text_append_n (&dir_path, "_", 1);
+ text_append (&dir_path, self->output_format);
+ }
+ url_encoded_path = url_protect_url_text (self, dir_path.text);
+ free (dir_path.text);
+ directory_part = url_encoded_path;
+ }
+ xasprintf (&directory, "%s/", directory_part);
+ free (directory_part);
+ }
+ else
+ { /* target not split */
+ if (htmlxref_href)
+ {
+ file = htmlxref_href;
+ }
+ else
+ {
+ TEXT file_path;
+ text_init (&file_path);
- destroy_named_string_element_list (replaced_substrings);
- tree->status = tree_added_status_new_tree;
- add_to_element_list (&self->tree_to_build, tree->tree);
+ if (self->conf->EXTERNAL_DIR)
+ {
+ text_printf (&file_path, "%s/%s", self->conf->EXTERNAL_DIR,
+ manual_base);
}
- else
+ else if (self->conf->SPLIT && strlen (self->conf->SPLIT))
{
- tree->status = tree_added_status_reused_tree;
- tree->tree = command->args.list[0];
+ text_append_n (&file_path, "../", 3);
+ text_append (&file_path, manual_base);
}
+ else
+ text_append (&file_path, manual_base);
+ if (extension)
+ text_printf (&file_path, ".%s", extension);
- target->tree_nonumber.tree = command->args.list[0];
- target->tree_nonumber.status = tree_added_status_reused_tree;
+ file = url_protect_url_text (self, file_path.text);
+ free (file_path.text);
}
}
-
- if (no_number && target->tree_nonumber.tree)
- return &target->tree_nonumber;
- else
- return &target->tree;
+ free (manual_base);
}
- return 0;
-}
-
-/* keep in sync with enum html_command_text_type */
-static char *html_command_text_type_name[] = {
- "text", "text_nonumber", "string", "string_nonumber"
-};
+ text_init (&result);
-char *
-html_command_text (CONVERTER *self, ELEMENT *command,
- const enum html_command_text_type type)
-{
- char *result;
- HTML_TARGET *target;
- ELEMENT *tree_root;
- ELEMENT *manual_content = lookup_extra_element (command,
- "manual_content");
- if (manual_content)
+ if (target_split)
{
- TREE_ADDED_ELEMENTS *command_tree = html_command_tree (self, command, 0);
- TREE_ADDED_ELEMENTS *string_tree = 0;
- if (type == HCTT_string)
- {
- ELEMENT *tree_root_string;
+ char *file_name = 0;
+ TARGET_DIRECTORY_FILENAME *target_dir_filename;
- string_tree = new_tree_added_elements ();
+ if ((!strcmp (target, "Top") || !strlen (target))
+ && self->conf->TOP_NODE_FILE_TARGET)
+ {
+ file_name = strdup (self->conf->TOP_NODE_FILE_TARGET);
+ }
+ else
+ {
+ if (extension)
+ xasprintf (&file_name, "%s.%s", target_filebase, extension);
+ else
+ file_name = strdup (target_filebase);
+ }
+ target_dir_filename
+ = call_file_id_setting_external_target_split_name (self,
+ normalized, external_node, target, directory, file_name);
+ if (target_dir_filename)
+ {
+ free (directory);
+ directory = target_dir_filename->directory;
+ free (file_name);
+ file_name = target_dir_filename->filename;
+ free (target);
+ target = target_dir_filename->target;
+ free (target_dir_filename);
+ }
+ text_append (&result, directory);
+ text_append (&result, file_name);
+ if (strlen (target))
+ {
+ text_append_n (&result, "#", 1);
+ text_append (&result, target);
+ }
- tree_root_string = new_element_added (string_tree, ET__string);
+ free (file_name);
+ free (directory);
+ }
+ else
+ {
+ TARGET_FILENAME *target_filename;
- add_to_element_contents (tree_root_string, command_tree->tree);
- tree_root = tree_root_string;
- add_to_element_list (&self->tree_to_build, tree_root);
+ if (!strlen (target))
+ {
+ free (target);
+ target = strdup ("Top");
}
- else
- tree_root = command_tree->tree;
- result = convert_tree_new_formatting_context (self, tree_root,
- element_command_name(command), 0,
- "command_text-manual_content", 0);
+ target_filename
+ = call_file_id_setting_external_target_non_split_name (self,
+ normalized, external_node, target, file);
- if (type == HCTT_string)
- destroy_tree_added_elements (self, string_tree);
- return result;
+ if (target_filename)
+ {
+ free (file);
+ file = target_filename->filename;
+ free (target);
+ target = target_filename->target;
+ free (target_filename);
+ }
+ text_append (&result, file);
+ if (strlen (target))
+ {
+ text_append_n (&result, "#", 1);
+ text_append (&result, target);
+ }
+
+ free (file);
}
- target = get_target (self, command);
- if (target)
+ free (target);
+ free (target_filebase);
+ return result.text;
+}
+
+FILE_NUMBER_NAME *
+html_command_filename (CONVERTER *self, const ELEMENT *command)
+{
+ HTML_TARGET *target_info;
+
+ target_info = get_target (self, command);
+
+ if (target_info)
{
- if (target->command_text[type])
- return target->command_text[type];
- else
+ ROOT_AND_UNIT *root_unit;
+
+ if (target_info->filename_set)
+ return &target_info->file_number_name;
+
+ /* this finds a special element for footnote command if such an element
+ exists. This is best, the special element filename is the footnote
+ filename. */
+
+ root_unit
+ = html_get_tree_root_element (self, command, 1);
+
+ if (root_unit && root_unit->output_unit
+ && root_unit->output_unit->unit_filename)
{
- 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);
+ size_t file_index
+ = self->output_unit_file_indices[root_unit->output_unit->index];
+ target_info->file_number_name.file_number
+ = file_index +1;
+ target_info->file_number_name.filename
+ = root_unit->output_unit->unit_filename;
+ }
+ target_info->filename_set = 1;
- if (!command_tree->tree)
- return 0;
+ free (root_unit);
- if (command->cmd)
+ return &target_info->file_number_name;
+ }
+
+ return 0;
+}
+
+ELEMENT *
+command_root_element_command (CONVERTER *self, const ELEMENT *command)
+{
+ HTML_TARGET *target_info;
+
+ target_info = get_target (self, command);
+ if (target_info)
+ {
+ if (!target_info->root_element_command_set)
+ {
+ /* in contrast with command_filename() we find the root element through
+ the location holding the @footnote command. It is better, as the
+ footnote special element is not associated with a root command,
+ it is better to stay in the document to find a root element. */
+ ROOT_AND_UNIT *root_unit
+ = html_get_tree_root_element (self, command, 0);
+
+ if (root_unit && root_unit->output_unit
+ && root_unit->output_unit->unit_type == OU_unit)
{
- char *command_name = element_command_name(command);
- context_name = command_name;
- xasprintf (&explanation, "command_text:%s @%s",
- html_command_text_type_name[type],
- command_name);
+ target_info->root_element_command
+ = root_unit->output_unit->unit_command;
}
else
- {
- context_name = element_type_names[command->type];
- if (command->type == ET_special_unit_element)
- {
- char *special_unit_variety
- = command->associated_unit->special_unit_variety;
- xasprintf (&explanation, "command_text %s",
- special_unit_variety);
- }
- }
- html_new_document_context (self, context_name, explanation, 0);
+ target_info->root_element_command = 0;
- if ((type == HCTT_text_nonumber || type == HCTT_string_nonumber)
- && target->tree_nonumber.tree)
- selected_tree = target->tree_nonumber.tree;
- else
- selected_tree = command_tree->tree;
+ target_info->root_element_command_set = 1;
- if (type == HCTT_string)
- {
- ELEMENT *tree_root_string;
+ free (root_unit);
- string_tree = new_tree_added_elements ();
+ return target_info->root_element_command;
+ }
+ }
+ return 0;
+}
- tree_root_string = new_element_added (string_tree, ET__string);
+/* Return string for linking to $COMMAND with <a href> */
+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
*/
+{
+ 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;
- add_to_element_contents (tree_root_string, selected_tree);
- tree_root = tree_root_string;
- add_to_element_list (&self->tree_to_build, tree_root);
- }
- else
- tree_root = selected_tree;
+ if (manual_content)
+ {
+ return external_node_href (self, command, filename_from,
+ source_command);
+ }
- self->ignore_notice++;
- add_to_element_list (&self->referred_command_stack, command);
- self->modified_state |= HMSF_referred_command_stack
- | HMSF_converter_state;
- target->command_text[type]
- = html_convert_tree (self, tree_root, explanation);
- free (explanation);
- remove_from_element_list (&self->referred_command_stack, -1);
- self->ignore_notice--;
- self->modified_state |= HMSF_referred_command_stack
- | HMSF_converter_state;
+ if (specified_target)
+ target = specified_target;
+ else
+ {
+ const ELEMENT *target_command = command;
+ /* for sectioning command prefer the associated node */
+ const ELEMENT *associated_node = lookup_extra_element (command,
+ "associated_node");
+ if (associated_node)
+ target_command = associated_node;
+ target_info = get_target (self, target_command);
+ if (target_info)
+ target = target_info->target;
+ }
+ if (!target)
+ return strdup ("");
- html_pop_document_context (self);
+ text_init (&href);
+ text_append (&href, "");
+
+ target_filename = html_command_filename (self, command);
+ if (!target_filename)
+ {
+ /* Happens if there are no pages, for example if OUTPUT is set to ''
+ as in the test cases. Also for things in @titlepage when
+ titlepage is not output. */
+ const OUTPUT_UNIT_LIST *output_units
+ = retrieve_output_units (self->document_units_descriptor);
+ if (output_units && output_units->number > 0
+ && output_units->list[0]->unit_filename)
+ { /* In that case use the first page. */
+ target_filename = (FILE_NUMBER_NAME *)
+ malloc (sizeof (FILE_NUMBER_NAME));
+ target_filename->filename = output_units->list[0]->unit_filename;
+ target_filename->file_number
+ = self->output_unit_file_indices[0] +1;
+ target_filename_to_be_freed = 1;
+ }
+ }
- if (type == HCTT_string)
+ if (target_filename && target_filename->filename)
+ {
+ if (!filename_from
+ || strcmp (target_filename->filename, filename_from))
+ {
+ ELEMENT *command_root_element
+ = command_root_element_command (self, command);
+ text_append (&href, target_filename->filename);
+ /* omit target if the command is an element command, there is only
+ one element in file and there is a file in the href */
+ if (filename_from && command_root_element)
{
- destroy_tree_added_elements (self, string_tree);
+ ELEMENT *associated_section
+ = lookup_extra_element (command_root_element,
+ "associated_section");
+ if (command_root_element == command
+ || (associated_section
+ && associated_section == command))
+ {
+ if (target_filename->file_number > 0)
+ {
+ size_t count_in_file
+ = count_elements_in_filename (self, CEFT_total,
+
target_filename->file_number);
+ if (count_in_file == 1)
+ target = "";
+ }
+ }
}
- return target->command_text[type];
}
}
- /*
- Can happen
- * if USE_NODES is 0 and there are no sectioning commands.
- * if a special element target was set to undef in user defined code.
- * for @*ref with missing targets (maybe @novalidate needed in that case).
- * for @node header if the node consist only in spaces (example in
sectioning
- in_menu_only_special_ascii_spaces_node).
- * for multiple targets with the same name, eg both @node and @anchor
- * with @inforef with node argument only, without manual argument.
- */
+ if (strlen (target))
+ {
+ text_append_n (&href, "#", 1);
+ text_append (&href, target);
+ }
- return 0;
+ if (target_filename_to_be_freed)
+ free (target_filename);
+
+ return href.text;
}
-static int
-compare_page_name_number (const void *a, const void *b)
+char *
+html_command_contents_target (CONVERTER *self, const ELEMENT *command,
+ enum command_id contents_or_shortcontents)
{
- const PAGE_NAME_NUMBER *pnn_a = (const PAGE_NAME_NUMBER *) a;
- const PAGE_NAME_NUMBER *pnn_b = (const PAGE_NAME_NUMBER *) b;
+ HTML_TARGET *target_info;
- return strcmp (pnn_a->page_name, pnn_b->page_name);
+ if (contents_or_shortcontents == CM_summarycontents)
+ contents_or_shortcontents = CM_shortcontents;
+
+ target_info = get_target (self, command);
+ if (target_info)
+ {
+ if (contents_or_shortcontents == CM_summarycontents)
+ return target_info->shortcontents_target;
+ else if (contents_or_shortcontents == CM_contents)
+ return target_info->contents_target;
+ }
+ return 0;
}
-size_t
-find_page_name_number
- (const PAGE_NAME_NUMBER_LIST *page_name_number,
- const char *page_name)
+/* Return string for linking to CONTENTS_OR_SHORTCONTENTS associated
+ element from $COMMAND with <a href> */
+char *
+html_command_contents_href (CONVERTER *self, const ELEMENT *command,
+ enum command_id contents_or_shortcontents,
+ const char *source_filename)
{
- PAGE_NAME_NUMBER *result = 0;
- static PAGE_NAME_NUMBER searched_page_name;
- searched_page_name.page_name = page_name;
+ int j;
+ const char *filename_from;
+ char *target = html_command_contents_target (self, command,
+ contents_or_shortcontents);
- result = (PAGE_NAME_NUMBER *) bsearch (&searched_page_name,
- page_name_number->list,
- page_name_number->number, sizeof(PAGE_NAME_NUMBER),
- compare_page_name_number);
- return result->number;
+ if (source_filename)
+ filename_from = source_filename;
+ else
+ filename_from = self->current_filename.filename;
+
+ for (j = 0; self->command_special_variety_name_index[j].cmd; j++)
+ {
+ COMMAND_ID_INDEX cmd_variety_index
+ = self->command_special_variety_name_index[j];
+ if (cmd_variety_index.cmd == contents_or_shortcontents)
+ {
+ TEXT href;
+ FILE_NUMBER_NAME *target_filename = 0;
+ char *special_unit_variety
+ = self->special_unit_varieties.list[cmd_variety_index.index];
+ int special_unit_direction_index
+ = special_unit_variety_direction_index (self,
+ special_unit_variety);
+ const OUTPUT_UNIT *special_unit
+ = self->global_units_directions[special_unit_direction_index];
+ if (special_unit)
+ {
+ target_filename = html_command_filename (self,
+ special_unit->unit_command);
+ }
+
+ text_init (&href);
+ text_append (&href, "");
+
+ if (target_filename
+ && (!filename_from
+ || strcmp (target_filename->filename, filename_from)))
+ text_append (&href, target_filename->filename);
+
+ if (target && strlen (target))
+ {
+ text_append_n (&href, "#", 1);
+ text_append (&href, target);
+ }
+
+ return href.text;
+ }
+ }
+ return 0;
}
-static int
-compare_selector_style (const void *a, const void *b)
+int *
+get_shared_conversion_state_integer (CONVERTER *self, char *key,
+ int value)
{
- const CSS_SELECTOR_STYLE *css_a = (const CSS_SELECTOR_STYLE *) a;
- const CSS_SELECTOR_STYLE *css_b = (const CSS_SELECTOR_STYLE *) b;
+ KEY_PAIR *k
+ = lookup_associated_info (&self->shared_conversion_state.integers, key);
- return strcmp (css_a->selector, css_b->selector);
+ if (!k)
+ {
+ add_associated_info_integer (&self->shared_conversion_state.integers,
+ key, value);
+ k = lookup_associated_info (&self->shared_conversion_state.integers,
key);
+ }
+ return &k->integer;
}
-CSS_SELECTOR_STYLE *
-find_css_selector_style
- (const CSS_SELECTOR_STYLE_LIST *css_element_class_styles,
- const char *selector)
+static void
+register_modified_shared_conversion_state_integer (CONVERTER *self,
+ const char *key)
{
- CSS_SELECTOR_STYLE *result = 0;
- static CSS_SELECTOR_STYLE searched_selector;
- /* remove const with a cast, it is more efficient than duplicating */
- searched_selector.selector = (char *) selector;
-
- result = (CSS_SELECTOR_STYLE *) bsearch (&searched_selector,
- css_element_class_styles->list,
- css_element_class_styles->number, sizeof(CSS_SELECTOR_STYLE),
- compare_selector_style);
+ self->modified_state |= HMSF_shared_conversion_state_integer;
+ if (!find_string (&self->shared_conversion_state_integer, key))
+ add_string (key, &self->shared_conversion_state_integer);
+}
- return result;
+ELEMENT *
+new_element_added (TREE_ADDED_ELEMENTS *added_elements, enum element_type type)
+{
+ ELEMENT *new = new_element (type);
+ add_to_element_list (&added_elements->added, new);
+ return new;
}
-static void
-collect_css_element_class (CONVERTER *self, const char *selector)
+TREE_ADDED_ELEMENTS *
+html_command_tree (CONVERTER *self, const ELEMENT *command, int no_number)
{
- CSS_SELECTOR_STYLE *selector_style
- = find_css_selector_style (&self->css_element_class_styles, selector);
- if (selector_style)
+ TREE_ADDED_ELEMENTS *tree;
+ HTML_TARGET *target_info;
+
+ ELEMENT *manual_content = lookup_extra_element (command,
+ "manual_content");
+ if (manual_content)
{
- size_t i;
- size_t css_files_index;
- CSS_LIST *page_css_list;
- if (self->document_global_context)
- {
- css_files_index = 0;
- }
- else
- {
- css_files_index = self->current_filename.file_number;
- }
- page_css_list = &self->page_css.list[css_files_index];
- for (i = 0; i < page_css_list->number; i++)
- {
- if (!strcmp (page_css_list->list[i], selector))
- return;
- }
- if (page_css_list->number == page_css_list->space)
- {
- page_css_list->list
- = realloc (page_css_list->list,
- (page_css_list->space += 5) * sizeof (char *));
- }
- page_css_list->list[page_css_list->number] = strdup (selector);
- page_css_list->number++;
- }
-}
-
-int
-compare_strings (const void *a, const void *b)
-{
- const char **str_a = (const char **) a;
- const char **str_b = (const char **) b;
+ ELEMENT *root_code;
+ ELEMENT *open_p;
+ ELEMENT *close_p;
- return strcmp (*str_a, *str_b);
-}
+ ELEMENT *node_content = lookup_extra_element (command,
+ "node_content");
-STRING_LIST *
-html_get_css_elements_classes (CONVERTER *self, const char *filename)
-{
- int j;
- size_t page_number;
- STRING_LIST *result;
- const char **selectors;
- size_t selector_nr = 0;
+ tree = new_tree_added_elements ();
- if (self->page_css.number <= 0)
- return 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);
- CSS_LIST *global_context_css_list = &self->page_css.list[0];
+ text_append_n (&open_p->text, "(", 1);
+ text_append_n (&close_p->text, ")", 1);
- if (filename)
- {
- CSS_LIST *css_list;
- page_number = find_page_name_number (&self->page_name_number,
- filename);
- if (!page_number)
- fatal ("Could not find page number of file name");
+ 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);
- css_list = &self->page_css.list[page_number];
- if (css_list->number)
- {
- /* +1 for 'span:hover a.copiable-link' */
- size_t space = css_list->number + global_context_css_list->number +1;
- selectors = (const char **) malloc (sizeof (char *) * space);
- memcpy (selectors, css_list->list,
- css_list->number * sizeof (char *));
- selector_nr = css_list->number;
- }
+ tree->tree = root_code;
+ add_to_element_list (&self->tree_to_build, root_code);
+ return tree;
}
- if (selector_nr <= 0)
- {
- if (global_context_css_list->number)
- {
- /* +1 for 'span:hover a.copiable-link' */
- size_t space = global_context_css_list->number +1;
- selectors = (const char **) malloc (sizeof (char *) * space);
- selector_nr = global_context_css_list->number;
- }
- else
- return 0;
- }
- else if (global_context_css_list->number)
+ target_info = get_target (self, command);
+ if (target_info)
{
- int i;
- size_t file_selector_nr = selector_nr;
- /* add global context selectors if not already present */
- for (i = 0; i < global_context_css_list->number; i++)
+ if (!target_info->tree.status)
{
- int j;
- const char *global_selector = global_context_css_list->list[i];
- int found = 0;
- for (j = 0; j < file_selector_nr; j++)
+ tree = &target_info->tree;
+ tree->status = tree_added_status_normal;
+ if (command->type == ET_special_unit_element)
{
- if (!strcmp (global_selector, selectors[j]))
- {
- found = 1;
- break;
- }
+ const char *special_unit_variety
+ = command->associated_unit->special_unit_variety;
+ ELEMENT *heading_tree = special_unit_info_tree (self,
+ SUIT_type_heading, special_unit_variety);
+ tree->tree = heading_tree;
}
- if (!found)
+ else if (command->cmd == CM_node || command->cmd == CM_anchor)
{
- selectors[selector_nr] = global_selector;
- selector_nr++;
+ ELEMENT *root_code = new_element_added (tree, ET__code);
+ add_to_contents_as_array (root_code, command->args.list[0]);
+ tree->tree = root_code;
+ add_to_element_list (&self->tree_to_build, tree->tree);
}
- }
- }
- for (j = 0; j < selector_nr; j++)
- {
- if (!strcmp ("a.copiable-link", selectors[j]))
- {
- selectors[selector_nr] = "span:hover a.copiable-link";
- selector_nr++;
- break;
- }
- }
-
- qsort (selectors, selector_nr, sizeof (char *), compare_strings);
+ else if (command->cmd == CM_float)
+ {
+ tree->tree = float_type_number (self, command);
+ tree->status = tree_added_status_new_tree;
+ add_to_element_list (&self->tree_to_build, tree->tree);
+ }
+ else if (command->args.number <= 0
+ || command->args.list[0]->contents.number <= 0)
+ { /* no argument, nothing to do */
+ /* TODO check if possible */
+ tree->status = tree_added_status_no_tree;
+ }
+ else
+ {
+ char *section_number
+ = lookup_extra_string (command, "section_number");
+ if (section_number && !self->conf->NUMBER_SECTIONS == 0)
+ {
+ NAMED_STRING_ELEMENT_LIST *replaced_substrings
+ = new_named_string_element_list ();
+ ELEMENT *e_number = new_element (ET_NONE);
+ ELEMENT *section_title_copy
+ = copy_tree (command->args.list[0]);
- result = (STRING_LIST *) malloc (sizeof (STRING_LIST));
- memset (result, 0, sizeof (STRING_LIST));
- for (j = 0; j < selector_nr; j++)
- add_string (selectors[j], result);
+ add_element_to_named_string_element_list (
+ replaced_substrings, "section_title",
+ section_title_copy);
+ text_append (&e_number->text, section_number);
+ add_element_to_named_string_element_list (
+ replaced_substrings, "number", e_number);
- free (selectors);
+ if (command->cmd == CM_appendix)
+ {
+ int status;
+ int section_level = lookup_extra_integer (command,
+ "section_level", &status);
+ if (section_level == 1)
+ {
+ tree->tree
+ = gdt_tree ("Appendix {number} {section_title}",
+ self->document, self->conf,
+ replaced_substrings, 0, 0);
+ }
+ }
+ if (!tree->tree)
+ /* TRANSLATORS: numbered section title */
+ tree->tree = gdt_tree ("{number} {section_title}",
+ self->document, self->conf,
+ replaced_substrings, 0, 0);
- return result;
-}
+ destroy_named_string_element_list (replaced_substrings);
+ tree->status = tree_added_status_new_tree;
+ add_to_element_list (&self->tree_to_build, tree->tree);
+ }
+ else
+ {
+ tree->status = tree_added_status_reused_tree;
+ tree->tree = command->args.list[0];
+ }
-static char *
-protect_class_name (const char *class_name)
-{
- TEXT result;
- TEXT space_protected;
- text_init (&result);
- text_init (&space_protected);
- const char *p = class_name;
- while (*p)
- {
- int n = strcspn (p, " ");
- if (n)
- {
- text_append_n (&space_protected, p, n);
- p += n;
- }
- if (*p)
- {
- int n = strspn (p, " ");
- if (n)
- {
- int i;
- for (i = 0; i < n; i++)
- text_append_n (&space_protected, "-", 1);
- p += n;
+ target_info->tree_nonumber.tree = command->args.list[0];
+ target_info->tree_nonumber.status =
tree_added_status_reused_tree;
}
}
+
+ if (no_number && target_info->tree_nonumber.tree)
+ return &target_info->tree_nonumber;
+ else
+ return &target_info->tree;
}
- /* do not use the customization API as in perl */
- html_default_format_protect_text (space_protected.text, &result);
- free (space_protected.text);
- return result.text;
+ return 0;
}
+/* keep in sync with enum html_command_text_type */
+static char *html_command_text_type_name[] = {
+ "text", "text_nonumber", "string", "string_nonumber"
+};
+
+/* cached, not to be freed */
char *
-html_attribute_class (CONVERTER *self, const char *element,
- const STRING_LIST *classes)
+html_command_text (CONVERTER *self, const ELEMENT *command,
+ const enum html_command_text_type type)
{
- TEXT result;
- char *style = 0;
- int i;
- int class_nr = 0;
- if (!classes || classes->number <= 0
- || self->conf->NO_CSS > 0)
+ char *result;
+ HTML_TARGET *target_info;
+ ELEMENT *tree_root;
+ ELEMENT *manual_content = lookup_extra_element (command,
+ "manual_content");
+ if (manual_content)
{
- if (!strcmp (element, "span"))
- return strdup ("");
- else
+ TREE_ADDED_ELEMENTS *command_tree = html_command_tree (self, command, 0);
+ TREE_ADDED_ELEMENTS *string_tree = 0;
+ if (type == HCTT_string)
{
- char *result;
- xasprintf (&result, "<%s", element);
- return result;
- }
- }
+ ELEMENT *tree_root_string;
- if (self->conf->INLINE_CSS_STYLE > 0)
- {
- int i;
- TEXT inline_styles;
- text_init (&inline_styles);
- int style_nr = 0;
- for (i = 0; i < classes->number; i++)
- {
- const char *style_class = classes->list[i];
- char *selector;
- CSS_SELECTOR_STYLE *selector_style;
+ string_tree = new_tree_added_elements ();
- xasprintf (&selector, "%s.%s", element, style_class);
- selector_style
- = find_css_selector_style (&self->css_element_class_styles,
- selector);
- free (selector);
- if (selector_style)
- {
- if (style_nr)
- text_printf (&inline_styles, ";%s", selector_style->style);
- else
- text_append (&inline_styles, selector_style->style);
- style_nr++;
- }
- }
- if (inline_styles.end)
- {
- xasprintf (&style, " style=\"%s\"", inline_styles.text);
- }
- free (inline_styles.text);
- }
- else
- {
- int i;
- for (i = 0; i < classes->number; i++)
- {
- const char *style_class = classes->list[i];
- char *selector;
+ tree_root_string = new_element_added (string_tree, ET__string);
- xasprintf (&selector, "%s.%s", element, style_class);
- collect_css_element_class (self, selector);
- free (selector);
+ add_to_element_contents (tree_root_string, command_tree->tree);
+ tree_root = tree_root_string;
+ add_to_element_list (&self->tree_to_build, tree_root);
}
- }
- text_init (&result);
- text_printf (&result, "<%s class=\"", element);
- for (i = 0; i < classes->number; i++)
- {
- const char *class_name = classes->list[i];
- char *protected_class = protect_class_name (class_name);
- if (class_nr)
- text_printf (&result, " %s", protected_class);
else
- text_append (&result, protected_class);
- free (protected_class);
- class_nr++;
- }
- text_append_n (&result, "\"", 1);
- if (style)
- {
- text_append (&result, style);
- free (style);
- }
- return result.text;
-}
-
-void
-html_merge_index_entries (CONVERTER *self)
-{
- if (self->document->index_names)
- {
- INDEX **index_names = self->document->index_names;
- MERGED_INDEX *merged_index_entries = merge_indices (index_names);
- self->index_entries = merged_index_entries;
- }
-}
+ tree_root = command_tree->tree;
-int
-compare_index_name (const void *a, const void *b)
-{
- const INDEX **idx_a = (const INDEX **) a;
- const INDEX **idx_b = (const INDEX **) b;
+ result = convert_tree_new_formatting_context (self, tree_root,
+ element_command_name(command),
+ "command_text-manual_content", 0, 0);
- return strcmp ((*idx_a)->name, (*idx_b)->name);
-}
+ if (type == HCTT_string)
+ destroy_tree_added_elements (self, string_tree);
+ return result;
+ }
-void
-prepare_index_entries_targets (CONVERTER *self)
-{
- if (self->document->index_names)
+ target_info = get_target (self, command);
+ if (target_info)
{
- INDEX **i, *idx;
- INDEX **index_names = self->document->index_names;
- INDEX **sorted_index_names;
- int index_nr = 0;
-
- /* TODO sort indices by name before? when registering in document?
- In parser?
- Depending on size? And use bsearch in some places?
- */
- for (i = index_names; (idx = *i); i++)
- index_nr++;
-
- sorted_index_names = (INDEX **) malloc ((index_nr+1) * sizeof (INDEX *));
+ if (target_info->command_text[type])
+ return strdup (target_info->command_text[type]);
+ else
+ {
+ 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);
- memcpy (sorted_index_names, index_names, (index_nr+1) * sizeof (INDEX
*));
- qsort (sorted_index_names, index_nr, sizeof (INDEX *),
- compare_index_name);
+ if (!command_tree->tree)
+ return 0;
- for (i = sorted_index_names; (idx = *i); i++)
- {
- if (idx->entries_number > 0)
+ if (command->cmd)
{
- int j;
- for (j = 0; j < idx->entries_number; j++)
+ char *command_name = element_command_name(command);
+ context_name = command_name;
+ xasprintf (&explanation, "command_text:%s @%s",
+ html_command_text_type_name[type],
+ command_name);
+ }
+ else
+ {
+ context_name = element_type_names[command->type];
+ if (command->type == ET_special_unit_element)
{
- INDEX_ENTRY *index_entry;
- const ELEMENT *main_entry_element;
- const ELEMENT *seeentry;
- const ELEMENT *seealso;
- ELEMENT *entry_reference_content_element;
- ELEMENT *normalize_index_element;
- ELEMENT_LIST *subentries_tree;
- const ELEMENT *target_element;
- TEXT target_base;
- char *normalized_index;
- char *region = 0;
- char *target;
+ char *special_unit_variety
+ = command->associated_unit->special_unit_variety;
+ xasprintf (&explanation, "command_text %s",
+ special_unit_variety);
+ }
+ }
+ html_new_document_context (self, context_name, explanation, 0);
- index_entry = &idx->index_entries[j];
- main_entry_element = index_entry->entry_element;
- seeentry = lookup_extra_element (main_entry_element,
- "seeentry");
- if (seeentry)
- continue;
- seealso = lookup_extra_element (main_entry_element,
- "seealso");
- if (seealso)
- continue;
+ if ((type == HCTT_text_nonumber || type == HCTT_string_nonumber)
+ && target_info->tree_nonumber.tree)
+ selected_tree = target_info->tree_nonumber.tree;
+ else
+ selected_tree = command_tree->tree;
- region = lookup_extra_string (main_entry_element,
- "element_region");
- entry_reference_content_element
- = index_content_element (main_entry_element, 1);
- /* construct element to convert to a normalized identifier to use as
- hrefs target */
- normalize_index_element = new_element (ET_NONE);
- add_to_element_contents (normalize_index_element,
- entry_reference_content_element);
+ if (type == HCTT_string)
+ {
+ ELEMENT *tree_root_string;
- subentries_tree
- = comma_index_subentries_tree (main_entry_element, " ");
- if (subentries_tree)
- {
- insert_list_slice_into_contents (normalize_index_element,
-
normalize_index_element->contents.number,
- subentries_tree, 0,
- subentries_tree->number);
- }
- normalized_index
- = normalize_transliterate_texinfo (normalize_index_element,
- (self->conf->TEST > 0));
+ string_tree = new_tree_added_elements ();
- destroy_element (normalize_index_element);
- if (subentries_tree)
- free_comma_index_subentries_tree (subentries_tree);
+ tree_root_string = new_element_added (string_tree, ET__string);
- text_init (&target_base);
- text_append (&target_base, "index-");
- if (region)
- {
- text_append (&target_base, region);
- text_append (&target_base, "-");
- }
- text_append (&target_base, normalized_index);
- free (normalized_index);
- target = unique_target (self, target_base.text);
- free (target_base.text);
- if (index_entry->entry_associated_element)
- target_element = index_entry->entry_associated_element;
- else
- target_element = main_entry_element;
+ add_to_element_contents (tree_root_string, selected_tree);
+ tree_root = tree_root_string;
+ add_to_element_list (&self->tree_to_build, tree_root);
+ }
+ else
+ tree_root = selected_tree;
- add_element_target (self, target_element, target);
- add_string (target, &self->seen_ids);
+ self->ignore_notice++;
+ push_stack_element (&self->referred_command_stack, command);
+ self->modified_state |= HMSF_referred_command_stack
+ | HMSF_converter_state;
+ target_info->command_text[type]
+ = html_convert_tree (self, tree_root, explanation);
+ free (explanation);
+ pop_stack_element (&self->referred_command_stack);
+ self->ignore_notice--;
+ self->modified_state |= HMSF_referred_command_stack
+ | HMSF_converter_state;
- free (target);
- }
+ html_pop_document_context (self);
+
+ if (type == HCTT_string)
+ {
+ destroy_tree_added_elements (self, string_tree);
}
+ return strdup (target_info->command_text[type]);
}
- free (sorted_index_names);
}
-}
-static const char *footid_base = "FOOT";
-static const char *docid_base = "DOCF";
+ /*
+ Can happen
+ * if USE_NODES is 0 and there are no sectioning commands.
+ * if a special element target was set to undef in user defined code.
+ * for @*ref with missing targets (maybe @novalidate needed in that case).
+ * for @node header if the node consist only in spaces (example in
sectioning
+ in_menu_only_special_ascii_spaces_node).
+ * for multiple targets with the same name, eg both @node and @anchor
+ * with @inforef with node argument only, without manual argument.
+ */
-static void
-prepare_footnotes_targets (CONVERTER *self)
-{
- const ELEMENT_LIST *global_footnotes =
&self->document->global_commands->footnotes;
- if (global_footnotes->number > 0)
- {
- int i;
- for (i = 0; i < global_footnotes->number; i++)
- {
- const ELEMENT *footnote = global_footnotes->list[i];
- TEXT footid;
- TEXT docid;
- int nr = i+1;
+ return 0;
+}
- text_init (&footid);
- text_init (&docid);
- text_printf (&footid, "%s%d", footid_base, nr);
- text_printf (&docid, "%s%d", docid_base, nr);
+static int
+compare_page_name_number (const void *a, const void *b)
+{
+ const PAGE_NAME_NUMBER *pnn_a = (const PAGE_NAME_NUMBER *) a;
+ const PAGE_NAME_NUMBER *pnn_b = (const PAGE_NAME_NUMBER *) b;
- while (1)
- {
- int j;
- int non_unique = 0;
- for (j = 0; j < self->seen_ids.number; j++)
- {
- if (!strcmp (footid.text, self->seen_ids.list[j])
- || !strcmp (docid.text, self->seen_ids.list[j]))
- {
- non_unique = 1;
- break;
- }
- }
- if (non_unique)
- {
- nr++;
- if (nr == 0)
- fatal ("overflow footnote target nr");
+ return strcmp (pnn_a->page_name, pnn_b->page_name);
+}
- text_init (&footid);
- text_init (&docid);
- text_printf (&footid, "%s%d", footid_base, nr);
- text_printf (&docid, "%s%d", docid_base, nr);
- }
- else
- break;
- }
- add_string (footid.text, &self->seen_ids);
- add_string (docid.text, &self->seen_ids);
- add_element_target (self, footnote, footid.text);
- add_special_target (self, ST_footnote_location, footnote,
- docid.text);
+size_t
+find_page_name_number
+ (const PAGE_NAME_NUMBER_LIST *page_name_number,
+ const char *page_name)
+{
+ PAGE_NAME_NUMBER *result = 0;
+ static PAGE_NAME_NUMBER searched_page_name;
+ searched_page_name.page_name = page_name;
- if (self->conf->DEBUG > 0)
- {
- char *footnote_txi = convert_to_texinfo (footnote);
- fprintf (stderr, "Enter footnote: target %s, nr %d\n%s\n",
- footid.text, nr, footnote_txi);
- free (footnote_txi);
- }
- free (footid.text);
- free (docid.text);
- }
- }
+ result = (PAGE_NAME_NUMBER *) bsearch (&searched_page_name,
+ page_name_number->list,
+ page_name_number->number, sizeof(PAGE_NAME_NUMBER),
+ compare_page_name_number);
+ return result->number;
}
-/* for conversion units except for associated special units that require
- files for document units to be set */
-void
-html_prepare_conversion_units_targets (CONVERTER *self,
- const char *document_name,
- int output_units_descriptor,
- int special_units_descriptor,
- int associated_special_units_descriptor)
+static int
+compare_selector_style (const void *a, const void *b)
{
- /*
- Do that before the other elements, to be sure that special page ids
- are registered before elements id are.
- */
- set_special_units_targets_files (self, special_units_descriptor,
- document_name);
+ const CSS_SELECTOR_STYLE *css_a = (const CSS_SELECTOR_STYLE *) a;
+ const CSS_SELECTOR_STYLE *css_b = (const CSS_SELECTOR_STYLE *) b;
- prepare_associated_special_units_targets (self,
- associated_special_units_descriptor);
+ return strcmp (css_a->selector, css_b->selector);
+}
- set_root_commands_targets_node_files (self);
+CSS_SELECTOR_STYLE *
+find_css_selector_style
+ (const CSS_SELECTOR_STYLE_LIST *css_element_class_styles,
+ const char *selector)
+{
+ CSS_SELECTOR_STYLE *result = 0;
+ static CSS_SELECTOR_STYLE searched_selector;
+ /* remove const with a cast, it is more efficient than duplicating */
+ searched_selector.selector = (char *) selector;
- prepare_index_entries_targets (self);
- prepare_footnotes_targets (self);
+ result = (CSS_SELECTOR_STYLE *) bsearch (&searched_selector,
+ css_element_class_styles->list,
+ css_element_class_styles->number, sizeof(CSS_SELECTOR_STYLE),
+ compare_selector_style);
+
+ return result;
}
-/* Associate output units to the global targets, First, Last, Top, Index.
- and special output units */
-void
-html_prepare_output_units_global_targets (CONVERTER *self,
- int output_units_descriptor,
- int special_units_descriptor,
- int
associated_special_units_descriptor)
+static void
+collect_css_element_class (CONVERTER *self, const char *selector)
{
- int i;
- int all_special_units_nr = 0;
- int s;
- const OUTPUT_UNIT_LIST *output_units
- = retrieve_output_units (output_units_descriptor);
+ CSS_SELECTOR_STYLE *selector_style
+ = find_css_selector_style (&self->css_element_class_styles, selector);
+ if (selector_style)
+ {
+ size_t i;
+ size_t css_files_index;
+ CSS_LIST *page_css_list;
+ if (self->document_global_context)
+ {
+ css_files_index = 0;
+ }
+ else
+ {
+ css_files_index = self->current_filename.file_number;
+ }
+ page_css_list = &self->page_css.list[css_files_index];
+ for (i = 0; i < page_css_list->number; i++)
+ {
+ if (!strcmp (page_css_list->list[i], selector))
+ return;
+ }
+ if (page_css_list->number == page_css_list->space)
+ {
+ page_css_list->list
+ = realloc (page_css_list->list,
+ (page_css_list->space += 5) * sizeof (char *));
+ }
+ page_css_list->list[page_css_list->number] = strdup (selector);
+ page_css_list->number++;
+ }
+}
- const OUTPUT_UNIT *top_output_unit = get_top_unit (self->document,
- output_units);
+int
+compare_strings (const void *a, const void *b)
+{
+ const char **str_a = (const char **) a;
+ const char **str_b = (const char **) b;
- int special_output_units_lists[2] = {special_units_descriptor,
- associated_special_units_descriptor};
+ return strcmp (*str_a, *str_b);
+}
- self->global_units_directions[D_First] = output_units->list[0];
- self->global_units_directions[D_Last]
- = output_units->list[output_units->number - 1];
+STRING_LIST *
+html_get_css_elements_classes (CONVERTER *self, const char *filename)
+{
+ int j;
+ size_t page_number;
+ STRING_LIST *result;
+ const char **selectors;
+ size_t selector_nr = 0;
- self->global_units_directions[D_Top] = top_output_unit;
+ if (self->page_css.number <= 0)
+ return 0;
- /* It is always the first printindex, even if it is not output (for example
- it is in @copying and @titlepage, which are certainly wrong constructs).
- */
- if (self->document->global_commands->printindex.number > 0)
+ CSS_LIST *global_context_css_list = &self->page_css.list[0];
+
+ if (filename)
{
- const ELEMENT *printindex
- = self->document->global_commands->printindex.list[0];
- ROOT_AND_UNIT *root_unit
- = html_get_tree_root_element (self, printindex, 0);
- if (root_unit->output_unit)
- {
- const OUTPUT_UNIT *document_unit = root_unit->output_unit;
- const ELEMENT *root_command = root_unit->root;
- if (root_command && root_command->cmd == CM_node)
- {
- const ELEMENT *associated_section
- = lookup_extra_element (root_command, "associated_section");
- if (associated_section)
- root_command = associated_section;
- }
- /* find the first level 1 sectioning element to associate the printindex
- with */
- if (root_command && root_command->cmd != CM_node)
- {
- while (1)
- {
- int status;
- int section_level
- = lookup_extra_integer (root_command, "section_level",
- &status);
- if (!status && section_level <= 1)
- break;
+ CSS_LIST *css_list;
+ page_number = find_page_name_number (&self->page_name_number,
+ filename);
+ if (!page_number)
+ fatal ("Could not find page number of file name");
- const ELEMENT *up_section_directions
- = lookup_extra_element (root_command,
"section_directions");
- if (up_section_directions
- && up_section_directions->contents.list[D_up]
- && up_section_directions->contents.list[D_up]
- ->associated_unit)
- {
- root_command =
up_section_directions->contents.list[D_up];
- document_unit = root_command->associated_unit;
- }
- else
- break;
- }
- }
- self->global_units_directions[D_Index] = document_unit;
+ css_list = &self->page_css.list[page_number];
+ if (css_list->number)
+ {
+ /* +1 for 'span:hover a.copiable-link' */
+ size_t space = css_list->number + global_context_css_list->number +1;
+ selectors = (const char **) malloc (sizeof (char *) * space);
+ memcpy (selectors, css_list->list,
+ css_list->number * sizeof (char *));
+ selector_nr = css_list->number;
}
- free (root_unit);
}
- if (self->conf->DEBUG > 0)
+ if (selector_nr <= 0)
{
- int i;
- fprintf (stderr, "GLOBAL DIRECTIONS:\n");
- for (i = 0; i < D_Last+1; i++)
+ if (global_context_css_list->number)
{
- if (self->global_units_directions[i])
- {
- const OUTPUT_UNIT *global_unit =
self->global_units_directions[i];
- char *unit_texi = output_unit_texi (global_unit);
- fprintf (stderr, " %s: %s\n",
html_global_unit_direction_names[i],
- unit_texi);
- free (unit_texi);
- }
+ /* +1 for 'span:hover a.copiable-link' */
+ size_t space = global_context_css_list->number +1;
+ selectors = (const char **) malloc (sizeof (char *) * space);
+ selector_nr = global_context_css_list->number;
}
- fprintf (stderr, "\n");
- }
-
- /* determine total number of special output units and fill
- special_units_directions_name_unit. Used to simplify building perl
- directions */
- for (i = 0; i < 2; i++)
- {
- int special_units_descriptor = special_output_units_lists[i];
- const OUTPUT_UNIT_LIST *units_list
- = retrieve_output_units (special_units_descriptor);
- if (units_list && units_list->number)
- all_special_units_nr += units_list->number;
+ else
+ return 0;
}
-
- self->special_units_direction_name = (SPECIAL_UNIT_DIRECTION *)
- malloc (sizeof (SPECIAL_UNIT_DIRECTION) * (all_special_units_nr+1));
- memset (self->special_units_direction_name, 0,
- sizeof (SPECIAL_UNIT_DIRECTION) * (all_special_units_nr+1));
-
- s = 0;
- for (i = 0; i < 2; i++)
+ else if (global_context_css_list->number)
{
- int special_units_descriptor = special_output_units_lists[i];
- OUTPUT_UNIT_LIST *units_list
- = retrieve_output_units (special_units_descriptor);
- if (units_list && units_list->number)
+ int i;
+ size_t file_selector_nr = selector_nr;
+ /* add global context selectors if not already present */
+ for (i = 0; i < global_context_css_list->number; i++)
{
int j;
- for (j = 0; j < units_list->number; j++)
+ const char *global_selector = global_context_css_list->list[i];
+ int found = 0;
+ for (j = 0; j < file_selector_nr; j++)
{
- 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,
- special_unit_variety);
- self->global_units_directions[special_unit_direction_index]
- = special_unit;
-
- self->special_units_direction_name[s].output_unit = special_unit;
- self->special_units_direction_name[s].direction
- = special_unit_info (self, SUI_type_direction,
- special_unit_variety);
- s++;
+ if (!strcmp (global_selector, selectors[j]))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ {
+ selectors[selector_nr] = global_selector;
+ selector_nr++;
}
}
}
-}
-
-static void
-set_file_source_info (FILE_SOURCE_INFO *file_source_info,
- char *file_info_type, char *file_info_name,
- const ELEMENT *file_info_element, char *filepath)
-{
- file_source_info->type = file_info_type;
- file_source_info->name = file_info_name;
- file_source_info->element = file_info_element;
- file_source_info->path = filepath;
-}
-
-static FILE_SOURCE_INFO *
-add_to_files_source_info (FILE_SOURCE_INFO_LIST *files_source_info,
- char *filename,
- char *file_info_type, char *file_info_name,
- const ELEMENT *file_info_element, char *filepath)
-{
- FILE_SOURCE_INFO *new_file_source_info;
- if (files_source_info->number == files_source_info->space)
+ for (j = 0; j < selector_nr; j++)
{
- files_source_info->list = realloc (files_source_info->list,
- (files_source_info->space += 5) * sizeof (FILE_SOURCE_INFO));
- if (!files_source_info->list)
- fatal ("realloc failed");
+ if (!strcmp ("a.copiable-link", selectors[j]))
+ {
+ selectors[selector_nr] = "span:hover a.copiable-link";
+ selector_nr++;
+ break;
+ }
}
- new_file_source_info =
- &files_source_info->list[files_source_info->number];
+ qsort (selectors, selector_nr, sizeof (char *), compare_strings);
- new_file_source_info->filename = strdup (filename);
- set_file_source_info (new_file_source_info, file_info_type,
- file_info_name, file_info_element, filepath);
+ result = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (result, 0, sizeof (STRING_LIST));
+ for (j = 0; j < selector_nr; j++)
+ add_string (selectors[j], result);
- files_source_info->number++;
+ free (selectors);
- return new_file_source_info;
+ return result;
}
-static FILE_SOURCE_INFO *
-find_file_source_info (FILE_SOURCE_INFO_LIST *files_source_info,
- char *filename)
+static char *
+protect_class_name (const char *class_name)
{
- int i;
- for (i = 0; i < files_source_info->number; i++)
+ TEXT result;
+ TEXT space_protected;
+ text_init (&result);
+ text_init (&space_protected);
+ const char *p = class_name;
+ while (*p)
{
- FILE_SOURCE_INFO *file_source_info = &files_source_info->list[i];
- if (!strcmp (file_source_info->filename, filename))
- return file_source_info;
+ int n = strcspn (p, " ");
+ if (n)
+ {
+ text_append_n (&space_protected, p, n);
+ p += n;
+ }
+ if (*p)
+ {
+ int n = strspn (p, " ");
+ if (n)
+ {
+ int i;
+ for (i = 0; i < n; i++)
+ text_append_n (&space_protected, "-", 1);
+ p += n;
+ }
+ }
}
- return 0;
+
+ /* do not use the customization API as in perl */
+ html_default_format_protect_text (space_protected.text, &result);
+ free (space_protected.text);
+ return result.text;
}
-void
-html_destroy_files_source_info (FILE_SOURCE_INFO_LIST *files_source_info)
+char *
+html_attribute_class (CONVERTER *self, const char *element,
+ const STRING_LIST *classes)
{
+ TEXT result;
+ char *style = 0;
int i;
- for (i = 0; i < files_source_info->number; i++)
+ int class_nr = 0;
+ if (!classes || classes->number <= 0
+ || self->conf->NO_CSS > 0)
{
- free (files_source_info->list[i].filename);
+ if (!strcmp (element, "span"))
+ return strdup ("");
+ else
+ {
+ char *result;
+ xasprintf (&result, "<%s", element);
+ return result;
+ }
}
- free (files_source_info->list);
- free (files_source_info);
-}
-
-static char *
-add_to_unit_file_name_paths (char **unit_file_name_paths,
- char *filename, OUTPUT_UNIT *output_unit)
-{
- char **new_output_unit_file_name
- = &unit_file_name_paths[output_unit->index];
- *new_output_unit_file_name = strdup (filename);
-
- return *new_output_unit_file_name;
-}
-
-static FILE_SOURCE_INFO_LIST *
-html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST *output_units,
- OUTPUT_UNIT_LIST *special_units,
- OUTPUT_UNIT_LIST *associated_special_units,
- char *output_file,
- char *destination_directory, char *output_filename,
- char *document_name)
-{
- FILE_SOURCE_INFO_LIST *files_source_info = 0;
- char **unit_file_name_paths;
- int i;
-
- if (!output_units || !output_units->number)
- return 0;
-
- initialize_output_units_files (self);
-
- files_source_info = (FILE_SOURCE_INFO_LIST *)
- malloc (sizeof (FILE_SOURCE_INFO_LIST));
- memset (files_source_info, 0, sizeof (FILE_SOURCE_INFO_LIST));
-
- unit_file_name_paths = (char **)
- malloc (output_units->number * sizeof (char *));
- memset (unit_file_name_paths, 0,
- output_units->number * sizeof (char *));
- if (!self->conf->SPLIT || !strlen (self->conf->SPLIT))
+ if (self->conf->INLINE_CSS_STYLE > 0)
{
int i;
- add_to_files_source_info (files_source_info, output_filename,
- "special_file", "non_split", 0,
- output_file);
- for (i = 0; i < output_units->number; i++)
+ TEXT inline_styles;
+ text_init (&inline_styles);
+ int style_nr = 0;
+ for (i = 0; i < classes->number; i++)
{
- add_to_unit_file_name_paths (unit_file_name_paths,
- output_filename,
- output_units->list[i]);
+ const char *style_class = classes->list[i];
+ char *selector;
+ CSS_SELECTOR_STYLE *selector_style;
+
+ xasprintf (&selector, "%s.%s", element, style_class);
+ selector_style
+ = find_css_selector_style (&self->css_element_class_styles,
+ selector);
+ free (selector);
+ if (selector_style)
+ {
+ if (style_nr)
+ text_printf (&inline_styles, ";%s", selector_style->style);
+ else
+ text_append (&inline_styles, selector_style->style);
+ style_nr++;
+ }
+ }
+ if (inline_styles.end)
+ {
+ xasprintf (&style, " style=\"%s\"", inline_styles.text);
}
+ free (inline_styles.text);
}
else
{
- char *top_node_filename_str;
- OUTPUT_UNIT *node_top_output_unit = 0;
- char *extension = 0;
- const ELEMENT *node_top = 0;
- int file_nr = 0;
int i;
+ for (i = 0; i < classes->number; i++)
+ {
+ const char *style_class = classes->list[i];
+ char *selector;
- /* first determine the top node file name. */
- if (self->document->identifiers_target)
- node_top = find_identifier_target (self->document->identifiers_target,
- "Top");
+ xasprintf (&selector, "%s.%s", element, style_class);
+ collect_css_element_class (self, selector);
+ free (selector);
+ }
+ }
+ text_init (&result);
+ text_printf (&result, "<%s class=\"", element);
+ for (i = 0; i < classes->number; i++)
+ {
+ const char *class_name = classes->list[i];
+ char *protected_class = protect_class_name (class_name);
+ if (class_nr)
+ text_printf (&result, " %s", protected_class);
+ else
+ text_append (&result, protected_class);
+ free (protected_class);
+ class_nr++;
+ }
+ text_append_n (&result, "\"", 1);
+ if (style)
+ {
+ text_append (&result, style);
+ free (style);
+ }
+ return result.text;
+}
- top_node_filename_str = top_node_filename (self, document_name);
+void
+html_merge_index_entries (CONVERTER *self)
+{
+ if (self->document->index_names)
+ {
+ INDEX **index_names = self->document->index_names;
+ MERGED_INDEX *merged_index_entries = merge_indices (index_names);
+ self->index_entries = merged_index_entries;
+ }
+}
- if (node_top && top_node_filename_str)
- {
- int i;
- node_top_output_unit = node_top->associated_unit;
- for (i = 0; i < output_units->number; i++)
- if (output_units->list[i] == node_top_output_unit)
- break;
- add_to_files_source_info (files_source_info, top_node_filename_str,
- "special_file", "Top", 0, 0);
- add_to_unit_file_name_paths (unit_file_name_paths,
- top_node_filename_str,
- node_top_output_unit);
- }
+int
+compare_index_name (const void *a, const void *b)
+{
+ const INDEX **idx_a = (const INDEX **) a;
+ const INDEX **idx_b = (const INDEX **) b;
- if (self->conf->EXTENSION && strlen (self->conf->EXTENSION))
- extension = self->conf->EXTENSION;
+ return strcmp ((*idx_a)->name, (*idx_b)->name);
+}
- for (i = 0; i < output_units->number; i++)
- {
- OUTPUT_UNIT *output_unit = output_units->list[i];
- OUTPUT_UNIT *file_output_unit;
- char *output_unit_file_name;
- /* For Top node. */
- if (node_top_output_unit && node_top_output_unit == output_unit)
- continue;
+void
+prepare_index_entries_targets (CONVERTER *self)
+{
+ if (self->document->index_names)
+ {
+ INDEX **i, *idx;
+ INDEX **index_names = self->document->index_names;
+ INDEX **sorted_index_names;
+ int index_nr = 0;
- file_output_unit = output_unit->first_in_page;
- output_unit_file_name
- = unit_file_name_paths[file_output_unit->index];
- if (!output_unit_file_name)
+ /* TODO sort indices by name before? when registering in document?
+ In parser?
+ Depending on size? And use bsearch in some places?
+ */
+ for (i = index_names; (idx = *i); i++)
+ index_nr++;
+
+ sorted_index_names = (INDEX **) malloc ((index_nr+1) * sizeof (INDEX *));
+
+ memcpy (sorted_index_names, index_names, (index_nr+1) * sizeof (INDEX
*));
+ qsort (sorted_index_names, index_nr, sizeof (INDEX *),
+ compare_index_name);
+
+ for (i = sorted_index_names; (idx = *i); i++)
+ {
+ if (idx->entries_number > 0)
{
- char *node_filename = 0;
int j;
- for (j = 0; j < file_output_unit->unit_contents.number; j++)
+ for (j = 0; j < idx->entries_number; j++)
{
- const ELEMENT *root_command
- = file_output_unit->unit_contents.list[j];
- if (root_command->cmd == CM_node)
+ INDEX_ENTRY *index_entry;
+ const ELEMENT *main_entry_element;
+ const ELEMENT *seeentry;
+ const ELEMENT *seealso;
+ ELEMENT *entry_reference_content_element;
+ ELEMENT *normalize_index_element;
+ ELEMENT_LIST *subentries_tree;
+ const ELEMENT *target_element;
+ TEXT target_base;
+ char *normalized_index;
+ char *region = 0;
+ char *target;
+
+ index_entry = &idx->index_entries[j];
+ main_entry_element = index_entry->entry_element;
+ seeentry = lookup_extra_element (main_entry_element,
+ "seeentry");
+ if (seeentry)
+ continue;
+ seealso = lookup_extra_element (main_entry_element,
+ "seealso");
+ if (seealso)
+ continue;
+
+ region = lookup_extra_string (main_entry_element,
+ "element_region");
+ entry_reference_content_element
+ = index_content_element (main_entry_element, 1);
+ /* construct element to convert to a normalized identifier to use as
+ hrefs target */
+ normalize_index_element = new_element (ET_NONE);
+ add_to_element_contents (normalize_index_element,
+ entry_reference_content_element);
+
+ subentries_tree
+ = comma_index_subentries_tree (main_entry_element, " ");
+ if (subentries_tree)
{
- const ELEMENT *node_target = 0;
- char *normalized = lookup_extra_string (root_command,
- "normalized");
- if (normalized)
- node_target
- = find_identifier_target (
- self->document->identifiers_target,
- normalized);
- /* double node are not normalized, they are handled here */
- if (!node_target)
- {
- FILE_SOURCE_INFO *file_source_info = 0;
+ insert_list_slice_into_contents (normalize_index_element,
+
normalize_index_element->contents.number,
+ subentries_tree, 0,
+ subentries_tree->number);
+ }
+ normalized_index
+ = normalize_transliterate_texinfo (normalize_index_element,
+ (self->conf->TEST > 0));
- TEXT file_name_text;
- text_init (&file_name_text);
- text_append (&file_name_text, "unknown_node");
- if (extension)
- {
- text_append (&file_name_text, ".");
- text_append (&file_name_text, extension);
- }
- file_source_info
- = find_file_source_info (files_source_info,
- file_name_text.text);
- if (!file_source_info)
- {
- file_source_info
- = add_to_files_source_info (files_source_info,
- file_name_text.text, "node", 0,
- root_command, 0);
- node_filename = file_source_info->filename;
- }
- free (file_name_text.text);
- }
- else
- {
- /* Nodes with {'extra'}->{'is_target'} should always be in
- 'identifiers_target', and thus in targets. It is a bug otherwise.
*/
- FILE_SOURCE_INFO *file_source_info = 0;
- HTML_TARGET *node_target
- = find_element_target (&self->html_targets,
- root_command);
- node_filename = node_target->node_filename;
+ destroy_element (normalize_index_element);
+ if (subentries_tree)
+ free_comma_index_subentries_tree (subentries_tree);
- file_source_info
- = find_file_source_info (files_source_info,
- node_filename);
- if (file_source_info)
- {
- if (!strcmp (file_source_info->type,
- "stand_in_file"))
- {/* NOTE we keep the order, as in perl */
- set_file_source_info (file_source_info,
- "node",
- 0, root_command, 0);
- }
- }
- else
- add_to_files_source_info (files_source_info,
- node_filename, "node", 0,
- root_command, 0);
- }
- output_unit_file_name
- = add_to_unit_file_name_paths (unit_file_name_paths,
- node_filename,
- file_output_unit);
- break;
- }
- }
- if (!node_filename)
- {
- /* use section to do the file name if there is no node */
- const ELEMENT *command = file_output_unit->unit_command;
- if (command)
- {
- if (command->cmd == CM_top && !node_top
- && top_node_filename_str)
- {
- /* existing top_node_filename can happen, see
- html_tests.t top_file_name_and_node_name_collision */
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info,
- top_node_filename_str);
- if (file_source_info)
- {/* NOTE we keep the order, as in perl */
- set_file_source_info (file_source_info,
- "special_file", "Top",
- 0, 0);
- }
- else
- {
- add_to_files_source_info (files_source_info,
- top_node_filename_str,
- "special_file", "Top",
- 0, 0);
- }
- output_unit_file_name
- = add_to_unit_file_name_paths (unit_file_name_paths,
-
top_node_filename_str,
- file_output_unit);
- }
- else
- {
- HTML_TARGET *section_target
- = find_element_target (&self->html_targets,
- command);
- char *section_filename
- = section_target->section_filename;
-
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info,
- section_filename);
- if (file_source_info)
- {
- if (!strcmp (file_source_info->type,
- "stand_in_file"))
- {/* NOTE we keep the order, as in perl */
- set_file_source_info (file_source_info,
- "section",
- 0, command, 0);
- }
- }
- else
- add_to_files_source_info (files_source_info,
- section_filename, "section",
0,
- command, 0);
- output_unit_file_name
- = add_to_unit_file_name_paths
(unit_file_name_paths,
- section_filename,
- file_output_unit);
- }
- }
- else
- {
- /* when everything else has failed */
- if (file_nr == 0 && !node_top
- && top_node_filename_str)
- {
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info,
- top_node_filename_str);
- if (!file_source_info)
- {
- add_to_files_source_info (files_source_info,
- top_node_filename_str,
- "stand_in_file", "Top",
- 0, 0);
- }
- output_unit_file_name
- = add_to_unit_file_name_paths (unit_file_name_paths,
- top_node_filename_str,
- file_output_unit);
- }
- else
- {
- FILE_SOURCE_INFO *file_source_info;
-
- TEXT file_name_text;
- text_init (&file_name_text);
- text_printf (&file_name_text, "%s_%d", document_name,
- file_nr);
- if (extension)
- {
- text_append (&file_name_text, ".");
- text_append (&file_name_text, extension);
- }
- file_source_info
- = find_file_source_info (files_source_info,
- file_name_text.text);
- if (!file_source_info)
- {
- add_to_files_source_info (files_source_info,
- file_name_text.text,
- "stand_in_file",
- "unknown",
- 0, 0);
- }
- output_unit_file_name
- = add_to_unit_file_name_paths (unit_file_name_paths,
- file_name_text.text,
- file_output_unit);
- free (file_name_text.text);
- }
- file_nr++;
+ text_init (&target_base);
+ text_append (&target_base, "index-");
+ if (region)
+ {
+ text_append (&target_base, region);
+ text_append (&target_base, "-");
}
+ text_append (&target_base, normalized_index);
+ free (normalized_index);
+ target = unique_target (self, target_base.text);
+ free (target_base.text);
+ if (index_entry->entry_associated_element)
+ target_element = index_entry->entry_associated_element;
+ else
+ target_element = main_entry_element;
+
+ add_element_target (self, target_element, target);
+ add_string (target, &self->seen_ids);
+
+ free (target);
}
}
- if (output_unit != file_output_unit)
- add_to_unit_file_name_paths (unit_file_name_paths,
- output_unit_file_name,
- output_unit);
}
- free (top_node_filename_str);
+ free (sorted_index_names);
}
+}
- self->output_unit_file_indices = (size_t *)
- malloc (output_units->number * sizeof (size_t));
+static const char *footid_base = "FOOT";
+static const char *docid_base = "DOCF";
- for (i = 0; i < output_units->number; i++)
+static void
+prepare_footnotes_targets (CONVERTER *self)
+{
+ const ELEMENT_LIST *global_footnotes =
&self->document->global_commands->footnotes;
+ if (global_footnotes->number > 0)
{
- size_t output_unit_file_idx = 0;
- FILE_NAME_PATH_COUNTER *output_unit_file;
- OUTPUT_UNIT *output_unit = output_units->list[i];
- char *output_unit_file_name = unit_file_name_paths[i];
- char *filename = strdup (output_unit_file_name);
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info, output_unit_file_name);
- char *filepath = file_source_info->path;
-
- FILE_NAME_PATH *file_name_path
- = call_file_id_setting_unit_file_name (self, output_unit,
- output_unit_file_name, filepath);
- if (file_name_path)
+ int i;
+ for (i = 0; i < global_footnotes->number; i++)
{
- if (file_name_path->filename)
+ const ELEMENT *footnote = global_footnotes->list[i];
+ TEXT footid;
+ TEXT docid;
+ int nr = i+1;
+
+ text_init (&footid);
+ text_init (&docid);
+ text_printf (&footid, "%s%d", footid_base, nr);
+ text_printf (&docid, "%s%d", docid_base, nr);
+
+ while (1)
{
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info,
- file_name_path->filename);
- if (file_source_info)
+ int j;
+ int non_unique = 0;
+ for (j = 0; j < self->seen_ids.number; j++)
{
- if (file_source_info->path && file_name_path->filepath
- && strcmp (file_source_info->path,
- file_name_path->filepath))
+ if (!strcmp (footid.text, self->seen_ids.list[j])
+ || !strcmp (docid.text, self->seen_ids.list[j]))
{
- message_list_document_warn (&self->error_messages,
- self->conf,
- "resetting %s file path %s to %s",
- file_name_path->filename,
- file_source_info->path,
- file_name_path->filepath);
+ non_unique = 1;
+ break;
}
- set_file_source_info (file_source_info, "special_file",
- "user_defined", 0, file_name_path->filepath);
+ }
+ if (non_unique)
+ {
+ nr++;
+ if (nr == 0)
+ fatal ("overflow footnote target nr");
+
+ text_init (&footid);
+ text_init (&docid);
+ text_printf (&footid, "%s%d", footid_base, nr);
+ text_printf (&docid, "%s%d", docid_base, nr);
}
else
- add_to_files_source_info (files_source_info,
- file_name_path->filename,
- "special_file", "user_defined",
- 0, file_name_path->filepath);
- free (filename);
- filename = file_name_path->filename;
+ break;
}
- free (file_name_path);
+ add_string (footid.text, &self->seen_ids);
+ add_string (docid.text, &self->seen_ids);
+ add_element_target (self, footnote, footid.text);
+ add_special_target (self, ST_footnote_location, footnote,
+ docid.text);
+
+ if (self->conf->DEBUG > 0)
+ {
+ char *footnote_txi = convert_to_texinfo (footnote);
+ fprintf (stderr, "Enter footnote: target %s, nr %d\n%s\n",
+ footid.text, nr, footnote_txi);
+ free (footnote_txi);
+ }
+ free (footid.text);
+ free (docid.text);
}
- output_unit_file_idx
- = set_output_unit_file (self, output_unit, filename, 1);
- self->output_unit_file_indices[i] = output_unit_file_idx;
- output_unit_file = &self->output_unit_files.list[output_unit_file_idx];
- if (self->conf->DEBUG > 0)
- fprintf (stderr, "Page %s: %s(%d)\n",
- output_unit_texi (output_unit),
- output_unit->unit_filename, output_unit_file->counter);
- free (filename);
- free (output_unit_file_name);
}
+}
- free (unit_file_name_paths);
+/* for conversion units except for associated special units that require
+ files for document units to be set */
+void
+html_prepare_conversion_units_targets (CONVERTER *self,
+ const char *document_name,
+ int output_units_descriptor,
+ int special_units_descriptor,
+ int associated_special_units_descriptor)
+{
+ /*
+ Do that before the other elements, to be sure that special page ids
+ are registered before elements id are.
+ */
+ set_special_units_targets_files (self, special_units_descriptor,
+ document_name);
- if (special_units && special_units->number)
- {
- int i;
- self->special_unit_file_indices = (size_t *)
- malloc (special_units->number * sizeof (size_t));
- for (i = 0; i < special_units->number; i++)
- {
- size_t special_unit_file_idx = 0;
- FILE_NAME_PATH_COUNTER *special_unit_file;
- OUTPUT_UNIT *special_unit = special_units->list[i];
- const ELEMENT *unit_command = special_unit->unit_command;
- const HTML_TARGET *special_unit_target
- = find_element_target (&self->html_targets, unit_command);
- char *filename = special_unit_target->special_unit_filename;
+ prepare_associated_special_units_targets (self,
+ associated_special_units_descriptor);
- /* Associate the special elements that have no page with the main page.
- This may only happen if not split. */
- if (!filename && special_units->number
- && output_units && output_units->number
- && output_units->list[0]->unit_filename)
- {
- filename = output_units->list[0]->unit_filename;
- }
+ set_root_commands_targets_node_files (self);
- if (filename)
+ prepare_index_entries_targets (self);
+ prepare_footnotes_targets (self);
+}
+
+/* Associate output units to the global targets, First, Last, Top, Index.
+ and special output units */
+void
+html_prepare_output_units_global_targets (CONVERTER *self,
+ int output_units_descriptor,
+ int special_units_descriptor,
+ int
associated_special_units_descriptor)
+{
+ int i;
+ int all_special_units_nr = 0;
+ int s;
+ const OUTPUT_UNIT_LIST *output_units
+ = retrieve_output_units (output_units_descriptor);
+
+ const OUTPUT_UNIT *top_output_unit = get_top_unit (self->document,
+ output_units);
+
+ int special_output_units_lists[2] = {special_units_descriptor,
+ associated_special_units_descriptor};
+
+ self->global_units_directions[D_First] = output_units->list[0];
+ self->global_units_directions[D_Last]
+ = output_units->list[output_units->number - 1];
+
+ self->global_units_directions[D_Top] = top_output_unit;
+
+ /* It is always the first printindex, even if it is not output (for example
+ it is in @copying and @titlepage, which are certainly wrong constructs).
+ */
+ if (self->document->global_commands->printindex.number > 0)
+ {
+ const ELEMENT *printindex
+ = self->document->global_commands->printindex.list[0];
+ ROOT_AND_UNIT *root_unit
+ = html_get_tree_root_element (self, printindex, 0);
+ if (root_unit->output_unit)
+ {
+ const OUTPUT_UNIT *document_unit = root_unit->output_unit;
+ const ELEMENT *root_command = root_unit->root;
+ if (root_command && root_command->cmd == CM_node)
{
- FILE_SOURCE_INFO *file_source_info
- = find_file_source_info (files_source_info, filename);
- if (file_source_info)
+ const ELEMENT *associated_section
+ = lookup_extra_element (root_command, "associated_section");
+ if (associated_section)
+ root_command = associated_section;
+ }
+ /* find the first level 1 sectioning element to associate the printindex
+ with */
+ if (root_command && root_command->cmd != CM_node)
+ {
+ while (1)
{
- if (!strcmp (file_source_info->type, "stand_in_file"))
- {/* NOTE we keep the order, as in perl */
- set_file_source_info (file_source_info, "special_unit",
- 0, unit_command, 0);
+ int status;
+ int section_level
+ = lookup_extra_integer (root_command, "section_level",
+ &status);
+ if (!status && section_level <= 1)
+ break;
+
+ const ELEMENT *up_section_directions
+ = lookup_extra_element (root_command,
"section_directions");
+ if (up_section_directions
+ && up_section_directions->contents.list[D_up]
+ && up_section_directions->contents.list[D_up]
+ ->associated_unit)
+ {
+ root_command =
up_section_directions->contents.list[D_up];
+ document_unit = root_command->associated_unit;
}
+ else
+ break;
}
- else
- add_to_files_source_info (files_source_info, filename,
- "special_unit", 0, unit_command, 0);
}
- special_unit_file_idx
- = set_output_unit_file (self, special_unit, filename, 1);
- self->special_unit_file_indices[i] = special_unit_file_idx;
- special_unit_file
- = &self->output_unit_files.list[special_unit_file_idx];
- if (self->conf->DEBUG > 0)
- fprintf (stderr, "Special page: %s(%d)\n", filename,
- special_unit_file->counter);
+ self->global_units_directions[D_Index] = document_unit;
+ }
+ free (root_unit);
+ }
+
+ if (self->conf->DEBUG > 0)
+ {
+ int i;
+ fprintf (stderr, "GLOBAL DIRECTIONS:\n");
+ for (i = 0; i < D_Last+1; i++)
+ {
+ if (self->global_units_directions[i])
+ {
+ const OUTPUT_UNIT *global_unit =
self->global_units_directions[i];
+ char *unit_texi = output_unit_texi (global_unit);
+ fprintf (stderr, " %s: %s\n",
html_global_unit_direction_names[i],
+ unit_texi);
+ free (unit_texi);
+ }
+ }
+ fprintf (stderr, "\n");
+ }
+
+ /* determine total number of special output units and fill
+ special_units_directions_name_unit. Used to simplify building perl
+ directions */
+ for (i = 0; i < 2; i++)
+ {
+ int special_units_descriptor = special_output_units_lists[i];
+ const OUTPUT_UNIT_LIST *units_list
+ = retrieve_output_units (special_units_descriptor);
+ if (units_list && units_list->number)
+ all_special_units_nr += units_list->number;
+ }
+
+ self->special_units_direction_name = (SPECIAL_UNIT_DIRECTION *)
+ malloc (sizeof (SPECIAL_UNIT_DIRECTION) * (all_special_units_nr+1));
+ memset (self->special_units_direction_name, 0,
+ sizeof (SPECIAL_UNIT_DIRECTION) * (all_special_units_nr+1));
+
+ s = 0;
+ for (i = 0; i < 2; i++)
+ {
+ int special_units_descriptor = special_output_units_lists[i];
+ OUTPUT_UNIT_LIST *units_list
+ = retrieve_output_units (special_units_descriptor);
+ if (units_list && units_list->number)
+ {
+ int j;
+ for (j = 0; j < units_list->number; j++)
+ {
+ 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,
+ special_unit_variety);
+ self->global_units_directions[special_unit_direction_index]
+ = special_unit;
+
+ self->special_units_direction_name[s].output_unit = special_unit;
+ self->special_units_direction_name[s].direction
+ = special_unit_info (self, SUI_type_direction,
+ special_unit_variety);
+ s++;
+ }
+ }
+ }
+}
+
+static void
+set_file_source_info (FILE_SOURCE_INFO *file_source_info,
+ char *file_info_type, char *file_info_name,
+ const ELEMENT *file_info_element, char *filepath)
+{
+ file_source_info->type = file_info_type;
+ file_source_info->name = file_info_name;
+ file_source_info->element = file_info_element;
+ file_source_info->path = filepath;
+}
+
+static FILE_SOURCE_INFO *
+add_to_files_source_info (FILE_SOURCE_INFO_LIST *files_source_info,
+ char *filename,
+ char *file_info_type, char *file_info_name,
+ const ELEMENT *file_info_element, char *filepath)
+{
+ FILE_SOURCE_INFO *new_file_source_info;
+ if (files_source_info->number == files_source_info->space)
+ {
+ files_source_info->list = realloc (files_source_info->list,
+ (files_source_info->space += 5) * sizeof (FILE_SOURCE_INFO));
+ if (!files_source_info->list)
+ fatal ("realloc failed");
+ }
+
+ new_file_source_info =
+ &files_source_info->list[files_source_info->number];
+
+ new_file_source_info->filename = strdup (filename);
+ set_file_source_info (new_file_source_info, file_info_type,
+ file_info_name, file_info_element, filepath);
+
+ files_source_info->number++;
+
+ return new_file_source_info;
+}
+
+static FILE_SOURCE_INFO *
+find_file_source_info (FILE_SOURCE_INFO_LIST *files_source_info,
+ char *filename)
+{
+ int i;
+ for (i = 0; i < files_source_info->number; i++)
+ {
+ FILE_SOURCE_INFO *file_source_info = &files_source_info->list[i];
+ if (!strcmp (file_source_info->filename, filename))
+ return file_source_info;
+ }
+ return 0;
+}
+
+void
+html_destroy_files_source_info (FILE_SOURCE_INFO_LIST *files_source_info)
+{
+ int i;
+ for (i = 0; i < files_source_info->number; i++)
+ {
+ free (files_source_info->list[i].filename);
+ }
+ free (files_source_info->list);
+ free (files_source_info);
+}
+
+static char *
+add_to_unit_file_name_paths (char **unit_file_name_paths,
+ char *filename, OUTPUT_UNIT *output_unit)
+{
+ /* FIXME simplify */
+ char **new_output_unit_file_name
+ = &unit_file_name_paths[output_unit->index];
+ *new_output_unit_file_name = strdup (filename);
+
+ return *new_output_unit_file_name;
+}
+
+static FILE_SOURCE_INFO_LIST *
+html_set_pages_files (CONVERTER *self, OUTPUT_UNIT_LIST *output_units,
+ OUTPUT_UNIT_LIST *special_units,
+ OUTPUT_UNIT_LIST *associated_special_units,
+ char *output_file,
+ char *destination_directory, char *output_filename,
+ char *document_name)
+{
+ FILE_SOURCE_INFO_LIST *files_source_info = 0;
+ char **unit_file_name_paths;
+ int i;
+
+ if (!output_units || !output_units->number)
+ return 0;
+
+ initialize_output_units_files (self);
+
+ files_source_info = (FILE_SOURCE_INFO_LIST *)
+ malloc (sizeof (FILE_SOURCE_INFO_LIST));
+ memset (files_source_info, 0, sizeof (FILE_SOURCE_INFO_LIST));
+
+ unit_file_name_paths = (char **)
+ malloc (output_units->number * sizeof (char *));
+ memset (unit_file_name_paths, 0,
+ output_units->number * sizeof (char *));
+
+ if (!self->conf->SPLIT || !strlen (self->conf->SPLIT))
+ {
+ int i;
+ add_to_files_source_info (files_source_info, output_filename,
+ "special_file", "non_split", 0,
+ output_file);
+ for (i = 0; i < output_units->number; i++)
+ {
+ add_to_unit_file_name_paths (unit_file_name_paths,
+ output_filename,
+ output_units->list[i]);
+ }
+ }
+ else
+ {
+ char *top_node_filename_str;
+ OUTPUT_UNIT *node_top_output_unit = 0;
+ char *extension = 0;
+ const ELEMENT *node_top = 0;
+ int file_nr = 0;
+ int i;
+
+ /* first determine the top node file name. */
+ if (self->document->identifiers_target)
+ node_top = find_identifier_target (self->document->identifiers_target,
+ "Top");
+
+ top_node_filename_str = top_node_filename (self, document_name);
+
+ if (node_top && top_node_filename_str)
+ {
+ int i;
+ node_top_output_unit = node_top->associated_unit;
+ for (i = 0; i < output_units->number; i++)
+ if (output_units->list[i] == node_top_output_unit)
+ break;
+ add_to_files_source_info (files_source_info, top_node_filename_str,
+ "special_file", "Top", 0, 0);
+ add_to_unit_file_name_paths (unit_file_name_paths,
+ top_node_filename_str,
+ node_top_output_unit);
+ }
+
+ if (self->conf->EXTENSION && strlen (self->conf->EXTENSION))
+ extension = self->conf->EXTENSION;
+
+ for (i = 0; i < output_units->number; i++)
+ {
+ OUTPUT_UNIT *output_unit = output_units->list[i];
+ OUTPUT_UNIT *file_output_unit;
+ char *output_unit_file_name;
+ /* For Top node. */
+ if (node_top_output_unit && node_top_output_unit == output_unit)
+ continue;
+
+ file_output_unit = output_unit->first_in_page;
+ output_unit_file_name
+ = unit_file_name_paths[file_output_unit->index];
+ if (!output_unit_file_name)
+ {
+ char *node_filename = 0;
+ int j;
+ for (j = 0; j < file_output_unit->unit_contents.number; j++)
+ {
+ const ELEMENT *root_command
+ = file_output_unit->unit_contents.list[j];
+ if (root_command->cmd == CM_node)
+ {
+ const ELEMENT *node_target = 0;
+ char *normalized = lookup_extra_string (root_command,
+ "normalized");
+ if (normalized)
+ node_target
+ = find_identifier_target (
+ self->document->identifiers_target,
+ normalized);
+ /* double node are not normalized, they are handled here */
+ if (!node_target)
+ {
+ FILE_SOURCE_INFO *file_source_info = 0;
+
+ TEXT file_name_text;
+ text_init (&file_name_text);
+ text_append (&file_name_text, "unknown_node");
+ if (extension)
+ {
+ text_append (&file_name_text, ".");
+ text_append (&file_name_text, extension);
+ }
+ file_source_info
+ = find_file_source_info (files_source_info,
+ file_name_text.text);
+ if (!file_source_info)
+ {
+ file_source_info
+ = add_to_files_source_info (files_source_info,
+ file_name_text.text, "node", 0,
+ root_command, 0);
+ node_filename = file_source_info->filename;
+ }
+ free (file_name_text.text);
+ }
+ else
+ {
+ /* Nodes with {'extra'}->{'is_target'} should always be in
+ 'identifiers_target', and thus in targets. It is a bug otherwise.
*/
+ FILE_SOURCE_INFO *file_source_info = 0;
+ HTML_TARGET *node_target
+ = find_element_target (&self->html_targets,
+ root_command);
+ node_filename = node_target->node_filename;
+
+ file_source_info
+ = find_file_source_info (files_source_info,
+ node_filename);
+ if (file_source_info)
+ {
+ if (!strcmp (file_source_info->type,
+ "stand_in_file"))
+ {/* NOTE we keep the order, as in perl */
+ set_file_source_info (file_source_info,
+ "node",
+ 0, root_command, 0);
+ }
+ }
+ else
+ add_to_files_source_info (files_source_info,
+ node_filename, "node", 0,
+ root_command, 0);
+ }
+ output_unit_file_name
+ = add_to_unit_file_name_paths (unit_file_name_paths,
+ node_filename,
+ file_output_unit);
+ break;
+ }
+ }
+ if (!node_filename)
+ {
+ /* use section to do the file name if there is no node */
+ const ELEMENT *command = file_output_unit->unit_command;
+ if (command)
+ {
+ if (command->cmd == CM_top && !node_top
+ && top_node_filename_str)
+ {
+ /* existing top_node_filename can happen, see
+ html_tests.t top_file_name_and_node_name_collision */
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info,
+ top_node_filename_str);
+ if (file_source_info)
+ {/* NOTE we keep the order, as in perl */
+ set_file_source_info (file_source_info,
+ "special_file", "Top",
+ 0, 0);
+ }
+ else
+ {
+ add_to_files_source_info (files_source_info,
+ top_node_filename_str,
+ "special_file", "Top",
+ 0, 0);
+ }
+ output_unit_file_name
+ = add_to_unit_file_name_paths (unit_file_name_paths,
+
top_node_filename_str,
+ file_output_unit);
+ }
+ else
+ {
+ HTML_TARGET *section_target
+ = find_element_target (&self->html_targets,
+ command);
+ char *section_filename
+ = section_target->section_filename;
+
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info,
+ section_filename);
+ if (file_source_info)
+ {
+ if (!strcmp (file_source_info->type,
+ "stand_in_file"))
+ {/* NOTE we keep the order, as in perl */
+ set_file_source_info (file_source_info,
+ "section",
+ 0, command, 0);
+ }
+ }
+ else
+ add_to_files_source_info (files_source_info,
+ section_filename, "section",
0,
+ command, 0);
+ output_unit_file_name
+ = add_to_unit_file_name_paths
(unit_file_name_paths,
+ section_filename,
+ file_output_unit);
+ }
+ }
+ else
+ {
+ /* when everything else has failed */
+ if (file_nr == 0 && !node_top
+ && top_node_filename_str)
+ {
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info,
+ top_node_filename_str);
+ if (!file_source_info)
+ {
+ add_to_files_source_info (files_source_info,
+ top_node_filename_str,
+ "stand_in_file", "Top",
+ 0, 0);
+ }
+ output_unit_file_name
+ = add_to_unit_file_name_paths (unit_file_name_paths,
+ top_node_filename_str,
+ file_output_unit);
+ }
+ else
+ {
+ FILE_SOURCE_INFO *file_source_info;
+
+ TEXT file_name_text;
+ text_init (&file_name_text);
+ text_printf (&file_name_text, "%s_%d", document_name,
+ file_nr);
+ if (extension)
+ {
+ text_append (&file_name_text, ".");
+ text_append (&file_name_text, extension);
+ }
+ file_source_info
+ = find_file_source_info (files_source_info,
+ file_name_text.text);
+ if (!file_source_info)
+ {
+ add_to_files_source_info (files_source_info,
+ file_name_text.text,
+ "stand_in_file",
+ "unknown",
+ 0, 0);
+ }
+ output_unit_file_name
+ = add_to_unit_file_name_paths (unit_file_name_paths,
+ file_name_text.text,
+ file_output_unit);
+ free (file_name_text.text);
+ }
+ file_nr++;
+ }
+ }
+ }
+ if (output_unit != file_output_unit)
+ add_to_unit_file_name_paths (unit_file_name_paths,
+ output_unit_file_name,
+ output_unit);
+ }
+ free (top_node_filename_str);
+ }
+
+ self->output_unit_file_indices = (size_t *)
+ malloc (output_units->number * sizeof (size_t));
+
+ for (i = 0; i < output_units->number; i++)
+ {
+ size_t output_unit_file_idx = 0;
+ FILE_NAME_PATH_COUNTER *output_unit_file;
+ OUTPUT_UNIT *output_unit = output_units->list[i];
+ char *output_unit_file_name = unit_file_name_paths[i];
+ char *filename = strdup (output_unit_file_name);
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info, output_unit_file_name);
+ char *filepath = file_source_info->path;
+
+ FILE_NAME_PATH *file_name_path
+ = call_file_id_setting_unit_file_name (self, output_unit,
+ output_unit_file_name, filepath);
+ if (file_name_path)
+ {
+ if (file_name_path->filename)
+ {
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info,
+ file_name_path->filename);
+ if (file_source_info)
+ {
+ if (file_source_info->path && file_name_path->filepath
+ && strcmp (file_source_info->path,
+ file_name_path->filepath))
+ {
+ message_list_document_warn (&self->error_messages,
+ self->conf,
+ "resetting %s file path %s to %s",
+ file_name_path->filename,
+ file_source_info->path,
+ file_name_path->filepath);
+ }
+ set_file_source_info (file_source_info, "special_file",
+ "user_defined", 0, file_name_path->filepath);
+ }
+ else
+ add_to_files_source_info (files_source_info,
+ file_name_path->filename,
+ "special_file", "user_defined",
+ 0, file_name_path->filepath);
+ free (filename);
+ filename = file_name_path->filename;
+ }
+ free (file_name_path);
+ }
+ output_unit_file_idx
+ = set_output_unit_file (self, output_unit, filename, 1);
+ self->output_unit_file_indices[i] = output_unit_file_idx;
+ output_unit_file = &self->output_unit_files.list[output_unit_file_idx];
+ if (self->conf->DEBUG > 0)
+ fprintf (stderr, "Page %s: %s(%d)\n",
+ output_unit_texi (output_unit),
+ output_unit->unit_filename, output_unit_file->counter);
+ free (filename);
+ free (output_unit_file_name);
+ }
+
+ free (unit_file_name_paths);
+
+ if (special_units && special_units->number)
+ {
+ int i;
+ self->special_unit_file_indices = (size_t *)
+ malloc (special_units->number * sizeof (size_t));
+ for (i = 0; i < special_units->number; i++)
+ {
+ size_t special_unit_file_idx = 0;
+ FILE_NAME_PATH_COUNTER *special_unit_file;
+ OUTPUT_UNIT *special_unit = special_units->list[i];
+ const ELEMENT *unit_command = special_unit->unit_command;
+ const HTML_TARGET *special_unit_target
+ = find_element_target (&self->html_targets, unit_command);
+ char *filename = special_unit_target->special_unit_filename;
+
+ /* Associate the special elements that have no page with the main page.
+ This may only happen if not split. */
+ if (!filename && special_units->number
+ && output_units && output_units->number
+ && output_units->list[0]->unit_filename)
+ {
+ filename = output_units->list[0]->unit_filename;
+ }
+
+ if (filename)
+ {
+ FILE_SOURCE_INFO *file_source_info
+ = find_file_source_info (files_source_info, filename);
+ if (file_source_info)
+ {
+ if (!strcmp (file_source_info->type, "stand_in_file"))
+ {/* NOTE we keep the order, as in perl */
+ set_file_source_info (file_source_info, "special_unit",
+ 0, unit_command, 0);
+ }
+ }
+ else
+ add_to_files_source_info (files_source_info, filename,
+ "special_unit", 0, unit_command, 0);
+ }
+ special_unit_file_idx
+ = set_output_unit_file (self, special_unit, filename, 1);
+ self->special_unit_file_indices[i] = special_unit_file_idx;
+ special_unit_file
+ = &self->output_unit_files.list[special_unit_file_idx];
+ if (self->conf->DEBUG > 0)
+ fprintf (stderr, "Special page: %s(%d)\n", filename,
+ special_unit_file->counter);
+ }
+ }
+
+ for (i = 0; i < files_source_info->number; i++)
+ {
+ FILE_SOURCE_INFO *file_source_info = &files_source_info->list[i];
+ set_file_path (self, file_source_info->filename, file_source_info->path,
+ destination_directory);
+ }
+
+ /*
+ to be able to associate to the output unit file the associated
+ output units will be output into, this is done after document output
+ units got files.
+ In practice only used for contents and shortcontents.
+ */
+ if (associated_special_units && associated_special_units->number > 0)
+ {
+ int i;
+ for (i = 0; i < associated_special_units->number; i++)
+ {
+ char *filename = 0;
+ OUTPUT_UNIT *special_unit = associated_special_units->list[i];
+ const OUTPUT_UNIT *associated_output_unit
+ = special_unit->associated_document_unit;
+ const ELEMENT *unit_command = special_unit->unit_command;
+ HTML_TARGET *element_target
+ = find_element_target (&self->html_targets, unit_command);
+
+ if (element_target->special_unit_filename)
+ filename = element_target->special_unit_filename;
+ else
+ {
+ if (associated_output_unit)
+ filename = strdup (associated_output_unit->unit_filename);
+ element_target->special_unit_filename = filename;
+ }
+
+ /* set here the file name, but do not increment the counter as it is
+ already set for the output unit the special output unit is in. */
+ if (filename)
+ set_output_unit_file (self, special_unit, filename, 0);
+ }
+ }
+
+ /* initialize data that requires output_unit_files number */
+ self->file_changed_counter.list = (size_t *)
+ malloc (self->output_unit_files.number * sizeof (size_t));
+ memset (self->file_changed_counter.list, 0,
+ self->output_unit_files.number * sizeof (size_t));
+
+ /* 0 is for document_global_context_css, the remaining indices
+ for the output unit files */
+ self->page_css.number = self->output_unit_files.number +1;
+ self->page_css.list = (CSS_LIST *)
+ malloc (self->page_css.number * sizeof (CSS_LIST));
+ memset (self->page_css.list, 0,
+ self->page_css.number * sizeof (CSS_LIST));
+
+ return files_source_info;
+}
+
+/* setup a page (+global context) in case there are no files, ie called
+ with convert or output with an empty string as filename. */
+void
+setup_output_simple_page (CONVERTER *self, const char *output_filename)
+{
+ PAGE_NAME_NUMBER *page_name_number;
+ self->page_css.number = 1+1;
+ self->page_css.list = (CSS_LIST *)
+ malloc (self->page_css.number * sizeof (CSS_LIST));
+ memset (self->page_css.list, 0,
+ self->page_css.number * sizeof (CSS_LIST));
+
+ self->page_name_number.number = 1;
+ self->page_name_number.list = (PAGE_NAME_NUMBER *)
+ malloc (self->page_name_number.number * sizeof (PAGE_NAME_NUMBER));
+
+ page_name_number = &self->page_name_number.list[0];
+ page_name_number->number = 1;
+ page_name_number->page_name = output_filename;
+}
+
+static void
+prepare_special_units_directions (CONVERTER *self,
+ OUTPUT_UNIT_LIST *special_units)
+{
+ int i;
+
+ if (!special_units)
+ return;
+
+ for (i = 0; i < special_units->number; i++)
+ {
+ OUTPUT_UNIT *special_unit = special_units->list[i];
+ special_unit->directions[RUD_type_This] = special_unit;
+ }
+}
+
+FILE_SOURCE_INFO_LIST *
+html_prepare_units_directions_files (CONVERTER *self,
+ int output_units_descriptor,
+ int special_units_descriptor, int
associated_special_units_descriptor,
+ char *output_file, char *destination_directory, char
*output_filename,
+ char *document_name)
+{
+ int i;
+ FILE_SOURCE_INFO_LIST *files_source_info = 0;
+ OUTPUT_UNIT_LIST *output_units
+ = retrieve_output_units (output_units_descriptor);
+ OUTPUT_UNIT_LIST *special_units
+ = retrieve_output_units (special_units_descriptor);
+ OUTPUT_UNIT_LIST *associated_special_units
+ = retrieve_output_units (associated_special_units_descriptor);
+
+ html_prepare_output_units_global_targets (self, output_units_descriptor,
+ special_units_descriptor,
+ associated_special_units_descriptor);
+
+ split_pages (output_units, self->conf->SPLIT);
+
+ if (strlen (output_file))
+ {
+ files_source_info =
+ html_set_pages_files (self, output_units, special_units,
+ associated_special_units, output_file,
+ destination_directory, output_filename, document_name);
+ }
+ else
+ setup_output_simple_page (self, output_filename);
+
+
+ units_directions (self->conf, self->document->identifiers_target,
+ output_units);
+
+ prepare_special_units_directions (self, special_units);
+
+ units_file_directions (output_units);
+
+ /* elements_in_file_count is only set in HTML, not in
+ Texinfo::Convert::Converter */
+ if (self->output_unit_files.number)
+ {
+ /* set elements_in_file_count and prepare page_name_number
+ for sorting */
+ self->page_name_number.number = self->output_unit_files.number;
+ self->page_name_number.list = (PAGE_NAME_NUMBER *)
+ malloc (self->page_name_number.number * sizeof (PAGE_NAME_NUMBER));
+
+ for (i = 0; i < self->output_unit_files.number; i++)
+ {
+ FILE_NAME_PATH_COUNTER *file_counter
+ = &self->output_unit_files.list[i];
+ PAGE_NAME_NUMBER *page_name_number = &self->page_name_number.list[i];
+
+ /* counter is dynamic, decreased when the element is encountered
+ elements_in_file_count is not modified afterwards */
+ file_counter->elements_in_file_count = file_counter->counter;
+
+ page_name_number->number = i+1;
+ page_name_number->page_name = file_counter->filename;
+ }
+
+ qsort (self->page_name_number.list,
+ self->page_name_number.number,
+ sizeof (PAGE_NAME_NUMBER), compare_page_name_number);
+ }
+
+ return files_source_info;
+}
+
+void
+convert_text (CONVERTER *self, const enum element_type type,
+ const ELEMENT *element, const char *content,
+ TEXT *result)
+{
+ char *content_used;
+ int contents_used_to_be_freed = 0;
+
+ if (html_in_verbatim (self))
+ {
+ /* do not use the customization API as in perl */
+ html_default_format_protect_text (content, result);
+ return;
+ }
+ else if (html_in_raw (self))
+ {
+ text_append (result, content);
+ return;
+ }
+
+ if (html_in_upper_case (self))
+ {
+ content_used = to_upper_or_lower_multibyte (content, 1);
+ contents_used_to_be_freed = 1;
+ }
+ else
+ /* cast needed to avoid a compiler warning */
+ content_used = (char *) content;
+
+ if (html_in_preformatted_context (self))
+ {
+ OTXI_ALL_CONVERT_TEXT ( , )
+ }
+ else if (html_in_non_breakable_space (self))
+ {
+ OTXI_ALL_CONVERT_TEXT (" \n", OTXI_NO_BREAK_CASES(p))
+ }
+ else if (html_in_space_protected (self))
+ {
+ OTXI_ALL_CONVERT_TEXT (" \n", OTXI_SPACE_PROTECTION_CASES(p))
+ }
+ else
+ {
+ OTXI_ALL_CONVERT_TEXT ( , )
+ }
+
+ if (contents_used_to_be_freed)
+ free (content_used);
+}
+
+void
+default_format_footnotes_segment (CONVERTER *self, TEXT *result)
+{
+ char *class_base;
+ char *attribute_class;
+ char *class;
+ STRING_LIST *classes;
+ ELEMENT *footnote_heading_tree;
+ char *footnote_heading;
+ int level;
+ char *formatted_heading;
+ char *foot_lines = call_formatting_function_format_footnotes_sequence (self);
+
+ if (!foot_lines || !strlen (foot_lines))
+ {
+ free (foot_lines);
+ return;
+ }
+
+ classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (classes, 0, sizeof (STRING_LIST));
+
+ class_base = special_unit_info (self, SUI_type_class,
+ "footnotes");
+ xasprintf (&class, "%s-segment", class_base);
+
+ add_string (class, classes);
+ free (class);
+ attribute_class = html_attribute_class (self, "div", classes);
+ clear_strings_list (classes);
+
+ text_append (result, attribute_class);
+ free (attribute_class);
+
+ text_append_n (result, ">\n", 2);
+
+ if (self->conf->DEFAULT_RULE && strlen (self->conf->DEFAULT_RULE))
+ {
+ text_append (result, self->conf->DEFAULT_RULE);
+ text_append_n (result, "\n", 1);
+ }
+
+ footnote_heading_tree = special_unit_info_tree (self,
+ SUIT_type_heading, "footnotes");
+ if (footnote_heading_tree)
+ {
+ footnote_heading = html_convert_tree (self, footnote_heading_tree,
+ "convert footnotes special heading");
+ }
+ else
+ {
+ footnote_heading = "";
+ }
+
+ level = self->conf->FOOTNOTE_END_HEADER_LEVEL;
+
+ xasprintf (&class, "%s-heading", class_base);
+
+ add_string (class, classes);
+ free (class);
+
+ formatted_heading
+ = call_formatting_function_format_heading_text (self, 0, classes,
+ footnote_heading,
+ level, 0, 0, 0);
+ destroy_strings_list (classes);
+ text_append (result, formatted_heading);
+ text_append_n (result, "\n", 1);
+
+ free (formatted_heading);
+
+ if (footnote_heading_tree)
+ free (footnote_heading);
+
+ text_append (result, foot_lines);
+ free (foot_lines);
+ text_append (result, "</div>\n");
+}
+
+void
+format_footnotes_segment (CONVERTER *self, TEXT *result)
+{
+ if (self->formatting_references[FR_format_footnotes_segment].status
+ == FRS_status_default_set)
+ {
+ default_format_footnotes_segment (self, result);
+ }
+ else
+ {
+ char *footnotes_segment
+ = call_formatting_function_format_footnotes_segment (self);
+ if (footnotes_segment)
+ {
+ text_append (result, footnotes_segment);
+ free (footnotes_segment);
}
}
+}
- for (i = 0; i < files_source_info->number; i++)
+void
+convert_table_term_type (CONVERTER *self, const enum element_type type,
+ const ELEMENT *element, const char *content,
+ TEXT *result)
+{
+ if (content)
{
- FILE_SOURCE_INFO *file_source_info = &files_source_info->list[i];
- set_file_path (self, file_source_info->filename, file_source_info->path,
- destination_directory);
+ text_append (result, "<dt>");
+ text_append (result, content);
}
+}
- /*
- to be able to associate to the output unit file the associated
- output units will be output into, this is done after document output
- units got files.
- In practice only used for contents and shortcontents.
- */
- if (associated_special_units && associated_special_units->number > 0)
+void
+convert_row_type (CONVERTER *self, const enum element_type type,
+ const ELEMENT *element, const char *content,
+ TEXT *result)
+{
+ if (html_in_string (self))
{
- int i;
- for (i = 0; i < associated_special_units->number; i++)
- {
- char *filename = 0;
- OUTPUT_UNIT *special_unit = associated_special_units->list[i];
- const OUTPUT_UNIT *associated_output_unit
- = special_unit->associated_document_unit;
- const ELEMENT *unit_command = special_unit->unit_command;
- HTML_TARGET *element_target
- = find_element_target (&self->html_targets, unit_command);
-
- if (element_target->special_unit_filename)
- filename = element_target->special_unit_filename;
- else
- {
- if (associated_output_unit)
- filename = strdup (associated_output_unit->unit_filename);
- element_target->special_unit_filename = filename;
- }
-
- /* set here the file name, but do not increment the counter as it is
- already set for the output unit the special output unit is in. */
- if (filename)
- set_output_unit_file (self, special_unit, filename, 0);
- }
+ if (content)
+ text_append (result, content);
}
- /* initialize data that requires output_unit_files number */
- self->file_changed_counter.list = (size_t *)
- malloc (self->output_unit_files.number * sizeof (size_t));
- memset (self->file_changed_counter.list, 0,
- self->output_unit_files.number * sizeof (size_t));
-
- /* 0 is for document_global_context_css, the remaining indices
- for the output unit files */
- self->page_css.number = self->output_unit_files.number +1;
- self->page_css.list = (CSS_LIST *)
- malloc (self->page_css.number * sizeof (CSS_LIST));
- memset (self->page_css.list, 0,
- self->page_css.number * sizeof (CSS_LIST));
+ if (!content || content[strspn (content, whitespace_chars)] == '\0')
+ return;
+ else
+ {
+ text_append (result, "<tr>");
+ text_append (result, content);
+ text_append (result, "</tr>");
- return files_source_info;
+ if (element->contents.number > 0
+ && element->contents.list[0]->cmd != CM_headitem)
+ /* if headitem, end of line added in _convert_multitable_head_type */
+ text_append (result, "\n");
+ }
}
-/* setup a page (+global context) in case there are no files, ie called
- with convert or output with an empty string as filename. */
void
-setup_output_simple_page (CONVERTER *self, const char *output_filename)
+convert_w_command (CONVERTER *self, const enum command_id cmd,
+ const ELEMENT *element,
+ const HTML_ARGS_FORMATTED *args_formatted,
+ const char *content, TEXT *result)
{
- PAGE_NAME_NUMBER *page_name_number;
- self->page_css.number = 1+1;
- self->page_css.list = (CSS_LIST *)
- malloc (self->page_css.number * sizeof (CSS_LIST));
- memset (self->page_css.list, 0,
- self->page_css.number * sizeof (CSS_LIST));
-
- self->page_name_number.number = 1;
- self->page_name_number.list = (PAGE_NAME_NUMBER *)
- malloc (self->page_name_number.number * sizeof (PAGE_NAME_NUMBER));
-
- page_name_number = &self->page_name_number.list[0];
- page_name_number->number = 1;
- page_name_number->page_name = output_filename;
+ if (args_formatted && args_formatted->number > 0)
+ {
+ if (args_formatted->args[0].formatted[AFT_type_normal])
+ text_append (result,
+ args_formatted->args[0].formatted[AFT_type_normal]);
+ }
+ if (!html_in_string (self))
+ {
+ text_append (result, "<!-- /@w -->");
+ }
}
-static void
-prepare_special_units_directions (CONVERTER *self,
- OUTPUT_UNIT_LIST *special_units)
+static char *
+contents_inline_element (CONVERTER *self, const enum command_id cmd,
+ const ELEMENT *command)
{
- int i;
+ char *content;
- if (!special_units)
- return;
+ if (self->conf->DEBUG > 0)
+ fprintf (stderr, "CONTENTS_INLINE %s\n", builtin_command_name (cmd));
- for (i = 0; i < special_units->number; i++)
+ content = call_formatting_function_format_contents (self,
+ builtin_command_name (cmd), command, 0);
+ if (content && strlen (content))
{
- OUTPUT_UNIT *special_unit = special_units->list[i];
- special_unit->directions[RUD_type_This] = special_unit;
- }
-}
+ int j;
+ for (j = 0; self->command_special_variety_name_index[j].cmd; j++)
+ {
+ COMMAND_ID_INDEX cmd_variety_index
+ = self->command_special_variety_name_index[j];
+ if (cmd_variety_index.cmd == cmd)
+ {
+ char *heading = 0;
+ char *formatted_heading;
+ TEXT result;
+ STRING_LIST *classes;
+ char *class_base;
+ char *class;
+ char *attribute_class;
+
+ char *special_unit_variety
+ = self->special_unit_varieties.list[cmd_variety_index.index];
+ int special_unit_direction_index
+ = special_unit_variety_direction_index (self,
+ special_unit_variety);
+ const OUTPUT_UNIT *special_unit
+ = self->global_units_directions[special_unit_direction_index];
-FILE_SOURCE_INFO_LIST *
-html_prepare_units_directions_files (CONVERTER *self,
- int output_units_descriptor,
- int special_units_descriptor, int
associated_special_units_descriptor,
- char *output_file, char *destination_directory, char
*output_filename,
- char *document_name)
-{
- int i;
- FILE_SOURCE_INFO_LIST *files_source_info = 0;
- OUTPUT_UNIT_LIST *output_units
- = retrieve_output_units (output_units_descriptor);
- OUTPUT_UNIT_LIST *special_units
- = retrieve_output_units (special_units_descriptor);
- OUTPUT_UNIT_LIST *associated_special_units
- = retrieve_output_units (associated_special_units_descriptor);
+ text_init (&result);
- html_prepare_output_units_global_targets (self, output_units_descriptor,
- special_units_descriptor,
- associated_special_units_descriptor);
+ classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (classes, 0, sizeof (STRING_LIST));
- split_pages (output_units, self->conf->SPLIT);
+ class_base = special_unit_info (self, SUI_type_class,
+ special_unit_variety);
+ xasprintf (&class, "element-%s", class_base);
- if (strlen (output_file))
- {
- files_source_info =
- html_set_pages_files (self, output_units, special_units,
- associated_special_units, output_file,
- destination_directory, output_filename, document_name);
- }
- else
- setup_output_simple_page (self, output_filename);
+ add_string (class, classes);
+ free (class);
+ attribute_class = html_attribute_class (self, "div", classes);
+ clear_strings_list (classes);
+ text_append (&result, attribute_class);
+ free (attribute_class);
- units_directions (self->conf, self->document->identifiers_target,
- output_units);
+ if (special_unit)
+ {
+ ELEMENT *command = special_unit->unit_command;
+ char *id = html_command_id (self, command);
+ if (id && strlen (id))
+ text_printf (&result, " id=\"%s\"", id);
+ heading = html_command_text (self, command, 0);
+ if (!heading)
+ heading = strdup ("");
+ }
+ else
+ { /* happens when called as convert() and not output() */
+ ELEMENT *heading_tree = special_unit_info_tree (self,
+ SUIT_type_heading, special_unit_variety);
+ if (heading_tree)
+ {
+ char *explanation;
+ xasprintf (&explanation, "convert %s special heading",
+ builtin_command_name (cmd));
+ heading = html_convert_tree (self, heading_tree,
+ explanation);
+ free (explanation);
+ }
+ }
+ text_append_n (&result, ">\n", 2);
- prepare_special_units_directions (self, special_units);
+ xasprintf (&class, "%s-heading", class_base);
- units_file_directions (output_units);
+ add_string (class, classes);
+ free (class);
- /* elements_in_file_count is only set in HTML, not in
- Texinfo::Convert::Converter */
- if (self->output_unit_files.number)
- {
- /* set elements_in_file_count and prepare page_name_number
- for sorting */
- self->page_name_number.number = self->output_unit_files.number;
- self->page_name_number.list = (PAGE_NAME_NUMBER *)
- malloc (self->page_name_number.number * sizeof (PAGE_NAME_NUMBER));
+ formatted_heading
+ = call_formatting_function_format_heading_text (self, 0,
classes,
+ heading, self->conf->CHAPTER_HEADER_LEVEL, 0, 0,
0);
+ destroy_strings_list (classes);
- for (i = 0; i < self->output_unit_files.number; i++)
- {
- FILE_NAME_PATH_COUNTER *file_counter
- = &self->output_unit_files.list[i];
- PAGE_NAME_NUMBER *page_name_number = &self->page_name_number.list[i];
+ free (heading);
- /* counter is dynamic, decreased when the element is encountered
- elements_in_file_count is not modified afterwards */
- file_counter->elements_in_file_count = file_counter->counter;
+ text_append (&result, formatted_heading);
+ free (formatted_heading);
+ text_append_n (&result, "\n", 1);
- page_name_number->number = i+1;
- page_name_number->page_name = file_counter->filename;
- }
+ text_append (&result, content);
+ text_append_n (&result, "</div>\n", 7);
- qsort (self->page_name_number.list,
- self->page_name_number.number,
- sizeof (PAGE_NAME_NUMBER), compare_page_name_number);
+ free (content);
+ return result.text;
+ }
+ }
}
-
- return files_source_info;
+ return 0;
}
+/* Output a list of the nodes immediately below this one */
void
-convert_text (CONVERTER *self, const enum element_type type,
- const ELEMENT *element, const char *content,
- TEXT *result)
+mini_toc_internal (CONVERTER *self, const ELEMENT *element, TEXT *result)
{
- char *content_used;
- int contents_used_to_be_freed = 0;
+ int entry_index = 0;
- if (html_in_verbatim (self))
- {
- html_default_format_protect_text (content, result);
- return;
- }
- else if (html_in_raw (self))
+ /* drop the const with a cast, but we know that it is not modified, with
+ 0 as the third argument */
+ ELEMENT_LIST *section_childs = lookup_extra_contents ((ELEMENT *) element,
+ "section_childs", 0);
+ if (section_childs && section_childs->number > 0)
{
- text_append (result, content);
- return;
+ STRING_LIST *classes;
+ char *attribute_class;
+ size_t i;
+
+ classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (classes, 0, sizeof (STRING_LIST));
+ add_string ("mini-toc", classes);
+ attribute_class = html_attribute_class (self, "ul", classes);
+ destroy_strings_list (classes);
+
+ text_append (result, attribute_class);
+ free (attribute_class);
+ text_append_n (result, ">\n", 2);
+
+ for (i = 0; i < section_childs->number; i++)
+ {
+ ELEMENT *section = section_childs->list[i];
+ /* using command_text leads to the same HTML formatting, but does not give
+ the same result for the other files, as the formatting is done in a
+ global context, while taking the tree first and calling convert_tree
+ converts in the current page context.
+ text = html_command_text(self, section, HCTT_text_nonumber);
+ */
+ TREE_ADDED_ELEMENTS *command_tree
+ = html_command_tree (self, section, 1);
+ char *explanation;
+ char *accesskey;
+ char *text;
+ char *href = html_command_href (self, section, 0, 0, 0);
+
+ xasprintf (&explanation, "mini_toc @%s",
+ element_command_name (section));
+ text = html_convert_tree (self, command_tree->tree, explanation);
+ free (explanation);
+
+ entry_index++;
+
+ if (self->conf->USE_ACCESSKEY > 0 && entry_index < 10)
+ {
+ xasprintf (&accesskey, " accesskey=\"%d\"", entry_index);
+ }
+ else
+ accesskey = strdup ("");
+
+ if (strlen (text))
+ {
+ if (strlen (href))
+ {
+ text_printf (result, "<li><a href=\"%s\"%s>%s</a>",
+ href, accesskey, text);
+ }
+ else
+ text_printf (result, "<li>%s", text);
+
+ text_append_n (result, "</li>\n", 6);
+ }
+ free (text);
+ free (href);
+ free (accesskey);
+ }
+ text_append_n (result, "</ul>\n", 6);
}
+}
- if (html_in_upper_case (self))
+void
+convert_heading_command (CONVERTER *self, const enum command_id cmd,
+ const ELEMENT *element,
+ const HTML_ARGS_FORMATTED *args_formatted,
+ const char *content, TEXT *result)
+{
+ char *element_id;
+ OUTPUT_UNIT *output_unit = 0;
+ char *element_header = 0;
+ /* could use only one, but this is more similar to perl code */
+ TEXT tables_of_contents;
+ TEXT mini_toc_or_auto_menu;
+ enum command_id level_corrected_cmd;
+ int status;
+ char *heading;
+ int heading_level = -1;
+ int do_heading;
+ char *heading_id = 0;
+ char *level_set_class = 0;
+
+ const ELEMENT *opening_section = 0;
+ enum command_id level_corrected_opening_section_cmd = 0;
+
+ enum command_id data_cmd = element_builtin_data_cmd (element);
+ unsigned long flags = builtin_command_data[data_cmd].flags;
+
+ /* No situation where this could happen */
+ if (html_in_string (self))
{
- content_used = to_upper_or_lower_multibyte (content, 1);
- contents_used_to_be_freed = 1;
+ if (element->cmd != CM_node)
+ {
+ char *heading = html_command_text (self, element, HCTT_string);
+ text_append (result, heading);
+ text_append_n (result, "\n", 1);
+ free (heading);
+ }
+ if (content)
+ text_append (result, content);
+ return;
}
- else
- /* cast needed to avoid a compiler warning */
- content_used = (char *) content;
- if (html_in_preformatted_context (self))
+ element_id = html_command_id (self, element);
+
+ if (self->conf->DEBUG > 0)
+ fprintf (stderr, "CONVERT elt heading %s\n",
+ root_heading_command_to_texinfo (element));
+
+ if (flags & CF_root && element->associated_unit)
+ output_unit = element->associated_unit;
+
+ if (output_unit)
+ element_header
+ = call_formatting_function_format_element_header (self,
+ element_command_name (element),
+ element, output_unit);
+ text_init (&tables_of_contents);
+ text_append (&tables_of_contents, "");
+ if (element->cmd == CM_top
+ && !strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "after_top")
+ && self->document->sections_list
+ && self->document->sections_list->number > 1)
{
- OTXI_ALL_CONVERT_TEXT ( , )
+ enum command_id contents_cmds[2] = {CM_shortcontents, CM_contents};
+ int i;
+ for (i = 0; i < 2; i++)
+ {
+ int contents_set = 0;
+ enum command_id cmd = contents_cmds[i];
+ COMMAND_OPTION_REF *contents_option_ref
+ = get_command_option (self->conf, cmd);
+ if (*(contents_option_ref->int_ref) > 0)
+ contents_set = 1;
+ free (contents_option_ref);
+ if (contents_set)
+ {
+ char *contents_text
+ = contents_inline_element (self, cmd, 0);
+ if (contents_text)
+ {
+ text_append (&tables_of_contents, contents_text);
+ free (contents_text);
+ }
+ }
+ }
}
- else if (html_in_non_breakable_space (self))
+
+ text_init (&mini_toc_or_auto_menu);
+ text_append (&mini_toc_or_auto_menu, "");
+ if (tables_of_contents.end <= 0
+ && (flags & CF_sectioning_heading))
{
- OTXI_ALL_CONVERT_TEXT (" \n", OTXI_NO_BREAK_CASES(p))
+ if (!strcmp (self->conf->FORMAT_MENU, "sectiontoc"))
+ {
+ mini_toc_internal (self, element, &mini_toc_or_auto_menu);
+ }
+ else if (!strcmp (self->conf->FORMAT_MENU, "menu"))
+ {
+ ELEMENT *node
+ = lookup_extra_element (element, "associated_node");
+ if (node)
+ {
+ int automatic_directions = (node->args.number <= 1);
+ ELEMENT_LIST *menus = lookup_extra_contents (node, "menus", 0);
+ if (!menus && automatic_directions)
+ {
+ ELEMENT *menu_node
+ = new_complete_menu_master_menu (self->conf,
+ self->document->identifiers_target, node);
+
+ /* FIXME probably need to rebuild menu_node tree */
+ if (menu_node)
+ {
+ convert_to_html_internal (self, menu_node,
+ &mini_toc_or_auto_menu, 0);
+ }
+ }
+ }
+ }
}
- else if (html_in_space_protected (self))
+
+ if (self->conf->NO_TOP_NODE_OUTPUT > 0
+ && builtin_command_data[cmd].flags & CF_root)
{
- OTXI_ALL_CONVERT_TEXT (" \n", OTXI_SPACE_PROTECTION_CASES(p))
+ const ELEMENT *node_element = 0;
+ int *in_skipped_node_top
+ = get_shared_conversion_state_integer (self, "in_skipped_node_top", 0);
+
+ if (cmd == CM_node)
+ node_element = element;
+ else if (cmd == CM_part)
+ {
+ ELEMENT *part_following_node
+ = lookup_extra_element (element, "part_following_node");
+ if (part_following_node)
+ node_element = part_following_node;
+ }
+ if (node_element || cmd == CM_part)
+ {
+ int node_is_top = 0;
+ if (node_element)
+ {
+ char *normalized = lookup_extra_string (node_element,
+ "normalized");
+ if (normalized && !strcmp (normalized, "Top"))
+ {
+ node_is_top = 1;
+ *in_skipped_node_top = 1;
+ register_modified_shared_conversion_state_integer (self,
+ "in_skipped_node_top");
+ }
+ }
+ if (!node_is_top && *in_skipped_node_top == 1)
+ {
+ *in_skipped_node_top = -1;
+ register_modified_shared_conversion_state_integer (self,
+ "in_skipped_node_top");
+ }
+ }
+ if (*in_skipped_node_top == 1)
+ {
+ char *anchor
+ = call_formatting_function_format_separate_anchor (self,
+ element_id, builtin_command_name(cmd));
+ text_append (result, anchor);
+ free (anchor);
+ text_append (result, element_header);
+ free (element_header);
+ text_append (result, tables_of_contents.text);
+ free (tables_of_contents.text);
+ text_append (result, mini_toc_or_auto_menu.text);
+ free (mini_toc_or_auto_menu.text);
+ return;
+ }
}
- else
+
+ lookup_extra_integer (element, "section_level", &status);
+ level_corrected_cmd = cmd;
+ if (status >= 0)
{
- OTXI_ALL_CONVERT_TEXT ( , )
+ /* if the level was changed, use a consistent command name */
+ level_corrected_cmd = section_level_adjusted_command_name (element);
+ if (level_corrected_cmd != cmd)
+ {
+ xasprintf (&level_set_class, "%s-level-set-%s",
+ builtin_command_name(cmd),
+ builtin_command_name (level_corrected_cmd));
+ }
}
- if (contents_used_to_be_freed)
- free (content_used);
-}
-
-void
-default_format_footnotes_segment (CONVERTER *self, TEXT *result)
-{
- char *class_base;
- char *attribute_class;
- char *class;
- STRING_LIST *classes;
- ELEMENT *footnote_heading_tree;
- char *footnote_heading;
- int level;
- char *formatted_heading;
- char *foot_lines = call_formatting_function_format_footnotes_sequence (self);
+ /* find the section starting here, can be through the associated node
+ preceding the section, or the section itself */
- if (!foot_lines || !strlen (foot_lines))
+ if (cmd == CM_node)
{
- free (foot_lines);
- return;
+ opening_section
+ = lookup_extra_element (element, "associated_section");
+ if (opening_section)
+ level_corrected_opening_section_cmd
+ = section_level_adjusted_command_name (opening_section);
}
+ else
+ {
+ ELEMENT *associated_node
+ = lookup_extra_element (element, "associated_node");
- classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
- memset (classes, 0, sizeof (STRING_LIST));
-
- class_base = special_unit_info (self, SUI_type_class,
- "footnotes");
- xasprintf (&class, "%s-segment", class_base);
-
- add_string (class, classes);
- free (class);
- attribute_class = html_attribute_class (self, "div", classes);
- clear_strings_list (classes);
+ /* if there is an associated node, it is not a section opening
+ the section was opened before when the node was encountered */
+ if (!associated_node
+ /* to avoid *heading* @-commands */
+ && (builtin_command_data[cmd].flags & CF_root))
+ {
+ opening_section = element;
+ level_corrected_opening_section_cmd = level_corrected_cmd;
+ }
+ }
- text_append (result, attribute_class);
- free (attribute_class);
+ /*
+ could use empty args information also, to avoid calling command_text
+ my $empty_heading = (!scalar(@$args) or !defined($args->[0]));
+ */
- text_append_n (result, ">\n", 2);
- if (self->conf->DEFAULT_RULE && strlen (self->conf->DEFAULT_RULE))
- {
- text_append (result, self->conf->DEFAULT_RULE);
- text_append_n (result, "\n", 1);
- }
+ /* heading not defined may happen if the command is a @node, for example
+ if there is an error in the node. */
+ heading = html_command_text (self, element, 0);
- footnote_heading_tree = special_unit_info_tree (self,
- SUIT_type_heading, "footnotes");
- if (footnote_heading_tree)
+ if (cmd == CM_node)
{
- footnote_heading = html_convert_tree (self, footnote_heading_tree,
- "convert footnotes special heading");
+ ELEMENT *associated_section
+ = lookup_extra_element (element, "associated_section");
+ char *normalized = lookup_extra_string (element, "normalized");
+ if ((!output_unit
+ || (output_unit->unit_command
+ && output_unit->unit_command == element
+ && !associated_section))
+ && normalized)
+ {
+ if (!strcmp (normalized, "Top"))
+ heading_level = 0;
+ else
+ {
+ int use_next_heading = 0;
+ if (self->conf->USE_NEXT_HEADING_FOR_LONE_NODE > 0)
+ {
+ ELEMENT *next_heading
+ = find_root_command_next_heading_command (element,
+ self->expanded_formats,
+ (!strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "inline")),
+ 0);
+ if (next_heading)
+ use_next_heading = 1;
+ }
+ if (!use_next_heading)
+ /* use node */
+ heading_level = 3;
+ }
+ }
}
else
{
- footnote_heading = "";
+ int status;
+ int level = lookup_extra_integer (element, "section_level", &status);
+ if (status >= 0)
+ {
+ heading_level = level;
+ }
+ else
+ {
+ heading_level = section_level (element);
+ }
}
+ do_heading = (heading && strlen (heading) && heading_level >= 0);
- level = self->conf->FOOTNOTE_END_HEADER_LEVEL;
+ /* if set, the id is associated to the heading text */
+ if (opening_section)
+ {
+ char *class;
+ STRING_LIST *classes;
+ char *attribute_class;
+ int status;
+ int level
+ = lookup_extra_integer (opening_section, "section_level", &status);
+ STRING_LIST *closed_strings;
- xasprintf (&class, "%s-heading", class_base);
+ closed_strings = html_close_registered_sections_level (self, level);
- add_string (class, classes);
- free (class);
+ if (closed_strings->number)
+ {
+ int i;
+ for (i = 0; i < closed_strings->number; i++)
+ {
+ text_append (result, closed_strings->list[i]);
+ free (closed_strings->list[i]);
+ }
+ }
+ free (closed_strings);
- formatted_heading
- = call_formatting_function_format_heading_text (self, 0, classes,
- footnote_heading,
- level, 0, 0, 0);
- destroy_strings_list (classes);
- text_append (result, formatted_heading);
- text_append_n (result, "\n", 1);
+ html_register_opened_section_level (self, level, "</div>\n");
- free (formatted_heading);
+ /* use a specific class name to mark that this is the start of
+ the section extent. It is not necessary where the section is. */
- if (footnote_heading_tree)
- free (footnote_heading);
+ classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (classes, 0, sizeof (STRING_LIST));
- text_append (result, foot_lines);
- free (foot_lines);
- text_append (result, "</div>\n");
-}
+ xasprintf (&class, "%s-level-extent",
+ builtin_command_name (level_corrected_opening_section_cmd));
-void
-format_footnotes_segment (CONVERTER *self, TEXT *result)
-{
- if (self->formatting_references[FR_format_footnotes_segment].status
- == FRS_status_default_set)
+ add_string (class, classes);
+ free (class);
+ attribute_class = html_attribute_class (self, "div", classes);
+ clear_strings_list (classes);
+
+ text_append (result, attribute_class);
+ free (attribute_class);
+
+ if (element_id && strlen (element_id))
+ text_printf (result, " id=\"%s\"", element_id);
+ text_append (result, ">\n");
+ }
+ else if (element_id && strlen (element_id))
+ {
+ if (element_header && strlen (element_header))
+ {
+ char *anchor;
+ /* case of a @node without sectioning command and with a header.
+ put the node element anchor before the header.
+ Set the class name to the command name if there is no heading,
+ else the class will be with the heading element. */
+
+ char *id_class = 0;
+ if (do_heading)
+ {
+ xasprintf (&id_class, "%s-id", builtin_command_name (cmd));
+ }
+ else
+ id_class = builtin_command_name (cmd);
+
+ anchor
+ = call_formatting_function_format_separate_anchor (self,
+ element_id, id_class);
+ text_append (result, anchor);
+ free (anchor);
+
+ if (do_heading)
+ free (id_class);
+ }
+ else
+ heading_id = element_id;
+ }
+
+ if (element_header)
{
- default_format_footnotes_segment (self, result);
+ text_append (result, element_header);
+ free (element_header);
}
- else
+
+ if (do_heading)
{
- char *footnotes_segment
- = call_formatting_function_format_footnotes_segment (self);
- if (footnotes_segment)
+ STRING_LIST *heading_classes;
+ if (self->conf->TOC_LINKS > 0
+ && (builtin_command_data[cmd].flags & CF_root)
+ && (builtin_command_data[cmd].flags & CF_sectioning_heading))
{
- text_append (result, footnotes_segment);
- free (footnotes_segment);
+ char *content_href = html_command_contents_href (self, element,
+ CM_contents, 0);
+ if (content_href)
+ {
+ if (strlen (content_href))
+ {
+ char *heading_tmp = strdup (heading);
+ free (heading);
+ xasprintf (&heading, "<a href=\"%s\">%s</a>",
+ content_href, heading_tmp);
+ free (heading_tmp);
+ }
+ free (content_href);
+ }
}
- }
-}
-void
-convert_table_term_type (CONVERTER *self, const enum element_type type,
- const ELEMENT *element, const char *content,
- TEXT *result)
-{
- if (content)
- {
- text_append (result, "<dt>");
- text_append (result, content);
- }
-}
+ heading_classes = (STRING_LIST *) malloc (sizeof (STRING_LIST));
+ memset (heading_classes, 0, sizeof (STRING_LIST));
+ add_string (builtin_command_name (level_corrected_cmd), heading_classes);
+ if (level_set_class)
+ add_string (level_set_class, heading_classes);
+ if (html_in_preformatted_context (self))
+ {
+ char *attribute_class;
+ char *id_str = 0;
+ if (heading_id)
+ {
+ xasprintf (&id_str, " id=\"%s\"", heading_id);
+ }
+ else
+ id_str = strdup ("");
-void
-convert_row_type (CONVERTER *self, const enum element_type type,
- const ELEMENT *element, const char *content,
- TEXT *result)
-{
- if (html_in_string (self))
+ attribute_class = html_attribute_class (self, "strong",
+ heading_classes);
+ text_append (result, attribute_class);
+ free (attribute_class);
+ text_printf (result, "%s>%s</strong>\n", id_str, heading);
+
+ free (id_str);
+ }
+ else
+ {
+ char *formatted_heading
+ = call_formatting_function_format_heading_text (self,
+ builtin_command_name (level_corrected_cmd),
+ heading_classes, heading,
+ heading_level + self->conf->CHAPTER_HEADER_LEVEL -1,
+ heading_id, element, element_id);
+ text_append (result, formatted_heading);
+ free (formatted_heading);
+ }
+ destroy_strings_list (heading_classes);
+ }
+ else if (heading_id)
{
- if (content)
- text_append (result, content);
+ /* case of a lone node and no header, and case of an empty @top */
+ char *anchor
+ = call_formatting_function_format_separate_anchor (self,
+ heading_id, builtin_command_name(cmd));
+ text_append (result, anchor);
+ free (anchor);
}
- if (!content || content[strspn (content, whitespace_chars)] == '\0')
- return;
- else
- {
- text_append (result, "<tr>");
- text_append (result, content);
- text_append (result, "</tr>");
+ free (heading);
+ free (level_set_class);
- if (element->contents.number > 0
- && element->contents.list[0]->cmd != CM_headitem)
- /* if headitem, end of line added in _convert_multitable_head_type */
- text_append (result, "\n");
- }
+ if (content)
+ text_append (result, content);
+
+ text_append (result, tables_of_contents.text);
+ free (tables_of_contents.text);
+ text_append (result, mini_toc_or_auto_menu.text);
+ free (mini_toc_or_auto_menu.text);
}
void
-convert_w_command (CONVERTER *self, const enum command_id cmd,
+convert_contents_command (CONVERTER *self, const enum command_id cmd,
const ELEMENT *element,
const HTML_ARGS_FORMATTED *args_formatted,
const char *content, TEXT *result)
{
- if (args_formatted && args_formatted->number > 0)
- {
- if (args_formatted->args[0].formatted[AFT_type_normal])
- text_append (result,
- args_formatted->args[0].formatted[AFT_type_normal]);
- }
- if (!html_in_string (self))
+ if (html_in_string (self))
+ return;
+
+ enum command_id used_cmd;
+
+ if (cmd == CM_summarycontents)
+ used_cmd = CM_shortcontents;
+ else
+ used_cmd = cmd;
+
+ set_informative_command_value (self->conf, element);
+
+ if (!strcmp (self->conf->CONTENTS_OUTPUT_LOCATION, "inline")
+ && ((used_cmd == CM_contents && self->conf->contents > 0)
+ || (used_cmd == CM_shortcontents && self->conf->shortcontents > 0))
+ && self->document->sections_list
+ && self->document->sections_list->number > 1)
{
- text_append (result, "<!-- /@w -->");
+ char *contents = contents_inline_element(self, used_cmd, element);
+ if (contents)
+ {
+ text_append (result, contents);
+ free (contents);
+ }
}
}
+
/* associate command to the C function implementing the conversion */
static COMMAND_INTERNAL_CONVERSION commands_internal_conversion_table[] = {
{CM_w, &convert_w_command},
+ {CM_contents, &convert_contents_command},
+ {CM_shortcontents, &convert_contents_command},
+ {CM_summarycontents, &convert_contents_command},
+ {CM_node, convert_heading_command},
+ {CM_section, convert_heading_command},
+ /*
+ {CM_heading, convert_heading_command},
+ */
{0, 0},
};
@@ -4104,10 +5570,8 @@ static TYPE_INTERNAL_CONVERSION
types_internal_conversion_table[] = {
/* associate type to the C function implementing the opening */
static TYPE_INTERNAL_OPEN types_internal_open_table[] = {
- /*
{ET_paragraph, &open_inline_container_type},
{ET_preformatted, &open_inline_container_type},
- */
{0, 0},
};
@@ -4763,6 +6227,9 @@ html_converter_initialize (CONVERTER *self)
(&self->special_unit_body_formatting[i],
self->special_unit_varieties.list[i], &self->special_unit_body[i]);
}
+
+ qsort (self->htmlxref.list, self->htmlxref.number,
+ sizeof (HTMLXREF_MANUAL), compare_htmlxref_manual);
}
/* called in the end of html_converter_prepare_output_sv */
@@ -4808,6 +6275,22 @@ reset_html_targets (CONVERTER *self, HTML_TARGET_LIST
*targets)
void
html_initialize_output_state (CONVERTER *self, char *context)
{
+ /* set the htmlxref type split of the document */
+ self->document_htmlxref_split_type = htmlxref_split_type_mono;
+
+ if (self->conf->SPLIT && strlen (self->conf->SPLIT))
+ {
+ int i;
+ for (i = 1; i < htmlxref_split_type_chapter+1; i++)
+ {
+ if (!strcmp (self->conf->SPLIT, htmlxref_split_type_names[i]))
+ {
+ self->document_htmlxref_split_type = i;
+ break;
+ }
+ }
+ }
+
/* directions */
memset (self->global_units_directions, 0,
(D_Last + self->special_unit_varieties.number+1) * sizeof (OUTPUT_UNIT));
@@ -5030,6 +6513,18 @@ html_free_converter (CONVERTER *self)
free (self->special_unit_info[i]);
}
+ for (i = 0; i < self->htmlxref.number; i++)
+ {
+ int j;
+ HTMLXREF_MANUAL *htmlxref_manual = &self->htmlxref.list[i];
+ free (htmlxref_manual->manual);
+ for (j = 0; j < htmlxref_split_type_chapter +1; j++)
+ {
+ free (htmlxref_manual->urlprefix[j]);
+ }
+ }
+ free (self->htmlxref.list);
+
free (self->no_arg_formatted_cmd.list);
free (self->pending_closes.stack);
@@ -5037,13 +6532,15 @@ html_free_converter (CONVERTER *self)
free (self->associated_inline_content.list);
+ free_strings_list (&self->shared_conversion_state_integer);
+
destroy_associated_info (&self->shared_conversion_state.integers);
free (self->no_arg_formatted_cmd_translated.list);
free (self->reset_target_commands.list);
free (self->file_changed_counter.list);
- free (self->referred_command_stack.list);
+ free (self->referred_command_stack.stack);
free (self->html_document_context.stack);
@@ -5261,18 +6758,18 @@ html_translate_names (CONVERTER *self)
ELEMENT *command = special_unit->unit_command;
if (command)
{
- HTML_TARGET *target
+ HTML_TARGET *target_info
= find_element_target (&self->html_targets, command);
- if (target)
+ if (target_info)
{
/* the tree is a reference to special_unit_info_tree, so it should
not be freed, but need to be reset to trigger the creation of the
special_unit_info_tree tree when needed */
- clear_tree_added_elements (self, &target->tree);
- free (target->command_text[HCTT_string]);
- target->command_text[HCTT_string] = 0;
- free (target->command_text[HCTT_text]);
- target->command_text[HCTT_text] = 0;
+ clear_tree_added_elements (self, &target_info->tree);
+ free (target_info->command_text[HCTT_string]);
+ target_info->command_text[HCTT_string] = 0;
+ free (target_info->command_text[HCTT_text]);
+ target_info->command_text[HCTT_text] = 0;
/* gather elements to pass information to perl */
add_to_element_list (&self->reset_target_commands,
command);
@@ -6546,7 +8043,7 @@ html_prepare_title_titlepage (CONVERTER *self, int
output_units_descriptor,
title_titlepage
= call_formatting_function_format_title_titlepage (self);
self->title_titlepage = title_titlepage;
- memset (&self->current_filename, 0, sizeof (CURRENT_FILE_INFO));
+ memset (&self->current_filename, 0, sizeof (FILE_NUMBER_NAME));
self->modified_state |= HMSF_current_filename;
}
@@ -6682,7 +8179,7 @@ html_convert_output (CONVERTER *self, const ELEMENT *root,
unit_nr++;
}
}
- memset (&self->current_filename, 0, sizeof (CURRENT_FILE_INFO));
+ memset (&self->current_filename, 0, sizeof (FILE_NUMBER_NAME));
self->modified_state |= HMSF_current_filename;
}
diff --git a/tp/Texinfo/XS/convert/convert_html.h
b/tp/Texinfo/XS/convert/convert_html.h
index 950c61a086..a3af23ab68 100644
--- a/tp/Texinfo/XS/convert/convert_html.h
+++ b/tp/Texinfo/XS/convert/convert_html.h
@@ -15,6 +15,7 @@ extern char *html_formatting_reference_names[];
extern TRANSLATED_SUI_ASSOCIATION translated_special_unit_info[];
extern const char *special_unit_info_type_names[SUI_type_heading + 1];
+extern const char *htmlxref_split_type_names[htmlxref_split_type_chapter + 1];
void html_format_init (void);
diff --git a/tp/Texinfo/XS/convert/converter.c
b/tp/Texinfo/XS/convert/converter.c
index 1c9c7fb4e1..e28a08b71a 100644
--- a/tp/Texinfo/XS/convert/converter.c
+++ b/tp/Texinfo/XS/convert/converter.c
@@ -580,6 +580,7 @@ free_generic_converter (CONVERTER *self)
destroy_translated_commands (self->translated_commands);
}
+ free (self->output_format);
free (self->expanded_formats);
if (self->init_conf)
@@ -649,7 +650,7 @@ xml_protect_text (const char *text, TEXT *result)
}
ELEMENT *
-float_type_number (CONVERTER *self, ELEMENT *float_e)
+float_type_number (CONVERTER *self, const ELEMENT *float_e)
{
int have_float_number;
ELEMENT *tree = 0;
diff --git a/tp/Texinfo/XS/convert/converter.h
b/tp/Texinfo/XS/convert/converter.h
index eef23706ad..0fb4de449d 100644
--- a/tp/Texinfo/XS/convert/converter.h
+++ b/tp/Texinfo/XS/convert/converter.h
@@ -89,7 +89,7 @@ void free_comma_index_subentries_tree (ELEMENT_LIST *element);
char *top_node_filename (CONVERTER *self, char *document_name);
-ELEMENT *float_type_number (CONVERTER *self, ELEMENT *float_e);
+ELEMENT *float_type_number (CONVERTER *self, const ELEMENT *float_e);
void initialize_output_units_files (CONVERTER *self);
size_t set_output_unit_file (CONVERTER *self, OUTPUT_UNIT *output_unit,
diff --git a/tp/Texinfo/XS/convert/get_html_perl_info.c
b/tp/Texinfo/XS/convert/get_html_perl_info.c
index 37e9026004..b9152f7f39 100644
--- a/tp/Texinfo/XS/convert/get_html_perl_info.c
+++ b/tp/Texinfo/XS/convert/get_html_perl_info.c
@@ -140,6 +140,7 @@ html_converter_initialize_sv (SV *converter_sv,
HV *default_types_conversion_hv;
HV *default_css_string_types_conversion_hv;
HV *default_output_units_conversion_hv;
+ SV **htmlxref_sv;
SV **formatting_function_sv;
SV **sorted_special_unit_varieties_sv;
SV **no_arg_commands_formatting_sv;
@@ -176,6 +177,55 @@ html_converter_initialize_sv (SV *converter_sv,
= (HV *)SvRV (default_css_string_formatting_references);
#define FETCH(key) key##_sv = hv_fetch (converter_hv, #key, strlen(#key), 0);
+ FETCH(htmlxref)
+
+ if (htmlxref_sv)
+ {
+ I32 hv_number;
+ I32 i;
+ HV *htmlxref_hv = (HV *) SvRV (*htmlxref_sv);
+
+ hv_number = hv_iterinit (htmlxref_hv);
+
+ converter->htmlxref.number = hv_number;
+
+ if (hv_number > 0)
+ {
+ converter->htmlxref.list = (HTMLXREF_MANUAL *)
+ malloc (hv_number * sizeof (HTMLXREF_MANUAL));
+ memset (converter->htmlxref.list, 0,
+ hv_number * sizeof (HTMLXREF_MANUAL));
+
+ for (i = 0; i < hv_number; i++)
+ {
+ int j;
+ HTMLXREF_MANUAL *htmlxref_manual = &converter->htmlxref.list[i];
+ HE *next = hv_iternext (htmlxref_hv);
+ SV *selector_sv = hv_iterkeysv (next);
+ char *selector = (char *) SvPVutf8_nolen (selector_sv);
+ SV *split_type_sv = HeVAL(next);
+ HV *split_type_hv = (HV *) SvRV (split_type_sv);
+
+ htmlxref_manual->manual = strdup (selector);
+
+ for (j = 0; j < htmlxref_split_type_chapter +1; j++)
+ {
+ const char *split_type_name = htmlxref_split_type_names[j];
+ SV **urlprefix_sv = hv_fetch (split_type_hv, split_type_name,
+ strlen (split_type_name), 0);
+ /* can be undef if there is an entry in the htmlxref.cnf file
+ without the urlprefix. We ignore completely, in perl
+ it is ignored later on when checking an external href */
+ if (urlprefix_sv && SvOK (*urlprefix_sv))
+ {
+ char *urlprefix = SvPVutf8_nolen (*urlprefix_sv);
+ htmlxref_manual->urlprefix[j] = strdup (urlprefix);
+ }
+ }
+ }
+ }
+ }
+
FETCH(formatting_function);
/* no need to check if it exists */
diff --git a/tp/Texinfo/XS/main/converter_types.h
b/tp/Texinfo/XS/main/converter_types.h
index 949a006e58..02f1e81b6d 100644
--- a/tp/Texinfo/XS/main/converter_types.h
+++ b/tp/Texinfo/XS/main/converter_types.h
@@ -168,6 +168,15 @@ enum html_command_text_type {
HCTT_string_nonumber, /* not sure that it is set/used */
};
+enum htmlxref_split_type {
+ htmlxref_split_type_none = -1,
+
+ htmlxref_split_type_mono,
+ htmlxref_split_type_node,
+ htmlxref_split_type_section,
+ htmlxref_split_type_chapter,
+};
+
typedef struct {
enum command_id *stack;
size_t top; /* One above last pushed command. */
@@ -201,6 +210,17 @@ typedef struct {
size_t space;
} INTEGER_STACK;
+typedef struct ELEMENT_STACK {
+ const ELEMENT **stack;
+ size_t top;
+ size_t space;
+} ELEMENT_STACK;
+
+typedef struct FILE_NUMBER_NAME {
+ size_t file_number;
+ char *filename;
+} FILE_NUMBER_NAME;
+
typedef struct VARIETY_DIRECTION_INDEX {
char *special_unit_variety;
int direction_index;
@@ -218,10 +238,12 @@ typedef struct HTML_TARGET {
char *command_text[HCTT_string_nonumber+1];
TREE_ADDED_ELEMENTS tree;
TREE_ADDED_ELEMENTS tree_nonumber;
- char *filename;
+ FILE_NUMBER_NAME file_number_name;
+ int filename_set;
+ ELEMENT *root_element_command;
+ int root_element_command_set;
/*
ELEMENT *node_command;
- ELEMENT *root_element_command;
*/
} HTML_TARGET;
@@ -337,11 +359,6 @@ typedef struct FILE_NAME_PATH_COUNTER_LIST {
FILE_NAME_PATH_COUNTER *list;
} FILE_NAME_PATH_COUNTER_LIST;
-typedef struct CURRENT_FILE_INFO {
- size_t file_number;
- char *filename;
-} CURRENT_FILE_INFO;
-
typedef struct FILE_STREAM {
char *file_path;
FILE *stream;
@@ -560,6 +577,27 @@ typedef struct HTML_ASSOCIATED_INLINE_CONTENT_LIST {
HTML_ASSOCIATED_INLINE_CONTENT *list;
} HTML_ASSOCIATED_INLINE_CONTENT_LIST;
+typedef struct HTMLXREF_MANUAL {
+ char *manual;
+ char *urlprefix[htmlxref_split_type_chapter +1];
+} HTMLXREF_MANUAL;
+
+typedef struct HTMLXREF_MANUAL_LIST {
+ size_t number;
+ HTMLXREF_MANUAL *list;
+} HTMLXREF_MANUAL_LIST;
+
+typedef struct HTMLXREF_MANUAL_ELEMENT_WARNED {
+ const ELEMENT *element;
+ char *manual;
+} HTMLXREF_MANUAL_ELEMENT_WARNED;
+
+typedef struct HTMLXREF_MANUAL_ELEMENT_WARNED_LIST {
+ size_t number;
+ size_t space;
+ HTMLXREF_MANUAL_ELEMENT_WARNED *list;
+} HTMLXREF_MANUAL_ELEMENT_WARNED_LIST;
+
typedef struct CONVERTER {
int converter_descriptor;
/* perl converter. This should be HV *hv,
@@ -568,6 +606,7 @@ typedef struct CONVERTER {
struct OPTIONS *conf;
struct OPTIONS *init_conf;
+ char *output_format;
EXPANDED_FORMAT *expanded_formats;
TRANSLATED_COMMAND *translated_commands;
@@ -613,6 +652,7 @@ typedef struct CONVERTER {
FORMATTING_REFERENCE *special_unit_body;
STRING_LIST special_unit_varieties;
char **special_unit_info[SUI_type_heading+1];
+ HTMLXREF_MANUAL_LIST htmlxref;
TYPE_CONVERSION_FUNCTION type_conversion_function[TXI_TREE_TYPES_NUMBER];
TYPE_CONVERSION_FUNCTION
css_string_type_conversion_function[TXI_TREE_TYPES_NUMBER];
TYPE_OPEN_FUNCTION type_open_function[TXI_TREE_TYPES_NUMBER];
@@ -625,6 +665,7 @@ typedef struct CONVERTER {
HTML_COMMAND_CONVERSION
html_command_conversion[BUILTIN_CMD_NUMBER][HCC_type_css_string+1];
/* set for a document */
+ enum htmlxref_split_type document_htmlxref_split_type;
const OUTPUT_UNIT **global_units_directions;
SPECIAL_UNIT_DIRECTION *special_units_direction_name;
ELEMENT **special_unit_info_tree[SUIT_type_heading+1];
@@ -639,6 +680,7 @@ typedef struct CONVERTER {
each position corresponding to an output unit. */
size_t *special_unit_file_indices; /* same for special output units */
PAGES_CSS_LIST page_css;
+ HTMLXREF_MANUAL_ELEMENT_WARNED_LIST check_htmlxref_already_warned;
/* state only in C converter */
unsigned long modified_state; /* specifies which perl state to rebuild */
@@ -652,6 +694,7 @@ typedef struct CONVERTER {
ARRAY_INDEX_LIST file_changed_counter; /* index of files in
output_unit_files with changed counter */
HTML_ADDED_TARGET_LIST added_targets; /* targets added */
+ STRING_LIST shared_conversion_state_integer; /* modified */
/* next three allow to switch from normal HTML formatting to css strings
formatting */
FORMATTING_REFERENCE *current_formatting_references;
@@ -667,8 +710,8 @@ typedef struct CONVERTER {
HTML_DOCUMENT_CONTEXT_STACK html_document_context;
STRING_STACK multiple_pass;
STRING_STACK pending_closes;
- CURRENT_FILE_INFO current_filename;
- ELEMENT_LIST referred_command_stack;
+ FILE_NUMBER_NAME current_filename;
+ ELEMENT_STACK referred_command_stack;
HTML_SHARED_CONVERSION_STATE shared_conversion_state;
HTML_INLINE_CONTENT_STACK pending_inline_content;
HTML_PENDING_FOOTNOTE_STACK pending_footnotes;
diff --git a/tp/Texinfo/XS/main/get_perl_info.c
b/tp/Texinfo/XS/main/get_perl_info.c
index fe58c6f056..6b08197c1a 100644
--- a/tp/Texinfo/XS/main/get_perl_info.c
+++ b/tp/Texinfo/XS/main/get_perl_info.c
@@ -341,12 +341,14 @@ set_translated_commands (CONVERTER *converter, HV *hv_in)
}
}
+#define FETCH(key) key##_sv = hv_fetch (hv_in, #key, strlen(#key), 0);
void
converter_initialize (SV *converter_sv, CONVERTER *converter)
{
HV *hv_in;
- SV **converter_conf_sv;
+ SV **conf_sv;
SV **converter_init_conf_sv;
+ SV **output_format_sv;
DOCUMENT *document;
dTHX;
@@ -356,18 +358,15 @@ converter_initialize (SV *converter_sv, CONVERTER
*converter)
document = get_sv_document_document (converter_sv, 0);
converter->document = document;
- converter_conf_sv = hv_fetch (hv_in, "conf",
- strlen ("conf"), 0);
+ FETCH(conf)
- if (converter_conf_sv && SvOK (*converter_conf_sv))
+ if (conf_sv && SvOK (*conf_sv))
{
converter->conf
- = copy_sv_options (*converter_conf_sv);
+ = copy_sv_options (*conf_sv);
}
- converter_init_conf_sv
- = hv_fetch (hv_in, "converter_init_conf",
- strlen ("converter_init_conf"), 0);
+ FETCH(converter_init_conf)
if (converter_init_conf_sv && SvOK (*converter_init_conf_sv))
{
@@ -375,6 +374,14 @@ converter_initialize (SV *converter_sv, CONVERTER
*converter)
= copy_sv_options (*converter_init_conf_sv);
}
+ FETCH(output_format)
+
+ if (output_format_sv && SvOK (*output_format_sv))
+ {
+ converter->output_format
+ = strdup (SvPVutf8_nolen (*output_format_sv));
+ }
+
set_translated_commands (converter, hv_in);
get_expanded_formats (hv_in, &converter->expanded_formats);
@@ -385,8 +392,8 @@ CONVERTER *
set_output_converter_sv (SV *sv_in, char *warn_string)
{
HV *hv_in;
- SV **converter_conf_sv;
- SV **converter_init_conf_sv;
+ SV **conf_sv;
+ SV **output_init_conf_sv;
CONVERTER *converter = 0;
dTHX;
@@ -394,34 +401,34 @@ set_output_converter_sv (SV *sv_in, char *warn_string)
converter = get_sv_converter (sv_in, warn_string);
hv_in = (HV *)SvRV (sv_in);
- converter_conf_sv = hv_fetch (hv_in, "conf",
- strlen ("conf"), 0);
- if (converter_conf_sv)
+ FETCH(conf)
+
+ if (conf_sv)
{
if (converter->conf)
free_options (converter->conf);
free (converter->conf);
converter->conf
- = copy_sv_options (*converter_conf_sv);
+ = copy_sv_options (*conf_sv);
}
- converter_init_conf_sv = hv_fetch (hv_in, "output_init_conf",
- strlen ("output_init_conf"), 0);
+ FETCH(output_init_conf)
- if (converter_init_conf_sv && SvOK(*converter_init_conf_sv))
+ if (output_init_conf_sv && SvOK(*output_init_conf_sv))
{
if (converter->init_conf)
free_options (converter->init_conf);
free (converter->init_conf);
converter->init_conf
- = copy_sv_options (*converter_init_conf_sv);
+ = copy_sv_options (*output_init_conf_sv);
}
return converter;
}
+#undef FETCH
/* code in comments allow to sort the index names to have a fixed order
in the data structure. Not clear that it is useful or not, not enabled