#!/usr/bin/env perl package Texi2HTML::Config; my $lastfilename; my $docnr = 0; my $page_toc_depth = 2; my @default_toc = []; my @section_to_filename; use Data::Dumper; $Data::Dumper::Maxdepth = 2; sub print_element_info($) { my $element = shift; print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; print "Element: $element\n"; print Dumper($element); } # Convert a given node name to its proper file name (normalization as explained # in the texinfo manual: # http://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Xref-Node-Name-Expansion.html sub texinfo_file_name($) { my $str = shift; # File name normalization by texinfo: # 1/2: letters and numbers are left unchanged # 3/4: multiple, leading and trailing whitespace is removed $str = main::normalise_space($str); # 5/6: all remaining spaces are converted to '-', all other 7- or 8-bit # chars are replaced by _xxxx (xxxx=ascii character code) my @chars = split(//, $str); my $str = ''; foreach my $char (@chars) { if ( $char eq ' ' ) { # space -> '-' $str .= '-'; } elsif ( ('0' le $char and $char le '9' ) or ('A' le $char and $char le 'Z' ) or ('a' le $char and $char le 'z' ) ) { # number or letter $str .= $char; } else { my $ccode = ord($char); my $addstr; if ( ord($char)<= 0xFFFF ) { $addstr = sprintf("_%4x", $ccode); } else { $addstr = sprintf("__%6x", $ccode); } # padding is done by spaces, replace by '0' $addstr =~ s/\ /0/g; $str .= $addstr; } } # 7: if name begins with number, prepend 't_g' (so it starts with a letter) if ($str =~ /^[0-9]/) { $str = 't_g' . $str; } # DONE return $str } # This function makes sure that files are only generated for numbered sections, # but not for unnumbered ones. It is called after texi2html has done its own # splitting and simply returns the filename for the node given as first argument # Nodes with the same filename will be printed out to the same filename, so # this really all we need. Also, make sure that the file names for sections # are derived from the section title. We also might want to name the anchors # according to node titles, which works by simply overriding the id element of # the $element hash. sub split_at_numbered_sections($$$) { my $element = shift; my $type = shift; my $docu_name = shift; my $docu_ext = $Texi2HTML::Config::EXTENSION; # TOC, footer, about etc. are called with undefined $element and $type == "toc"|"stoc"|"foot"|"about" if ($type eq "toc" or $type eq "stoc" or $type eq "foot" or $type eq "about") { return; } else { # derive the name of the anchor (i.e. the part after # in the links!), # don't use texi2html's SECx.x default! my $sec_name = main::remove_texi($$element{texi}); my $anchor = $sec_name; if ($$element{translationof}) { $anchor = main::remove_texi($$element{translationof}); } # normalize to the same file name as texinfo $anchor = texinfo_file_name($anchor); $$element{id} = $anchor; # Numbered sections will get a filename Section_1.1.2, unnumbered sections will use # the file name of the previous numbered section: if ($$element{number}) { my $filename = $anchor; $filename .= ".$docu_ext" if (defined($docu_ext)); $docnr += 1; $$element{doc_nr} = $docnr; $lastfilename = $filename; push (@section_to_filename, [$sec_name, $filename, $anchor]); return $filename; } else { $$element{doc_nr} = $docnr; push (@section_to_filename, [$sec_name, $lastfilename, $anchor]); return $lastfilename; } } return; } sub lilypond_finish_out() { my $map_filename = "$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}_xref.map"; if (open(XREFFILE, ">$map_filename")) { foreach (@section_to_filename) { my ($sec, $file, $anchor) = @$_; print XREFFILE "$sec\t$file\t$anchor\n"; } close XREFFILE; } else { print "Can't open $map_filename for writing: $! The map of X-refs will not be written out\n"; } } # The default formatting of external refs returns e.g. # "(lilypond-internals)Timing_translator", so we remove all (...) from the # file_and_node argument. Also, we want only a very simple format, so we don't # even call the default handler! sub lilypond_external_ref($$$$$$) { my $type = shift; my $section = shift; my $book = shift; my $file_node = shift; my $href = shift; my $cross_ref = shift; $file_node =~ s/\(.*\)//; $file_node = &$anchor('', $href, $file_node) if ($file_node ne ''); return &$I('%{node_file_href}', { 'node_file_href' => $file_node }); # Default: format as "see NODE section 'SECTION' in BOOK" # return t2h_default_external_ref($type, $section, $book, $file_node, $href, $cross_ref); } # Construct a href to an external source of information. # node is the node with texinfo @-commands # node_id is the node transliterated and transformed as explained in the # texinfo manual # node_xhtml_id is the node transformed such that it is unique and can # be used to make an html cross ref as explained in the texinfo manual # file is the file in '(file)node' sub lilypond_external_href($$$) { my $node = shift; my $node_id = shift; my $node_xhtml_id = shift; my $file = shift; # TODO: # 1) Keep a hash of book->section_map # 2) if not file in keys hash => try to load the map (assign empty map is non-existent => will load only once!) # 3) if node in the section=>(file, anchor) map, replace node_id and node_xhtml_id by the map's values # 4) call the t2h_default_external_href with these values (or the old ones if not found) print STDERR "lilypond_external_href: texi_node='$node', node_file='$node_id', node_xhtml_id='$node_xhtml_id', file='$file'\n\n"; # # $file = '' if (!defined($file)); # my $default_target_split = $EXTERNAL_CROSSREF_SPLIT; # my $target_split; # my $target_mono; # my $href_split; # my $href_mono; # if ($file ne '') # { # if ($NEW_CROSSREF_STYLE) # { # $file =~ s/\.[^\.]*$//; # $file =~ s/^.*\///; # my $href; # if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file})) # { # if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'})) # { # $target_split = 1; # $href_split = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}->{'href'}; # } # if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'})) # { # $target_mono = 1; # $href_mono = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}->{'href'}; # } # } # # if ((not $target_mono) and (not $target_split)) # { # nothing specified for that manual, use default # $target_split = $default_target_split; # } # elsif ($target_split and $target_mono) # { # depends on the splitting of the manual # $target_split = $SPLIT; # } # elsif ($target_mono) # { # only mono specified # $target_split = 0; # } # # if ($target_split) # { # if (defined($href_split)) # { # $file = "$href_split"; # } # elsif (defined($EXTERNAL_DIR)) # { # $file = "$EXTERNAL_DIR/$file"; # } # elsif ($SPLIT) # { # $file = "../$file"; # } # $file .= "/"; # } # else # {# target not split # if (defined($href_mono)) # { # $file = "$href_mono"; # } # else # { # if (defined($EXTERNAL_DIR)) # { # $file = "$EXTERNAL_DIR/$file"; # } # elsif ($SPLIT) # { # $file = "../$file"; # } # $file .= "." . $NODE_FILE_EXTENSION; # } # } # } # else # { # $file .= "/"; # if (defined($EXTERNAL_DIR)) # { # $file = $EXTERNAL_DIR . $file; # } # else # { # $file = '../' . $file; # } # } # } # else # { # $target_split = $default_target_split; # } # if ($node eq '') # { # if ($NEW_CROSSREF_STYLE) # { # if ($target_split) # { # return $file . $TOP_NODE_FILE . '.' . $NODE_FILE_EXTENSION . '#Top'; # # or ? # #return $file . '#Top'; # } # else # { # return $file . '#Top'; # } # } # else # { # return $file; # } # } # my $target; # if ($NEW_CROSSREF_STYLE) # { # $node = $node_id; # $target = $node_xhtml_id; # } # else # { # $node = main::remove_texi($node); # $node =~ s/[^\w\.\-]/-/g; # } # my $file_basename = $node; # $file_basename = $TOP_NODE_FILE if ($node =~ /^top$/i); # if ($NEW_CROSSREF_STYLE) # { # if ($target_split) # { # return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target; # } # else # { # return $file . '#' . $target; # } # } # else # { # return $file . $file_basename . ".$NODE_FILE_EXTENSION"; # } return t2h_default_external_href($node, $node_id, $node_hxmlt_id, $file); } # recursively generate the TOC entries for the element and its children (which # are only shown up to maxlevel. All ancestors of the current element are also # shown with their immediate children, irrespective of their level. sub generate_ly_toc_entries($$$) { my $element = shift; my $element_path = shift; my $maxlevel = shift; # Skip undefined sections, plus all sections generated by index splitting return() if (not defined($element) or exists($element->{'index_page'})); my @result = (); my $level = $element->{'toc_level'}; my $is_parent_of_current = $element_path->{$element->{'number'}}; my $print_children = ( ($level < $maxlevel) or $is_parent_of_current ); my $ind = ' ' x $level; my $this_css_class = $is_parent_of_current ? " class=\"toc_current\"" : ""; my $entry = "$ind
$program_string
$PRE_BODY_CLOSE