2 # -*- coding: utf-8; -*-
4 ### texi2html customization script for LilyPond
5 ### Author: Reinhold Kainhofer <reinhold@kainhofer.com>, 2008.
6 ### Some code parts copied from texi2html and adapted. These functions
7 ### were written mainly by Patrice Dumas
11 ### Features implemented here:
12 ### -) For split manuals, the main page is index.html.
13 ### -) All @unnumbered* sections are placed into the same file
14 ### (implemented by split_at_numbered_sections)
15 ### -) Use our custom CSS file, with IE-specific fixes in another CSS file,
16 ### impelmented by lilypond_css_lines
17 ### -) TOC (folded, with the current page highlighted) in an overflown <div>
18 ### is added to every page; implemented by:
19 ### lilypond_print_element_header -- building of the TOC
20 ### lilypond_toc_body -- generation of customized TOC output
21 ### lilypond_print_page_head -- start <div id="main">
22 ### print_lilypond_page_foot -- closing id=main, output of footer & TOC
23 ### -) External refs are formatted only as "Text of the node" (not as >>see
24 ### "NODE" section "SECTION" in "BOOK"<< like with default texi2html). Also,
25 ### the leading "(book-name)" is removed.
26 ### Implemented by overriding lilypond_external_ref
27 ### -) Navigation bars on top/bottom of the page and between sections are not
28 ### left-aligned, but use a combination of left/center/right aligned table
29 ### cells; For this, I heavily extend the texi2html code to allow for
30 ### differently aligned cells and for multi-line tables);
31 ### Implemented in lilypond_print_navigation
32 ### -) Different formatting than the default: example uses the same formatting
34 ### -) Allow translated section titles: All section titles can be translated,
35 ### the original (English) title is associated with @translationof. This is
36 ### needed, because the file name / anchor is generated from the original
37 ### English title, since otherwise language-autoselection would break with
39 ### Since it is then no longer possible to obtain the file name from the
40 ### section title, I keep a sectionname<=>filename/anchor around. This way,
41 ### xrefs from other manuals can simply load that map and retrieve the
42 ### correct file name for the link. Implemented in:
43 ### lilypond_unknown (handling of @translationof, in case
44 ### extract_texi_filenames.py messes up...)
45 ### lilypond_element_file_name (correct file name: use the map)
46 ### lilypond_element_target_name (correct anchor: use the map)
47 ### lilypond_init_map (read in the externally created map from disk)
48 ### lilypond_external_href (load the map for xrefs, use the correct
50 ### -) The HTML anchors for all sections are derived from the node name /
51 ### section title (pre-generated in the .xref-map file). Implemented by:
52 ### lilypond_element_target_name (adjust section anchors)
53 ### -) Use the standard footnote format "<sup>nr</sup> text" instead of the
54 ### ugly format of texi2html (<h3>(nr)</h3><p>text</p>). Implemented in
55 ### makeinfo_like_foot_line_and_ref
56 ### makeinfo_like_foot_lines
57 ### makeinfo_like_paragraph
60 ### Useful helper functions:
61 ### -) texinfo_file_name($node_name): returns a texinfo-compatible file name
62 ### for the given string $node_name (whitespace trimmed/replaced by -,
63 ### non-standard chars replaced by _xxxx (ascii char code) and forced to
64 ### start with a letter by prepending t_g if necessary)
67 package Texi2HTML::Config;
70 use Encode qw(decode);
72 #############################################################################
74 #############################################################################
76 my $LY_LANGUAGES = {};
77 $LY_LANGUAGES->{'fr'} = {
78 'Back to Documentation Index' => 'Retour à l\'accueil de la documentation',
80 $LY_LANGUAGES->{'es'} = {
81 'Back to Documentation Index' => 'Volver al índice de la documentación',
83 $LY_LANGUAGES->{'de'} = {
84 'Back to Documentation Index' => 'Zur Dokumentationsübersicht',
86 $LY_LANGUAGES->{'ja'} = {
87 'Back to Documentation Index' => 'ドキュメント インデックスに戻る',
90 $LY_LANGUAGES->{'hu'} = {
91 'Back to Documentation Index' => 'Vissza a dokumentációk jegyzékéhez',
94 $LY_LANGUAGES->{'it'} = {
95 'Back to Documentation Index' => 'Torna all\'indice della documentazione',
98 # FIXME: request the translations below then send them to texi2html/texinfo devs
99 $LANGUAGES->{'it'} = {
100 ' The buttons in the navigation panels have the following meaning:' => ' I bottoni nei pannelli di navigazione hanno il seguente significato:',
101 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' dove @strong{ Esempio } assume che l\'attuale posizione è alla @strong{ Sottosottosezione Uno-Due-Tre } di un documento che ha la seguente struttura:',
103 '(outside of any element)' => '(fuori da qualsiasi elemento)',
104 '(outside of any node)' => '(fuori da qualsiasi nodo)',
105 '@b{{quotation_arg}:} ' => '@b{{quotation_arg}:} ',
106 '@cite{{book}}' => '@cite{{book}}',
107 '@{No value for `{value}\'@}' => '@{Nessun valore per `{value}\'@}',
108 'About' => 'Informazioni',
109 'About (help)' => 'Informazioni (aiuto)',
110 'About This Document' => 'Informazioni su questo documento',
112 'August' => 'Agosto',
113 'Back' => 'Indietro',
114 'Back section in previous file' => '',
115 'Beginning of this chapter or previous chapter' => 'Inizio di questo capitolo o capitolo precedente',
116 'Button' => 'Bottone',
117 'Contents' => 'Contenuti',
118 'Cover (top) of document' => 'Copertina (inizio) del documento',
119 'Current' => 'Attuale',
120 'Current Position' => 'Posizione Attuale',
121 'Current section' => 'Sezione attuale',
122 'December' => 'Dicembre',
123 'FastBack' => 'Indietro veloce',
124 'FastForward' => 'Avanti veloce',
125 'February' => 'Febbraio',
127 'First section in reading order' => 'Prima sezione in ordine di lettura',
128 'Following' => 'Seguente',
129 'Following node' => 'Nodo seguente',
130 'Footnotes' => 'Note a piè di pagina',
131 'Forward' => 'Avanti',
132 'Forward section in next file' => 'Sezione successiva nel prossimo file',
133 'From 1.2.3 go to' => 'Da 1.2.3 vai a',
136 'Index Entry' => 'Voce dell\'indice',
137 'January' => 'Gennaio',
139 'Jump to' => 'Salta a',
142 'Last section in reading order' => 'Ultima sezione in ordine di lettura',
147 'Next' => 'Successivo',
148 'Next chapter' => 'Capitolo successivo',
149 'Next file' => 'File successivo',
150 'Next node' => 'Nodo successivo',
151 'Next section in reading order' => 'Sezione successiva in ordine di lettura',
152 'Next section on same level' => 'Sezione successiva sullo stesso livello',
153 'NextFile' => 'File successivo',
154 'Node following in node reading order' => 'Nodo seguente in ordine di lettura',
155 'Node up' => 'Nodo superiore',
156 'NodeNext' => 'Nodo successivo',
157 'NodePrev' => 'Nodo precedente',
158 'NodeUp' => 'Nodo superiore',
159 'November' => 'Novembre',
160 'October' => 'Ottobre',
161 'Overview' => 'Panoramica',
163 'PrevFile' => 'File precedente',
164 'Previous' => 'Precedente',
165 'Previous file' => 'File precedente',
166 'Previous node' => 'Nodo precedente',
167 'Previous section in reading order' => 'Sezione precedente in ordine di lettura',
168 'Previous section on same level' => 'Sezione precedente sullo stesso livello',
169 'Section' => 'Sezione',
170 'Section One' => 'Sezione uno',
172 'See @cite{{book}}' => 'Vedi @cite{{book}}',
173 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'Vedi la sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}',
174 'See section `{section}\' in @cite{{book}}' => 'Vedi la sezione `{section}\' in @cite{{book}}',
175 'See section {reference_name}' => 'Vedi la sezione {reference_name}',
176 'See {node_file_href}' => 'Vedi {node_file_href}',
177 'See {node_file_href} @cite{{book}}' => 'Vedi {node_file_href} @cite{{book}}',
178 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Vedi {node_file_href} nella sezione `{section}\' in @cite{{book}}',
179 'See {reference_name}' => 'Vedi {reference_name}',
180 'See {ref}' => 'Vedi {ref}',
181 'See {title_ref}' => 'Vedi {title_ref}',
182 'September' => 'Settembre',
183 'Short Table of Contents' => 'Indice breve',
184 'Short table of contents' => 'Indice breve',
185 'Subsection One-Four' => 'Sottosezione Uno-Quattro',
186 'Subsection One-One' => 'Sottosezione Uno-Uno',
187 'Subsection One-Three' => 'Sottosezione Uno-Tre',
188 'Subsection One-Two' => 'Sottosezione Uno-Due',
189 'Subsubsection One-Two-Four' => 'Sottosottosezione Uno-Due-Quattro',
190 'Subsubsection One-Two-One' => 'Sottosottosezione Uno-Due-Uno',
191 'Subsubsection One-Two-Three' => 'Sottosottosezione Uno-Due-Tre',
192 'Subsubsection One-Two-Two' => 'Sottosottosezione Uno-Due-Due',
193 'T2H_today' => '%s, %d %d',
194 'Table of Contents' => 'Indice',
195 'Table of contents' => 'Indice',
196 'The node you are looking for is at {href}.' => 'Il nodo che stai cercando è {href}',
198 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Questo documento è stato generato il @i{{date}} con @uref{{program_homepage}, @i{{program}}}.',
199 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Questo documento è stato generato con @uref{{program_homepage}, @emph{{program}}}.',
201 'Untitled Document' => 'Documento senza titolo',
203 'Up node' => 'Nodo superiore',
204 'Up section' => 'Sezione superiore',
205 'current' => 'attuale',
206 'on @emph{{date}}' => 'il @emph{{date}}',
207 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}',
208 'section `{section}\' in @cite{{book}}' => 'sezione `{section}\' in @cite{{book}}',
210 'see @cite{{book}}' => 'vedi @cite{{book}}',
211 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'vedi la sezione `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}',
212 'see section `{section}\' in @cite{{book}}' => 'vedi la sezione `{section}\' in @cite{{book}}',
213 'see section {reference_name}' => 'vedi la sezione {reference_name}',
214 'see {node_file_href}' => 'vedi {node_file_href}',
215 'see {node_file_href} @cite{{book}}' => 'vedi {node_file_href} @cite{{book}}',
216 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'vedi {node_file_href} nella sezione `{section}\' in @cite{{book}}',
217 'see {reference_name}' => 'vedi {reference_name}',
218 'see {ref}' => 'vedi {ref}',
219 'see {title_ref}' => 'vedi {title_ref}',
220 '{acronym_like} ({explanation})' => '{acronym_like} ({explanation})',
221 '{name} of {class}' => '{name} di {class}',
222 '{name} on {class}' => '{name} in {class}',
223 '{node_file_href}' => '{node_file_href}',
224 '{node_file_href} @cite{{book}}' => '{node_file_href} @cite{{book}}',
225 '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} nella sezione `{section}\' in @cite{{book}}',
226 '{reference_name}' => '{reference_name}',
228 '{style} {number}' => '{style} {number}',
229 '{style}: {caption_first_line}' => '{style}: {caption_first_line}',
230 '{style}: {shortcaption_first_line}' => '{style}: {shortcaption_first_line}',
231 '{title_ref}' => '{title_ref}'
234 $LANGUAGES->{'hu'} = {
235 ' The buttons in the navigation panels have the following meaning:' => ' A navigációs panelen levő gombok jelentése a következő:',
236 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' @strong{ Példánkban } az aktuális pozíció az @strong{ 1.2.3 alalszakasz } egy olyan dokumentumban, melynek szerkezete a következő:',
238 '(outside of any element)' => '(bármelyik elemen kívül)',
239 '(outside of any node)' => '(bármelyik csomóponton kívül)',
240 '@b{{quotation_arg}:} ' => '@b{{quotation_arg}:} ',
241 '@cite{{book}}' => '@cite{{book}}',
242 '@{No value for `{value}\'@}' => '@{Nincs értéke ennek: `{value}\'@}',
244 'About (help)' => 'Segítség a navigációhoz',
245 'About This Document' => 'A navigációs panel használata',
246 'April' => 'április',
247 'August' => 'augusztus',
249 'Back section in previous file' => 'Előző fájl hátsó szakasza',
250 'Beginning of this chapter or previous chapter' => 'Fejezet eleje vagy előző fejezet',
252 'Contents' => 'Tartalom',
253 'Cover (top) of document' => 'Dokumentum címoldala',
254 'Current' => 'Aktuális',
255 'Current Position' => 'Aktuális pozíció',
256 'Current section' => 'Aktuális szakasz',
257 'December' => 'december',
258 'FastBack' => 'Visszaugrás',
259 'FastForward' => 'Előreugrás',
260 'February' => 'február',
262 'First section in reading order' => 'Első szakasz az olvasási sorrendben',
263 'Following' => 'Következő',
264 'Following node' => 'Következő csomópont',
265 'Footnotes' => 'Lábjegyzet',
266 'Forward' => 'Előre',
267 'Forward section in next file' => 'Következő fájl elülső szakasza',
268 'From 1.2.3 go to' => '1.2.3-ból ide jutunk',
270 'Index' => 'Tárgymutató',
271 'Index Entry' => 'Tárgymutató-bejegyzés',
272 'January' => 'január',
274 'Jump to' => 'Ugorj ide',
277 'Last section in reading order' => 'Utolsó szakasz az olvasási sorrendben',
278 'March' => 'március',
282 'Next' => 'Következő',
283 'Next chapter' => 'Következő fejezet',
284 'Next file' => 'Következő fájl',
285 'Next node' => 'Következő csomópont',
286 'Next section in reading order' => 'Következő szakasz az olvasási sorrendben',
287 'Next section on same level' => 'Következő szakasz ugyanazon a szinten',
288 'NextFile' => 'KövetkezőFájl',
289 'Node following in node reading order' => 'Következő csomópont az olvasási sorrendben',
290 'Node up' => 'Szülő csomópont',
291 'NodeNext' => 'KövetkezőCsomópont',
292 'NodePrev' => 'ElőzőCsomópont',
293 'NodeUp' => 'SzülőCsomópont',
294 'November' => 'november',
295 'October' => 'október',
296 'Overview' => 'Áttekintés',
298 'PrevFile' => 'ElőzőFájl',
299 'Previous' => 'Előző',
300 'Previous file' => 'Előző fájl',
301 'Previous node' => 'Előző csomópont',
302 'Previous section in reading order' => 'Előző szakasz az olvasási sorrendben',
303 'Previous section on same level' => 'Előző szakasz ugyanazon a szinten',
304 'Section' => 'Szakasz',
305 'Section One' => 'szakasz',
307 'See @cite{{book}}' => 'Ld. @cite{{book}}',
308 'See section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'Ld. ezt a szakaszt: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}',
309 'See section `{section}\' in @cite{{book}}' => 'Ld. ezt a szakaszt: `{section}\' itt: @cite{{book}}',
310 'See section {reference_name}' => 'Ld. ezt a szakaszt: {reference_name}',
311 'See {node_file_href}' => 'Ld. {node_file_href}',
312 'See {node_file_href} @cite{{book}}' => 'See {node_file_href} @cite{{book}}',
313 'See {node_file_href} section `{section}\' in @cite{{book}}' => 'Ld. {node_file_href} ezt a szakaszt: `{section}\' itt: @cite{{book}}',
314 'See {reference_name}' => 'Ld. {reference_name}',
315 'See {ref}' => 'Ld. {ref}',
316 'See {title_ref}' => 'Ld. {title_ref}',
317 'September' => 'szeptember',
318 'Short Table of Contents' => 'Rövid tartalomjegyzék',
319 'Short table of contents' => 'Rövid tartalomjegyzék',
320 'Subsection One-Four' => 'alszakasz',
321 'Subsection One-One' => 'alszakasz',
322 'Subsection One-Three' => 'alszakasz',
323 'Subsection One-Two' => 'alszakasz',
324 'Subsubsection One-Two-Four' => 'alalszakasz',
325 'Subsubsection One-Two-One' => 'alalszakasz',
326 'Subsubsection One-Two-Three' => 'alalszakasz',
327 'Subsubsection One-Two-Two' => 'alalszakasz',
328 'T2H_today' => '%s, %d %d',
329 'Table of Contents' => 'Tartalomjegyzék',
330 'Table of contents' => 'Tartalomjegyzék',
331 'The node you are looking for is at {href}.' => 'A keresett csomópont itt található: {href}.',
333 'This document was generated on @i{{date}} using @uref{{program_homepage}, @i{{program}}}.' => 'Ezt a dokumentumot @i{{date}} napon generálta a(z) @uref{{program_homepage}, @i{{program}}}.',
334 'This document was generated using @uref{{program_homepage}, @emph{{program}}}.' => 'Ezt a dokumentumot a(z) @uref{{program_homepage}, @emph{{program}}} generálta.',
336 'Untitled Document' => 'Névtelen dokumentum',
338 'Up node' => 'Szülő csomópont',
339 'Up section' => 'Szülő szakasz',
340 'current' => 'aktuális',
341 'on @emph{{date}}' => 'ekkor: @emph{{date}}',
342 'section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'szakasz: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}',
343 'section `{section}\' in @cite{{book}}' => 'szakasz: `{section}\' itt: @cite{{book}}',
345 'see @cite{{book}}' => 'ld. @cite{{book}}',
346 'see section `@asis{}`{section_name}\'@asis{}\' in @cite{{book}}' => 'ld. ezt a szakaszt: `@asis{}`{section_name}\'@asis{}\' itt: @cite{{book}}',
347 'see section `{section}\' in @cite{{book}}' => 'ld. ezt a szakaszt: `{section}\' itt: @cite{{book}}',
348 'see section {reference_name}' => 'ld. ezt a szakaszt: {reference_name}',
349 'see {node_file_href}' => 'ld. {node_file_href}',
350 'see {node_file_href} @cite{{book}}' => 'ld. {node_file_href} @cite{{book}}',
351 'see {node_file_href} section `{section}\' in @cite{{book}}' => 'ld. {node_file_href} ezt a szakaszt: `{section}\' itt: @cite{{book}}',
352 'see {reference_name}' => 'ld. {reference_name}',
353 'see {ref}' => 'ld. {ref}',
354 'see {title_ref}' => 'ld. {title_ref}',
355 '{acronym_like} ({explanation})' => '{acronym_like} ({explanation})',
356 '{name} of {class}' => '{name} típusa: {class}',
357 '{name} on {class}' => '{name} ezen: {class}',
358 '{node_file_href}' => '{node_file_href}',
359 '{node_file_href} @cite{{book}}' => '{node_file_href} @cite{{book}}',
360 '{node_file_href} section `{section}\' in @cite{{book}}' => '{node_file_href} szakasz: `{section}\' itt: @cite{{book}}',
361 '{reference_name}' => '{reference_name}',
363 '{style} {number}' => '{style} {number}',
364 '{style}: {caption_first_line}' => '{style}: {caption_first_line}',
365 '{style}: {shortcaption_first_line}' => '{style}: {shortcaption_first_line}',
366 '{title_ref}' => '{title_ref}'
369 sub ly_get_string () {
370 my $lang = $Texi2HTML::THISDOC{current_lang};
372 if ($lang and $lang ne "en" and $LY_LANGUAGES->{$lang}->{$string}) {
373 return $LY_LANGUAGES->{$lang}->{$string};
380 #############################################################################
381 ### FUNCTIONALITY FOR MAIN WEB PAGES
382 #############################################################################
386 #############################################################################
387 ### SETTINGS FOR TEXI2HTML
388 #############################################################################
390 # Validation fix for texi2html<=1.82
391 $Texi2HTML::Config::DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
393 @Texi2HTML::Config::CSS_REFS = (
394 {FILENAME => "lilypond-mccarty.css", TITLE => "Default style"}
396 @Texi2HTML::Config::ALT_CSS_REFS = (
397 {FILENAME => "lilypond.css", TITLE => "Andrew Hawryluk's design" },
398 {FILENAME => "lilypond-blue.css", TITLE => "Kurt Kroon's blue design" },
402 print STDERR "Initializing settings for web site\n";
403 $Texi2HTML::Config::BODYTEXT = "";
404 @Texi2HTML::Config::CSS_REFS = (
405 {FILENAME => "lilypond-web.css", TITLE => "Patrick McCarty's design"}
407 @Texi2HTML::Config::ALT_CSS_REFS = (
408 {FILENAME => "lilypond-web-alt1.css", TITLE => "Alternate style 1"},
409 {FILENAME => "lilypond-web-alt2.css", TITLE => "Alternate style 2"},
413 # web_settings() if (exists($main::value{'web_manual'}));
415 $Texi2HTML::Config::USE_ACCESSKEY = 1;
416 $Texi2HTML::Config::USE_LINKS = 1;
417 $Texi2HTML::Config::USE_REL_REV = 1;
418 $Texi2HTML::Config::SPLIT_INDEX = 0;
419 $Texi2HTML::Config::SEPARATED_FOOTNOTES = 0; # Print footnotes on same page, not separated
421 if ($Texi2HTML::Config::SPLIT eq 'section' or
422 $Texi2HTML::Config::SPLIT eq 'node') {
423 $Texi2HTML::Config::element_file_name = \&lilypond_element_file_name;
426 $Texi2HTML::Config::element_target_name = \&lilypond_element_target_name;
427 $default_print_element_header = $Texi2HTML::Config::print_element_header;
428 $Texi2HTML::Config::print_element_header = \&lilypond_print_element_header;
429 $Texi2HTML::Config::print_page_foot = \&print_lilypond_page_foot;
430 $Texi2HTML::Config::print_navigation = \&lilypond_print_navigation;
431 $Texi2HTML::Config::external_ref = \&lilypond_external_ref;
432 $default_external_href = $Texi2HTML::Config::external_href;
433 $Texi2HTML::Config::external_href = \&lilypond_external_href;
434 $default_toc_body = $Texi2HTML::Config::toc_body;
435 $Texi2HTML::Config::toc_body = \&lilypond_toc_body;
436 $Texi2HTML::Config::css_lines = \&lilypond_css_lines;
437 $default_unknown = $Texi2HTML::Config::unknown;
438 $Texi2HTML::Config::unknown = \&lilypond_unknown;
439 $default_print_page_head = $Texi2HTML::Config::print_page_head;
440 $Texi2HTML::Config::print_page_head = \&lilypond_print_page_head;
441 # $Texi2HTML::Config::foot_line_and_ref = \&lilypond_foot_line_and_ref;
442 $Texi2HTML::Config::foot_line_and_ref = \&makeinfo_like_foot_line_and_ref;
443 $Texi2HTML::Config::foot_lines = \&makeinfo_like_foot_lines;
444 $Texi2HTML::Config::paragraph = \&makeinfo_like_paragraph;
448 # Examples should be formatted similar to quotes:
449 $Texi2HTML::Config::complex_format_map->{'example'} = {
450 'begin' => q{"<blockquote>"},
451 'end' => q{"</blockquote>\n"},
455 %Texi2HTML::config::misc_pages_targets = (
456 'Overview' => 'Overview',
457 'Contents' => 'Contents',
462 my @section_to_filename;
467 #############################################################################
469 #############################################################################
472 $Data::Dumper::Maxdepth = 2;
474 sub print_element_info($)
477 print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
478 print "Element: $element\n";
479 print Dumper($element);
486 #############################################################################
488 #############################################################################
490 # Convert a given node name to its proper file name (normalization as explained
491 # in the texinfo manual:
492 # http://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Xref-Node-Name-Expansion.html
493 sub texinfo_file_name($)
497 # File name normalization by texinfo:
498 # 1/2: letters and numbers are left unchanged
499 # 3/4: multiple, leading and trailing whitespace is removed
500 $text = main::normalise_space($text);
501 # 5/6: all remaining spaces are converted to '-', all other 7- or 8-bit
502 # chars are replaced by _xxxx (xxxx=ascii character code)
503 while ($text ne '') {
504 if ($text =~ s/^([A-Za-z0-9]+)//o) { # number or letter stay unchanged
506 } elsif ($text =~ s/^ //o) { # space -> '-'
508 } elsif ($text =~ s/^(.)//o) { # Otherwise use _xxxx (ascii char code)
510 if ( $ccode <= 0xFFFF ) {
511 $result .= sprintf("_%04x", $ccode);
513 $result .= sprintf("__%06x", $ccode);
517 # 7: if name does not begin with a letter, prepend 't_g' (so it starts with a letter)
518 if ($result !~ /^[a-zA-Z]/) {
519 $result = 't_g' . $result;
525 # Load a file containing a nodename<=>filename map (tab-sepatared, i.e.
526 # NODENAME\tFILENAME\tANCHOR
527 # Returns a ref to a hash "Node title" => ["FilenameWithoutExt", "Anchor"]
528 sub load_map_file ($)
533 # For some unknown reason, Perl on my system (5.10.0 on Fedora 12)
534 # refuses to open map files of translated documents with
535 # '<:encoding(utf8)', but decoding from UTF-8 line by line works. -jm
536 if (open(XREFFILE,'<', $mapfile)) {
538 # print STDERR "*** PRINTING MAP FILE LINES ***\n";
539 while ( $line = decode ('UTF-8', <XREFFILE>) ) {
540 # parse the tab-separated entries and insert them into the map:
542 my @entries = split(/\t/, $line);
543 if (scalar (@entries) == 3) {
544 $node_map->{$entries[0]} = [$entries[1], $entries[2]];
546 # print STDERR @entries;
549 print STDERR "Invalid entry in the node file $mapfile: $line\n";
554 print STDERR "WARNING: Unable to load the map file $mapfile\n";
560 # Split the given path into dir and basename (with .texi removed). Used mainly
561 # to get the path/basename of the original texi input file
562 sub split_texi_filename ($)
565 my ($docu_dir, $docu_name);
566 if ($docu =~ /(.*\/)/) {
567 chop($docu_dir = $1);
569 $docu_name =~ s/.*\///;
574 $docu_name =~ s/\.te?x(i|info)?$//;
575 return ($docu_dir, $docu_name);
582 #############################################################################
584 #############################################################################
586 # Include our standard CSS file, not hard-coded CSS code directly in the HTML!
587 # For IE, conditionally include the lilypond-ie-fixes.css style sheet
588 sub lilypond_css_lines ($$)
590 my $import_lines = shift;
591 my $rule_lines = shift;
592 return if (defined($Texi2HTML::THISDOC{'CSS_LINES'}));
593 if (@$rule_lines or @$import_lines)
595 $Texi2HTML::THISDOC{'CSS_LINES'} = "<style type=\"text/css\">\n<!--\n";
596 $Texi2HTML::THISDOC{'CSS_LINES'} .= join('',@$import_lines) . "\n" if (@$import_lines);
597 $Texi2HTML::THISDOC{'CSS_LINES'} .= join('',@$rule_lines) . "\n" if (@$rule_lines);
598 $Texi2HTML::THISDOC{'CSS_LINES'} .= "-->\n</style>\n";
600 foreach my $ref (@CSS_REFS)
602 $Texi2HTML::THISDOC{'CSS_LINES'} .= "<link rel=\"stylesheet\" type=\"text/css\" title=\"$ref->{TITLE}\" href=\"$ref->{FILENAME}\">\n";
604 foreach my $ref (@Texi2HTML::Config::ALT_CSS_REFS)
606 $Texi2HTML::THISDOC{'CSS_LINES'} .= "<link rel=\"alternate stylesheet\" type=\"text/css\" href=\"$ref->{FILENAME}\" title=\"$ref->{TITLE}\">\n";
608 # FIXME: the website doesn't use ie7-specific fixes; do the
609 # docs still need this? -gp
610 $Texi2HTML::THISDOC{'CSS_LINES'} .= "<!--[if lte IE 7]>\n<link href=\"lilypond-ie-fixes.css\" rel=\"stylesheet\" type=\"text/css\">\n<![endif]-->\n";
617 #############################################################################
618 ### SPLITTING BASED ON NUMBERED SECTIONS
619 #############################################################################
623 my $node_to_filename_map = ();
626 # This function makes sure that files are only generated for numbered sections,
627 # but not for unnumbered ones. It is called after texi2html has done its own
628 # splitting and simply returns the filename for the node given as first argument
629 # Nodes with the same filename will be printed out to the same filename, so
630 # this really all we need. Also, make sure that the file names for sections
631 # are derived from the section title. We also might want to name the anchors
632 # according to node titles, which works by simply overriding the id element of
634 # If an external nodename<=>filename/anchor map file is found (loaded in
635 # the command handler, use the externally created values, otherwise use the
637 sub lilypond_element_file_name($$$)
641 my $docu_name = shift;
642 my $docu_ext = $Texi2HTML::Config::EXTENSION;
644 my $node_name = main::remove_texi($element->{'node_ref'}->{'texi'});
645 # the snippets page does not use nodes for the snippets, so in this case
646 # we'll have to use the section name!
647 if ($node_name eq '') {
648 $node_name = main::remove_texi($element->{'texi'});
651 # If we have an entry in the section<=>filename map, use that one, otherwise
652 # generate the filename/anchor here. In the latter case, external manuals
653 # will not be able to retrieve the file name for xrefs!!! Still, I already
654 # had that code, so I'll leave it in in case something goes wrong with the
655 # extract_texi_filenames.py script in the lilypond build process!
656 if (exists ($node_to_filename_map->{$node_name})) {
657 (my $filename, my $anchor) = @{$node_to_filename_map->{$node_name}};
658 $filename .= ".$docu_ext" if (defined($docu_ext));
659 $filename = lc($filename);
661 # unnumbered sections (except those at top-level!) always go to the same
662 # file as the previous numbered section
663 if (not $docu_name == "web" and not ($element->{number})
664 and not ($lastfilename eq '') and ($element->{level} > 1)) {
665 $filename = $lastfilename;
667 if (($filename eq $lastfilename)) {
668 $$element{doc_nr} = $docnr;
671 $$element{doc_nr} = $docnr;
672 $lastfilename = $filename;
674 print STDERR "Output file name: $filename\n";
677 } elsif ($type eq "top" or $type eq "toc" or $type eq "doc" or $type eq "stoc" or $type eq "foot" or $type eq "about") {
680 print STDERR "WARNING: Node '$node_name' was NOT found in the map\n"
681 unless ($node_name eq '') or ($element->{'tag'} eq 'unnumberedsec')
682 or ($node_name =~ /NOT REALLY USED/);
684 # Numbered sections will get a filename Node_title, unnumbered sections will use
685 # the file name of the previous numbered section:
686 if (($element->{number}) or ($lastfilename eq '') or ($element->{level} == 1)) {
687 # normalize to the same file name as texinfo
688 if ($element->{translationof}) {
689 $node_name = main::remove_texi($element->{translationof});
691 my $filename = texinfo_file_name($node_name);
692 $filename .= ".$docu_ext" if (defined($docu_ext));
693 $filename = lc($filename);
695 $$element{doc_nr} = $docnr;
696 $lastfilename = $filename;
697 print STDERR "File name: $filename\n";
700 $$element{doc_nr} = $docnr;
701 $filename = lc ($filename);
702 print STDERR "File name: $filename\n";
710 sub lilypond_element_target_name($$$)
715 # Target is based on node name (or sec name for secs without node attached)
716 my $node_name = main::remove_texi($element->{'node_ref'}->{'texi'});
717 if ($node_name eq '') {
718 $node_name = main::remove_texi($element->{'texi'});
721 # If we have an entry in the section<=>filename map, use that one, otherwise
722 # generate the anchor here.
723 if (exists ($node_to_filename_map->{$node_name})) {
724 (my $filename, $target) = @{$node_to_filename_map->{$node_name}};
726 my $anchor = $node_name;
727 if ($element->{translationof}) {
728 $anchor = main::remove_texi($element->{translationof});
730 # normalize to the same file name as texinfo
731 $target = texinfo_file_name($anchor);
733 # TODO: Once texi2html correctly prints out the target and not the id for
734 # the sections, change this back to ($id, $target)
735 $target = lc($target);
736 return ($target, $target);
740 ## Load the map file for the corrently processed texi file. We do this
741 # using a command init handler, since texi2html does not have any
742 # other hooks that are called after THISDOC is filled but before phase 2
743 # of the texi2html conversion.
744 sub lilypond_init_map ()
746 my ($docu_dir, $docu_name) = split_texi_filename ($Texi2HTML::THISDOC{'input_file_name'});
747 my $map_filename = main::locate_include_file ("${docu_name}.$Texi2HTML::THISDOC{current_lang}.xref-map")
748 || main::locate_include_file ("${docu_name}.xref-map");
749 print STDERR "Map filename is: $map_filename\nDocu name is $docu_name\n";
750 if ($docu_name eq 'web') {
754 $node_to_filename_map = load_map_file ($map_filename);
756 push @Texi2HTML::Config::command_handler_init, \&lilypond_init_map;
760 #############################################################################
761 ### CLEANER LINK TITLE FOR EXTERNAL REFS
762 #############################################################################
764 # The default formatting of external refs returns e.g.
765 # "(lilypond-internals)Timing_translator", so we remove all (...) from the
766 # file_and_node argument. Also, we want only a very simple format, so we don't
767 # even call the default handler!
768 sub lilypond_external_ref($$$$$$)
773 my $file_node = shift;
774 my $href = lc(shift);
775 my $cross_ref = shift;
777 my $displaytext = '';
779 # 1) if we have a cross ref name, that's the text to be displayed:
780 # 2) For the top node, use the (printable) name of the manual, unless we
781 # have an explicit cross ref name
782 # 3) In all other cases use the section name
783 if ($cross_ref ne '') {
784 $displaytext = $cross_ref;
785 } elsif (($section eq '') or ($section eq 'Top')) {
786 $displaytext = $book;
788 $displaytext = $section;
791 $displaytext = &$anchor('', $href, $displaytext) if ($displaytext ne '');
792 return &$I('%{node_file_href}', { 'node_file_href' => $displaytext });
799 #############################################################################
800 ### HANDLING TRANSLATED SECTIONS: handle @translationof, secname<->filename
801 ### map stored on disk, xrefs in other manuals load that map
802 #############################################################################
805 # Try to make use of @translationof to generate files according to the original
806 # English section title...
807 sub lilypond_unknown($$$$$)
815 # the @translationof macro provides the original English section title,
816 # which should be used for file/anchor naming, while the title will be
817 # translated to each language
818 # It is already used by extract_texi_filenames.py, so this should not be
819 # necessary here at all. Still, I'll leave the code in just in case the
820 # python script messed up ;-)
821 if ($pass == 1 and $macro eq "translationof") {
822 if (ref($state->{'element'}) eq 'HASH') {
823 $state->{'element'}->{'translationof'} = main::normalise_space($line);
825 return ('', 1, undef, undef);
827 return &$default_unknown($macro, $line, $pass, $stack, $state);
834 my %translated_books = ();
835 # Construct a href to an external source of information.
836 # node is the node with texinfo @-commands
837 # node_id is the node transliterated and transformed as explained in the
839 # node_xhtml_id is the node transformed such that it is unique and can
840 # be used to make an html cross ref as explained in the texinfo manual
841 # file is the file in '(file)node'
842 sub lilypond_external_href($$$)
846 my $node_hxmlt_id = shift;
849 # 1) Keep a hash of book->section_map
850 # 2) if not file in keys hash => try to load the map (assign empty map if
851 # non-existent => will load only once!)
852 # 3) if node in the section=>(file, anchor) map, replace node_id and
853 # node_xhtml_id by the map's values
854 # 4) call the default_external_href with these values (or the old ones if not found)
856 if (($node_id ne '') and defined($file) and ($node_id ne 'Top')) {
857 my $map_name = $file;
858 $map_name =~ s/-big-page//;
860 # Load the map if we haven't done so already
861 if (!exists($translated_books{$map_name})) {
862 my ($docu_dir, $docu_name) = split_texi_filename ($Texi2HTML::THISDOC{'input_file_name'});
863 my $map_filename = main::locate_include_file ("${map_name}.$Texi2HTML::THISDOC{current_lang}.xref-map")
864 || main::locate_include_file ("${map_name}.xref-map");
865 $translated_books{$map_name} = load_map_file ($map_filename);
868 # look up translation. use these values instead of the old filename/anchor
869 my $section_name_map = $translated_books{$map_name};
870 my $node_text = main::remove_texi($node);
871 if (defined($section_name_map->{$node_text})) {
872 ($node_id, $node_hxmlt_id) = @{$section_name_map->{$node_text}};
874 print STDERR "WARNING: Unable to find node '$node_text' in book $map_name.\n";
879 return &$default_external_href($node, $node_id, $node_hxmlt_id, lc($file));
881 return &$default_external_href($node, $node_id, $node_hxmlt_id);
889 #############################################################################
890 ### CUSTOM TOC FOR EACH PAGE (in a frame on the left)
891 #############################################################################
893 my $page_toc_depth = 2;
894 my @default_toc = [];
896 # Initialize the toc_depth to 1 if the command-line option -D=short_toc is given
897 sub lilypond_init_toc_depth ()
899 if (exists($main::value{'short_toc'}) and not exists($main::value{'bigpage'})
900 and not $web_manual) {
904 # Set the TOC-depth (depending on a texinfo variable short_toc) in a
905 # command-handler, so we have them available when creating the pages
906 push @Texi2HTML::Config::command_handler_process, \&lilypond_init_toc_depth;
910 # recursively generate the TOC entries for the element and its children (which
911 # are only shown up to maxlevel. All ancestors of the current element are also
912 # shown with their immediate children, irrespective of their level.
913 # Unnumbered entries are only printed out if they are at top-level or 2nd level
914 # or their parent element is an ancestor of the currently viewed node.
915 # The conditions to call this method to print the entry for a child node is:
916 # -) the parent is an ancestor of the current page node
917 # -) the parent is a numbered element at top-level toplevel (i.e. show numbered
918 # and unnumbered 2nd-level children of numbered nodes)
919 # -) the child element is a numbered node below level maxlevel
920 sub generate_ly_toc_entries($$$)
923 my $element_path = shift;
927 my $maxlevel = shift;
929 # Skip undefined sections, plus all sections generated by index splitting
930 return() if (not defined($element) or exists($element->{'index_page'}));
932 my $level = $element->{'toc_level'};
933 my $is_parent_of_current = $element->{'id'} && $element_path->{$element->{'id'}};
934 my $ind = ' ' x $level;
937 $this_css_class = " class=\"";
939 $this_css_class = "";
941 $this_css_class .= $is_parent_of_current ? " toc_current" : "";
944 "Learning", "Glossary", "Essay",
945 "Contact", "Tiny examples", "Bug reports"
948 "Features", "Examples", "Freedom", "Background",
949 "Unix", "MacOS X", "Windows",
950 "Notation", "Usage", "Snippets",
951 "Help us", "Development", "Authors"
954 "Productions", "Testimonials",
955 "Source", "Old downloads",
956 "Web", "FAQ", "Changes", "Extend", "Internals",
957 "Publications", "Old news"
960 "Text input", "Alternate input",
962 "Translated", "All", "FDL"
965 my $addColor = " colorDefault";
966 foreach $color (@color_1) {
967 if ($element->{'text'} eq $color) {
968 $addColor = " color1";
971 foreach $color (@color_2) {
972 if ($element->{'text'} eq $color) {
973 $addColor = " color2";
976 foreach $color (@color_3) {
977 if ($element->{'text'} eq $color) {
978 $addColor = " color3";
981 foreach $color (@color_4) {
982 if ($element->{'text'} eq $color) {
983 $addColor = " color4";
987 $this_css_class .= $addColor . "\"";
990 my $entry = "$ind<li$this_css_class>" . &$anchor ($element->{'tocid'}, "$element->{'file'}#$element->{'target'}",$element->{'text'});
992 push (@result, $entry);
993 my $children = $element->{'section_childs'};
994 if (defined($children) and (ref($children) eq "ARRAY")) {
995 my $force_children = $is_parent_of_current or ($level == 1 and $element->{'number'});
996 my @child_result = ();
997 foreach my $c (@$children) {
998 my $is_numbered_child = defined ($c->{'number'});
999 my $below_maxlevel = $c->{'toc_level'} le $maxlevel;
1000 if ($force_children or ($is_numbered_child and $below_maxlevel)) {
1001 my @child_res = generate_ly_toc_entries($c, $element_path, $maxlevel);
1002 push (@child_result, @child_res);
1005 # if no child nodes were generated, e.g. for the index, where expanded pages
1006 # are ignored, don't generate a list at all...
1007 if (@child_result) {
1008 push (@result, "\n$ind<ul$NO_BULLET_LIST_ATTRIBUTE>\n");
1010 push (@result, "$ind<li$this_css_class>" . &$anchor ($element->{'tocid'}, "$element->{'file'}#$element->{'target'}","(main)"));
1012 push (@result, @child_result);
1013 push (@result, "$ind</ul>\n");
1016 push (@result, "$ind</li>\n");
1021 # Print a customized TOC, containing only the first two levels plus the whole
1022 # path to the current page
1023 sub lilypond_generate_page_toc_body($)
1025 my $element = shift;
1026 my $current_element = $element;
1028 $parentelements{$element->{'id'}} = 1;
1029 # Find the path to the current element
1030 while ( defined($current_element->{'sectionup'}) and
1031 ($current_element->{'sectionup'} ne $current_element) )
1033 $parentelements{$current_element->{'sectionup'}->{'id'}} = 1
1034 if ($current_element->{'sectionup'}->{'id'} ne '');
1035 $current_element = $current_element->{'sectionup'};
1037 if (exists($main::value{'shallow_toc'})) {
1042 return () if not defined($current_element);
1043 # Create the toc entries recursively
1044 my @toc_entries = "";
1046 @toc_entries = "<ul$NO_BULLET_LIST_ATTRIBUTE>\n";
1047 # FIXME: add link to main page, really hackily.
1048 if ($element->{'sectionup'}) {
1049 # it's not the top element
1050 push (@toc_entries, "<li><a href=\"index.html\">Main</a></li>\n");
1052 push (@toc_entries, "<li class=\"toc_current\"><a href=\"index.html\">Main</a></li>\n");
1055 push (@toc_entries, "<div class=\"contents\">\n");
1056 push (@toc_entries, "<ul$NO_BULLET_LIST_ATTRIBUTE>\n");
1058 my $children = $current_element->{'section_childs'};
1059 foreach ( @$children ) {
1060 push (@toc_entries, generate_ly_toc_entries($_, \%parentelements, $page_toc_depth));
1063 if ($sergsmoeivjriohuemf) {
1064 # WTF, perl needs 6 lines of magic to do: ' ' + open ('file-name').read ()?
1066 my $name = "search-box.html";
1067 open FILE, "$ENV{SRC_DIR}/$name" or open FILE, "$ENV{SRC_DIR}/../$name" or die "no such file: $name: $!";
1069 my $string = <FILE>;
1070 $string = "<li>\n" . $string . "</li>\n";
1071 push (@toc_entries, $string);
1074 push (@toc_entries, "</ul>\n");
1076 push (@toc_entries, "\n");
1078 push (@toc_entries, "</div>\n");
1080 return @toc_entries;
1083 sub lilypond_print_toc_div ($$)
1087 my @lines = @$tocref;
1088 # use default TOC if no custom lines have been generated
1089 @lines = @default_toc if (not @lines);
1092 print $fh "\n\n<div id=\"tocframe\">\n";
1094 # Remove the leading "GNU LilyPond --- " from the manual title
1095 my $topname = $Texi2HTML::NAME{'Top'};
1096 $topname =~ s/^GNU LilyPond(:| &[mn]dash;) //;
1098 # construct the top-level Docs index (relative path and including language!)
1099 my $lang = $Texi2HTML::THISDOC{current_lang};
1100 if ($lang and $lang ne "en") {
1106 $reldir = "../" if ($Texi2HTML::Config::SPLIT eq 'section');
1107 my $uplink = $reldir."web/manuals.${lang}html";
1109 if (not $web_manual) {
1110 print $fh "<p class=\"toc_uplink\"><a href=\"$uplink\"
1111 title=\"Documentation Index\"><< " .
1112 &ly_get_string ('Back to Documentation Index') .
1115 print $fh '<h4 class="toc_header"> ' . &$anchor('',
1116 $Texi2HTML::HREF{'Top'},
1118 'title="Start of the manual"'
1122 foreach my $line (@lines) {
1125 print $fh "</div>\n\n";
1129 # Create the custom TOC for this page (partially folded, current page is
1130 # highlighted) and store it in a global variable. The TOC is written out after
1131 # the html contents (but positioned correctly using CSS), so that browsers with
1132 # css turned off still show the contents first.
1133 our @this_page_toc = ();
1134 sub lilypond_print_element_header
1136 my $first_in_page = shift;
1137 my $previous_is_top = shift;
1138 if ($first_in_page and not @this_page_toc) {
1139 if (defined($Texi2HTML::THIS_ELEMENT)) {
1140 # Create the TOC for this page
1141 @this_page_toc = lilypond_generate_page_toc_body($Texi2HTML::THIS_ELEMENT);
1144 return &$default_print_element_header( $first_in_page, $previous_is_top);
1147 # Generate the HTML output for the TOC
1148 sub lilypond_toc_body($)
1150 my $elements_list = shift;
1151 # Generate a default TOC for pages without THIS_ELEMENT
1152 @default_toc = lilypond_generate_page_toc_body(@$elements_list[0]);
1153 return &$default_toc_body($elements_list);
1156 # Print out the TOC in a <div> at the beginning of the page
1157 sub lilypond_print_page_head($)
1160 &$default_print_page_head($fh);
1161 print $fh "<div id=\"main\">\n";
1164 # Print out the TOC in a <div> at the end of th page, which will be formatted as a
1165 # sidebar mimicking a TOC frame
1166 sub print_lilypond_page_foot($)
1169 my $program_string = &$program_string();
1170 # print $fh "<p><font size='-1'>$program_string</font><br>$PRE_BODY_CLOSE</p>\n";
1171 print $fh "<!-- FOOTER -->\n\n";
1172 print $fh "<!-- end div#main here -->\n</div>\n\n";
1175 # FIXME: This div and p#languages need to be in div#footer.
1176 # Should we move this div to postprocess_html.py ?
1177 print $fh "<div id=\"verifier_texinfo\">\n";
1178 print $fh "<h3>Validation</h3>\n";
1179 print $fh "<p>Thanks to <a href=\"http://www.webdev.nl/\">webdev.nl</a>";
1180 print $fh " for hosting <code>lilypond.org</code>.\n";
1181 print $fh "<a href=\"http://validator.w3.org/check?uri=referer\">\n";
1182 print $fh "<img src=\"http://www.w3.org/Icons/valid-html401\"\n";
1183 print $fh " alt=\"Valid HTML 4.01 Transitional\"\n";
1184 print $fh " height=\"31\" width=\"88\"></a></p>\n";
1188 # Print the TOC frame and reset the TOC:
1189 lilypond_print_toc_div ($fh, \@this_page_toc);
1190 @this_page_toc = ();
1193 print $fh "</body>\n</html>\n";
1200 #############################################################################
1201 ### NICER / MORE FLEXIBLE NAVIGATION PANELS
1202 #############################################################################
1204 sub get_navigation_text
1207 my $text = $NAVIGATION_TEXT{$button};
1208 if ( ($button eq 'Back') or ($button eq 'FastBack') ) {
1209 $text = $text . $Texi2HTML::NODE{$button} . " ";
1210 } elsif ( ($button eq 'Forward') or ($button eq 'FastForward') ) {
1211 $text = " " . $Texi2HTML::NODE{$button} . $text;
1212 } elsif ( $button eq 'Up' ) {
1213 $text = " ".$text.": " . $Texi2HTML::NODE{$button} . " ";
1219 # Don't automatically create left-aligned table cells for every link, but
1220 # instead create a <td> only on an appropriate '(left|right|center)-aligned-cell-n'
1221 # button text. It's alignment as well as the colspan will be taken from the
1222 # name of the button. Also, add 'newline' button text to create a new table
1223 # row. The texts of the buttons are generated by get_navigation_text and
1224 # will contain the name of the next/previous section/chapter.
1225 sub lilypond_print_navigation
1227 my $buttons = shift;
1228 my $vertical = shift;
1230 my $result = "<table class=\"nav_table\">\n";
1232 $result .= "<tr>" unless $vertical;
1233 my $beginofline = 1;
1234 foreach my $button (@$buttons)
1236 $result .= qq{<tr valign="top" align="left">\n} if $vertical;
1237 # Allow (left|right|center)-aligned-cell and newline as buttons!
1238 if ( $button =~ /^(.*)-aligned-cell-(.*)$/ )
1240 $result .= qq{</td>} unless $beginofline;
1241 $result .= qq{<td valign="middle" align="$1" colspan="$2">};
1244 elsif ( $button eq 'newline' )
1246 $result .= qq{</td>} unless $beginofline;
1247 $result .= qq{</tr>};
1248 $result .= qq{<tr>};
1252 elsif (ref($button) eq 'CODE')
1254 $result .= &$button($vertical);
1256 elsif (ref($button) eq 'SCALAR')
1258 $result .= "$$button" if defined($$button);
1260 elsif (ref($button) eq 'ARRAY')
1262 my $text = $button->[1];
1263 my $button_href = $button->[0];
1264 # verify that $button_href is simple text and text is a reference
1265 if (defined($button_href) and !ref($button_href)
1266 and defined($text) and (ref($text) eq 'SCALAR') and defined($$text))
1268 if ($Texi2HTML::HREF{$button_href})
1270 my $anchor_attributes = '';
1271 if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button_href})) and ($BUTTONS_ACCESSKEY{$button_href} ne ''))
1273 $anchor_attributes = "accesskey=\"$BUTTONS_ACCESSKEY{$button_href}\"";
1275 if ($USE_REL_REV and (defined($BUTTONS_REL{$button_href})) and ($BUTTONS_REL{$button_href} ne ''))
1277 $anchor_attributes .= " rel=\"$BUTTONS_REL{$button_href}\"";
1281 $Texi2HTML::HREF{$button_href},
1282 get_navigation_text($$text),
1288 $result .= get_navigation_text($$text);
1292 elsif ($button eq ' ')
1293 { # handle space button
1295 ($ICONS && $ACTIVE_ICONS{' '}) ?
1296 &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) :
1297 $NAVIGATION_TEXT{' '};
1300 elsif ($Texi2HTML::HREF{$button})
1301 { # button is active
1302 my $btitle = $BUTTONS_GOTO{$button} ?
1303 'title="' . $BUTTONS_GOTO{$button} . '"' : '';
1304 if ($USE_ACCESSKEY and (defined($BUTTONS_ACCESSKEY{$button})) and ($BUTTONS_ACCESSKEY{$button} ne ''))
1306 $btitle .= " accesskey=\"$BUTTONS_ACCESSKEY{$button}\"";
1308 if ($USE_REL_REV and (defined($BUTTONS_REL{$button})) and ($BUTTONS_REL{$button} ne ''))
1310 $btitle .= " rel=\"$BUTTONS_REL{$button}\"";
1312 if ($ICONS && $ACTIVE_ICONS{$button})
1316 $Texi2HTML::HREF{$button},
1317 &$button_icon_img($BUTTONS_NAME{$button},
1318 $ACTIVE_ICONS{$button},
1319 $Texi2HTML::SIMPLE_TEXT{$button}),
1328 $Texi2HTML::HREF{$button},
1329 get_navigation_text($button),
1336 { # button is passive
1338 $ICONS && $PASSIVE_ICONS{$button} ?
1339 &$button_icon_img($BUTTONS_NAME{$button},
1340 $PASSIVE_ICONS{$button},
1341 $Texi2HTML::SIMPLE_TEXT{$button}) :
1343 "[" . get_navigation_text($button) . "]";
1345 $result .= "</td>\n" if $vertical;
1346 $result .= "</tr>\n" if $vertical;
1348 $result .= "</td>" unless $beginofline;
1349 $result .= "</tr>" unless $vertical;
1350 $result .= "</table>\n";
1359 @Texi2HTML::Config::SECTION_BUTTONS =
1360 ('left-aligned-cell-1', 'FastBack',
1361 'center-aligned-cell-3', 'Top', 'Contents', 'Index', 'About',
1362 'right-aligned-cell-1', 'FastForward',
1364 'left-aligned-cell-2', 'Back',
1365 'center-aligned-cell-1', 'Up',
1366 'right-aligned-cell-2', 'Forward'
1369 # buttons for misc stuff
1370 @Texi2HTML::Config::MISC_BUTTONS = ('center-aligned-cell-3', 'Top', 'Contents', 'Index', 'About');
1372 # buttons for chapter file footers
1373 # (and headers but only if SECTION_NAVIGATION is false)
1374 @Texi2HTML::Config::CHAPTER_BUTTONS =
1375 ('left-aligned-cell-1', 'FastBack',
1376 'center-aligned-cell-3', 'Top', 'Contents', 'Index', 'About',
1377 'right-aligned-cell-1', 'FastForward',
1380 # buttons for section file footers
1381 @Texi2HTML::Config::SECTION_FOOTER_BUTTONS =
1382 ('left-aligned-cell-1', 'FastBack',
1383 'center-aligned-cell-3', 'Top', 'Contents', 'Index', 'About',
1384 'right-aligned-cell-1', 'FastForward',
1386 'left-aligned-cell-2', 'Back',
1387 'center-aligned-cell-1', 'Up',
1388 'right-aligned-cell-2', 'Forward'
1391 @Texi2HTML::Config::NODE_FOOTER_BUTTONS =
1392 ('left-aligned-cell-1', 'FastBack',
1393 'center-aligned-cell-3', 'Top', 'Contents', 'Index', 'About',
1394 'right-aligned-cell-1', 'FastForward',
1396 'left-aligned-cell-2', 'Back',
1397 'center-aligned-cell-1', 'Up',
1398 'right-aligned-cell-2', 'Forward'
1405 #############################################################################
1406 ### FOOTNOTE FORMATTING
1407 #############################################################################
1409 # Format footnotes in a nicer way: Instead of printing the number in a separate
1410 # (nr) heading line, use the standard way of prepending <sup>nr</sup> immediately
1411 # before the fn text.
1414 # The following code is copied from texi2html's examples/makeinfo.init and
1415 # should be updated when texi2html makes some changes there!
1417 my $makekinfo_like_footnote_absolute_number = 0;
1419 sub makeinfo_like_foot_line_and_ref($$$$$$$$)
1421 my $foot_num = shift;
1422 my $relative_num = shift;
1425 my $from_file = shift;
1426 my $footnote_file = shift;
1430 $makekinfo_like_footnote_absolute_number++;
1432 # this is a bit obscure, this allows to add an anchor only if formatted
1433 # as part of the document.
1434 $docid = '' if ($state->{'outside_document'} or $state->{'multiple_pass'});
1436 if ($from_file eq $footnote_file)
1438 $from_file = $footnote_file = '';
1441 my $foot_anchor = "<sup>" . &$anchor($docid, "$footnote_file#$footid", $relative_num) . "</sup>";
1442 $foot_anchor = &$anchor($docid, "$footnote_file#$footid", "($relative_num)") if ($state->{'preformatted'});
1444 # unshift @$lines, "<li>";
1445 # push @$lines, "</li>\n";
1446 return ($lines, $foot_anchor);
1449 sub makeinfo_like_foot_lines($)
1452 unshift @$lines, "<hr>\n<h4>$Texi2HTML::I18n::WORDS->{'Footnotes_Title'}</h4>\n";
1453 #<ol type=\"1\">\n";
1454 # push @$lines, "</ol>";
1458 my %makekinfo_like_paragraph_in_footnote_nr;
1460 sub makeinfo_like_paragraph ($$$$$$$$$$$$$)
1465 my $paragraph_command = shift;
1466 my $paragraph_command_formatted = shift;
1467 my $paragraph_number = shift;
1469 my $item_nr = shift;
1470 my $enumerate_style = shift;
1472 my $command_stack_at_end = shift;
1473 my $command_stack_at_begin = shift;
1475 #print STDERR "format: $format\n" if (defined($format));
1476 #print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n";
1477 $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or
1478 exists($special_list_commands{$format}->{$paragraph_command}));
1479 return '' if ($text =~ /^\s*$/);
1480 foreach my $style(t2h_collect_styles($command_stack_at_begin))
1482 $text = t2h_begin_style($style, $text);
1484 foreach my $style(t2h_collect_styles($command_stack_at_end))
1486 $text = t2h_end_style($style, $text);
1488 if (defined($paragraph_number) and defined($$paragraph_number))
1490 $$paragraph_number++;
1491 return $text if (($format eq 'itemize' or $format eq 'enumerate') and
1492 ($$paragraph_number == 1));
1497 $open .= " align=\"$paragraph_style{$align}\"";
1499 my $footnote_text = '';
1500 if (defined($command_stack_at_begin->[0]) and $command_stack_at_begin->[0] eq 'footnote')
1502 my $state = $Texi2HTML::THISDOC{'state'};
1503 $makekinfo_like_paragraph_in_footnote_nr{$makekinfo_like_footnote_absolute_number}++;
1504 if ($makekinfo_like_paragraph_in_footnote_nr{$makekinfo_like_footnote_absolute_number} <= 1)
1506 $open.=' class="footnote"';
1507 my $document_file = $state->{'footnote_document_file'};
1508 if ($document_file eq $state->{'footnote_footnote_file'})
1510 $document_file = '';
1512 my $docid = $state->{'footnote_place_id'};
1513 my $doc_state = $state->{'footnote_document_state'};
1514 $docid = '' if ($doc_state->{'outside_document'} or $doc_state->{'multiple_pass'});
1515 my $foot_label = &$anchor($state->{'footnote_footnote_id'},
1516 $document_file . "#$state->{'footnote_place_id'}",
1517 "$state->{'footnote_number_in_page'}");
1518 $footnote_text = "<small>[${foot_label}]</small> ";
1521 return $open.'>'.$footnote_text.$text.'</p>';
1525 #############################################################################
1527 #############################################################################
1529 # For split pages, use index.html as start page!
1530 if ($Texi2HTML::Config::SPLIT eq 'section' or
1531 $Texi2HTML::Config::SPLIT eq 'node') {
1532 $Texi2HTML::Config::TOP_FILE = 'index.html';