1#! /usr/bin/perl -- # perl 2'di '; 3'ig 00 '; 4#+############################################################################## 5# 6# texi2html: Program to transform Texinfo documents to HTML 7# 8# Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>, 9# Derek Price <derek@ximbiot.com>, 10# Adrian Aichner <adrian@xemacs.org>, 11# & others. 12# 13# This program is free software; you can redistribute it and/or modify 14# it under the terms of the GNU General Public License as published by 15# the Free Software Foundation; either version 2 of the License, or 16# (at your option) any later version. 17# 18# This program is distributed in the hope that it will be useful, 19# but WITHOUT ANY WARRANTY; without even the implied warranty of 20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21# GNU General Public License for more details. 22# 23# You should have received a copy of the GNU General Public License 24# along with this program; if not, write to the Free Software 25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26# 02110-1301 USA 27# 28#-############################################################################## 29# The man page for this program is included at the end of this file and can be 30# viewed using the command 'nroff -man texi2html'. 31 32# for POSIX::setlocale and File::Spec 33require 5.00405; 34# Perl pragma to restrict unsafe constructs 35use strict; 36# used in case of tests, to revert to "C" locale. 37use POSIX qw(setlocale LC_ALL LC_CTYPE); 38# used to obtain the name of the current working directory 39use Cwd; 40# used to find a relative path back to the current working directory 41use File::Spec; 42 43# 44# According to 45# larry.jones@sdrc.com (Larry Jones) 46# this pragma is not present in perl5.004_02: 47# 48# Perl pragma to control optional warnings 49# use warnings; 50 51#++########################################################################## 52# 53# NOTE FOR DEBUGGING THIS SCRIPT: 54# You can run 'perl texi2html.pl' directly, provided you have 55# the environment variable T2H_HOME set to the directory containing 56# the texi2html.init, T2h_i18n.pm, translations.pl, l2h.init, 57# T2h_l2h.pm files 58# 59#--########################################################################## 60 61# CVS version: 62# $Id: texi2html.pl,v 1.182 2007/05/07 22:56:02 pertusus Exp $ 63 64# Homepage: 65my $T2H_HOMEPAGE = "https://www.nongnu.org/texi2html/"; 66 67# Authors (appears in comments): 68my $T2H_AUTHORS = <<EOT; 69Written by: Lionel Cons <Lionel.Cons\@cern.ch> (original author) 70 Karl Berry <karl\@freefriends.org> 71 Olaf Bachmann <obachman\@mathematik.uni-kl.de> 72 and many others. 73Maintained by: Many creative people. 74Send bugs and suggestions to <texi2html-bug\@nongnu.org> 75EOT 76 77# Version: set in configure.in 78my $THISVERSION = '1.78a'; 79my $THISPROG = "texi2html $THISVERSION"; # program name and version 80 81#+++######################################################################## 82# # 83# Paths and file names # 84# # 85#---######################################################################## 86 87# set by configure, prefix for the sysconfdir and so on 88my $prefix = '/usr/local'; 89my $sysconfdir; 90my $pkgdatadir; 91my $datadir; 92 93# We need to eval as $prefix has to be expanded. However when we haven't 94# run configure @sysconfdir will be expanded as an array, thus we verify 95# whether configure was run or not 96if ('${prefix}/etc' ne '@' . 'sysconfdir@') 97{ 98 $sysconfdir = eval '"${prefix}/etc"'; 99} 100else 101{ 102 $sysconfdir = "/usr/local/etc"; 103} 104 105if ('${prefix}/share' ne '@' . 'datadir@') 106{ 107 $pkgdatadir = eval '"${prefix}/share/texi2html"'; 108 $datadir = eval '"${prefix}/share"'; 109} 110else 111{ 112 $pkgdatadir = "/usr/local/share/texi2html"; 113 $datadir = "/usr/local/share"; 114} 115 116my $i18n_dir = 'i18n'; # name of the directory containing the per language files 117my $conf_file_name = 'Config' ; 118my $texinfo_htmlxref = 'htmlxref.cnf'; 119 120# directories for texi2html init files 121my @texi2html_config_dirs = ('./'); 122push @texi2html_config_dirs, "$ENV{'HOME'}/.texi2html/" if (defined($ENV{'HOME'})); 123push @texi2html_config_dirs, "$sysconfdir/texi2html/" if (defined($sysconfdir)); 124push @texi2html_config_dirs, "$pkgdatadir" if (defined($pkgdatadir)); 125 126# directories for texinfo configuration files 127my @texinfo_config_dirs = ('./.texinfo/'); 128push @texinfo_config_dirs, "$ENV{'HOME'}/.texinfo/" if (defined($ENV{'HOME'})); 129push @texinfo_config_dirs, "$sysconfdir/texinfo/" if (defined($sysconfdir)); 130push @texinfo_config_dirs, "$datadir/texinfo/" if (defined($datadir)); 131 132 133#+++######################################################################## 134# # 135# Constants # 136# # 137#---######################################################################## 138 139my $DEBUG_MENU = 1; 140my $DEBUG_INDEX = 2; 141my $DEBUG_TEXI = 4; 142my $DEBUG_MACROS = 8; 143my $DEBUG_FORMATS = 16; 144my $DEBUG_ELEMENTS = 32; 145my $DEBUG_USER = 64; 146my $DEBUG_L2H = 128; 147 148my $ERROR = "***"; # prefix for errors 149my $WARN = "**"; # prefix for warnings 150 151my $VARRE = '[\w\-]+'; # RE for a variable name 152my $NODERE = '[^:]+'; # RE for node names 153 154my $MAX_LEVEL = 4; 155my $MIN_LEVEL = 1; 156 157#+++########################################################################### 158# # 159# Initialization # 160# Some declarations, some functions that are GPL and therefore cannot be in # 161# texi2html.init, some functions that are not to be customized. # 162# Pasted content of File $(srcdir)/texi2html.init: Default initializations # 163# # 164#---########################################################################### 165 166{ 167package Texi2HTML::Config; 168 169 170sub load($) 171{ 172 my $file = shift; 173 eval { require($file) ;}; 174 if ($@ ne '') 175 { 176 print STDERR "error loading $file: $@\n"; 177 return 0; 178 } 179 return 1; 180} 181 182# customization options variables 183 184use vars qw( 185$DEBUG 186$PREFIX 187$VERBOSE 188$SUBDIR 189$IDX_SUMMARY 190$SPLIT 191$SHORT_REF 192@EXPAND 193$EXPAND 194$TOP 195$DOCTYPE 196$FRAMESET_DOCTYPE 197$CHECK 198$TEST 199$DUMP_TEXI 200$MACRO_EXPAND 201$USE_GLOSSARY 202$INVISIBLE_MARK 203$USE_ISO 204$TOP_FILE 205$TOC_FILE 206$FRAMES 207$SHOW_MENU 208$NUMBER_SECTIONS 209$USE_NODES 210$USE_UNICODE 211$USE_UNIDECODE 212$TRANSLITERATE_NODE 213$NODE_FILES 214$NODE_NAME_IN_MENU 215$AVOID_MENU_REDUNDANCY 216$SECTION_NAVIGATION 217$SHORTEXTN 218$EXTENSION 219$OUT 220$NOVALIDATE 221$DEF_TABLE 222$LANG 223$DO_CONTENTS 224$DO_SCONTENTS 225$SEPARATED_FOOTNOTES 226$TOC_LINKS 227$L2H 228$L2H_L2H 229$L2H_SKIP 230$L2H_TMP 231$L2H_CLEAN 232$L2H_FILE 233$L2H_HTML_VERSION 234$EXTERNAL_DIR 235@INCLUDE_DIRS 236@PREPEND_DIRS 237@CONF_DIRS 238$IGNORE_PREAMBLE_TEXT 239@CSS_FILES 240$INLINE_CONTENTS 241); 242 243# customization variables 244# ENCODING is deprecated 245use vars qw( 246$ENCODING 247 248$ENCODING_NAME 249$DOCUMENT_ENCODING 250$OUT_ENCODING 251$IN_ENCODING 252$DEFAULT_ENCODING 253$MENU_PRE_STYLE 254$CENTER_IMAGE 255$EXAMPLE_INDENT_CELL 256$SMALL_EXAMPLE_INDENT_CELL 257$SMALL_FONT_SIZE 258$SMALL_RULE 259$DEFAULT_RULE 260$MIDDLE_RULE 261$BIG_RULE 262$TOP_HEADING 263$INDEX_CHAPTER 264$SPLIT_INDEX 265$HREF_DIR_INSTEAD_FILE 266$USE_MENU_DIRECTIONS 267$AFTER_BODY_OPEN 268$PRE_BODY_CLOSE 269$EXTRA_HEAD 270$VERTICAL_HEAD_NAVIGATION 271$WORDS_IN_PAGE 272$ICONS 273$UNNUMBERED_SYMBOL_IN_MENU 274$SIMPLE_MENU 275$MENU_SYMBOL 276$OPEN_QUOTE_SYMBOL 277$CLOSE_QUOTE_SYMBOL 278$TOC_LIST_STYLE 279$TOC_LIST_ATTRIBUTE 280$TOP_NODE_FILE 281$TOP_NODE_UP 282$NODE_FILE_EXTENSION 283$BEFORE_OVERVIEW 284$AFTER_OVERVIEW 285$BEFORE_TOC_LINES 286$AFTER_TOC_LINES 287$NEW_CROSSREF_STYLE 288$USER 289$USE_NUMERIC_ENTITY 290$DATE 291%ACTIVE_ICONS 292%NAVIGATION_TEXT 293%PASSIVE_ICONS 294%BUTTONS_NAME 295%BUTTONS_GOTO 296%BUTTONS_EXAMPLE 297@CHAPTER_BUTTONS 298@MISC_BUTTONS 299@SECTION_BUTTONS 300@SECTION_FOOTER_BUTTONS 301@NODE_FOOTER_BUTTONS 302@IMAGE_EXTENSIONS 303); 304 305# customization variables which may be guessed in the script 306#our $ADDRESS; 307use vars qw( 308$BODYTEXT 309$CSS_LINES 310$DOCUMENT_DESCRIPTION 311$EXTERNAL_CROSSREF_SPLIT 312); 313 314# I18n 315use vars qw( 316$I 317$LANGUAGES 318); 319 320# customizable subroutines references 321use vars qw( 322$print_section 323$one_section 324$end_section 325$print_Top_header 326$print_Top_footer 327$print_Top 328$print_Toc 329$print_Overview 330$print_Footnotes 331$print_About 332$print_misc_header 333$print_misc_footer 334$print_misc 335$print_section_header 336$print_section_footer 337$print_chapter_header 338$print_chapter_footer 339$print_page_head 340$print_page_foot 341$print_head_navigation 342$print_foot_navigation 343$button_icon_img 344$print_navigation 345$about_body 346$print_frame 347$print_toc_frame 348$toc_body 349$titlepage 350$css_lines 351$print_redirection_page 352$init_out 353$finish_out 354$node_file_name 355$element_file_name 356$inline_contents 357 358$protect_text 359$anchor 360$def_item 361$def 362$menu 363$menu_link 364$menu_description 365$menu_comment 366$simple_menu_link 367$ref_beginning 368$info_ref 369$book_ref 370$external_href 371$external_ref 372$internal_ref 373$table_item 374$table_line 375$row 376$cell 377$list_item 378$comment 379$def_line 380$def_line_no_texi 381$raw 382$raw_no_texi 383$heading 384$paragraph 385$preformatted 386$foot_line_and_ref 387$foot_section 388$address 389$image 390$image_files 391$index_entry_label 392$index_entry 393$index_letter 394$print_index 395$index_summary 396$summary_letter 397$complex_format 398$cartouche 399$sp 400$definition_category 401$table_list 402$copying_comment 403$index_summary_file_entry 404$index_summary_file_end 405$index_summary_file_begin 406$style 407$format 408$normal_text 409$empty_line 410$unknown 411$unknown_style 412$float 413$caption_shortcaption 414$listoffloats 415$listoffloats_entry 416$listoffloats_caption 417$listoffloats_float_style 418$listoffloats_style 419$acronym_like 420$quotation 421$quotation_prepend_text 422$paragraph_style_command 423$heading_texi 424$index_element_heading_texi 425 426$PRE_ABOUT 427$AFTER_ABOUT 428); 429 430# hash which entries might be redefined by the user 431use vars qw( 432$complex_format_map 433%accent_map 434%def_map 435%format_map 436%simple_map 437%simple_map_pre 438%simple_map_texi 439%style_map 440%style_map_pre 441%style_map_texi 442%simple_format_simple_map_texi 443%simple_format_style_map_texi 444%simple_format_texi_map 445%command_type 446%paragraph_style 447%things_map 448%pre_map 449%texi_map 450%unicode_map 451%unicode_diacritical 452%transliterate_map 453%transliterate_accent_map 454%no_transliterate_map 455%ascii_character_map 456%ascii_simple_map 457%ascii_things_map 458%numeric_entity_map 459%perl_charset_to_html 460%iso_symbols 461%misc_command 462%css_map 463%format_in_paragraph 464%special_list_commands 465%accent_letters 466%unicode_accents 467%special_accents 468@command_handler_init 469@command_handler_process 470@command_handler_finish 471%command_handler 472); 473 474# needed in this namespace for translations 475$I = \&Texi2HTML::I18n::get_string; 476 477# 478# Function refs covered by the GPL as part of the texi2html.pl original 479# code. As such they cannot appear in texi2html.init which is public 480# domain (at least the things coded by me, and, if I'm not wrong also the 481# things coded by Olaf -- Pat). 482# 483 484$toc_body = \&T2H_GPL_toc_body; 485$style = \&T2H_GPL_style; 486$format = \&T2H_GPL_format; 487 488sub T2H_GPL_toc_body($) 489{ 490 my $elements_list = shift; 491 return unless ($DO_CONTENTS or $DO_SCONTENTS or $FRAMES); 492 my $current_level = 0; 493 my $ul_style = $NUMBER_SECTIONS ? $TOC_LIST_ATTRIBUTE : ''; 494 foreach my $element (@$elements_list) 495 { 496 next if ($element->{'top'} or $element->{'index_page'}); 497 my $ind = ' ' x $current_level; 498 my $level = $element->{'toc_level'}; 499 print STDERR "Bug no toc_level for ($element) $element->{'texi'}\n" if (!defined ($level)); 500 if ($level > $current_level) 501 { 502 while ($level > $current_level) 503 { 504 $current_level++; 505 my $ln = "\n$ind<ul${ul_style}>\n"; 506 $ind = ' ' x $current_level; 507 push(@{$Texi2HTML::TOC_LINES}, $ln); 508 } 509 } 510 elsif ($level < $current_level) 511 { 512 while ($level < $current_level) 513 { 514 $current_level--; 515 $ind = ' ' x $current_level; 516 my $line = "</li>\n$ind</ul>"; 517 $line .= "</li>" if ($level == $current_level); 518 push(@{$Texi2HTML::TOC_LINES}, "$line\n"); 519 520 } 521 } 522 else 523 { 524 push(@{$Texi2HTML::TOC_LINES}, "</li>\n"); 525 } 526 my $file = ''; 527 $file = $element->{'file'} if ($SPLIT); 528 my $text = $element->{'text'}; 529 #$text = $element->{'name'} unless ($NUMBER_SECTIONS); 530 my $entry = "<li>" . &$anchor ($element->{'tocid'}, "$file#$element->{'id'}",$text); 531 push (@{$Texi2HTML::TOC_LINES}, $ind . $entry); 532 push(@{$Texi2HTML::OVERVIEW}, $entry. "</li>\n") if ($level == 1); 533 } 534 while (0 < $current_level) 535 { 536 $current_level--; 537 my $ind = ' ' x $current_level; 538 push(@{$Texi2HTML::TOC_LINES}, "</li>\n$ind</ul>\n"); 539 } 540 @{$Texi2HTML::TOC_LINES} = () unless ($DO_CONTENTS); 541 if (@{$Texi2HTML::TOC_LINES}) 542 { 543 unshift @{$Texi2HTML::TOC_LINES}, $BEFORE_TOC_LINES; 544 push @{$Texi2HTML::TOC_LINES}, $AFTER_TOC_LINES; 545 } 546 @{$Texi2HTML::OVERVIEW} = () unless ($DO_SCONTENTS or $FRAMES); 547 if (@{$Texi2HTML::OVERVIEW}) 548 { 549 unshift @{$Texi2HTML::OVERVIEW}, "<ul${ul_style}>\n"; 550 push @{$Texi2HTML::OVERVIEW}, "</ul>\n"; 551 unshift @{$Texi2HTML::OVERVIEW}, $BEFORE_OVERVIEW; 552 push @{$Texi2HTML::OVERVIEW}, $AFTER_OVERVIEW; 553 } 554} 555 556sub T2H_GPL_style($$$$$$$$$) 557{ # known style 558 my $style = shift; 559 my $command = shift; 560 my $text = shift; 561 my $args = shift; 562 my $no_close = shift; 563 my $no_open = shift; 564 my $line_nr = shift; 565 my $state = shift; 566 my $style_stack = shift; 567 568 my $do_quotes = 0; 569 my $use_attribute = 0; 570 my $use_begin_end = 0; 571 if (ref($style) eq 'HASH') 572 { 573 #print STDERR "GPL_STYLE $command\n"; 574 #print STDERR " @$args\n"; 575 $do_quotes = $style->{'quote'}; 576 if ((@{$style->{'args'}} == 1) and defined($style->{'attribute'})) 577 { 578 $style = $style->{'attribute'}; 579 $use_attribute = 1; 580 $text = $args->[0]; 581 } 582 elsif (defined($style->{'function'})) 583 { 584 $text = &{$style->{'function'}}($command, $args, $style_stack, $state, $line_nr); 585 } 586 } 587 else 588 { 589 if ($style =~ s/^\"//) 590 { # add quotes 591 $do_quotes = 1; 592 } 593 if ($style =~ s/^\&//) 594 { # custom 595 $style = 'Texi2HTML::Config::' . $style; 596 eval "\$text = &$style(\$text, \$command, \$style_stack)"; 597 } 598 elsif ($style ne '') 599 { 600 $use_attribute = 1; 601 } 602 else 603 { # no style 604 } 605 } 606 if ($use_attribute) 607 { # good style 608 my $attribute_text = ''; 609 if ($style =~ /^(\w+)(\s+.*)/) 610 { 611 $style = $1; 612 $attribute_text = $2; 613 } 614# $text = "<${style}$attribute_text>$text</$style>" ; 615 $text = "<${style}$attribute_text>" . "$text" if (!$no_open); 616 $text .= "</$style>" if (!$no_close); 617 if ($do_quotes) 618 { 619 $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open); 620 $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close); 621 } 622 } 623 if (ref($style) eq 'HASH') 624 { 625 if (defined($style->{'begin'}) and !$no_open) 626 { 627 $text = $style->{'begin'} . $text; 628 } 629 if (defined($style->{'end'}) and !$no_close) 630 { 631 $text = $text . $style->{'end'}; 632 } 633 } 634 if ($do_quotes and !$use_attribute) 635 { 636 $text = $OPEN_QUOTE_SYMBOL . "$text" if (!$no_open); 637 $text .= $CLOSE_QUOTE_SYMBOL if (!$no_close); 638 } 639 return $text; 640} 641 642sub T2H_GPL_format($$$) 643{ 644 my $tag = shift; 645 my $element = shift; 646 my $text = shift; 647 return '' if (!defined($element) or ($text !~ /\S/)); 648 return $text if ($element eq ''); 649 my $attribute_text = ''; 650 if ($element =~ /^(\w+)(\s+.*)/) 651 { 652 $element = $1; 653 $attribute_text = $2; 654 } 655 return "<${element}$attribute_text>\n" . $text. "</$element>\n"; 656} 657 658# leave this within comments, and keep the require statement 659# This way, you can directly run texi2html.pl, if 660# $ENV{T2H_HOME}/texi2html.init exists. 661 662# @INIT@ 663# -*-perl-*- 664###################################################################### 665# File: texi2html.init 666# 667# Default values for command-line arguments and for various customizable 668# procedures are set in this file. 669# 670# A copy of this file is pasted into the beginning of texi2html by 671# running './configure'. 672# 673# Copy this file, rename it and make changes to it, if you like. 674# Afterwards, load the file with command-line 675# option -init-file <your_init_file> 676# 677# $Id: texi2html.init,v 1.116 2007/05/07 22:56:02 pertusus Exp $ 678 679###################################################################### 680# The following variables can also be set by command-line options 681# 682# 683# The default values are set in this file, texi2html.init and the content 684# of this file is included at the beginning of the texi2html script file. 685# Those values may be overrided by values set in $sysconfdir/texi2htmlrc 686# and then by values set in $HOME/texi2htmlrc. 687# 688# command line switches may override these values, and values set in files 689# specified by -init-file are also taken into account. 690# values set in these files overwrite values set by the command-line 691# options appearing before -init-file and might still be overwritten by 692# command-line arguments following the -init-file option. 693 694# -debug 695# The integer value specifies what kind of debugging output is generated. 696$DEBUG = 0; 697 698# -doctype 699# The value is the 'SystemLiteral' which identifies the canonical DTD 700# for the document. 701# Definition: The SystemLiteral is called the entity's system 702# identifier. It is a URI, which may be used to retrieve the entity. 703# See https://www.xml.com/axml/target.html#NT-ExternalID 704$DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd">'; 705 706# -frameset-doctype 707# When frames are used, this SystemLiteral identifies the DTD used for 708# the file containing the frame description. 709$FRAMESET_DOCTYPE = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html401/frameset.dtd">'; 710 711# -test 712# If this value is true, some variables which should be dynamically generated 713# (the date, the user running texi2html, the version of texi2html) are set to 714# fix and given values. This is usefull in case the resulting manual is 715# compared with a reference. For example this is used in the tests of test.sh. 716$TEST = 0; 717 718# -dump-texi 719# This value is usefull for debugging purposes. The result of the first pass is 720# put in <document name>.passtexi, the result of the second pass is put in 721# <document name>.passfirst. 722$DUMP_TEXI = 0; 723 724# -expand 725# the @EXPAND array contains the expanded section names. 726@EXPAND = ('html'); 727 728# -invisible 729# This seems obsolete and is not used anywhere. 730# This was a workaround for a known bug of many WWW browsers, including 731# netscape. This was used to create invisible destination in anchors. 732$INVISIBLE_MARK = ''; 733# $INVISIBLE_MARK = ' '; 734 735# -iso 736# if this value is true, ISO8859 characters are used for special symbols 737# (like copyright, etc). 738$USE_ISO = 1; 739 740# -I 741# add a directory to the list of directories where @include files are 742# searched for (besides the directory of the file). additional '-I' 743# args are appended to this list. 744# (APA: Don't implicitely search ., to conform with the docs!) 745# my @INCLUDE_DIRS = ("."); 746@INCLUDE_DIRS = (); 747 748# -P 749# prepend a directory to the list of directories where @include files are 750# searched for before the directory of the file. additional '-P' 751# args are prepended to this list. 752@PREPEND_DIRS = (); 753 754# --conf-dir 755# append to the files searched for init files. 756@CONF_DIRS = (); 757 758# -top-file 759# This file name is used for the top-level file. 760# The extension is set appropriately, if necessary. 761# If empty, <basename of document>.html is used. 762# Typically, you would set this to "index.html". 763$TOP_FILE = ''; 764 765# -toc-file 766# This file name is used for the table of contents. The 767# extension is set appropriately, if necessary. 768# If empty, <basename of document>_toc.html is used. 769$TOC_FILE = ''; 770 771# -frames 772# if the value is true, HTML 4.0 "frames" are used. 773# A file describing the frame layout is generated, together with a file 774# with the short table of contents. 775$FRAMES = 0; 776 777# -menu | -nomenu 778# if the value is true the Texinfo menus are shown. 779$SHOW_MENU = 1; 780 781# -number | -nonumber 782# if this is set the sections are numbered, and section names and numbers 783# are used in references and menus (instead of node names). 784$NUMBER_SECTIONS = 1; 785 786# -use-nodes 787# if this is set the nodes are used as sectionning elements. 788# Otherwise the nodes are incorporated in sections. 789$USE_NODES = 0; 790 791# -node-files 792# if this is set one file per node is generated, which can be a target for 793# cross manual references. 794$NODE_FILES = 0; 795 796# -split section|chapter|node|none 797# if $SPLIT is set to 'section' (resp. 'chapter') one html file per section 798# (resp. chapter) is generated. If $SPLIT is set to 'node' one html file per 799# node or sectionning element is generated. In all these cases separate pages 800# for Top, Table of content (Toc), Overview and About are generated. 801# Otherwise a monolithic html file that contains the whole document is 802# created. 803#$SPLIT = 'section'; 804$SPLIT = ''; 805 806# -sec-nav|-nosec-nav 807# if this is set then navigation panels are printed at the beginning of each 808# section. 809# If the document is split at nodes then navigation panels are 810# printed at the end if there were more than $WORDS_IN_PAGE words on page. 811# 812# If the document is split at sections this is ignored. 813# 814# This is most useful if you do not want to have section navigation 815# with -split chapter. There will be chapter navigation panel at the 816# beginning and at the end of chapters anyway. 817$SECTION_NAVIGATION = 1; 818 819# -separated-footnotes 820# if this is set footnotes are on a separated page. Otherwise they are at 821# the end of each file (if the document is split). 822$SEPARATED_FOOTNOTES = 1; 823 824# -toc-links 825# if this is set, links from headings to toc entries are created. 826$TOC_LINKS = 0; 827 828# -subdir 829# If this is set, then put result files into the specified directory. 830# If not set, then result files are put into the current directory. 831#$SUBDIR = 'html'; 832$SUBDIR = ''; 833 834# -short-extn 835# If this is set, then all HTML files will have extension ".htm" instead of 836# ".html". This is helpful when shipping the document to DOS-based systems. 837$SHORTEXTN = 0; 838 839# -prefix 840# This set the output file prefix, prepended to all .html, .gif and .pl files. 841# By default, this is the basename of the document. 842$PREFIX = ''; 843 844# -o filename 845# If this is set a monolithic document is outputted into $filename. 846$OUT = ''; 847 848# -no-validate 849# suppress node cross-reference validation 850$NOVALIDATE = 0; 851 852# -short-ref 853# if this is set cross-references are given without section numbers. 854$SHORT_REF = ''; 855 856# -idx-sum 857# if value is set, then for each @printindex <index name> 858# <document name>_<index name>.idx is created which contains lines of the form 859# key ref sorted alphabetically (case matters). 860$IDX_SUMMARY = 0; 861 862# -def-table 863# If this is set a table construction for @def.... instead of definition 864# lists. 865# (New Option: 27.07.2000 Karl Heinz Marbaise) 866$DEF_TABLE = 0; 867 868# -verbose 869# if this is set chatter about what we are doing. 870$VERBOSE = ''; 871 872# -lang 873# use &$I('my string') if you want to have translations of 'my string' 874# and provide the translations in $LANGUAGES->{$LANG} with 'my string' 875# as key. 876# To add a new language use ISO 639 language codes (see e.g. perl module 877# Locale-Codes-1.02 for definitions). Supply translations in the 878# $LANGUAGES hash and put it in a file with $LANG as name in an i18n 879# directory. 880# Default's to 'en' if not set or no @documentlanguage is specified. 881$LANG = 'en'; 882 883# -ignore-preamble-text 884# If this is set the text before @node and sectionning commands is ignored. 885$IGNORE_PREAMBLE_TEXT = 0; 886 887# -html-xref-prefix 888# base directory for external manuals. 889#$EXTERNAL_DIR = '../'; 890$EXTERNAL_DIR = undef; 891 892# -l2h 893# if this is set, latex2html is used for generation of math content. 894$L2H = ''; 895 896# -css-include 897# All the specified css files are used. More precisely the @import sections 898# are added to the beginning of the CSS_LINES the remaining is added at 899# the end of the CSS_LINES (after the css rules generated by texi2html). 900# cf texinfo manual for more info. 901# - means STDIN 902@CSS_FILES = (); 903 904###################### 905# The following options are only relevant if $L2H is set 906# 907# -l2h-l2h 908# name/location of latex2html program 909$L2H_L2H = "latex2html"; 910 911# -l2h-skip 912# If this is set the actual call to latex2html is skipped. The previously 913# generated content is reused, instead. 914$L2H_SKIP = ''; 915 916# -l2h-tmp 917# If this is set l2h uses the specified directory for temporary files. The path 918# leading to this directory may not contain a dot (i.e., a "."); 919# otherwise, l2h will fail. 920$L2H_TMP = ''; 921 922# -l2h-file 923# If set, l2h uses the file as latex2html init file 924$L2H_FILE = 'l2h.init'; 925 926# -l2h-clean 927# if this is set the intermediate files generated by texi2html in relation with 928# latex2html are cleaned (they all have the prefix <document name>_l2h_). 929$L2H_CLEAN = 1; 930 931############################################################################## 932# 933# The following can only be set in the init file 934# 935############################################################################## 936 937# If true do table of contents even if there is no @content 938$DO_CONTENTS = 0; 939 940# If true do short table of contents even if there is no @shortcontent 941$DO_SCONTENTS = 0; 942 943# if set, output the contents where the command is located 944$INLINE_CONTENTS = 1; 945 946# if this variable is true, numeric entities are used when there is no 947# corresponding textual entity. 948$USE_NUMERIC_ENTITY = 1; 949 950# if set, then use node names in menu entries, instead of section names 951$NODE_NAME_IN_MENU = 0; 952 953# new style for crossrefs 954$NEW_CROSSREF_STYLE = 1; 955 956# transliterate node names for external refs (and internal if NODE_FILES) 957$TRANSLITERATE_NODE = 1; 958 959# if set and menu entry equals menu description, then do not print 960# menu description. 961# Likewise, if node name equals entry name, do not print entry name. 962$AVOID_MENU_REDUNDANCY = 1; 963 964# if set, center @image by default 965# otherwise, do not center by default 966# Deprecated and not used anymore 967$CENTER_IMAGE = 1; 968 969# used as identation for block enclosing command @example, etc 970# If not empty, must be enclosed in <td></td> 971$EXAMPLE_INDENT_CELL = '<td> </td>'; 972 973# same as above, only for @small 974$SMALL_EXAMPLE_INDENT_CELL = '<td> </td>'; 975 976# font size for @small 977$SMALL_FONT_SIZE = '-1'; 978 979# horizontal rules 980$SMALL_RULE = '<hr size="1">'; 981$DEFAULT_RULE = '<hr>'; 982$MIDDLE_RULE = '<hr size="2">'; 983$BIG_RULE = ''; 984 985# if non-empty, and no @..heading appeared in Top node, then 986# use this as header for top node/section, otherwise use value of 987# @settitle or @shorttitle (in that order) 988$TOP_HEADING = ''; 989 990# if set, use this chapter for 'Index' button, else 991# use first chapter with @printindex 992$INDEX_CHAPTER = ''; 993 994# if set and $SPLIT is set, then split index pages at the next letter 995# after they have more than that many entries 996$SPLIT_INDEX = 100; 997 998# symbol put at the beginning of nodes entry in menu (and optionnaly of 999# unnumbered in menus, see next variable) 1000$MENU_SYMBOL = '•'; 1001#$MENU_SYMBOL = '*'; 1002 1003$SIMPLE_MENU = 0; 1004 1005$OPEN_QUOTE_SYMBOL = "\`"; 1006$CLOSE_QUOTE_SYMBOL = "'"; 1007 1008# if true put a $MENU_SYMBOL before unnumbered in menus 1009$UNNUMBERED_SYMBOL_IN_MENU = 0; 1010 1011# extension for nodes files when NODE_FILES is true 1012$NODE_FILE_EXTENSION = "html"; 1013 1014# extension 1015$EXTENSION = "html"; 1016 1017# file name used for Top node when NODE_FILES is true 1018$TOP_NODE_FILE = "index"; 1019 1020# node name used for Top node when automatic node directions are used 1021$TOP_NODE_UP = '(dir)'; 1022 1023# this controls the pre style for menus 1024$MENU_PRE_STYLE = 'font-family: serif'; 1025 1026# This controls the ul style for toc 1027$TOC_LIST_STYLE = 'list-style: none'; 1028$TOC_LIST_ATTRIBUTE = ' class="toc"'; 1029 1030# These lines are inserted before and after the shortcontents 1031$BEFORE_OVERVIEW = "<div class=\"shortcontents\">\n"; 1032$AFTER_OVERVIEW = "</div>\n"; 1033 1034# These lines are inserted before and after the contents 1035$BEFORE_TOC_LINES = "<div class=\"contents\">\n"; 1036$AFTER_TOC_LINES = "</div>\n"; 1037 1038# if set (e.g., to index.html) replace hrefs to this file 1039# (i.e., to index.html) by ./ 1040# Obsolete. Worked around a bug that is fixed now. 1041$HREF_DIR_INSTEAD_FILE = ''; 1042 1043# text inserted after <body ...> 1044$AFTER_BODY_OPEN = ''; 1045 1046# text inserted before </body>, this will be automatically inside <p></p> 1047$PRE_BODY_CLOSE = ''; 1048 1049# this is added inside <head></head> after <title> and some <meta name> 1050# stuff, it can be used for eg. <style>, <script>, <meta> etc. tags. 1051$EXTRA_HEAD = ''; 1052 1053# Specifies the minimum page length required before a navigation panel 1054# is placed at the bottom of a page 1055# FIXME this is not true: 1056# THIS_WORDS_IN_PAGE holds number of words of current page 1057$WORDS_IN_PAGE = 300; 1058 1059# if this is set a vertical navigation panel is used. 1060$VERTICAL_HEAD_NAVIGATION = 0; 1061 1062# html version for latex2html 1063$L2H_HTML_VERSION = "4.0"; 1064 1065# use the information given by menus to complete the node directions 1066$USE_MENU_DIRECTIONS = 1; 1067 1068# specify in this array which "buttons" should appear in which order 1069# in the navigation panel for sections; use ' ' for empty buttons (space) 1070@SECTION_BUTTONS = 1071 ( 1072 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward', 1073 ' ', ' ', ' ', ' ', 1074 'Top', 'Contents', 'Index', 'About', 1075 ); 1076 1077# buttons for misc stuff 1078@MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About'); 1079 1080# buttons for chapter file footers 1081# (and headers but only if SECTION_NAVIGATION is false) 1082@CHAPTER_BUTTONS = 1083 ( 1084 'FastBack', 'FastForward', ' ', 1085 ' ', ' ', ' ', ' ', 1086 'Top', 'Contents', 'Index', 'About', 1087 ); 1088 1089# buttons for section file footers 1090@SECTION_FOOTER_BUTTONS = 1091 ( 1092 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward' 1093 ); 1094 1095@NODE_FOOTER_BUTTONS = 1096 ( 1097 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward', 1098 ' ', ' ', ' ', ' ', 1099 'Top', 'Contents', 'Index', 'About', 1100# 'Back', 'Forward', ' ', 'FastBack', 'Up', 'FastForward' 1101 ); 1102 1103$ICONS = 0; 1104 1105# insert here name of icon images for buttons 1106# Icons are used, if $ICONS and resp. value are set 1107%ACTIVE_ICONS = 1108 ( 1109 'Top', '', 1110 'Contents', '', 1111 'Overview', '', 1112 'Index', '', 1113 'This', '', 1114 'Back', '', 1115 'FastBack', '', 1116 'Prev', '', 1117 'Up', '', 1118 'Next', '', 1119 'NodeUp', '', 1120 'NodeNext', '', 1121 'NodePrev', '', 1122 'Following', '', 1123 'Forward', '', 1124 'FastForward', '', 1125 'About' , '', 1126 'First', '', 1127 'Last', '', 1128 ' ', '' 1129 ); 1130 1131# insert here name of icon images for these, if button is inactive 1132%PASSIVE_ICONS = 1133 ( 1134 'Top', '', 1135 'Contents', '', 1136 'Overview', '', 1137 'Index', '', 1138 'This', '', 1139 'Back', '', 1140 'FastBack', '', 1141 'Prev', '', 1142 'Up', '', 1143 'Next', '', 1144 'NodeUp', '', 1145 'NodeNext', '', 1146 'NodePrev', '', 1147 'Following', '', 1148 'Forward', '', 1149 'FastForward', '', 1150 'About', '', 1151 'First', '', 1152 'Last', '', 1153 ); 1154 1155@IMAGE_EXTENSIONS = ('png','jpg','jpeg','gif'); 1156 1157$init_out = \&t2h_default_init_out; 1158$finish_out = \&t2h_default_finish_out; 1159 1160# We have to do this dynamically because of internationalization and because 1161# in body $LANG could be used. 1162sub t2h_default_init_out() 1163{ 1164# Names of text as alternative for icons 1165# FIXME maybe get those in simple_format? 1166 %NAVIGATION_TEXT = 1167 ( 1168 'Top', &$I('Top'), 1169 'Contents', &$I('Contents'), 1170 'Overview', &$I('Overview'), 1171 'Index', &$I('Index'), 1172 ' ', ' ', 1173 'This', &$I('current'), 1174 'Back', ' < ', 1175 'FastBack', ' << ', 1176 'Prev', &$I('Prev'), 1177 'Up', &$I(' Up '), 1178 'Next', &$I('Next'), 1179 'NodeUp', &$I('Node up'), 1180 'NodeNext', &$I('Next node'), 1181 'NodePrev', &$I('Previous node'), 1182 'Following', &$I('Following node'), 1183 'Forward', ' > ', 1184 'FastForward', ' >> ', 1185 'About', ' ? ', 1186 'First', ' |< ', 1187 'Last', ' >| ' 1188 ); 1189 1190 %BUTTONS_GOTO = 1191 ( 1192 'Top', &$I('Cover (top) of document'), 1193 'Contents', &$I('Table of contents'), 1194 'Overview', &$I('Short table of contents'), 1195 'Index', &$I('Index'), 1196 'This', &$I('Current section'), 1197 'Back', &$I('Previous section in reading order'), 1198 'FastBack', &$I('Beginning of this chapter or previous chapter'), 1199 'Prev', &$I('Previous section on same level'), 1200 'Up', &$I('Up section'), 1201 'Next', &$I('Next section on same level'), 1202 'NodeUp', &$I('Up node'), 1203 'NodeNext', &$I('Next node'), 1204 'NodePrev', &$I('Previous node'), 1205 'Following', &$I('Node following in node reading order'), 1206 'Forward', &$I('Next section in reading order'), 1207 'FastForward', &$I('Next chapter'), 1208 'About' , &$I('About (help)'), 1209 'First', &$I('First section in reading order'), 1210 'Last', &$I('Last section in reading order'), 1211 ); 1212 1213 %BUTTONS_NAME = 1214 ( 1215 'Top', &$I('Top'), 1216 'Contents', &$I('Contents'), 1217 'Overview', &$I('Overview'), 1218 'Index', &$I('Index'), 1219 ' ', ' ', 1220 'This', &$I('This'), 1221 'Back', &$I('Back'), 1222 'FastBack', &$I('FastBack'), 1223 'Prev', &$I('Prev'), 1224 'Up', &$I('Up'), 1225 'Next', &$I('Next'), 1226 'NodeUp', &$I('NodeUp'), 1227 'NodeNext', &$I('NodeNext'), 1228 'NodePrev', &$I('NodePrev'), 1229 'Following', &$I('Following'), 1230 'Forward', &$I('Forward'), 1231 'FastForward', &$I('FastForward'), 1232 'About', &$I('About'), 1233 'First', &$I('First'), 1234 'Last', &$I('Last') 1235 ); 1236 1237 # Set the default body text, inserted between <body ... > 1238 $BODYTEXT = 'lang="' . $LANG . '" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"' unless (defined($BODYTEXT)); 1239 if (!defined($EXTERNAL_CROSSREF_SPLIT)) 1240 { 1241 if ($SPLIT) 1242 { 1243 $EXTERNAL_CROSSREF_SPLIT = 1; 1244 } 1245 else 1246 { 1247 $EXTERNAL_CROSSREF_SPLIT = 0; 1248 } 1249 } 1250 1251 $ENCODING_NAME = $ENCODING if (!defined($ENCODING_NAME) and 1252 defined($ENCODING)); 1253 1254 if (!defined($OUT_ENCODING) and (defined($ENCODING_NAME))) 1255 { 1256 $OUT_ENCODING = main::encoding_alias ($ENCODING_NAME); 1257 $OUT_ENCODING = $ENCODING_NAME if (!defined($OUT_ENCODING)); 1258 } 1259 if (!defined($OUT_ENCODING) and (defined($IN_ENCODING))) 1260 { 1261 $OUT_ENCODING = $IN_ENCODING; 1262 } 1263 if (!defined($OUT_ENCODING) and (defined($DOCUMENT_ENCODING))) 1264 { 1265 $OUT_ENCODING = main::encoding_alias ($DOCUMENT_ENCODING); 1266 $OUT_ENCODING = $DOCUMENT_ENCODING if (!defined($OUT_ENCODING)); 1267 } 1268 1269 if (!defined($ENCODING_NAME)) 1270 { 1271 if (defined($OUT_ENCODING) and defined($perl_charset_to_html{$OUT_ENCODING})) 1272 { 1273 $ENCODING_NAME = $perl_charset_to_html{$OUT_ENCODING}; 1274 } 1275 elsif (defined($IN_ENCODING) and defined($perl_charset_to_html{$IN_ENCODING})) 1276 { 1277 $ENCODING_NAME = $perl_charset_to_html{$IN_ENCODING}; 1278 } 1279 elsif (defined($DOCUMENT_ENCODING) and defined($perl_charset_to_html{$DOCUMENT_ENCODING})) 1280 { 1281 $ENCODING_NAME = $perl_charset_to_html{$DOCUMENT_ENCODING}; 1282 } 1283 elsif (defined($OUT_ENCODING)) 1284 { 1285 $ENCODING_NAME = $OUT_ENCODING; 1286 } 1287 elsif (defined($IN_ENCODING)) 1288 { 1289 $ENCODING_NAME = $IN_ENCODING; 1290 } 1291 elsif (defined($DOCUMENT_ENCODING)) 1292 { 1293 $ENCODING_NAME = $DOCUMENT_ENCODING; 1294 } 1295 elsif (defined($perl_charset_to_html{$DEFAULT_ENCODING})) 1296 { 1297 $ENCODING_NAME = $perl_charset_to_html{$DEFAULT_ENCODING}; 1298 } 1299 else 1300 { 1301 $ENCODING_NAME = 'us-ascii'; 1302 } 1303 } 1304 my $out_encoding = $OUT_ENCODING; 1305 $out_encoding = 'UNDEF' if (!defined($out_encoding)); 1306 my $in_encoding = $IN_ENCODING; 1307 $in_encoding = 'UNDEF' if (!defined($in_encoding)); 1308 my $document_encoding = $DOCUMENT_ENCODING; 1309 $document_encoding = 'UNDEF' if (!defined($document_encoding)); 1310 print STDERR "# Encodings: doc $document_encoding, in $in_encoding out $out_encoding, name $ENCODING_NAME\n" if ($VERBOSE); 1311 1312 if ($SIMPLE_MENU and !defined($complex_format_map->{'menu'})) 1313 { 1314 $complex_format_map->{'menu'} = { 'begin' => q{''} , 'end' => q{''}, 1315 'pre_style' => "$MENU_PRE_STYLE", 'class' => 'menu-preformatted' }; 1316 } 1317 1318 return $OUT_ENCODING; 1319}; 1320 1321sub t2h_default_finish_out() 1322{ 1323} 1324 1325####################################################################### 1326# 1327# Values guessed if not set here, set in init_out 1328# 1329####################################################################### 1330 1331$BODYTEXT = undef; 1332 1333# default used in init_out for the setting of the ENCODING_NAME variable 1334$DEFAULT_ENCODING = 'utf8'; 1335 1336# In file encoding. The @documentencoding overrides that variable. 1337$DOCUMENT_ENCODING = undef; 1338 1339# In file encoding, understandable by perl. Set according to DOCUMENT_ENCODING 1340$IN_ENCODING = undef; 1341 1342# Formatted document encoding name. If undef, set in init_out based on 1343# $OUT_ENCODING or $DOCUMENT_ENCODING if they are defined 1344$ENCODING_NAME = undef; 1345 1346# Out files encoding, understandable by perl. If undef, set in init_out 1347# using $ENCODING_NAME or $IN_ENCODING if they are defined 1348$OUT_ENCODING = undef; 1349 1350# if undef set to @documentdescription. If there is no @documentdescription, 1351# set in page_head 1352$DOCUMENT_DESCRIPTION = undef; 1353 1354# if undef set 1 if SPLIT, to 0 otherwise 1355$EXTERNAL_CROSSREF_SPLIT = undef; 1356 1357$USER = undef; 1358$DATE = undef; 1359 1360 1361######################################################################## 1362# Control of Page layout: 1363# You can make changes of the Page layout at two levels: 1364# 1.) For small changes, it is often enough to change the value of 1365# some global string/hash/array variables 1366# 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines, 1367# give them another name, and assign them to the respective 1368# $<fnc> variable. 1369 1370# As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, hold 1371# href, html-name, node-name, name after removal of texi commands of 1372# This -- current section (resp. html page) 1373# Top -- top element 1374# Contents -- Table of contents element 1375# Overview -- Short table of contents element 1376# Index -- Index page element 1377# About -- page which explain "navigation buttons" element 1378# First -- first node element 1379# Last -- last node element 1380# 1381# Whether or not the following hash values are set, depends on the context 1382# (all values are w.r.t. 'This' section) 1383# Next -- next element of texinfo 1384# Prev -- previous element of texinfo 1385# NodeUp -- up node of texinfo 1386# Following -- following node in node reading order, taking menu into account 1387# Forward -- next node in reading order 1388# Back -- previous node in reading order 1389# Up -- parent given by sectionning commands 1390# FastForward -- if leave node, up and next, else next node 1391# FastBackward-- if leave node, up and prev, else prev node 1392# 1393# Furthermore, the following global variabels are set: 1394# $Texi2HTML::THISDOC{title} -- title as set by @setttile 1395# $Texi2HTML::THISDOC{title_no_texi} -- title without texi (without html elements) 1396# $Texi2HTML::THISDOC{title_texi} -- title with texinfo @-commands 1397# $Texi2HTML::THISDOC{fulltitle} -- full title as set by @title... 1398# $Texi2HTML::THISDOC{subtitle} -- subtitle as set by @subtitle 1399# $Texi2HTML::THISDOC{author} -- author as set by @author 1400# $Texi2HTML::THISDOC{copying} -- text of @copying and @end copying in comment 1401# 1402# $Texi2HTML::THISDOC{program} -- name and version of texi2html 1403# $Texi2HTML::THISDOC{program_homepage} -- homepage for texi2html 1404# $Texi2HTML::THISDOC{program_authors} -- authors of texi2html 1405# $Texi2HTML::THISDOC{today} -- date formatted with pretty_date 1406# $Texi2HTML::THISDOC{toc_file} -- table of contents file 1407# $Texi2HTML::THISDOC{file_base_name} -- base name of the texinfo manual file 1408# $Texi2HTML::THISDOC{destination_directory} 1409 # -- directory for the resulting files 1410# $Texi2HTML::THISDOC{user} -- user running the script 1411# $Texi2HTML::THISDOC{css_import_lines} -- ref on @import lines in css files 1412# $Texi2HTML::THISDOC{css_lines} -- ref on css rules lines 1413# other $Texi2HTML::THISDOC keys corresponds with texinfo commands, the value 1414# being the command arg, for the following commands: 1415# kbdinputstyle, paragraphindent, setchapternewpage, headings, footnotestyle, 1416# exampleindent, firstparagraphindent, everyheading, everyfooting, 1417# evenheading, evenfooting, oddheading, oddfooting 1418# 1419# and pointer to arrays of lines which need to be printed by main::print_lines 1420# $Texi2HTML::THIS_SECTION -- lines of 'This' section 1421# $Texi2HTML::THIS_HEADER -- lines preceding navigation panel of 'This' section 1422# $Texi2HTML::OVERVIEW -- lines of short table of contents 1423# $Texi2HTML::TOC_LINES -- lines of table of contents 1424# $Texi2HTML::TITLEPAGE -- lines of title page 1425# 1426# $Texi2HTML::THIS_ELEMENT holds the element reference. 1427 1428# 1429# There are the following subs which control the layout: 1430# 1431$print_section = \&T2H_DEFAULT_print_section; 1432$end_section = \&T2H_DEFAULT_end_section; 1433$one_section = \&T2H_DEFAULT_one_section; 1434$print_Top_header = \&T2H_DEFAULT_print_Top_header; 1435$print_Top_footer = \&T2H_DEFAULT_print_Top_footer; 1436$print_Top = \&T2H_DEFAULT_print_Top; 1437$print_Toc = \&T2H_DEFAULT_print_Toc; 1438$print_Overview = \&T2H_DEFAULT_print_Overview; 1439$print_Footnotes = \&T2H_DEFAULT_print_Footnotes; 1440$print_About = \&T2H_DEFAULT_print_About; 1441$print_misc_header = \&T2H_DEFAULT_print_misc_header; 1442$print_misc_footer = \&T2H_DEFAULT_print_misc_footer; 1443$print_misc = \&T2H_DEFAULT_print_misc; 1444$print_section_footer = \&T2H_DEFAULT_print_section_footer; 1445$print_chapter_header = \&T2H_DEFAULT_print_chapter_header; 1446$print_section_header = \&T2H_DEFAULT_print_section_header; 1447$print_chapter_footer = \&T2H_DEFAULT_print_chapter_footer; 1448$print_page_head = \&T2H_DEFAULT_print_page_head; 1449$print_page_foot = \&T2H_DEFAULT_print_page_foot; 1450$print_head_navigation = \&T2H_DEFAULT_print_head_navigation; 1451$print_foot_navigation = \&T2H_DEFAULT_print_foot_navigation; 1452$button_icon_img = \&T2H_DEFAULT_button_icon_img; 1453$print_navigation = \&T2H_DEFAULT_print_navigation; 1454$about_body = \&T2H_DEFAULT_about_body; 1455$print_frame = \&T2H_DEFAULT_print_frame; 1456$print_toc_frame = \&T2H_DEFAULT_print_toc_frame; 1457#$toc_body = \&T2H_DEFAULT_toc_body; 1458$titlepage = \&T2H_DEFAULT_titlepage; 1459$css_lines = \&T2H_DEFAULT_css_lines; 1460$print_redirection_page = \&T2H_DEFAULT_print_redirection_page; 1461$node_file_name = \&T2H_DEFAULT_node_file_name; 1462$inline_contents = \&T2H_DEFAULT_inline_contents; 1463 1464######################################################################## 1465# Layout for html for every sections 1466# 1467sub T2H_DEFAULT_print_section 1468{ 1469 my $fh = shift; 1470 my $first_in_page = shift; 1471 my $previous_is_top = shift; 1472 my $buttons = \@SECTION_BUTTONS; 1473 1474 if ($first_in_page and $SECTION_NAVIGATION) 1475 { 1476 &$print_head_navigation($fh, $buttons); 1477 } 1478 else 1479 { # got to do this here, as it isn't done in print_head_navigation 1480 main::print_lines($fh, $Texi2HTML::THIS_HEADER); 1481 &$print_navigation($fh, $buttons) if ($SECTION_NAVIGATION); 1482 } 1483 my $nw = main::print_lines($fh); 1484 if (defined $SPLIT 1485 and (($SPLIT eq 'node') && $SECTION_NAVIGATION)) 1486 { 1487 &$print_foot_navigation($fh); 1488 print $fh "$SMALL_RULE\n"; 1489 &$print_navigation($fh, \@NODE_FOOTER_BUTTONS) if (!defined($WORDS_IN_PAGE) or (defined ($nw) 1490 and $nw >= $WORDS_IN_PAGE)); 1491 } 1492} 1493 1494sub T2H_DEFAULT_one_section($) 1495{ 1496 my $fh = shift; 1497 main::print_lines($fh, $Texi2HTML::THIS_HEADER); 1498 main::print_lines($fh); 1499 print $fh "$SMALL_RULE\n"; 1500 &$print_foot_navigation($fh); 1501 &$print_page_foot($fh); 1502} 1503 1504################################################################### 1505# Layout of top-page I recommend that you use @ifnothtml, @ifhtml, 1506# @html within the Top texinfo node to specify content of top-level 1507# page. 1508# 1509# If you enclose everything in @ifnothtml, then title, subtitle, 1510# author and overview is printed 1511# Texi2HTML::HREF of Next, Prev, Up, Forward, Back are not defined 1512# if $T2H_SPLIT then Top page is in its own html file 1513sub T2H_DEFAULT_print_Top_header($$) 1514{ 1515 my $fh = shift; 1516 my $do_page_head = shift; 1517 &$print_page_head($fh) if ($do_page_head); 1518} 1519sub T2H_DEFAULT_print_Top_footer($$) 1520{ 1521 my $fh = shift; 1522 my $end_page = shift; 1523 my $buttons = \@MISC_BUTTONS; 1524 &$print_foot_navigation($fh); 1525 print $fh "$SMALL_RULE\n"; 1526 if ($end_page) 1527 { 1528 &$print_navigation($fh, $buttons); 1529 &$print_page_foot($fh); 1530 } 1531} 1532sub T2H_DEFAULT_print_Top($$) 1533{ 1534 my $fh = shift; 1535 my $has_top_heading = shift; 1536 1537 # for redefining navigation buttons use: 1538 # my $buttons = [...]; 1539 # as it is, 'Top', 'Contents', 'Index', 'About' are printed 1540 my $buttons = \@MISC_BUTTONS; 1541 &$print_head_navigation($fh, $buttons) if ($SPLIT or $SECTION_NAVIGATION); 1542 my $nw; 1543 if (@$Texi2HTML::THIS_SECTION) 1544 { 1545 # if top-level node has content, then print it with extra header 1546 #print $fh "<h1>$Texi2HTML::NAME{Top}</h1>\n" 1547 print $fh "<h1 class=\"settitle\">$Texi2HTML::NAME{Top}</h1>\n" 1548 unless ($has_top_heading); 1549 $nw = main::print_lines($fh, $Texi2HTML::THIS_SECTION); 1550 } 1551 else 1552 { 1553 # top-level node is fully enclosed in @ifnothtml 1554 # print fulltitle, subtitle, author, Overview or table of contents 1555 print $fh $Texi2HTML::TITLEPAGE; 1556 if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'}) 1557 { 1558 print $fh '<h2> ' . $Texi2HTML::NAME{'Overview'} . "</h2>\n" . "<blockquote\n"; 1559 my $nw = main::print_lines($fh, $Texi2HTML::OVERVIEW); 1560 print $fh "</blockquote>\n"; 1561 } 1562 elsif (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::THISDOC{'setcontentsaftertitlepage'}) 1563 { 1564 print $fh '<h1> ' . $Texi2HTML::NAME{'Contents'} . "</h1>\n"; 1565 my $nw = main::print_lines($fh, $Texi2HTML::TOC_LINES); 1566 } 1567 } 1568} 1569 1570################################################################### 1571# Layout of Toc, Overview, and Footnotes pages 1572# By default, we use "normal" layout 1573# Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined 1574# use: my $buttons = [...] to redefine navigation buttons 1575sub T2H_DEFAULT_print_Toc 1576{ 1577 return &$print_misc(@_); 1578} 1579sub T2H_DEFAULT_print_Overview 1580{ 1581 return &$print_misc(@_); 1582} 1583sub T2H_DEFAULT_print_Footnotes 1584{ 1585 return &$print_misc(@_); 1586} 1587sub T2H_DEFAULT_print_About 1588{ 1589 # if there is no section navigation and it is not split, the 1590 # navigation information is useless 1591 return &$print_misc(@_) if ($SPLIT or $SECTION_NAVIGATION); 1592} 1593 1594sub T2H_DEFAULT_print_misc_header 1595{ 1596 my $fh = shift; 1597 my $buttons = shift; 1598 &$print_page_head($fh) if $SPLIT; 1599 &$print_head_navigation($fh, $buttons) if ($SPLIT or $SECTION_NAVIGATION); 1600} 1601 1602sub T2H_DEFAULT_print_misc_footer 1603{ 1604 my $fh = shift; 1605 my $buttons = shift; 1606 my $nwords = shift; 1607 &$print_foot_navigation($fh, $buttons); 1608 print $fh "$SMALL_RULE\n"; 1609 if ($SPLIT) 1610 { 1611 &$print_navigation($fh, $buttons);# if ($SPLIT ne 'node'); 1612 &$print_page_foot($fh); 1613 } 1614} 1615 1616sub T2H_DEFAULT_print_misc 1617{ 1618 my $fh = shift; 1619 my $buttons = \@MISC_BUTTONS; 1620 &$print_misc_header($fh, $buttons); 1621 print $fh "<h1>$Texi2HTML::NAME{This}</h1>\n"; 1622 main::print_lines($fh); 1623 &$print_misc_footer($fh, $buttons); 1624} 1625################################################################## 1626# section_footer is only called if SPLIT eq 'section' 1627# section_footer: after print_section of last section, before print_page_foot 1628# 1629 1630sub T2H_DEFAULT_print_section_footer 1631{ 1632 my $fh = shift; 1633 my $buttons = \@SECTION_FOOTER_BUTTONS; 1634 &$end_section ($fh, 1); 1635 &$print_navigation($fh, $buttons); 1636} 1637 1638################################################################### 1639# chapter_header and chapter_footer are only called if 1640# SPLIT eq 'chapter' 1641# chapter_header: after print_page_head, before print_section 1642# chapter_footer: after print_section of last section, before print_page_foot 1643# 1644# If you want to get rid of navigation stuff after each section, 1645# redefine print_section such that it does not call print_navigation, 1646# and put print_navigation into print_chapter_header 1647sub T2H_DEFAULT_print_chapter_header 1648{ 1649 # nothing to do there, by default, the navigation panel 1650 # is the section navigation panel 1651 if (! $SECTION_NAVIGATION) 1652 { # in this case print_navigation is called here. 1653 my $fh = shift; 1654 my $buttons = \@CHAPTER_BUTTONS; 1655 &$print_head_navigation($fh, $buttons); #do that instead ? 1656 #&$print_head_navigation($fh, $buttons); # FIXME VERTICAL_HEAD_NAVIGATION ? 1657 print $fh "\n$MIDDLE_RULE\n"; 1658 } 1659} 1660 1661sub T2H_DEFAULT_print_chapter_footer 1662{ 1663 my $fh = shift; 1664 my $buttons = \@CHAPTER_BUTTONS; 1665 &$print_foot_navigation($fh); 1666 print $fh "$BIG_RULE\n"; 1667 &$print_navigation($fh, $buttons); 1668} 1669 1670sub T2H_DEFAULT_print_section_header 1671{ 1672 # nothing to do there, by default 1673 if (! $SECTION_NAVIGATION) 1674 { # in this case print_navigation is called here. 1675 my $fh = shift; 1676 my $buttons = \@SECTION_BUTTONS; 1677 &$print_head_navigation($fh, $buttons); 1678 } 1679} 1680 1681################################################################### 1682# Layout of standard header and footer 1683# 1684 1685sub T2H_DEFAULT_print_page_head($) 1686{ 1687 my $fh = shift; 1688 my $longtitle = "$Texi2HTML::THISDOC{'title_simple_format'}"; 1689 $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if (defined ($Texi2HTML::SIMPLE_TEXT{'This'}) and ($Texi2HTML::SIMPLE_TEXT{'This'} !~ /^\s*$/) and $SPLIT); 1690 my $description = $DOCUMENT_DESCRIPTION; 1691 $description = $longtitle if (!defined($description)); 1692 $description = "<meta name=\"description\" content=\"$description\">" if 1693 ($description ne ''); 1694 my $encoding = ''; 1695 $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING_NAME\">" if (defined($ENCODING_NAME) and ($ENCODING_NAME ne '')); 1696 print $fh <<EOT; 1697$DOCTYPE 1698<html> 1699$Texi2HTML::THISDOC{'copying'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program} --> 1700<!-- 1701$Texi2HTML::THISDOC{program_authors} 1702--> 1703<head> 1704<title>$longtitle</title> 1705 1706$description 1707<meta name="keywords" content="$longtitle"> 1708<meta name="resource-type" content="document"> 1709<meta name="distribution" content="global"> 1710<meta name="Generator" content="$Texi2HTML::THISDOC{program}"> 1711$encoding 1712$CSS_LINES 1713$EXTRA_HEAD 1714</head> 1715 1716<body $BODYTEXT> 1717$AFTER_BODY_OPEN 1718EOT 1719} 1720 1721sub program_string() 1722{ 1723 my $user = $Texi2HTML::THISDOC{'user'}; 1724 my $date = $Texi2HTML::THISDOC{'today'}; 1725 $user = '' if (!defined($user)); 1726 $date = '' if (!defined($date)); 1727 if (($user ne '') and ($date ne '')) 1728 { 1729 return &$I('This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.', { 1730 'user' => $user, 'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} }); 1731 } 1732 elsif ($user ne '') 1733 { 1734 return &$I('This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.', { 1735 'user' => $user, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} }); 1736 } 1737 elsif ($date ne '') 1738 { 1739 return &$I('This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.', { 1740 'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program'} }); 1741 } 1742 return &$I('This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.', { 1743 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' 1744=> $Texi2HTML::THISDOC{'program'} }); 1745} 1746 1747sub T2H_DEFAULT_end_section($$) 1748{ 1749 my $fh = shift; 1750 my $end_foot_navigation = shift; 1751 &$print_foot_navigation($fh) if ($end_foot_navigation); 1752 print $fh "$BIG_RULE\n"; 1753} 1754 1755sub T2H_DEFAULT_print_page_foot($) 1756{ 1757 my $fh = shift; 1758 my $program_string = program_string(); 1759 print $fh <<EOT; 1760<p> 1761 <font size="-1"> 1762 $program_string 1763 </font> 1764 <br> 1765$PRE_BODY_CLOSE 1766</p> 1767</body> 1768</html> 1769EOT 1770} 1771 1772################################################################### 1773# Layout of navigation panel 1774 1775sub T2H_DEFAULT_print_head_navigation($$) 1776{ 1777 my $fh = shift; 1778 my $buttons = shift; 1779 if ($VERTICAL_HEAD_NAVIGATION) 1780 { 1781 print $fh <<EOT; 1782<table border="0" cellpadding="0" cellspacing="0"> 1783<tr valign="top"> 1784<td align="left"> 1785EOT 1786 } 1787 main::print_lines($fh, $Texi2HTML::THIS_HEADER); 1788 &$print_navigation($fh, $buttons, $VERTICAL_HEAD_NAVIGATION); 1789 if ($VERTICAL_HEAD_NAVIGATION) 1790 { 1791 print $fh <<EOT; 1792</td> 1793<td align="left"> 1794EOT 1795 } 1796 elsif (defined $SPLIT 1797 and ($SPLIT eq 'node')) 1798 { 1799 print $fh "$SMALL_RULE\n"; 1800 } 1801} 1802 1803sub T2H_DEFAULT_print_foot_navigation 1804{ 1805 my $fh = shift; 1806 if ($VERTICAL_HEAD_NAVIGATION) 1807 { 1808 print $fh <<EOT; 1809</td> 1810</tr> 1811</table> 1812EOT 1813 } 1814} 1815 1816###################################################################### 1817# navigation panel 1818# 1819# how to create IMG tag 1820sub T2H_DEFAULT_button_icon_img 1821{ 1822 my $button = shift; 1823 my $icon = shift; 1824 my $name = shift; 1825 return '' if (!defined($icon)); 1826 $button = "" if (!defined ($button)); 1827 $name = '' if (!defined($name)); 1828 my $alt = ''; 1829 if ($name ne '') 1830 { 1831 if ($button ne '') 1832 { 1833 $alt = "$button: $name"; 1834 } 1835 else 1836 { 1837 $alt = $name; 1838 } 1839 } 1840 else 1841 { 1842 $alt = $button; 1843 } 1844 return qq{<img src="$icon" border="0" alt="$alt" align="middle">}; 1845} 1846 1847sub T2H_DEFAULT_print_navigation 1848{ 1849 my $fh = shift; 1850 my $buttons = shift; 1851 my $vertical = shift; 1852 my $spacing = 1; 1853 print $fh '<table cellpadding="', $spacing, '" cellspacing="', $spacing, 1854 "\" border=\"0\">\n"; 1855 1856 print $fh "<tr>" unless $vertical; 1857 for my $button (@$buttons) 1858 { 1859 print $fh qq{<tr valign="top" align="left">\n} if $vertical; 1860 print $fh qq{<td valign="middle" align="left">}; 1861 1862 if (ref($button) eq 'CODE') 1863 { 1864 &$button($fh, $vertical); 1865 } 1866 elsif (ref($button) eq 'SCALAR') 1867 { 1868 print $fh "$$button" if defined($$button); 1869 } 1870 elsif (ref($button) eq 'ARRAY') 1871 { 1872 my $text = $button->[1]; 1873 my $button_href = $button->[0]; 1874 # verify that $button_href is simple text and text is a reference 1875 if (defined($button_href) and !ref($button_href) 1876 and defined($text) and (ref($text) eq 'SCALAR') and defined($$text)) 1877 { # use given text 1878 if ($Texi2HTML::HREF{$button_href}) 1879 { 1880 print $fh "" . 1881 &$anchor('', 1882 $Texi2HTML::HREF{$button_href}, 1883 $$text 1884 ) 1885 ; 1886 } 1887 else 1888 { 1889 print $fh $$text; 1890 } 1891 } 1892 } 1893 elsif ($button eq ' ') 1894 { # handle space button 1895 print $fh 1896 ($ICONS && $ACTIVE_ICONS{' '}) ? 1897 &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{' '}) : 1898 $NAVIGATION_TEXT{' '}; 1899 #next; 1900 } 1901 elsif ($Texi2HTML::HREF{$button}) 1902 { # button is active 1903 my $btitle = $BUTTONS_GOTO{$button} ? 1904 'title="' . $BUTTONS_GOTO{$button} . '"' : ''; 1905 if ($ICONS && $ACTIVE_ICONS{$button}) 1906 { # use icon 1907 print $fh '' . 1908 &$anchor('', 1909 $Texi2HTML::HREF{$button}, 1910 &$button_icon_img($BUTTONS_NAME{$button}, 1911 $ACTIVE_ICONS{$button}, 1912 $Texi2HTML::SIMPLE_TEXT{$button}), 1913 $btitle 1914 ); 1915 } 1916 else 1917 { # use text 1918 print $fh 1919 '[' . 1920 &$anchor('', 1921 $Texi2HTML::HREF{$button}, 1922 $NAVIGATION_TEXT{$button}, 1923 $btitle 1924 ) . 1925 ']'; 1926 } 1927 } 1928 else 1929 { # button is passive 1930 print $fh 1931 $ICONS && $PASSIVE_ICONS{$button} ? 1932 &$button_icon_img($BUTTONS_NAME{$button}, 1933 $PASSIVE_ICONS{$button}, 1934 $Texi2HTML::SIMPLE_TEXT{$button}) : 1935 1936 "[" . $NAVIGATION_TEXT{$button} . "]"; 1937 } 1938 print $fh "</td>\n"; 1939 print $fh "</tr>\n" if $vertical; 1940 } 1941 print $fh "</tr>" unless $vertical; 1942 print $fh "</table>\n"; 1943} 1944 1945###################################################################### 1946# Frames: this is from "Richard Y. Kim" <ryk@coho.net> 1947# Should be improved to be more conforming to other _print* functions 1948# FIXME pass toc_file and main_file as args or in $Texi2HTML::THISDOC ? 1949 1950sub T2H_DEFAULT_print_frame 1951{ 1952 my $fh = shift; 1953 my $toc_file = shift; 1954 my $main_file = shift; 1955 print $fh <<EOT; 1956$FRAMESET_DOCTYPE 1957<html> 1958<head><title>$Texi2HTML::THISDOC{title}</title></head> 1959<frameset cols="140,*"> 1960 <frame name="toc" src="$toc_file"> 1961 <frame name="main" src="$main_file"> 1962</frameset> 1963</html> 1964EOT 1965} 1966 1967sub T2H_DEFAULT_print_toc_frame 1968{ 1969 my $fh = shift; 1970 my $stoc_lines = shift; 1971 &$print_page_head($fh); 1972 print $fh <<EOT; 1973<h2>Content</h2> 1974EOT 1975 print $fh map {s/\bhref=/target="main" href=/; $_;} @$stoc_lines; 1976 print $fh "</body></html>\n"; 1977} 1978 1979# This subroutine is intended to fill @Texi2HTML::TOC_LINES and 1980# @Texi2HTML::OVERVIEW with the table of contents and short table of 1981# contents. 1982# 1983# arguments: 1984# ref on an array containing all the elements 1985 1986# each element is a reference on a hash. The following keys might be of 1987# use: 1988# 'top': true if this is the top element 1989# 'index_page': true if the element is an index page added because of index 1990# splitting 1991# 'toc_level': level of the element in the table of content. Highest level 1992# is 1 for the @top element and for chapters, appendix and so on, 1993# 2 for section, unnumberedsec and so on... 1994# 'tocid': label used for reference linking to the element in table of 1995# contents 1996# 'file': the file containing the element, usefull to do href to that file 1997# in case the document is split. 1998# 'text': text of the element, with section number 1999# 'text_nonumber': text of the element, without section number 2000 2001# Relevant configuration variables are: 2002# $NUMBER_SECTIONS 2003# $TOC_LIST_ATTRIBUTE: usefull in case a list is used 2004# $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames. 2005# $BEFORE_OVERVIEW 2006# $AFTER_OVERVIEW 2007# $BEFORE_TOC_LINES 2008# $AFTER_TOC_LINES 2009# $DO_CONTENTS 2010# $DO_SCONTENTS 2011 2012sub T2H_DEFAULT_toc_body($) 2013{ 2014} 2015 2016sub T2H_DEFAULT_inline_contents($$$) 2017{ 2018 my $fh = shift; 2019 my $command = shift; 2020 my $element = shift; 2021 my $name; 2022 my $lines; 2023 2024 my $result = undef; 2025 2026 if ($command eq 'contents') 2027 { 2028 $name = $Texi2HTML::NAME{'Contents'}; 2029 $lines = $Texi2HTML::TOC_LINES; 2030 } 2031 else 2032 { 2033 $name = $Texi2HTML::NAME{'Overview'}; 2034 $lines = $Texi2HTML::OVERVIEW; 2035 } 2036 if (@{$lines}) 2037 { 2038 $result = [ "".&$anchor($element->{'id'})."\n", 2039 "<h1>$name</h1>\n" ]; 2040 push @$result, @$lines; 2041 } 2042 2043 return $result; 2044} 2045 2046sub T2H_DEFAULT_css_lines ($$) 2047{ 2048 my $import_lines = shift; 2049 my $rule_lines = shift; 2050 return if (defined($CSS_LINES) or (!@$rule_lines and !@$import_lines and (! keys(%css_map)))); 2051 $CSS_LINES = "<style type=\"text/css\">\n<!--\n"; 2052 $CSS_LINES .= join('',@$import_lines) . "\n" if (@$import_lines); 2053 foreach my $css_rule (sort(keys(%css_map))) 2054 { 2055 next unless ($css_map{$css_rule}); 2056 $CSS_LINES .= "$css_rule {$css_map{$css_rule}}\n"; 2057 } 2058 $CSS_LINES .= join('',@$rule_lines) . "\n" if (@$rule_lines); 2059 $CSS_LINES .= "-->\n</style>\n"; 2060} 2061 2062###################################################################### 2063# About page 2064# 2065 2066# PRE_ABOUT can be a function reference or a scalar. 2067# Note that if it is a scalar, T2H_InitGlobals has not been called, 2068# and all global variables like $ADDRESS are not available. 2069$PRE_ABOUT = sub 2070{ 2071 return ' ' . program_string() . "\n"; 2072}; 2073 2074# If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>. 2075$AFTER_ABOUT = ''; 2076 2077%BUTTONS_EXAMPLE = 2078 ( 2079 'Top', ' ', 2080 'Contents', ' ', 2081 'Overview', ' ', 2082 'Index', ' ', 2083 'This', '1.2.3', 2084 'Back', '1.2.2', 2085 'FastBack', '1', 2086 'Prev', '1.2.2', 2087 'Up', '1.2', 2088 'Next', '1.2.4', 2089 'NodeUp', '1.2', 2090 'NodeNext', '1.2.4', 2091 'NodePrev', '1.2.2', 2092 'Following', '1.2.4', 2093 'Forward', '1.2.4', 2094 'FastForward', '2', 2095 'About', ' ', 2096 'First', '1.', 2097 'Last', '1.2.4', 2098 ); 2099 2100sub T2H_DEFAULT_about_body 2101{ 2102 my $about = "<p>\n"; 2103 if (ref($PRE_ABOUT) eq 'CODE') 2104 { 2105 $about .= &$PRE_ABOUT(); 2106 } 2107 else 2108 { 2109 $about .= $PRE_ABOUT; 2110 } 2111 $about .= <<EOT; 2112</p> 2113<p> 2114EOT 2115 $about .= &$I(' The buttons in the navigation panels have the following meaning:') . "\n"; 2116 $about .= <<EOT; 2117</p> 2118<table border="1"> 2119 <tr> 2120EOT 2121 $about .= ' <th> ' . &$I('Button') . " </th>\n" . 2122' <th> ' . &$I('Name') . " </th>\n" . 2123' <th> ' . &$I('Go to') . " </th>\n" . 2124' <th> ' . &$I('From 1.2.3 go to') . "</th>\n" . " </tr>\n"; 2125 2126 for my $button (@SECTION_BUTTONS) 2127 { 2128 next if $button eq ' ' || ref($button) eq 'CODE' || ref($button) eq 'SCALAR' || ref($button) eq 'ARRAY'; 2129 $about .= " <tr>\n <td align=\"center\">"; 2130 $about .= 2131 ($ICONS && $ACTIVE_ICONS{$button} ? 2132 &$button_icon_img($BUTTONS_NAME{$button}, $ACTIVE_ICONS{$button}) : 2133 ' [' . $NAVIGATION_TEXT{$button} . '] '); 2134 $about .= "</td>\n"; 2135 $about .= <<EOT; 2136 <td align="center">$BUTTONS_NAME{$button}</td> 2137 <td>$BUTTONS_GOTO{$button}</td> 2138 <td>$BUTTONS_EXAMPLE{$button}</td> 2139 </tr> 2140EOT 2141 } 2142 2143 $about .= <<EOT; 2144</table> 2145 2146<p> 2147EOT 2148 $about .= &$I(' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:') . "\n"; 2149 2150# where the <strong> Example </strong> assumes that the current position 2151# is at <strong> Subsubsection One-Two-Three </strong> of a document of 2152# the following structure: 2153 $about .= <<EOT; 2154</p> 2155 2156<ul> 2157EOT 2158 $about .= ' <li> 1. ' . &$I('Section One') . "\n" . 2159" <ul>\n" . 2160' <li>1.1 ' . &$I('Subsection One-One') . "\n"; 2161 $about .= <<EOT; 2162 <ul> 2163 <li>...</li> 2164 </ul> 2165 </li> 2166EOT 2167 $about .= ' <li>1.2 ' . &$I('Subsection One-Two') . "\n" . 2168" <ul>\n" . 2169' <li>1.2.1 ' . &$I('Subsubsection One-Two-One') . "</li>\n" . 2170' <li>1.2.2 ' . &$I('Subsubsection One-Two-Two') . "</li>\n" . 2171' <li>1.2.3 ' . &$I('Subsubsection One-Two-Three') . " \n" 2172. 2173' <strong><== ' . &$I('Current Position') . " </strong></li>\n" . 2174' <li>1.2.4 ' . &$I('Subsubsection One-Two-Four') . "</li>\n" . 2175" </ul>\n" . 2176" </li>\n" . 2177' <li>1.3 ' . &$I('Subsection One-Three') . "\n"; 2178 $about .= <<EOT; 2179 <ul> 2180 <li>...</li> 2181 </ul> 2182 </li> 2183EOT 2184 $about .= ' <li>1.4 ' . &$I('Subsection One-Four') . "</li>\n"; 2185 $about .= <<EOT; 2186 </ul> 2187 </li> 2188</ul> 2189$AFTER_ABOUT 2190EOT 2191 return $about; 2192} 2193 2194sub T2H_DEFAULT_titlepage() 2195{ 2196 my $result = ''; 2197 if (@{$Texi2HTML::THISDOC{'titles'}} 2198 or @{$Texi2HTML::THISDOC{'subtitles'}} 2199 or @{$Texi2HTML::THISDOC{'authors'}}) 2200 { 2201 $result = "<div align=\"center\">\n"; 2202 foreach my $title (@{$Texi2HTML::THISDOC{'titles'}}) 2203 { 2204 $result .= '<h1>' . $title . "</h1>\n"; 2205 } 2206 foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}}) 2207 { 2208 $result .= '<h2>' . $subtitle . "</h2>\n"; 2209 } 2210 foreach my $author (@{$Texi2HTML::THISDOC{'authors'}}) 2211 { 2212 $result .= '<strong> ' . $author . " </strong><br>\n"; 2213 } 2214 $result .= "</div>\n$DEFAULT_RULE\n"; 2215 } 2216 2217 $Texi2HTML::TITLEPAGE = $result . $Texi2HTML::TITLEPAGE; 2218 2219 if ($Texi2HTML::THISDOC{'setcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}}) 2220 { 2221 foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}}) 2222 { 2223 $Texi2HTML::TITLEPAGE .= $line; 2224 } 2225 $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; 2226 } 2227 if ($Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'} and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}}) 2228 { 2229 foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}}) 2230 { 2231 $Texi2HTML::TITLEPAGE .= $line; 2232 } 2233 $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n"; 2234 } 2235} 2236 2237# FIXME Honor DOCUMENT_DESCRIPTION? 2238sub T2H_DEFAULT_print_redirection_page($) 2239{ 2240 my $fh = shift; 2241 my $longtitle = "$Texi2HTML::THISDOC{'title_simple_format'}"; 2242 $longtitle .= ": $Texi2HTML::SIMPLE_TEXT{'This'}" if exists $Texi2HTML::SIMPLE_TEXT{'This'}; 2243 my $description = $longtitle; 2244 my $encoding = ''; 2245 $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING_NAME\">" if (defined($ENCODING_NAME) and ($ENCODING_NAME ne '')); 2246 my $href = &$anchor('', $Texi2HTML::HREF{'This'}, $Texi2HTML::NAME{'This'}); 2247 my $string = &$I('The node you are looking for is at %{href}.', 2248 { 'href' => $href }); 2249 print $fh <<EOT; 2250$DOCTYPE 2251<html> 2252<!-- Created on $Texi2HTML::THISDOC{'today'} by $Texi2HTML::THISDOC{'program'} --> 2253<!-- 2254$Texi2HTML::THISDOC{'program_authors'} 2255--> 2256<head> 2257<title>$longtitle</title> 2258 2259<meta name="description" content="$description"> 2260<meta name="keywords" content="$longtitle"> 2261<meta name="resource-type" content="document"> 2262<meta name="distribution" content="global"> 2263<meta name="Generator" content="$Texi2HTML::THISDOC{program}"> 2264$encoding 2265$CSS_LINES 2266<meta http-equiv="Refresh" content="2; url=$Texi2HTML::HREF{'This'}"> 2267$EXTRA_HEAD 2268</head> 2269 2270<body $BODYTEXT> 2271$AFTER_BODY_OPEN 2272<p>$string</p> 2273</body> 2274EOT 2275} 2276 2277sub T2H_DEFAULT_node_file_name($$) 2278{ 2279 my $node = shift; 2280 my $type = shift; 2281 return undef if ($node->{'external_node'} or $node->{'index_page'} 2282 or ($type eq 'top' and !$NEW_CROSSREF_STYLE)); 2283 my $node_file_base; 2284 if ($type eq 'top' and defined($TOP_NODE_FILE)) 2285 { 2286 $node_file_base = $TOP_NODE_FILE; 2287 } 2288 elsif ($NEW_CROSSREF_STYLE) 2289 { 2290 if ($TRANSLITERATE_NODE) 2291 { 2292 $node_file_base = $node->{'cross_manual_file'}; 2293 } 2294 else 2295 { 2296 $node_file_base = $node->{'cross_manual_target'}; 2297 } 2298 } 2299 else 2300 { 2301 $node_file_base = main::remove_texi($node->{'texi'}); 2302 $node_file_base =~ s/[^\w\.\-]/-/g; 2303 } 2304 if (defined($NODE_FILE_EXTENSION) and $NODE_FILE_EXTENSION ne '') 2305 { 2306 return ($node_file_base . ".$NODE_FILE_EXTENSION"); 2307 } 2308 return $node_file_base; 2309} 2310 2311######################################################################## 2312# Control of formatting: 2313# 1.) For some changes, it is often enough to change the value of 2314# some global map. It might necessitate building a little 2315# function along with the change in hash, if the change is the use 2316# of another function (in style_map). 2317# 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines, 2318# give them another name, and assign them to the respective 2319# $<fnc> variable (below). 2320 2321 2322# 2323# This hash should have keys corresponding with the nonletter command accent 2324# whose following character is considered to be the argument 2325# This hash associates an accent macro to the ISO name for the accent if any. 2326# The customary use of this map is to find the ISO name appearing in html 2327# entity (like é) associated with a texinfo accent macro. 2328# 2329# The keys of the hash are 2330# ": umlaut 2331# ~: tilda accent 2332# ^: circumflex accent 2333# `: grave accent 2334# ': acute accent 2335# =: macron accent 2336%accent_map = ( 2337 '"', 'uml', 2338 '~', 'tilde', 2339 '^', 'circ', 2340 '`', 'grave', 2341 "'", 'acute', 2342 '=', '', 2343 ); 2344 2345# 2346# texinfo "simple things" (@foo) to HTML ones 2347# 2348%simple_map = ( 2349 "*", "<br>", # HTML+ 2350 ' ', ' ', 2351 "\t", ' ', 2352 "\n", ' ', 2353 # "­" or "­" could also be possible for @-, but it seems 2354 # that some browser will consider this as an always visible hyphen mark 2355 # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html) 2356 '-', '', # hyphenation hint 2357 '|', '', # used in formatting commands @evenfooting and friends 2358 '/', '', 2359 # spacing commands 2360 ':', '', 2361 '!', '!', 2362 '?', '?', 2363 '.', '.', 2364 '@', '@', 2365 '}', '}', 2366 '{', '{', 2367 ); 2368 2369# this map is used in preformatted text 2370%simple_map_pre = %simple_map; 2371$simple_map_pre{'*'} = "\n"; 2372 2373# 2374# texinfo "things" (@foo{}) to HTML ones 2375# 2376%things_map = ( 2377 'TeX' => 'TeX', 2378 'LaTeX' => 'LaTeX', 2379# pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing) 2380# 'br', '<br>', # paragraph break 2381 'bullet' => '*', 2382# #'copyright' => '(C)', 2383 'copyright' => '©', 2384 'registeredsymbol' => '®', 2385 'dots' => '<small class="dots">...</small>', 2386 'enddots' => '<small class="enddots">....</small>', 2387 'equiv' => '==', 2388# FIXME i18n 2389 'error' => 'error-->', 2390 'expansion' => '==>', 2391 'minus' => '-', 2392 'point' => '-!-', 2393 'print' => '-|', 2394 'result' => '=>', 2395 # set in code using the language 2396 # 'today', &pretty_date, 2397 'today' => '', 2398 'aa' => 'å', 2399 'AA' => 'Å', 2400 'ae' => 'æ', 2401 'oe' => 'œ', #pertusus: also œ. œ not in html 3.2 2402 'AE' => 'Æ', 2403 'OE' => 'Œ', #pertusus: also Œ. Œ not in html 3.2 2404 'o' => 'ø', 2405 'O' => 'Ø', 2406 'ss' => 'ß', 2407 'l' => 'ł', 2408 'L' => 'Ł', 2409 'exclamdown' => '¡', 2410 'questiondown' => '¿', 2411 'pounds' => '£', 2412 'ordf' => 'ª', 2413 'ordm' => 'º', 2414 'comma' => ',', 2415 'euro' => '€', 2416 'tie' => ' ', 2417 ); 2418 2419# This map is used in preformatted environments 2420%pre_map = %things_map; 2421$pre_map{'dots'} = '...'; 2422$pre_map{'enddots'} = '....'; 2423#$pre_map{'br'} = "\n"; 2424 2425# ascii representation of @-commands 2426%ascii_simple_map = ( 2427 "*", "\n", # HTML+ 2428 ' ', ' ', 2429 "\t", "\t", 2430 "\n", "\n", 2431 '-', '', # hyphenation hint 2432 '|', '', # used in formatting commands @evenfooting and friends 2433 '/', '', 2434 ':', '', 2435 '!', '!', 2436 '?', '?', 2437 '.', '.', 2438 '@', '@', 2439 '}', '}', 2440 '{', '{', 2441); 2442 2443%ascii_things_map = ( 2444 'TeX' => 'TeX', 2445 'LaTeX' => 'LaTeX', 2446 'bullet' => '*', 2447 'copyright' => '(C)', 2448 'registeredsymbol' => '(R)', 2449 'dots' => '...', 2450 'enddots' => '....', 2451 'equiv' => '==', 2452# FIXME i18n 2453 'error' => 'error-->', 2454 'expansion' => '==>', 2455 'minus' => '-', 2456 'point' => '-!-', 2457 'print' => '-|', 2458 'result' => '=>', 2459 'today' => '', 2460 'aa' => 'aa', 2461 'AA' => 'AA', 2462 'ae' => 'ae', 2463 'oe' => 'oe', 2464 'AE' => 'AE', 2465 'OE' => 'OE', 2466 'o' => '/o', 2467 'O' => '/O', 2468 'ss' => 'ss', 2469 'l' => '/l', 2470 'L' => '/L', 2471 'exclamdown' => '?', 2472 'questiondown' => '!', 2473 'pounds' => '#', 2474 'ordf' => 'a', 2475 'ordm' => 'o', 2476 'comma' => ',', 2477 'euro' => 'Euro', 2478 'tie' => ' ', 2479); 2480 2481# 2482# This map is used when texi elements are removed and replaced 2483# by simple text 2484# 2485%simple_map_texi = ( 2486 "*", "", 2487 " ", " ", 2488 "\t", " ", 2489 "-", "-", # soft hyphen 2490 "\n", "\n", 2491 "|", "", 2492 # spacing commands 2493 ":", "", 2494 "!", "!", 2495 "?", "?", 2496 ".", ".", 2497 "-", "", 2498 '@', '@', 2499 '}', '}', 2500 '{', '{', 2501 ); 2502 2503# text replacing macros when texi commands are removed and plain text is 2504# produced 2505%texi_map = ( 2506 'TeX', 'TeX', 2507 'LaTeX', 'LaTeX', 2508 'bullet', '*', 2509 'copyright', 'C', 2510 'registeredsymbol', 'R', 2511 'dots', '...', 2512 'enddots', '....', 2513 'equiv', '==', 2514 'error', 'error-->', 2515 'expansion', '==>', 2516 'minus', '-', 2517 'point', '-!-', 2518 'print', '-|', 2519 'result', '=>', 2520 'today' => '', 2521 'aa', 'aa', 2522 'AA', 'AA', 2523 'ae', 'ae', 2524 'oe', 'oe', 2525 'AE', 'AE', 2526 'OE', 'OE', 2527 'o', 'o', 2528 'O', 'O', 2529 'ss', 'ss', 2530 'l', 'l', 2531 'L', 'L', 2532 'exclamdown', '! upside-down', 2533 #'exclamdown', '¡', 2534 'questiondown', '? upside-down', 2535 #'questiondown', '¿', 2536 'pounds', 'pound sterling', 2537 #'pounds', '£' 2538 'ordf' => 'a', 2539 'ordm' => 'o', 2540 'comma' => ',', 2541 'euro' => 'Euro', 2542 'tie' => ' ', 2543 ); 2544 2545# taken from 2546#Latin extended additionnal 2547#http://www.alanwood.net/unicode/latin_extended_additional.html 2548#C1 Controls and Latin-1 Supplement 2549#http://www.alanwood.net/unicode/latin_1_supplement.html 2550#Latin Extended-A 2551#http://www.alanwood.net/unicode/latin_extended_a.html 2552#Latin Extended-B 2553#http://www.alanwood.net/unicode/latin_extended_b.html 2554#dotless i: 0131 2555 2556#http://www.alanwood.net/unicode/arrows.html 21** 2557#http://www.alanwood.net/unicode/general_punctuation.html 20** 2558#http://www.alanwood.net/unicode/mathematical_operators.html 22** 2559 2560%unicode_map = ( 2561 'bullet' => '2022', 2562 'copyright' => '00A9', 2563 'registeredsymbol' => '00AE', 2564 'dots' => '2026', 2565 'enddots' => '', 2566 'equiv' => '2261', 2567 'error' => '', 2568 'expansion' => '2192', 2569 'minus' => '2212', # in mathematical operators 2570# 'minus' => '002D', # in latin1 2571 'point' => '2605', 2572 'print' => '22A3', 2573 'result' => '21D2', 2574 'today' => '', 2575 'aa' => '00E5', 2576 'AA' => '00C5', 2577 'ae' => '00E6', 2578 'oe' => '0153', 2579 'AE' => '00C6', 2580 'OE' => '0152', 2581 'o' => '00F8', 2582 'O' => '00D8', 2583 'ss' => '00DF', 2584 'l' => '0142', 2585 'L' => '0141', 2586 'exclamdown' => '00A1', 2587 'questiondown' => '00BF', 2588 'pounds' => '00A3', 2589 'ordf' => '00AA', 2590 'ordm' => '00BA', 2591 'comma' => '002C', 2592 'euro' => '20AC', 2593 'tie' => '', 2594# 'tie' => '0020', 2595 ); 2596 2597%transliterate_map = ( 2598 '00C5' => 'AA', 2599 '00E5' => 'aa', 2600 '00D8' => 'OE', 2601 '00F8' => 'oe', 2602 '00E6' => 'ae', 2603 '0153' => 'oe', 2604 '00C6' => 'AE', 2605 '0152' => 'OE', 2606 '00DF' => 'ss', 2607 '0141' => 'L', 2608 '0142' => 'l', 2609 '00D0' => 'DH', 2610 '0415' => 'E', 2611 '0435' => 'e', 2612 '0426' => 'C', 2613 '042A' => 'W', 2614 '044A' => 'w', 2615 '042C' => 'X', 2616 '044C' => 'x', 2617 '042E' => 'yu', 2618 '042F' => 'YA', 2619 '044F' => 'ya', 2620 '0433' => 'g', 2621 '0446' => 'c', 2622 '04D7' => 'IO', 2623 '00DD' => 'Y', # unidecode gets this wrong ? 2624 ); 2625 2626foreach my $symbol(keys(%unicode_map)) 2627{ 2628 if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol})) 2629 { 2630 $no_transliterate_map{$unicode_map{$symbol}} = 1; 2631 } 2632} 2633 2634%ascii_character_map = ( 2635 ' ' => '0020', 2636 '!' => '0021', 2637 '"' => '0022', 2638 '#' => '0023', 2639 '$' => '0024', 2640 '%' => '0025', 2641 '&' => '0026', 2642 "'" => '0027', 2643 '(' => '0028', 2644 ')' => '0029', 2645 '*' => '002A', 2646 '+' => '002B', 2647 ',' => '002C', 2648 '-' => '002D', 2649 '.' => '002E', 2650 '/' => '002F', 2651 ':' => '003A', 2652 ';' => '003B', 2653 '<' => '003C', 2654 '=' => '003D', 2655 '>' => '003E', 2656 '?' => '003F', 2657 '@' => '0040', 2658 '[' => '005B', 2659 '\\' => '005C', 2660 ']' => '005D', 2661 '^' => '005E', 2662 '_' => '005F', 2663 '`' => '0060', 2664 '{' => '007B', 2665 '|' => '007C', 2666 '}' => '007D', 2667 '~' => '007E', 2668); 2669 2670%perl_charset_to_html = ( 2671 'utf8' => 'utf-8', 2672 'utf-8-strict' => 'utf-8', 2673 'ascii' => 'us-ascii', 2674); 2675 2676# symbols used for the commands if $USE_ISO is true. 2677%iso_symbols = ( 2678 'equiv' => '≡', 2679 'dots' => '…', 2680 'bullet' => '•', 2681 'result' => '⇒', 2682 'expansion' => '→', 2683 'point' => '∗', 2684 "'" => '’', 2685 '`' => '‘', 2686 ); 2687 2688# not used currently for html, but used in chm.init 2689%numeric_entity_map = (); 2690 2691foreach my $symbol (keys(%unicode_map)) 2692{ 2693 if ($symbol ne '') 2694 { 2695 $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';'; 2696 } 2697} 2698 2699# When the value begins with & the function with that name is used to do the 2700# html. The first argument is the text enclosed within {}, the second is the 2701# style name (which is also the key of the hash) 2702# 2703# Otherwithe the value is the html element used to enclose the text, and if 2704# there is a " the resulting text is also enclosed within `' 2705my %old_style_map = ( 2706 'acronym', '', 2707 'asis', '', 2708 'b', 'b', 2709 'cite', 'cite', 2710 'code', 'code', 2711 'command', 'code', 2712 'ctrl', '&default_ctrl', 2713 'dfn', 'em', 2714 'dmn', '', 2715 'email', '&default_email', 2716 'emph', 'em', 2717 'env', 'code', 2718 'file', '"tt', 2719 'i', 'i', 2720 'kbd', 'kbd', 2721 'key', 'kbd', 2722 'math', 'em', 2723 'option', '"samp', 2724 'r', '', 2725 'samp', '"samp', 2726 'sc', '&default_sc', 2727 'strong', 'strong', 2728 't', 'tt', 2729 'uref', '&default_uref', 2730 'url', '&default_url', 2731 'var', 'var', 2732 'verb', 'tt', 2733 'titlefont', '&default_titlefont', 2734 'w', '', 2735 ); 2736 2737# default is {'args' => ['normal'], 'attribute' => ''}, 2738%style_map = ( 2739 'asis', {}, 2740 'b', {'attribute' => 'b'}, 2741 'cite', {'attribute' => 'cite'}, 2742 'code', {'args' => ['code'], 'attribute' => 'code'}, 2743 'command', {'args' => ['code'], 'attribute' => 'code'}, 2744 'ctrl', {'function' => \&t2h_default_ctrl,'type' => 'simple_type'}, 2745 'dfn', {'attribute' => 'em'}, 2746 'dmn', {}, 2747 'email', {'args' => ['code', 'normal'], 2748 'function' => \&t2h_default_email, 2749 'type' => 'simple_type'}, 2750 #'email', {'args' => ['normal', 'normal'], 2751 # 'function' => \&t2h_default_email}, 2752 'emph', {'attribute' => 'em'}, 2753 'env', {'args' => ['code'], 'attribute' => 'code'}, 2754 'file', {'args' => ['code'], 'attribute' => 'tt', 'quote' => '"'}, 2755 'i', {'attribute' => 'i'}, 2756 'slanted', {'attribute' => 'i'}, 2757 'sansserif', {'attribute' => 'span class="sansserif"'}, 2758 'kbd', {'args' => ['code'], 'attribute' => 'kbd'}, 2759 'key', {'begin' => '<', 'end' => '>'}, 2760 'math', {'attribute' => 'em'}, 2761 'option', {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'}, 2762 'r', {'attribute' => 'span class="roman"'}, 2763 'samp', {'args' => ['code'], 'attribute' => 'samp', 'quote' => '"'}, 2764# 'sc', {'function' => \&t2h_default_sc}, 2765 'sc', {'attribute' => 'small'}, 2766 'strong', {'attribute' => 'strong'}, 2767 't', {'attribute' => 'tt'}, 2768 'uref', {'function' => \&t2h_default_uref, 2769 'args' => ['code', 'normal', 'normal'], 2770 'type' => 'simple_type' }, 2771 #'uref', {'function' => \&t2h_default_uref, 2772 # 'args' => ['normal', 'normal', 'normal']}, 2773 'url', {'function' => \&t2h_default_uref, 2774 'args' => ['code', 'normal', 'normal'], 2775 'type' => 'simple_type'}, 2776 'indicateurl', {'args' => ['code'], 'begin' => '<<code>', 'end' => '</code>>','type' => 'simple_type'}, 2777 'var', {'attribute' => 'var'}, 2778 'verb', {'args' => ['code'], 'attribute' => 'tt'}, 2779 'titlefont', {'function' => \&t2h_default_titlefont, 2780 'type' => 'simple_type'}, 2781 'w', {'type' => 'simple_type'}, 2782 ); 2783 2784%command_type = (); 2785 2786foreach my $style (keys(%style_map)) 2787{ 2788 if (exists($style_map{$style}->{'type'})) 2789 { 2790 $command_type{$style} = $style_map{$style}->{'type'}; 2791 } 2792 else 2793 { 2794 $command_type{$style} = 'style'; 2795 } 2796} 2797 2798%unicode_diacritical = ( 2799 'H' => '030B', 2800 'ringaccent' => '030A', 2801 "'" => '0301', 2802 'v' => '030C', 2803 ',' => '0327', 2804 '^' => '0302', 2805 'dotaccent' => '0307', 2806 '`' => '0300', 2807 '=' => '0304', 2808 '~' => '0303', 2809 '"' => '0308', 2810 'udotaccent' => '0323', 2811 'ubaraccent' => '0332', 2812 'u' => '0306', 2813 'tieaccent' => '0361' 2814); 2815 2816%unicode_accents = ( 2817 'dotaccent' => { # dot above 2818 'A' => '0226', #C moz-1.2 2819 'a' => '0227', #c moz-1.2 2820 'B' => '1E02', 2821 'b' => '1E03', 2822 'C' => '010A', 2823 'c' => '010B', 2824 'D' => '1E0A', 2825 'd' => '1E0B', 2826 'E' => '0116', 2827 'e' => '0117', 2828 'F' => '1E1E', 2829 'f' => '1E1F', 2830 'G' => '0120', 2831 'g' => '0121', 2832 'H' => '1E22', 2833 'h' => '1E23', 2834 'i' => '0069', 2835 'I' => '0130', 2836 'N' => '1E44', 2837 'n' => '1E45', 2838 'O' => '022E', #Y moz-1.2 2839 'o' => '022F', #v moz-1.2 2840 'P' => '1E56', 2841 'p' => '1E57', 2842 'R' => '1E58', 2843 'r' => '1E59', 2844 'S' => '1E60', 2845 's' => '1E61', 2846 'T' => '1E6A', 2847 't' => '1E6B', 2848 'W' => '1E86', 2849 'w' => '1E87', 2850 'X' => '1E8A', 2851 'x' => '1E8B', 2852 'Y' => '1E8E', 2853 'y' => '1E8F', 2854 'Z' => '017B', 2855 'z' => '017C', 2856 }, 2857 'udotaccent' => { # dot below 2858 'A' => '1EA0', 2859 'a' => '1EA1', 2860 'B' => '1E04', 2861 'b' => '1E05', 2862 'D' => '1E0C', 2863 'd' => '1E0D', 2864 'E' => '1EB8', 2865 'e' => '1EB9', 2866 'H' => '1E24', 2867 'h' => '1E25', 2868 'I' => '1ECA', 2869 'i' => '1ECB', 2870 'K' => '1E32', 2871 'k' => '1E33', 2872 'L' => '1E36', 2873 'l' => '1E37', 2874 'M' => '1E42', 2875 'm' => '1E43', 2876 'N' => '1E46', 2877 'n' => '1E47', 2878 'O' => '1ECC', 2879 'o' => '1ECD', 2880 'R' => '1E5A', 2881 'r' => '1E5B', 2882 'S' => '1E62', 2883 's' => '1E63', 2884 'T' => '1E6C', 2885 't' => '1E6D', 2886 'U' => '1EE4', 2887 'u' => '1EE5', 2888 'V' => '1E7E', 2889 'v' => '1E7F', 2890 'W' => '1E88', 2891 'w' => '1E89', 2892 'Y' => '1EF4', 2893 'y' => '1EF5', 2894 'Z' => '1E92', 2895 'z' => '1E93', 2896 }, 2897 'ubaraccent' => { # line below 2898 'B' => '1E06', 2899 'b' => '1E07', 2900 'D' => '1E0E', 2901 'd' => '1E0F', 2902 'h' => '1E96', 2903 'K' => '1E34', 2904 'k' => '1E35', 2905 'L' => '1E3A', 2906 'l' => '1E3B', 2907 'N' => '1E48', 2908 'n' => '1E49', 2909 'R' => '1E5E', 2910 'r' => '1E5F', 2911 'T' => '1E6E', 2912 't' => '1E6F', 2913 'Z' => '1E94', 2914 'z' => '1E95', 2915 }, 2916 ',' => { # cedilla 2917 'C' => '00C7', 2918 'c' => '00E7', 2919 'D' => '1E10', 2920 'd' => '1E11', 2921 'E' => '0228', #C moz-1.2 2922 'e' => '0229', #c moz-1.2 2923 'G' => '0122', 2924 'g' => '0123', 2925 'H' => '1E28', 2926 'h' => '1E29', 2927 'K' => '0136', 2928 'k' => '0137', 2929 'L' => '013B', 2930 'l' => '013C', 2931 'N' => '0145', 2932 'n' => '0146', 2933 'R' => '0156', 2934 'r' => '0157', 2935 'S' => '015E', 2936 's' => '015F', 2937 'T' => '0162', 2938 't' => '0163', 2939 }, 2940 '=' => { # macron 2941 'A' => '0100', 2942 'a' => '0101', 2943 'E' => '0112', 2944 'e' => '0113', 2945 'I' => '012A', 2946 'i' => '012B', 2947 'G' => '1E20', 2948 'g' => '1E21', 2949 'O' => '014C', 2950 'o' => '014D', 2951 'U' => '016A', 2952 'u' => '016B', 2953 'Y' => '0232', #? moz-1.2 2954 'y' => '0233', #? moz-1.2 2955 }, 2956 '"' => { # diaeresis 2957 'A' => '00C4', 2958 'a' => '00E4', 2959 'E' => '00CB', 2960 'e' => '00EB', 2961 'H' => '1E26', 2962 'h' => '1E27', 2963 'I' => '00CF', 2964 'i' => '00EF', 2965 'O' => '00D6', 2966 'o' => '00F6', 2967 't' => '1E97', 2968 'U' => '00DC', 2969 'u' => '00FC', 2970 'W' => '1E84', 2971 'w' => '1E85', 2972 'X' => '1E8C', 2973 'x' => '1E8D', 2974 'y' => '00FF', 2975 'Y' => '0178', 2976 }, 2977 'u' => { # breve 2978 'A' => '0102', 2979 'a' => '0103', 2980 'E' => '0114', 2981 'e' => '0115', 2982 'G' => '011E', 2983 'g' => '011F', 2984 'I' => '012C', 2985 'i' => '012D', 2986 'O' => '014E', 2987 'o' => '014F', 2988 'U' => '016C', 2989 'u' => '016D', 2990 }, 2991 "'" => { # acute 2992 'A' => '00C1', 2993 'a' => '00E1', 2994 'C' => '0106', 2995 'c' => '0107', 2996 'E' => '00C9', 2997 'e' => '00E9', 2998 'G' => '01F4', 2999 'g' => '01F5', 3000 'I' => '00CD', 3001 'i' => '00ED', 3002 'K' => '1E30', 3003 'k' => '1E31', 3004 'L' => '0139', 3005 'l' => '013A', 3006 'M' => '1E3E', 3007 'm' => '1E3F', 3008 'N' => '0143', 3009 'n' => '0144', 3010 'O' => '00D3', 3011 'o' => '00F3', 3012 'P' => '1E54', 3013 'p' => '1E55', 3014 'R' => '0154', 3015 'r' => '0155', 3016 'S' => '015A', 3017 's' => '015B', 3018 'U' => '00DA', 3019 'u' => '00FA', 3020 'W' => '1E82', 3021 'w' => '1E83', 3022 'Y' => '00DD', 3023 'y' => '00FD', 3024 'Z' => '0179', 3025 'z' => '018A', 3026 }, 3027 '~' => { # tilde 3028 'A' => '00C3', 3029 'a' => '00E3', 3030 'E' => '1EBC', 3031 'e' => '1EBD', 3032 'I' => '0128', 3033 'i' => '0129', 3034 'N' => '00D1', 3035 'n' => '00F1', 3036 'O' => '00D5', 3037 'o' => '00F5', 3038 'U' => '0168', 3039 'u' => '0169', 3040 'V' => '1E7C', 3041 'v' => '1E7D', 3042 'Y' => '1EF8', 3043 'y' => '1EF9', 3044 }, 3045 '`' => { # grave 3046 'A' => '00C0', 3047 'a' => '00E0', 3048 'E' => '00C8', 3049 'e' => '00E8', 3050 'I' => '00CC', 3051 'i' => '00EC', 3052 'N' => '01F8', 3053 'n' => '01F9', 3054 'O' => '00D2', 3055 'o' => '00F2', 3056 'U' => '00D9', 3057 'u' => '00F9', 3058 'W' => '1E80', 3059 'w' => '1E81', 3060 'Y' => '1EF2', 3061 'y' => '1EF3', 3062 }, 3063 '^' => { # circumflex 3064 'A' => '00C2', 3065 'a' => '00E2', 3066 'C' => '0108', 3067 'c' => '0109', 3068 'E' => '00CA', 3069 'e' => '00EA', 3070 'G' => '011C', 3071 'g' => '011D', 3072 'H' => '0124', 3073 'h' => '0125', 3074 'I' => '00CE', 3075 'i' => '00EE', 3076 'J' => '0134', 3077 'j' => '0135', 3078 'O' => '00D4', 3079 'o' => '00F4', 3080 'S' => '015C', 3081 's' => '015D', 3082 'U' => '00DB', 3083 'u' => '00FB', 3084 'W' => '0174', 3085 'w' => '0175', 3086 'Y' => '0176', 3087 'y' => '0177', 3088 'Z' => '1E90', 3089 'z' => '1E91', 3090 }, 3091 'ringaccent' => { # ring 3092 'A' => '00C5', 3093 'a' => '00E5', 3094 'U' => '016E', 3095 'u' => '016F', 3096 'w' => '1E98', 3097 'y' => '1E99', 3098 }, 3099 'v' => { # caron 3100 'A' => '01CD', 3101 'a' => '01CE', 3102 'C' => '010C', 3103 'c' => '010D', 3104 'D' => '010E', 3105 'd' => '010F', 3106 'E' => '011A', 3107 'e' => '011B', 3108 'G' => '01E6', 3109 'g' => '01E7', 3110 'H' => '021E', #K with moz-1.2 3111 'h' => '021F', #k with moz-1.2 3112 'I' => '01CF', 3113 'i' => '01D0', 3114 'K' => '01E8', 3115 'k' => '01E9', 3116 'L' => '013D', #L' with moz-1.2 3117 'l' => '013E', #l' with moz-1.2 3118 'N' => '0147', 3119 'n' => '0148', 3120 'O' => '01D1', 3121 'o' => '01D2', 3122 'R' => '0158', 3123 'r' => '0159', 3124 'S' => '0160', 3125 's' => '0161', 3126 'T' => '0164', 3127 't' => '0165', 3128 'U' => '01D3', 3129 'u' => '01D4', 3130 'Z' => '017D', 3131 'z' => '017E', 3132 }, 3133 'H' => { # double acute 3134 'O' => '0150', 3135 'o' => '0151', 3136 'U' => '0170', 3137 'u' => '0171', 3138 }, 3139); 3140 3141%transliterate_accent_map = (); 3142foreach my $command (keys(%unicode_accents)) 3143{ 3144 foreach my $letter(keys (%{$unicode_accents{$command}})) 3145 { 3146 $transliterate_accent_map{$unicode_accents{$command}->{$letter}} 3147 = $letter 3148 unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}})); 3149 } 3150} 3151 3152%special_accents = ( 3153 'ringaccent' => 'aA', 3154 "'" => 'aeiouyAEIOUY', 3155 ',' => 'cC', 3156 '^' => 'aeiouAEIOU', 3157 '`' => 'aeiouAEIOU', 3158 '~' => 'nNaoAO', 3159 '"' => 'aeiouyAEIOU', 3160); 3161 3162foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) 3163{ 3164 $style_map{$accent_command} = { 'function' => \&t2h_default_accent }; 3165 $old_style_map{$accent_command} = '&default_accent'; 3166 $style_map_texi{$accent_command} = { 'function' => \&t2h_default_ascii_accent }; 3167} 3168 3169sub default_accent($$) 3170{ 3171 my $text = shift; 3172 my $accent = shift; 3173 return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/)); 3174 return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); 3175 return $text . '<' if ($accent eq 'v'); 3176 return "&${text}cedil;" if (($accent eq ',') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); 3177 return ascii_accents($text, $accent); 3178} 3179 3180sub t2h_default_accent($$) 3181{ 3182 my $accent = shift; 3183 my $args = shift; 3184 3185 my $text = $args->[0]; 3186 3187 return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/)); 3188 return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); 3189 return $text . '<' if ($accent eq 'v'); 3190 return "&${text}cedil;" if (($accent eq ',') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/)); 3191# FIXME here there could be a conversion to the character in the right 3192# encoding, like 3193# if ($USE_UNICODE and defined($OUT_ENCODING) and $OUT_ENCODING ne '' 3194# and exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text})) 3195# { 3196# my $encoded_char = Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET); 3197# return $encoded_char if ($encoded_char ne ''); 3198# } 3199 if ($USE_NUMERIC_ENTITY) 3200 { 3201 if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text})) 3202 { 3203 return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';'); 3204 } 3205 } 3206 return ascii_accents($text, $accent); 3207} 3208 3209sub ascii_accents($$) 3210{ 3211 my $text = shift; 3212 my $accent = shift; 3213 return $text if ($accent eq 'dotless'); 3214 return $text . $accent if (defined($accent_map{$accent})); 3215 return $text . "''" if ($accent eq 'H'); 3216 return $text . '.' if ($accent eq 'dotaccent'); 3217 return $text . '*' if ($accent eq 'ringaccent'); 3218 return $text . '[' if ($accent eq 'tieaccent'); 3219 return $text . '(' if ($accent eq 'u'); 3220 return $text . '_' if ($accent eq 'ubaraccent'); 3221 return '.' . $text if ($accent eq 'udotaccent'); 3222 return $text . '<' if ($accent eq 'v'); 3223 return $text . ',' if ($accent eq ','); 3224} 3225 3226sub default_sc($$) 3227{ 3228 return '<small>' . uc($_[0]) . '</small>'; 3229} 3230 3231# now unused, upcasing is done in normal_text 3232sub t2h_default_sc($$$) 3233{ 3234 shift; 3235 my $args = shift; 3236 return '<small>' . uc($args->[0]) . '</small>'; 3237} 3238 3239sub default_ctrl($$) 3240{ 3241 return "^$_[0]"; 3242} 3243 3244sub t2h_default_ctrl($$$) 3245{ 3246 shift; 3247 my $args = shift; 3248 return "^$args->[0]"; 3249} 3250 3251sub default_sc_pre($$) 3252{ 3253 return uc($_[0]); 3254} 3255 3256# now unused, upcasing is done in normal_text 3257sub t2h_default_sc_pre($$$) 3258{ 3259 shift; 3260 my $args = shift; 3261 return uc($args->[0]); 3262} 3263 3264sub default_titlefont($$) 3265{ 3266 return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/); 3267 return ''; 3268} 3269 3270# Avoid adding h1 if the text is empty 3271sub t2h_default_titlefont($$$) 3272{ 3273 shift; 3274 my $args = shift; 3275 return "<h1 class=\"titlefont\">$args->[0]</h1>" if ($args->[0] =~ /\S/); 3276 return ''; 3277} 3278 3279# At some point in time (before 4.7?) according to the texinfo 3280# manual, url shouldn't lead to a link but rather be formatted 3281# like text. It is now what indicateurl do, url is the same that 3282# uref with one arg. If we did like makeinfo did it would have been 3283#sub url($$) 3284#{ 3285# return '<<code>' . $_[0] . '</code>>'; 3286#} 3287# 3288# This is unused, t2h_default_uref is used instead 3289sub t2h_default_url ($$) 3290{ 3291 shift; 3292 my $args = shift; 3293 my $url = shift @$args; 3294 #$url =~ s/\s*$//; 3295 #$url =~ s/^\s*//; 3296 $url = main::normalise_space($url); 3297 return '' unless ($url =~ /\S/); 3298 return &$anchor('', $url, $url); 3299} 3300 3301sub default_url ($$) 3302{ 3303 my $url = shift; 3304 my $command = shift; 3305 $url =~ s/\s*$//; 3306 $url =~ s/^\s*//; 3307 return '' unless ($url =~ /\S/); 3308 return &$anchor('', $url, $url); 3309} 3310 3311sub default_uref($$) 3312{ 3313 my $arg = shift; 3314 my $command = shift; 3315 my ($url, $text, $replacement); 3316 ($url, $text, $replacement) = split /,\s*/, $arg; 3317 $url =~ s/\s*$//; 3318 $url =~ s/^\s*//; 3319 $text = $replacement if (defined($replacement)); 3320 $text = $url unless ($text); 3321 return $text if ($url eq ''); 3322 return &$anchor('', $url, $text); 3323} 3324 3325sub t2h_default_uref($$) 3326{ 3327 shift; 3328 my $args = shift; 3329 my $url = shift @$args; 3330 my $text = shift @$args; 3331 my $replacement = shift @$args; 3332 #$url =~ s/\s*$//; 3333 #$url =~ s/^\s*//; 3334 $url = main::normalise_space($url); 3335 $replacement = '' if (!defined($replacement)); 3336 $replacement = main::normalise_space($replacement); 3337 $text = '' if (!defined($text)); 3338 $text = main::normalise_space($text); 3339 $text = $replacement if ($replacement ne ''); 3340 $text = $url unless ($text ne ''); 3341 return $text if ($url eq ''); 3342 return &$anchor('', $url, $text); 3343} 3344 3345sub default_email($$) 3346{ 3347 my $arg = shift; 3348 my $command = shift; 3349 my ($mail, $text); 3350 ($mail, $text) = split /,\s*/, $arg; 3351 $mail =~ s/\s*$//; 3352 $mail =~ s/^\s*//; 3353 $text = $mail unless ($text); 3354 return $text if ($mail eq ''); 3355 return &$anchor('', "mailto:$mail", $text); 3356} 3357 3358sub t2h_default_email($$) 3359{ 3360 my $command = shift; 3361 my $args = shift; 3362 my $mail = shift @$args; 3363 my $text = shift @$args; 3364 $mail = main::normalise_space($mail); 3365 #$mail =~ s/\s*$//; 3366 #$mail =~ s/^\s*//; 3367 $text = $mail unless (defined($text) and ($text ne '')); 3368 $text = main::normalise_space($text); 3369 return $text if ($mail eq ''); 3370 return &$anchor('', "mailto:$mail", $text); 3371} 3372 3373sub t2h_default_ascii_accent($$$$) 3374{ 3375 my $accent = shift; 3376 my $args = shift; 3377 3378 my $text = $args->[0]; 3379 return ascii_accents($text, $accent); 3380} 3381 3382sub t2h_default_no_texi_email 3383{ 3384 my $command = shift; 3385 my $args = shift; 3386 my $mail = shift @$args; 3387 my $text = shift @$args; 3388 $mail = main::normalise_space($mail); 3389 #$mail =~ s/\s*$//; 3390 #$mail =~ s/^\s*//; 3391 return $text if (defined($text) and ($text ne '')); 3392 return $mail; 3393} 3394 3395sub t2h_default_no_texi_image($$$$) 3396{ 3397 my $command = shift; 3398 my $args = shift; 3399 my $text = $args->[0]; 3400 $text = main::normalise_space($text); 3401 my @args = split (/\s*,\s*/, $text); 3402 return $args[0]; 3403} 3404 3405sub t2h_default_no_texi_acronym_like($$) 3406{ 3407 my $command = shift; 3408 my $args = shift; 3409 my $acronym_texi = $args->[0]; 3410 return (main::remove_texi($acronym_texi)); 3411} 3412 3413sub t2h_remove_command($$$$) 3414{ 3415 return ''; 3416} 3417 3418# This is used for style in preformatted sections 3419my %old_style_map_pre = %old_style_map; 3420$old_style_map_pre{'sc'} = '&default_sc_pre'; 3421$old_style_map_pre{'titlefont'} = ''; 3422 3423foreach my $command (keys(%style_map)) 3424{ 3425 $style_map_pre{$command} = {}; 3426 $style_map_texi{$command} = {} if (!exists($style_map_texi{$command})); 3427 $style_map_texi{$command}->{'args'} = $style_map{$command}->{'args'} 3428 if (exists($style_map{$command}->{'args'})); 3429 #print STDERR "COMMAND $command"; 3430 3431 foreach my $key (keys(%{$style_map{$command}})) 3432 { 3433 $style_map_pre{$command}->{$key} = $style_map{$command}->{$key}; 3434 } 3435} 3436 3437#$style_map_pre{'sc'}->{'function'} = \&t2h_default_sc_pre; 3438$style_map_pre{'sc'} = {}; 3439$style_map_pre{'titlefont'} = {}; 3440 3441#$style_map_texi{'sc'}->{'function'} = \&t2h_default_sc_pre; 3442$style_map_texi{'sc'} = {}; 3443$style_map_texi{'email'}->{'function'} = \&t2h_default_no_texi_email; 3444 3445####### special styles. You shouldn't need to change them 3446my %special_style = ( 3447 #'xref' => ['keep','normal','normal','keep','normal'], 3448 'xref' => { 'args' => ['keep','keep','keep','keep','keep'], 3449 'function' => \&main::do_xref }, 3450 'ref' => { 'args' => ['keep','keep','keep','keep','keep'], 3451 'function' => \&main::do_xref }, 3452 'pxref' => { 'args' => ['keep','keep','keep','keep','keep'], 3453 'function' => \&main::do_xref }, 3454 'inforef' => { 'args' => ['keep','keep','keep'], 3455 'function' => \&main::do_xref }, 3456 'image' => { 'args' => ['keep'], 'function' => \&main::do_image }, 3457 'anchor' => { 'args' => ['keep'], 'function' => \&main::do_anchor_label }, 3458 'footnote' => { 'args' => ['keep'], 'function' => \&main::do_footnote }, 3459 'shortcaption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption }, 3460 'caption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption }, 3461 'acronym', {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like}, 3462 'abbr', {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like}, 3463); 3464 3465# @image is replaced by the first arg in strings 3466$style_map_texi{'image'} = { 'args' => ['keep'], 3467 'function' => \&t2h_default_no_texi_image }; 3468 3469$style_map_texi{'acronym'} = { 'args' => ['keep','keep'], 3470 'function' => \&t2h_default_no_texi_acronym_like }; 3471$style_map_texi{'abbr'} = { 'args' => ['keep','keep'], 3472 'function' => \&t2h_default_no_texi_acronym_like }; 3473 3474foreach my $special (keys(%special_style)) 3475{ 3476 $style_map{$special} = $special_style{$special} 3477 unless (defined($style_map{$special})); 3478 $style_map_pre{$special} = $special_style{$special} 3479 unless (defined($style_map_pre{$special})); 3480 $style_map_texi{$special} = { 'args' => ['keep'], 3481 'function' => \&t2h_remove_command } 3482 unless (defined($style_map_texi{$special})); 3483} 3484####### end special styles. 3485 3486 3487#foreach my $command (keys(%style_map)) 3488#{ 3489# print STDERR "STYLE_MAP_TEXI $command($style_map_texi{$command}) "; 3490# print STDERR "ARGS $style_map_texi{$command}->{'args'} " if (defined($style_map_texi{$command}->{'args'})); 3491# print STDERR "FUN $style_map_texi{$command}->{'function'} " if (defined($style_map_texi{$command}->{'function'})); 3492# print STDERR "\n"; 3493#} 3494 3495# uncomment to use the old interface 3496#%style_map = %old_style_map; 3497#%style_map_pre = %old_style_map_pre; 3498 3499%simple_format_simple_map_texi = %simple_map_pre; 3500%simple_format_texi_map = %pre_map; 3501%simple_format_style_map_texi = (); 3502 3503foreach my $command (keys(%style_map_texi)) 3504{ 3505 #$simple_format_style_map_texi{$command} = {}; 3506 foreach my $key (keys (%{$style_map_texi{$command}})) 3507 { 3508 #print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n"; 3509 $simple_format_style_map_texi{$command}->{$key} = 3510 $style_map_texi{$command}->{$key}; 3511 } 3512 $simple_format_style_map_texi{$command} = {} if (!defined($simple_format_style_map_texi{$command})); 3513} 3514 3515foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents)) 3516{ 3517# $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal']; 3518 $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent; 3519} 3520 3521%format_map = ( 3522# 'quotation' => 'blockquote', 3523 # lists 3524# 'itemize' => 'ul', 3525 'enumerate' => 'ol', 3526 'multitable' => 'table', 3527 'table' => 'dl compact="compact"', 3528 'vtable' => 'dl compact="compact"', 3529 'ftable' => 'dl compact="compact"', 3530 'group' => '', 3531 ); 3532 3533%special_list_commands = ( 3534 'table' => {}, 3535 'vtable' => {}, 3536 'ftable' => {}, 3537 'itemize' => { 'bullet' => '' } 3538 ); 3539# 3540# texinfo format to align attribute of paragraphs 3541# 3542 3543%paragraph_style = ( 3544 'center' => 'center', 3545 'flushleft' => 'left', 3546 'flushright' => 'right', 3547 ); 3548 3549# an eval of these $complex_format_map->{what}->{'begin'} yields beginning 3550# an eval of these $complex_format_map->{what}->{'end'} yields end 3551# $EXAMPLE_INDENT_CELL and SMALL_EXAMPLE_INDENT_CELL can be usefull here 3552$complex_format_map = 3553{ 3554 'example' => 3555 { 3556 'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"}, 3557 'end' => q{"</td></tr></table>\n"}, 3558 }, 3559 'smallexample' => 3560 { 3561 'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"}, 3562 'end' => q{"</td></tr></table>\n"}, 3563 }, 3564 'display' => 3565 { 3566 'begin' => q{"<table><tr>$EXAMPLE_INDENT_CELL<td>"}, 3567 'end' => q{"</td></tr></table>\n"}, 3568 }, 3569 'smalldisplay' => 3570 { 3571 'begin' => q{"<table><tr>$SMALL_EXAMPLE_INDENT_CELL<td>"}, 3572 'end' => q{"</td></tr></table>\n"}, 3573 } 3574}; 3575 3576# format shouldn't narrow the margins 3577 3578$complex_format_map->{'lisp'} = $complex_format_map->{'example'}; 3579$complex_format_map->{'smalllisp'} = $complex_format_map->{'smallexample'}; 3580$complex_format_map->{'format'} = $complex_format_map->{'display'}; 3581$complex_format_map->{'smallformat'} = $complex_format_map->{'smalldisplay'}; 3582 3583%def_map = ( 3584 # basic commands 3585 'deffn', [ 'f', 'category', 'name', 'arg' ], 3586 'defvr', [ 'v', 'category', 'name' ], 3587 'deftypefn', [ 'f', 'category', 'type', 'name', 'arg' ], 3588 'deftypeop', [ 'f', 'category', 'class' , 'type', 'name', 'arg' ], 3589 'deftypevr', [ 'v', 'category', 'type', 'name' ], 3590 'defcv', [ 'v', 'category', 'class' , 'name' ], 3591 'deftypecv', [ 'v', 'category', 'class' , 'type', 'name' ], 3592 'defop', [ 'f', 'category', 'class' , 'name', 'arg' ], 3593 'deftp', [ 't', 'category', 'name', 'arg' ], 3594 # shortcuts 3595 # FIXME i18n 3596 'defun', 'deffn Function', 3597 'defmac', 'deffn Macro', 3598 'defspec', 'deffn {Special Form}', 3599 'defvar', 'defvr Variable', 3600 'defopt', 'defvr {User Option}', 3601 'deftypefun', 'deftypefn {Function}', 3602 'deftypevar', 'deftypevr Variable', 3603 'defivar', 'defcv {Instance Variable}', 3604 'deftypeivar', 'deftypecv {Instance Variable}', 3605 'defmethod', 'defop Method', 3606 'deftypemethod', 'deftypeop Method', 3607 ); 3608 3609# basic x commands 3610foreach my $key (keys(%def_map)) 3611{ 3612 $def_map{$key . 'x'} = $def_map{$key}; 3613} 3614 3615# 3616# miscalleneous commands 3617# 3618# Depending on the value, the command arg or spaces following the command 3619# are handled differently: 3620# 3621# the value is a reference on a hash. 3622# the hash keys are 3623# 'arg' if the value is 'line' then the remaining of the line is the arg 3624# if it is a number it is the number of args (separated by spaces) 3625# 'skip' if the value is 'line' then the remaining of the line is skipped 3626# if the value is 'space' space but no newline is skipped 3627# if the value is 'whitespace' space is skipped 3628# if the value is 'linewhitespace' space is skipped if there are 3629# only spaces remaining on the line 3630# if the value is 'linespace' space but no newline is skipped if 3631# there are only spaces remaining on the line 3632# 'texi' if true it is some texinfo code and @value and @macros are expanded 3633# 'keep' if true the args and the macro are kept, otherwise the macro 3634# args and skipped stuffs are removed 3635%misc_command = ( 3636 # not needed for formatting 3637 'raisesections' => {'skip' => 'line'}, # no arg 3638 'lowersections' => {'skip' => 'line'}, # no arg 3639 'contents' => {}, # no arg 3640 'shortcontents' => {}, # no arg 3641 'summarycontents'=> {}, # no arg 3642 'setcontentsaftertitlepage' => {}, # no arg 3643 'setshortcontentsaftertitlepage' => {}, # no arg 3644 'detailmenu' => {'skip' => 'whitespace'}, # no arg 3645 'end detailmenu' => {'skip' => 'space'}, # no arg 3646 'bye' => {'skip' => 'line'}, # no arg 3647 # comments 3648 'comment' => {'arg' => 'line'}, 3649 'c' => {'arg' => 'line'}, 3650 # in preamble 3651 'novalidate' => {}, # no arg 3652 'dircategory'=> {'skip' => 'line'}, # line. Position with regard 3653 # with direntry is significant 3654 'pagesizes' => {'skip' => 'line', 'arg' => 2}, # can have 2 args 3655 # or one? 200mm,150mm 11.5in 3656 'finalout' => {}, # no arg 3657 'paragraphindent' => {'skip' => 'line', 'arg' => 1}, # arg none asis 3658 # or a number and forbids anything else on the line 3659 'firstparagraphindent' => {'skip' => 'line', 'arg' => 1}, # none insert 3660 'frenchspacing' => {'arg' => 1}, # on off 3661 'exampleindent' => {'skip' => 'line', 'arg' => 1}, # asis or a number 3662 'footnotestyle'=> {'skip' => 'line', 'arg' => 1}, # end and separate 3663 # and nothing else on the line 3664 'afourpaper' => {'skip' => 'line'}, # no arg 3665 'afourlatex' => {'skip' => 'line'}, # no arg 3666 'afourwide' => {'skip' => 'line'}, # no arg 3667 'headings'=> {'skip' => 'line', 'arg' => 1}, 3668 #off on single double singleafter doubleafter 3669 # interacts with setchapternewpage 3670 'setchapternewpage' => {'skip' => 'line', 'arg' => 1}, # off on odd 3671 'everyheading' => {'arg' => 'line'}, 3672 'everyfooting' => {'arg' => 'line'}, 3673 'evenheading' => {'arg' => 'line'}, 3674 'evenfooting' => {'arg' => 'line'}, 3675 'oddheading' => {'arg' => 'line'}, 3676 'oddfooting' => {'arg' => 'line'}, 3677 'smallbook' => {'skip' => 'line'}, # no arg 3678 'setfilename' => {'arg' => 'line'}, 3679 'shorttitle' => {'arg' => 'line', 'texi' => 1}, 3680 'shorttitlepage' => {'arg' => 'line', 'texi' => 1}, 3681 'settitle' => {'arg' => 'line', 'texi' => 1}, 3682 'author' => {'arg' => 'line', 'texi' => 1}, 3683 'subtitle' => {'arg' => 'line', 'texi' => 1}, 3684 'title' => {'arg' => 'line', 'texi' => 1}, 3685 'syncodeindex' => {'skip' => 'linespace', 'arg' => 2}, 3686 # args are index identifiers 3687 'synindex' => {'skip' => 'linespace', 'arg' => 2}, 3688 'defindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg 3689 'defcodeindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg 3690 'documentlanguage' => {'skip' => 'whitespace', 'arg' => 1}, 3691 # language code arg 3692 'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code 3693 #example distinct 3694 'sp' => {'skip' => 'whitespace', 'arg' => 1}, # no arg 3695 # at the end of line or a numerical arg 3696 # formatting 3697 'page' => {}, # no arg (pagebreak) 3698 'refill' => {}, # no arg (obsolete, to be ignored) 3699 'noindent' => {'skip' => 'whitespace'}, # no arg 3700 'indent' => {'skip' => 'whitespace'}, 3701 'need' => {'skip' => 'line', 'arg' => 1}, # one numerical/real arg 3702 'exdent' => {'skip' => 'space'}, 3703 # not valid for info (should be in @iftex) 3704 'vskip' => {'arg' => 'line'}, # arg line in TeX 3705 'cropmarks' => {}, # no arg 3706 # miscalleneous 3707 'verbatiminclude'=> {'skip' => 'line'}, 3708 'documentencoding' => {'arg' => 1}, # makeinfo ignore the whole line 3709 # ??? 3710 'filbreak' => {}, 3711 # obsolete @-commands 3712 'quote-arg' => {}, 3713 'allow-recursion' => {}, 3714 ); 3715my %misc_command_old = ( 3716 # not needed for formatting 3717 'raisesections', 'line', # no arg 3718 'lowersections', 'line', # no arg 3719 'contents', 1, # no arg 3720 'shortcontents', 1, # no arg 3721 'summarycontents', 1, # no arg 3722 'detailmenu', 'whitespace', # no arg 3723 'end detailmenu', 'space', # no arg 3724 #'end detailmenu', 1, # no arg 3725 'novalidate', 1, # no arg 3726 'bye', 'line', # no arg 3727 # comments 3728 'comment', 'line', 3729 'c', 'line', 3730 # in preamble 3731 'dircategory', 'line', # line. Position with regard with direntry is 3732 # significant 3733 'pagesizes', 'line arg2', # can have 2 args 3734 'finalout', 1, # no arg 3735 'paragraphindent', 'line arg1', # in fact accepts only none asis 3736 # or a number and forbids anything else on the line 3737 'firstparagraphindent', 'line arg1', # in fact accepts only none insert 3738 'exampleindent', 'line arg1', # in fact accepts only asis or a number 3739 'footnotestyle', 'line arg1', # in fact accepts only end and separate 3740 # and nothing else on the line 3741 'afourpaper', 'line', # no arg 3742 'afourlatex', 'line', # no arg 3743 'afourwide', 'line', # no arg 3744 'headings', 'line', # one arg, possibilities are 3745 #off on single double singleafter doubleafter 3746 # interacts with setchapternewpage 3747 'setchapternewpage', 'line', # no arg 3748 'everyheading', 'line', 3749 'everyfooting', 'line', 3750 'evenheading', 'line', 3751 'evenfooting', 'line', 3752 'oddheading', 'line', 3753 'oddfooting', 'line', 3754 'smallbook', 'line', # no arg 3755 'setfilename', 'line', 3756 'shorttitle', 'linetexi', 3757 'shorttitlepage', 'linetexi', 3758 'settitle', 'linetexi', 3759 'author', 'linetexi', 3760 'subtitle', 'linetexi', 3761 'title','linetexi', 3762 'syncodeindex','linespace arg2', # args are 3763 'synindex','linespace arg2', 3764 'defindex', 'line arg1', # one identifier arg 3765 'defcodeindex', 'line arg1', # one identifier arg 3766 'documentlanguage', 'whitespace arg1', # one language code arg 3767 'kbdinputstyle', 'whitespace arg1', # one arg within 3768 #code example distnct 3769 'sp', 'whitespace arg1', # no arg at the en of line or a numerical arg 3770 # formatting 3771 'page', 1, # no arg (pagebreak) 3772 'refill', 1, # no arg (obsolete, to be ignored)) 3773 'noindent', 'space', # no arg 3774 'need', 'line arg1', # one numerical/real arg 3775 'exdent', 'space', 3776 # not valid for info (should be in @iftex) 3777 'vskip', 'line', # arg line in TeX 3778 'cropmarks', 1, # no arg 3779 # miscalleneous 3780 'verbatiminclude', 'line', 3781 'documentencoding', 'arg1', 3782 # ??? 3783 'filbreak', 1, 3784 ); 3785 3786%format_in_paragraph = ( 3787 'group' => 1, 3788 'html' => 1, 3789); 3790# map mapping css specification to style 3791 3792%css_map = 3793 ( 3794 'ul.toc' => "$TOC_LIST_STYLE", 3795 'pre.menu-comment' => "$MENU_PRE_STYLE", 3796 'pre.menu-preformatted' => "$MENU_PRE_STYLE", 3797 'a.summary-letter' => 'text-decoration: none', 3798 'pre.display' => 'font-family: serif', 3799 'pre.smalldisplay' => 'font-family: serif; font-size: smaller', 3800 'pre.smallexample' => 'font-size: smaller', 3801 'span.sansserif' => 'font-family:sans-serif; font-weight:normal;', 3802 'span.roman' => 'font-family:serif; font-weight:normal;' 3803 ); 3804 3805$css_map{'pre.format'} = $css_map{'pre.display'}; 3806$css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'}; 3807$css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'}; 3808 3809# The command_handler arrays are for commands formatted externally. 3810# The function references in @command_handler_init are called 3811# before the second pass, before the @-commands text collection. 3812# Those in @command_handler_process are called between the second pass 3813# and the third pass, after collection of @-commands text and before their 3814# expansion. 3815# Those in @command_handler_process are called after the third pass, 3816# after the document generation. 3817@command_handler_init = (); 3818@command_handler_process = (); 3819@command_handler_finish = (); 3820 3821# the keys of %command_handler are @-command names and the value 3822# is a hash reference with the following keys: 3823# 'init' function reference used to collect the @-command text 3824# 'expand' function reference used when expanding the @-command text 3825%command_handler = (); 3826 3827# formatting functions 3828 3829$anchor = \&t2h_default_anchor; 3830$def_item = \&t2h_default_def_item; 3831$def = \&t2h_default_def; 3832$menu = \&t2h_default_menu; 3833$menu_link = \&t2h_default_menu_link; 3834$menu_comment = \&t2h_default_menu_comment; 3835$menu_description = \&t2h_default_menu_description; 3836$simple_menu_link = \&t2h_default_simple_menu_link; 3837$external_ref = \&t2h_default_external_ref; 3838$external_href = \&t2h_default_external_href; 3839$internal_ref = \&t2h_default_internal_ref; 3840$table_item = \&t2h_default_table_item; 3841$table_line = \&t2h_default_table_line; 3842$table_list = \&t2h_default_table_list; 3843$row = \&t2h_default_row; 3844$cell = \&t2h_default_cell; 3845$list_item = \&t2h_default_list_item; 3846$comment = \&t2h_default_comment; 3847$def_line = \&t2h_default_def_line; 3848$def_line_no_texi = \&t2h_default_def_line_no_texi; 3849$raw = \&t2h_default_raw; 3850$raw_no_texi = \&t2h_default_raw_no_texi; 3851$heading = \&t2h_default_heading; 3852$paragraph = \&t2h_default_paragraph; 3853$preformatted = \&t2h_default_preformatted; 3854$foot_line_and_ref = \&t2h_default_foot_line_and_ref; 3855$foot_section = \&t2h_default_foot_section; 3856$image_files = \&t2h_default_image_files; 3857$image = \&t2h_default_image; 3858$address = \&t2h_default_address; 3859$index_entry_label = \&t2h_default_index_entry_label; 3860$index_summary = \&t2h_default_index_summary; 3861$summary_letter = \&t2h_default_summary_letter; 3862$index_entry = \&t2h_default_index_entry; 3863$index_letter = \&t2h_default_index_letter; 3864$print_index = \&t2h_default_print_index; 3865$protect_text = \&t2h_default_protect_text; 3866$normal_text = \&t2h_default_normal_text; 3867$complex_format = \&t2h_default_complex_format; 3868$cartouche = \&t2h_default_cartouche; 3869$sp = \&t2h_default_sp; 3870$definition_category = \&t2h_default_definition_category; 3871$copying_comment = \&t2h_default_copying_comment; 3872$index_summary_file_entry = \&t2h_default_index_summary_file_entry; 3873$index_summary_file_end = \&t2h_default_index_summary_file_end; 3874$index_summary_file_begin = \&t2h_default_index_summary_file_begin; 3875$empty_line = \&t2h_default_empty_line; 3876$unknown = \&t2h_default_unknown; 3877$unknown_style = \&t2h_default_unknown_style; 3878$caption_shortcaption = \&t2h_caption_shortcaption; 3879$float = \&t2h_default_float; 3880$listoffloats = \&t2h_default_listoffloats; 3881$listoffloats_entry = \&t2h_default_listoffloats_entry; 3882$listoffloats_caption = \&t2h_default_listoffloats_caption; 3883$listoffloats_float_style = \&t2h_default_listoffloats_float_style; 3884$listoffloats_style = \&t2h_default_listoffloats_style; 3885$acronym_like = \&t2h_default_acronym_like; 3886$quotation = \&t2h_default_quotation; 3887$quotation_prepend_text = \&t2h_default_quotation_prepend_text; 3888$paragraph_style_command = \&t2h_default_paragraph_style_command; 3889$heading_texi = \&t2h_default_heading_texi; 3890$index_element_heading_texi = \&t2h_default_index_element_heading_texi; 3891 3892# This function is called whenever a complex format is processed 3893# 3894# arguments: 3895# name of the format 3896# text appearing inside the format 3897# 3898# an eval of $complex_format->{format name}->{'begin'} should lead to the 3899# beginning of the complex format, an eval of 3900# $complex_format->{format name}->{'end'} should lead to the end of the 3901# complex format. 3902sub t2h_default_complex_format($$) 3903{ 3904 my $name = shift; 3905 my $text = shift; 3906 return '' if ($text eq ''); 3907 my $beginning = eval "$complex_format_map->{$name}->{'begin'}"; 3908 if ($@ ne '') 3909 { 3910 print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'begin'}: $@"; 3911 $beginning = ''; 3912 3913 } 3914 my $end = eval "$complex_format_map->{$name}->{'end'}"; 3915 if ($@ ne '') 3916 { 3917 print STDERR "$ERROR Evaluation of $complex_format_map->{$name}->{'end'}: $@"; 3918 $end = ''; 3919 3920 } 3921 return $beginning . $text . $end; 3922} 3923 3924sub t2h_default_empty_line($$) 3925{ 3926 my $text = shift; 3927 my $state = shift; 3928 #ignore the line if it just follows a deff 3929 return '' if ($state->{'deff_line'}); 3930 return $text; 3931} 3932 3933sub t2h_default_unknown($$$$) 3934{ 3935 my $macro = shift; 3936 my $line = shift; 3937 my $stack = shift; 3938 my $state = shift; 3939 3940 my ($result_line, $result, $result_text, $message); 3941 return ($line, 0, undef, undef); 3942} 3943 3944sub t2h_default_unknown_style($$$$) 3945{ 3946 my $command = shift; 3947 my $text = shift; 3948 my $state = shift; 3949 3950 my ($result, $result_text, $message); 3951 return (0, undef, undef); 3952} 3953 3954sub t2h_caption_shortcaption($) 3955{ 3956 my $float = shift; 3957 my $caption_lines; 3958 my $shortcaption_lines; 3959 my $style = $float->{'style_texi'}; 3960 if (defined($float->{'nr'})) 3961 { 3962 my $nr = $float->{'nr'}; 3963 if ($style ne '') 3964 { 3965 $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr}); 3966 } 3967 else 3968 { 3969 $style = $nr; 3970 } 3971 } 3972 3973 if (defined($float->{'caption_texi'})) 3974 { 3975 @$caption_lines = @{$float->{'caption_texi'}}; 3976 if (defined($style)) 3977 { 3978 $caption_lines->[0] = '@strong{' . &$I('%{style}: %{caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] }); 3979 } 3980 else 3981 { 3982 $caption_lines->[0] = '@strong{' . $caption_lines->[0]; 3983 } 3984 push @$caption_lines, "}\n"; 3985 } 3986 elsif (defined($style)) 3987 { 3988 $caption_lines->[0] = '@strong{' . $style . '}' . "\n"; 3989 } 3990 if (defined($float->{'shortcaption_texi'})) 3991 { 3992 @$shortcaption_lines = @{$float->{'shortcaption_texi'}}; 3993 if (defined($style)) 3994 { 3995 $shortcaption_lines->[0] = '@strong{' . &$I('%{style}: %{shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] }); 3996 } 3997 else 3998 { 3999 $shortcaption_lines->[0] = '@strong{' . $shortcaption_lines->[0]; 4000 } 4001 push @$shortcaption_lines, "}\n"; 4002 } 4003 elsif (defined($style)) 4004 { 4005 $shortcaption_lines->[0] = '@strong{' . $style . '}' . "\n"; 4006 } 4007 return ($caption_lines, $shortcaption_lines); 4008} 4009 4010sub t2h_default_float($$$$$) 4011{ 4012 my $text = shift; 4013 my $float = shift; 4014 my $caption = shift; 4015 my $shortcaption = shift; 4016 4017 my $label = ''; 4018 if (exists($float->{'id'})) 4019 { 4020 $label = &$anchor($float->{'id'}); 4021 } 4022 my $caption_text = ''; 4023 4024 if (defined($float->{'caption_texi'})) 4025 { 4026 $caption_text = $caption; 4027 } 4028 elsif (defined($float->{'shortcaption_texi'})) 4029 { 4030 $caption_text = $shortcaption; 4031 } 4032 elsif (defined($caption)) 4033 { 4034 $caption_text = $caption; 4035 } 4036 4037 return '<div class="float">' . "$label\n" . $text . '</div>' . $caption_text; 4038} 4039 4040sub t2h_default_listoffloats_style($) 4041{ 4042 my $style_texi = shift; 4043 return ($style_texi); 4044} 4045 4046sub t2h_default_listoffloats_float_style($$) 4047{ 4048 my $style_texi = shift; 4049 my $float = shift; 4050 4051 my $style = $float->{'style_texi'}; 4052 if (defined($float->{'nr'})) 4053 { 4054 my $nr = $float->{'nr'}; 4055 if ($style ne '') 4056 { 4057 $style = &$I('%{style} %{number}', { 'style' => $style, 'number' => $nr}); 4058 } 4059 else 4060 { 4061 $style = $nr; 4062 } 4063 } 4064 return $style; 4065} 4066 4067sub t2h_default_listoffloats_caption($) 4068{ 4069 my $float = shift; 4070 if (defined($float->{'shortcaption_texi'})) 4071 { 4072 return [ @{$float->{'shortcaption_texi'}} ]; 4073 } 4074 elsif (defined($float->{'caption_texi'})) 4075 { 4076 return [ @{$float->{'caption_texi'}} ]; 4077 } 4078 return [ ]; 4079} 4080 4081sub t2h_default_listoffloats_entry($$$$) 4082{ 4083 my $style_texi = shift; 4084 my $float = shift; 4085 my $float_style = shift; 4086 my $caption = shift; 4087 my $href = shift; 4088 4089 return '<dt>' . &$anchor('', $href, $float_style) . '</dt><dd>' . $caption 4090. '</dd>' . "\n"; 4091} 4092 4093sub t2h_default_listoffloats($$$) 4094{ 4095 my $style_texi = shift; 4096 my $style = shift; 4097 my $float_entries = shift; 4098 4099 my $result = "<dl class=\"listoffloats\">\n" ; 4100 foreach my $float_entry (@$float_entries) 4101 { 4102 $result .= $float_entry; 4103 } 4104 return $result . "</dl>\n"; 4105} 4106 4107# This function is used to protect characters which are special in html 4108# in inline text: &, ", <, and >. 4109# 4110# argument: 4111# text to be protected 4112sub t2h_default_protect_text($) 4113{ 4114 my $text = shift; 4115 $text =~ s/&/&/g; 4116 $text =~ s/</</g; 4117 $text =~ s/>/>/g; 4118 $text =~ s/\"/"/g; 4119 return $text; 4120} 4121 4122 4123sub in_small_caps($) 4124{ 4125 my $style_stack = shift; 4126 my $in_sc = 0; 4127 if ($style_stack and scalar(@{$style_stack})) 4128 { 4129 my $level = $#$style_stack; 4130 #print STDERR ":::$level ::@{$style_stack}\n"; 4131 while ($level >= 0) 4132 { 4133 if ($style_stack->[$level] eq 'sc') 4134 { 4135 $in_sc = 1; 4136 last; 4137 } 4138 $level--; 4139 } 4140 } 4141 return $in_sc; 4142} 4143# 4144# 4145sub t2h_default_normal_text($$$$$) 4146{ 4147 my $text = shift; 4148 my $in_raw_text = shift; 4149 my $in_preformatted = shift; 4150 my $in_code = shift; 4151 my $style_stack = shift; 4152 $text = uc($text) if (in_small_caps($style_stack)); 4153 $text = &$protect_text($text) unless($in_raw_text); 4154 if (! $in_code and !$in_preformatted) 4155 { 4156 if ($USE_ISO and !$in_raw_text) 4157 { 4158 $text =~ s/---/\&mdash\;/g; 4159 $text =~ s/--/\&ndash\;/g; 4160 $text =~ s/``/\&ldquo\;/g; 4161 $text =~ s/''/\&rdquo\;/g; 4162 } 4163 else 4164 { 4165 if ($in_raw_text) #FIXME really do that ? 4166 { 4167 $text =~ s/``/"/g; 4168 $text =~ s/''/"/g; 4169 } 4170 else 4171 { 4172 $text =~ s/``/"/g; 4173 $text =~ s/''/"/g; 4174 } 4175 # temporary reuse '' to store --- !.... 4176 # FIXME won't '---' be handled wrongly? 4177 # FIXME really do that in raw text? 4178 $text =~ s/---/''/g; 4179 $text =~ s/--/-/g; 4180 $text =~ s/''/--/g; 4181 } 4182 } 4183 return $text; 4184} 4185 4186# This function produces an anchor 4187# 4188# arguments: 4189# $name : anchor name 4190# $href : anchor href 4191# text : text displayed 4192# extra_attribs : added to anchor attributes list 4193sub t2h_default_anchor($;$$$) 4194{ 4195 my $name = shift; 4196 my $href = shift; 4197 my $text = shift; 4198 my $attributes = shift; 4199#print STDERR "!$name!$href!$text!$attributes!\n"; 4200 if (!defined($attributes) or ($attributes !~ /\S/)) 4201 { 4202 $attributes = ''; 4203 } 4204 else 4205 { 4206 $attributes = ' ' . $attributes; 4207 } 4208 $name = '' if (!defined($name) or ($name !~ /\S/)); 4209 $href = '' if (!defined($href) or ($href !~ /\S/)); 4210 $text = '' if (!defined($text)); 4211 return $text if (($name eq '') and ($href eq '')); 4212 $name = "name=\"$name\"" if ($name ne ''); 4213 $href = "href=\"$href\"" if ($href ne ''); 4214 $href = ' ' . $href if (($name ne '') and ($href ne '')); 4215#print STDERR "!!!$name!$href!$text!$attributes!\n"; 4216 return "<a ${name}${href}${attributes}>$text</a>"; 4217} 4218 4219# This function is used to format the text associated with a @deff/@end deff 4220# 4221# argument: 4222# text 4223# 4224# $DEF_TABLE should be used to distinguish between @def formatted as table 4225# and as definition lists. 4226sub t2h_default_def_item($) 4227{ 4228 my $text = shift; 4229 if ($text =~ /\S/) 4230 { 4231 if (! $DEF_TABLE) 4232 { 4233 return '<dd>' . $text . '</dd>'; 4234 } 4235 else 4236 { 4237 return '<tr><td colspan="2">' . $text . '</td></tr>'; 4238 } 4239 } 4240 return ''; 4241} 4242 4243sub t2h_default_definition_category($$$) 4244{ 4245 my $name = shift; 4246 my $class = shift; 4247 my $style = shift; 4248 return ($name) if (!defined($class) or $class =~ /^\s*$/); 4249 if ($style eq 'f') 4250 { 4251 return &$I('%{name} on %{class}', { 'name' => $name, 'class' => $class }); 4252 } 4253 elsif ($style eq 'v') 4254 { 4255 return &$I('%{name} of %{class}', { 'name' => $name, 'class' => $class }); 4256 } 4257 else 4258 { 4259 return $name; 4260 } 4261} 4262 4263# format the container for the @deffn line and text 4264# 4265# argument 4266# text of the whole @def, line and associated text. 4267# 4268# $DEF_TABLE should be used. 4269sub t2h_default_def($) 4270{ 4271 my $text = shift; 4272 if ($text =~ /\S/) 4273 { 4274 if (! $DEF_TABLE) 4275 { 4276 return "<dl>\n" . $text . "</dl>\n"; 4277 } 4278 else 4279 { 4280 return "<table width=\"100%\">\n" . $text . "</table>\n"; 4281 } 4282 } 4283 return ''; 4284 4285} 4286 4287# a whole menu 4288# 4289# argument: 4290# the whole menu text (entries and menu comments) 4291# 4292# argument: 4293# whole menu text. 4294sub t2h_default_menu($) 4295{ 4296 my $text = shift; 4297 if ($text =~ /\S/) 4298 { 4299 return "<table class=\"menu\" border=\"0\" cellspacing=\"0\">\n" 4300 . $text . "</table>\n"; 4301 } 4302} 4303 4304# a simple menu entry ref in case we aren't in a standard menu context 4305sub t2h_default_simple_menu_link($$$$$$) 4306{ 4307 my $entry = shift; 4308 my $preformatted = shift; 4309 my $href = shift; 4310 my $node = shift; 4311 my $name = shift; 4312 my $ending = shift; 4313 $ending = '' if (!defined($ending)); 4314 if (($entry eq '') or $NODE_NAME_IN_MENU or $preformatted) 4315 { 4316 $name .= ':' if ($name ne ''); 4317 $entry = "$MENU_SYMBOL$name$node"; 4318 } 4319 $entry = &$anchor('', $href, $entry) if ($href); 4320 $entry .= $ending if ($preformatted); 4321 $entry .= ' ' unless $preformatted; 4322 return $entry; 4323} 4324 4325# formats a menu entry link pointing to a node or section 4326# 4327# arguments: 4328# the entry text 4329# the state, a hash reference holding informations about the context, with a 4330# usefull entry, 'preformatted', true if we are in a preformatted format 4331# (a format keeping space between words). In that case a function 4332# of the main program, main::do_preformatted($text, $state) might 4333# be used to format the text with the current format style. 4334# href is optionnal. It is the reference to the section or the node anchor 4335# which should be used to make the link (typically it is the argument 4336# of a href= attribute in a <a> element). 4337sub t2h_default_menu_link($$$$$$) 4338{ 4339 my $entry = shift; 4340 my $state = shift; 4341 my $href = shift; 4342 my $node = shift; 4343 my $name = shift; 4344 my $ending = shift; 4345#print STDERR "MENU_LINK\n"; 4346 if (($entry eq '') or $NODE_NAME_IN_MENU or $state->{'preformatted'}) 4347 { 4348 $name .= ':' if ($name ne ''); 4349 $entry = "$MENU_SYMBOL$name$node"; 4350 } 4351 $entry = &$anchor ('', $href, $entry) if (defined($href)); 4352 return $entry if ($SIMPLE_MENU); 4353 if ($state->{'preformatted'}) 4354 { 4355 return '<tr><td>' . main::do_preformatted($entry . $ending, $state); 4356 } 4357 return "<tr><td align=\"left\" valign=\"top\">$entry</td><td> </td>"; 4358} 4359 4360sub simplify_text($) 4361{ 4362 my $text = shift; 4363 $text =~ s/[^\w]//og; 4364 return $text; 4365} 4366 4367# formats a menu entry description, ie the text appearing after the node 4368# specification in a menu entry an spanning until there is another 4369# menu entry, an empty line or some text at the very beginning of the line 4370# (we consider that text at the beginning of the line begins a menu comment) 4371# 4372# arguments: 4373# the description text 4374# the state. See menu_entry. 4375# the heading of the element associated with the node. 4376sub t2h_default_menu_description($$$) 4377{ 4378 my $text = shift; 4379 my $state = shift; 4380 my $element_text = shift; 4381 return $text if ($SIMPLE_MENU); 4382#print STDERR "MENU_DESCRIPTION element_text!$element_text, text!$text\n"; 4383 if ($state->{'preformatted'}) 4384 { 4385 return main::do_preformatted($text, $state) . '</td></tr>'; 4386 } 4387 elsif ($AVOID_MENU_REDUNDANCY) 4388 { 4389 $text = '' if (simplify_text($element_text) eq simplify_text($text)); 4390 } 4391 return "<td align=\"left\" valign=\"top\">$text</td></tr>\n"; 4392} 4393 4394# a menu comment (between menu lines) 4395# formats the container of a menu comment. A menu comment is any text 4396# appearing between menu lines, either separated by an empty line from 4397# the preceding menu entry, or a text beginning at the first character 4398# of the line (text not at the very beginning of the line is considered to 4399# be the continuation of a menu entry description text). 4400# 4401# The text itself is considered to be in a preformatted environment 4402# with name 'menu-commment' and with style $MENU_PRE_STYLE. 4403# 4404# argument 4405# text contained in the menu comment. 4406sub t2h_default_menu_comment($) 4407{ 4408 my $text = shift; 4409 return $text if ($SIMPLE_MENU); 4410 if ($text =~ /\S/) 4411 { 4412 return "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">$text</th></tr>"; 4413 } 4414 return ''; 4415} 4416 4417# Construct a href to an external source of information. 4418# node is the node with texinfo @-commands 4419# node_id is the node transliterated and transformed as explained in the 4420# texinfo manual 4421# node_xhtml_id is the node transformed such that it is unique and can 4422# be used to make an html cross ref as explained in the texinfo manual 4423# file is the file in '(file)node' 4424sub t2h_default_external_href($$$) 4425{ 4426 my $node = shift; 4427 my $node_id = shift; 4428 my $node_xhtml_id = shift; 4429 my $file = shift; 4430 $file = '' if (!defined($file)); 4431 my $default_target_split = $EXTERNAL_CROSSREF_SPLIT; 4432 my $target_split; 4433 my $target_mono; 4434 my $href_split; 4435 my $href_mono; 4436 if ($file ne '') 4437 { 4438 if ($NEW_CROSSREF_STYLE) 4439 { 4440 $file =~ s/\.[^\.]*$//; 4441 $file =~ s/^.*\///; 4442 my $href; 4443 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file})) 4444 { 4445 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'})) 4446 { 4447 $target_split = 1; 4448 $href_split = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'split'}->{'href'}; 4449 } 4450 if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'})) 4451 { 4452 $target_mono = 1; 4453 $href_mono = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{'mono'}->{'href'}; 4454 } 4455 } 4456 4457 if ((not $target_mono) and (not $target_split)) 4458 { # nothing specified for that manual, use default 4459 $target_split = $default_target_split; 4460 } 4461 elsif ($target_split and $target_mono) 4462 { # depends on the splitting of the manual 4463 $target_split = $SPLIT; 4464 } 4465 elsif ($target_mono) 4466 { # only mono specified 4467 $target_split = 0; 4468 } 4469 4470 if ($target_split) 4471 { 4472 if (defined($href_split)) 4473 { 4474 $file = "$href_split"; 4475 } 4476 elsif (defined($EXTERNAL_DIR)) 4477 { 4478 $file = "$EXTERNAL_DIR/$file"; 4479 } 4480 elsif ($SPLIT) 4481 { 4482 $file = "../$file"; 4483 } 4484 $file .= "/"; 4485 } 4486 else 4487 {# target not split 4488 if (defined($href_mono)) 4489 { 4490 $file = "$href_mono"; 4491 } 4492 else 4493 { 4494 if (defined($EXTERNAL_DIR)) 4495 { 4496 $file = "$EXTERNAL_DIR/$file"; 4497 } 4498 elsif ($SPLIT) 4499 { 4500 $file = "../$file"; 4501 } 4502 $file .= "." . $NODE_FILE_EXTENSION; 4503 } 4504 } 4505 } 4506 else 4507 { 4508 $file .= "/"; 4509 if (defined($EXTERNAL_DIR)) 4510 { 4511 $file = $EXTERNAL_DIR . $file; 4512 } 4513 else 4514 { 4515 $file = '../' . $file; 4516 } 4517 } 4518 } 4519 else 4520 { 4521 $target_split = $default_target_split; 4522 } 4523 if ($node eq '') 4524 { 4525 if ($NEW_CROSSREF_STYLE) 4526 { 4527 if ($target_split) 4528 { 4529 return $file . $TOP_NODE_FILE . '.' . $NODE_FILE_EXTENSION . '#Top'; 4530 # or ? 4531 #return $file . '#Top'; 4532 } 4533 else 4534 { 4535 return $file . '#Top'; 4536 } 4537 } 4538 else 4539 { 4540 return $file; 4541 } 4542 } 4543 my $target; 4544 if ($NEW_CROSSREF_STYLE) 4545 { 4546 $node = $node_id; 4547 $target = $node_xhtml_id; 4548 } 4549 else 4550 { 4551 $node = main::remove_texi($node); 4552 $node =~ s/[^\w\.\-]/-/g; 4553 } 4554 my $file_basename = $node; 4555 $file_basename = $TOP_NODE_FILE if ($node =~ /^top$/i); 4556 if ($NEW_CROSSREF_STYLE) 4557 { 4558 if ($target_split) 4559 { 4560 return $file . $file_basename . ".$NODE_FILE_EXTENSION" . '#' . $target; 4561 } 4562 else 4563 { 4564 return $file . '#' . $target; 4565 } 4566 } 4567 else 4568 { 4569 return $file . $file_basename . ".$NODE_FILE_EXTENSION"; 4570 } 4571} 4572 4573# format a reference external to the generated manual. This produces a full 4574# reference with introductive words and the reference itself. 4575# 4576# arguments: 4577# type of the reference: xref (reference at the beginning of a sentence), 4578# pxref (reference in a parenthesis), 4579# section in the book. This might be undef. 4580# book name. 4581# node and file name formatted according to the convention used in info 4582# '(file)node' and no node means the Top node. 4583# href linking to the html page containing the referenced node. A typical 4584# use for this href is a href attribute in an <a> element 4585# an optionnal cross reference name 4586sub t2h_default_external_ref($$$$$$) 4587{ 4588 my $type = shift; 4589 my $section = shift; 4590 my $book = shift; 4591 my $file_node = shift; 4592 my $href = shift; 4593 my $cross_ref = shift; 4594 4595 $file_node = "$cross_ref: $file_node" if (($file_node ne '') and ($cross_ref ne '')); 4596 $file_node = &$anchor('', $href, $file_node) if ($file_node ne ''); 4597 4598 # Yes, this is ugly, but this helps internationalization 4599 if ($type eq 'pxref') 4600 { 4601 if (($book ne '') and ($file_node ne '')) 4602 { 4603 return &$I('see %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne ''); 4604 return &$I('see %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book }); 4605 } 4606 elsif ($book ne '') 4607 { 4608 return &$I('see section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne ''); 4609 return &$I('see @cite{%{book}}', { 'book' => $book }); 4610 } 4611 elsif ($file_node ne '') 4612 { 4613 return &$I('see %{node_file_href}', { 'node_file_href' => $file_node }); 4614 } 4615 } 4616 if ($type eq 'xref') 4617 { 4618 if (($book ne '') and ($file_node ne '')) 4619 { 4620 return &$I('See %{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne ''); 4621 return &$I('See %{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book }); 4622 } 4623 elsif ($book ne '') 4624 { 4625 return &$I('See section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne ''); 4626 return &$I('See @cite{%{book}}', { 'book' => $book }); 4627 } 4628 elsif ($file_node ne '') 4629 { 4630 return &$I('See %{node_file_href}', { 'node_file_href' => $file_node }); 4631 } 4632 } 4633 if ($type eq 'ref') 4634 { 4635 if (($book ne '') and ($file_node ne '')) 4636 { 4637 return &$I('%{node_file_href} section `%{section}\' in @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book, 'section' => $section }) if ($section ne ''); 4638 return &$I('%{node_file_href} @cite{%{book}}', { 'node_file_href' => $file_node, 'book' => $book }); 4639 } 4640 elsif ($book ne '') 4641 { 4642 return &$I('section `%{section}\' in @cite{%{book}}', { 'book' => $book, 'section' => $section }) if ($section ne ''); 4643 return &$I('@cite{%{book}}', { 'book' => $book }); 4644 } 4645 elsif ($file_node ne '') 4646 { 4647 return &$I('%{node_file_href}', { 'node_file_href' => $file_node }); 4648 } 4649 } 4650 return ''; 4651} 4652 4653# format a reference to a node or a section in the generated manual. This 4654# produces a full reference with introductive words and the reference itself. 4655# 4656# arguments: 4657# type of the reference: xref (reference at the beginning of a sentence), 4658# pxref (reference in a parenthesis), 4659# href linking to the html page containing the node or the section. A typical 4660# use for this href is a href attribute in an <a> element 4661# short name for this reference 4662# name for this reference 4663# boolean true if the reference is a reference to a section 4664# 4665# $SHORT_REF should be used. 4666sub t2h_default_internal_ref($$$$$) 4667{ 4668 my $type = shift; 4669 my $href = shift; 4670 my $short_name = shift; 4671 my $name = shift; 4672 my $is_section = shift; 4673 4674 if (! $SHORT_REF) 4675 { 4676 $name = &$anchor('', $href, $name); 4677 if ($type eq 'pxref') 4678 { 4679 return &$I('see section %{reference_name}', { 'reference_name' => $name }) if ($is_section); 4680 return &$I('see %{reference_name}', { 'reference_name' => $name }); 4681 } 4682 elsif ($type eq 'xref') 4683 { 4684 return &$I('See section %{reference_name}', { 'reference_name' => $name }) if ($is_section); 4685 return &$I('See %{reference_name}', { 'reference_name' => $name }); 4686 } 4687 elsif ($type eq 'ref') 4688 { 4689 return &$I('%{reference_name}', { 'reference_name' => $name }); 4690 } 4691 } 4692 else 4693 { 4694 $name = &$anchor('', $href, $short_name); 4695 if ($type eq 'pxref') 4696 { 4697 return &$I('see %{reference_name}', { 'reference_name' => $name }); 4698 } 4699 elsif ($type eq 'xref') 4700 { 4701 return &$I('See %{reference_name}', { 'reference_name' => $name }); 4702 } 4703 elsif ($type eq 'ref') 4704 { 4705 return &$I('%{reference_name}', { 'reference_name' => $name }); 4706 } 4707 } 4708 return ''; 4709} 4710 4711sub teletyped_in_stack($) 4712{ 4713 my $stack = shift; 4714 foreach my $element(reverse(@$stack)) 4715 { 4716 if ($complex_format_map->{$element}) 4717 { 4718 if (!$complex_format_map->{$element}->{'pre_style'}) 4719 { 4720 return 1; 4721 } 4722 else 4723 { 4724 return 0; 4725 } 4726 } 4727 } 4728 return 0; 4729} 4730 4731# text after @item in table, vtable and ftable 4732sub t2h_default_table_item($$$$$$) 4733{ 4734 my $text = shift; 4735 my $index_label = shift; 4736 my $format = shift; 4737 my $command = shift; 4738 my $formatted_command = shift; 4739 my $style_stack = shift; 4740 #print STDERR "-> $format (@$style_stack)\n"; 4741 $formatted_command = '' if (!defined($formatted_command) or 4742 exists($special_list_commands{$format}->{$command})); 4743 if (teletyped_in_stack($style_stack)) 4744 { 4745 $text .= '</tt>'; 4746 $formatted_command = '<tt>' . $formatted_command; 4747 } 4748 $text .= "\n" . $index_label if (defined($index_label)); 4749 return '<dt>' . $formatted_command . $text . '</dt>' . "\n"; 4750} 4751 4752# format text on the line following the @item line (in table, vtable and ftable) 4753sub t2h_default_table_line($) 4754{ 4755 my $text = shift; 4756 4757 if ($text =~ /\S/) 4758 { 4759 return '<dd>' . $text . '</dd>' . "\n"; 4760 } 4761 return ''; 4762} 4763 4764# row in multitable 4765sub t2h_default_row($$) 4766{ 4767 my $text = shift; 4768 my $macro = shift; 4769 4770 if ($text =~ /\S/) 4771 { 4772 if ($macro eq 'headitem') 4773 { 4774 return '<thead><tr>' . $text . '</tr></thead>' . "\n"; 4775 } 4776 return '<tr>' . $text . '</tr>' . "\n"; 4777 } 4778 return ''; 4779} 4780 4781# cell in multitable 4782sub t2h_default_cell($$) 4783{ 4784 my $text = shift; 4785 my $row_macro = shift; 4786 4787 if ($row_macro eq 'headitem') 4788 { 4789 return '<th>' . $text . '</th>'; 4790 } 4791 return '<td>' . $text . '</td>'; 4792} 4793 4794# format an item in a list 4795# 4796# argument: 4797# text of the item 4798# format of the list (itemize or enumerate) 4799# command passed as argument to the format 4800# formatted_command leading command formatted, if it is a thing command 4801sub t2h_default_list_item($$$$$$$) 4802{ 4803 my $text = shift; 4804 my $format = shift; 4805 my $command = shift; 4806 my $formatted_command = shift; 4807 my $item_nr = shift; 4808 my $enumerate_style = shift; 4809 my $number = shift; 4810 4811 $formatted_command = '' if (!defined($formatted_command) or 4812 exists($special_list_commands{$format}->{$command})); 4813 if ($text =~ /\S/) 4814 { 4815 return '<li>' . $formatted_command . $text . '</li>'; 4816 } 4817 return ''; 4818} 4819 4820sub t2h_default_table_list($$$$$$) 4821{ 4822 my $format = shift; 4823 my $text = shift; 4824 my $command = shift; 4825 my $formatted_command = shift; 4826 my $item_nr = shift; 4827 my $enumerate_style = shift; 4828 my $number = shift; 4829 $formatted_command = '' if (!defined($formatted_command) or 4830 exists($special_list_commands{$format}->{$command})); 4831 if ($format eq 'itemize') 4832 { 4833 return "<ul>\n" . $text . "</ul>\n" if ($command eq 'bullet'); 4834 return "<ul$TOC_LIST_ATTRIBUTE>\n" . $text . "</ul>\n"; 4835 } 4836} 4837 4838# an html comment 4839sub t2h_default_comment($) 4840{ 4841 my $text = shift; 4842 $text =~ s/--+/-/go; 4843 return '<!-- ' . $text . ' -->' . "\n"; 4844} 4845 4846sub t2h_collect_styles($) 4847{ 4848 my $stack = shift; 4849 my @result = (); 4850 foreach my $style (reverse(@$stack)) 4851 { 4852# last unless (defined($command_type{$style}) and $command_type{$style} eq 'style'); 4853 push @result, $style if (defined($command_type{$style}) and $command_type{$style} eq 'style'); 4854 } 4855 return @result; 4856} 4857 4858sub t2h_get_attribute($;$) 4859{ 4860 my $command = shift; 4861 my $map_ref = shift; 4862 $map_ref = \%style_map if (!defined($map_ref)); 4863 return '' unless (defined($map_ref->{$command})); 4864 if ((ref($map_ref->{$command}) eq 'HASH') 4865 and exists($map_ref->{$command}->{'attribute'})) 4866 { 4867 return $map_ref->{$command}->{'attribute'}; 4868 } 4869 elsif ($map_ref->{$command} !~ /^&/) 4870 { 4871 my $attribute = $map_ref->{$command}; 4872 $attribute =~ s/^\"//; 4873 return $attribute; 4874 } 4875 return ''; 4876} 4877 4878sub t2h_begin_style($$;$) 4879{ 4880 my $command = shift; 4881 my $text = shift; 4882 my $map_ref = shift; 4883 my $attribute = t2h_get_attribute($command,$map_ref); 4884 $attribute = "<$attribute>" if ($attribute ne ''); 4885 return $attribute.$text; 4886} 4887 4888sub t2h_end_style($$;$) 4889{ 4890 my $command = shift; 4891 my $text = shift; 4892 my $map_ref = shift; 4893 my $attribute = t2h_get_attribute($command,$map_ref); 4894 if ($attribute =~ /^(\w+)/) 4895 { 4896 $attribute = $1; 4897 } 4898 $attribute = "</$attribute>" if ($attribute ne ''); 4899 return $text.$attribute; 4900} 4901 4902# a paragraph 4903# arguments: 4904# $text of the paragraph 4905# $align for the alignement 4906# $indent for the indent style (indent or noindent) 4907# The following is usefull if the paragraph is in an itemize. 4908# $paragraph_command is the leading formatting command (like @minus) 4909# $paragraph_command_formatted is the leading formatting command formatted 4910# $paragraph_number is a reference on the number of paragraphs appearing 4911# in the format. The value should be increased if a paragraph is done 4912# $format is the format name (@itemize) 4913sub t2h_default_paragraph($$$$$$$$$$$$) 4914{ 4915 my $text = shift; 4916 my $align = shift; 4917 my $indent = shift; 4918 my $paragraph_command = shift; 4919 my $paragraph_command_formatted = shift; 4920 my $paragraph_number = shift; 4921 my $format = shift; 4922 my $item_nr = shift; 4923 my $enumerate_style = shift; 4924 my $number = shift; 4925 my $command_stack_at_end = shift; 4926 my $command_stack_at_begin = shift; 4927#print STDERR "format: $format\n" if (defined($format)); 4928#print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n"; 4929 $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or 4930 exists($special_list_commands{$format}->{$paragraph_command})); 4931 return '' if ($text =~ /^\s*$/); 4932 foreach my $style(t2h_collect_styles($command_stack_at_begin)) 4933 { 4934 $text = t2h_begin_style($style, $text); 4935 } 4936 foreach my $style(t2h_collect_styles($command_stack_at_end)) 4937 { 4938 $text = t2h_end_style($style, $text); 4939 } 4940 if (defined($paragraph_number) and defined($$paragraph_number)) 4941 { 4942 $$paragraph_number++; 4943 return $text if (($format eq 'itemize' or $format eq 'enumerate') and 4944 ($$paragraph_number == 1)); 4945 } 4946 my $open = '<p>'; 4947 if ($align) 4948 { 4949 $open = "<p align=\"$paragraph_style{$align}\">"; 4950 } 4951 return $open.$text.'</p>'; 4952} 4953 4954# a preformatted region 4955# arguments: 4956# $text of the preformatted region 4957# $pre_style css style 4958# $class identifier for the preformatted region (example, menu-comment) 4959# The following is usefull if the preformatted is in an itemize. 4960# $leading_command is the leading formatting command (like @minus) 4961# $leading_command_formatted is the leading formatting command formatted 4962# $preformatted_number is a reference on the number of preformatteds appearing 4963# in the format. The value should be increased if a preformatted is done 4964sub t2h_default_preformatted($$$$$$$$$$$$) 4965{ 4966 my $text = shift; 4967 my $pre_style = shift; 4968 my $class = shift; 4969 my $leading_command = shift; 4970 my $leading_command_formatted = shift; 4971 my $preformatted_number = shift; 4972 my $format = shift; 4973 my $item_nr = shift; 4974 my $enumerate_style = shift; 4975 my $number = shift; 4976 my $command_stack_at_end = shift; 4977 my $command_stack_at_begin = shift; 4978 4979#print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n"; 4980 return '' if ($text eq ''); 4981 $leading_command_formatted = '' if (!defined($leading_command_formatted) or 4982 exists($special_list_commands{$format}->{$leading_command})); 4983 if (defined($preformatted_number) and defined($$preformatted_number)) 4984 { 4985 $$preformatted_number++; 4986 } 4987 foreach my $style(t2h_collect_styles($command_stack_at_begin)) 4988 { 4989 $text = t2h_begin_style($style, $text, \%style_map_pre); 4990 } 4991 foreach my $style(t2h_collect_styles($command_stack_at_end)) 4992 { 4993 $text = t2h_end_style($style, $text, \%style_map_pre); 4994 } 4995 return "<pre class=\"$class\">".$text."</pre>"; 4996} 4997 4998# This function formats a heading for an element 4999# 5000# argument: 5001# an element. It is a hash reference for a node or a sectionning command. 5002# The interesting keys are: 5003# 'text': the heading text 5004# 'text_nonumber': the heading text without section number 5005# 'node': true if it is a node 5006# 'level': level of the element. 0 for @top, 1 for chapter, heading, 5007# appendix..., 2 for section and so on... 5008# 'tag_level': the sectionning element name, raisesections and lowersections 5009# taken into account 5010sub t2h_default_heading($) 5011{ 5012 my $element = shift; 5013 my $level = 3; 5014 if (!$element->{'node'}) 5015 { 5016 $level = $element->{'level'}; 5017 } 5018 $level = 1 if ($level == 0); 5019 my $text = $element->{'text'}; 5020 return '' if ($text !~ /\S/); 5021 my $class = $element->{'tag_level'}; 5022 $class = 'unnumbered' if ($class eq 'top'); 5023 if (defined($element->{'tocid'}) and $TOC_LINKS) 5024 { 5025 $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text); 5026 } 5027 my $align = ''; 5028 $align = ' align="center"' if ($element->{'tag'} eq 'centerchap'); 5029 return "<h$level class=\"$class\"$align> $text </h$level>\n"; 5030} 5031 5032# formatting of raw regions 5033# if L2H is true another mechanism is used for tex 5034sub t2h_default_raw($$) 5035{ 5036 my $style = shift; 5037 my $text = shift; 5038 if ($style eq 'verbatim' or $style eq 'tex') 5039 { 5040 return "<pre class=\"$style\">" . &$protect_text($text) . '</pre>'; 5041 } 5042 elsif ($style eq 'html') 5043 { 5044 return $text; 5045 } 5046 else 5047 { 5048 warn "$WARN (bug) unknown style $style\n"; 5049 return &$protect_text($text); 5050 } 5051} 5052 5053# raw environment when removing texi (in comments) 5054sub t2h_default_raw_no_texi($$) 5055{ 5056 my $style = shift; 5057 my $text = shift; 5058 return $text; 5059} 5060 5061# This function formats a footnote reference and the footnote text associated 5062# with a given footnote. 5063# The footnote reference is the text appearing in the main document pointing 5064# to the footnote text. 5065# 5066# arguments: 5067# absolute number of the footnote (in the document) 5068# relative number of the footnote (in the page) 5069# identifier for the footnote 5070# identifier for the footnote reference in the main document 5071# main document file 5072# footnote text file 5073# array with the footnote text lines 5074# the state. See menu entry. 5075# 5076# returns: 5077# reference on an array containing the footnote text lines which should 5078# have been updated 5079# the text for the reference pointing on the footnote text 5080sub t2h_default_foot_line_and_ref($$$$$$$) 5081{ 5082 my $number_in_doc = shift; 5083 my $number_in_page = shift; 5084 my $footnote_id = shift; 5085 my $place_id = shift; 5086 my $document_file = shift; 5087 my $footnote_file = shift; 5088 my $lines = shift; 5089 my $state = shift; 5090 5091 unshift (@$lines, '<h3>' . 5092 &$anchor($footnote_id, $document_file . "#$place_id", 5093 "($number_in_doc)") 5094 . "</h3>\n"); 5095 return ($lines, &$anchor($place_id, $footnote_file . "#$footnote_id", 5096 "($number_in_doc)")); 5097} 5098 5099# formats a group of footnotes. 5100# 5101# argument: 5102# array reference on the footnotes texts lines 5103# 5104# returns an array reference on the group of footnotes lines 5105sub t2h_default_foot_section($) 5106{ 5107 my $lines = shift; 5108 unshift (@$lines, "<div class=\"footnote\">\n" ,"$DEFAULT_RULE\n", "<h3>" . &$I('Footnotes') . "</h3>\n"); 5109 push (@$lines, "</div>\n"); 5110 return $lines; 5111} 5112 5113sub t2h_default_image_files($$) 5114{ 5115 my $base = shift; 5116 my $extension = shift; 5117 my @files = (); 5118 return @files if (!defined($base) or ($base eq '')); 5119 push @files,"$base.$extension" if (defined($extension) and ($extension ne '')); 5120 foreach my $ext (@IMAGE_EXTENSIONS) 5121 { 5122 push @files, "$base.$ext"; 5123 } 5124 return @files; 5125} 5126 5127# format an image 5128# 5129# arguments: 5130# image file name with path 5131# image basename 5132# a boolean true if we are in a preformatted format 5133# image file name without path 5134# alt text 5135# width 5136# height 5137# raw alt 5138# extension 5139# path to working dir 5140# path to file relative from working dir 5141sub t2h_default_image($$$$$$$$$$$) 5142{ 5143 my $file = shift; 5144 my $base = shift; 5145 my $preformatted = shift; 5146 my $file_name = shift; 5147 my $alt = shift; 5148 my $width = shift; 5149 my $height = shift; 5150 my $raw_alt = shift; 5151 my $extension = shift; 5152 my $working_dir = shift; 5153 my $file_path = shift; 5154 5155 if (!defined($file_path) or $file_path eq '') 5156 { 5157 if (defined($extension) and $extension ne '') 5158 { 5159 $file = "$base.$extension"; 5160 } 5161 else 5162 { 5163 $file = "$base.jpg"; 5164 } 5165 main::echo_warn ("no image file for $base, (using $file)"); 5166 } 5167 $alt = &$protect_text($base) if (!defined($alt) or ($alt eq '')); 5168 return "[ $alt ]" if ($preformatted); 5169 # it is possible that $file_name is more correct as it allows the user 5170 # to chose the relative path. 5171 $file = &$protect_text($file); 5172 return "<img src=\"$file\" alt=\"$alt\">"; 5173} 5174 5175# address put in footer describing when was generated and who did the manual 5176sub t2h_default_address($$) 5177{ 5178 my $user = shift; 5179 my $date = shift; 5180 $user = '' if (!defined($user)); 5181 $date = '' if (!defined($date)); 5182 if (($user ne '') and ($date ne '')) 5183 { 5184 return &$I('by @emph{%{user}} on @emph{%{date}}', { 'user' => $user, 5185 'date' => $date }); 5186 } 5187 elsif ($user ne '') 5188 { 5189 return &$I('by @emph{%{user}}', { 'user' => $user }); 5190 } 5191 elsif ($date ne '') 5192 { 5193 return &$I('on @emph{%{date}}', { 'date' => $date }); 5194 } 5195 return ''; 5196} 5197 5198# format a target in the main document for an index entry. 5199# 5200# arguments: 5201# target identifier 5202# boolean true if in preformatted format 5203# FIXME document the remaining 5204sub t2h_default_index_entry_label($$) 5205{ 5206 my $identifier = shift; 5207 my $preformatted = shift; 5208 5209 return '' if (!defined($identifier) or ($identifier !~ /\S/)); 5210 my $label = &$anchor($identifier); 5211 return $label . "\n" if (!$preformatted); 5212 return $label; 5213} 5214 5215# process definition commands line @deffn for example 5216sub t2h_default_def_line($$$$$) 5217{ 5218 my $category = shift; 5219 my $name = shift; 5220 my $type = shift; 5221 my $arguments = shift; 5222 my $index_label = shift; 5223 $index_label = '' if (!defined($index_label)); 5224 $category = '' if (!defined($category) or ($category =~ /^\s*$/)); 5225 $name = '' if (!defined($name) or ($name =~ /^\s*$/)); 5226 $type = '' if (!defined($type) or $type =~ /^\s*$/); 5227 if (!defined($arguments) or $arguments =~ /^\s*$/) 5228 { 5229 $arguments = ''; 5230 } 5231 else 5232 { 5233 chomp ($arguments); 5234 $arguments = '<i>' . $arguments . '</i>'; 5235 } 5236 my $type_name = ''; 5237 $type_name = " $type" if ($type ne ''); 5238 $type_name .= ' <b>' . $name . '</b>' if ($name ne ''); 5239 $type_name .= $arguments . "\n"; 5240 if (! $DEF_TABLE) 5241 { 5242 return '<dt>'. '<u>' . $category . ':</u>' . $type_name . $index_label . "</dt>\n"; 5243 } 5244 else 5245 { 5246 5247 return "<tr>\n<td align=\"left\">" . $type_name . 5248 "</td>\n<td align=\"right\">" . $category . $index_label . "</td>\n" . "</tr>\n"; 5249 } 5250} 5251 5252# process definition commands line @deffn for example while removing texi 5253# commands 5254sub t2h_default_def_line_no_texi($$$$$) 5255{ 5256 my $category = shift; 5257 my $name = shift; 5258 my $type = shift; 5259 my $arguments = shift; 5260 $name = '' if (!defined($name) or ($name =~ /^\s*$/)); 5261 $type = '' if (!defined($type) or $type =~ /^\s*$/); 5262 if (!defined($arguments) or $arguments =~ /^\s*$/) 5263 { 5264 $arguments = ''; 5265 } 5266 my $type_name = ''; 5267 $type_name = " $type" if ($type ne ''); 5268 $type_name .= ' ' . $name if ($name ne ''); 5269 $type_name .= $arguments; 5270 if (! $DEF_TABLE) 5271 { 5272 return $category . ':' . $type_name . "\n"; 5273 } 5274 else 5275 { 5276 5277 return $type_name . " " . $category . "\n"; 5278 } 5279} 5280 5281# a cartouche 5282sub t2h_default_cartouche($$) 5283{ 5284 my $text = shift; 5285 5286 if ($text =~ /\S/) 5287 { 5288 return "<table class=\"cartouche\" border=\"1\"><tr><td>\n" . $text . "</td></tr></table>\n"; 5289 } 5290 return ''; 5291} 5292 5293# key: 5294# origin_href: 5295# entry: 5296# texi entry: 5297# element_href: 5298# element_text: 5299sub t2h_default_index_summary_file_entry ($$$$$$$$) 5300{ 5301 my $index_name = shift; 5302 my $key = shift; 5303 my $origin_href = shift; 5304 my $entry = shift; 5305 my $texi_entry = shift; 5306 my $element_href = shift; 5307 my $element_text = shift; 5308 my $is_printed = shift; 5309 print IDXFILE "key: $key\n origin_href: $origin_href\n entry: $entry\n" 5310 . " texi_entry: $texi_entry\n" 5311 . " element_href: $element_href\n element_text: $element_text\n"; 5312} 5313 5314sub t2h_default_index_summary_file_begin($$) 5315{ 5316 my $name = shift; 5317 my $is_printed = shift; 5318 open(IDXFILE, ">$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx") 5319 || die "Can't open >$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx for writing: $!\n"; 5320} 5321 5322sub t2h_default_index_summary_file_end($$) 5323{ 5324 my $name = shift; 5325 my $is_printed = shift; 5326 close (IDXFILE); 5327} 5328 5329sub t2h_default_sp($$) 5330{ 5331 my $number = shift; 5332 my $preformatted = shift; 5333 return "<br>\n" x $number if (!$preformatted); 5334 return "\n" x $number; 5335} 5336 5337sub t2h_default_acronym_like($$$$$$) 5338{ 5339 my $command = shift; 5340 my $acronym_texi = shift; 5341 my $acronym_text = shift; 5342 my $with_explanation = shift; 5343 my $explanation_lines = shift; 5344 my $explanation_text = shift; 5345 my $explanation_simply_formatted = shift; 5346 5347 my $attribute = $command; 5348 my $opening = "<$attribute>"; 5349 if (defined($explanation_simply_formatted)) 5350 { 5351 $opening = "<$attribute title=\"$explanation_simply_formatted\">"; 5352 } 5353 if ($with_explanation) 5354 { 5355 return &$I('%{acronym_like} (%{explanation})', {'acronym_like' => $opening . $acronym_text . "</$attribute>", 'explanation' => $explanation_text}) 5356 } 5357 else 5358 { 5359 return $opening . $acronym_text . "</$attribute>"; 5360 } 5361} 5362 5363sub t2h_default_quotation_prepend_text($) 5364{ 5365 my $text = shift; 5366 return undef if (!defined($text) or $text =~ /^$/); 5367# FIXME if there is a @ protecting the end of line the result is 5368# @b{some text @:} 5369# It is likely not to be what was intended 5370 chomp($text); 5371 return &$I('@b{%{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1}); 5372} 5373 5374sub t2h_default_quotation($$$) 5375{ 5376 my $text = shift; 5377 my $argument_text = shift; 5378 my $argument_text_texi = shift; 5379# my $argument_style_texi = shift; 5380# my $argument_style_id = shift; 5381# if (defined($argument_text)) 5382# { 5383# return '<blockquote>' . &$I('%{style}:%{quotation}', 5384# {'style' => $argument_text, 'quotation' => $text}) . '</blockquote>' ; 5385# } 5386 return '<blockquote>' . $text . "</blockquote>\n"; 5387} 5388 5389# format the text within a paragraph style format, 5390# 5391# argument: 5392# format name 5393# text within the format 5394sub t2h_default_paragraph_style_command($$) 5395{ 5396 my $format = shift; 5397 my $text = shift; 5398 return $text; 5399} 5400 5401# format a whole index 5402# 5403# argument: 5404# index text 5405# index name 5406sub t2h_default_print_index($$) 5407{ 5408 my $text = shift; 5409 my $name = shift; 5410 return "<table border=\"0\" class=\"index-$name\">\n" . 5411 "<tr><td></td><th align=\"left\">" . &$I('Index Entry') . "</th><th align=\"left\"> " . &$I('Section') . "</th></tr>\n" 5412 . "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n" . $text . 5413 "</table>\n"; 5414} 5415 5416# format a letter entry in an index page. The letter entry contains 5417# the index entries for the words beginning with that letter. It is 5418# a target for links pointing from the summary of the index. 5419# 5420# arguments: 5421# the letter 5422# identifier for the letter entry. This should be used to make the target 5423# identifier 5424# text of the index entries 5425sub t2h_default_index_letter($$$) 5426{ 5427 my $letter = shift; 5428 my $id = shift; 5429 my $text = shift; 5430 return '<tr><th>' . &$anchor($id,'',&$protect_text($letter)) . 5431 "</th><td></td><td></td></tr>\n" . $text . 5432 "<tr><td colspan=\"3\"> $DEFAULT_RULE</td></tr>\n"; 5433} 5434 5435# format an index entry (in a letter entry). 5436# 5437# arguments: 5438# href to the main text, linking to the place where the index entry appears 5439# entry text 5440# href to the main text, linking to the section or node where the index 5441# entry appears 5442# section or node heading 5443sub t2h_default_index_entry($$$$) 5444{ 5445 my $text_href = shift; 5446 my $entry = shift; 5447 my $element_href = shift; 5448 my $element_text = shift; 5449 5450 return '<tr><td></td><td valign="top">' . &$anchor('', $text_href, $entry) 5451 . '</td><td valign="top">' . &$anchor('', $element_href, $element_text) 5452 . "</td></tr>\n"; 5453} 5454 5455 5456sub t2h_default_copying_comment($) 5457{ 5458 my $copying_lines = shift; 5459 my $text = &$comment(main::remove_texi(@$copying_lines)); 5460 return $text; 5461} 5462# format a letter appearing in a summary for an index. The letter links to 5463# the place where the index elements beginning with this letter are (called 5464# a letter entry). 5465# 5466# arguments: 5467# letter 5468# file where the target letter entry is 5469# identifier for the target letter entry 5470sub t2h_default_summary_letter($$$) 5471{ 5472 my $letter = shift; 5473 my $file = shift; 5474 my $identifier = shift; 5475 return &$anchor('', $file . '#' . $identifier, '<b>' . &$protect_text($letter) . '</b>', 'class="summary-letter"'); 5476} 5477 5478# format an index summary. This is a list of letters linking to the letter 5479# entries. 5480# 5481# arguments: 5482# array reference containing the formatted alphabetical letters 5483# array reference containing the formatted non lphabetical letters 5484sub t2h_default_index_summary($$) 5485{ 5486 my $alpha = shift; 5487 my $nonalpha = shift; 5488 my $join = ''; 5489 my $nonalpha_text = ''; 5490 my $alpha_text = ''; 5491 $join = " \n<br>\n" if (@$nonalpha and @$alpha); 5492 if (@$nonalpha) 5493 { 5494 $nonalpha_text = join("\n \n", @$nonalpha) . "\n"; 5495 } 5496 if (@$alpha) 5497 { 5498 $alpha_text = join("\n \n", @$alpha) . "\n \n"; 5499 } 5500 return "<table><tr><th valign=\"top\">" . &$I('Jump to') .": </th><td>" . 5501 $nonalpha_text . $join . $alpha_text . "</td></tr></table>\n"; 5502} 5503 5504# return the heading with number texinfo text 5505# also called for nodes. 5506sub t2h_default_heading_texi($$$) 5507{ 5508 my $tag = shift; 5509 my $texi = shift; 5510 my $number = shift; 5511 $texi =~ s/\s*$//; 5512 $texi =~ s/^\s*//; 5513 return "$number $texi" if ($NUMBER_SECTIONS and defined($number) and ($number !~ /^\s*$/)) ; 5514 return $texi; 5515} 5516 5517# return the heading texinfo text for split index sections 5518sub t2h_default_index_element_heading_texi($$$) 5519{ # FIXME i18n 5520 my $heading_texi = shift; 5521 my $tag = shift; 5522 my $texi = shift; 5523 my $number = shift; 5524 my $first_letter = shift; 5525 my $last_letter = shift; 5526 return "$heading_texi: $first_letter -- $last_letter" if ($last_letter ne $first_letter); 5527 return "$heading_texi: $first_letter"; 5528} 5529 55301; 5531 5532require "$ENV{T2H_HOME}/texi2html.init" 5533 if ($0 =~ /\.pl$/ && 5534 -e "$ENV{T2H_HOME}/texi2html.init" && -r "$ENV{T2H_HOME}/texi2html.init"); 5535 5536my $translation_file = 'translations.pl'; # file containing all the translations 5537my $T2H_OBSOLETE_STRINGS; 5538 5539# leave this within comments, and keep the require statement 5540# This way, you can directly run texi2html.pl, 5541# if $ENV{T2H_HOME}/translations.pl exists. 5542# 5543# @T2H_TRANSLATIONS_FILE@ 5544$LANGUAGES->{'de'} = { 5545 ' The buttons in the navigation panels have the following meaning:' => '', 5546 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', 5547 ' Up ' => '', 5548 '%{acronym_like} (%{explanation})' => '', 5549 '%{month}, %{day} %{year}' => '', 5550 '%{name} of %{class}' => '', 5551 '%{name} on %{class}' => '', 5552 '%{node_file_href}' => '', 5553 '%{node_file_href} @cite{%{book}}' => '', 5554 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5555 '%{reference_name}' => '', 5556 '%{style} %{number}' => '', 5557 '%{style}: %{caption_first_line}' => '', 5558 '%{style}: %{shortcaption_first_line}' => '', 5559 '@b{%{quotation_arg}:} ' => '', 5560 '@cite{%{book}}' => '', 5561 'About' => '', 5562 'About (help)' => '', 5563 'About This Document' => '@"Uber dieses Dokument', 5564 'April' => 'April', 5565 'August' => 'August', 5566 'Back' => '', 5567 'Beginning of this chapter or previous chapter' => '', 5568 'Button' => '', 5569 'Contents' => '', 5570 'Cover (top) of document' => '', 5571 'Current Position' => '', 5572 'Current section' => '', 5573 'December' => 'Dezember', 5574 'FastBack' => '', 5575 'FastForward' => '', 5576 'February' => 'Februar', 5577 'First' => '', 5578 'First section in reading order' => '', 5579 'Following' => '', 5580 'Following node' => '', 5581 'Footnotes' => 'Fu@ss{}noten', 5582 'Forward' => '', 5583 'From 1.2.3 go to' => '', 5584 'Go to' => '', 5585 'Index' => 'Index', 5586 'Index Entry' => '', 5587 'January' => 'Januar', 5588 'July' => 'Juli', 5589 'Jump to' => '', 5590 'June' => 'Juni', 5591 'Last' => '', 5592 'Last section in reading order' => '', 5593 'March' => 'M@"arz', 5594 'May' => 'Mai', 5595 'Menu:' => '', 5596 'Name' => '', 5597 'Next' => '', 5598 'Next chapter' => '', 5599 'Next node' => '', 5600 'Next section in reading order' => '', 5601 'Next section on same level' => '', 5602 'Node following in node reading order' => '', 5603 'Node up' => '', 5604 'NodeNext' => '', 5605 'NodePrev' => '', 5606 'NodeUp' => '', 5607 'November' => 'November', 5608 'October' => 'Oktober', 5609 'Overview' => '', 5610 'Overview:' => '', 5611 'Prev' => '', 5612 'Previous node' => '', 5613 'Previous section in reading order' => '', 5614 'Previous section on same level' => '', 5615 'Section' => '', 5616 'Section One' => '', 5617 'See %{node_file_href}' => '', 5618 'See %{node_file_href} @cite{%{book}}' => '', 5619 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5620 'See %{reference_name}' => '', 5621 'See @cite{%{book}}' => '', 5622 'See section %{reference_name}' => '', 5623 'See section `%{section}\' in @cite{%{book}}' => '', 5624 'September' => 'September', 5625 'Short Table of Contents' => 'Kurzes Inhaltsverzeichniss', 5626 'Short table of contents' => '', 5627 'Subsection One-Four' => '', 5628 'Subsection One-One' => '', 5629 'Subsection One-Three' => '', 5630 'Subsection One-Two' => '', 5631 'Subsubsection One-Two-Four' => '', 5632 'Subsubsection One-Two-One' => '', 5633 'Subsubsection One-Two-Three' => '', 5634 'Subsubsection One-Two-Two' => '', 5635 'T2H_today' => '', 5636 'Table of Contents' => 'Inhaltsverzeichniss', 5637 'Table of contents' => '', 5638 'The node you are looking for is at %{href}.' => '', 5639 'This' => '', 5640 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5641 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5642 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '', 5643 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5644 'Top' => '', 5645 'Untitled Document' => '', 5646 'Up' => '', 5647 'Up node' => '', 5648 'Up section' => '', 5649 'by @emph{%{user}}' => '', 5650 'by @emph{%{user}} on @emph{%{date}}' => '', 5651 'current' => '', 5652 'on @emph{%{date}}' => '', 5653 'section `%{section}\' in @cite{%{book}}' => '', 5654 'see %{node_file_href}' => '', 5655 'see %{node_file_href} @cite{%{book}}' => '', 5656 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5657 'see %{reference_name}' => '', 5658 'see @cite{%{book}}' => '', 5659 'see section %{reference_name}' => '', 5660 'see section `%{section}\' in @cite{%{book}}' => '', 5661 'unknown' => '' 5662 }; 5663 5664$T2H_OBSOLETE_STRINGS->{'de'} = { 5665 'See' => 'Siehe', 5666 'section' => 'Abschnitt', 5667 'see' => 'siehe' 5668 }; 5669 5670 5671$LANGUAGES->{'en'} = { 5672 ' The buttons in the navigation panels have the following meaning:' => '', 5673 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', 5674 ' Up ' => '', 5675 '%{acronym_like} (%{explanation})' => '', 5676 '%{month}, %{day} %{year}' => '', 5677 '%{name} of %{class}' => '', 5678 '%{name} on %{class}' => '', 5679 '%{node_file_href}' => '', 5680 '%{node_file_href} @cite{%{book}}' => '', 5681 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5682 '%{reference_name}' => '', 5683 '%{style} %{number}' => '', 5684 '%{style}: %{caption_first_line}' => '', 5685 '%{style}: %{shortcaption_first_line}' => '', 5686 '@b{%{quotation_arg}:} ' => '', 5687 '@cite{%{book}}' => '', 5688 'About' => '', 5689 'About (help)' => '', 5690 'About This Document' => '', 5691 'April' => '', 5692 'August' => '', 5693 'Back' => '', 5694 'Beginning of this chapter or previous chapter' => '', 5695 'Button' => '', 5696 'Contents' => '', 5697 'Cover (top) of document' => '', 5698 'Current Position' => '', 5699 'Current section' => '', 5700 'December' => '', 5701 'FastBack' => '', 5702 'FastForward' => '', 5703 'February' => '', 5704 'First' => '', 5705 'First section in reading order' => '', 5706 'Following' => '', 5707 'Following node' => '', 5708 'Footnotes' => '', 5709 'Forward' => '', 5710 'From 1.2.3 go to' => '', 5711 'Go to' => '', 5712 'Index' => '', 5713 'Index Entry' => '', 5714 'January' => '', 5715 'July' => '', 5716 'Jump to' => '', 5717 'June' => '', 5718 'Last' => '', 5719 'Last section in reading order' => '', 5720 'March' => '', 5721 'May' => '', 5722 'Menu:' => '', 5723 'Name' => '', 5724 'Next' => '', 5725 'Next chapter' => '', 5726 'Next node' => '', 5727 'Next section in reading order' => '', 5728 'Next section on same level' => '', 5729 'Node following in node reading order' => '', 5730 'Node up' => '', 5731 'NodeNext' => '', 5732 'NodePrev' => '', 5733 'NodeUp' => '', 5734 'November' => '', 5735 'October' => '', 5736 'Overview' => '', 5737 'Overview:' => '', 5738 'Prev' => '', 5739 'Previous node' => '', 5740 'Previous section in reading order' => '', 5741 'Previous section on same level' => '', 5742 'Section' => '', 5743 'Section One' => '', 5744 'See %{node_file_href}' => '', 5745 'See %{node_file_href} @cite{%{book}}' => '', 5746 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5747 'See %{reference_name}' => '', 5748 'See @cite{%{book}}' => '', 5749 'See section %{reference_name}' => '', 5750 'See section `%{section}\' in @cite{%{book}}' => '', 5751 'September' => '', 5752 'Short Table of Contents' => '', 5753 'Short table of contents' => '', 5754 'Subsection One-Four' => '', 5755 'Subsection One-One' => '', 5756 'Subsection One-Three' => '', 5757 'Subsection One-Two' => '', 5758 'Subsubsection One-Two-Four' => '', 5759 'Subsubsection One-Two-One' => '', 5760 'Subsubsection One-Two-Three' => '', 5761 'Subsubsection One-Two-Two' => '', 5762 'T2H_today' => '%s, %d %d', 5763 'Table of Contents' => '', 5764 'Table of contents' => '', 5765 'The node you are looking for is at %{href}.' => '', 5766 'This' => '', 5767 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5768 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5769 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '', 5770 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5771 'Top' => '', 5772 'Untitled Document' => '', 5773 'Up' => '', 5774 'Up node' => '', 5775 'Up section' => '', 5776 'by @emph{%{user}}' => '', 5777 'by @emph{%{user}} on @emph{%{date}}' => '', 5778 'current' => '', 5779 'on @emph{%{date}}' => '', 5780 'section `%{section}\' in @cite{%{book}}' => '', 5781 'see %{node_file_href}' => '', 5782 'see %{node_file_href} @cite{%{book}}' => '', 5783 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5784 'see %{reference_name}' => '', 5785 'see @cite{%{book}}' => '', 5786 'see section %{reference_name}' => '', 5787 'see section `%{section}\' in @cite{%{book}}' => '', 5788 'unknown' => '' 5789 }; 5790 5791$T2H_OBSOLETE_STRINGS->{'en'} = {}; 5792 5793 5794$LANGUAGES->{'es'} = { 5795 ' The buttons in the navigation panels have the following meaning:' => '', 5796 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', 5797 ' Up ' => '', 5798 '%{acronym_like} (%{explanation})' => '', 5799 '%{month}, %{day} %{year}' => '', 5800 '%{name} of %{class}' => '', 5801 '%{name} on %{class}' => '', 5802 '%{node_file_href}' => '', 5803 '%{node_file_href} @cite{%{book}}' => '', 5804 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5805 '%{reference_name}' => '', 5806 '%{style} %{number}' => '', 5807 '%{style}: %{caption_first_line}' => '', 5808 '%{style}: %{shortcaption_first_line}' => '', 5809 '@b{%{quotation_arg}:} ' => '', 5810 '@cite{%{book}}' => '', 5811 'About' => '', 5812 'About (help)' => '', 5813 'About This Document' => '', 5814 'April' => 'abril', 5815 'August' => 'agosto', 5816 'Back' => '', 5817 'Beginning of this chapter or previous chapter' => '', 5818 'Button' => '', 5819 'Contents' => '', 5820 'Cover (top) of document' => '', 5821 'Current Position' => '', 5822 'Current section' => '', 5823 'December' => 'diciembre', 5824 'FastBack' => '', 5825 'FastForward' => '', 5826 'February' => 'febrero', 5827 'First' => '', 5828 'First section in reading order' => '', 5829 'Following' => '', 5830 'Following node' => '', 5831 'Footnotes' => '', 5832 'Forward' => '', 5833 'From 1.2.3 go to' => '', 5834 'Go to' => '', 5835 'Index' => 'Index', 5836 'Index Entry' => '', 5837 'January' => 'enero', 5838 'July' => 'julio', 5839 'Jump to' => '', 5840 'June' => 'junio', 5841 'Last' => '', 5842 'Last section in reading order' => '', 5843 'March' => 'marzo', 5844 'May' => 'mayo', 5845 'Menu:' => '', 5846 'Name' => '', 5847 'Next' => '', 5848 'Next chapter' => '', 5849 'Next node' => '', 5850 'Next section in reading order' => '', 5851 'Next section on same level' => '', 5852 'Node following in node reading order' => '', 5853 'Node up' => '', 5854 'NodeNext' => '', 5855 'NodePrev' => '', 5856 'NodeUp' => '', 5857 'November' => 'noviembre', 5858 'October' => 'octubre', 5859 'Overview' => '', 5860 'Overview:' => '', 5861 'Prev' => '', 5862 'Previous node' => '', 5863 'Previous section in reading order' => '', 5864 'Previous section on same level' => '', 5865 'Section' => '', 5866 'Section One' => '', 5867 'See %{node_file_href}' => '', 5868 'See %{node_file_href} @cite{%{book}}' => '', 5869 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5870 'See %{reference_name}' => '', 5871 'See @cite{%{book}}' => '', 5872 'See section %{reference_name}' => '', 5873 'See section `%{section}\' in @cite{%{book}}' => '', 5874 'September' => 'septiembre', 5875 'Short Table of Contents' => 'Resumen del Contenido', 5876 'Short table of contents' => '', 5877 'Subsection One-Four' => '', 5878 'Subsection One-One' => '', 5879 'Subsection One-Three' => '', 5880 'Subsection One-Two' => '', 5881 'Subsubsection One-Two-Four' => '', 5882 'Subsubsection One-Two-One' => '', 5883 'Subsubsection One-Two-Three' => '', 5884 'Subsubsection One-Two-Two' => '', 5885 'T2H_today' => '', 5886 'Table of Contents' => '@\'{@dotless{I}}ndice General', 5887 'Table of contents' => '', 5888 'The node you are looking for is at %{href}.' => '', 5889 'This' => '', 5890 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5891 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5892 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '', 5893 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 5894 'Top' => '', 5895 'Untitled Document' => '', 5896 'Up' => '', 5897 'Up node' => '', 5898 'Up section' => '', 5899 'by @emph{%{user}}' => '', 5900 'by @emph{%{user}} on @emph{%{date}}' => '', 5901 'current' => '', 5902 'on @emph{%{date}}' => '', 5903 'section `%{section}\' in @cite{%{book}}' => '', 5904 'see %{node_file_href}' => '', 5905 'see %{node_file_href} @cite{%{book}}' => '', 5906 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 5907 'see %{reference_name}' => '', 5908 'see @cite{%{book}}' => '', 5909 'see section %{reference_name}' => '', 5910 'see section `%{section}\' in @cite{%{book}}' => '', 5911 'unknown' => '' 5912 }; 5913 5914$T2H_OBSOLETE_STRINGS->{'es'} = { 5915 'See' => 'V@\'ease', 5916 'section' => 'secci@\'on', 5917 'see' => 'v@\'ase' 5918 }; 5919 5920 5921$LANGUAGES->{'fr'} = { 5922 ' The buttons in the navigation panels have the following meaning:' => ' Les boutons de navigation ont la signification suivante :', 5923 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' Dans cet exemple on est @`a @strong{ Sous section un-deux-trois } dans un document dont la structure est :', 5924 ' Up ' => 'Plus haut', 5925 '%{acronym_like} (%{explanation})' => '', 5926 '%{month}, %{day} %{year}' => 'le %{day} %{month} %{year}', 5927 '%{name} of %{class}' => '%{name} de %{class}', 5928 '%{name} on %{class}' => '%{name} de %{class}', 5929 '%{node_file_href}' => '', 5930 '%{node_file_href} @cite{%{book}}' => '', 5931 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} section `%{section}\' dans @cite{%{book}}', 5932 '%{reference_name}' => '', 5933 '%{style} %{number}' => '', 5934 '%{style}: %{caption_first_line}' => '', 5935 '%{style}: %{shortcaption_first_line}' => '', 5936 '@b{%{quotation_arg}:} ' => '', 5937 '@cite{%{book}}' => '', 5938 'About' => 'A propos', 5939 'About (help)' => 'A propos (page d\'aide)', 5940 'About This Document' => 'A propos de ce document', 5941 'April' => 'Avril', 5942 'August' => 'Ao@^ut', 5943 'Back' => 'Retour', 5944 'Beginning of this chapter or previous chapter' => 'D@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent', 5945 'Button' => 'Bouton', 5946 'Contents' => 'Table des mati@`eres', 5947 'Cover (top) of document' => 'Couverture (top) du document', 5948 'Current Position' => 'Position', 5949 'Current section' => 'Section actuelle', 5950 'December' => 'D@\'ecembre', 5951 'FastBack' => 'RetourRapide', 5952 'FastForward' => 'AvanceRapide', 5953 'February' => 'F@\'evrier', 5954 'First' => 'Premier', 5955 'First section in reading order' => 'Premi@`e section dans l\'ordre de lecture', 5956 'Following' => 'Suivant', 5957 'Following node' => 'N@oe{}ud suivant', 5958 'Footnotes' => 'Notes de bas de page', 5959 'Forward' => 'Avant', 5960 'From 1.2.3 go to' => 'Depuis 1.2.3 aller @`a', 5961 'Go to' => 'Aller @`a', 5962 'Index' => 'Index', 5963 'Index Entry' => 'Entr@\'ee d\'index', 5964 'January' => 'Janvier', 5965 'July' => 'Juillet', 5966 'Jump to' => 'Aller @`a', 5967 'June' => 'Juin', 5968 'Last' => 'Dernier', 5969 'Last section in reading order' => 'Derni@`ere section dans l\'ordre de lecture', 5970 'March' => 'Mars', 5971 'May' => 'Mai', 5972 'Menu:' => 'Menu@ :', 5973 'Name' => 'Nom', 5974 'Next' => 'Suivant', 5975 'Next chapter' => 'Chapitre suivant', 5976 'Next node' => 'N@oe{}ud suivant', 5977 'Next section in reading order' => 'Section suivante dans l\'ordre de lecture', 5978 'Next section on same level' => 'Section suivante au m@^eme niveau', 5979 'Node following in node reading order' => 'N@oe{}ud suivant dans l\'ordre de lecture', 5980 'Node up' => 'N@oe{}ud au dessus', 5981 'NodeNext' => 'N@oe{}udSuivant', 5982 'NodePrev' => 'N@oe{}udPr@\'ec@\'edent', 5983 'NodeUp' => 'N@oe{}udMonter', 5984 'November' => 'Novembre', 5985 'October' => 'Octobre', 5986 'Overview' => 'Vue d\'ensemble', 5987 'Overview:' => 'Vue d\'ensemble@ :', 5988 'Prev' => 'Pr@\'ec@\'edent', 5989 'Previous node' => 'N@oe{}ud pr@\'ec@\'edent', 5990 'Previous section in reading order' => 'Section pr@\'ec@\'edente dans l\'ordre de lecture', 5991 'Previous section on same level' => 'Section pr@\'ec@\'edente au m@^eme niveau', 5992 'Section' => '', 5993 'Section One' => 'Section un', 5994 'See %{node_file_href}' => 'Voir %{node_file_href}', 5995 'See %{node_file_href} @cite{%{book}}' => 'Voir %{node_file_href} @cite{%{book}}', 5996 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Voir %{node_file_href} section `%{section}\' dans @cite{%{book}}', 5997 'See %{reference_name}' => 'Voir %{reference_name}', 5998 'See @cite{%{book}}' => 'Voir @cite{%{book}}', 5999 'See section %{reference_name}' => 'Voir la section %{reference_name}', 6000 'See section `%{section}\' in @cite{%{book}}' => 'Voir la section `%{section}\' dans @cite{%{book}}', 6001 'September' => 'Septembre', 6002 'Short Table of Contents' => 'R@\'esum@\'e du contenu', 6003 'Short table of contents' => 'R@\'esum@\'e du contenu', 6004 'Subsection One-Four' => 'Sous section un-quatre', 6005 'Subsection One-One' => 'Sous section un-un', 6006 'Subsection One-Three' => 'Sous section un-trois', 6007 'Subsection One-Two' => 'Sous section un-deux', 6008 'Subsubsection One-Two-Four' => 'Sous sous section un-deux-quatre', 6009 'Subsubsection One-Two-One' => 'Sous sous section un-deux-un', 6010 'Subsubsection One-Two-Three' => 'Sous sous section un-deux-trois', 6011 'Subsubsection One-Two-Two' => 'Sous sous section un-deux-deux', 6012 'T2H_today' => 'le %2$d %1$s %3$d', 6013 'Table of Contents' => 'Table des mati@`eres', 6014 'Table of contents' => 'Table des mati@`eres', 6015 'The node you are looking for is at %{href}.' => 'Le n@oe{}ud que vous recherchez est ici@ : %{href}.', 6016 'This' => 'Ici', 6017 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.', 6018 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.', 6019 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}', 6020 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e en utilisant @uref{%{program_homepage}, @emph{%{program}}}.', 6021 'Top' => '', 6022 'Untitled Document' => 'Document sans titre', 6023 'Up' => 'Monter', 6024 'Up node' => 'N@oe{}ud au dessus', 6025 'Up section' => 'Section sup@\'erieure', 6026 'by @emph{%{user}}' => 'par @emph{%{user}}', 6027 'by @emph{%{user}} on @emph{%{date}}' => 'par @emph{%{user}} @emph{%{date}}', 6028 'current' => 'courante', 6029 'on @emph{%{date}}' => '@emph{%{date}}', 6030 'section `%{section}\' in @cite{%{book}}' => 'section `%{section}\' dans @cite{%{book}}', 6031 'see %{node_file_href}' => 'voir %{node_file_href}', 6032 'see %{node_file_href} @cite{%{book}}' => 'voir %{node_file_href} @cite{%{book}}', 6033 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'voir %{node_file_href} section `%{section}\' dans @cite{%{book}}', 6034 'see %{reference_name}' => 'voir %{reference_name}', 6035 'see @cite{%{book}}' => 'voir @cite{%{book}}', 6036 'see section %{reference_name}' => 'voir la section %{reference_name}', 6037 'see section `%{section}\' in @cite{%{book}}' => 'voir la section `%{section}\' dans @cite{{book}}', 6038 'unknown' => 'inconnu' 6039 }; 6040 6041$T2H_OBSOLETE_STRINGS->{'fr'} = { 6042 ' This document was generated %{who_and_when_generated} using %{program_homepage_href}.' => ' Ce document a été généré %{who_and_when_generated} en utilisant %{program_homepage_href}.', 6043 ' where the <strong> Example </strong> assumes that the current position is at <strong> Subsubsection One-Two-Three </strong> of a document of the following structure:' => ' Dans cet exemple on est à <strong> Sous section un-deux-trois </strong> dans un document dont la structure est :', 6044 '%{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => '%{node_file_href} section `%{section}\' dans <cite>%{book}</cite>', 6045 'See' => 'Voir', 6046 'See %{node_file_href} <cite>%{book}</cite>' => 'Voir %{node_file_href} <cite>%{book}</cite>', 6047 'See %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'Voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>', 6048 'See <cite>%{book}</cite>' => 'Voir <cite>%{book}</cite>', 6049 'See section `%{section}\' in <cite>%{book}</cite>' => 'Voir la section `%{section}\' dans <cite>%{book}</cite>', 6050 'This document was generated by <i>%{user}</i> on <i>%{date}</i> using %{program_homepage_href}.' => 'Ce document a été généré par <i>%{user}</i> <i>%{date}</i> en utilisant %{program_homepage_href}.', 6051 'This document was generated by <i>%{user}</i> using %{program_homepage_href}.' => 'Ce document a été généré par <i>%{user}</i> en utilisant %{program_homepage_href}.', 6052 'This document was generated by @emph{%{user}} on @emph{%{date}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} @emph{%{date}} en utilisant %{program_homepage_href}.', 6053 'This document was generated by @emph{%{user}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e par @emph{%{user}} en utilisant %{program_homepage_href}.', 6054 'This document was generated on <i>%{date}</i> using %{program_homepage_href}.' => 'Ce document a été généré <i>%{date}</i> en utilisant %{program_homepage_href}.', 6055 'This document was generated on @emph{%{date}} using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant %{program_homepage_href}.', 6056 'This document was generated on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e @emph{%{date}} en utilisant @uref{%{program_homepage}, @emph{%{program}}}.', 6057 'This document was generated using %{program_homepage_href}.' => 'Ce document a @\'et@\'e g@\'en@\'er@\'e en utilisant %{program_homepage_href}.', 6058 'about (help)' => '@`a propos (page d\'aide)', 6059 'about (this page)' => 'a propos (cette page)', 6060 'beginning of this chapter or previous chapter' => 'd@\'ebut de ce chapitre ou chapitre pr@\'ec@\'edent', 6061 'by <i>%{user}</i>' => 'par <i>%{user}</i>', 6062 'by <i>%{user}</i> on <i>%{date}</i>' => 'par <i>%{user}</i> <i>%{date}</i>', 6063 'concept index' => 'index', 6064 'cover (top) of document' => 'couverture (top) du document', 6065 'current section' => 'section actuelle', 6066 'first section in reading order' => 'premi@`e section dans l\'ordre de lecture', 6067 'following node' => 'node suivant', 6068 'index' => 'index', 6069 'last section in reading order' => 'derni@`ere section dans l\'ordre de lecture', 6070 'next chapter' => 'chapitre suivant', 6071 'next node' => 'node suivant', 6072 'next section in reading order' => 'section suivante dans l\'ordre de lecture', 6073 'next section on same level' => 'section suivante au m@^eme niveau', 6074 'node following in node reading order' => 'node suivant dans l\'ordre des nodes', 6075 'node up' => 'node au dessus', 6076 'on <i>%{date}</i>' => '<i>%{date}</i>', 6077 'previous node' => 'node pr@\'ec@\'edent', 6078 'previous section in reading order' => 'section pr@\'ec@\'edente dans l\'ordre de lecture', 6079 'previous section on same level' => 'section pr@\'ec@\'edente au m@^eme niveau', 6080 'section' => 'section', 6081 'section `%{section}\' in <cite>%{book}</cite>' => 'section `%{section}\' dans <cite>%{book}</cite>', 6082 'see' => 'voir', 6083 'see %{node_file_href} <cite>%{book}</cite>' => 'voir %{node_file_href} <cite>%{book}</cite>', 6084 'see %{node_file_href} section `%{section}\' in <cite>%{book}</cite>' => 'voir %{node_file_href} section `%{section}\' dans <cite>%{book}</cite>', 6085 'see <cite>%{book}</cite>' => 'voir <cite>%{book}</cite>', 6086 'see section `%{section}\' in <cite>%{book}</cite>' => 'voir la section `%{section}\' dans <cite>%{book}</cite>', 6087 'short table of contents' => 'table des mati@`eres r@\'esum@\'ee', 6088 'table of contents' => 'table des mati@`eres', 6089 'up node' => 'node au dessus', 6090 'up section' => 'section sup@\'erieure' 6091 }; 6092 6093 6094$LANGUAGES->{'ja'} = { 6095 ' The buttons in the navigation panels have the following meaning:' => 'ナビゲーションパネル中のボタンには以下の意味があります。', 6096 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '@strong{例}では、以下に示す構造を持つ文書の@strong{1.2.3項}を現在位置に仮定しています。', 6097 ' Up ' => '上', 6098 '%{acronym_like} (%{explanation})' => '', 6099 '%{month}, %{day} %{year}' => '%{year}年%{month}月%{day}日', 6100 '%{name} of %{class}' => '', 6101 '%{name} on %{class}' => '', 6102 '%{node_file_href}' => '', 6103 '%{node_file_href} @cite{%{book}}' => '', 6104 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6105 '%{reference_name}' => '', 6106 '%{style} %{number}' => '', 6107 '%{style}: %{caption_first_line}' => '', 6108 '%{style}: %{shortcaption_first_line}' => '', 6109 '@b{%{quotation_arg}:} ' => '', 6110 '@cite{%{book}}' => '', 6111 'About' => '', 6112 'About (help)' => '', 6113 'About This Document' => 'この文書について', 6114 'April' => '4月', 6115 'August' => '8月', 6116 'Back' => '', 6117 'Beginning of this chapter or previous chapter' => '', 6118 'Button' => 'ボタン', 6119 'Contents' => '目次', 6120 'Cover (top) of document' => '', 6121 'Current Position' => '現在位置', 6122 'Current section' => '', 6123 'December' => '12月', 6124 'FastBack' => '', 6125 'FastForward' => '', 6126 'February' => '2月', 6127 'First' => '', 6128 'First section in reading order' => '', 6129 'Following' => '', 6130 'Following node' => '', 6131 'Footnotes' => '脚注', 6132 'Forward' => '', 6133 'From 1.2.3 go to' => '1.2.3項からの移動先', 6134 'Go to' => '移動先', 6135 'Index' => '見出し', 6136 'Index Entry' => '見出し一覧', 6137 'January' => '1月', 6138 'July' => '7月', 6139 'Jump to' => '移動', 6140 'June' => '6月', 6141 'Last' => '', 6142 'Last section in reading order' => '', 6143 'March' => '3月', 6144 'May' => '5月', 6145 'Menu:' => 'メニュー', 6146 'Name' => '名称', 6147 'Next' => '次', 6148 'Next chapter' => '', 6149 'Next node' => '', 6150 'Next section in reading order' => '', 6151 'Next section on same level' => '', 6152 'Node following in node reading order' => '', 6153 'Node up' => '', 6154 'NodeNext' => '', 6155 'NodePrev' => '', 6156 'NodeUp' => '', 6157 'November' => '11月', 6158 'October' => '10月', 6159 'Overview' => '概要', 6160 'Overview:' => '概要:', 6161 'Prev' => '前', 6162 'Previous node' => '', 6163 'Previous section in reading order' => '', 6164 'Previous section on same level' => '', 6165 'Section' => '項', 6166 'Section One' => '第1項', 6167 'See %{node_file_href}' => '', 6168 'See %{node_file_href} @cite{%{book}}' => '', 6169 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6170 'See %{reference_name}' => '', 6171 'See @cite{%{book}}' => '', 6172 'See section %{reference_name}' => '', 6173 'See section `%{section}\' in @cite{%{book}}' => '', 6174 'September' => '9月', 6175 'Short Table of Contents' => '簡略化した目次', 6176 'Short table of contents' => '', 6177 'Subsection One-Four' => '第1.4項', 6178 'Subsection One-One' => '第1.1項', 6179 'Subsection One-Three' => '第1.3項', 6180 'Subsection One-Two' => '第1.2項', 6181 'Subsubsection One-Two-Four' => '第1.2.4項', 6182 'Subsubsection One-Two-One' => '第1.2.1項', 6183 'Subsubsection One-Two-Three' => '第1.2.3項', 6184 'Subsubsection One-Two-Two' => '第1.2.2項', 6185 'T2H_today' => '%s, %d %d', 6186 'Table of Contents' => '目次', 6187 'Table of contents' => '', 6188 'The node you are looking for is at %{href}.' => '', 6189 'This' => '', 6190 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@emph{%{user}}によって@emph{%{date}}に@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。', 6191 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@emph{%{user}}によって@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。', 6192 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'この文書は@emph{%{date}}に@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。', 6193 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'この文書は@uref{%{program_homepage}, @emph{%{program}}}を用いて生成されました。', 6194 'Top' => '冒頭', 6195 'Untitled Document' => '無題の文書', 6196 'Up' => '', 6197 'Up node' => '', 6198 'Up section' => '', 6199 'by @emph{%{user}}' => '@emph{%{user}}', 6200 'by @emph{%{user}} on @emph{%{date}}' => '@emph{%{user}}, @emph{%{date}', 6201 'current' => '現在位置', 6202 'on @emph{%{date}}' => '@emph{%{date}}', 6203 'section `%{section}\' in @cite{%{book}}' => '@cite{%{book}}の `%{section}\' ', 6204 'see %{node_file_href}' => '%{node_file_href}参照', 6205 'see %{node_file_href} @cite{%{book}}' => '%{node_file_href} @cite{%{book}}参照', 6206 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6207 'see %{reference_name}' => '', 6208 'see @cite{%{book}}' => '', 6209 'see section %{reference_name}' => '', 6210 'see section `%{section}\' in @cite{%{book}}' => '', 6211 'unknown' => '不明' 6212 }; 6213 6214$T2H_OBSOLETE_STRINGS->{'ja'} = { 6215 'about (help)' => '使用法 (ヘルプ)', 6216 'beginning of this chapter or previous chapter' => 'この章または前の章の冒頭', 6217 'cover (top) of document' => '文書の表紙 (トップ)', 6218 'current section' => '現在の節', 6219 'first section in reading order' => '文書順で前の項', 6220 'following node' => '次の節', 6221 'index' => '見出し', 6222 'last section in reading order' => '文書順で最後の項', 6223 'next chapter' => '次の章', 6224 'next node' => '次の節', 6225 'next section in reading order' => '文書順で次の項', 6226 'next section on same level' => '同じ階層にある次の項', 6227 'node following in node reading order' => '文書順で次の節', 6228 'node up' => '上の節へ', 6229 'previous node' => '前の節', 6230 'previous section in reading order' => '文書順で前の節', 6231 'previous section on same level' => '同じ階層にある前の項', 6232 'short table of contents' => '簡略化した目次', 6233 'table of contents' => '文書の目次', 6234 'up node' => '上の節', 6235 'up section' => '上の項' 6236 }; 6237 6238 6239$LANGUAGES->{'nl'} = { 6240 ' The buttons in the navigation panels have the following meaning:' => '', 6241 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', 6242 ' Up ' => '', 6243 '%{acronym_like} (%{explanation})' => '', 6244 '%{month}, %{day} %{year}' => '', 6245 '%{name} of %{class}' => '', 6246 '%{name} on %{class}' => '', 6247 '%{node_file_href}' => '', 6248 '%{node_file_href} @cite{%{book}}' => '', 6249 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6250 '%{reference_name}' => '', 6251 '%{style} %{number}' => '', 6252 '%{style}: %{caption_first_line}' => '', 6253 '%{style}: %{shortcaption_first_line}' => '', 6254 '@b{%{quotation_arg}:} ' => '', 6255 '@cite{%{book}}' => '', 6256 'About' => '', 6257 'About (help)' => '', 6258 'About This Document' => 'No translation available!', 6259 'April' => 'April', 6260 'August' => 'Augustus', 6261 'Back' => '', 6262 'Beginning of this chapter or previous chapter' => '', 6263 'Button' => '', 6264 'Contents' => '', 6265 'Cover (top) of document' => '', 6266 'Current Position' => '', 6267 'Current section' => '', 6268 'December' => 'December', 6269 'FastBack' => '', 6270 'FastForward' => '', 6271 'February' => 'Februari', 6272 'First' => '', 6273 'First section in reading order' => '', 6274 'Following' => '', 6275 'Following node' => '', 6276 'Footnotes' => 'No translation available!', 6277 'Forward' => '', 6278 'From 1.2.3 go to' => '', 6279 'Go to' => '', 6280 'Index' => 'Index', 6281 'Index Entry' => '', 6282 'January' => 'Januari', 6283 'July' => 'Juli', 6284 'Jump to' => '', 6285 'June' => 'Juni', 6286 'Last' => '', 6287 'Last section in reading order' => '', 6288 'March' => 'Maart', 6289 'May' => 'Mei', 6290 'Menu:' => '', 6291 'Name' => '', 6292 'Next' => '', 6293 'Next chapter' => '', 6294 'Next node' => '', 6295 'Next section in reading order' => '', 6296 'Next section on same level' => '', 6297 'Node following in node reading order' => '', 6298 'Node up' => '', 6299 'NodeNext' => '', 6300 'NodePrev' => '', 6301 'NodeUp' => '', 6302 'November' => 'November', 6303 'October' => 'Oktober', 6304 'Overview' => '', 6305 'Overview:' => '', 6306 'Prev' => '', 6307 'Previous node' => '', 6308 'Previous section in reading order' => '', 6309 'Previous section on same level' => '', 6310 'Section' => '', 6311 'Section One' => '', 6312 'See %{node_file_href}' => '', 6313 'See %{node_file_href} @cite{%{book}}' => '', 6314 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6315 'See %{reference_name}' => '', 6316 'See @cite{%{book}}' => '', 6317 'See section %{reference_name}' => '', 6318 'See section `%{section}\' in @cite{%{book}}' => '', 6319 'September' => 'September', 6320 'Short Table of Contents' => 'Korte inhoudsopgave', 6321 'Short table of contents' => '', 6322 'Subsection One-Four' => '', 6323 'Subsection One-One' => '', 6324 'Subsection One-Three' => '', 6325 'Subsection One-Two' => '', 6326 'Subsubsection One-Two-Four' => '', 6327 'Subsubsection One-Two-One' => '', 6328 'Subsubsection One-Two-Three' => '', 6329 'Subsubsection One-Two-Two' => '', 6330 'T2H_today' => '', 6331 'Table of Contents' => 'Inhoudsopgave', 6332 'Table of contents' => '', 6333 'The node you are looking for is at %{href}.' => '', 6334 'This' => '', 6335 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6336 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6337 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '', 6338 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6339 'Top' => '', 6340 'Untitled Document' => '', 6341 'Up' => '', 6342 'Up node' => '', 6343 'Up section' => '', 6344 'by @emph{%{user}}' => '', 6345 'by @emph{%{user}} on @emph{%{date}}' => '', 6346 'current' => '', 6347 'on @emph{%{date}}' => '', 6348 'section `%{section}\' in @cite{%{book}}' => '', 6349 'see %{node_file_href}' => '', 6350 'see %{node_file_href} @cite{%{book}}' => '', 6351 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6352 'see %{reference_name}' => '', 6353 'see @cite{%{book}}' => '', 6354 'see section %{reference_name}' => '', 6355 'see section `%{section}\' in @cite{%{book}}' => '', 6356 'unknown' => '' 6357 }; 6358 6359$T2H_OBSOLETE_STRINGS->{'nl'} = { 6360 'See' => 'Zie', 6361 'section' => 'sectie', 6362 'see' => 'zie' 6363 }; 6364 6365 6366$LANGUAGES->{'no'} = { 6367 ' The buttons in the navigation panels have the following meaning:' => '', 6368 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => '', 6369 ' Up ' => '', 6370 '%{acronym_like} (%{explanation})' => '', 6371 '%{month}, %{day} %{year}' => '', 6372 '%{name} of %{class}' => '', 6373 '%{name} on %{class}' => '', 6374 '%{node_file_href}' => '', 6375 '%{node_file_href} @cite{%{book}}' => '', 6376 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6377 '%{reference_name}' => '', 6378 '%{style} %{number}' => '', 6379 '%{style}: %{caption_first_line}' => '', 6380 '%{style}: %{shortcaption_first_line}' => '', 6381 '@b{%{quotation_arg}:} ' => '', 6382 '@cite{%{book}}' => '', 6383 'About' => '', 6384 'About (help)' => '', 6385 'About This Document' => 'No translation available!', 6386 'April' => 'april', 6387 'August' => 'august', 6388 'Back' => '', 6389 'Beginning of this chapter or previous chapter' => '', 6390 'Button' => '', 6391 'Contents' => '', 6392 'Cover (top) of document' => '', 6393 'Current Position' => '', 6394 'Current section' => '', 6395 'December' => 'desember', 6396 'FastBack' => '', 6397 'FastForward' => '', 6398 'February' => 'februar', 6399 'First' => '', 6400 'First section in reading order' => '', 6401 'Following' => '', 6402 'Following node' => '', 6403 'Footnotes' => 'No translation available!', 6404 'Forward' => '', 6405 'From 1.2.3 go to' => '', 6406 'Go to' => '', 6407 'Index' => 'Indeks', 6408 'Index Entry' => '', 6409 'January' => 'januar', 6410 'July' => 'juli', 6411 'Jump to' => '', 6412 'June' => 'juni', 6413 'Last' => '', 6414 'Last section in reading order' => '', 6415 'March' => 'mars', 6416 'May' => 'mai', 6417 'Menu:' => '', 6418 'Name' => '', 6419 'Next' => '', 6420 'Next chapter' => '', 6421 'Next node' => '', 6422 'Next section in reading order' => '', 6423 'Next section on same level' => '', 6424 'Node following in node reading order' => '', 6425 'Node up' => '', 6426 'NodeNext' => '', 6427 'NodePrev' => '', 6428 'NodeUp' => '', 6429 'November' => 'november', 6430 'October' => 'oktober', 6431 'Overview' => '', 6432 'Overview:' => '', 6433 'Prev' => '', 6434 'Previous node' => '', 6435 'Previous section in reading order' => '', 6436 'Previous section on same level' => '', 6437 'Section' => '', 6438 'Section One' => '', 6439 'See %{node_file_href}' => '', 6440 'See %{node_file_href} @cite{%{book}}' => '', 6441 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6442 'See %{reference_name}' => '', 6443 'See @cite{%{book}}' => '', 6444 'See section %{reference_name}' => '', 6445 'See section `%{section}\' in @cite{%{book}}' => '', 6446 'September' => 'september', 6447 'Short Table of Contents' => 'Kort innholdsfortegnelse', 6448 'Short table of contents' => '', 6449 'Subsection One-Four' => '', 6450 'Subsection One-One' => '', 6451 'Subsection One-Three' => '', 6452 'Subsection One-Two' => '', 6453 'Subsubsection One-Two-Four' => '', 6454 'Subsubsection One-Two-One' => '', 6455 'Subsubsection One-Two-Three' => '', 6456 'Subsubsection One-Two-Two' => '', 6457 'T2H_today' => '', 6458 'Table of Contents' => 'Innholdsfortegnelse', 6459 'Table of contents' => '', 6460 'The node you are looking for is at %{href}.' => '', 6461 'This' => '', 6462 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6463 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6464 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => '', 6465 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => '', 6466 'Top' => '', 6467 'Untitled Document' => '', 6468 'Up' => '', 6469 'Up node' => '', 6470 'Up section' => '', 6471 'by @emph{%{user}}' => '', 6472 'by @emph{%{user}} on @emph{%{date}}' => '', 6473 'current' => '', 6474 'on @emph{%{date}}' => '', 6475 'section `%{section}\' in @cite{%{book}}' => '', 6476 'see %{node_file_href}' => '', 6477 'see %{node_file_href} @cite{%{book}}' => '', 6478 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => '', 6479 'see %{reference_name}' => '', 6480 'see @cite{%{book}}' => '', 6481 'see section %{reference_name}' => '', 6482 'see section `%{section}\' in @cite{%{book}}' => '', 6483 'unknown' => '' 6484 }; 6485 6486$T2H_OBSOLETE_STRINGS->{'no'} = { 6487 'See' => 'Se', 6488 'section' => 'avsnitt', 6489 'see' => 'se' 6490 }; 6491 6492 6493$LANGUAGES->{'pt'} = { 6494 ' The buttons in the navigation panels have the following meaning:' => ' Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:', 6495 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' onde o @strong{ Exemplo } assume que a posi@,{c}@~ao atual localiza-se em @strong{ Subsub@,{c}@~ao Um-Dois-Tr@^es } de um documento com a seguinte estrutura:', 6496 ' Up ' => ' Acima ', 6497 '%{acronym_like} (%{explanation})' => '', 6498 '%{month}, %{day} %{year}' => '%{day} de %{month} de %{year}', 6499 '%{name} of %{class}' => '%{name} da %{class}', 6500 '%{name} on %{class}' => '%{name} na %{class}', 6501 '%{node_file_href}' => '', 6502 '%{node_file_href} @cite{%{book}}' => '', 6503 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6504 '%{reference_name}' => '', 6505 '%{style} %{number}' => '', 6506 '%{style}: %{caption_first_line}' => '', 6507 '%{style}: %{shortcaption_first_line}' => '', 6508 '@b{%{quotation_arg}:} ' => '', 6509 '@cite{%{book}}' => '', 6510 'About' => 'Sobre', 6511 'About (help)' => 'Sobre (ajuda)', 6512 'About This Document' => 'Sobre Esse Documento', 6513 'April' => 'Abril', 6514 'August' => 'Agosto', 6515 'Back' => 'Volta', 6516 'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 6517 'Button' => 'Bot@~ao', 6518 'Contents' => 'Conte@\'udo', 6519 'Cover (top) of document' => 'In@\'icio (topo) do documento', 6520 'Current Position' => 'Posi@,{c}@~ao Atual', 6521 'Current section' => 'Se@,{c}@~ao atual', 6522 'December' => 'Dezembro', 6523 'FastBack' => 'Voltar R@\'apido', 6524 'FastForward' => 'Avan@,{c}ar R@\'apido', 6525 'February' => 'Fevereiro', 6526 'First' => 'Primeiro', 6527 'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura', 6528 'Following' => 'Seguinte', 6529 'Following node' => 'Nodo seguinte', 6530 'Footnotes' => 'Notas de Rodap@\'e', 6531 'Forward' => 'Avan@,{c}ar', 6532 'From 1.2.3 go to' => 'De 1.2.3 v@\'a para', 6533 'Go to' => 'V@\'a para', 6534 'Index' => '@\'Indice', 6535 'Index Entry' => 'Entrada de @\'Indice', 6536 'January' => 'Janeiro', 6537 'July' => 'Julho', 6538 'Jump to' => 'Pular para', 6539 'June' => 'Junho', 6540 'Last' => '@\'Ultimo', 6541 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura', 6542 'March' => 'Mar@,{c}o', 6543 'May' => 'Maio', 6544 'Menu:' => '', 6545 'Name' => 'Nome', 6546 'Next' => 'Pr@\'oximo', 6547 'Next chapter' => 'Pr@\'oximo cap@\'itulo', 6548 'Next node' => 'Pr@\'oximo nodo', 6549 'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura', 6550 'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 6551 'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos', 6552 'Node up' => 'Nodo acima', 6553 'NodeNext' => 'Pr@\'oximo Nodo', 6554 'NodePrev' => 'Nodo Anterior', 6555 'NodeUp' => 'Nodo Acima', 6556 'November' => 'Novembro', 6557 'October' => 'Outubro', 6558 'Overview' => 'Vis@~ao geral', 6559 'Overview:' => 'Vis@~ao geral:', 6560 'Prev' => 'Pr@\'evio', 6561 'Previous node' => 'Nodo anterior', 6562 'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura', 6563 'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel', 6564 'Section' => 'Se@,{c}@~ao', 6565 'Section One' => 'Se@,{c}@~ao Um', 6566 'See %{node_file_href}' => 'Veja %{node_file_href}', 6567 'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}', 6568 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6569 'See %{reference_name}' => 'Veja %{reference_name}', 6570 'See @cite{%{book}}' => 'Veja @cite{%{book}}', 6571 'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}', 6572 'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6573 'September' => 'Setembro', 6574 'Short Table of Contents' => 'Breve Sum@\'ario', 6575 'Short table of contents' => 'Breve sum@\'ario', 6576 'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro', 6577 'Subsection One-One' => 'Subse@,{c}@~ao Um-Um', 6578 'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es', 6579 'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois', 6580 'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro', 6581 'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um', 6582 'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es', 6583 'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois', 6584 'T2H_today' => '', 6585 'Table of Contents' => 'Sum@\'ario', 6586 'Table of contents' => 'Sum@\'ario', 6587 'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.', 6588 'This' => 'Esse', 6589 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gereado por @emph{%{user}} em @emph{%{date}} usando @uref{%{program_homepage}, @emph{%{program}}}.', 6590 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado por @emph{%{user}} usando @uref{%{program_homepage}, @emph{%{program}}}.', 6591 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Esse documento foi gerado em @i{%{date}} usando @uref{%{program_homepage}, @i{%{program}}}.', 6592 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.', 6593 'Top' => 'Topo', 6594 'Untitled Document' => 'Documento Sem Nome', 6595 'Up' => 'Acima', 6596 'Up node' => 'Nodo acima', 6597 'Up section' => 'Se@,{c}@~ao acima', 6598 'by @emph{%{user}}' => 'por @emph{%{user}}', 6599 'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}', 6600 'current' => 'atual', 6601 'on @emph{%{date}}' => 'em @emph{%{date}}', 6602 'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6603 'see %{node_file_href}' => 'veja %{node_file_href}', 6604 'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}', 6605 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6606 'see %{reference_name}' => 'veja %{reference_name}', 6607 'see @cite{%{book}}' => 'veja @cite{%{book}}', 6608 'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}', 6609 'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6610 'unknown' => 'desconhecido' 6611 }; 6612 6613$T2H_OBSOLETE_STRINGS->{'pt'} = { 6614 'See' => 'Veja', 6615 'about (help)' => 'sobre (ajuda)', 6616 'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 6617 'cover (top) of document' => 'in@\'icio (topo) do documento', 6618 'current section' => 'se@,{c}@~ao atual', 6619 'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura', 6620 'following node' => 'nodo seguinte', 6621 'index' => '@\'indice', 6622 'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura', 6623 'next chapter' => 'pr@\'oximo cap@\'itulo', 6624 'next node' => 'pr@\'oximo nodo', 6625 'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura', 6626 'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 6627 'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos', 6628 'node up' => 'nodo acima', 6629 'previous node' => 'nodo anterior', 6630 'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura', 6631 'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel', 6632 'section' => 'Se@,{c}@~ao', 6633 'see' => 'veja', 6634 'short table of contents' => 'breve sum@\'ario', 6635 'table of contents' => 'sum@\'ario', 6636 'up node' => 'nodo acima', 6637 'up section' => 'se@,{c}@~ao acima' 6638 }; 6639 6640 6641$LANGUAGES->{'pt_BR'} = { 6642 ' The buttons in the navigation panels have the following meaning:' => ' Os bot@~oes nos pain@\'eis de navega@,{c}@~ao possuem os seguintes significados:', 6643 ' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:' => ' onde o @strong{ Exemplo } assume que a posi@,{c}@~ao atual localiza-se em @strong{ Subsub@,{c}@~ao Um-Dois-Tr@^es } de um documento com a seguinte estrutura:', 6644 ' Up ' => ' Acima ', 6645 '%{acronym_like} (%{explanation})' => '', 6646 '%{month}, %{day} %{year}' => '%{day} de %{month} de %{year}', 6647 '%{name} of %{class}' => '%{name} da %{class}', 6648 '%{name} on %{class}' => '%{name} na %{class}', 6649 '%{node_file_href}' => '', 6650 '%{node_file_href} @cite{%{book}}' => '', 6651 '%{node_file_href} section `%{section}\' in @cite{%{book}}' => '%{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6652 '%{reference_name}' => '', 6653 '%{style} %{number}' => '', 6654 '%{style}: %{caption_first_line}' => '', 6655 '%{style}: %{shortcaption_first_line}' => '', 6656 '@b{%{quotation_arg}:} ' => '', 6657 '@cite{%{book}}' => '', 6658 'About' => 'Sobre', 6659 'About (help)' => 'Sobre (ajuda)', 6660 'About This Document' => 'Sobre Esse Documento', 6661 'April' => 'Abril', 6662 'August' => 'Agosto', 6663 'Back' => 'Volta', 6664 'Beginning of this chapter or previous chapter' => 'Come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 6665 'Button' => 'Bot@~ao', 6666 'Contents' => 'Conte@\'udo', 6667 'Cover (top) of document' => 'In@\'icio (topo) do documento', 6668 'Current Position' => 'Posi@,{c}@~ao Atual', 6669 'Current section' => 'Se@,{c}@~ao atual', 6670 'December' => 'Dezembro', 6671 'FastBack' => 'Voltar R@\'apido', 6672 'FastForward' => 'Avan@,{c}ar R@\'apido', 6673 'February' => 'Fevereiro', 6674 'First' => 'Primeiro', 6675 'First section in reading order' => 'Primeira se@,{c}@~ao na ordem de leitura', 6676 'Following' => 'Seguinte', 6677 'Following node' => 'Nodo seguinte', 6678 'Footnotes' => 'Notas de Rodap@\'e', 6679 'Forward' => 'Avan@,{c}ar', 6680 'From 1.2.3 go to' => 'De 1.2.3 v@\'a para', 6681 'Go to' => 'V@\'a para', 6682 'Index' => '@\'Indice', 6683 'Index Entry' => 'Entrada de @\'Indice', 6684 'January' => 'Janeiro', 6685 'July' => 'Julho', 6686 'Jump to' => 'Pular para', 6687 'June' => 'Junho', 6688 'Last' => '@\'Ultimo', 6689 'Last section in reading order' => '@\'Ultima se@,{c}@~ao na ordem de leitura', 6690 'March' => 'Mar@,{c}o', 6691 'May' => 'Maio', 6692 'Menu:' => '', 6693 'Name' => 'Nome', 6694 'Next' => 'Pr@\'oximo', 6695 'Next chapter' => 'Pr@\'oximo cap@\'itulo', 6696 'Next node' => 'Pr@\'oximo nodo', 6697 'Next section in reading order' => 'Pr@\'oxima se@,{c}@~ao na ordem de leitura', 6698 'Next section on same level' => 'Pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 6699 'Node following in node reading order' => 'Nodo seguinte na ordem de leitura de nodos', 6700 'Node up' => 'Nodo acima', 6701 'NodeNext' => 'Pr@\'oximo Nodo', 6702 'NodePrev' => 'Nodo Anterior', 6703 'NodeUp' => 'Nodo Acima', 6704 'November' => 'Novembro', 6705 'October' => 'Outubro', 6706 'Overview' => 'Vis@~ao geral', 6707 'Overview:' => 'Vis@~ao geral:', 6708 'Prev' => 'Pr@\'evio', 6709 'Previous node' => 'Nodo anterior', 6710 'Previous section in reading order' => 'Se@,{c}@~ao anterior na ordem de leitura', 6711 'Previous section on same level' => 'Se@,{c}@~ao anterior no mesmo n@\'ivel', 6712 'Section' => 'Se@,{c}@~ao', 6713 'Section One' => 'Se@,{c}@~ao Um', 6714 'See %{node_file_href}' => 'Veja %{node_file_href}', 6715 'See %{node_file_href} @cite{%{book}}' => 'Veja %{node_file_href} @cite{%{book}}', 6716 'See %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'Veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6717 'See %{reference_name}' => 'Veja %{reference_name}', 6718 'See @cite{%{book}}' => 'Veja @cite{%{book}}', 6719 'See section %{reference_name}' => 'Veja se@,{c}@~ao %{reference_name}', 6720 'See section `%{section}\' in @cite{%{book}}' => 'Veja se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6721 'September' => 'Setembro', 6722 'Short Table of Contents' => 'Breve Sum@\'ario', 6723 'Short table of contents' => 'Breve sum@\'ario', 6724 'Subsection One-Four' => 'Subse@,{c}@~ao Um-Quatro', 6725 'Subsection One-One' => 'Subse@,{c}@~ao Um-Um', 6726 'Subsection One-Three' => 'Subse@,{c}@~ao Um-Tr@^es', 6727 'Subsection One-Two' => 'Subse@,{c}@~ao Um-Dois', 6728 'Subsubsection One-Two-Four' => 'Subse@,{c}@~ao Um-Dois-Quatro', 6729 'Subsubsection One-Two-One' => 'Subse@,{c}@~ao Um-Dois-Um', 6730 'Subsubsection One-Two-Three' => 'Subse@,{c}@~ao Um-Dois-Tr@^es', 6731 'Subsubsection One-Two-Two' => 'Subse@,{c}@~ao Um-Dois-Dois', 6732 'T2H_today' => '', 6733 'Table of Contents' => 'Sum@\'ario', 6734 'Table of contents' => 'Sum@\'ario', 6735 'The node you are looking for is at %{href}.' => 'O nodo que vo@^e est@\'a olhando est@\'a em %{href}.', 6736 'This' => 'Esse', 6737 'This document was generated by @emph{%{user}} on @emph{%{date}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gereado por @emph{%{user}} em @emph{%{date}} usando @uref{%{program_homepage}, @emph{%{program}}}.', 6738 'This document was generated by @emph{%{user}} using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado por @emph{%{user}} usando @uref{%{program_homepage}, @emph{%{program}}}.', 6739 'This document was generated on @i{%{date}} using @uref{%{program_homepage}, @i{%{program}}}.' => 'Esse documento foi gerado em @i{%{date}} usando @uref{%{program_homepage}, @i{%{program}}}.', 6740 'This document was generated using @uref{%{program_homepage}, @emph{%{program}}}.' => 'Esse documento foi gerado usando @uref{%{program_homepage}, @emph{%{program}}}.', 6741 'Top' => 'Topo', 6742 'Untitled Document' => 'Documento Sem Nome', 6743 'Up' => 'Acima', 6744 'Up node' => 'Nodo acima', 6745 'Up section' => 'Se@,{c}@~ao acima', 6746 'by @emph{%{user}}' => 'por @emph{%{user}}', 6747 'by @emph{%{user}} on @emph{%{date}}' => 'por @emph{%{user}} em @emph{%{date}}', 6748 'current' => 'atual', 6749 'on @emph{%{date}}' => 'em @emph{%{date}}', 6750 'section `%{section}\' in @cite{%{book}}' => 'se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6751 'see %{node_file_href}' => 'veja %{node_file_href}', 6752 'see %{node_file_href} @cite{%{book}}' => 'veja %{node_file_href} @cite{%{book}}', 6753 'see %{node_file_href} section `%{section}\' in @cite{%{book}}' => 'veja %{node_file_href} se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6754 'see %{reference_name}' => 'veja %{reference_name}', 6755 'see @cite{%{book}}' => 'veja @cite{%{book}}', 6756 'see section %{reference_name}' => 'veja se@,{c}@~ao %{reference_name}', 6757 'see section `%{section}\' in @cite{%{book}}' => 'veja se@,{c}@~ao `%{section}\' em @cite{%{book}}', 6758 'unknown' => 'desconhecido' 6759 }; 6760 6761$T2H_OBSOLETE_STRINGS->{'pt_BR'} = { 6762 'See' => 'Veja', 6763 'about (help)' => 'sobre (ajuda)', 6764 'beginning of this chapter or previous chapter' => 'come@,{c}o desse cap@\'itulo ou cap@\'itulo anterior', 6765 'cover (top) of document' => 'in@\'icio (topo) do documento', 6766 'current section' => 'se@,{c}@~ao atual', 6767 'first section in reading order' => 'primeira se@,{c}@~ao na ordem de leitura', 6768 'following node' => 'nodo seguinte', 6769 'index' => '@\'indice', 6770 'last section in reading order' => '@\'ultima se@,{c}@~ao na ordem de leitura', 6771 'next chapter' => 'pr@\'oximo cap@\'itulo', 6772 'next node' => 'pr@\'oximo nodo', 6773 'next section in reading order' => 'pr@\'oxima se@,{c}@~ao na ordem de leitura', 6774 'next section on same level' => 'pr@\'oxima se@,{c}@~ao no mesmo n@\'ivel', 6775 'node following in node reading order' => 'nodo seguinte na ordem de leitura de nodos', 6776 'node up' => 'nodo acima', 6777 'previous node' => 'nodo anterior', 6778 'previous section in reading order' => 'se@,{c}@~ao anterior na ordem de leitura', 6779 'previous section on same level' => 'se@,{c}@~ao anterior no mesmo n@\'ivel', 6780 'section' => 'Se@,{c}@~ao', 6781 'see' => 'veja', 6782 'short table of contents' => 'breve sum@\'ario', 6783 'table of contents' => 'sum@\'ario', 6784 'up node' => 'nodo acima', 6785 'up section' => 'se@,{c}@~ao acima' 6786 }; 6787 6788 6789 6790require "$ENV{T2H_HOME}/$translation_file" 6791 if ($0 =~ /\.pl$/ && 6792 -e "$ENV{T2H_HOME}/$translation_file" && -r "$ENV{T2H_HOME}/$translation_file"); 6793 6794# set the default 'args' entry to normal for each style hash (and each command 6795# within) 6796my $name_index = -1; 6797my @hash_names = ('style_map', 'style_map_pre', 'style_map_texi', 'simple_format_style_map_texi'); 6798foreach my $hash (\%style_map, \%style_map_pre, \%style_map_texi, \%simple_format_style_map_texi) 6799{ 6800 $name_index++; 6801 my $name = $hash_names[$name_index]; # name associated with hash ref 6802 foreach my $style (keys(%{$hash})) 6803 { 6804 next unless (ref($hash->{$style}) eq 'HASH'); 6805 $hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'})); 6806 die "Bug: args not defined, but existing, for $style in $name" if (!defined($hash->{$style}->{'args'})); 6807#print STDERR "DEFAULT($name, $hash) add normal as arg for $style ($hash->{$style}), $hash->{$style}->{'args'}\n"; 6808 } 6809} 6810 6811# 6812# Some functions used to override normal formatting functions in specific 6813# cases. The user shouldn't want to change them, but can use them. 6814# 6815 6816# used to utf8 encode the result 6817sub t2h_utf8_accent($$$) 6818{ 6819 my $accent = shift; 6820 my $args = shift; 6821 my $style_stack = shift; 6822 6823 my $text = $args->[0]; 6824 #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n"; 6825 6826 # special handling of @dotless{i} 6827 if ($accent eq 'dotless') 6828 { 6829 if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent'))) 6830 { 6831 return "\x{0131}"; 6832 } 6833 #return "\x{}" if ($text eq 'j'); # not found ! 6834 return $text; 6835 } 6836 6837 # FIXME \x{0131}\x{0308} for @dotless{i} @" doesn't lead to NFC 00ef. 6838 return Unicode::Normalize::NFC($text . chr(hex($unicode_diacritical{$accent}))) 6839 if (defined($unicode_diacritical{$accent})); 6840 return ascii_accents($text, $accent); 6841} 6842 6843sub t2h_utf8_normal_text($$$$$) 6844{ 6845 my $text = shift; 6846 my $in_raw_text = shift; 6847 my $in_preformatted = shift; 6848 my $in_code =shift; 6849 my $style_stack = shift; 6850 $text = &$protect_text($text) unless($in_raw_text); 6851 $text = uc($text) if (in_small_caps($style_stack)); 6852 6853 if (!$in_code and !$in_preformatted) 6854 { 6855 $text =~ s/---/\x{2014}/g; 6856 $text =~ s/--/\x{2013}/g; 6857 $text =~ s/``/\x{201C}/g; 6858 $text =~ s/''/\x{201D}/g; 6859 } 6860 return Unicode::Normalize::NFC($text); 6861} 6862 6863# these are unlikely to be used by users, as they are essentially 6864# used to follow the html external refs specification in texinfo 6865sub t2h_cross_manual_normal_text($$$$$) 6866{ 6867 my $text = shift; 6868 my $in_raw_text = shift; 6869 my $in_preformatted = shift; 6870 my $in_code =shift; 6871 my $style_stack = shift; 6872 6873 $text = uc($text) if (in_small_caps($style_stack)); 6874 return $text if ($USE_UNICODE); 6875 6876 # if there is no unicode support, we do all the transformations here 6877 my $result = ''; 6878 while ($text ne '') 6879 { 6880 if ($text =~ s/^([A-Za-z0-9]+)//o) 6881 { 6882 $result .= $1; 6883 } 6884 elsif ($text =~ s/^ //o) 6885 { 6886 $result .= '-'; 6887 } 6888 elsif ($text =~ s/^(.)//o) 6889 { 6890 if (exists($ascii_character_map{$1})) 6891 { 6892 $result .= '_' . lc($ascii_character_map{$1}); 6893 } 6894 else 6895 { # wild guess that should work for latin1 6896 $result .= '_' . '00' . lc(sprintf("%02x",ord($1))); 6897 } 6898 } 6899 else 6900 { 6901 print STDERR "Bug: unknown character in cross ref (likely in infinite loop)\n"; 6902 sleep 1; 6903 } 6904 } 6905 6906 return $result; 6907} 6908 6909sub t2h_nounicode_cross_manual_accent($$$) 6910{ 6911 my $accent = shift; 6912 my $args = shift; 6913 my $style_stack = shift; 6914 6915 my $text = $args->[0]; 6916 6917 if ($accent eq 'dotless') 6918 { 6919 if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent'))) 6920 { 6921 return "_0131"; 6922 } 6923 #return "\x{}" if ($text eq 'j'); # not found ! 6924 return $text; 6925 } 6926 return '_' . lc($unicode_accents{$accent}->{$text}) 6927 if (defined($unicode_accents{$accent}->{$text})); 6928 return ($text . '_' . lc($unicode_diacritical{$accent})) 6929 if (defined($unicode_diacritical{$accent})); 6930 return ascii_accents($text, $accent); 6931} 6932 6933sub t2h_transliterate_cross_manual_accent($$) 6934{ 6935 my $accent = shift; 6936 my $args = shift; 6937 6938 my $text = $args->[0]; 6939 6940 if (exists($unicode_accents{$accent}->{$text}) and 6941 exists ($transliterate_map{$unicode_accents{$accent}->{$text}})) 6942 { 6943 return $transliterate_map{$unicode_accents{$accent}->{$text}}; 6944 } 6945 return $text; 6946} 6947 6948 6949} # end package Texi2HTML::Config 6950 6951use vars qw( 6952%value 6953); 6954 6955# variables which might be redefined by the user but aren't likely to be 6956# they seem to be in the main namespace 6957use vars qw( 6958%index_names 6959%predefined_index 6960%valid_index 6961%sec2level 6962%code_style_map 6963%region_lines 6964%forbidden_index_name 6965); 6966 6967# Some global variables are set in the script, and used in the subroutines 6968# they are in the Texi2HTML namespace, thus prefixed with Texi2HTML::. 6969# see texi2html.init for details. 6970 6971#+++############################################################################ 6972# # 6973# Initialization # 6974# Pasted content of File $(srcdir)/MySimple.pm: Command-line processing # 6975# # 6976#---############################################################################ 6977 6978# leave this within comments, and keep the require statement 6979# This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/texi2html.init 6980# exists. 6981 6982# @MYSIMPLE@ 6983package Getopt::MySimple; 6984 6985# Name: 6986# Getopt::MySimple. 6987# 6988# Documentation: 6989# POD-style (incomplete) documentation is in file MySimple.pod 6990# 6991# Tabs: 6992# 4 spaces || die. 6993# 6994# Author: 6995# Ron Savage rpsavage@ozemail.com.au. 6996# 1.00 19-Aug-97 Initial version. 6997# 1.10 13-Oct-97 Add arrays of switches (eg '=s@'). 6998# 1.20 3-Dec-97 Add 'Help' on a per-switch basis. 6999# 1.30 11-Dec-97 Change 'Help' to 'verbose'. Make all hash keys lowercase. 7000# 1.40 10-Nov-98 Change width of help report. Restructure tests. 7001# 1-Jul-00 Modifications for Texi2html 7002 7003# -------------------------------------------------------------------------- 7004# Locally modified by obachman (Display type instead of env, order by cmp) 7005# $Id: MySimple.pm,v 1.5 2006/04/17 23:11:09 pertusus Exp $ 7006 7007# use strict; 7008# no strict 'refs'; 7009 7010use vars qw(@EXPORT @EXPORT_OK @ISA); 7011use vars qw($fieldWidth $opt $VERSION); 7012 7013use Exporter(); 7014use Getopt::Long; 7015 7016@ISA = qw(Exporter); 7017@EXPORT = qw(); 7018@EXPORT_OK = qw($opt); # An alias for $self -> {'opt'}. 7019 7020# -------------------------------------------------------------------------- 7021 7022$fieldWidth = 20; 7023$VERSION = '1.41'; 7024 7025# -------------------------------------------------------------------------- 7026 7027sub byOrder 7028{ 7029 my($self) = @_; 7030 7031 return uc($a) cmp (uc($b)); 7032} 7033 7034# -------------------------------------------------------------------------- 7035 7036sub dumpOptions 7037{ 7038 my($self) = @_; 7039 7040 print 'Option', ' ' x ($fieldWidth - length('Option') ), "Value\n"; 7041 7042 for (sort byOrder keys(%{$self -> {'opt'} }) ) 7043 { 7044 print "-$_", ' ' x ($fieldWidth - (1 + length) ), "${$self->{'opt'} }{$_}\n"; 7045 } 7046 7047 print "\n"; 7048 7049} # End of dumpOptions. 7050 7051# -------------------------------------------------------------------------- 7052# Return: 7053# 0 -> Error. 7054# 1 -> Ok. 7055 7056sub getOptions 7057{ 7058 push(@_, 0) if ($#_ == 2); # Default for $ignoreCase is 0. 7059 push(@_, 1) if ($#_ == 3); # Default for $helpThenExit is 1. 7060 7061 my($self, $default, $helpText, $versionText, 7062 $helpThenExit, $versionThenExit, $ignoreCase) = @_; 7063 7064 $helpThenExit = 1 unless (defined($helpThenExit)); 7065 $versionThenExit = 1 unless (defined($versionThenExit)); 7066 $ignoreCase = 0 unless (defined($ignoreCase)); 7067 7068 $self -> {'default'} = $default; 7069 $self -> {'helpText'} = $helpText; 7070 $self -> {'versionText'} = $versionText; 7071 $Getopt::Long::ignorecase = $ignoreCase; 7072 7073 unless (defined($self -> {'default'}{'help'})) 7074 { 7075 $self -> {'default'}{'help'} = 7076 { 7077 type => ':i', 7078 default => '', 7079 linkage => sub {$self->helpOptions($_[1]); sleep 5;exit (0) if $helpThenExit;}, 7080 verbose => "print help and exit" 7081 }; 7082 } 7083 7084 unless (defined($self -> {'default'}{'version'})) 7085 { 7086 $self -> {'default'}{'version'} = 7087 { 7088 type => '', 7089 default => '', 7090 linkage => sub {print $self->{'versionText'}; exit (0) if $versionThenExit;}, 7091 verbose => "print version and exit" 7092 }; 7093 } 7094 7095 for (keys(%{$self -> {'default'} }) ) 7096 { 7097 next unless (ref(${$self -> {'default'} }{$_}) eq 'HASH'); 7098 my $type = ${$self -> {'default'} }{$_}{'type'}; 7099 push(@{$self -> {'type'} }, "$_$type"); 7100 $self->{'opt'}->{$_} = ${$self -> {'default'} }{$_}{'linkage'} 7101 if ${$self -> {'default'} }{$_}{'linkage'}; 7102 } 7103 7104 my($result) = &GetOptions($self -> {'opt'}, @{$self -> {'type'} }); 7105 7106 return $result unless $result; 7107 7108 for (keys(%{$self -> {'default'} }) ) 7109 { 7110 if (! defined(${$self -> {'opt'} }{$_})) #{ 7111 { 7112 ${$self -> {'opt'} }{$_} = ${$self -> {'default'} }{$_}{'default'}; 7113 } 7114 } 7115 7116 $result; 7117} # End of getOptions. 7118 7119# -------------------------------------------------------------------------- 7120 7121sub helpOptions 7122{ 7123 my($self) = shift; 7124 my($noHelp) = shift; 7125 $noHelp = 0 unless $noHelp; 7126 my($optwidth, $typewidth, $defaultwidth, $maxlinewidth, $valind, $valwidth) 7127 = (10, 5, 9, 78, 4, 11); 7128 7129 print "$self->{'helpText'}" if ($self -> {'helpText'}); 7130 7131 print ' Option', ' ' x ($optwidth - length('Option') -1 ), 7132 'Type', ' ' x ($typewidth - length('Type') + 1), 7133 'Default', ' ' x ($defaultwidth - length('Default') ), 7134 "Description\n"; 7135 7136 for (sort byOrder keys(%{$self -> {'default'} }) ) 7137 { 7138 my($line, $help, $option, $val); 7139 $option = $_; 7140 next if ${$self->{'default'} }{$_}{'noHelp'} && ${$self->{'default'} }{$_}{'noHelp'} > $noHelp; 7141 #$line = " -$_" . ' ' x ($optwidth - (2 + length) ) . 7142 # "${$self->{'default'} }{$_}{'type'} ". 7143 # ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) )); 7144 $line = " --$_" . "${$self->{'default'} }{$_}{'type'}". 7145 ' ' x ($typewidth - (1+length(${$self -> {'default'} }{$_}{'type'}) )); 7146 7147 $val = ${$self->{'default'} }{$_}{'linkage'}; 7148 if ($val) 7149 { 7150 if ((ref($val) eq 'SCALAR') and (defined($$val))) 7151 { 7152 $val = $$val; 7153 } 7154 else 7155 { 7156 $val = ''; 7157 } 7158 } 7159 elsif (defined(${$self->{'default'} }{$_}{'default'})) 7160 { 7161 $val = ${$self->{'default'} }{$_}{'default'}; 7162 } 7163 else 7164 { 7165 $val = ''; 7166 } 7167 $line .= "$val "; 7168 $line .= ' ' x ($optwidth + $typewidth + $defaultwidth + 1 - length($line)); 7169 7170 if (defined(${$self -> {'default'} }{$_}{'verbose'}) && 7171 ${$self -> {'default'} }{$_}{'verbose'} ne '') 7172 { 7173 $help = "${$self->{'default'} }{$_}{'verbose'}"; 7174 } 7175 else 7176 { 7177 $help = ' '; 7178 } 7179 if ((length("$line") + length($help)) < $maxlinewidth) 7180 { 7181 print $line , $help, "\n"; 7182 } 7183 else 7184 { 7185 print $line, "\n", ' ' x $valind, $help, "\n"; 7186 } 7187 for $val (sort byOrder keys(%{${$self->{'default'}}{$option}{'values'}})) 7188 { 7189 print ' ' x ($valind + 2); 7190 print $val, ' ', ' ' x ($valwidth - length($val) - 2); 7191 print ${$self->{'default'}}{$option}{'values'}{$val}, "\n"; 7192 } 7193 } 7194 7195 print <<EOT; 7196Note: 'Options' may be abbreviated. 'Type' specifications mean: 7197 <none>| ! no argument: variable is set to 1 on -foo (or, to 0 on -nofoo) 7198 =s | :s mandatory (or, optional) string argument 7199 =i | :i mandatory (or, optional) integer argument 7200EOT 7201} # End of helpOptions. 7202 7203#------------------------------------------------------------------- 7204 7205sub new 7206{ 7207 my($class) = @_; 7208 my($self) = {}; 7209 $self -> {'default'} = {}; 7210 $self -> {'helpText'} = ''; 7211 $self -> {'opt'} = {}; 7212 $opt = $self -> {'opt'}; # An alias for $self -> {'opt'}. 7213 $self -> {'type'} = (); 7214 7215 return bless $self, $class; 7216 7217} # End of new. 7218 7219# -------------------------------------------------------------------------- 7220 72211; 7222 7223# End MySimple.pm 7224 7225require "$ENV{T2H_HOME}/MySimple.pm" 7226 if ($0 =~ /\.pl$/ && 7227 -e "$ENV{T2H_HOME}/MySimple.pm" && -r "$ENV{T2H_HOME}/MySimple.pm"); 7228 7229#+++######################################################################## 7230# # 7231# Initialization # 7232# Pasted content of File $(srcdir)/T2h_i18n.pm: Internationalisation # 7233# # 7234#---######################################################################## 7235 7236# leave this within comments, and keep the require statement 7237# This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_i18n.pm 7238# exists. 7239 7240# @T2H_I18N@ 7241#+############################################################################## 7242# 7243# T2h_i18n.pm: Internationalization for texi2html 7244# 7245# Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>, 7246# Derek Price <derek@ximbiot.com>, 7247# Adrian Aichner <adrian@xemacs.org>, 7248# & others. 7249# 7250# This program is free software; you can redistribute it and/or modify 7251# it under the terms of the GNU General Public License as published by 7252# the Free Software Foundation; either version 2 of the License, or 7253# (at your option) any later version. 7254# 7255# This program is distributed in the hope that it will be useful, 7256# but WITHOUT ANY WARRANTY; without even the implied warranty of 7257# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7258# GNU General Public License for more details. 7259# 7260# You should have received a copy of the GNU General Public License 7261# along with this program; if not, write to the Free Software 7262# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 7263# 7264#-############################################################################## 7265 7266# This requires perl version 5 or higher 7267require 5.0; 7268 7269package Texi2HTML::I18n; 7270 7271use strict; 7272 7273use vars qw( 7274@ISA 7275@EXPORT 7276); 7277 7278use Exporter; 7279@ISA = qw(Exporter); 7280@EXPORT = qw(pretty_date); 7281 7282my $language; 7283my $i18n_dir = 'i18n'; # name of the directory containing the per language files 7284#my $translation_file = 'translations.pl'; # file containing all the translations 7285#my @known_languages = ('de', 'nl', 'es', 'no', 'pt', 'fr'); # The supported 7286 # languages 7287 7288######################################################################## 7289# Language dependencies: 7290# To add a new language extend the WORDS hash and create $T2H_<...>_WORDS hash 7291# To redefine one word, simply do: 7292# $T2h_i18n::T2H_LANGUAGES->{<language>}->{<word>} = 'whatever' in your personal init file. 7293# 7294 7295# Those hashes are obsolete but retained here for reference 7296 7297my $T2H_WORDS_EN = 7298{ 7299 # titles of pages 7300 #'Table of Contents' => 'Table of Contents', 7301 #'Short Table of Contents' => 'Short Table of Contents', 7302 #'Index' => 'Index', 7303 #'About This Document' => 'About This Document', 7304 #'Footnotes' => 'Footnotes', 7305 #'See' => 'See', 7306 #'see' => 'see', 7307 #'section' => 'section', 7308 'About This Document' => '', 7309 'Table of Contents' => '', 7310 'Short Table of Contents', => '', 7311 'Index' => '', 7312 'Footnotes' => '', 7313 'See' => '', 7314 'see' => '', 7315 'section' => '', 7316 'Top' => '', 7317 'Untitled Document' => '', 7318 # If necessary, we could extend this as follows: 7319 # # text for buttons 7320 # 'Top_Button' => 'Top', 7321 # 'ToC_Button' => 'Contents', 7322 # 'Overview_Button' => 'Overview', 7323 # 'Index_button' => 'Index', 7324 # 'Back_Button' => 'Back', 7325 # 'FastBack_Button' => 'FastBack', 7326 # 'Prev_Button' => 'Prev', 7327 # 'Up_Button' => 'Up', 7328 # 'Next_Button' => 'Next', 7329 # 'Forward_Button' =>'Forward', 7330 # 'FastWorward_Button' => 'FastForward', 7331 # 'First_Button' => 'First', 7332 # 'Last_Button' => 'Last', 7333 # 'About_Button' => 'About' 7334 'January' => '', 7335 'February' => '', 7336 'March' => '', 7337 'April' => '', 7338 'May' => '', 7339 'June' => '', 7340 'July' => '', 7341 'August' => '', 7342 'September' => '', 7343 'October' => '', 7344 'November' => '', 7345 'December' => '', 7346 'T2H_today' => '%s, %d %d', 7347}; 7348 7349my $T2H_WORDS_DE = 7350{ 7351 'Table of Contents' => 'Inhaltsverzeichniss', 7352 'Short Table of Contents' => 'Kurzes Inhaltsverzeichniss', 7353 'Index' => 'Index', 7354 'About This Document' => 'Über dieses Dokument', 7355 'Footnotes' => 'Fußnoten', 7356 'See' => 'Siehe', 7357 'see' => 'siehe', 7358 'section' => 'Abschnitt', 7359 'January' => 'Januar', 7360 'February' => 'Februar', 7361 'March' => 'März', 7362 'April' => 'April', 7363 'May' => 'Mai', 7364 'June' => 'Juni', 7365 'July' => 'Juli', 7366 'August' => 'August', 7367 'September' => 'September', 7368 'October' => 'Oktober', 7369 'November' => 'November', 7370 'December' => 'Dezember', 7371}; 7372 7373my $T2H_WORDS_NL = 7374{ 7375 'Table of Contents' => 'Inhoudsopgave', 7376 'Short Table of Contents' => 'Korte inhoudsopgave', 7377 'Index' => 'Index', #Not sure ;-) 7378 'About This Document' => 'No translation available!', #No translation available! 7379 'Footnotes' => 'No translation available!', #No translation available! 7380 'See' => 'Zie', 7381 'see' => 'zie', 7382 'section' => 'sectie', 7383 'January' => 'Januari', 7384 'February' => 'Februari', 7385 'March' => 'Maart', 7386 'April' => 'April', 7387 'May' => 'Mei', 7388 'June' => 'Juni', 7389 'July' => 'Juli', 7390 'August' => 'Augustus', 7391 'September' => 'September', 7392 'October' => 'Oktober', 7393 'November' => 'November', 7394 'December' => 'December', 7395}; 7396 7397my $T2H_WORDS_ES = 7398{ 7399 'Table of Contents' => 'índice General', 7400 'Short Table of Contents' => 'Resumen del Contenido', 7401 'Index' => 'Index', #Not sure ;-) 7402 'About This Document' => 'No translation available!', #No translation available! 7403 'Footnotes' => 'Fußnoten', 7404 'See' => 'Véase', 7405 'see' => 'véase', 7406 'section' => 'sección', 7407 'January' => 'enero', 7408 'February' => 'febrero', 7409 'March' => 'marzo', 7410 'April' => 'abril', 7411 'May' => 'mayo', 7412 'June' => 'junio', 7413 'July' => 'julio', 7414 'August' => 'agosto', 7415 'September' => 'septiembre', 7416 'October' => 'octubre', 7417 'November' => 'noviembre', 7418 'December' => 'diciembre', 7419}; 7420 7421my $T2H_WORDS_NO = 7422{ 7423 'Table of Contents' => 'Innholdsfortegnelse', 7424 'Short Table of Contents' => 'Kort innholdsfortegnelse', 7425 'Index' => 'Indeks', #Not sure ;-) 7426 'About This Document' => 'No translation available!', #No translation available! 7427 'Footnotes' => 'No translation available!', 7428 'See' => 'Se', 7429 'see' => 'se', 7430 'section' => 'avsnitt', 7431 'January' => 'januar', 7432 'February' => 'februar', 7433 'March' => 'mars', 7434 'April' => 'april', 7435 'May' => 'mai', 7436 'June' => 'juni', 7437 'July' => 'juli', 7438 'August' => 'august', 7439 'September' => 'september', 7440 'October' => 'oktober', 7441 'November' => 'november', 7442 'December' => 'desember', 7443}; 7444 7445my $T2H_WORDS_PT = 7446{ 7447 'Table of Contents' => 'Sumário', 7448 'Short Table of Contents' => 'Breve Sumário', 7449 'Index' => 'Índice', #Not sure ;-) 7450 'About This Document' => 'No translation available!', #No translation available! 7451 'Footnotes' => 'No translation available!', 7452 'See' => 'Veja', 7453 'see' => 'veja', 7454 'section' => 'Seção', 7455 'January' => 'Janeiro', 7456 'February' => 'Fevereiro', 7457 'March' => 'Março', 7458 'April' => 'Abril', 7459 'May' => 'Maio', 7460 'June' => 'Junho', 7461 'July' => 'Julho', 7462 'August' => 'Agosto', 7463 'September' => 'Setembro', 7464 'October' => 'Outubro', 7465 'November' => 'Novembro', 7466 'December' => 'Dezembro', 7467}; 7468 7469my $T2H_WORDS_FR = 7470{ 7471 'Table of Contents' => 'Table des matières', 7472 'Short Table of Contents' => 'Résumée du contenu', 7473 'Index' => 'Index', 7474 'About This Document' => 'A propos de ce document', 7475 'Footnotes' => 'Notes de bas de page', 7476 'See' => 'Voir', 7477 'see' => 'voir', 7478 'section' => 'section', 7479 'January' => 'Janvier', 7480 'February' => 'Février', 7481 'March' => 'Mars', 7482 'April' => 'Avril', 7483 'May' => 'Mai', 7484 'June' => 'Juin', 7485 'July' => 'Juillet', 7486 'August' => 'Août', 7487 'September' => 'Septembre', 7488 'October' => 'Octobre', 7489 'November' => 'Novembre', 7490 'December' => 'Décembre', 7491 'T2H_today' => 'le %2$d %1$s %3$d' 7492}; 7493 7494#$T2H_LANGUAGES = 7495#{ 7496# 'en' => $T2H_WORDS_EN, 7497# 'de' => $T2H_WORDS_DE, 7498# 'nl' => $T2H_WORDS_NL, 7499# 'es' => $T2H_WORDS_ES, 7500# 'no' => $T2H_WORDS_NO, 7501# 'pt' => $T2H_WORDS_PT, 7502# 'fr' => $T2H_WORDS_FR, 7503#}; 7504 7505sub set_language($) 7506{ 7507 my $lang = shift; 7508 if (defined($lang) && exists($Texi2HTML::Config::LANGUAGES->{$lang}) && defined($Texi2HTML::Config::LANGUAGES->{$lang})) 7509 { 7510 $language = $lang; 7511 return 1; 7512 } 7513 else 7514 { 7515 return 0; 7516 } 7517} 7518 7519 7520my @MONTH_NAMES = 7521 ( 7522 'January', 'February', 'March', 'April', 'May', 7523 'June', 'July', 'August', 'September', 'October', 7524 'November', 'December' 7525 ); 7526 7527my $I = \&get_string; 7528 7529sub pretty_date($) 7530{ 7531 my $lang = shift; 7532 my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); 7533 7534 ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); 7535 $year += ($year < 70) ? 2000 : 1900; 7536 # obachman: Let's do it as the Americans do 7537 #return($MONTH_NAMES->{$lang}[$mon] . ", " . $mday . " " . $year); 7538 #return(sprintf(&$I('T2H_today'), (get_string($MONTH_NAMES[$mon]), $mday, $year))); 7539 return &$I('%{month}, %{day} %{year}', { 'month' => get_string($MONTH_NAMES[$mon]), 7540 'day' => $mday, 'year' => $year }); 7541} 7542 7543my $error_no_en = 0; 7544sub get_string($;$$) 7545{ 7546 my $string = shift; 7547 my $arguments = shift; 7548 my $state = shift; 7549 my $T2H_LANGUAGES = $Texi2HTML::Config::LANGUAGES; 7550 if (! exists($T2H_LANGUAGES->{'en'})) 7551 { 7552 unless($error_no_en) 7553 { 7554 print STDERR "i18n: no LANGUAGES->{'en'} hash\n"; 7555 $error_no_en = 1; 7556 } 7557 } 7558 else 7559 { 7560 print STDERR "i18n: missing string $string\n" unless (exists ($T2H_LANGUAGES->{'en'}->{$string})); 7561 if (defined ($T2H_LANGUAGES->{$language}->{$string}) and 7562 ($T2H_LANGUAGES->{$language}->{$string} ne '')) 7563 { 7564 $string = $T2H_LANGUAGES->{$language}->{$string}; 7565 } 7566 elsif (defined ($T2H_LANGUAGES->{'en'}->{$string}) and 7567 ($T2H_LANGUAGES->{'en'}->{$string} ne '')) 7568 { 7569 $string = $T2H_LANGUAGES->{'en'}->{$string}; 7570 } 7571 } 7572 return main::substitute_line($string, $state) unless (defined($arguments) or !keys(%$arguments)); 7573 # if there are arguments, we must protect the %{arg} constructs before 7574 # doing substitute_line. So there is a first pass here to change %{arg} 7575 # to %@{arg@} 7576 my $result = ''; 7577 if (!$state->{'keep_texi'}) 7578 { 7579 while ($string) 7580 { 7581 if ($string =~ s/^([^%]*)%//) 7582 { 7583 $result .= $1 if (defined($1)); 7584 $result .= '%'; 7585 if ($string =~ s/^%//) 7586 { 7587 $result .= '%'; 7588 } 7589 elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1})) 7590 { 7591 $string =~ s/^\{(\w+)\}//; 7592 $result .= "\@\{$1\@\}"; 7593 } 7594 else 7595 { 7596 $result .= '%'; 7597 } 7598 next; 7599 } 7600 else 7601 { 7602 $result .= $string; 7603 last; 7604 } 7605 } 7606 $string = main::substitute_line($result, $state); 7607 } 7608 # now we substitute the arguments 7609 $result = ''; 7610 while ($string) 7611 { 7612 if ($string =~ s/^([^%]*)%//) 7613 { 7614 $result .= $1 if (defined($1)); 7615 if ($string =~ s/^%//) 7616 { 7617 $result .= '%'; 7618 } 7619 elsif ($string =~ /^\{(\w+)\}/ and exists($arguments->{$1})) 7620 { 7621 $string =~ s/^\{(\w+)\}//; 7622 $result .= $arguments->{$1}; 7623 } 7624 else 7625 { 7626 $result .= '%'; 7627 } 7628 next; 7629 } 7630 else 7631 { 7632 $result .= $string; 7633 last; 7634 } 7635 } 7636 return $result; 7637} 7638 76391; 7640require "$ENV{T2H_HOME}/T2h_i18n.pm" 7641 if ($0 =~ /\.pl$/ && 7642 -e "$ENV{T2H_HOME}/T2h_i18n.pm" && -r "$ENV{T2H_HOME}/T2h_i18n.pm"); 7643 7644 7645######################################################################### 7646# 7647# latex2html stuff 7648# 7649#---###################################################################### 7650 7651{ 7652# leave this within comments, and keep the require statement 7653# This way, you can directly run texi2html.pl, if $ENV{T2H_HOME}/T2h_l2h.pm 7654# exists. 7655 7656# @T2H_L2H@ 7657#+############################################################################## 7658# 7659# T2h_l2h.pm: interface to LaTeX2HTML 7660# 7661# Copyright (C) 1999-2005 Patrice Dumas <dumas@centre-cired.fr>, 7662# Derek Price <derek@ximbiot.com>, 7663# Adrian Aichner <adrian@xemacs.org>, 7664# & others. 7665# 7666# This program is free software; you can redistribute it and/or modify 7667# it under the terms of the GNU General Public License as published by 7668# the Free Software Foundation; either version 2 of the License, or 7669# (at your option) any later version. 7670# 7671# This program is distributed in the hope that it will be useful, 7672# but WITHOUT ANY WARRANTY; without even the implied warranty of 7673# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7674# GNU General Public License for more details. 7675# 7676# You should have received a copy of the GNU General Public License 7677# along with this program; if not, write to the Free Software 7678# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 7679# 02110-1301 USA 7680# 7681#-############################################################################## 7682 7683require 5.0; 7684use strict; 7685 7686package Texi2HTML::LaTeX2HTML; 7687use Cwd; 7688 7689 7690# latex2html conversions consist of three stages: 7691# 1) ToLatex: Put "latex" code into a latex file 7692# 2) ToHtml: Use latex2html to generate corresponding html code and images 7693# 3) FromHtml: Extract generated code and images from latex2html run 7694# 7695 7696# init l2h defaults for files and names 7697 7698# global variable used for caching 7699use vars qw( 7700 %l2h_cache 7701 ); 7702 7703my ($l2h_name, $l2h_latex_file, $l2h_cache_file, $l2h_html_file, $l2h_prefix); 7704 7705# holds the status of latex2html operations. If 0 it means that there was 7706# an error 7707my $status = 0; 7708 7709my $debug; 7710my $verbose; 7711my $docu_rdir; 7712my $docu_name; 7713my $docu_ext; 7714my $ERROR = '***'; 7715 7716########################## 7717# 7718# First stage: Generation of Latex file 7719# Initialize with: init 7720# Add content with: to_latex ($text) --> HTML placeholder comment 7721# Finish with: finish_to_latex 7722# 7723 7724my $l2h_latex_preamble = <<EOT; 7725% This document was automatically generated by the l2h extenstion of texi2html 7726% DO NOT EDIT !!! 7727\\documentclass{article} 7728\\usepackage{html} 7729\\begin{document} 7730EOT 7731 7732my $l2h_latex_closing = <<EOT; 7733\\end{document} 7734EOT 7735 7736my %l2h_to_latex = (); # associate a latex text with the index in the 7737 # html result array. 7738my @l2h_to_latex = (); # array used to associate the index with 7739 # the original latex text. 7740my $latex_count = 0; # number of latex texts really stored 7741my $latex_converted_count = 0; # number of latex texts passed through latex2html 7742my $to_latex_count = 0; # total number of latex texts processed 7743my $cached_count = 0; # number of cached latex texts 7744%l2h_cache = (); # the cache hash. Associate latex text with 7745 # html from the previous run 7746my @l2h_from_html; # array of resulting html 7747 7748my %global_count = (); # associate a command name and the 7749 # corresponding counter to the index in the 7750 # html result array 7751 7752# set $status to 1, if l2h could be initalized properly, to 0 otherwise 7753sub init() 7754{ 7755 $docu_name = $Texi2HTML::THISDOC{'file_base_name'}; 7756 $docu_rdir = $Texi2HTML::THISDOC{'out_dir'}; 7757 $docu_ext = $Texi2HTML::THISDOC{'extension'}; 7758 $l2h_name = "${docu_name}_l2h"; 7759 $l2h_latex_file = "$docu_rdir${l2h_name}.tex"; 7760 $l2h_cache_file = "${docu_rdir}${docu_name}-l2h_cache.pm"; 7761 # destination dir -- generated images are put there, should be the same 7762 # as dir of enclosing html document -- 7763 $l2h_html_file = "$docu_rdir${l2h_name}.html"; 7764 $l2h_prefix = "${l2h_name}_"; 7765 $debug = $Texi2HTML::THISDOC{'debug_l2h'}; 7766 $verbose = $Texi2HTML::Config::VERBOSE; 7767 7768 unless ($Texi2HTML::Config::L2H_SKIP) 7769 { 7770 unless (open(L2H_LATEX, ">$l2h_latex_file")) 7771 { 7772 warn "$ERROR l2h: Can't open latex file '$l2h_latex_file' for writing: $!\n"; 7773 $status = 0; 7774 return; 7775 } 7776 warn "# l2h: use ${l2h_latex_file} as latex file\n" if ($verbose); 7777 print L2H_LATEX $l2h_latex_preamble; 7778 } 7779 # open the database that holds cached text 7780 init_cache(); 7781 $status = 1; 7782} 7783 7784 7785# print text (2nd arg) into latex file (if not already there nor in cache) 7786# which can be later on replaced by the latex2html generated text. 7787# 7788sub to_latex($$$) 7789{ 7790 my $command = shift; 7791 my $text = shift; 7792 my $counter = shift; 7793 if ($command eq 'tex') 7794 { 7795 $text .= ' '; 7796 } 7797 elsif ($command eq 'math') 7798 { 7799 $text = "\$".$text."\$"; 7800 } 7801 $to_latex_count++; 7802 $text =~ s/(\s*)$//; 7803 # try whether we have text already on things to do 7804 my $count = $l2h_to_latex{$text}; 7805 unless ($count) 7806 { 7807 $latex_count++; 7808 $count = $latex_count; 7809 # try whether we can get it from cache 7810 my $cached_text = from_cache($text); 7811 if (defined($cached_text)) 7812 { 7813 $cached_count++; 7814 # put the cached result in the html result array 7815 $l2h_from_html[$count] = $cached_text; 7816 } 7817 else 7818 { 7819 $latex_converted_count++; 7820 unless ($Texi2HTML::Config::L2H_SKIP) 7821 { 7822 print L2H_LATEX "\\begin{rawhtml}\n"; 7823 print L2H_LATEX "<!-- l2h_begin $l2h_name $count -->\n"; 7824 print L2H_LATEX "\\end{rawhtml}\n"; 7825 7826 print L2H_LATEX "$text\n"; 7827 7828 print L2H_LATEX "\\begin{rawhtml}\n"; 7829 print L2H_LATEX "<!-- l2h_end $l2h_name $count -->\n"; 7830 print L2H_LATEX "\\end{rawhtml}\n"; 7831 } 7832 } 7833 $l2h_to_latex[$count] = $text; 7834 $l2h_to_latex{$text} = $count; 7835 } 7836 $global_count{"${command}_$counter"} = $count; 7837 return 1; 7838} 7839 7840# print closing into latex file and close it 7841sub finish_to_latex() 7842{ 7843 my $reused = $to_latex_count - $latex_converted_count - $cached_count; 7844 unless ($Texi2HTML::Config::L2H_SKIP) 7845 { 7846 print L2H_LATEX $l2h_latex_closing; 7847 close (L2H_LATEX); 7848 } 7849 warn "# l2h: finished to latex ($cached_count cached, $reused reused, $latex_converted_count to process)\n" if ($verbose); 7850 unless ($latex_count) 7851 { 7852 # no @tex nor @math 7853 finish(); 7854 return 0; 7855 } 7856 return 1; 7857} 7858 7859################################### 7860# Second stage: Use latex2html to generate corresponding html code and images 7861# 7862# to_html([$l2h_latex_file, [$l2h_html_dir]]): 7863# Call latex2html on $l2h_latex_file 7864# Put images (prefixed with $l2h_name."_") and html file(s) in $l2h_html_dir 7865# Return 1, on success 7866# 0, otherwise 7867# 7868sub to_html() 7869{ 7870 my ($call, $dotbug); 7871 # when there are no tex constructs to convert (happens in case everything 7872 # comes from the cache), there is no latex2html run 7873 if ($Texi2HTML::Config::L2H_SKIP or ($latex_converted_count == 0)) 7874 { 7875 warn "# l2h: skipping latex2html run\n" if ($verbose); 7876 return 1; 7877 } 7878 # Check for dot in directory where dvips will work 7879 if ($Texi2HTML::Config::L2H_TMP) 7880 { 7881 if ($Texi2HTML::Config::L2H_TMP =~ /\./) 7882 { 7883 warn "$ERROR Warning l2h: l2h_tmp dir contains a dot. Use /tmp, instead\n"; 7884 $dotbug = 1; 7885 } 7886 } 7887 else 7888 { 7889 if (cwd() =~ /\./) 7890 { 7891 warn "$ERROR Warning l2h: current dir contains a dot. Use /tmp as l2h_tmp dir \n"; 7892 $dotbug = 1; 7893 } 7894 } 7895 # fix it, if necessary and hope that it works 7896 $Texi2HTML::Config::L2H_TMP = "/tmp" if ($dotbug); 7897 7898 $call = $Texi2HTML::Config::L2H_L2H; 7899 # use init file, if specified 7900 my $init_file = main::locate_init_file($Texi2HTML::Config::L2H_FILE); 7901 $call = $call . " -init_file " . $init_file if ($init_file); 7902 # set output dir 7903 $call .= ($docu_rdir ? " -dir $docu_rdir" : " -no_subdir"); 7904 # use l2h_tmp, if specified 7905 $call .= " -tmp $Texi2HTML::Config::L2H_TMP" if ($Texi2HTML::Config::L2H_TMP); 7906 # use a given html version if specified 7907 $call .= " -html_version $Texi2HTML::Config::L2H_HTML_VERSION" if ($Texi2HTML::Config::L2H_HTML_VERSION); 7908 # options we want to be sure of 7909 $call .= " -address 0 -info 0 -split 0 -no_navigation -no_auto_link"; 7910 $call .= " -prefix $l2h_prefix $l2h_latex_file"; 7911 7912 warn "# l2h: executing '$call'\n" if ($verbose); 7913 if (system($call)) 7914 { 7915 warn "$ERROR l2h: '${call}' did not succeed\n"; 7916 return 0; 7917 } 7918 else 7919 { 7920 warn "# l2h: latex2html finished successfully\n" if ($verbose); 7921 return 1; 7922 } 7923} 7924 7925########################## 7926# Third stage: Extract generated contents from latex2html run 7927# Initialize with: init_from_html 7928# open $l2h_html_file for reading 7929# reads in contents into array indexed by numbers 7930# return 1, on success -- 0, otherwise 7931# Finish with: finish 7932# closes $l2h_html_dir/$l2h_name.".$docu_ext" 7933 7934# the images generated by latex2html have names like ${docu_name}_l2h_img?.png 7935# they are copied to ${docu_name}_?.png, and html is changed accordingly. 7936my %l2h_img; # associate src file to destination file 7937 # such that files are not copied twice 7938my $image_count = 1; 7939sub change_image_file_names($) 7940{ 7941 my $content = shift; 7942 my @images = ($content =~ /SRC="(.*?)"/g); 7943 my ($src, $dest); 7944 7945 for $src (@images) 7946 { 7947 $dest = $l2h_img{$src}; 7948 unless ($dest) 7949 { 7950 my $ext = ''; 7951 if ($src =~ /.*\.(.*)$/ && $1 ne $docu_ext) 7952 { 7953 $ext = ".$1"; 7954 } 7955 else 7956 { 7957 warn "$ERROR: L2h image $src has invalid extension\n"; 7958 next; 7959 } 7960 while (-e "$docu_rdir${docu_name}_${image_count}$ext") 7961 { 7962 $image_count++; 7963 } 7964 $dest = "${docu_name}_${image_count}$ext"; 7965# FIXME this isn't portable. + error condition not checked. 7966 system("cp -f $docu_rdir$src $docu_rdir$dest"); 7967 $l2h_img{$src} = $dest; 7968# FIXME error condition not checked 7969 unlink "$docu_rdir$src" unless ($debug); 7970 } 7971 $content =~ s/SRC="$src"/SRC="$dest"/g; 7972 } 7973 return $content; 7974} 7975 7976my $extract_error_count = 0; 7977my $invalid_counter_count = 0; 7978 7979sub init_from_html() 7980{ 7981 # when there are no tex constructs to convert (happens in case everything 7982 # comes from the cache), the html file that was generated by previous 7983 # latex2html runs isn't reused. 7984 if ($latex_converted_count == 0) 7985 { 7986 return 1; 7987 } 7988 7989 if (! open(L2H_HTML, "<$l2h_html_file")) 7990 { 7991 warn "$ERROR l2h: Can't open $l2h_html_file for reading\n"; 7992 return 0; 7993 } 7994 warn "# l2h: use $l2h_html_file as html file\n" if ($verbose); 7995 7996 my $html_converted_count = 0; # number of html resulting texts 7997 # retrieved in the file 7998 7999 my ($count, $h_line); 8000 while ($h_line = <L2H_HTML>) 8001 { 8002 if ($h_line =~ /^<!-- l2h_begin $l2h_name ([0-9]+) -->/) 8003 { 8004 $count = $1; 8005 my $h_content = ''; 8006 my $h_end_found = 0; 8007 while ($h_line = <L2H_HTML>) 8008 { 8009 if ($h_line =~ /^<!-- l2h_end $l2h_name $count -->/) 8010 { 8011 $h_end_found = 1; 8012 chomp $h_content; 8013 chomp $h_content; 8014 $html_converted_count++; 8015 # transform image file names and copy image files 8016 $h_content = change_image_file_names($h_content); 8017 # store result in the html result array 8018 $l2h_from_html[$count] = $h_content; 8019 # also add the result in cache hash 8020 $l2h_cache{$l2h_to_latex[$count]} = $h_content; 8021 last; 8022 } 8023 $h_content = $h_content.$h_line; 8024 } 8025 unless ($h_end_found) 8026 { # couldn't found the closing comment. Certainly a bug. 8027 warn "$ERROR l2h(BUG): l2h_end $l2h_name $count not found\n"; 8028 close(L2H_HTML); 8029 return 0; 8030 } 8031 } 8032 } 8033 8034 # Not the same number of converted elements and retrieved elements 8035 if ($latex_converted_count != $html_converted_count) 8036 { 8037 warn "$ERROR l2h(BUG): waiting for $latex_converted_count elements found $html_converted_count\n"; 8038 } 8039 8040 warn "# l2h: Got $html_converted_count of $latex_count html contents\n" 8041 if ($verbose); 8042 8043 close(L2H_HTML); 8044 return 1; 8045} 8046 8047my $html_output_count = 0; # html text outputed in html result file 8048 8049# called each time a construct handled by latex2html is encountered, should 8050# output the corresponding html 8051sub do_tex($$$$) 8052{ 8053 my $style = shift; 8054 my $counter = shift; 8055 my $state = shift; 8056 my $count = $global_count{"${style}_$counter"}; 8057 ################################## begin debug section (incorrect counts) 8058 if (!defined($count)) 8059 { 8060 # counter is undefined 8061 $invalid_counter_count++; 8062 warn "$ERROR l2h(BUG): undefined count for ${style}_$counter\n"; 8063 return ("<!-- l2h: ". __LINE__ . " undef count for ${style}_$counter -->") 8064 if ($debug); 8065 return ''; 8066 } 8067 elsif(($count <= 0) or ($count > $latex_count)) 8068 { 8069 # counter out of range 8070 $invalid_counter_count++; 8071 warn "$ERROR l2h(BUG): Request of $count content which is out of valide range [0,$latex_count)\n"; 8072 return ("<!-- l2h: ". __LINE__ . " out of range count $count -->") 8073 if ($debug); 8074 return ''; 8075 } 8076 ################################## end debug section (incorrect counts) 8077 8078 # this seems to be a valid counter 8079 my $result = ''; 8080 $result = "<!-- l2h_begin $l2h_name $count -->" if ($debug); 8081 if (defined($l2h_from_html[$count])) 8082 { 8083 $html_output_count++; 8084 # maybe we could also have something if simple_format 8085 # with Texi2HTML::Config::protect_text, once simple_format 8086 # may happen for anything else than lines 8087 if ($state->{'remove_texi'}) 8088 {# don't protect anything 8089 $result .= $l2h_to_latex[$count]; 8090 } 8091 else 8092 { 8093 $result .= $l2h_from_html[$count]; 8094 } 8095 } 8096 else 8097 { 8098 # if the result is not in @l2h_from_html, there is an error somewhere. 8099 $extract_error_count++; 8100 warn "$ERROR l2h(BUG): can't extract content $count from html\n"; 8101 # try simple (ordinary) substitution (without l2h) 8102 $result .= "<!-- l2h: ". __LINE__ . " use texi2html -->" if ($debug); 8103 $result .= main::substitute_text({}, $l2h_to_latex[$count]); 8104 } 8105 $result .= "<!-- l2h_end $l2h_name $count -->" if ($debug); 8106 return $result; 8107} 8108 8109# store results in the cache and remove temporary files. 8110sub finish() 8111{ 8112 return unless($status); 8113 if ($verbose) 8114 { 8115 if ($extract_error_count + $invalid_counter_count) 8116 { 8117 warn "# l2h: finished from html ($extract_error_count extract and $invalid_counter_count invalid counter errors)\n"; 8118 } 8119 else 8120 { 8121 warn "# l2h: finished from html (no error)\n"; 8122 } 8123 if ($html_output_count != $latex_converted_count) 8124 { # this may happen if @-commands are collected at some places 8125 # but @-command at those places are not expanded later. For 8126 # example @math on @multitable lines. 8127 warn "# l2h: $html_output_count html outputed for $latex_converted_count converted\n"; 8128 } 8129 } 8130 store_cache(); 8131 if ($Texi2HTML::Config::L2H_CLEAN) 8132 { 8133 local ($_); 8134 warn "# l2h: removing temporary files generated by l2h extension\n" 8135 if $verbose; 8136 while (<"$docu_rdir$l2h_name"*>) 8137 { 8138# FIXME error condition not checked 8139 unlink $_; 8140 } 8141 } 8142 warn "# l2h: Finished\n" if $verbose; 8143 return 1; 8144} 8145 8146# the driver of end of first pass, second pass and beginning of third pass 8147# 8148sub latex2html() 8149{ 8150 return unless($status); 8151 return unless ($status = finish_to_latex()); 8152 return unless ($status = to_html()); 8153 return unless ($status = init_from_html()); 8154} 8155 8156 8157############################## 8158# stuff for l2h caching 8159# 8160 8161# I tried doing this with a dbm data base, but it did not store all 8162# keys/values. Hence, I did as latex2html does it 8163sub init_cache 8164{ 8165 if (-r "$l2h_cache_file") 8166 { 8167 my $rdo = do "$l2h_cache_file"; 8168 warn("$ERROR l2h Error: could not load $docu_rdir$l2h_cache_file: $@\n") 8169 unless ($rdo); 8170 } 8171} 8172 8173# store all the text obtained through latex2html 8174sub store_cache 8175{ 8176 return unless $latex_count; 8177 my ($key, $value); 8178 unless (open(FH, ">$l2h_cache_file")) 8179 { 8180 warn "$ERROR l2h Error: could not open $docu_rdir$l2h_cache_file for writing: $!\n"; 8181 return; 8182 } 8183 while (($key, $value) = each %l2h_cache) 8184 { 8185 # escape stuff 8186 $key =~ s|/|\\/|g; 8187 $key =~ s|\\\\/|\\/|g; 8188 # weird, a \ at the end of the key results in an error 8189 # maybe this also broke the dbm database stuff 8190 $key =~ s|\\$|\\\\|; 8191 $value =~ s/\|/\\\|/go; 8192 $value =~ s/\\\\\|/\\\|/go; 8193 $value =~ s|\\\\|\\\\\\\\|g; 8194 print FH "\n\$l2h_cache_key = q/$key/;\n"; 8195 print FH "\$l2h_cache{\$l2h_cache_key} = q|$value|;\n"; 8196 } 8197 print FH "1;"; 8198 close (FH); 8199} 8200 8201# return cached html, if it exists for text, and if all pictures 8202# are there, as well 8203sub from_cache($) 8204{ 8205 my $text = shift; 8206 my $cached = $l2h_cache{$text}; 8207 if (defined($cached)) 8208 { 8209 while ($cached =~ m/SRC="(.*?)"/g) 8210 { 8211 unless (-e "$docu_rdir$1") 8212 { 8213 return undef; 8214 } 8215 } 8216 return $cached; 8217 } 8218 return undef; 8219} 8220 82211; 8222 8223 8224require "$ENV{T2H_HOME}/T2h_l2h.pm" 8225 if ($0 =~ /\.pl$/ && 8226 -e "$ENV{T2H_HOME}/T2h_l2h.pm" && -r "$ENV{T2H_HOME}/T2h_l2h.pm"); 8227 8228} 8229 8230{ 8231package Texi2HTML::LaTeX2HTML::Config; 8232 8233# latex2html variables 8234# These variables are not used. They are here for information only, and 8235# an example of config file for latex2html file is included. 8236my $ADDRESS; 8237my $ANTI_ALIAS; 8238my $ANTI_ALIAS_TEXT; 8239my $ASCII_MODE; 8240my $AUTO_LINK; 8241my $AUTO_PREFIX; 8242my $CHILDLINE; 8243my $DEBUG; 8244my $DESTDIR; 8245my $ERROR; 8246my $EXTERNAL_FILE; 8247my $EXTERNAL_IMAGES; 8248my $EXTERNAL_UP_LINK; 8249my $EXTERNAL_UP_TITLE; 8250my $FIGURE_SCALE_FACTOR; 8251my $HTML_VERSION; 8252my $IMAGES_ONLY; 8253my $INFO; 8254my $LINE_WIDTH; 8255my $LOCAL_ICONS; 8256my $LONG_TITLES; 8257my $MATH_SCALE_FACTOR; 8258my $MAX_LINK_DEPTH; 8259my $MAX_SPLIT_DEPTH; 8260my $NETSCAPE_HTML; 8261my $NOLATEX; 8262my $NO_FOOTNODE; 8263my $NO_IMAGES; 8264my $NO_NAVIGATION; 8265my $NO_SIMPLE_MATH; 8266my $NO_SUBDIR; 8267my $PAPERSIZE; 8268my $PREFIX; 8269my $PS_IMAGES; 8270my $REUSE; 8271my $SCALABLE_FONTS; 8272my $SHORTEXTN; 8273my $SHORT_INDEX; 8274my $SHOW_SECTION_NUMBERS; 8275my $SPLIT; 8276my $TEXDEFS; 8277my $TITLE; 8278my $TITLES_LANGUAGE; 8279my $TMP; 8280my $VERBOSE; 8281my $WORDS_IN_NAVIGATION_PANEL_TITLES; 8282my $WORDS_IN_PAGE; 8283 8284# @T2H_L2H_INIT@ 8285 8286###################################################################### 8287# from here on, its l2h init stuff 8288# 8289 8290## initialization for latex2html as for Singular manual generation 8291## obachman 3/99 8292 8293# 8294# Options controlling Titles, File-Names, Tracing and Sectioning 8295# 8296$TITLE = ''; 8297 8298$SHORTEXTN = 0; 8299 8300$LONG_TITLES = 0; 8301 8302$DESTDIR = ''; 8303 8304$NO_SUBDIR = 1; 8305 8306$PREFIX = ''; 8307 8308$AUTO_PREFIX = 0; 8309 8310$AUTO_LINK = 0; 8311 8312$SPLIT = 0; 8313 8314$MAX_LINK_DEPTH = 0; 8315 8316$TMP = ''; 8317 8318$DEBUG = 0; 8319 8320$VERBOSE = 1; 8321 8322# 8323# Options controlling Extensions and Special Features 8324# 8325#$HTML_VERSION = "3.2"; # set by command line 8326 8327$TEXDEFS = 1; # we absolutely need that 8328 8329$EXTERNAL_FILE = ''; 8330 8331$SCALABLE_FONTS = 1; 8332 8333$NO_SIMPLE_MATH = 1; 8334 8335$LOCAL_ICONS = 1; 8336 8337$SHORT_INDEX = 0; 8338 8339$NO_FOOTNODE = 1; 8340 8341$ADDRESS = ''; 8342 8343$INFO = ''; 8344 8345# 8346# Switches controlling Image Generation 8347# 8348$ASCII_MODE = 0; 8349 8350$NOLATEX = 0; 8351 8352$EXTERNAL_IMAGES = 0; 8353 8354$PS_IMAGES = 0; 8355 8356$NO_IMAGES = 0; 8357 8358$IMAGES_ONLY = 0; 8359 8360$REUSE = 2; 8361 8362$ANTI_ALIAS = 1; 8363 8364$ANTI_ALIAS_TEXT = 1; 8365 8366# 8367#Switches controlling Navigation Panels 8368# 8369$NO_NAVIGATION = 1; 8370$ADDRESS = ''; 8371$INFO = 0; # 0 = do not make a "About this document..." section 8372 8373# 8374#Switches for Linking to other documents 8375# 8376# currently -- we don't care 8377 8378$MAX_SPLIT_DEPTH = 0; # Stop making separate files at this depth 8379 8380$MAX_LINK_DEPTH = 0; # Stop showing child nodes at this depth 8381 8382$NOLATEX = 0; # 1 = do not pass unknown environments to Latex 8383 8384$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document 8385 8386$ASCII_MODE = 0; # 1 = do not use any icons or internal images 8387 8388# 1 = use links to external postscript images rather than inlined bitmap 8389# images. 8390$PS_IMAGES = 0; 8391$SHOW_SECTION_NUMBERS = 0; 8392 8393### Other global variables ############################################### 8394$CHILDLINE = ""; 8395 8396# This is the line width measured in pixels and it is used to right justify 8397# equations and equation arrays; 8398$LINE_WIDTH = 500; 8399 8400# Used in conjunction with AUTO_NAVIGATION 8401$WORDS_IN_PAGE = 300; 8402 8403# The value of this variable determines how many words to use in each 8404# title that is added to the navigation panel (see below) 8405# 8406$WORDS_IN_NAVIGATION_PANEL_TITLES = 0; 8407 8408# This number will determine the size of the equations, special characters, 8409# and anything which will be converted into an inlined image 8410# *except* "image generating environments" such as "figure", "table" 8411# or "minipage". 8412# Effective values are those greater than 0. 8413# Sensible values are between 0.1 - 4. 8414$MATH_SCALE_FACTOR = 1.5; 8415 8416# This number will determine the size of 8417# image generating environments such as "figure", "table" or "minipage". 8418# Effective values are those greater than 0. 8419# Sensible values are between 0.1 - 4. 8420$FIGURE_SCALE_FACTOR = 1.6; 8421 8422 8423# If both of the following two variables are set then the "Up" button 8424# of the navigation panel in the first node/page of a converted document 8425# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set 8426# to some text which describes this external link. 8427$EXTERNAL_UP_LINK = ""; 8428$EXTERNAL_UP_TITLE = ""; 8429 8430# If this is set then the resulting HTML will look marginally better if viewed 8431# with Netscape. 8432$NETSCAPE_HTML = 1; 8433 8434# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0" 8435# Paper sizes has no effect other than in the time it takes to create inlined 8436# images and in whether large images can be created at all ie 8437# - larger paper sizes *MAY* help with large image problems 8438# - smaller paper sizes are quicker to handle 8439$PAPERSIZE = "a4"; 8440 8441# Replace "english" with another language in order to tell LaTeX2HTML that you 8442# want some generated section titles (eg "Table of Contents" or "References") 8443# to appear in a different language. Currently only "english" and "french" 8444# is supported but it is very easy to add your own. See the example in the 8445# file "latex2html.config" 8446$TITLES_LANGUAGE = "english"; 8447 84481; # This must be the last non-comment line 8449 8450# End File l2h.init 8451###################################################################### 8452 8453} 8454 8455package main; 8456 8457# 8458# pre-defined indices 8459# 8460 8461my %index_prefix_to_name = (); 8462 8463%index_names = 8464( 8465 'cp' => { 'prefix' => ['cp','c']}, 8466 'fn' => { 'prefix' => ['fn', 'f'], code => 1}, 8467 'vr' => { 'prefix' => ['vr', 'v'], code => 1}, 8468 'ky' => { 'prefix' => ['ky', 'k'], code => 1}, 8469 'pg' => { 'prefix' => ['pg', 'p'], code => 1}, 8470 'tp' => { 'prefix' => ['tp', 't'], code => 1} 8471); 8472 8473foreach my $name(keys(%index_names)) 8474{ 8475 foreach my $prefix (@{$index_names{$name}->{'prefix'}}) 8476 { 8477 $forbidden_index_name{$prefix} = 1; 8478 $index_prefix_to_name{$prefix} = $name; 8479 } 8480} 8481 8482foreach my $other_forbidden_index_name ('info','ps','pdf','htm', 8483 'log','aux','dvi','texi','txi','texinfo','tex','bib') 8484{ 8485 $forbidden_index_name{$other_forbidden_index_name} = 1; 8486} 8487 8488# commands with ---, -- '' and `` preserved 8489# usefull with the old interface 8490 8491%code_style_map = ( 8492 'code' => 1, 8493 'command' => 1, 8494 'env' => 1, 8495 'file' => 1, 8496 'kbd' => 1, 8497 'option' => 1, 8498 'samp' => 1, 8499 'verb' => 1, 8500); 8501 8502my @element_directions = ('Up', 'Forward', 'Back', 'Next', 'Prev', 8503'SectionNext', 'SectionPrev', 'SectionUp', 'FastForward', 'FastBack', 8504'This', 'NodeUp', 'NodePrev', 'NodeNext', 'Following' ); 8505$::simple_map_ref = \%Texi2HTML::Config::simple_map; 8506$::simple_map_pre_ref = \%Texi2HTML::Config::simple_map_pre; 8507$::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; 8508$::style_map_ref = \%Texi2HTML::Config::style_map; 8509$::style_map_pre_ref = \%Texi2HTML::Config::style_map_pre; 8510$::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; 8511$::things_map_ref = \%Texi2HTML::Config::things_map; 8512$::pre_map_ref = \%Texi2HTML::Config::pre_map; 8513$::texi_map_ref = \%Texi2HTML::Config::texi_map; 8514 8515# delete from hash if we are using the new interface 8516foreach my $code (keys(%code_style_map)) 8517{ 8518 delete ($code_style_map{$code}) 8519 if (ref($::style_map_ref->{$code}) eq 'HASH'); 8520} 8521 8522# no paragraph in these commands 8523my %no_paragraph_macro = ( 8524 'xref' => 1, 8525 'ref' => 1, 8526 'pxref' => 1, 8527 'inforef' => 1, 8528 'anchor' => 1, 8529); 8530 8531 8532# 8533# texinfo section names to level 8534# 8535%sec2level = ( 8536 'top', 0, 8537 'chapter', 1, 8538 'unnumbered', 1, 8539 'chapheading', 1, 8540 'appendix', 1, 8541 'section', 2, 8542 'unnumberedsec', 2, 8543 'heading', 2, 8544 'appendixsec', 2, 8545 'subsection', 3, 8546 'unnumberedsubsec', 3, 8547 'subheading', 3, 8548 'appendixsubsec', 3, 8549 'subsubsection', 4, 8550 'unnumberedsubsubsec', 4, 8551 'subsubheading', 4, 8552 'appendixsubsubsec', 4, 8553 ); 8554 8555# the reverse mapping. There is an entry for each sectionning command. 8556# The value is a ref on an array containing at each index the corresponding 8557# sectionning command name. 8558my %level2sec; 8559{ 8560 my $sections = [ ]; 8561 my $appendices = [ ]; 8562 my $unnumbered = [ ]; 8563 my $headings = [ ]; 8564 foreach my $command (keys (%sec2level)) 8565 { 8566 if ($command =~ /^appendix/) 8567 { 8568 $level2sec{$command} = $appendices; 8569 } 8570 elsif ($command =~ /^unnumbered/ or $command eq 'top') 8571 { 8572 $level2sec{$command} = $unnumbered; 8573 } 8574 elsif ($command =~ /section$/ or $command eq 'chapter') 8575 { 8576 $level2sec{$command} = $sections; 8577 } 8578 else 8579 { 8580 $level2sec{$command} = $headings; 8581 } 8582 $level2sec{$command}->[$sec2level{$command}] = $command; 8583 } 8584} 8585 8586# this are synonyms 8587$sec2level{'appendixsection'} = 2; 8588# sec2level{'majorheading'} is also 1 and not 0 8589$sec2level{'majorheading'} = 1; 8590$sec2level{'chapheading'} = 1; 8591$sec2level{'centerchap'} = 1; 8592 8593# sction to level hash not taking into account raise and lower sections 8594my %reference_sec2level = %sec2level; 8595 8596# regions treated especially. The text for these regions is collected in the 8597# corresponding array 8598%region_lines = ( 8599 'titlepage' => [ ], 8600 'documentdescription' => [ ], 8601 'copying' => [ ], 8602); 8603 8604# those macros aren't considered as beginning a paragraph 8605my %no_line_macros = ( 8606 'macro' => 1, 8607 'unmacro' => 1, 8608 'rmacro' => 1, 8609 'set' => 1, 8610 'clear' => 1, 8611 'titlefont' => 1, 8612 'include' => 1, 8613 'copying' => 1, 8614 'end copying' => 1, 8615 'tab' => 1, 8616 'item' => 1, 8617 'itemx' => 1, 8618 '*' => 1, 8619 'float' => 1, 8620 'end float' => 1, 8621 'caption' => 1, 8622 'shortcaption' => 1, 8623); 8624 8625foreach my $key (keys(%Texi2HTML::Config::misc_command)) 8626{ 8627 $no_line_macros{$key} = 1; 8628} 8629 8630# a hash associating a format @thing / @end thing with the type of the format 8631# 'complex_format' 'simple_format' 'deff' 'list' 'menu' 'paragraph_format' 8632my %format_type = (); 8633 8634foreach my $simple_format (keys(%Texi2HTML::Config::format_map)) 8635{ 8636 $format_type{$simple_format} = 'simple_format'; 8637} 8638foreach my $paragraph_style (keys(%Texi2HTML::Config::paragraph_style)) 8639{ 8640 $format_type{$paragraph_style} = 'paragraph_format'; 8641} 8642foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map)) 8643{ 8644 $format_type{$complex_format} = 'complex_format'; 8645} 8646foreach my $table (('table', 'ftable', 'vtable', 'multitable')) 8647{ 8648 $format_type{$table} = 'table'; 8649} 8650foreach my $def_format (keys(%Texi2HTML::Config::def_map)) 8651{ 8652 $format_type{$def_format} = 'deff'; 8653} 8654$format_type{'itemize'} = 'list'; 8655$format_type{'enumerate'} = 'list'; 8656 8657$format_type{'menu'} = 'menu'; 8658 8659$format_type{'cartouche'} = 'cartouche'; 8660 8661$format_type{'float'} = 'float'; 8662 8663$format_type{'quotation'} = 'quotation'; 8664 8665$format_type{'group'} = 'group'; 8666 8667foreach my $key (keys(%format_type)) 8668{ 8669 $no_line_macros{$key} = 1; 8670 $no_line_macros{"end $key"} = 1; 8671} 8672 8673foreach my $macro (keys(%Texi2HTML::Config::format_in_paragraph)) 8674{ 8675 $no_line_macros{$macro} = 1; 8676 $no_line_macros{"end $macro"} = 1; 8677} 8678 8679# fake format at the bottom of the stack 8680$format_type{'noformat'} = ''; 8681 8682# fake formats are formats used internally within other formats 8683# we associate them with a real format, for the error messages 8684my %fake_format = ( 8685 'line' => 'table', 8686 'term' => 'table', 8687 'item' => 'list or table', 8688 'row' => 'multitable row', 8689 'cell' => 'multitable cell', 8690 'deff_item' => 'definition command', 8691 'menu_comment' => 'menu', 8692 'menu_description' => 'menu', 8693 'menu_preformatted' => 'menu', 8694 ); 8695 8696foreach my $key (keys(%fake_format)) 8697{ 8698 $format_type{$key} = 'fake'; 8699} 8700 8701# raw formats which are expanded especially 8702my @raw_regions = ('html', 'verbatim', 'tex', 'xml', 'docbook'); 8703 8704# regions expanded or not depending on the value of this hash 8705my %text_macros = ( 8706 'iftex' => 0, 8707 'ignore' => 0, 8708 'menu' => 0, 8709 'ifplaintext' => 0, 8710 'ifinfo' => 0, 8711 'ifxml' => 0, 8712 'ifhtml' => 0, 8713 'ifdocbook' => 0, 8714 'html' => 0, 8715 'tex' => 0, 8716 'xml' => 0, 8717 'titlepage' => 1, 8718 'documentdescription' => 1, 8719 'copying' => 1, 8720 'ifnothtml' => 1, 8721 'ifnottex' => 1, 8722 'ifnotplaintext' => 1, 8723 'ifnotinfo' => 1, 8724 'ifnotxml' => 1, 8725 'ifnotdocbook' => 1, 8726 'direntry' => 0, 8727 'verbatim' => 'raw', 8728 'ifclear' => 'value', 8729 'ifset' => 'value' , 8730 ); 8731 8732foreach my $key (keys(%text_macros)) 8733{ 8734 unless ($text_macros{$key} eq 'raw') 8735 { 8736 $no_line_macros{$key} = 1; 8737 $no_line_macros{"end $key"} = 1; 8738 } 8739} 8740 8741# The css formats are associated with complex format commands, and associated 8742# with the 'pre_style' key 8743foreach my $complex_format (keys(%$Texi2HTML::Config::complex_format_map)) 8744{ 8745 next if (defined($Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'})); 8746 $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = ''; 8747 $Texi2HTML::Config::complex_format_map->{$complex_format}->{'pre_style'} = $Texi2HTML::Config::css_map{"pre.$complex_format"} if (exists($Texi2HTML::Config::css_map{"pre.$complex_format"})); 8748} 8749 8750#+++############################################################################ 8751# # 8752# Argument parsing, initialisation # 8753# # 8754#---############################################################################ 8755 8756# 8757# flush stdout and stderr after every write 8758# 8759select(STDERR); 8760$| = 1; 8761select(STDOUT); 8762$| = 1; 8763 8764my $I = \&Texi2HTML::I18n::get_string; 8765 8766my $T2H_USER; # user running the script 8767my $documentdescription; # text in @documentdescription 8768 8769# shorthand for Texi2HTML::Config::VERBOSE 8770my $T2H_VERBOSE; 8771my $T2H_DEBUG; 8772 8773sub echo_warn($;$); 8774#print STDERR "" . &$I('test i18n: \' , \a \\ %% %{unknown}a %known % %{known} \\', { 'known' => 'a known string', 'no' => 'nope'}); exit 0; 8775 8776# file: file name to locate. It can be a file path. 8777# all_files: if true collect all the files with that name, otherwise stop 8778# at first match. 8779# directories: a reference on a array containing a list of directories to 8780# search the file in. default is \@texi2html_config_dirs. 8781sub locate_init_file($;$$) 8782{ 8783 my $file = shift; 8784 my $all_files = shift; 8785 my $directories = shift; 8786 8787 $directories = \@texi2html_config_dirs if !defined($directories); 8788 8789 if ($file =~ /^\//) 8790 { 8791 return $file if (-e $file and -r $file); 8792 } 8793 else 8794 { 8795 my @files; 8796 foreach my $dir (@$directories) 8797 { 8798 next unless (-d "$dir"); 8799 if ($all_files) 8800 { 8801 push (@files, "$dir/$file") if (-e "$dir/$file" and -r "$dir/$file"); 8802 } 8803 else 8804 { 8805 return "$dir/$file" if (-e "$dir/$file" and -r "$dir/$file"); 8806 } 8807 } 8808 return @files if ($all_files); 8809 } 8810 return undef; 8811} 8812 8813# called on -init-file 8814sub load_init_file 8815{ 8816 # First argument is option 8817 shift; 8818 # second argument is value of options 8819 my $init_file = shift; 8820 my $file; 8821 if ($file = locate_init_file($init_file)) 8822 { 8823 print STDERR "# reading initialization file from $file\n" 8824 if ($T2H_VERBOSE); 8825 return (Texi2HTML::Config::load($file)); 8826 } 8827 else 8828 { 8829 print STDERR "$ERROR Error: can't read init file $init_file\n"; 8830 return 0; 8831 } 8832} 8833 8834my $cmd_line_lang = 0; # 1 if lang was succesfully set by the command line 8835 # in that case @documentlanguage is ignored. 8836my $lang_set = 0; # 1 if lang was set 8837 8838# 8839# called on -lang 8840sub set_document_language ($;$$) 8841{ 8842 my $lang = shift; 8843 my $from_command_line = shift; 8844 my $line_nr = shift; 8845 my @files = locate_init_file("$i18n_dir/$lang", 1); 8846 foreach my $file (@files) 8847 { 8848 Texi2HTML::Config::load($file); 8849 } 8850 if (Texi2HTML::I18n::set_language($lang)) 8851 { 8852 print STDERR "# using '$lang' as document language\n" if ($T2H_VERBOSE); 8853 $Texi2HTML::Config::LANG = $lang; 8854 $lang_set = 1; 8855 $cmd_line_lang = 1 if ($from_command_line); 8856 if (!$Texi2HTML::Config::TEST) 8857 { 8858 print STDERR "# Setting date in $Texi2HTML::Config::LANG\n" if ($T2H_DEBUG); 8859 $Texi2HTML::THISDOC{'today'} = Texi2HTML::I18n::pretty_date($Texi2HTML::Config::LANG); # like "20 September 1993"; 8860 } 8861 else 8862 { 8863 $Texi2HTML::THISDOC{'today'} = 'a sunny day'; 8864 } 8865 $Texi2HTML::THISDOC{'today'} = $Texi2HTML::Config::DATE 8866 if (defined($Texi2HTML::Config::DATE)); 8867 $::things_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; 8868 $::pre_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; 8869 $::texi_map_ref->{'today'} = $Texi2HTML::THISDOC{'today'}; 8870 } 8871 else 8872 { 8873 echo_error ("Language specs for '$lang' do not exists. Reverting to '$Texi2HTML::Config::LANG'", $line_nr); 8874 } 8875} 8876 8877# used to manage expanded sections from the command line 8878sub set_expansion($$) 8879{ 8880 my $region = shift; 8881 my $set = shift; 8882 $set = 1 if (!defined($set)); 8883 if ($set) 8884 { 8885 push (@Texi2HTML::Config::EXPAND, $region) unless (grep {$_ eq $region} @Texi2HTML::Config::EXPAND); 8886 } 8887 else 8888 { 8889 @Texi2HTML::Config::EXPAND = grep {$_ ne $region} @Texi2HTML::Config::EXPAND; 8890 } 8891} 8892 8893 8894# find the encoding alias. 8895# with encoding support (USE_UNICODE), may return undef if no alias was found 8896sub encoding_alias($) 8897{ 8898 my $encoding = shift; 8899 return $encoding if (!defined($encoding) or $encoding eq ''); 8900 if ($Texi2HTML::Config::USE_UNICODE) 8901 { 8902 if (! Encode::resolve_alias($encoding)) 8903 { 8904 echo_warn("Encoding $encoding unknown"); 8905 return undef; 8906 } 8907 print STDERR "# Using encoding " . Encode::resolve_alias($encoding) . "\n" 8908 if ($T2H_VERBOSE); 8909 return Encode::resolve_alias($encoding); 8910 } 8911 else 8912 { 8913 echo_warn("No alias searched for encoding"); 8914 return $encoding; 8915 } 8916} 8917 8918# setup hashes used for html manual cross references in texinfo 8919my %cross_ref_texi_map = %Texi2HTML::Config::texi_map; 8920 8921$cross_ref_texi_map{'enddots'} = '...'; 8922 8923my %cross_ref_simple_map_texi = %Texi2HTML::Config::simple_map_texi; 8924my %cross_ref_style_map_texi = (); 8925my %cross_transliterate_style_map_texi = (); 8926 8927my %cross_transliterate_texi_map = %cross_ref_texi_map; 8928 8929foreach my $command (keys(%Texi2HTML::Config::style_map_texi)) 8930{ 8931 $cross_ref_style_map_texi{$command} = {}; 8932 $cross_transliterate_style_map_texi{$command} = {}; 8933 foreach my $key (keys (%{$Texi2HTML::Config::style_map_texi{$command}})) 8934 { 8935#print STDERR "$command, $key, $style_map_texi{$command}->{$key}\n"; 8936 $cross_ref_style_map_texi{$command}->{$key} = 8937 $Texi2HTML::Config::style_map_texi{$command}->{$key}; 8938 $cross_transliterate_style_map_texi{$command}->{$key} = 8939 $Texi2HTML::Config::style_map_texi{$command}->{$key}; 8940 } 8941} 8942 8943$cross_ref_simple_map_texi{"\n"} = ' '; 8944$cross_ref_simple_map_texi{"*"} = ' '; 8945 8946my %nodes = (); # nodes hash. The key is the texi node name 8947my %cross_reference_nodes = (); # normalized node names arrays 8948 8949# This function is used to construct link names from node names as 8950# specified for texinfo 8951sub cross_manual_links() 8952{ 8953 print STDERR "# Doing ".scalar(keys(%nodes))." cross manual links\n" 8954 if ($T2H_DEBUG); 8955 my $normal_text_kept = $Texi2HTML::Config::normal_text; 8956 $::simple_map_texi_ref = \%cross_ref_simple_map_texi; 8957 $::style_map_texi_ref = \%cross_ref_style_map_texi; 8958 $::texi_map_ref = \%cross_ref_texi_map; 8959 $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text; 8960 8961 foreach my $key (keys(%nodes)) 8962 { 8963 my $node = $nodes{$key}; 8964 #print STDERR "CROSS_MANUAL:$key,$node\n"; 8965 next if ($node->{'index_page'}); 8966 if (!defined($node->{'texi'})) 8967 { 8968 ###################### debug section 8969 foreach my $key (keys(%$node)) 8970 { 8971 #print STDERR "$key:$node->{$key}!!!\n"; 8972 } 8973 ###################### end debug section 8974 } 8975 else 8976 { 8977 $node->{'cross_manual_target'} = remove_texi($node->{'texi'}); 8978 if ($Texi2HTML::Config::USE_UNICODE) 8979 { 8980 $node->{'cross_manual_target'} = Unicode::Normalize::NFC($node->{'cross_manual_target'}); 8981 if ($Texi2HTML::Config::TRANSLITERATE_NODE and $Texi2HTML::Config::USE_UNIDECODE) 8982 { 8983 $node->{'cross_manual_file'} = 8984 unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_target'})); 8985 } 8986 $node->{'cross_manual_target'} = 8987 unicode_to_protected($node->{'cross_manual_target'}); 8988 } 8989#print STDERR "CROSS_MANUAL_TARGET $node->{'cross_manual_target'}\n"; 8990 unless ($node->{'external_node'}) 8991 { 8992 if (exists($cross_reference_nodes{$node->{'cross_manual_target'}})) 8993 { 8994 my $other_node_array = $cross_reference_nodes{$node->{'cross_manual_target'}}; 8995 my $node_seen; 8996 foreach my $other_node (@{$other_node_array}) 8997 { 8998 $node_seen = $other_node; 8999 last if ($nodes{$other_node}->{'seen'}) 9000 } 9001 echo_error("Node equivalent with `$node->{'texi'}' allready used `$node_seen'"); 9002 push @{$other_node_array}, $node->{'texi'}; 9003 } 9004 else 9005 { 9006 push @{$cross_reference_nodes{$node->{'cross_manual_target'}}}, $node->{'texi'}; 9007 } 9008 } 9009 } 9010 } 9011 9012 9013 if ($Texi2HTML::Config::TRANSLITERATE_NODE and 9014 (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE)) 9015 { 9016 $::style_map_texi_ref = \%cross_transliterate_style_map_texi; 9017 $::texi_map_ref = \%cross_transliterate_texi_map; 9018 9019 foreach my $key (keys(%nodes)) 9020 { 9021 my $node = $nodes{$key}; 9022 next if ($node->{'index_page'}); 9023 if (defined($node->{'texi'})) 9024 { 9025 $node->{'cross_manual_file'} = remove_texi($node->{'texi'}); 9026 $node->{'cross_manual_file'} = unicode_to_protected(unicode_to_transliterate($node->{'cross_manual_file'})) if ($Texi2HTML::Config::USE_UNICODE); 9027 } 9028 } 9029 } 9030 9031 $Texi2HTML::Config::normal_text = $normal_text_kept; 9032 $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; 9033 $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; 9034 $::texi_map_ref = \%Texi2HTML::Config::texi_map; 9035} 9036 9037sub unicode_to_protected($) 9038{ 9039 my $text = shift; 9040 my $result = ''; 9041 while ($text ne '') 9042 { 9043 if ($text =~ s/^([A-Za-z0-9]+)//o) 9044 { 9045 $result .= $1; 9046 } 9047 elsif ($text =~ s/^ //o) 9048 { 9049 $result .= '-'; 9050 } 9051 elsif ($text =~ s/^(.)//o) 9052 { 9053 if (exists($Texi2HTML::Config::ascii_character_map{$1})) 9054 { 9055 $result .= '_' . lc($Texi2HTML::Config::ascii_character_map{$1}); 9056 } 9057 else 9058 { 9059 $result .= '_' . lc(sprintf("%04x",ord($1))); 9060 } 9061 } 9062 else 9063 { 9064 print STDERR "Bug: unknown character in a cross ref (likely in infinite loop)\n"; 9065 print STDERR "Text: !!$text!!\n"; 9066 sleep 1; 9067 } 9068 } 9069 return $result; 9070} 9071 9072sub unicode_to_transliterate($) 9073{ 9074 my $text = shift; 9075 my $result = ''; 9076 while ($text ne '') 9077 { 9078 if ($text =~ s/^([A-Za-z0-9 ]+)//o) 9079 { 9080 $result .= $1; 9081 } 9082 elsif ($text =~ s/^(.)//o) 9083 { 9084 if (exists($Texi2HTML::Config::ascii_character_map{$1})) 9085 { 9086 $result .= $1; 9087 } 9088 elsif (exists($Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))})) 9089 { 9090 $result .= $Texi2HTML::Config::transliterate_map{uc(sprintf("%04x",ord($1)))}; 9091 } 9092 elsif (exists($Texi2HTML::Config::unicode_diacritical{uc(sprintf("%04x",ord($1)))})) 9093 { 9094 $result .= ''; 9095 } 9096 else 9097 { 9098 if ($Texi2HTML::Config::USE_UNIDECODE) 9099 { 9100 $result .= unidecode($1); 9101 } 9102 else 9103 { 9104 $result .= $1; 9105 } 9106 } 9107 } 9108 else 9109 { 9110 print STDERR "Bug: unknown character in cross ref transliteration (likely in infinite loop)\n"; 9111 sleep 1; 9112 } 9113 } 9114 return $result; 9115} 9116 9117# This function is used to construct a link name from a node name as 9118# specified for texinfo 9119sub cross_manual_line($;$) 9120{ 9121 my $text = shift; 9122 my $transliterate = shift; 9123#print STDERR "cross_manual_line $text\n"; 9124#print STDERR "remove_texi text ". remove_texi($text)."\n\n\n"; 9125 $::simple_map_texi_ref = \%cross_ref_simple_map_texi; 9126 $::style_map_texi_ref = \%cross_ref_style_map_texi; 9127 $::texi_map_ref = \%cross_ref_texi_map; 9128 my $normal_text_kept = $Texi2HTML::Config::normal_text; 9129 $Texi2HTML::Config::normal_text = \&Texi2HTML::Config::t2h_cross_manual_normal_text; 9130 9131 my ($cross_ref_target, $cross_ref_file); 9132 if ($Texi2HTML::Config::USE_UNICODE) 9133 { 9134 $cross_ref_target = Unicode::Normalize::NFC(remove_texi($text)); 9135 if ($transliterate and $Texi2HTML::Config::USE_UNIDECODE) 9136 { 9137 $cross_ref_file = 9138 unicode_to_protected(unicode_to_transliterate($cross_ref_target)); 9139 } 9140 $cross_ref_target = unicode_to_protected($cross_ref_target); 9141 } 9142 else 9143 { 9144 $cross_ref_target = remove_texi($text); 9145 } 9146 9147 if ($transliterate and 9148 (!$Texi2HTML::Config::USE_UNICODE or !$Texi2HTML::Config::USE_UNIDECODE)) 9149 { 9150 $::style_map_texi_ref = \%cross_transliterate_style_map_texi; 9151 $::texi_map_ref = \%cross_transliterate_texi_map; 9152 $cross_ref_file = remove_texi($text); 9153 $cross_ref_file = unicode_to_protected(unicode_to_transliterate($cross_ref_file)) 9154 if ($Texi2HTML::Config::USE_UNICODE); 9155 } 9156 9157 $Texi2HTML::Config::normal_text = $normal_text_kept; 9158 $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; 9159 $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; 9160 $::texi_map_ref = \%Texi2HTML::Config::texi_map; 9161#print STDERR "\n\ncross_ref $cross_ref\n"; 9162 unless ($transliterate) 9163 { 9164 return $cross_ref_target; 9165 } 9166# print STDERR "$text|$cross_ref_target|$cross_ref_file\n"; 9167 return ($cross_ref_target, $cross_ref_file); 9168} 9169 9170# T2H_OPTIONS is a hash whose keys are the (long) names of valid 9171# command-line options and whose values are a hash with the following keys: 9172# type ==> one of !|=i|:i|=s|:s (see GetOpt::Long for more info) 9173# linkage ==> ref to scalar, array, or subroutine (see GetOpt::Long for more info) 9174# verbose ==> short description of option (displayed by -h) 9175# noHelp ==> if 1 -> for "not so important options": only print description on -h 1 9176# 2 -> for obsolete options: only print description on -h 2 9177my $T2H_OPTIONS; 9178$T2H_OPTIONS -> {'debug'} = 9179{ 9180 type => '=i', 9181 linkage => \$Texi2HTML::Config::DEBUG, 9182 verbose => 'output HTML with debuging information', 9183}; 9184 9185$T2H_OPTIONS -> {'doctype'} = 9186{ 9187 type => '=s', 9188 linkage => \$Texi2HTML::Config::DOCTYPE, 9189 verbose => 'document type which is output in header of HTML files', 9190 noHelp => 1 9191}; 9192 9193$T2H_OPTIONS -> {'frameset-doctype'} = 9194{ 9195 type => '=s', 9196 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE, 9197 verbose => 'document type for HTML frameset documents', 9198 noHelp => 1 9199}; 9200 9201$T2H_OPTIONS -> {'test'} = 9202{ 9203 type => '!', 9204 linkage => \$Texi2HTML::Config::TEST, 9205 verbose => 'use predefined information to avoid differences with reference files', 9206 noHelp => 1 9207}; 9208 9209$T2H_OPTIONS -> {'dump-texi'} = 9210{ 9211 type => '!', 9212 linkage => \$Texi2HTML::Config::DUMP_TEXI, 9213 verbose => 'dump the output of first pass into a file with extension passfirst and exit', 9214 noHelp => 1 9215}; 9216 9217$T2H_OPTIONS -> {'macro-expand'} = 9218{ 9219 type => '=s', 9220 linkage => \$Texi2HTML::Config::MACRO_EXPAND, 9221 verbose => 'output macro expanded source in <file>', 9222}; 9223 9224$T2H_OPTIONS -> {'expand'} = 9225{ 9226 type => '=s', 9227 linkage => sub {set_expansion($_[1], 1);}, 9228 verbose => 'Expand info|tex|none section of texinfo source', 9229 noHelp => 1, 9230}; 9231 9232$T2H_OPTIONS -> {'no-expand'} = 9233{ 9234 type => '=s', 9235 linkage => sub {set_expansion ($_[1], 0);}, 9236 verbose => 'Don\'t expand the given section of texinfo source', 9237}; 9238 9239$T2H_OPTIONS -> {'noexpand'} = 9240{ 9241 type => '=s', 9242 linkage => $T2H_OPTIONS->{'no-expand'}->{'linkage'}, 9243 verbose => $T2H_OPTIONS->{'no-expand'}->{'verbose'}, 9244 noHelp => 1, 9245}; 9246 9247$T2H_OPTIONS -> {'ifhtml'} = 9248{ 9249 type => '!', 9250 linkage => sub { set_expansion('html', $_[1]); }, 9251 verbose => "expand ifhtml and html sections", 9252}; 9253 9254$T2H_OPTIONS -> {'ifinfo'} = 9255{ 9256 type => '!', 9257 linkage => sub { set_expansion('info', $_[1]); }, 9258 verbose => "expand ifinfo", 9259}; 9260 9261$T2H_OPTIONS -> {'ifxml'} = 9262{ 9263 type => '!', 9264 linkage => sub { set_expansion('xml', $_[1]); }, 9265 verbose => "expand ifxml and xml sections", 9266}; 9267 9268$T2H_OPTIONS -> {'ifdocbook'} = 9269{ 9270 type => '!', 9271 linkage => sub { set_expansion('docbook', $_[1]); }, 9272 verbose => "expand ifdocbook and docbook sections", 9273}; 9274 9275$T2H_OPTIONS -> {'iftex'} = 9276{ 9277 type => '!', 9278 linkage => sub { set_expansion('tex', $_[1]); }, 9279 verbose => "expand iftex and tex sections", 9280}; 9281 9282$T2H_OPTIONS -> {'ifplaintext'} = 9283{ 9284 type => '!', 9285 linkage => sub { set_expansion('plaintext', $_[1]); }, 9286 verbose => "expand ifplaintext sections", 9287}; 9288 9289$T2H_OPTIONS -> {'invisible'} = 9290{ 9291 type => '=s', 9292 linkage => \$Texi2HTML::Config::INVISIBLE_MARK, 9293 verbose => 'use text in invisble anchor', 9294 noHelp => 1, 9295}; 9296 9297$T2H_OPTIONS -> {'iso'} = 9298{ 9299 type => 'iso', 9300 linkage => \$Texi2HTML::Config::USE_ISO, 9301 verbose => 'if set, ISO8859 characters are used for special symbols (like copyright, etc)', 9302 noHelp => 1, 9303}; 9304 9305$T2H_OPTIONS -> {'I'} = 9306{ 9307 type => '=s', 9308 linkage => \@Texi2HTML::Config::INCLUDE_DIRS, 9309 verbose => 'append $s to the @include search path', 9310}; 9311 9312$T2H_OPTIONS -> {'conf-dir'} = 9313{ 9314 type => '=s', 9315 linkage => \@Texi2HTML::Config::CONF_DIRS, 9316 verbose => 'append $s to the init file directories', 9317}; 9318 9319$T2H_OPTIONS -> {'P'} = 9320{ 9321 type => '=s', 9322 linkage => sub {unshift (@Texi2HTML::Config::PREPEND_DIRS, $_[1]);}, 9323 verbose => 'prepend $s to the @include search path', 9324}; 9325 9326$T2H_OPTIONS -> {'top-file'} = 9327{ 9328 type => '=s', 9329 linkage => \$Texi2HTML::Config::TOP_FILE, 9330 verbose => 'use $s as top file, instead of <docname>.html', 9331}; 9332 9333$T2H_OPTIONS -> {'toc-file'} = 9334{ 9335 type => '=s', 9336 linkage => \$Texi2HTML::Config::TOC_FILE, 9337 verbose => 'use $s as ToC file, instead of <docname>_toc.html', 9338}; 9339 9340$T2H_OPTIONS -> {'frames'} = 9341{ 9342 type => '!', 9343 linkage => \$Texi2HTML::Config::FRAMES, 9344 verbose => 'output files which use HTML 4.0 frames (experimental)', 9345 noHelp => 1, 9346}; 9347 9348$T2H_OPTIONS -> {'menu'} = 9349{ 9350 type => '!', 9351 linkage => \$Texi2HTML::Config::SHOW_MENU, 9352 verbose => 'output Texinfo menus', 9353}; 9354 9355$T2H_OPTIONS -> {'number'} = 9356{ 9357 type => '!', 9358 linkage => \$Texi2HTML::Config::NUMBER_SECTIONS, 9359 verbose => 'use numbered sections', 9360}; 9361 9362$T2H_OPTIONS -> {'use-nodes'} = 9363{ 9364 type => '!', 9365 linkage => \$Texi2HTML::Config::USE_NODES, 9366 verbose => 'use nodes for sectionning', 9367}; 9368 9369$T2H_OPTIONS -> {'node-files'} = 9370{ 9371 type => '!', 9372 linkage => \$Texi2HTML::Config::NODE_FILES, 9373 verbose => 'produce one file per node for cross references' 9374}; 9375 9376$T2H_OPTIONS -> {'separated-footnotes'} = 9377{ 9378 type => '!', 9379 linkage => \$Texi2HTML::Config::SEPARATED_FOOTNOTES, 9380 verbose => 'footnotes on a separated page', 9381 noHelp => 1, 9382}; 9383 9384$T2H_OPTIONS -> {'toc-links'} = 9385{ 9386 type => '!', 9387 linkage => \$Texi2HTML::Config::TOC_LINKS, 9388 verbose => 'create links from headings to toc entries' 9389}; 9390 9391$T2H_OPTIONS -> {'split'} = 9392{ 9393 type => '=s', 9394 linkage => \$Texi2HTML::Config::SPLIT, 9395 verbose => 'split document on section|chapter|node else no splitting', 9396}; 9397 9398$T2H_OPTIONS -> {'sec-nav'} = 9399{ 9400 type => '!', 9401 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION, 9402 verbose => 'output navigation panels for each section', 9403}; 9404 9405$T2H_OPTIONS -> {'subdir'} = 9406{ 9407 type => '=s', 9408 linkage => \$Texi2HTML::Config::SUBDIR, 9409 verbose => 'put files in directory $s, not $cwd', 9410 noHelp => 1, 9411}; 9412 9413$T2H_OPTIONS -> {'short-ext'} = 9414{ 9415 type => '!', 9416 linkage => \$Texi2HTML::Config::SHORTEXTN, 9417 verbose => 'use "htm" extension for output HTML files', 9418}; 9419 9420$T2H_OPTIONS -> {'prefix'} = 9421{ 9422 type => '=s', 9423 linkage => \$Texi2HTML::Config::PREFIX, 9424 verbose => 'use as prefix for output files, instead of <docname>', 9425}; 9426 9427$T2H_OPTIONS -> {'output'} = 9428{ 9429 type => '=s', 9430 linkage => \$Texi2HTML::Config::OUT, 9431 verbose => 'output goes to $s (directory if split)', 9432}; 9433 9434$T2H_OPTIONS -> {'no-validate'} = 9435{ 9436 type => '!', 9437 linkage => \$Texi2HTML::Config::NOVALIDATE, 9438 verbose => 'suppress node cross-reference validation', 9439}; 9440 9441$T2H_OPTIONS -> {'short-ref'} = 9442{ 9443 type => '!', 9444 linkage => \$Texi2HTML::Config::SHORT_REF, 9445 verbose => 'if set, references are without section numbers', 9446}; 9447 9448$T2H_OPTIONS -> {'idx-sum'} = 9449{ 9450 type => '!', 9451 linkage => \$Texi2HTML::Config::IDX_SUMMARY, 9452 verbose => 'if set, also output index summary', 9453 noHelp => 1, 9454}; 9455 9456$T2H_OPTIONS -> {'def-table'} = 9457{ 9458 type => '!', 9459 linkage => \$Texi2HTML::Config::DEF_TABLE, 9460 verbose => 'if set, \@def.. are converted using tables.', 9461 noHelp => 1, 9462}; 9463 9464$T2H_OPTIONS -> {'Verbose'} = 9465{ 9466 type => '!', 9467 linkage=> \$Texi2HTML::Config::VERBOSE, 9468 verbose => 'print progress info to stdout', 9469}; 9470 9471$T2H_OPTIONS -> {'lang'} = 9472{ 9473 type => '=s', 9474 linkage => sub {set_document_language($_[1], 1)}, 9475 verbose => 'use $s as document language (ISO 639 encoding)', 9476}; 9477 9478$T2H_OPTIONS -> {'ignore-preamble-text'} = 9479{ 9480 type => '!', 9481 linkage => \$Texi2HTML::Config::IGNORE_PREAMBLE_TEXT, 9482 verbose => 'if set, ignore the text before @node and sectionning commands', 9483 noHelp => 1, 9484}; 9485 9486$T2H_OPTIONS -> {'html-xref-prefix'} = 9487{ 9488 type => '=s', 9489 linkage => \$Texi2HTML::Config::EXTERNAL_DIR, 9490 verbose => '$s is the base dir for external manual references', 9491 noHelp => 1, 9492}; 9493 9494$T2H_OPTIONS -> {'l2h'} = 9495{ 9496 type => '!', 9497 linkage => \$Texi2HTML::Config::L2H, 9498 verbose => 'if set, uses latex2html for @math and @tex', 9499}; 9500 9501$T2H_OPTIONS -> {'l2h-l2h'} = 9502{ 9503 type => '=s', 9504 linkage => \$Texi2HTML::Config::L2H_L2H, 9505 verbose => 'program to use for latex2html translation', 9506 noHelp => 1, 9507}; 9508 9509$T2H_OPTIONS -> {'l2h-skip'} = 9510{ 9511 type => '!', 9512 linkage => \$Texi2HTML::Config::L2H_SKIP, 9513 verbose => 'if set, tries to reuse previously latex2html output', 9514 noHelp => 1, 9515}; 9516 9517$T2H_OPTIONS -> {'l2h-tmp'} = 9518{ 9519 type => '=s', 9520 linkage => \$Texi2HTML::Config::L2H_TMP, 9521 verbose => 'if set, uses $s as temporary latex2html directory', 9522 noHelp => 1, 9523}; 9524 9525$T2H_OPTIONS -> {'l2h-file'} = 9526{ 9527 type => '=s', 9528 linkage => \$Texi2HTML::Config::L2H_FILE, 9529 verbose => 'if set, uses $s as latex2html init file', 9530 noHelp => 1, 9531}; 9532 9533 9534$T2H_OPTIONS -> {'l2h-clean'} = 9535{ 9536 type => '!', 9537 linkage => \$Texi2HTML::Config::L2H_CLEAN, 9538 verbose => 'if set, do not keep intermediate latex2html files for later reuse', 9539 noHelp => 1, 9540}; 9541 9542$T2H_OPTIONS -> {'D'} = 9543{ 9544 type => '=s', 9545 linkage => sub {$value{$_[1]} = 1;}, 9546 verbose => 'equivalent to Texinfo "@set $s 1"', 9547 noHelp => 1, 9548}; 9549 9550$T2H_OPTIONS -> {'U'} = 9551{ 9552 type => '=s', 9553 linkage => sub {delete $value{$_[1]};}, 9554 verbose => 'equivalent to Texinfo "@clear $s"', 9555 noHelp => 1, 9556}; 9557 9558$T2H_OPTIONS -> {'init-file'} = 9559{ 9560 type => '=s', 9561 linkage => \&load_init_file, 9562 verbose => 'load init file $s' 9563}; 9564 9565$T2H_OPTIONS -> {'css-include'} = 9566{ 9567 type => '=s', 9568 linkage => \@Texi2HTML::Config::CSS_FILES, 9569 verbose => 'use css file $s' 9570}; 9571 9572## 9573## obsolete cmd line options 9574## 9575my $T2H_OBSOLETE_OPTIONS; 9576 9577$T2H_OBSOLETE_OPTIONS -> {'out-file'} = 9578{ 9579 type => '=s', 9580 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, 9581 verbose => 'if set, all HTML output goes into file $s, obsoleted by "-output" with different semantics', 9582 noHelp => 2 9583}; 9584 9585$T2H_OBSOLETE_OPTIONS -> {init_file} = 9586{ 9587 type => '=s', 9588 linkage => \&load_init_file, 9589 verbose => 'obsolete, use "-init-file" instead', 9590 noHelp => 2 9591}; 9592 9593$T2H_OBSOLETE_OPTIONS -> {l2h_clean} = 9594{ 9595 type => '!', 9596 linkage => \$Texi2HTML::Config::L2H_CLEAN, 9597 verbose => 'obsolete, use "-l2h-clean" instead', 9598 noHelp => 2, 9599}; 9600 9601$T2H_OBSOLETE_OPTIONS -> {l2h_l2h} = 9602{ 9603 type => '=s', 9604 linkage => \$Texi2HTML::Config::L2H_L2H, 9605 verbose => 'obsolete, use "-l2h-l2h" instead', 9606 noHelp => 2 9607}; 9608 9609$T2H_OBSOLETE_OPTIONS -> {l2h_skip} = 9610{ 9611 type => '!', 9612 linkage => \$Texi2HTML::Config::L2H_SKIP, 9613 verbose => 'obsolete, use "-l2h-skip" instead', 9614 noHelp => 2 9615}; 9616 9617$T2H_OBSOLETE_OPTIONS -> {l2h_tmp} = 9618{ 9619 type => '=s', 9620 linkage => \$Texi2HTML::Config::L2H_TMP, 9621 verbose => 'obsolete, use "-l2h-tmp" instead', 9622 noHelp => 2 9623}; 9624 9625$T2H_OBSOLETE_OPTIONS -> {out_file} = 9626{ 9627 type => '=s', 9628 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, 9629 verbose => 'obsolete, use "-out-file" instead', 9630 noHelp => 2 9631}; 9632 9633$T2H_OBSOLETE_OPTIONS -> {short_ref} = 9634{ 9635 type => '!', 9636 linkage => \$Texi2HTML::Config::SHORT_REF, 9637 verbose => 'obsolete, use "-short-ref" instead', 9638 noHelp => 2 9639}; 9640 9641$T2H_OBSOLETE_OPTIONS -> {idx_sum} = 9642{ 9643 type => '!', 9644 linkage => \$Texi2HTML::Config::IDX_SUMMARY, 9645 verbose => 'obsolete, use "-idx-sum" instead', 9646 noHelp => 2 9647}; 9648 9649$T2H_OBSOLETE_OPTIONS -> {def_table} = 9650{ 9651 type => '!', 9652 linkage => \$Texi2HTML::Config::DEF_TABLE, 9653 verbose => 'obsolete, use "-def-table" instead', 9654 noHelp => 2 9655}; 9656 9657$T2H_OBSOLETE_OPTIONS -> {short_ext} = 9658{ 9659 type => '!', 9660 linkage => \$Texi2HTML::Config::SHORTEXTN, 9661 verbose => 'obsolete, use "-short-ext" instead', 9662 noHelp => 2 9663}; 9664 9665$T2H_OBSOLETE_OPTIONS -> {sec_nav} = 9666{ 9667 type => '!', 9668 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION, 9669 verbose => 'obsolete, use "-sec-nav" instead', 9670 noHelp => 2 9671}; 9672 9673$T2H_OBSOLETE_OPTIONS -> {top_file} = 9674{ 9675 type => '=s', 9676 linkage => \$Texi2HTML::Config::TOP_FILE, 9677 verbose => 'obsolete, use "-top-file" instead', 9678 noHelp => 2 9679}; 9680 9681$T2H_OBSOLETE_OPTIONS -> {toc_file} = 9682{ 9683 type => '=s', 9684 linkage => \$Texi2HTML::Config::TOC_FILE, 9685 verbose => 'obsolete, use "-toc-file" instead', 9686 noHelp => 2 9687}; 9688 9689$T2H_OBSOLETE_OPTIONS -> {glossary} = 9690{ 9691 type => '!', 9692 linkage => \$Texi2HTML::Config::USE_GLOSSARY, 9693 verbose => "this does nothing", 9694 noHelp => 2, 9695}; 9696 9697$T2H_OBSOLETE_OPTIONS -> {check} = 9698{ 9699 type => '!', 9700 linkage => sub {exit 0;}, 9701 verbose => "exit without doing anything", 9702 noHelp => 2, 9703}; 9704 9705$T2H_OBSOLETE_OPTIONS -> {dump_texi} = 9706{ 9707 type => '!', 9708 linkage => \$Texi2HTML::Config::DUMP_TEXI, 9709 verbose => 'obsolete, use "-dump-texi" instead', 9710 noHelp => 1 9711}; 9712 9713$T2H_OBSOLETE_OPTIONS -> {frameset_doctype} = 9714{ 9715 type => '=s', 9716 linkage => \$Texi2HTML::Config::FRAMESET_DOCTYPE, 9717 verbose => 'obsolete, use "-frameset-doctype" instead', 9718 noHelp => 2 9719}; 9720 9721$T2H_OBSOLETE_OPTIONS -> {'no-section_navigation'} = 9722{ 9723 type => '!', 9724 linkage => sub {$Texi2HTML::Config::SECTION_NAVIGATION = 0;}, 9725 verbose => 'obsolete, use -nosec_nav', 9726 noHelp => 2, 9727}; 9728my $use_acc; # not used 9729$T2H_OBSOLETE_OPTIONS -> {use_acc} = 9730{ 9731 type => '!', 9732 linkage => \$use_acc, 9733 verbose => 'obsolete, set to true unconditionnaly', 9734 noHelp => 2 9735}; 9736$T2H_OBSOLETE_OPTIONS -> {expandinfo} = 9737{ 9738 type => '!', 9739 linkage => sub {push @Texi2HTML::Config::EXPAND, 'info';}, 9740 verbose => 'obsolete, use "-expand info" instead', 9741 noHelp => 2, 9742}; 9743$T2H_OBSOLETE_OPTIONS -> {expandtex} = 9744{ 9745 type => '!', 9746 linkage => sub {push @Texi2HTML::Config::EXPAND, 'tex';}, 9747 verbose => 'obsolete, use "-expand tex" instead', 9748 noHelp => 2, 9749}; 9750$T2H_OBSOLETE_OPTIONS -> {monolithic} = 9751{ 9752 type => '!', 9753 linkage => sub {$Texi2HTML::Config::SPLIT = '';}, 9754 verbose => 'obsolete, use "-split no" instead', 9755 noHelp => 2 9756}; 9757$T2H_OBSOLETE_OPTIONS -> {split_node} = 9758{ 9759 type => '!', 9760 linkage => sub{$Texi2HTML::Config::SPLIT = 'section';}, 9761 verbose => 'obsolete, use "-split section" instead', 9762 noHelp => 2, 9763}; 9764$T2H_OBSOLETE_OPTIONS -> {split_chapter} = 9765{ 9766 type => '!', 9767 linkage => sub{$Texi2HTML::Config::SPLIT = 'chapter';}, 9768 verbose => 'obsolete, use "-split chapter" instead', 9769 noHelp => 2, 9770}; 9771$T2H_OBSOLETE_OPTIONS -> {no_verbose} = 9772{ 9773 type => '!', 9774 linkage => sub {$Texi2HTML::Config::VERBOSE = 0;}, 9775 verbose => 'obsolete, use -noverbose instead', 9776 noHelp => 2, 9777}; 9778$T2H_OBSOLETE_OPTIONS -> {output_file} = 9779{ 9780 type => '=s', 9781 linkage => sub {$Texi2HTML::Config::OUT = $_[1]; $Texi2HTML::Config::SPLIT = '';}, 9782 verbose => 'obsolete, use --out-file instead', 9783 noHelp => 2 9784}; 9785 9786$T2H_OBSOLETE_OPTIONS -> {section_navigation} = 9787{ 9788 type => '!', 9789 linkage => \$Texi2HTML::Config::SECTION_NAVIGATION, 9790 verbose => 'obsolete, use --sec-nav instead', 9791 noHelp => 2, 9792}; 9793 9794$T2H_OBSOLETE_OPTIONS -> {verbose} = 9795{ 9796 type => '!', 9797 linkage=> \$Texi2HTML::Config::VERBOSE, 9798 verbose => 'obsolete, use -Verbose instead', 9799 noHelp => 2 9800}; 9801 9802# read initialzation from $sysconfdir/texi2htmlrc or $HOME/.texi2htmlrc 9803# (this is obsolete) 9804my @rc_files = (); 9805push @rc_files, "$sysconfdir/texi2htmlrc" if defined($sysconfdir); 9806push @rc_files, "$ENV{'HOME'}/.texi2htmlrc" if (defined($ENV{HOME})); 9807foreach my $i (@rc_files) 9808{ 9809 if (-e $i and -r $i) 9810 { 9811 print STDERR "# reading initialization file from $i\n" 9812 if ($T2H_VERBOSE); 9813 print STDERR "Reading config from $i is obsolete, use texi2html/$conf_file_name instead\n"; 9814 Texi2HTML::Config::load($i); 9815 } 9816} 9817 9818# read initialization files 9819foreach my $file (locate_init_file($conf_file_name, 1)) 9820{ 9821 print STDERR "# reading initialization file from $file\n" if ($T2H_VERBOSE); 9822 Texi2HTML::Config::load($file); 9823} 9824 9825# 9826# %value hold texinfo variables, see also -D, -U, @set and @clear. 9827# we predefine html (the output format) and texi2html (the translator) 9828%value = 9829 ( 9830 'html' => 1, 9831 'texi2html' => $THISVERSION, 9832 ); 9833 9834#+++############################################################################ 9835# # 9836# parse command-line options 9837# # 9838#---############################################################################ 9839 9840 9841my $T2H_USAGE_TEXT = <<EOT; 9842Usage: texi2html [OPTIONS] TEXINFO-FILE 9843Translates Texinfo source documentation to HTML. 9844EOT 9845my $T2H_FAILURE_TEXT = <<EOT; 9846Try 'texi2html --help' for usage instructions. 9847EOT 9848 9849my $options = new Getopt::MySimple; 9850 9851$T2H_OPTIONS -> {'help'} = 9852{ 9853 type => ':i', 9854 default => '', 9855 linkage => sub {$options->helpOptions($_[1]); 9856 print "\nSend bugs and suggestions to <texi2html-bug\@nongnu.org>\n"; 9857 exit (0);}, 9858 verbose => "print help and exit" 9859}; 9860 9861# this avoids getOptions defining twice 'help' and 'version'. 9862$T2H_OBSOLETE_OPTIONS -> {'help'} = 0; 9863$T2H_OBSOLETE_OPTIONS -> {'version'} = 0; 9864 9865# some older version of GetOpt::Long don't have 9866# Getopt::Long::Configure("pass_through") 9867eval {Getopt::Long::Configure("pass_through");}; 9868my $Configure_failed = $@ && <<EOT; 9869**WARNING: Parsing of obsolete command-line options could have failed. 9870 Consider to use only documented command-line options (run 9871 'texi2html --help 2' for a complete list) or upgrade to perl 9872 version 5.005 or higher. 9873EOT 9874if (! $options->getOptions($T2H_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n")) 9875{ 9876 print STDERR "$Configure_failed" if $Configure_failed; 9877 die $T2H_FAILURE_TEXT; 9878} 9879if (@ARGV > 1) 9880{ 9881 eval {Getopt::Long::Configure("no_pass_through");}; 9882 if (! $options->getOptions($T2H_OBSOLETE_OPTIONS, $T2H_USAGE_TEXT, "$THISVERSION\n")) 9883 { 9884 print STDERR "$Configure_failed" if $Configure_failed; 9885 die $T2H_FAILURE_TEXT; 9886 } 9887} 9888 9889# 9890# read texi2html extensions (if any) 9891# It is obsolete (obsoleted by -init-file). we keep it for backward 9892# compatibility. 9893my $extensions = 'texi2html.ext'; # extensions in working directory 9894if (-f $extensions) 9895{ 9896 print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE; 9897 require($extensions); 9898} 9899my $progdir; 9900($progdir = $0) =~ s/[^\/]+$//; 9901if ($progdir && ($progdir ne './')) 9902{ 9903 $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory 9904 if (-f $extensions) 9905 { 9906 print STDERR "# reading extensions from $extensions\n" if $T2H_VERBOSE; 9907 require($extensions); 9908 } 9909} 9910 9911# $T2H_DEBUG and $T2H_VERBOSE are shorthands 9912$T2H_DEBUG = $Texi2HTML::Config::DEBUG; 9913$T2H_VERBOSE = $Texi2HTML::Config::VERBOSE; 9914 9915$Texi2HTML::THISDOC{'debug_l2h'} = 0; 9916$Texi2HTML::THISDOC{'debug_l2h'} = 1 if ($T2H_DEBUG & $DEBUG_L2H); 9917 9918 9919#+++############################################################################ 9920# # 9921# evaluation of cmd line options 9922# # 9923#---############################################################################ 9924 9925# Fill in the %style_type hash, a hash associating style @-comand with 9926# the type, 'accent', real 'style', simple' style, or 'special'. 9927# 'simple_style' styles don't extend accross lines. 9928my %style_type = (); 9929my @simple_styles = ('ctrl', 'w', 'url','uref','indicateurl','email', 9930 'titlefont'); 9931foreach my $style (keys(%Texi2HTML::Config::style_map)) 9932{ 9933 if (exists $Texi2HTML::Config::command_type{$style}) 9934 { 9935 $style_type{$style} = $Texi2HTML::Config::command_type{$style}; 9936 next; 9937 } 9938 if (ref($Texi2HTML::Config::style_map{$style} eq 'HASH')) 9939 { 9940 $style_type{$style} = $Texi2HTML::Config::style_map{$style}->{'type'} 9941 if (exists($Texi2HTML::Config::style_map{$style}->{'type'})); 9942 } 9943 else 9944 { 9945 $style_type{$style} = 'simple_style' if (grep {$_ eq $style} @simple_styles); 9946 } 9947 $style_type{$style} = 'style' unless (defined($style_type{$style})); 9948} 9949foreach my $accent (keys(%Texi2HTML::Config::unicode_accents), 'tieaccent', 'dotless') 9950{ 9951 if (exists $Texi2HTML::Config::command_type{$accent}) 9952 { 9953 $style_type{$accent} = $Texi2HTML::Config::command_type{$accent}; 9954 next; 9955 } 9956 $style_type{$accent} = 'accent'; 9957} 9958#foreach my $simple ('ctrl', 'w', 'url','uref','indicateurl','email') 9959#{ 9960# $style_type{$simple} = 'simple_style'; 9961#} 9962foreach my $special ('footnote', 'ref', 'xref', 'pxref', 'inforef', 'anchor', 'image') 9963{ 9964 if (exists $Texi2HTML::Config::command_type{$special}) 9965 { 9966 $style_type{$special} = $Texi2HTML::Config::command_type{$special}; 9967 next; 9968 } 9969 $style_type{$special} = 'special'; 9970} 9971 9972# retro compatibility for $Texi2HTML::Config::EXPAND 9973push (@Texi2HTML::Config::EXPAND, $Texi2HTML::Config::EXPAND) if ($Texi2HTML::Config::EXPAND); 9974 9975unshift @texi2html_config_dirs, @Texi2HTML::Config::CONF_DIRS; 9976# correct %text_macros based on command line and init 9977# variables 9978$text_macros{'menu'} = 1 if ($Texi2HTML::Config::SHOW_MENU); 9979 9980foreach my $expanded (@Texi2HTML::Config::EXPAND) 9981{ 9982 $text_macros{"if$expanded"} = 1 if (exists($text_macros{"if$expanded"})); 9983 next unless (exists($text_macros{$expanded})); 9984 if (grep {$_ eq $expanded} @raw_regions) 9985 { 9986 $text_macros{$expanded} = 'raw'; 9987 } 9988 else 9989 { 9990 $text_macros{$expanded} = 1; 9991 } 9992} 9993 9994# handle ifnot regions 9995foreach my $region (keys (%text_macros)) 9996{ 9997 next if ($region =~ /^ifnot/); 9998 if ($text_macros{$region} and $region =~ /^if(\w+)$/) 9999 { 10000 $text_macros{"ifnot$1"} = 0; 10001 } 10002} 10003 10004if ($T2H_VERBOSE) 10005{ 10006 print STDERR "# Expanded: "; 10007 foreach my $text_macro (keys(%text_macros)) 10008 { 10009 print STDERR "$text_macro " if ($text_macros{$text_macro}); 10010 } 10011 print STDERR "\n"; 10012} 10013 10014# This is kept in that file although it is html formatting as it seems to 10015# be rather obsolete 10016$Texi2HTML::Config::INVISIBLE_MARK = '<img src="invisible.xbm" alt="">' if $Texi2HTML::Config::INVISIBLE_MARK eq 'xbm'; 10017 10018$T2H_DEBUG |= $DEBUG_TEXI if ($Texi2HTML::Config::DUMP_TEXI); 10019 10020# no user provided USE_UNICODE, use configure provided 10021if (!defined($Texi2HTML::Config::USE_UNICODE)) 10022{ 10023 $Texi2HTML::Config::USE_UNICODE = '1'; 10024} 10025 10026# no user provided nor configured, run time test 10027if ($Texi2HTML::Config::USE_UNICODE eq '@' .'USE_UNICODE@') 10028{ 10029 $Texi2HTML::Config::USE_UNICODE = 1; 10030 eval { 10031 require Encode; 10032 require Unicode::Normalize; 10033 Encode->import('encode'); 10034 }; 10035 $Texi2HTML::Config::USE_UNICODE = 0 if ($@); 10036} 10037elsif ($Texi2HTML::Config::USE_UNICODE) 10038{# user provided or set by configure 10039 require Encode; 10040 require Unicode::Normalize; 10041 Encode->import('encode'); 10042} 10043 10044# no user provided USE_UNIDECODE, use configure provided 10045if (!defined($Texi2HTML::Config::USE_UNIDECODE)) 10046{ 10047 $Texi2HTML::Config::USE_UNIDECODE = '0'; 10048} 10049 10050# no user provided nor configured, run time test 10051if ($Texi2HTML::Config::USE_UNIDECODE eq '@' .'USE_UNIDECODE@') 10052{ 10053 $Texi2HTML::Config::USE_UNIDECODE = 1; 10054 eval { 10055 require Text::Unidecode; 10056 Text::Unidecode->import('unidecode'); 10057 }; 10058 $Texi2HTML::Config::USE_UNIDECODE = 0 if ($@); 10059} 10060elsif ($Texi2HTML::Config::USE_UNIDECODE) 10061{# user provided or set by configure 10062 require Text::Unidecode; 10063 Text::Unidecode->import('unidecode'); 10064} 10065 10066print STDERR "# USE_UNICODE $Texi2HTML::Config::USE_UNICODE, USE_UNIDECODE $Texi2HTML::Config::USE_UNIDECODE \n" 10067 if ($T2H_VERBOSE); 10068 10069# Construct hashes used for cross references generation 10070# Do it now as the user may have changed $USE_UNICODE 10071 10072foreach my $key (keys(%Texi2HTML::Config::unicode_map)) 10073{ 10074 if ($Texi2HTML::Config::unicode_map{$key} ne '') 10075 { 10076 if ($Texi2HTML::Config::USE_UNICODE) 10077 { 10078 $cross_ref_texi_map{$key} = chr(hex($Texi2HTML::Config::unicode_map{$key})); 10079 if (($Texi2HTML::Config::TRANSLITERATE_NODE and !$Texi2HTML::Config::USE_UNIDECODE) 10080 and (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}))) 10081 { 10082 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}; 10083 10084 } 10085 } 10086 else 10087 { 10088 $cross_ref_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key}); 10089 if ($Texi2HTML::Config::TRANSLITERATE_NODE) 10090 { 10091 if (exists ($Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}})) 10092 { 10093 $cross_transliterate_texi_map{$key} = $Texi2HTML::Config::transliterate_map{$Texi2HTML::Config::unicode_map{$key}}; 10094 } 10095 else 10096 { 10097 $cross_transliterate_texi_map{$key} = '_' . lc($Texi2HTML::Config::unicode_map{$key}); 10098 } 10099 } 10100 } 10101 } 10102} 10103if ($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::TRANSLITERATE_NODE 10104 and ! $Texi2HTML::Config::USE_UNIDECODE) 10105{ 10106 foreach my $key (keys (%Texi2HTML::Config::transliterate_accent_map)) 10107 { 10108 $Texi2HTML::Config::transliterate_map{$key} = $Texi2HTML::Config::transliterate_accent_map{$key}; 10109 } 10110} 10111 10112foreach my $key (keys(%cross_ref_style_map_texi)) 10113{ 10114 if ($style_type{$key} eq 'accent' 10115 and (ref($cross_ref_style_map_texi{$key}) eq 'HASH')) 10116 { 10117 if ($Texi2HTML::Config::USE_UNICODE) 10118 { 10119 $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_utf8_accent; 10120 } 10121 else 10122 { 10123 $cross_ref_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_nounicode_cross_manual_accent; 10124 } 10125 if ($Texi2HTML::Config::TRANSLITERATE_NODE and 10126 !($Texi2HTML::Config::USE_UNICODE and $Texi2HTML::Config::USE_UNIDECODE)) 10127 { 10128 $cross_transliterate_style_map_texi{$key}->{'function'} = \&Texi2HTML::Config::t2h_transliterate_cross_manual_accent; 10129 } 10130 } 10131} 10132 10133# 10134# file name business 10135# 10136 10137 10138my $docu_dir; # directory of the document 10139my $docu_name; # basename of the document 10140my $docu_rdir; # directory for the output 10141my $docu_ext = $Texi2HTML::Config::EXTENSION; # extension 10142my $docu_toc; # document's table of contents 10143my $docu_stoc; # document's short toc 10144my $docu_foot; # document's footnotes 10145my $docu_about; # about this document 10146my $docu_top; # document top 10147my $docu_doc; # document (or document top of split) 10148 10149die "Need exactly one file to translate\n$T2H_FAILURE_TEXT" unless @ARGV == 1; 10150my $docu = shift(@ARGV); 10151if ($docu =~ /(.*\/)/) 10152{ 10153 chop($docu_dir = $1); 10154 $docu_name = $docu; 10155 $docu_name =~ s/.*\///; 10156} 10157else 10158{ 10159 $docu_dir = '.'; 10160 $docu_name = $docu; 10161} 10162unshift(@Texi2HTML::Config::INCLUDE_DIRS, $docu_dir); 10163unshift(@Texi2HTML::Config::INCLUDE_DIRS, @Texi2HTML::Config::PREPEND_DIRS); 10164$docu_name =~ s/\.te?x(i|info)?$//; 10165$docu_name = $Texi2HTML::Config::PREFIX if $Texi2HTML::Config::PREFIX; 10166 10167# resulting files splitting 10168if ($Texi2HTML::Config::SPLIT =~ /section/i) 10169{ 10170 $Texi2HTML::Config::SPLIT = 'section'; 10171} 10172elsif ($Texi2HTML::Config::SPLIT =~ /node/i) 10173{ 10174 $Texi2HTML::Config::SPLIT = 'node'; 10175} 10176elsif ($Texi2HTML::Config::SPLIT =~ /chapter/i) 10177{ 10178 $Texi2HTML::Config::SPLIT = 'chapter'; 10179} 10180else 10181{ 10182 $Texi2HTML::Config::SPLIT = ''; 10183} 10184 10185# Something like backward compatibility 10186if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SUBDIR) 10187{ 10188 $Texi2HTML::Config::OUT = $Texi2HTML::Config::SUBDIR; 10189} 10190 10191# subdir 10192 10193die "output to STDOUT and split or frames incompatible\n" 10194 if (($Texi2HTML::Config::SPLIT or $Texi2HTML::Config::FRAMES) and ($Texi2HTML::Config::OUT eq '-')); 10195 10196if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq '')) 10197{ 10198 $Texi2HTML::Config::OUT = $docu_name; 10199} 10200 10201if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT eq '.')) 10202{# This is to avoid trouble with latex2html 10203 $Texi2HTML::Config::OUT = ''; 10204} 10205 10206$docu_rdir = ''; 10207 10208if ($Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne '')) 10209{ 10210 $Texi2HTML::Config::OUT =~ s|/*$||; 10211 $docu_rdir = "$Texi2HTML::Config::OUT/"; 10212 unless (-d $Texi2HTML::Config::OUT) 10213 { 10214 if ( mkdir($Texi2HTML::Config::OUT, oct(755))) 10215 { 10216 print STDERR "# created directory $Texi2HTML::Config::OUT\n" if ($T2H_VERBOSE); 10217 } 10218 else 10219 { 10220 die "$ERROR can't create directory $Texi2HTML::Config::OUT\n"; 10221 } 10222 } 10223 print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE); 10224} 10225elsif (! $Texi2HTML::Config::SPLIT and ($Texi2HTML::Config::OUT ne '')) 10226{ 10227 if ($Texi2HTML::Config::OUT =~ m|(.*)/|) 10228 {# there is a leading directories 10229 $docu_rdir = "$1/"; 10230 unless (-d $docu_rdir) 10231 { 10232 if ( mkdir($docu_rdir, oct(755))) 10233 { 10234 print STDERR "# created directory $docu_rdir\n" if ($T2H_VERBOSE); 10235 } 10236 else 10237 { 10238 die "$ERROR can't create directory $docu_rdir\n"; 10239 } 10240 } 10241 print STDERR "# putting result files into directory $docu_rdir\n" if ($T2H_VERBOSE); 10242 } 10243 else 10244 { 10245 print STDERR "# putting result files into current directory \n" if ($T2H_VERBOSE); 10246 $docu_rdir = ''; 10247 } 10248} 10249 10250# We don't use "./" as $docu_rdir when $docu_rdir is the current directory 10251# because it is problematic for latex2html. To test writability with -w, 10252# however we need a real directory. 10253my $result_rdir = $docu_rdir; 10254$result_rdir = "." if ($docu_rdir eq ''); 10255unless (-w $result_rdir) 10256{ 10257 $docu_rdir = 'current directory' if ($docu_rdir eq ''); 10258 die "$ERROR $docu_rdir not writable\n"; 10259} 10260 10261# relative path leading to the working directory from the document directory 10262my $path_to_working_dir = $docu_rdir; 10263if ($docu_rdir ne '') 10264{ 10265 my $cwd = cwd; 10266 my $docu_path = $docu_rdir; 10267 $docu_path = $cwd . '/' . $docu_path unless ($docu_path =~ /^\//); 10268 my @result = (); 10269 foreach my $element (split /\//, File::Spec->canonpath($docu_path)) 10270 { 10271 if ($element eq '') 10272 { 10273 push @result, ''; 10274 } 10275 elsif ($element eq '..') 10276 { 10277 if (@result and ($result[-1] eq '')) 10278 { 10279 print STDERR "Too much .. in absolute file name\n"; 10280 } 10281 elsif (@result and ($result[-1] ne '..')) 10282 { 10283 pop @result; 10284 } 10285 else 10286 { 10287 push @result, $element; 10288 } 10289 } 10290 else 10291 { 10292 push @result, $element; 10293 } 10294 } 10295 $path_to_working_dir = File::Spec->abs2rel($cwd, join ('/', @result)); 10296 $path_to_working_dir =~ s|.*/||; 10297 $path_to_working_dir .= '/' unless($path_to_working_dir eq ''); 10298} 10299 10300# extension 10301if ($Texi2HTML::Config::SHORTEXTN) 10302{ 10303 $docu_ext = "htm"; 10304} 10305 10306$docu_doc = $docu_name . ($docu_ext ? ".$docu_ext" : ""); # document's contents 10307if ($Texi2HTML::Config::SPLIT) 10308{ 10309 $docu_top = $Texi2HTML::Config::TOP_FILE || $docu_doc; 10310 10311 if (defined $Texi2HTML::Config::element_file_name) 10312 { 10313 $docu_toc = &$Texi2HTML::Config::element_file_name 10314 (undef, "toc", $docu_name); 10315 $docu_stoc = &$Texi2HTML::Config::element_file_name 10316 (undef, "stoc", $docu_name); 10317 $docu_foot = &$Texi2HTML::Config::element_file_name 10318 (undef, "foot", $docu_name); 10319 $docu_about = &$Texi2HTML::Config::element_file_name 10320 (undef, "about", $docu_name); 10321 # $docu_top may be overwritten later. 10322 } 10323 if (!defined($docu_toc)) 10324 { 10325 my $default_toc = "${docu_name}_toc"; 10326 $default_toc .= ".$docu_ext" if (defined($docu_ext)); 10327 $docu_toc = $Texi2HTML::Config::TOC_FILE || $default_toc; 10328 } 10329 if (!defined($docu_stoc)) 10330 { 10331 $docu_stoc = "${docu_name}_ovr"; 10332 $docu_stoc .= ".$docu_ext" if (defined($docu_ext)); 10333 } 10334 if (!defined($docu_foot)) 10335 { 10336 $docu_foot = "${docu_name}_fot"; 10337 $docu_foot .= ".$docu_ext" if (defined($docu_ext)); 10338 } 10339 if (!defined($docu_about)) 10340 { 10341 $docu_about = "${docu_name}_abt"; 10342 $docu_about .= ".$docu_ext" if (defined($docu_ext)); 10343 } 10344} 10345else 10346{ 10347 if ($Texi2HTML::Config::OUT) 10348 { 10349 $docu_doc = $Texi2HTML::Config::OUT; 10350 $docu_doc =~ s|.*/||; 10351 } 10352 if (defined $Texi2HTML::Config::element_file_name) 10353 { 10354 my $docu_name = &$Texi2HTML::Config::element_file_name 10355 (undef, "doc", $docu_name); 10356 $docu_top = $docu_name if (defined($docu_name)); 10357 } 10358 $docu_toc = $docu_foot = $docu_stoc = $docu_about = $docu_top = $docu_doc; 10359} 10360 10361# Note that file extension has already been added here. 10362 10363# For use in init files 10364$Texi2HTML::THISDOC{'filename'}->{'top'} = $docu_top; 10365$Texi2HTML::THISDOC{'filename'}->{'foot'} = $docu_foot; 10366$Texi2HTML::THISDOC{'filename'}->{'stoc'} = $docu_stoc; 10367$Texi2HTML::THISDOC{'filename'}->{'about'} = $docu_about; 10368$Texi2HTML::THISDOC{'filename'}->{'toc'} = $docu_toc; 10369$Texi2HTML::THISDOC{'extension'} = $docu_ext; 10370# FIXME document that 10371$Texi2HTML::THISDOC{'out_dir'} = $docu_rdir; 10372$Texi2HTML::THISDOC{'file_base_name'} = $docu_name; 10373 10374 10375my $docu_doc_file = "$docu_rdir$docu_doc"; 10376my $docu_toc_file = "$docu_rdir$docu_toc"; 10377my $docu_stoc_file = "$docu_rdir$docu_stoc"; 10378my $docu_foot_file = "$docu_rdir$docu_foot"; 10379my $docu_about_file = "$docu_rdir$docu_about"; 10380my $docu_top_file = "$docu_rdir$docu_top"; 10381 10382my $docu_frame_file = "$docu_rdir${docu_name}_frame"; 10383$docu_frame_file .= ".$docu_ext" if $docu_ext; 10384my $docu_toc_frame_file = "$docu_rdir${docu_name}_toc_frame"; 10385$docu_toc_frame_file .= ".$docu_ext" if $docu_ext; 10386 10387# 10388# _foo: internal variables to track @foo 10389# 10390foreach my $key ('_author', '_title', '_subtitle', '_shorttitlepage', 10391 '_settitle', '_setfilename', '_shorttitle', '_titlefont') 10392{ 10393 $value{$key} = ''; # prevent -w warnings 10394} 10395my $index; # ref on a hash for the index entries 10396my %indices = (); # hash of indices names containing 10397 #[ $pages, $entries ] (page indices and 10398 # raw index entries) 10399my @index_labels = (); # array corresponding with @?index commands 10400 # constructed during pass_texi, used to 10401 # put labels in pass_text 10402# 10403# initial counters 10404# 10405my $foot_num = 0; 10406my $relative_foot_num = 0; 10407my $idx_num = 0; 10408my $sec_num = 0; 10409my $anchor_num = 0; 10410 10411# 10412# can I use ISO8859 characters? (HTML+) 10413# 10414if ($Texi2HTML::Config::USE_ISO) 10415{ 10416 foreach my $thing (keys(%Texi2HTML::Config::iso_symbols)) 10417 { 10418 next unless exists ($::things_map_ref->{$thing}); 10419 $::things_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing}; 10420 $::pre_map_ref->{$thing} = $Texi2HTML::Config::iso_symbols{$thing}; 10421 $Texi2HTML::Config::simple_format_texi_map{$thing} = $Texi2HTML::Config::iso_symbols{$thing}; 10422 } 10423 # we don't override the user defined quote, but beware that this works 10424 # only if the hardcoded defaults, '`' and "'" match with the defaults 10425 # in the default init file 10426 $Texi2HTML::Config::OPEN_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{'`'} 10427 if (exists($Texi2HTML::Config::iso_symbols{'`'}) and ($Texi2HTML::Config::OPEN_QUOTE_SYMBOL eq '`')); 10428 $Texi2HTML::Config::CLOSE_QUOTE_SYMBOL = $Texi2HTML::Config::iso_symbols{"'"} 10429 if (exists($Texi2HTML::Config::iso_symbols{"'"}) and ($Texi2HTML::Config::CLOSE_QUOTE_SYMBOL eq "'")); 10430} 10431 10432 10433 10434# process a css file 10435sub process_css_file ($$) 10436{ 10437 my $fh =shift; 10438 my $file = shift; 10439 my $in_rules = 0; 10440 my $in_comment = 0; 10441 my $in_import = 0; 10442 my $in_string = 0; 10443 my $rules = []; 10444 my $imports = []; 10445 while (<$fh>) 10446 { 10447 #print STDERR "Line: $_"; 10448 if ($in_rules) 10449 { 10450 push @$rules, $_; 10451 next; 10452 } 10453 my $text = ''; 10454 while (1) 10455 { 10456 #sleep 1; 10457 #print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $_"; 10458 if ($in_comment) 10459 { 10460 if (s/^(.*?\*\/)//) 10461 { 10462 $text .= $1; 10463 $in_comment = 0; 10464 } 10465 else 10466 { 10467 push @$imports, $text . $_; 10468 last; 10469 } 10470 } 10471 elsif (!$in_string and s/^\///) 10472 { # what do '\' do here ? 10473 if (s/^\*//) 10474 { 10475 $text .= '/*'; 10476 $in_comment = 1; 10477 } 10478 else 10479 { 10480 push (@$imports, $text. "\n") if ($text ne ''); 10481 push (@$rules, '/' . $_); 10482 $in_rules = 1; 10483 last; 10484 } 10485 } 10486 elsif (!$in_string and $in_import and s/^([\"\'])//) 10487 { # strings outside of import start rules 10488 $text .= "$1"; 10489 $in_string = quotemeta("$1"); 10490 } 10491 elsif ($in_string and s/^(\\$in_string)//) 10492 { 10493 $text .= $1; 10494 } 10495 elsif ($in_string and s/^($in_string)//) 10496 { 10497 $text .= $1; 10498 $in_string = 0; 10499 } 10500 elsif ((! $in_string and !$in_import) and (s/^([\\]?\@import)$// or s/^([\\]?\@import\s+)//)) 10501 { 10502 $text .= $1; 10503 $in_import = 1; 10504 } 10505 elsif (!$in_string and $in_import and s/^\;//) 10506 { 10507 $text .= ';'; 10508 $in_import = 0; 10509 } 10510 elsif (($in_import or $in_string) and s/^(.)//) 10511 { 10512 $text .= $1; 10513 } 10514 elsif (!$in_import and s/^([^\s])//) 10515 { 10516 push (@$imports, $text. "\n") if ($text ne ''); 10517 push (@$rules, $1 . $_); 10518 $in_rules = 1; 10519 last; 10520 } 10521 elsif (s/^(\s)//) 10522 { 10523 $text .= $1; 10524 } 10525 elsif ($_ eq '') 10526 { 10527 push (@$imports, $text); 10528 last; 10529 } 10530 } 10531 } 10532 warn "$WARN string not closed in css file $file\n" if ($in_string); 10533 warn "$WARN comment not closed in css file $file\n" if ($in_comment); 10534 warn "$WARN \@import not finished in css file $file\n" if ($in_import and !$in_comment and !$in_string); 10535 return ($imports, $rules); 10536} 10537 10538 10539 10540# parse texinfo cnf file for external manual specifications. This was 10541# discussed on texinfo list but not in makeinfo for now. 10542my @texinfo_htmlxref_files = locate_init_file ($texinfo_htmlxref, 1, \@texinfo_config_dirs); 10543foreach my $file (@texinfo_htmlxref_files) 10544{ 10545 print STDERR "html refs config file: $file\n" if ($T2H_DEBUG); 10546 unless (open (HTMLXREF, $file)) 10547 { 10548 warn "Cannot open html refs config file ${file}: $!"; 10549 next; 10550 } 10551 while (<HTMLXREF>) 10552 { 10553 my $line = $_; 10554 s/[#]\s.*//; 10555 s/^\s*//; 10556 next if /^\s*$/; 10557 my @htmlxref = split /\s+/; 10558 my $manual = shift @htmlxref; 10559 my $split_or_mono = shift @htmlxref; 10560 if (!defined($split_or_mono) or ($split_or_mono ne 'split' and $split_or_mono ne 'mono')) 10561 { 10562 echo_warn("Bad line in $file: $line"); 10563 next; 10564 } 10565 my $href = shift @htmlxref; 10566 next if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}) and exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'})); 10567 10568 if (defined($href)) 10569 { 10570 $href =~ s/\/*$// if ($split_or_mono eq 'split'); 10571 $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono}->{'href'} = $href; 10572 } 10573 else 10574 { 10575 $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split_or_mono} = {}; 10576 } 10577 } 10578 close (HTMLXREF); 10579} 10580 10581if ($T2H_DEBUG) 10582{ 10583 foreach my $manual (keys(%{$Texi2HTML::THISDOC{'htmlxref'}})) 10584 { 10585 foreach my $split ('split', 'mono') 10586 { 10587 my $href = 'NO'; 10588 next unless (exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split})); 10589 $href = $Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split}->{'href'} if 10590 exists($Texi2HTML::THISDOC{'htmlxref'}->{$manual}->{$split}->{'href'}); 10591 print STDERR "$manual: $split, href: $href\n"; 10592 } 10593 } 10594} 10595 10596print STDERR "# reading from $docu\n" if $T2H_VERBOSE; 10597 10598#+++########################################################################### 10599# # 10600# Pass texi: read source, handle variable, ignored text, # 10601# # 10602#---########################################################################### 10603 10604my @fhs = (); # hold the file handles to read 10605my $input_spool; # spooled lines to read 10606my @lines = (); # whole document 10607my @lines_numbers = (); # line number, originating file associated with 10608 # whole document 10609my $macros; # macros. reference on a hash 10610my %info_enclose; # macros defined with definfoenclose 10611my $texi_line_number = { 'file_name' => '', 'line_nr' => 0, 'macro' => '' }; 10612my @floats = (); # floats list 10613my %floats = (); # floats by style 10614 10615sub initialise_state_texi($) 10616{ 10617 my $state = shift; 10618 $state->{'texi'} = 1; # for substitute_text and close_stack: 10619 # 1 if pass_texi/scan_texi is to be used 10620 $state->{'macro_inside'} = 0 unless(defined($state->{'macro_inside'})); 10621 $state->{'ifvalue_inside'} = 0 unless(defined($state->{'ifvalue_inside'})); 10622 $state->{'arg_expansion'} = 0 unless(defined($state->{'arg_expansion'})); 10623} 10624 10625my @first_lines = (); 10626 10627sub pass_texi() 10628{ 10629 my $first_lines = 1; # is it the first lines 10630 my $state = {}; 10631 # holds the informations about the context 10632 # to pass it down to the functions 10633 initialise_state_texi($state); 10634 my @stack; 10635 my $text; 10636 INPUT_LINE: while (defined($_ = next_line($texi_line_number))) 10637 { 10638 # 10639 # remove the lines preceding \input or an @-command 10640 # 10641 if ($first_lines) 10642 { 10643 if (/^\\input/) 10644 { 10645 push @first_lines, $_; 10646 $first_lines = 0; 10647 next; 10648 } 10649 if (/^\s*\@/) 10650 { 10651 $first_lines = 0; 10652 } 10653 else 10654 { 10655 push @first_lines, $_; 10656 next; 10657 } 10658 } 10659 #print STDERR "PASS_TEXI($texi_line_number->{'line_nr'})$_"; 10660 my $chomped_line = $_; 10661 if (scan_texi ($_, \$text, \@stack, $state, $texi_line_number) and chomp($chomped_line)) 10662 { 10663 #print STDERR "==> new page (line_nr $texi_line_number->{'line_nr'},$texi_line_number->{'file_name'},$texi_line_number->{'macro'})\n"; 10664 push (@lines_numbers, { 'file_name' => $texi_line_number->{'file_name'}, 10665 'line_nr' => $texi_line_number->{'line_nr'}, 10666 'macro' => $texi_line_number->{'macro'} }); 10667 } 10668 #dump_stack (\$text, \@stack, $state); 10669 if ($state->{'bye'}) 10670 { 10671 #dump_stack(\$text, \@stack, $state); 10672 # close stack after bye 10673 #print STDERR "close stack after bye\n"; 10674 close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number); 10675 #dump_stack(\$text, \@stack, $state); 10676 } 10677 next if (@stack); 10678 $_ = $text; 10679 $text = ''; 10680 if (!defined($_)) 10681 {# FIXME: remove the error message if it is reported too often 10682 print STDERR "# \$_ undefined after scan_texi. This may be a bug, or not.\n"; 10683 print STDERR "# Report (with texinfo file) if you want, otherwise ignore that message.\n"; 10684 next unless ($state->{'bye'}); 10685 } 10686 push @lines, split_lines($_); 10687 last if ($state->{'bye'}); 10688 } 10689 # close stack at the end of pass texi 10690 #print STDERR "close stack at the end of pass texi\n"; 10691 close_stack_texi_structure(\$text, \@stack, $state, $texi_line_number); 10692 push @lines, split_lines($text); 10693 print STDERR "# end of pass texi\n" if $T2H_VERBOSE; 10694} 10695 10696# return the line after preserving things according to misc_command map. 10697sub preserve_command($$) 10698{ 10699 my $line = shift; 10700 my $macro = shift; 10701 my $text = ''; 10702 my $args = ''; 10703 my $skip_spec = ''; 10704 my $arg_spec = ''; 10705 10706 $skip_spec = $Texi2HTML::Config::misc_command{$macro}->{'skip'} 10707 if (defined($Texi2HTML::Config::misc_command{$macro}->{'skip'})); 10708 $arg_spec = $Texi2HTML::Config::misc_command{$macro}->{'arg'} 10709 if (defined($Texi2HTML::Config::misc_command{$macro}->{'arg'})); 10710 10711 if ($arg_spec eq 'line') 10712 { 10713 $text .= $line; 10714 $args .= $line; 10715 $line = ''; 10716 } 10717 elsif ($arg_spec) 10718 { 10719 my $arg_nr = $Texi2HTML::Config::misc_command{$macro}->{'arg'}; 10720 while ($arg_nr) 10721 { 10722 $line =~ s/(\s+\S*)//o; 10723 $text .= $1 if defined($1); 10724 $args .= $1 if defined($1); 10725 $arg_nr--; 10726 } 10727 } 10728 10729 if ($macro eq 'bye') 10730 { 10731 $line = ''; 10732 $text = "\n"; 10733 } 10734 elsif ($skip_spec eq 'linespace') 10735 { 10736 if ($line =~ /^\s*$/o) 10737 { 10738 $line =~ s/([ \t]*)//o; 10739 $text .= $1; 10740 } 10741 } 10742 elsif ($skip_spec eq 'linewhitespace') 10743 { 10744 if ($line =~ /^\s*$/o) 10745 { 10746 $text .= $line; 10747 $line = ''; 10748 } 10749 } 10750 elsif ($skip_spec eq 'line') 10751 { 10752 $text .= $line; 10753 $line = ''; 10754 } 10755 elsif ($skip_spec eq 'whitespace') 10756 { 10757 $line =~ s/(\s*)//o; 10758 $text .= $1; 10759 } 10760 elsif ($skip_spec eq 'space') 10761 { 10762 $line =~ s/([ \t]*)//o; 10763 $text .= $1; 10764 } 10765 $line = '' if (!defined($line)); 10766 return ($line, $text, $args); 10767} 10768 10769#+++########################################################################### 10770# # 10771# Pass structure: parse document structure # 10772# # 10773#---########################################################################### 10774 10775# This is a virtual element for things appearing before @node and 10776# sectionning commands 10777my $element_before_anything = 10778{ 10779 'before_anything' => 1, 10780 'place' => [], 10781 'texi' => 'VIRTUAL ELEMENT BEFORE ANYTHING', 10782}; 10783 10784# This is a place for index entries, anchors and so on appearing in 10785# copying or documentdescription 10786my $region_place = []; 10787 10788sub initialise_state_structure($) 10789{ 10790 my $state = shift; 10791 $state->{'structure'} = 1; # for substitute_text and close_stack: 10792 # 1 if pass_structure/scan_structure is 10793 # to be used 10794 $state->{'menu'} = 0; # number of opened menus 10795 $state->{'detailmenu'} = 0; # number of opened detailed menus 10796 $state->{'sectionning_base'} = 0; # current base sectionning level 10797 $state->{'table_stack'} = [ "no table" ]; # a stack of opened tables/lists 10798 if (exists($state->{'region_lines'}) and !defined($state->{'region_lines'})) 10799 { 10800 delete ($state->{'region_lines'}); 10801 print STDERR "Bug: state->{'region_lines'} exists but undef.\n"; 10802 } 10803} 10804 10805my @doc_lines = (); # whole document 10806my @doc_numbers = (); # whole document line numbers and file names 10807my @nodes_list = (); # nodes in document reading order 10808 # each member is a reference on a hash 10809my @sections_list = (); # sections in reading order 10810 # each member is a reference on a hash 10811my @all_elements = (); # sectionning elements (nodes and sections) 10812 # in reading order. Each member is a reference 10813 # on a hash which also appears in %nodes, 10814 # @sections_list @nodes_list, @elements_list 10815my @elements_list; # all the resulting elements in document order 10816my %sections = (); # sections hash. The key is the section number 10817 # headings are there, although they are not elements 10818my $section_top; # @top section 10819my $element_top; # Top element 10820my $node_top; # Top node 10821my $node_first; # First node 10822my $element_index; # element with first index 10823my $element_chapter_index; # chapter with first index 10824my $element_first; # first element 10825my $element_last; # last element 10826my %special_commands; # hash for the commands specially handled 10827 # by the user 10828 10829# This is a virtual element used to have the right hrefs for index entries 10830# and anchors in footnotes 10831my $footnote_element = 10832{ 10833 'id' => 'SEC_Foot', 10834 'file' => $docu_foot, 10835 'footnote' => 1, 10836 'element' => 1, 10837 'place' => [], 10838}; 10839 10840my %content_element = 10841( 10842 'contents' => { 'id' => 'SEC_Contents', 'contents' => 1, 'texi' => '_contents' }, 10843 'shortcontents' => { 'id' => 'SEC_Overview', 'shortcontents' => 1, 'texi' => '_shortcontents' }, 10844); 10845 10846#my $do_contents; # do table of contents if true 10847#my $do_scontents; # do short table of contents if true 10848my $novalidate = $Texi2HTML::Config::NOVALIDATE; # @novalidate appeared 10849 10850sub pass_structure() 10851{ 10852 my $state = {}; 10853 # holds the informations about the context 10854 # to pass it down to the functions 10855 initialise_state_structure($state); 10856 $state->{'element'} = $element_before_anything; 10857 $state->{'place'} = $element_before_anything->{'place'}; 10858 my @stack; 10859 my $text; 10860 my $line_nr; 10861 10862 while (@lines) 10863 { 10864 $_ = shift @lines; 10865 my $chomped_line = $_; 10866 if (!chomp($chomped_line) and @lines) 10867 { 10868 $lines[0] = $_ . $lines[0]; 10869 next; 10870 } 10871 $line_nr = shift (@lines_numbers); 10872 #print STDERR "PASS_STRUCTURE: $_"; 10873 if (!$state->{'raw'} and !$state->{'verb'}) 10874 { 10875 my $tag = ''; 10876 if (/^\s*\@(\w+)\b/) 10877 { 10878 $tag = $1; 10879 } 10880 10881 # 10882 # analyze the tag 10883 # 10884 if ($tag and $tag eq 'node' or defined($sec2level{$tag}) or $tag eq 'printindex') 10885 { 10886 $_ = substitute_texi_line($_); 10887 if ($tag eq 'node' or defined($sec2level{$tag})) 10888 {# in pass structure node shouldn't appear in formats 10889 close_stack_texi_structure(\$text, \@stack, $state, $line_nr); 10890 if (exists($state->{'region_lines'})) 10891 { 10892 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($text); 10893 close_region($state); 10894 } 10895 else 10896 { 10897 push @doc_lines, split_lines($text); 10898 } 10899 $text = ''; 10900 } 10901 if ($tag eq 'node') 10902 { 10903 my $node_ref; 10904 my $auto_directions; 10905 $auto_directions = 1 unless (/,/o); 10906 my ($node, $node_next, $node_prev, $node_up) = split(/,/, $_); 10907 $node =~ s/^\@node\s+// if ($node); 10908 if ($node) 10909 { 10910 $node = normalise_space($node); 10911 if (exists($nodes{$node}) and defined($nodes{$node}) 10912 and $nodes{$node}->{'seen'}) 10913 { 10914 echo_error ("Duplicate node found: $node", $line_nr); 10915 next; 10916 } 10917 else 10918 { 10919 if (exists($nodes{$node}) and defined($nodes{$node})) 10920 { # node appeared in a menu 10921 $node_ref = $nodes{$node}; 10922 } 10923 else 10924 { 10925 my $first; 10926 $first = 1 if (!defined($node_ref)); 10927 $node_ref = {}; 10928 $node_first = $node_ref if ($first); 10929 $nodes{$node} = $node_ref; 10930 } 10931 $node_ref->{'node'} = 1; 10932 $node_ref->{'tag'} = 'node'; 10933 $node_ref->{'tag_level'} = 'node'; 10934 $node_ref->{'texi'} = $node; 10935 $node_ref->{'seen'} = 1; 10936 $node_ref->{'automatic_directions'} = $auto_directions; 10937 $node_ref->{'place'} = []; 10938 $node_ref->{'current_place'} = []; 10939 merge_element_before_anything($node_ref); 10940 $node_ref->{'index_names'} = []; 10941 $state->{'place'} = $node_ref->{'current_place'}; 10942 $state->{'element'} = $node_ref; 10943 $state->{'after_element'} = 1; 10944 $state->{'node_ref'} = $node_ref; 10945 # makeinfo treats differently case variants of 10946 # top in nodes and anchors and in refs commands and 10947 # refs from nodes. 10948 if ($node =~ /^top$/i) 10949 { 10950 if (!defined($node_top)) 10951 { 10952 $node_top = $node_ref; 10953 $node_top->{'texi'} = 'Top'; 10954 delete $nodes{$node}; 10955 $nodes{$node_top->{'texi'}} = $node_ref; 10956 } 10957 else 10958 { # All the refs are going to point to the first Top 10959 echo_warn ("Top node allready exists", $line_nr); 10960 #warn "$WARN Top node allready exists\n"; 10961 } 10962 } 10963 unless (@nodes_list) 10964 { 10965 $node_ref->{'first'} = 1; 10966 } 10967 push (@nodes_list, $node_ref); 10968 push @all_elements, $node_ref; 10969 } 10970 } 10971 else 10972 { 10973 echo_error ("Node is undefined: $_ (eg. \@node NODE-NAME, NEXT, PREVIOUS, UP)", $line_nr); 10974 next; 10975 } 10976 10977 if ($node_next) 10978 { 10979 $node_ref->{'node_next'} = normalise_node($node_next); 10980 } 10981 if ($node_prev) 10982 { 10983 $node_ref->{'node_prev'} = normalise_node($node_prev); 10984 } 10985 if ($node_up) 10986 { 10987 $node_ref->{'node_up'} = normalise_node($node_up); 10988 } 10989 } 10990 elsif (defined($sec2level{$tag})) 10991 { # section or heading 10992 if (/^\@$tag\s*(.*)$/) 10993 { 10994 my $name = normalise_space($1); 10995 $name = '' if (!defined($name)); 10996 my $level = $sec2level{$tag}; 10997 $state->{'after_element'} = 1; 10998 my ($docid, $num); 10999 if($tag ne 'top') 11000 { 11001 $sec_num++; 11002 $num = $sec_num; 11003 $docid = "SEC$sec_num"; 11004 } 11005 else 11006 { 11007 $num = 0; 11008 $docid = "SEC_Top"; 11009 } 11010 if ($tag !~ /heading/) 11011 { 11012 my $section_ref = { 'texi' => $name, 11013 'level' => $level, 11014 'tag' => $tag, 11015 'sec_num' => $num, 11016 'section' => 1, 11017 'id' => $docid, 11018 'seen' => 1, 11019 'index_names' => [], 11020 'current_place' => [], 11021 'place' => [] 11022 }; 11023 11024 if ($tag eq 'top') 11025 { 11026 $section_ref->{'top'} = 1; 11027 $section_ref->{'number'} = ''; 11028 $sections{0} = $section_ref; 11029 $section_top = $section_ref; 11030 } 11031 $sections{$num} = $section_ref; 11032 merge_element_before_anything($section_ref); 11033 if ($state->{'node_ref'} and !exists($state->{'node_ref'}->{'with_section'})) 11034 { 11035 my $node_ref = $state->{'node_ref'}; 11036 $section_ref->{'node_ref'} = $node_ref; 11037 $section_ref->{'titlefont'} = $node_ref->{'titlefont'}; 11038 $node_ref->{'with_section'} = $section_ref; 11039 $node_ref->{'top'} = 1 if ($tag eq 'top'); 11040 } 11041 if (! $name and $level) 11042 { 11043 echo_warn ("$tag without name", $line_nr); 11044 } 11045 push @sections_list, $section_ref; 11046 push @all_elements, $section_ref; 11047 $state->{'element'} = $section_ref; 11048 $state->{'place'} = $section_ref->{'current_place'}; 11049 my $node_ref = "NO NODE"; 11050 my $node_texi =''; 11051 if ($state->{'node_ref'}) 11052 { 11053 $node_ref = $state->{'node_ref'}; 11054 $node_texi = $state->{'node_ref'}->{'texi'}; 11055 } 11056 print STDERR "# pass_structure node($node_ref)$node_texi, tag \@$tag($level) ref $section_ref, num,id $num,$docid\n $name\n" 11057 if $T2H_DEBUG & $DEBUG_ELEMENTS; 11058 } 11059 else 11060 { 11061 my $section_ref = { 'texi' => $name, 11062 'level' => $level, 11063 'heading' => 1, 11064 'tag' => $tag, 11065 'tag_level' => $tag, 11066 'sec_num' => $sec_num, 11067 'id' => $docid, 11068 'number' => '' }; 11069 $state->{'element'} = $section_ref; 11070 push @{$state->{'place'}}, $section_ref; 11071 $sections{$sec_num} = $section_ref; 11072 } 11073 } 11074 } 11075 elsif (/^\@printindex\s+(\w+)/) 11076 { 11077 unless (@all_elements) 11078 { 11079 echo_warn ("Printindex before document beginning: \@printindex $1", $line_nr); 11080 next; 11081 } 11082 delete $state->{'after_element'}; 11083 # $element_index is the first element with index 11084 $element_index = $all_elements[-1] unless (defined($element_index)); 11085 # associate the index to the element such that the page 11086 # number is right 11087 my $placed_elements = []; 11088 push @{$all_elements[-1]->{'index_names'}}, { 'name' => $1, 'place' => $placed_elements }; 11089 $state->{'place'} = $placed_elements; 11090 } 11091 if (exists($state->{'region_lines'})) 11092 { 11093 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, $_; 11094 } 11095 else 11096 { 11097 push @doc_lines, $_; 11098 push @doc_numbers, $line_nr; 11099 } 11100 next; 11101 } 11102 } 11103 if (scan_structure ($_, \$text, \@stack, $state, $line_nr) and !(exists($state->{'region_lines'}))) 11104 { 11105 push (@doc_numbers, $line_nr); 11106 } 11107 next if (@stack); 11108 $_ = $text; 11109 $text = ''; 11110 next if (!defined($_)); 11111 if ($state->{'region_lines'}) 11112 { 11113 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, split_lines($_); 11114 } 11115 else 11116 { 11117 push @doc_lines, split_lines($_); 11118 } 11119 } 11120 if (@stack) 11121 {# close stack at the end of pass structure 11122 close_stack_texi_structure(\$text, \@stack, $state, $line_nr); 11123 if ($text) 11124 { 11125 if (exists($state->{'region_lines'})) 11126 { 11127 push @{$region_lines{$state->{'region_lines'}->{'format'}}}, 11128 split_lines($text); 11129 } 11130 else 11131 { 11132 push @doc_lines, split_lines($text); 11133 } 11134 } 11135 } 11136 echo_warn ("At end of document, $state->{'region_lines'}->{'number'} $state->{'region_lines'}->{'format'} not closed") if (exists($state->{'region_lines'})); 11137 print STDERR "# end of pass structure\n" if $T2H_VERBOSE; 11138} 11139 11140# split line at end of line and put each resulting line in an array 11141# FIXME there must be a more perlish way to do it... Not a big deal 11142# as long as it work 11143sub split_lines($) 11144{ 11145 my $line = shift; 11146 my @result = (); 11147 my $i = 0; 11148 while ($line) 11149 { 11150 $result[$i] = ''; 11151 $line =~ s/^(.*)//; 11152 $result[$i] .= $1; 11153 $result[$i] .= "\n" if ($line =~ s/^\n//); 11154 #print STDERR "$i: $result[$i]"; 11155 $i++; 11156 } 11157 return @result; 11158} 11159 11160# handle misc commands and misc command args 11161sub misc_command_structure($$$$) 11162{ 11163 my $line = shift; 11164 my $macro = shift; 11165 my $state = shift; 11166 my $line_nr = shift; 11167 my $text; 11168 my $args; 11169 11170 if ($macro eq 'lowersections') 11171 { 11172 my ($sec, $level); 11173 while (($sec, $level) = each %sec2level) 11174 { 11175 $sec2level{$sec} = $level + 1; 11176 } 11177 $state->{'sectionning_base'}--; 11178 } 11179 elsif ($macro eq 'raisesections') 11180 { 11181 my ($sec, $level); 11182 while (($sec, $level) = each %sec2level) 11183 { 11184 $sec2level{$sec} = $level - 1; 11185 } 11186 $state->{'sectionning_base'}++; 11187 } 11188 elsif (($macro eq 'contents') or ($macro eq 'summarycontents') or ($macro eq 'shortcontents')) 11189 { 11190 if ($macro eq 'contents') 11191 { 11192 $Texi2HTML::Config::DO_CONTENTS = 1; 11193 } 11194 else 11195 { 11196 $macro = 'shortcontents'; 11197 $Texi2HTML::Config::DO_SCONTENTS = 1; 11198 } 11199 push @{$state->{'place'}}, $content_element{$macro}; 11200 } 11201 elsif ($macro eq 'detailmenu') 11202 { 11203 $state->{'detailmenu'}++; 11204 } 11205 elsif ($macro eq 'novalidate') 11206 { 11207 $novalidate = 1; 11208 $Texi2HTML::THISDOC{$macro} = 1; 11209 } 11210 elsif (grep {$_ eq $macro} ('settitle','setfilename','shortitle','shorttitlepage') 11211 and ($line =~ /^\s+(.*)$/)) 11212 { 11213 $value{"_$macro"} = substitute_texi_line($1); 11214 } 11215 elsif (grep {$_ eq $macro} ('author','subtitle','title') 11216 and ($line =~ /^\s+(.*)$/)) 11217 { 11218 $value{"_$macro"} .= substitute_texi_line($1)."\n"; 11219 push @{$Texi2HTML::THISDOC{"${macro}s"}}, substitute_texi_line($1); 11220 } 11221 elsif ($macro eq 'synindex' || $macro eq 'syncodeindex') 11222 { 11223 if ($line =~ /^\s+(\w+)\s+(\w+)/) 11224 { 11225 my $index_from = $1; 11226 my $index_to = $2; 11227 echo_error ("unknown from index name $index_from in \@$macro", $line_nr) 11228 unless $index_names{$index_from}; 11229 echo_error ("unknown to index name $index_to in \@$macro", $line_nr) 11230 unless $index_names{$index_to}; 11231 if ($index_names{$index_from} and $index_names{$index_to}) 11232 { 11233 if ($macro eq 'syncodeindex') 11234 { 11235 $index_names{$index_to}->{'associated_indices_code'}->{$index_from} = 1; 11236 } 11237 else 11238 { 11239 $index_names{$index_to}->{'associated_indices'}->{$index_from} = 1; 11240 } 11241 push @{$Texi2HTML::THISDOC{$macro}}, [$index_from,$index_to]; 11242 } 11243 } 11244 else 11245 { 11246 echo_error ("Bad $macro line: $line", $line_nr); 11247 } 11248 } 11249 elsif ($macro eq 'defindex' || $macro eq 'defcodeindex') 11250 { 11251 if ($line =~ /^\s+(\w+)\s*$/) 11252 { 11253 my $name = $1; 11254 if ($forbidden_index_name{$name}) 11255 { 11256 echo_error("Reserved index name $name", $line_nr); 11257 } 11258 else 11259 { 11260 @{$index_names{$name}->{'prefix'}} = ($name); 11261 $index_names{$name}->{'code'} = 1 if $macro eq 'defcodeindex'; 11262 $index_prefix_to_name{$name} = $name; 11263 push @{$Texi2HTML::THISDOC{$macro}}, $name; 11264 } 11265 } 11266 else 11267 {# makeinfo don't warn and even accepts index with empty name 11268 # and index with numbers only. I reported it on the mailing list 11269 # this should be fixed in future makeinfo versions. 11270 echo_error ("Bad $macro line: $line", $line_nr); 11271 } 11272 } 11273 elsif ($macro eq 'documentlanguage') 11274 { 11275 if ($line =~ /\s+(\w+)/) 11276 { 11277 my $lang = $1; 11278 set_document_language($lang, 0, $line_nr) if (!$cmd_line_lang && $lang); 11279 # warning, this is not the language of the document but the one that 11280 # appear in the texinfo... 11281 $Texi2HTML::THISDOC{$macro} = $lang; 11282 } 11283 } 11284 elsif ($macro eq 'kbdinputstyle') 11285 {# makeinfo ignores that with --html. I reported it and it should be 11286 # fixed in future makeinfo releases 11287 if ($line =~ /\s+([a-z]+)/) 11288 { 11289 if ($1 eq 'code') 11290 { 11291 $::style_map_ref->{'kbd'} = $::style_map_ref->{'code'}; 11292 $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'}; 11293 $Texi2HTML::THISDOC{$macro} = $1; 11294 } 11295 elsif ($1 eq 'example') 11296 { 11297 $::style_map_pre_ref->{'kbd'} = $::style_map_pre_ref->{'code'}; 11298 $Texi2HTML::THISDOC{$macro} = $1; 11299 } 11300 elsif ($1 ne 'distinct') 11301 { 11302 echo_error ("Unknown argument for \@$macro: $1", $line_nr); 11303 } 11304 } 11305 else 11306 { 11307 echo_error ("Bad \@$macro", $line_nr); 11308 } 11309 } 11310 elsif ($macro eq 'paragraphindent') 11311 { 11312 if ($line =~ /\s+([0-9]+)/) 11313 { 11314 $Texi2HTML::THISDOC{$macro} = $1; 11315 } 11316 elsif (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(asis)[^\w\-]/)) 11317 { 11318 $Texi2HTML::THISDOC{$macro} = $1; 11319 } 11320 else 11321 { 11322 echo_error ("Bad \@$macro", $line_nr); 11323 } 11324 } 11325 elsif ($macro eq 'firstparagraphindent') 11326 { 11327 if (($line =~ /\s+(none)[^\w\-]/) or ($line =~ /\s+(insert)[^\w\-]/)) 11328 { 11329 $Texi2HTML::THISDOC{$macro} = $1; 11330 } 11331 else 11332 { 11333 echo_error ("Bad \@$macro", $line_nr); 11334 } 11335 } 11336 elsif ($macro eq 'exampleindent') 11337 { 11338 if ($line =~ /^\s+([0-9]+)/) 11339 { 11340 $Texi2HTML::THISDOC{$macro} = $1; 11341 } 11342 elsif ($line =~ /^\s+(asis)[^\w\-]/) 11343 { 11344 $Texi2HTML::THISDOC{$macro} = $1; 11345 } 11346 else 11347 { 11348 echo_error ("Bad \@$macro", $line_nr); 11349 } 11350 } 11351 elsif ($macro eq 'frenchspacing') 11352 { 11353 if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/)) 11354 { 11355 $Texi2HTML::THISDOC{$macro} = $1; 11356 } 11357 else 11358 { 11359 echo_error ("Bad \@$macro", $line_nr); 11360 } 11361 } 11362 elsif ($macro eq 'footnotestyle') 11363 { 11364 if (($line =~ /^\s+(end)[^\w\-]/) or ($line =~ /^\s+(separate)[^\w\-]/)) 11365 { 11366 $Texi2HTML::THISDOC{$macro} = $1; 11367 } 11368 else 11369 { 11370 echo_error ("Bad \@$macro", $line_nr); 11371 } 11372 } 11373 elsif ($macro eq 'headings') 11374 { 11375 my $valid_arg = 0; 11376 foreach my $possible_arg (('off','on','single','double', 11377 'singleafter','doubleafter')) 11378 { 11379 if ($line =~ /^\s+($possible_arg)[^\w\-]/) 11380 { 11381 $valid_arg = 1; 11382 $Texi2HTML::THISDOC{$macro} = $possible_arg; 11383 last; 11384 } 11385 } 11386 unless ($valid_arg) 11387 { 11388 echo_error ("Bad \@$macro", $line_nr); 11389 } 11390 } 11391 elsif ($macro eq 'setchapternewpage') 11392 { 11393 if (($line =~ /^\s+(on)[^\w\-]/) or ($line =~ /^\s+(off)[^\w\-]/) 11394 or ($line =~ /^\s+(odd)[^\w\-]/)) 11395 { 11396 $Texi2HTML::THISDOC{$macro} = $1; 11397 } 11398 else 11399 { 11400 echo_error ("Bad \@$macro", $line_nr); 11401 } 11402 } 11403 elsif ($macro eq 'setcontentsaftertitlepage' or $macro eq 'setshortcontentsaftertitlepage') 11404 { 11405 $Texi2HTML::THISDOC{$macro} = 1; 11406 my $tag = 'contents'; 11407 $tag = 'shortcontents' if ($macro ne 'setcontentsaftertitlepage'); 11408 $content_element{$tag}->{'aftertitlepage'} = 1; 11409 } 11410 elsif (grep {$macro eq $_} ('everyheading', 'everyfooting', 11411 'evenheading', 'evenfooting', 'oddheading', 'oddfooting')) 11412 { 11413 my $arg = $line; 11414 $arg =~ s/^\s+//; 11415 $Texi2HTML::THISDOC{$macro} = $arg; 11416 } 11417 elsif ($macro eq 'need') 11418 { 11419 unless (($line =~ /^\s+([0-9]+(\.[0-9]*)?)[^\w\-]/) or 11420 ($line =~ /^\s+(\.[0-9]+)[^\w\-]/)) 11421 { 11422 echo_warn ("Bad \@$macro", $line_nr); 11423 } 11424 } 11425 11426 ($text, $line, $args) = preserve_command($line, $macro); 11427 return ($text, $line); 11428} 11429 11430# return the line after removing things according to misc_command map. 11431# if the skipped macro has an effect it is done here 11432# this is used during pass_text 11433sub misc_command_text($$$$$$) 11434{ 11435 my $line = shift; 11436 my $macro = shift; 11437 my $stack = shift; 11438 my $state = shift; 11439 my $text = shift; 11440 my $line_nr = shift; 11441 my ($skipped, $remaining, $args); 11442 # if it is true the command args are kept so the user can modify how 11443 # they are skipped and handle them as unknown @-commands 11444 my $keep = $Texi2HTML::Config::misc_command{$macro}->{'keep'}; 11445 11446 if ($macro eq 'detailmenu') 11447 { 11448 $state->{'detailmenu'}++; 11449 } 11450 elsif ($macro eq 'sp') 11451 { 11452 my $sp_number; 11453 if ($line =~ /^\s+(\d+)\s/) 11454 { 11455 $sp_number = $1; 11456 } 11457 elsif ($line =~ /(\s*)$/) 11458 { 11459 $sp_number = ''; 11460 } 11461 else 11462 { 11463 echo_error ("\@$macro needs a numeric arg or no arg", $line_nr); 11464 } 11465 $sp_number = 1 if ($sp_number eq ''); 11466 if (!$state->{'remove_texi'}) 11467 { 11468 add_prev($text, $stack, &$Texi2HTML::Config::sp($sp_number, $state->{'preformatted'})); 11469 } 11470 } 11471 elsif($macro eq 'verbatiminclude' and !$keep) 11472 { 11473 if ($line =~ /\s+(.+)/) 11474 { 11475 my $arg = $1; 11476 my $file = locate_include_file($arg); 11477 if (defined($file)) 11478 { 11479 if (!open(VERBINCLUDE, $file)) 11480 { 11481 echo_warn ("Can't read file $file: $!",$line_nr); 11482 } 11483 else 11484 { 11485 my $verb_text = ''; 11486 while (my $line = <VERBINCLUDE>) 11487 { 11488 $verb_text .= $line; 11489 } 11490 11491 if ($state->{'remove_texi'}) 11492 { 11493 add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi('verbatim', $verb_text)); 11494 } 11495 else 11496 { 11497 add_prev($text, $stack, &$Texi2HTML::Config::raw('verbatim', $verb_text)); 11498 } 11499 close VERBINCLUDE; 11500 } 11501 } 11502 else 11503 { 11504 echo_error ("Can't find $arg, skipping", $line_nr); 11505 } 11506 } 11507 else 11508 { 11509 echo_error ("Bad \@$macro line: $_", $line_nr); 11510 } 11511 } 11512 elsif ($macro eq 'indent' or $macro eq 'noindent') 11513 { 11514 $state->{'paragraph_indent'} = $macro; 11515 } 11516 ($remaining, $skipped, $args) = preserve_command($line, $macro); 11517 return ($skipped) if ($keep); 11518 return $remaining if ($remaining ne ''); 11519 return undef; 11520} 11521 11522# merge the things appearing before the first @node or sectionning command 11523# (held by element_before_anything) with the current element 11524# do that only once. 11525sub merge_element_before_anything($) 11526{ 11527 my $element = shift; 11528 if (exists($element_before_anything->{'place'})) 11529 { 11530 $element->{'current_place'} = $element_before_anything->{'place'}; 11531 delete $element_before_anything->{'place'}; 11532 foreach my $placed_thing (@{$element->{'current_place'}}) 11533 { 11534 $placed_thing->{'element'} = $element if (exists($placed_thing->{'element'})); 11535 } 11536 } 11537 # this is certainly redundant with the above condition, but cleaner 11538 # that way 11539 if (exists($element_before_anything->{'titlefont'})) 11540 { 11541 $element->{'titlefont'} = $element_before_anything->{'titlefont'}; 11542 delete $element_before_anything->{'titlefont'}; 11543 } 11544} 11545 11546# find menu_prev, menu_up... for a node in menu 11547sub menu_entry_texi($$$) 11548{ 11549 my $node = shift; 11550 my $state = shift; 11551 my $line_nr = shift; 11552 my $node_menu_ref = {}; 11553 if (exists($nodes{$node})) 11554 { 11555 $node_menu_ref = $nodes{$node}; 11556 } 11557 else 11558 { 11559 $nodes{$node} = $node_menu_ref; 11560 $node_menu_ref->{'texi'} = $node; 11561 $node_menu_ref->{'external_node'} = 1 if ($node =~ /\(.+\)/); 11562 } 11563 return if ($state->{'detailmenu'}); 11564 if ($state->{'node_ref'}) 11565 { 11566 $node_menu_ref->{'menu_up'} = $state->{'node_ref'}; 11567 $node_menu_ref->{'menu_up_hash'}->{$state->{'node_ref'}->{'texi'}} = 1; 11568 } 11569 else 11570 { 11571 echo_warn ("menu entry without previous node: $node", $line_nr) unless ($node =~ /\(.+\)/); 11572 } 11573 if ($state->{'prev_menu_node'}) 11574 { 11575 $node_menu_ref->{'menu_prev'} = $state->{'prev_menu_node'}; 11576 $state->{'prev_menu_node'}->{'menu_next'} = $node_menu_ref; 11577 } 11578 elsif ($state->{'node_ref'}) 11579 { 11580 $state->{'node_ref'}->{'menu_child'} = $node_menu_ref; 11581 } 11582 $state->{'prev_menu_node'} = $node_menu_ref; 11583} 11584 11585sub equivalent_nodes($) 11586{ 11587 my $name = shift; 11588#print STDERR "equivalent_nodes $name\n"; 11589 my $node = normalise_node($name); 11590 $name = cross_manual_line($node); 11591 my @equivalent_nodes = (); 11592 if (exists($cross_reference_nodes{$name})) 11593 { 11594 @equivalent_nodes = grep {$_ ne $node} @{$cross_reference_nodes{$name}}; 11595 } 11596 return @equivalent_nodes; 11597} 11598 11599my %files = (); # keys are files. This is used to avoid reusing an allready 11600 # used file name 11601my %empty_indices = (); # value is true for an index name key if the index 11602 # is empty 11603my %printed_indices = (); # value is true for an index name not empty and 11604 # printed 11605 11606# find next, prev, up, back, forward, fastback, fastforward 11607# find element id and file 11608# split index pages 11609# associate placed items (items which have links to them) with the right 11610# file and id 11611# associate nodes with sections 11612sub rearrange_elements() 11613{ 11614 print STDERR "# find sections levels and toplevel\n" 11615 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11616 11617 my $toplevel = 4; 11618 # correct level if raisesections or lowersections overflowed 11619 # and find toplevel level 11620 # use %sections to modify also the headings 11621 foreach my $section (values(%sections)) 11622 { 11623 my $level = $section->{'level'}; 11624 if ($level > $MAX_LEVEL) 11625 { 11626 $section->{'level'} = $MAX_LEVEL; 11627 } 11628 elsif ($level < $MIN_LEVEL and !$section->{'top'}) 11629 { 11630 $section->{'level'} = $MIN_LEVEL; 11631 } 11632 else 11633 { 11634 $section->{'level'} = $level; 11635 } 11636 $section->{'toc_level'} = $section->{'level'}; 11637 # This is for top 11638 $section->{'toc_level'} = $MIN_LEVEL if ($section->{'level'} < $MIN_LEVEL); 11639 # find the new tag corresponding with the level of the section 11640 if ($section->{'tag'} !~ /heading/ and ($level ne $reference_sec2level{$section->{'tag'}})) 11641 { 11642 $section->{'tag_level'} = $level2sec{$section->{'tag'}}->[$section->{'level'}]; 11643 } 11644 else 11645 { 11646 $section->{'tag_level'} = $section->{'tag'}; 11647 } 11648 $toplevel = $section->{'level'} if (($section->{'level'} < $toplevel) and ($section->{'level'} > 0 and ($section->{'tag'} !~ /heading/))); 11649 print STDERR "# section level $level: $section->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11650 } 11651 11652 print STDERR "# find sections structure, construct section numbers (toplevel=$toplevel)\n" 11653 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11654 my $in_appendix = 0; 11655 # these arrays have an element per sectionning level. 11656 my @previous_numbers = (); # holds the number of the previous sections 11657 # at the same and upper levels 11658 my @previous_sections = (); # holds the ref of the previous sections 11659 11660 foreach my $section (@sections_list) 11661 { 11662 ########################### debug 11663 print STDERR "BUG: node or section_ref defined for section $section->{'texi'}\n" 11664 if (exists($section->{'node'}) or exists($section->{'section_ref'})); 11665 ########################### end debug 11666 next if ($section->{'top'}); 11667 print STDERR "Bug level undef for ($section) $section->{'texi'}\n" if (!defined($section->{'level'})); 11668 $section->{'toplevel'} = 1 if ($section->{'level'} == $toplevel); 11669 # undef things under that section level 11670 for (my $level = $section->{'level'} + 1; $level < $MAX_LEVEL + 1 ; $level++) 11671 { 11672 $previous_numbers[$level] = undef; 11673 $previous_sections[$level] = undef; 11674 } 11675 my $number_set; 11676 # find number at the current level 11677 if ($section->{'tag'} =~ /appendix/ and !$in_appendix) 11678 { 11679 $previous_numbers[$toplevel] = 'A'; 11680 $in_appendix = 1; 11681 $number_set = 1 if ($section->{'level'} == $toplevel); 11682 } 11683 if (!defined($previous_numbers[$section->{'level'}]) and !$number_set) 11684 { 11685 if ($section->{'tag'} =~ /unnumbered/) 11686 { 11687 $previous_numbers[$section->{'level'}] = undef; 11688 } 11689 else 11690 { 11691 $previous_numbers[$section->{'level'}] = 1; 11692 } 11693 } 11694 elsif ($section->{'tag'} !~ /unnumbered/ and !$number_set) 11695 { 11696 $previous_numbers[$section->{'level'}]++; 11697 } 11698 # construct the section number 11699 $section->{'number'} = ''; 11700 11701 unless ($section->{'tag'} =~ /unnumbered/) 11702 { 11703 my $level = $section->{'level'}; 11704 while ($level > $toplevel) 11705 { 11706 my $number = $previous_numbers[$level]; 11707 $number = 0 if (!defined($number)); 11708 if ($section->{'number'}) 11709 { 11710 $section->{'number'} = "$number.$section->{'number'}"; 11711 } 11712 else 11713 { 11714 $section->{'number'} = $number; 11715 } 11716 $level--; 11717 } 11718 my $toplevel_number = $previous_numbers[$toplevel]; 11719 $toplevel_number = 0 if (!defined($toplevel_number)); 11720 $section->{'number'} = "$toplevel_number.$section->{'number'}"; 11721 } 11722 # find the previous section 11723 if (defined($previous_sections[$section->{'level'}])) 11724 { 11725 my $prev_section = $previous_sections[$section->{'level'}]; 11726 $section->{'sectionprev'} = $prev_section; 11727 $prev_section->{'sectionnext'} = $section; 11728 } 11729 # find the up section 11730 if ($section->{'level'} == $toplevel) 11731 { 11732 $section->{'sectionup'} = undef; 11733 } 11734 else 11735 { 11736 my $level = $section->{'level'} - 1; 11737 while (!defined($previous_sections[$level]) and ($level >= 0)) 11738 { 11739 $level--; 11740 } 11741 if ($level >= 0) 11742 { 11743 $section->{'sectionup'} = $previous_sections[$level]; 11744 # 'child' is the first child 11745 $section->{'sectionup'}->{'child'} = $section unless ($section->{'sectionprev'}); 11746 push @{$section->{'sectionup'}->{'section_childs'}}, $section; 11747 } 11748 else 11749 { 11750 $section->{'sectionup'} = undef; 11751 } 11752 } 11753 $previous_sections[$section->{'level'}] = $section; 11754 # This is what is used in the .init file. 11755 $section->{'up'} = $section->{'sectionup'}; 11756 # Not used but documented. 11757 $section->{'next'} = $section->{'sectionnext'}; 11758 $section->{'prev'} = $section->{'sectionprev'}; 11759 11760 ############################# debug 11761 my $up = "NO_UP"; 11762 $up = $section->{'sectionup'} if (defined($section->{'sectionup'})); 11763 print STDERR "# numbering section ($section->{'level'}): $section->{'number'}: (up: $up) $section->{'texi'}\n" 11764 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11765 ############################# end debug 11766 } 11767 11768 # at that point there are still some node structures that are not 11769 # in %nodes, (the external nodes, and unknown nodes in case 11770 # novalidate is true) so we cannot find the id. The consequence is that 11771 # some node equivalent with another node may not be catched during 11772 # that pass. We mark the nodes that have directions for unreferenced 11773 # nodes and make a second pass for these nodes afterwards. 11774 my @nodes_with_unknown_directions = (); 11775 11776 my @node_directions = ('node_prev', 'node_next', 'node_up'); 11777 # handle nodes 11778 # the node_prev... are texinfo strings, find the associated node references 11779 print STDERR "# Resolve nodes directions\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11780 foreach my $node (@nodes_list) 11781 { 11782 foreach my $direction (@node_directions) 11783 { 11784 if (defined($node->{$direction}) and !ref($node->{$direction}) 11785 and ($node->{$direction} ne '')) 11786 { 11787 if ($nodes{$node->{$direction}} and $nodes{$node->{$direction}}->{'seen'}) 11788 { 11789 $node->{$direction} = $nodes{$node->{$direction}}; 11790 } 11791 elsif (($node->{$direction} =~ /^\(.*\)/) or $novalidate) 11792 { # ref to an external node 11793 if (exists($nodes{$node->{$direction}})) 11794 { 11795 $node->{$direction} = $nodes{$node->{$direction}}; 11796 } 11797 else 11798 { 11799 # FIXME if {'seen'} this is a node appearing in the 11800 # document and a node like `(file)node'. What to 11801 # do then ? 11802 my $node_ref = { 'texi' => $node->{$direction} }; 11803 $node_ref->{'external_node'} = 1 if ($node->{$direction} =~ /^\(.*\)/); 11804 $nodes{$node->{$direction}} = $node_ref; 11805 $node->{$direction} = $node_ref; 11806 } 11807 } 11808 else 11809 { 11810 push @nodes_with_unknown_directions, $node; 11811 } 11812 } 11813 } 11814 } 11815 11816 # Find cross manual links as explained on the texinfo mailing list 11817 # The specification is such that cross manual links formatting should 11818 # be insensitive to the manual split 11819 cross_manual_links(); 11820 11821 # Now it is possible to find the unknown directions that are equivalent 11822 # (have same node id) than an existing node 11823 foreach my $node (@nodes_with_unknown_directions) 11824 { 11825 foreach my $direction (@node_directions) 11826 { 11827 if (defined($node->{$direction}) and !ref($node->{$direction}) 11828 and ($node->{$direction} ne '')) 11829 { 11830 echo_warn ("$direction `$node->{$direction}' for `$node->{'texi'}' not found"); 11831 my @equivalent_nodes = equivalent_nodes($node->{$direction}); 11832 my $node_seen; 11833 foreach my $equivalent_node (@equivalent_nodes) 11834 { 11835 if ($nodes{$equivalent_node}->{'seen'}) 11836 { 11837 $node_seen = $equivalent_node; 11838 last; 11839 } 11840 } 11841 if (defined($node_seen)) 11842 { 11843 echo_warn (" ---> but equivalent node `$node_seen' found"); 11844 $node->{$direction} = $nodes{$node_seen}; 11845 } 11846 else 11847 { 11848 delete $node->{$direction}; 11849 } 11850 } 11851 } 11852 } 11853 11854 # find section preceding and following top 11855 my $section_before_top; # section preceding the top node 11856 my $section_after_top; # section following the top node 11857 if ($node_top) 11858 { 11859 my $previous_is_top = 0; 11860 foreach my $element (@all_elements) 11861 { 11862 if ($element eq $node_top) 11863 { 11864 $previous_is_top = 1; 11865 next; 11866 } 11867 if ($previous_is_top) 11868 { 11869 if ($element->{'section'}) 11870 { 11871 $section_after_top = $element; 11872 last; 11873 } 11874 next; 11875 } 11876 $section_before_top = $element if ($element->{'section'}); 11877 } 11878 } 11879 print STDERR "# section before Top: $section_before_top->{'texi'}\n" 11880 if ($section_before_top and ($T2H_DEBUG & $DEBUG_ELEMENTS)); 11881 print STDERR "# section after Top: $section_after_top->{'texi'}\n" 11882 if ($section_after_top and ($T2H_DEBUG & $DEBUG_ELEMENTS)); 11883 11884 print STDERR "# Build the elements list\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11885 if (!$Texi2HTML::Config::USE_NODES) 11886 { 11887 #the only sectionning elements are sections 11888 @elements_list = @sections_list; 11889 # if there is no section we use nodes... 11890 if (!@elements_list) 11891 { 11892 print STDERR "# no section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11893 @elements_list = @all_elements; 11894 } 11895 elsif (!$section_top and $node_top and !$node_top->{'with_section'}) 11896 { # special case for the top node if it isn't associated with 11897 # a section. The top node element is inserted between the 11898 # $section_before_top and the $section_after_top 11899 print STDERR "# Top not associated with a section\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11900 $node_top->{'top_as_section'} = 1; 11901 $node_top->{'section_ref'} = $node_top; 11902 my @old_element_lists = @elements_list; 11903 @elements_list = (); 11904 while (@old_element_lists) 11905 { 11906 my $section = shift @old_element_lists; 11907 if ($section_before_top and ($section eq $section_before_top)) 11908 { 11909 push @elements_list, $section; 11910 push @elements_list, $node_top; 11911 last; 11912 } 11913 elsif ($section_after_top and ($section eq $section_after_top)) 11914 { 11915 push @elements_list, $node_top; 11916 push @elements_list, $section; 11917 last; 11918 } 11919 push @elements_list, $section; 11920 } 11921 push @elements_list, @old_element_lists; 11922 } 11923 11924 foreach my $element (@elements_list) 11925 { 11926 print STDERR "# new section element $element->{'texi'}\n" 11927 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11928 } 11929 } 11930 else 11931 { 11932 # elements are sections if possible, and node if no section associated 11933 foreach my $element(@all_elements) 11934 { 11935 if ($element->{'node'}) 11936 { 11937 if (!defined($element->{'with_section'})) 11938 { 11939 $element->{'toc_level'} = $MIN_LEVEL if (!defined($element->{'toc_level'})); 11940 print STDERR "# new node element ($element) $element->{'texi'}\n" 11941 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11942 push @elements_list, $element; 11943 } 11944 } 11945 else 11946 { 11947 print STDERR "# new section element ($element) $element->{'texi'}\n" 11948 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11949 push @elements_list, $element; 11950 } 11951 } 11952 } 11953 11954 # nodes are attached to the section preceding them if not allready 11955 # associated with a section 11956 # here we don't set @{$element->{'nodes'}} since it may be changed 11957 # below if split by indices. Therefore we only set 11958 # @{$element->{'all_elements'}} with all the elements associated 11959 # with an element output, in the right order 11960 print STDERR "# Find the section associated with each node\n" 11961 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 11962 my $current_section = $sections_list[0]; 11963 $current_section = $node_top if ($node_top and $node_top->{'top_as_section'} and !$section_before_top); 11964 foreach my $element (@all_elements) 11965 { 11966 if ($element->{'node'} and !$element->{'top_as_section'}) 11967 { 11968 if ($element->{'with_section'}) 11969 { # the node is associated with a section 11970 $element->{'section_ref'} = $element->{'with_section'}; 11971 push @{$element->{'section_ref'}->{'all_elements'}}, $element, $element->{'section_ref'}; 11972 # first index is section if the first index is associated with that node 11973 $element_index = $element->{'section_ref'} if ($element_index and ($element_index eq $element)); 11974 } 11975 elsif (defined($current_section)) 11976 {# node appearing after a section, but not before another section, 11977 # or appearing before any section 11978 $element->{'section_ref'} = $current_section; 11979 $element->{'toc_level'} = $current_section->{'toc_level'}; 11980 push @{$current_section->{'node_childs'}}, $element; 11981 if ($Texi2HTML::Config::USE_NODES) 11982 { # the node is an element itself 11983 push @{$element->{'all_elements'}}, $element; 11984 } 11985 else 11986 { 11987 push @{$current_section->{'all_elements'}}, $element; 11988 # first index is section if the first index is associated with that node 11989 $element_index = $current_section if ($element_index and ($element_index eq $element)); 11990 } 11991 } 11992 else 11993 { # seems like there are only nodes in the documents 11994 $element->{'toc_level'} = $MIN_LEVEL; 11995 push @{$element->{'all_elements'}}, $element; 11996 } 11997 } 11998 else 11999 { 12000 $current_section = $element; 12001 if ($element->{'node'}) 12002 { # Top node not associated with a section 12003 $element->{'toc_level'} = $MIN_LEVEL; 12004 push @{$element->{'section_ref'}->{'all_elements'}}, $element; 12005 } 12006 elsif (!$element->{'node_ref'}) 12007 { # a section not preceded by a node 12008 push @{$element->{'all_elements'}}, $element; 12009 } 12010 } 12011 } 12012 12013 # find first, last and top elements 12014 $element_first = $elements_list[0]; 12015 print STDERR "# element first: $element_first->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12016 print STDERR "# top node: $node_top->{'texi'}\n" if (defined($node_top) and 12017 ($T2H_DEBUG & $DEBUG_ELEMENTS)); 12018 # element top is the element with @top. 12019 $element_top = $section_top; 12020 # If the top node is associated with a section it is the top_element 12021 # otherwise element top may be the top node 12022 $element_top = $node_top if (!defined($element_top) and defined($node_top)); 12023 # If there is no @top section no top node the first node is the top element 12024 $element_top = $element_first unless (defined($element_top)); 12025 $element_top->{'top'} = 1 if ($element_top->{'node'}); 12026 print STDERR "# element top: $element_top->{'texi'}\n" if ($element_top and 12027 ($T2H_DEBUG & $DEBUG_ELEMENTS)); 12028 12029 # It is the last element before indices split, which may add new 12030 # elements 12031 $element_last = $elements_list[-1]; 12032 12033 print STDERR "# Complete nodes next prev and up based on menus and sections\n" 12034 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12035 # set the default id based on the node number 12036 my $node_nr = 1; 12037 # find the node* directions 12038 # find the directions corresponding with sections 12039 # and set 'up' for the node 12040 foreach my $node (@nodes_list) 12041 { 12042 # first a warning if the node and the equivalent nodes don't 12043 # appear in menus 12044 if (!$node->{'first'} and !$node->{'top'} and !$node->{'menu_up'} and ($node->{'texi'} !~ /^top$/i) and $Texi2HTML::Config::SHOW_MENU) 12045 { 12046 my @equivalent_nodes = equivalent_nodes($node->{'texi'}); 12047 my $found = 0; 12048 foreach my $equivalent_node (@equivalent_nodes) 12049 { 12050 if ($nodes{$equivalent_node}->{'first'} or $nodes{$equivalent_node}->{'menu_up'}) 12051 { 12052 $found = 1; 12053 last; 12054 } 12055 } 12056 unless ($found) 12057 { 12058 warn "$WARN `$node->{'texi'}' doesn't appear in menus\n"; 12059 } 12060 } 12061 12062 # use values deduced from menus to complete missing up, next, prev 12063 # or from sectionning commands if automatic sectionning 12064 if ($node->{'node_up'}) 12065 { 12066 $node->{'nodeup'} = $node->{'node_up'}; 12067 } 12068 elsif ($node->{'automatic_directions'} and $node->{'section_ref'}) 12069 { 12070 if (defined($node_top) and ($node eq $node_top)) 12071 { # Top node has a special up, which is (dir) by default 12072 my $top_nodeup = $Texi2HTML::Config::TOP_NODE_UP; 12073 if (exists($nodes{$top_nodeup})) 12074 { 12075 $node->{'nodeup'} = $nodes{$top_nodeup}; 12076 } 12077 else 12078 { 12079 my $node_ref = { 'texi' => $top_nodeup }; 12080 $node_ref->{'external_node'} = 1; 12081 $nodes{$top_nodeup} = $node_ref; 12082 $node->{'nodeup'} = $node_ref; 12083 } 12084 } 12085 elsif (defined($node->{'section_ref'}->{'sectionup'})) 12086 { 12087 $node->{'nodeup'} = get_node($node->{'section_ref'}->{'sectionup'}); 12088 } 12089 elsif ($node->{'section_ref'}->{'toplevel'} and ($node->{'section_ref'} ne $element_top)) 12090 { 12091 $node->{'nodeup'} = get_node($element_top); 12092 } 12093 print STDERR "# Deducing from section node_up $node->{'nodeup'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS and defined($node->{'nodeup'})); 12094 } 12095 12096 if (!$node->{'nodeup'} and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS) 12097 { # makeinfo don't do that 12098 $node->{'nodeup'} = $node->{'menu_up'}; 12099 print STDERR "# Deducing from menu node_up $node->{'menu_up'}->{'texi'} for $node->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12100 } 12101 12102 if ($node->{'nodeup'} and !$node->{'nodeup'}->{'external_node'}) 12103 { 12104 # We detect when the up node has no menu entry for that node, as 12105 # there may be infinite loops when finding following node (see below) 12106 unless (defined($node->{'menu_up_hash'}) and ($node->{'menu_up_hash'}->{$node->{'nodeup'}->{'texi'}})) 12107 { 12108 print STDERR "$WARN `$node->{'nodeup'}->{'texi'}' is up for `$node->{'texi'}', but has no menu entry for this node\n" if ($Texi2HTML::Config::SHOW_MENU); 12109 push @{$node->{'up_not_in_menu'}}, $node->{'nodeup'}->{'texi'}; 12110 } 12111 } 12112 12113 # Find next node 12114 if ($node->{'node_next'}) 12115 { 12116 $node->{'nodenext'} = $node->{'node_next'}; 12117 } 12118 elsif ($node->{'texi'} eq 'Top') 12119 { # special case as said in the texinfo manual 12120 $node->{'nodenext'} = $node->{'menu_child'} if ($node->{'menu_child'}); 12121 } 12122 elsif ($node->{'automatic_directions'}) 12123 { 12124 if (defined($node->{'section_ref'})) 12125 { 12126 my $next; 12127 my $section = $node->{'section_ref'}; 12128 if (defined($section->{'sectionnext'})) 12129 { 12130 $next = get_node($section->{'sectionnext'}) 12131 } 12132 else 12133 { 12134 while (defined($section->{'sectionup'}) and !defined($section->{'sectionnext'})) 12135 { 12136 $section = $section->{'sectionup'}; 12137 } 12138 if (defined($section->{'sectionnext'})) 12139 { 12140 $next = get_node($section->{'sectionnext'}); 12141 } 12142 } 12143 $node->{'nodenext'} = $next; 12144 } 12145 } 12146 # next we try menus. makeinfo don't do that 12147 if (!defined($node->{'nodenext'}) and $node->{'menu_next'} 12148 and $Texi2HTML::Config::USE_MENU_DIRECTIONS) 12149 { 12150 $node->{'nodenext'} = $node->{'menu_next'}; 12151 } 12152 # Find prev node 12153 if ($node->{'node_prev'}) 12154 { 12155 $node->{'nodeprev'} = $node->{'node_prev'}; 12156 } 12157 elsif ($node->{'automatic_directions'}) 12158 { 12159 if (defined($node->{'section_ref'})) 12160 { 12161 my $section = $node->{'section_ref'}; 12162 if (defined($section->{'sectionprev'})) 12163 { 12164 $node->{'nodeprev'} = get_node($section->{'sectionprev'}); 12165 } 12166 elsif (defined($section->{'sectionup'})) 12167 { 12168 $node->{'nodeprev'} = get_node($section->{'sectionup'}); 12169 } 12170 } 12171 } 12172 # next we try menus. makeinfo don't do that 12173 if (!defined($node->{'nodeprev'}) and $node->{'menu_prev'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS) 12174 { 12175 $node->{'nodeprev'} = $node->{'menu_prev'}; 12176 } 12177 # the prev node is the parent node 12178 elsif (!defined($node->{'nodeprev'}) and $node->{'menu_up'} and $Texi2HTML::Config::USE_MENU_DIRECTIONS) 12179 { 12180 $node->{'nodeprev'} = $node->{'menu_up'}; 12181 } 12182 12183 # the following node is the node following in node reading order 12184 # it is thus first the child, else the next, else the next following 12185 # the up 12186 if ($node->{'menu_child'}) 12187 { 12188 $node->{'following'} = $node->{'menu_child'}; 12189 } 12190 elsif ($node->{'automatic_directions'} and defined($node->{'section_ref'}) and defined($node->{'section_ref'}->{'child'})) 12191 { 12192 $node->{'following'} = get_node($node->{'section_ref'}->{'child'}); 12193 } 12194 elsif (defined($node->{'nodenext'})) 12195 { 12196 $node->{'following'} = $node->{'nodenext'}; 12197 } 12198 else 12199 { 12200 my $up = $node->{'nodeup'}; 12201 # in order to avoid infinite recursion in case the up node is the 12202 # node itself we use the up node as following when there isn't 12203 # a correct menu structure, here and also below. 12204 $node->{'following'} = $up if (defined($up) and grep {$_ eq $up->{'texi'}} @{$node->{'up_not_in_menu'}}); 12205 while ((!defined($node->{'following'})) and (defined($up))) 12206 { 12207 if (($node_top) and ($up eq $node_top)) 12208 { # if we are at Top, Top is following 12209 $node->{'following'} = $node_top; 12210 $up = undef; 12211 } 12212 if (defined($up->{'nodenext'})) 12213 { 12214 $node->{'following'} = $up->{'nodenext'}; 12215 } 12216 elsif (defined($up->{'nodeup'})) 12217 { 12218 if (! grep { $_ eq $up->{'nodeup'}->{'texi'} } @{$node->{'up_not_in_menu'}}) 12219 { 12220 $up = $up->{'nodeup'}; 12221 } 12222 else 12223 { # in that case we can go into a infinite loop 12224 $node->{'following'} = $up->{'nodeup'}; 12225 } 12226 } 12227 else 12228 { 12229 $up = undef; 12230 } 12231 } 12232 } 12233 12234 if (defined($node->{'section_ref'})) 12235 { 12236 my $section = $node->{'section_ref'}; 12237 foreach my $direction ('sectionnext', 'sectionprev', 'sectionup') 12238 { 12239 $node->{$direction} = $section->{$direction} 12240 if (defined($section->{$direction})); 12241 } 12242 # this is a node appearing within a section but not associated 12243 # with that section. We consider that it is below that section. 12244 $node->{'sectionup'} = $section 12245 if (grep {$node eq $_} @{$section->{'node_childs'}}); 12246 } 12247 # 'up' is used in .init files. Maybe should go away. 12248 if (defined($node->{'sectionup'})) 12249 { 12250 $node->{'up'} = $node->{'sectionup'}; 12251 } 12252 elsif (defined($node->{'nodeup'}) and 12253 (!$node_top or ($node ne $node_top))) 12254 { 12255 $node->{'up'} = $node->{'nodeup'}; 12256 } 12257 # 'next' not used but documented. 12258 if (defined($node->{'sectionnext'})) 12259 { 12260 $node->{'next'} = $node->{'sectionnext'}; 12261 } 12262 if (defined($node->{'sectionprev'})) 12263 { 12264 $node->{'prev'} = $node->{'sectionprev'}; 12265 } 12266 12267 # default id for nodes. Should be overriden later. 12268 $node->{'id'} = 'NOD' . $node_nr; 12269 $node_nr++; 12270 } 12271 12272 print STDERR "# find forward and back\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12273 my $prev; 12274 foreach my $element (@elements_list) 12275 { 12276 $element->{'element'} = 1; 12277 # complete the up for toplevel elements now that element_top is defined 12278 print STDERR "# fwd and back for $element->{'texi'}\n" 12279 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12280 # at that point no node may be toplevel, only sections. 12281 if ($element->{'toplevel'} and ($element ne $element_top)) 12282 { 12283 $element->{'sectionup'} = $element_top; 12284 $element->{'up'} = $element_top; 12285 } 12286 if ($prev) 12287 { 12288 $element->{'back'} = $prev; 12289 $prev->{'forward'} = $element; 12290 $prev = $element; 12291 } 12292 else 12293 { 12294 $prev = $element; 12295 } 12296 # If the element is not a node, then all the node directions are copied 12297 # if there is an associated node 12298 if (defined($element->{'node_ref'})) 12299 { 12300 $element->{'nodenext'} = $element->{'node_ref'}->{'nodenext'}; 12301 $element->{'nodeprev'} = $element->{'node_ref'}->{'nodeprev'}; 12302 $element->{'menu_next'} = $element->{'node_ref'}->{'menu_next'}; 12303 $element->{'menu_prev'} = $element->{'node_ref'}->{'menu_prev'}; 12304 $element->{'menu_child'} = $element->{'node_ref'}->{'menu_child'}; 12305 $element->{'menu_up'} = $element->{'node_ref'}->{'menu_up'}; 12306 $element->{'nodeup'} = $element->{'node_ref'}->{'nodeup'}; 12307 $element->{'following'} = $element->{'node_ref'}->{'following'}; 12308 } 12309 elsif (! $element->{'node'}) 12310 { # the section has no node associated. Find the node directions using 12311 # sections 12312 if (defined($element->{'sectionnext'})) 12313 { 12314 $element->{'nodenext'} = get_node($element->{'sectionnext'}); 12315 } 12316 if (defined($element->{'sectionprev'})) 12317 { 12318 $element->{'nodeprev'} = get_node($element->{'sectionprev'}); 12319 } 12320 if (defined($element->{'up'})) 12321 { 12322 $element->{'nodeup'} = get_node($element->{'up'}); 12323 } 12324 if ($element->{'child'}) 12325 { 12326 $element->{'following'} = get_node($element->{'child'}); 12327 } 12328 elsif ($element->{'sectionnext'}) 12329 { 12330 $element->{'following'} = get_node($element->{'sectionnext'}); 12331 } 12332 elsif ($element->{'up'}) 12333 { 12334 my $up = $element; 12335 while ($up->{'up'} and !$element->{'following'}) 12336 { 12337 print STDERR "# Going up, searching next section from $up->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12338 $up = $up->{'up'}; 12339 if ($up->{'sectionnext'}) 12340 { 12341 $element->{'following'} = get_node ($up->{'sectionnext'}); 12342 } 12343 # avoid infinite loop if the top is up for itself 12344 last if ($up->{'toplevel'} or $up->{'top'}); 12345 } 12346 } 12347 } 12348 } 12349 12350 my @new_elements = (); 12351 print STDERR "# preparing indices\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12352 12353 while(@elements_list) 12354 { 12355 my $element = shift @elements_list; 12356 # current_element is the last element which can hold text. It is 12357 # initialized to a fake element 12358 my $current_element = { 'holder' => 1, 'texi' => 'HOLDER', 12359 'place' => [], 'indices' => [] }; 12360 # $back, $forward and $sectionnext are kept because $element 12361 # is in @{$element->{'all_elements'}}, so it is possible that 12362 # those directions get changed. 12363 # back is set to find back and forward 12364 my $back = $element->{'back'} if defined($element->{'back'}); 12365 my $forward = $element->{'forward'}; 12366 my $sectionnext = $element->{'sectionnext'}; 12367 my $index_num = 0; 12368 my @waiting_elements = (); # elements (nodes) not used for sectionning 12369 # waiting to be associated with an element 12370 foreach my $checked_element(@{$element->{'all_elements'}}) 12371 { 12372 if ($checked_element->{'element'}) 12373 { # this is the element, we must add it 12374 push @new_elements, $checked_element; 12375 if ($current_element->{'holder'}) 12376 { # no previous element added 12377 push @{$checked_element->{'place'}}, @{$current_element->{'place'}}; 12378 foreach my $index(@{$current_element->{'indices'}}) 12379 { 12380 push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ; 12381 } 12382 } 12383 else 12384 { 12385 $current_element->{'sectionnext'} = $checked_element; 12386 $current_element->{'following'} = $checked_element; 12387 $checked_element->{'sectionprev'} = $current_element; 12388 } 12389 $current_element = $checked_element; 12390 $checked_element->{'back'} = $back; 12391 $back->{'forward'} = $checked_element if (defined($back)); 12392 $back = $checked_element; 12393 push @{$checked_element->{'nodes'}}, @waiting_elements; 12394 @waiting_elements = (); 12395 } 12396 elsif ($current_element->{'holder'}) 12397 { 12398 push @waiting_elements, $checked_element; 12399 } 12400 else 12401 { 12402 push @{$current_element->{'nodes'}}, $checked_element; 12403 $checked_element->{'section_ref'} = $current_element; 12404 } 12405 push @{$current_element->{'place'}}, @{$checked_element->{'current_place'}}; 12406 foreach my $index (@{$checked_element->{'index_names'}}) 12407 { 12408 print STDERR "# Index in `$checked_element->{'texi'}': $index->{'name'}. Current is `$current_element->{'texi'}'\n" 12409 if ($T2H_DEBUG & $DEBUG_INDEX); 12410 my ($pages, $entries) = get_index($index->{'name'}); 12411 if (defined($pages)) 12412 { 12413 my @pages = @$pages; 12414 my $first_page = shift @pages; 12415 ############################## begin debug section 12416 my $back_texi = 'NO_BACK'; 12417 $back_texi = $back->{'texi'} if (defined($back)); 12418 print STDERR "# Index first page (back `$back_texi', in `$current_element->{'texi'}')\n" if ($T2H_DEBUG & $DEBUG_INDEX); 12419 ############################## end debug section 12420 push @{$current_element->{'indices'}}, [ {'element' => $current_element, 'page' => $first_page, 'name' => $index->{'name'} } ]; 12421 if (@pages) 12422 {# index is split accross more than one page 12423 if ($current_element->{'holder'}) 12424 { # the current element isn't an element which is 12425 # normally outputted. We add a real element. 12426 # we are in a node of a section but the element 12427 # is split by the index, thus we must add 12428 # a new element which will contain the text 12429 # between the beginning of the element and the index 12430 # WARNING the added element is like a section, and 12431 # indeed it is a 'section_ref' and 'sectionup' 12432 # for other nodes, it has 'nodes' 12433 # (see below and above). 12434 # But it is also a node. It may have a 'with_section' 12435 # and have a 'section_ref' 12436 # it may be considered 'node_ref' for a section. 12437 # and the Texi2HTML::NODE is relative to this 12438 # added element. 12439 12440 push @new_elements, $checked_element; 12441 print STDERR "# Add `$checked_element->{'texi'}' before index page for `$element->{'texi'}'\n" 12442 if ($T2H_DEBUG & $DEBUG_INDEX); 12443 echo_warn("Add `$checked_element->{'texi'}' for indicing"); 12444 $checked_element->{'element'} = 1; 12445 $checked_element->{'level'} = $element->{'level'}; 12446 $checked_element->{'toc_level'} = $element->{'toc_level'}; 12447 $checked_element->{'toplevel'} = $element->{'toplevel'}; 12448 if ($element->{'top'}) 12449 { 12450 $checked_element->{'toplevel'} = 1; 12451 $checked_element->{'top'} = 1; 12452 } 12453 $checked_element->{'up'} = $element->{'up'}; 12454 $checked_element->{'sectionup'} = $element->{'sectionup'}; 12455 $checked_element->{'element_added'} = 1; 12456 print STDERR "Bug: checked element wasn't seen" if 12457 (!$checked_element->{'seen'}); 12458 $element->{'sectionprev'}->{'sectionnext'} = $checked_element if (exists($element->{'sectionprev'})); 12459 push @{$checked_element->{'place'}}, @{$current_element->{'place'}}; 12460 foreach my $index(@{$current_element->{'indices'}}) 12461 { 12462 push @{$checked_element->{'indices'}}, [ { 'element' => $checked_element, 'page' => $index->[0]->{'page'}, 'name' => $index->[0]->{'name'} } ] ; 12463 } 12464 foreach my $waiting_element (@waiting_elements) 12465 { 12466 next if ($waiting_element eq $checked_element); 12467 $waiting_element->{'section_ref'} = $checked_element; 12468 $waiting_element->{'sectionup'} = $checked_element; 12469 push @{$checked_element->{'nodes'}}, $waiting_element; 12470 } 12471 @waiting_elements = (); 12472 $checked_element->{'back'} = $back; 12473 $back->{'forward'} = $checked_element if (defined($back)); 12474 $current_element = $checked_element; 12475 $back = $checked_element; 12476 } 12477 my $index_page; 12478 while(@pages) 12479 { 12480 print STDERR "# New page (back `$back->{'texi'}', current `$current_element->{'texi'}')\n" if ($T2H_DEBUG & $DEBUG_INDEX); 12481 $index_num++; 12482 my $page = shift @pages; 12483 $index_page = { 'index_page' => 1, 12484 'texi' => "NOT REALLY USED: $current_element->{'texi'}' index $index->{'name'} page $index_num", 12485 'level' => $element->{'level'}, 12486 'tag' => $element->{'tag'}, 12487 'tag_level' => $element->{'tag_level'}, 12488 'toplevel' => $element->{'toplevel'}, 12489 'top' => $element->{'top'}, 12490 'up' => $element->{'up'}, 12491 'sectionup' => $element->{'sectionup'}, 12492 'back' => $back, 12493 'prev' => $back, 12494 'sectionnext' => $sectionnext, 12495 'following' => $current_element->{'following'}, 12496 'nodeup' => $current_element->{'nodeup'}, 12497 'nodenext' => $current_element->{'nodenext'}, 12498 'nodeprev' => $back, 12499 'place' => [], 12500 'seen' => 1, 12501 'page' => $page 12502 }; 12503 # the index page is associated with the new element 12504 # if there is one, the element otherwise 12505 if ($checked_element->{'element_added'}) 12506 { 12507 $index_page->{'original_index_element'} = $checked_element; 12508 } 12509 else 12510 { 12511 $index_page->{'original_index_element'} = $element; 12512 } 12513 $index_page->{'node'} = 1 if ($element->{'node'}); 12514 while ($nodes{$index_page->{'texi'}}) 12515 { 12516 $nodes{$index_page->{'texi'}} .= ' '; 12517 } 12518 $nodes{$index_page->{'texi'}} = $index_page; 12519 push @{$current_element->{'indices'}->[-1]}, {'element' => $index_page, 'page' => $page, 'name' => $index->{'name'} }; 12520 push @new_elements, $index_page; 12521 $back->{'forward'} = $index_page; 12522 $back->{'nodenext'} = $index_page; 12523 $back->{'sectionnext'} = $index_page unless ($back->{'top'}); 12524 $back->{'following'} = $index_page; 12525 $back = $index_page; 12526 $index_page->{'toplevel'} = 1 if ($element->{'top'}); 12527 } 12528 $current_element = $index_page; 12529 } 12530 } 12531 else 12532 { 12533 print STDERR "# Empty index: $index->{'name'}\n" 12534 if ($T2H_DEBUG & $DEBUG_INDEX); 12535 $empty_indices{$index->{'name'}} = 1; 12536 } 12537 push @{$current_element->{'place'}}, @{$index->{'place'}}; 12538 } 12539 } 12540 if ($forward and ($current_element ne $element)) 12541 { 12542 $current_element->{'forward'} = $forward; 12543 $forward->{'back'} = $current_element; 12544 } 12545 next if ($current_element eq $element or !$element->{'toplevel'}); 12546 # reparent the elements below $element to the last index page 12547 print STDERR "# Reparent for `$element->{'texi'}':\n" if ($T2H_DEBUG & $DEBUG_INDEX); 12548 foreach my $reparented(@{$element->{'section_childs'}},@{$element->{'node_childs'}}) 12549 { 12550 $reparented->{'sectionup'} = $current_element; 12551 print STDERR " reparented: $reparented->{'texi'}\n" 12552 if ($T2H_DEBUG & $DEBUG_INDEX); 12553 } 12554 } 12555 @elements_list = @new_elements; 12556 12557 print STDERR "# find fastback and fastforward\n" 12558 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12559 foreach my $element (@elements_list) 12560 { 12561 my $up = get_top($element); 12562 next unless (defined($up)); 12563 $element_chapter_index = $up if ($element_index and ($element_index eq $element)); 12564 # fastforward is the next element on same level than the upper parent 12565 # element 12566 $element->{'fastforward'} = $up->{'sectionnext'} if (exists ($up->{'sectionnext'})); 12567 # if the element isn't at the highest level, fastback is the 12568 # highest parent element 12569 if ($up and ($up ne $element)) 12570 { 12571 $element->{'fastback'} = $up; 12572 } 12573 elsif ($element->{'toplevel'}) 12574 { 12575 # the element is a top level element, we adjust the next 12576 # toplevel element fastback 12577 $element->{'fastforward'}->{'fastback'} = $element if ($element->{'fastforward'}); 12578 } 12579 } 12580 12581 # set 'reference_element' which is used each time there is a cross ref 12582 # to that node. 12583 # It is the section associated with the node except if USE_NODES 12584 unless ($Texi2HTML::Config::USE_NODES) 12585 { 12586 foreach my $node(@nodes_list) 12587 { 12588 if ($node->{'with_section'}) 12589 { 12590 $node->{'reference_element'} = $node->{'with_section'}; 12591 } 12592 } 12593 } 12594 12595 my $index_nr = 0; 12596 # convert directions in direction with first letter in all caps, to be 12597 # consistent with the convention used in the .init file. 12598 # find id for nodes and indices 12599 foreach my $element (@elements_list) 12600 { 12601 $element->{'this'} = $element; 12602 foreach my $direction (@element_directions) 12603 { 12604 my $direction_no_caps = $direction; 12605 $direction_no_caps =~ tr/A-Z/a-z/; 12606 $element->{$direction} = $element->{$direction_no_caps}; 12607 } 12608 if ($element->{'index_page'}) 12609 { 12610 $element->{'id'} = "INDEX" . $index_nr; 12611 $index_nr++; 12612 } 12613 } 12614 12615 print STDERR "# find float id\n" 12616 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12617 foreach my $float (@floats) 12618 { 12619 $float->{'style_id'} = cross_manual_line(normalise_space($float->{'style_texi'})); 12620 my $float_style = { }; 12621 if (exists($floats{$float->{'style_id'}})) 12622 { 12623 $float_style = $floats{$float->{'style_id'}}; 12624 } 12625 else 12626 { 12627 $floats{$float->{'style_id'}} = $float_style; 12628 } 12629 push @{$float_style->{'floats'}}, $float; 12630 $float->{'absolute_nr'} = scalar(@{$float_style->{'floats'}}); 12631 my $up = get_top($float->{'element'}); 12632 if (defined($up) and (!defined($float_style->{'current_chapter'}) or ($up->{'texi'} ne $float_style->{'current_chapter'}))) 12633 { 12634 $float_style->{'current_chapter'} = $up->{'texi'}; 12635 $float_style->{'nr_in_chapter'} = 1; 12636 } 12637 else 12638 { 12639 $float_style->{'nr_in_chapter'}++; 12640 } 12641 if (defined($up) and $up->{'number'} ne '') 12642 { 12643 $float->{'chapter_nr'} = $up->{'number'}; 12644 $float->{'nr'} = $float->{'chapter_nr'} . $float_style->{'nr_in_chapter'}; 12645 } 12646 else 12647 { 12648 $float->{'nr'} = $float->{'absolute_nr'}; 12649 } 12650 } 12651 12652 if ($Texi2HTML::Config::NEW_CROSSREF_STYLE) 12653 { 12654 foreach my $key (keys(%nodes)) 12655 { 12656 my $node = $nodes{$key}; 12657 next if ($node->{'external_node'} or $node->{'index_page'}); 12658 $node->{'id'} = node_to_id($node->{'cross_manual_target'}); 12659 } 12660 } 12661 12662 # Find node file names and file names for nodes considered as elements 12663 my $node_as_top; 12664 if ($node_top) 12665 { 12666 $node_as_top = $node_top; 12667 } 12668 elsif ($element_top->{'node_ref'}) 12669 { 12670 $node_as_top = $element_top->{'node_ref'}; 12671 } 12672 else 12673 { 12674 $node_as_top = $node_first; 12675 } 12676 if ($node_as_top) 12677 { 12678 my $node_file; 12679 $node_file = &$Texi2HTML::Config::node_file_name($node_as_top,'top'); 12680 $node_as_top->{'node_file'} = $node_file if (defined($node_file)); 12681 } 12682 foreach my $key (keys(%nodes)) 12683 { 12684 my $node = $nodes{$key}; 12685 next if (defined($node_as_top) and ($node eq $node_as_top)); 12686 my $node_file = &$Texi2HTML::Config::node_file_name($node,''); 12687 $node->{'node_file'} = $node_file if (defined($node_file)); 12688 } 12689 12690 print STDERR "# split and set files\n" 12691 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12692 # find document nr and document file for sections and nodes. 12693 # Split according to Texi2HTML::Config::SPLIT. 12694 # find file and id for placed elements (anchors, index entries, headings) 12695 if ($Texi2HTML::Config::SPLIT) 12696 { 12697 my $cut_section = $toplevel; 12698 my $doc_nr = -1; 12699 if ($Texi2HTML::Config::SPLIT eq 'section') 12700 { 12701 $cut_section = 2 if ($toplevel <= 2); 12702 } 12703 my $previous_file; 12704 foreach my $element (@elements_list) 12705 { 12706 print STDERR "# Splitting ($Texi2HTML::Config::SPLIT:$cut_section) $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12707 my $new_file = 0; 12708 if ( 12709 ($Texi2HTML::Config::SPLIT eq 'node') or 12710 ( 12711 defined($element->{'level'}) and ($element->{'level'} <= $cut_section) 12712 ) 12713 ) 12714 { 12715 $new_file = 1; 12716 $doc_nr++; 12717 } 12718 $doc_nr = 0 if ($doc_nr < 0); # happens if first elements are nodes 12719 $element->{'doc_nr'} = $doc_nr; 12720 my $is_top = ''; 12721 $element->{'file'} = "${docu_name}_$doc_nr" 12722 . ($docu_ext ? ".$docu_ext" : ""); 12723 if ($element->{'top'} or (defined($element->{'node_ref'}) and $element->{'node_ref'} eq $element_top)) 12724 { # the top elements 12725 $is_top = "top"; 12726 $element->{'file'} = $docu_top; 12727 } 12728 elsif ($Texi2HTML::Config::NODE_FILES) 12729 { 12730 if ($new_file) 12731 { 12732 my $node = get_node($element) unless(exists($element->{'node_ref'}) 12733 and $element->{'node_ref'}->{'element_added'}); 12734 if ($node and defined($node->{'node_file'})) 12735 { 12736 $element->{'file'} = $node->{'node_file'}; 12737 } 12738 $previous_file = $element->{'file'}; 12739 } 12740 elsif($previous_file) 12741 { 12742 $element->{'file'} = $previous_file; 12743 } 12744 } 12745 if (defined($Texi2HTML::Config::element_file_name)) 12746 { 12747 my $filename = 12748 &$Texi2HTML::Config::element_file_name ($element, $is_top, $docu_name); 12749 $element->{'file'} = $filename if (defined($filename)); 12750 } 12751 print STDERR "# add_file $element->{'file'} for $element->{'texi'}\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12752 add_file($element->{'file'}); 12753 foreach my $place(@{$element->{'place'}}) 12754 { 12755 $place->{'file'} = $element->{'file'}; 12756 $place->{'id'} = $element->{'id'} unless defined($place->{'id'}); 12757 } 12758 if ($element->{'nodes'}) 12759 { 12760 foreach my $node (@{$element->{'nodes'}}) 12761 { 12762 $node->{'doc_nr'} = $element->{'doc_nr'}; 12763 $node->{'file'} = $element->{'file'}; 12764 } 12765 } 12766 } 12767 } 12768 else 12769 { # not split 12770 add_file($docu_doc); 12771 foreach my $element(@elements_list) 12772 { 12773 $element->{'file'} = $docu_doc; 12774 $element->{'doc_nr'} = 0; 12775 foreach my $place(@{$element->{'place'}}) 12776 { 12777 $place->{'file'} = $element->{'file'}; 12778 $place->{'id'} = $element->{'id'} unless defined($place->{'id'}); 12779 } 12780 } 12781 foreach my $node(@nodes_list) 12782 { 12783 $node->{'file'} = $docu_doc; 12784 $node->{'doc_nr'} = 0; 12785 } 12786 } 12787 # correct the id and file for the things placed in footnotes 12788 foreach my $place(@{$footnote_element->{'place'}}) 12789 { 12790 $place->{'file'} = $footnote_element->{'file'}; 12791 $place->{'id'} = $footnote_element->{'id'} unless defined($place->{'id'}); 12792 } 12793 # if setcontentsaftertitlepage is set, the contents should be associated 12794 # with the titlepage. That's wat is done there. 12795 push @$region_place, $content_element{'contents'} 12796 if ($Texi2HTML::Config::DO_CONTENTS and $Texi2HTML::THISDOC{'setcontentsaftertitlepage'}); 12797 push @$region_place, $content_element{'shortcontents'} 12798 if ($Texi2HTML::Config::DO_SCONTENTS and $Texi2HTML::THISDOC{'setshortcontentsaftertitlepage'}); 12799 # correct the id and file for the things placed in regions (copying...) 12800 foreach my $place(@$region_place) 12801 { 12802#print STDERR "entry $place->{'entry'} texi $place->{'texi'}\n"; 12803 $place->{'file'} = $element_top->{'file'}; 12804 $place->{'id'} = $element_top->{'id'} unless defined($place->{'id'}); 12805 $place->{'element'} = $element_top if (exists($place->{'element'})); 12806 } 12807 foreach my $content_type(keys(%content_element)) 12808 { 12809 if (!defined($content_element{$content_type}->{'file'})) 12810 { 12811 print STDERR "# No content $content_type\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 12812 $content_element{$content_type} = undef; 12813 } 12814 } 12815 12816 ########################### debug prints 12817 foreach my $file (keys(%files)) 12818 { 12819 last unless ($T2H_DEBUG & $DEBUG_ELEMENTS); 12820 print STDERR "$file: counter $files{$file}->{'counter'}\n"; 12821 } 12822 foreach my $element ((@elements_list, $footnote_element)) 12823 { 12824 last unless ($T2H_DEBUG & $DEBUG_ELEMENTS); 12825 my $is_toplevel = 'not toplevel'; 12826 $is_toplevel = 'toplevel' if ($element->{'toplevel'}); 12827 print STDERR "$element "; 12828 if ($element->{'index_page'}) 12829 { 12830 print STDERR "index($element->{'id'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})): $element->{'texi'}\n"; 12831 } 12832 elsif ($element->{'node'}) 12833 { 12834 print STDERR "node($element->{'id'}, toc_level $element->{'toc_level'}, $is_toplevel, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n"; 12835 print STDERR " section_ref: $element->{'section_ref'}->{'texi'}\n" if (defined($element->{'section_ref'})); 12836 } 12837 elsif ($element->{'footnote'}) 12838 { 12839 print STDERR "footnotes($element->{'id'}, file $element->{'file'})\n"; 12840 } 12841 else 12842 { 12843 my $number = "UNNUMBERED"; 12844 $number = $element->{'number'} if ($element->{'number'}); 12845 print STDERR "$number ($element->{'id'}, $is_toplevel, level $element->{'level'}-$element->{'toc_level'}, doc_nr $element->{'doc_nr'}($element->{'file'})) $element->{'texi'}:\n"; 12846 print STDERR " node_ref: $element->{'node_ref'}->{'texi'}\n" if (defined($element->{'node_ref'})); 12847 } 12848 12849 if (!$element->{'footnote'}) 12850 { 12851 if (!defined($files{$element->{'file'}})) 12852 { 12853 die "Bug: files{\$element->{'file'}} undef element $element->{'texi'}, file $element->{'file'}."; 12854 } 12855 print STDERR " file: $element->{'file'} $files{$element->{'file'}}, counter $files{$element->{'file'}}->{'counter'}\n"; 12856 } 12857 print STDERR " TOP($toplevel) " if ($element->{'top'}); 12858 print STDERR " u: $element->{'up'}->{'texi'}\n" if (defined($element->{'up'})); 12859 print STDERR " ch: $element->{'child'}->{'texi'}\n" if (defined($element->{'child'})); 12860 print STDERR " fb: $element->{'fastback'}->{'texi'}\n" if (defined($element->{'fastback'})); 12861 print STDERR " b: $element->{'back'}->{'texi'}\n" if (defined($element->{'back'})); 12862 print STDERR " p: $element->{'prev'}->{'texi'}\n" if (defined($element->{'prev'})); 12863 print STDERR " n: $element->{'sectionnext'}->{'texi'}\n" if (defined($element->{'sectionnext'})); 12864 print STDERR " n_u: $element->{'nodeup'}->{'texi'}\n" if (defined($element->{'nodeup'})); 12865 print STDERR " f: $element->{'forward'}->{'texi'}\n" if (defined($element->{'forward'})); 12866 print STDERR " follow: $element->{'following'}->{'texi'}\n" if (defined($element->{'following'})); 12867 print STDERR " m_p: $element->{'menu_prev'}->{'texi'}\n" if (defined($element->{'menu_prev'})); 12868 print STDERR " m_n: $element->{'menu_next'}->{'texi'}\n" if (defined($element->{'menu_next'})); 12869 print STDERR " m_u: $element->{'menu_up'}->{'texi'}\n" if (defined($element->{'menu_up'})); 12870 print STDERR " m_ch: $element->{'menu_child'}->{'texi'}\n" if (defined($element->{'menu_child'})); 12871 print STDERR " ff: $element->{'fastforward'}->{'texi'}\n" if (defined($element->{'fastforward'})); 12872 if (defined($element->{'menu_up_hash'})) 12873 { 12874 print STDERR " parent nodes:\n"; 12875 foreach my $menu_up (keys%{$element->{'menu_up_hash'}}) 12876 { 12877 print STDERR " $menu_up ($element->{'menu_up_hash'}->{$menu_up})\n"; 12878 } 12879 } 12880 if (defined($element->{'nodes'})) 12881 { 12882 print STDERR " nodes: $element->{'nodes'} (@{$element->{'nodes'}})\n"; 12883 foreach my $node (@{$element->{'nodes'}}) 12884 { 12885 my $beginning = " "; 12886 $beginning = " *" if ($node->{'with_section'}); 12887 my $file = $node->{'file'}; 12888 $file = "file undef" if (! defined($node->{'file'})); 12889 print STDERR "${beginning}$node->{'texi'} $file\n"; 12890 } 12891 } 12892 print STDERR " places: $element->{'place'}\n"; 12893 foreach my $place(@{$element->{'place'}}) 12894 { 12895 if (!$place->{'entry'} and !$place->{'float'} and !$place->{'texi'} and !$place->{'contents'} and !$place->{'shortcontents'}) 12896 { 12897 print STDERR "BUG: unknown placed stuff ========\n"; 12898 foreach my $key (keys(%$place)) 12899 { 12900 print STDERR "$key: $place->{$key}\n"; 12901 } 12902 print STDERR "==================================\n"; 12903 } 12904 elsif ($place->{'entry'}) 12905 { 12906 print STDERR " index($place): $place->{'entry'}\n"; 12907 } 12908 elsif ($place->{'anchor'}) 12909 { 12910 print STDERR " anchor: $place->{'texi'}\n"; 12911 } 12912 elsif ($place->{'float'}) 12913 { 12914 if (defined($place->{'texi'})) 12915 { 12916 print STDERR " float($place): $place->{'texi'}\n"; 12917 } 12918 else 12919 { 12920 print STDERR " float($place): NO LABEL\n"; 12921 } 12922 } 12923 elsif ($place->{'contents'}) 12924 { 12925 print STDERR " contents\n"; 12926 } 12927 elsif ($place->{'shortcontents'}) 12928 { 12929 print STDERR " shortcontents\n"; 12930 } 12931 else 12932 { 12933 print STDERR " heading: $place->{'texi'}\n"; 12934 } 12935 } 12936 if ($element->{'indices'}) 12937 { 12938 print STDERR " indices: $element->{'indices'}\n"; 12939 foreach my $index(@{$element->{'indices'}}) 12940 { 12941 print STDERR " $index: "; 12942 foreach my $page (@$index) 12943 { 12944 print STDERR "'$page->{'element'}->{'texi'}'($page->{'name'}): $page->{'page'} "; 12945 } 12946 print STDERR "\n"; 12947 } 12948 } 12949 } 12950 ########################### end debug prints 12951} 12952 12953sub add_file($) 12954{ 12955 my $file = shift; 12956 if ($files{$file}) 12957 { 12958 $files{$file}->{'counter'}++; 12959 } 12960 else 12961 { 12962 $files{$file} = { 12963 #'type' => 'section', 12964 'counter' => 1, 12965 'relative_foot_num' => 1, 12966 'foot_lines' => [] 12967 }; 12968 } 12969} 12970 12971# find parent element which is a top element, or a node within the top section 12972sub get_top($) 12973{ 12974 my $element = shift; 12975 my $up = $element; 12976 while (!$up->{'toplevel'} and !$up->{'top'}) 12977 { 12978 $up = $up->{'sectionup'}; 12979 if (!defined($up)) 12980 { 12981 # If there is no section, it is normal not to have toplevel element, 12982 # and it is also the case if there is a low level element before 12983 # a top level element 12984 return undef; 12985 } 12986 } 12987 return $up; 12988} 12989 12990sub get_node($) 12991{ 12992 my $element = shift; 12993 return undef if (!defined($element)); 12994 return $element if ($element->{'node'}); 12995 return $element->{'node_ref'} if ($element->{'node_ref'}); 12996 return $element; 12997} 12998# get the html names from the texi for all elements 12999sub do_names() 13000{ 13001 print STDERR "# Doing ". scalar(keys(%nodes)) . " nodes, ". 13002 scalar(keys(%sections)) . " sections in ". $#elements_list . 13003 " elements\n" if ($T2H_DEBUG); 13004 # for nodes and anchors we haven't any state defined 13005 # This seems right, however, as we don't want @refs or @footnotes 13006 # or @anchors within nodes, section commands or anchors. 13007 foreach my $node (keys(%nodes)) 13008 { 13009 next if ($nodes{$node}->{'index_page'}); # some nodes are index pages. 13010 my $texi = &$Texi2HTML::Config::heading_texi($nodes{$node}->{'tag'}, 13011 $nodes{$node}->{'texi'}, undef); 13012 $nodes{$node}->{'text'} = substitute_line ($texi); 13013 $nodes{$node}->{'text_nonumber'} = $nodes{$node}->{'text'}; 13014 # backward compatibility 13015 $nodes{$node}->{'name'} = $nodes{$node}->{'text_nonumber'}; 13016 $nodes{$node}->{'no_texi'} = remove_texi($texi); 13017 $nodes{$node}->{'simple_format'} = simple_format(undef, $texi); 13018 $nodes{$node}->{'heading_texi'} = $texi; 13019 # FIXME : what to do if $nodes{$node}->{'external_node'} and 13020 # $nodes{$node}->{'seen'} 13021 } 13022 foreach my $number (keys(%sections)) 13023 { 13024 my $section = $sections{$number}; 13025 #$section->{'name'} = substitute_line($section->{'texi'}); 13026 my $texi = &$Texi2HTML::Config::heading_texi($section->{'tag'}, $section->{'texi'}, $section->{'number'}); 13027 $section->{'text'} = substitute_line($texi); 13028 $section->{'text_nonumber'} = substitute_line($section->{'texi'}); 13029 # backward compatibility 13030 $section->{'name'} = $section->{'text_nonumber'}; 13031 $section->{'no_texi'} = remove_texi($texi); 13032 $section->{'simple_format'} = simple_format(undef,$texi); 13033 $section->{'heading_texi'} = $texi; 13034 } 13035 my $tocnr = 1; 13036 foreach my $element (@elements_list) 13037 { 13038 if (!$element->{'top'} and !$element->{'index_page'}) 13039 { # for link back to table of contents 13040 # FIXME do it for top too? 13041 $element->{'tocid'} = 'TOC' . $tocnr; 13042 $tocnr++; 13043 } 13044 next if (defined($element->{'text'})); 13045 if ($element->{'index_page'}) 13046 { 13047 my $page = $element->{'page'}; 13048 my $original_element = $element->{'original_index_element'}; 13049 my $texi = &$Texi2HTML::Config::index_element_heading_texi( 13050 $original_element->{'heading_texi'}, 13051 $original_element->{'tag'}, 13052 $original_element->{'texi'}, 13053 $original_element->{'number'}, 13054 $page->{'first_letter'}, $page->{'last_letter'}); 13055 $element->{'heading_texi'} = $texi; 13056 $element->{'text'} = substitute_line($texi); 13057 $element->{'no_texi'} = remove_texi($texi); 13058 $element->{'simple_format'} = simple_format(undef,$texi); 13059 } 13060 } 13061 print STDERR "# Names done\n" if ($T2H_DEBUG); 13062} 13063 13064@{$Texi2HTML::TOC_LINES} = (); # table of contents 13065@{$Texi2HTML::OVERVIEW} = (); # short table of contents 13066 13067 13068 13069#+++############################################################################ 13070# # 13071# Stuff related to Index generation # 13072# # 13073#---############################################################################ 13074 13075# called during pass_structure 13076sub enter_index_entry($$$$$$$) 13077{ 13078 my $prefix = shift; 13079 my $line_nr = shift; 13080 my $key = shift; 13081 my $place = shift; 13082 my $element = shift; 13083 my $use_section_id = shift; 13084 my $command = shift; 13085 unless ($index_prefix_to_name{$prefix}) 13086 { 13087 echo_error ("Undefined index command: ${prefix}index", $line_nr); 13088 $key = ''; 13089 } 13090 if (!exists($element->{'tag'}) and !$element->{'footnote'}) 13091 { 13092 echo_warn ("Index entry before document: \@${prefix}index $key", $line_nr); 13093 } 13094 $key =~ s/\s+$//; 13095 $key =~ s/^\s*//; 13096 my $entry = $key; 13097 # The $key is mostly usefull for alphabetical sorting 13098 $key = remove_texi($key); 13099 my $id = ''; 13100 # don't add a specific index target if after a section or the index 13101 # entry is in @copying or the like 13102 unless ($use_section_id or ($place eq $region_place)) 13103 { 13104 $id = 'IDX' . ++$idx_num; 13105 } 13106 my $index_entry = { 13107 'entry' => $entry, 13108 'element' => $element, 13109 'prefix' => $prefix, 13110 'label' => $id, 13111 'command' => $command 13112 }; 13113 13114 print STDERR "# enter \@$command ${prefix}index '$key' with id $id ($index_entry)\n" 13115 if ($T2H_DEBUG & $DEBUG_INDEX); 13116 if ($key =~ /^\s*$/) 13117 { 13118 echo_warn("Empty index entry for \@$command",$line_nr); 13119 # don't add the index entry to the list of index entries used for index 13120 # entry formatting,if the index entry appears in a region like copying 13121 push @index_labels, $index_entry unless ($place eq $region_place); 13122 return; 13123 } 13124 while (exists $index->{$prefix}->{$key}) 13125 { 13126 $key .= ' '; 13127 } 13128 $index->{$prefix}->{$key} = $index_entry; 13129 push @$place, $index_entry; 13130 # don't add the index entry to the list of index entries used for index 13131 # entry formatting,if the index entry appears in a region like copying 13132 push @index_labels, $index_entry unless ($place eq $region_place); 13133} 13134 13135# sort according to cmp if both $a and $b are alphabetical or non alphabetical, 13136# otherwise the alphabetical is ranked first 13137sub by_alpha 13138{ 13139 if ($a =~ /^[A-Za-z]/) 13140 { 13141 if ($b =~ /^[A-Za-z]/) 13142 { 13143 return lc($a) cmp lc($b); 13144 } 13145 else 13146 { 13147 return 1; 13148 } 13149 } 13150 elsif ($b =~ /^[A-Za-z]/) 13151 { 13152 return -1; 13153 } 13154 else 13155 { 13156 return lc($a) cmp lc($b); 13157 } 13158} 13159 13160# returns an array of index entries pages splitted by letters 13161# each page has the following members: 13162# 'first_letter' first letter on that page 13163# 'last_letter' last letter on that page 13164# 'letters' ref on an array with all the letters for that page 13165# 'entries_by_letter' ref on a hash. Each key is a letter, with value a ref 13166# on arrays of index entries beginning with this letter 13167sub get_index_pages($) 13168{ 13169 my $entries = shift; 13170 my (@letters); 13171 my ($entries_by_letter, $pages, $page) = ({}, [], {}); 13172 my @keys = sort by_alpha keys %$entries; 13173 13174 # each index entry is placed according to its first letter in 13175 # entries_by_letter 13176 for my $key (@keys) 13177 { 13178 push @{$entries_by_letter->{uc(substr($key,0, 1))}} , $entries->{$key}; 13179 } 13180 @letters = sort by_alpha keys %$entries_by_letter; 13181 $Texi2HTML::Config::SPLIT_INDEX = 0 unless $Texi2HTML::Config::SPLIT; 13182 13183 if ($Texi2HTML::Config::SPLIT_INDEX and $Texi2HTML::Config::SPLIT_INDEX =~ /^\d+$/) 13184 { 13185 my $i = 0; 13186 my ($prev_letter); 13187 foreach my $letter (@letters) 13188 { 13189 if ($i > $Texi2HTML::Config::SPLIT_INDEX) 13190 { 13191 $page->{'last_letter'} = $prev_letter; 13192 push @$pages, $page; 13193 $i=0; 13194 } 13195 if ($i == 0) 13196 { 13197 $page = {}; 13198 $page->{'letters'} = []; 13199 $page->{'entries_by_letter'} = {}; 13200 $page->{'first_letter'} = $letter; 13201 } 13202 push @{$page->{'letters'}}, $letter; 13203 $page->{'entries_by_letter'}->{$letter} = [@{$entries_by_letter->{$letter}}]; 13204 $i += scalar(@{$entries_by_letter->{$letter}}); 13205 $prev_letter = $letter; 13206 } 13207 $page->{'last_letter'} = $letters[$#letters]; 13208 push @$pages, $page; 13209 } 13210 else 13211 { 13212 warn "$WARN Bad Texi2HTML::Config::SPLIT_INDEX: $Texi2HTML::Config::SPLIT_INDEX\n" if ($Texi2HTML::Config::SPLIT_INDEX); 13213 $page->{'first_letter'} = $letters[0]; 13214 $page->{'last_letter'} = $letters[$#letters]; 13215 $page->{'letters'} = \@letters; 13216 $page->{'entries_by_letter'} = $entries_by_letter; 13217 push @$pages, $page; 13218 return $pages; 13219 } 13220 return $pages; 13221} 13222 13223# return the page and the entries. Cache the result in %indices. 13224sub get_index($;$) 13225{ 13226 my $index_name = shift; 13227 my $line_nr = shift; 13228 13229 return (@{$indices{$index_name}}) if ($indices{$index_name}); 13230 13231 unless (exists($index_names{$index_name})) 13232 { 13233 echo_error ("Bad index name: $index_name", $line_nr); 13234 return; 13235 } 13236 # add the index name itself to the index names searched for index 13237 # prefixes. Only those found associated by synindex or syncodeindex are 13238 # allready there (unless this code has allready been called). 13239 if ($index_names{$index_name}->{'code'}) 13240 { 13241 $index_names{$index_name}->{'associated_indices_code'}->{$index_name} = 1; 13242 } 13243 else 13244 { 13245 $index_names{$index_name}->{'associated_indices'}->{$index_name} = 1; 13246 } 13247 13248 # find all the index names associated with the prefixes and then 13249 # all the entries associated with each prefix 13250 my $entries = {}; 13251 foreach my $associated_indice(keys %{$index_names{$index_name}->{'associated_indices'}}) 13252 { 13253 foreach my $prefix(@{$index_names{$associated_indice}->{'prefix'}}) 13254 { 13255 foreach my $key (keys %{$index->{$prefix}}) 13256 { 13257 $entries->{$key} = $index->{$prefix}->{$key}; 13258 } 13259 } 13260 } 13261 13262 foreach my $associated_indice (keys %{$index_names{$index_name}->{'associated_indices_code'}}) 13263 { 13264 unless (exists ($index_names{$index_name}->{'associated_indices'}->{$associated_indice})) 13265 { 13266 foreach my $prefix (@{$index_names{$associated_indice}->{'prefix'}}) 13267 { 13268 foreach my $key (keys (%{$index->{$prefix}})) 13269 { 13270 $entries->{$key} = $index->{$prefix}->{$key}; 13271 # use @code for code style index entry 13272 $entries->{$key}->{'entry'} = "\@code{$entries->{$key}->{entry}}"; 13273 } 13274 } 13275 } 13276 } 13277 13278 return unless %$entries; 13279 my $pages = get_index_pages($entries); 13280 $indices{$index_name} = [ $pages, $entries ]; 13281 return ($pages, $entries); 13282} 13283 13284my @foot_lines = (); # footnotes 13285my $copying_comment = ''; # comment constructed from text between 13286 # @copying and @end copying with licence 13287my $to_encoding; # out file encoding 13288my %acronyms_like = (); # acronyms or similar commands associated texts 13289 # the key are the commands, the values are 13290 # hash references associating shorthands to 13291 # texts. 13292 13293sub initialise_state($) 13294{ 13295 my $state = shift; 13296 $state->{'preformatted'} = 0 unless exists($state->{'preformatted'}); 13297 $state->{'code_style'} = 0 unless exists($state->{'code_style'}); 13298 $state->{'keep_texi'} = 0 unless exists($state->{'keep_texi'}); 13299 $state->{'keep_nr'} = 0 unless exists($state->{'keep_nr'}); 13300 $state->{'detailmenu'} = 0 unless exists($state->{'detailmenu'}); # number of opened detailed menus 13301 $state->{'table_list_stack'} = [ {'format' => "noformat"} ] unless exists($state->{'table_list_stack'}); 13302 $state->{'paragraph_style'} = [ '' ] unless exists($state->{'paragraph_style'}); 13303 $state->{'preformatted_stack'} = [ '' ] unless exists($state->{'preformatted_stack'}); 13304 $state->{'menu'} = 0 unless exists($state->{'menu'}); 13305 $state->{'command_stack'} = [] unless exists($state->{'command_stack'}); 13306 $state->{'quotation_stack'} = [] unless exists($state->{'quotation_stack'}); 13307 # if there is no $state->{'element'} the first element is used 13308 $state->{'element'} = $elements_list[0] unless (exists($state->{'element'}) and !$state->{'element'}->{'before_anything'}); 13309} 13310 13311sub pass_text() 13312{ 13313 my %state; 13314 initialise_state(\%state); 13315 my @stack; 13316 my $text; 13317 my $doc_nr; 13318 my $in_doc = 0; 13319 my $element; 13320 my @text =(); 13321 my @section_lines = (); 13322 my @head_lines = (); 13323 my $one_section = 1 if (@elements_list == 1); 13324 13325 if (@elements_list == 0) 13326 { 13327 warn "$WARN empty document\n"; 13328 exit (0); 13329 } 13330 13331 # We set titlefont only if the titlefont appeared in the top element 13332 if (defined($element_top->{'titlefont'})) 13333 { 13334 $value{'_titlefont'} = $element_top->{'titlefont'}; 13335 } 13336 13337 # prepare %Texi2HTML::THISDOC 13338# $Texi2HTML::THISDOC{'settitle_texi'} = $value{'_settitle'}; 13339 $Texi2HTML::THISDOC{'fulltitle_texi'} = ''; 13340 $Texi2HTML::THISDOC{'title_texi'} = ''; 13341 foreach my $possible_fulltitle (('_title', '_settitle', '_shorttitlepage', '_titlefont')) 13342 { 13343 if ($value{$possible_fulltitle} ne '') 13344 { 13345 $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{$possible_fulltitle}; 13346 last; 13347 } 13348 } 13349 foreach my $possible_title_texi ($value{'_settitle'}, $Texi2HTML::THISDOC{'fulltitle_texi'}) 13350 { 13351 if ($possible_title_texi ne '') 13352 { 13353 $Texi2HTML::THISDOC{'title_texi'} = $possible_title_texi; 13354 last; 13355 } 13356 } 13357# $Texi2HTML::THISDOC{'fulltitle_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'}; 13358# $Texi2HTML::THISDOC{'title_texi'} = $value{'_title'} || $value{'_settitle'} || $value{'_shorttitlepage'} || $value{'_titlefont'}; 13359 foreach my $texi_cmd (('shorttitlepage', 'settitle', 'author', 13360 'titlefont', 'subtitle', 'shorttitle')) 13361 { 13362 $Texi2HTML::THISDOC{$texi_cmd . '_texi'} = $value{'_' . $texi_cmd}; 13363 } 13364 foreach my $doc_thing (('shorttitlepage', 'settitle', 'author', 13365 'titlefont', 'subtitle', 'shorttitle', 'fulltitle', 'title')) 13366 { 13367 my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'}; 13368 $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi); 13369 $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} = 13370 remove_texi($thing_texi); 13371 $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} = 13372 simple_format(undef, $thing_texi); 13373 } 13374 13375 # find Top name 13376 my $element_top_text = ''; 13377 my $top_no_texi = ''; 13378 my $top_simple_format = ''; 13379 my $top_name; 13380 if ($element_top and $element_top->{'text'} and (!$node_top or ($element_top ne $node_top))) 13381 { 13382 $element_top_text = $element_top->{'text'}; 13383 $top_no_texi = $element_top->{'no_texi'}; 13384 $top_simple_format = $element_top->{'simple_format'}; 13385 } 13386 foreach my $possible_top_name ($Texi2HTML::Config::TOP_HEADING, 13387 $element_top_text, $Texi2HTML::THISDOC{'title'}, 13388 $Texi2HTML::THISDOC{'shorttitle'}, &$I('Top')) 13389 { 13390 if (defined($possible_top_name) and $possible_top_name ne '') 13391 { 13392 $top_name = $possible_top_name; 13393 last; 13394 } 13395 } 13396 foreach my $possible_top_no_texi ($Texi2HTML::Config::TOP_HEADING, 13397 $top_no_texi, $Texi2HTML::THISDOC{'title_no_texi'}, 13398 $Texi2HTML::THISDOC{'shorttitle_no_texi'}, 13399 &$I('Top',{},{'remove_texi' => 1})) 13400 { 13401 if (defined($possible_top_no_texi) and $possible_top_no_texi ne '') 13402 { 13403 $top_no_texi = $possible_top_no_texi; 13404 last; 13405 } 13406 } 13407 13408 foreach my $possible_top_simple_format ($top_simple_format, 13409 $Texi2HTML::THISDOC{'title_simple_format'}, 13410 $Texi2HTML::THISDOC{'shorttitle_simple_format'}, 13411 &$I('Top',{}, {'simple_format' => 1})) 13412 { 13413 if (defined($possible_top_simple_format) and $possible_top_simple_format ne '') 13414 { 13415 $top_simple_format = $possible_top_simple_format; 13416 last; 13417 } 13418 } 13419 13420 13421# my $top_name = $Texi2HTML::Config::TOP_HEADING || $element_top_text || $Texi2HTML::THISDOC{'title'} || $Texi2HTML::THISDOC{'shorttitle'} || &$I('Top'); 13422 13423 if ($Texi2HTML::THISDOC{'fulltitle_texi'} eq '') 13424 { 13425 $Texi2HTML::THISDOC{'fulltitle_texi'} = &$I('Untitled Document',{}, 13426 {'keep_texi' => 1}); 13427 } 13428 $Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'settitle_texi'}; 13429 $Texi2HTML::THISDOC{'title_texi'} = $Texi2HTML::THISDOC{'fulltitle_texi'} 13430 if ($Texi2HTML::THISDOC{'title_texi'} eq ''); 13431 13432 foreach my $doc_thing (('fulltitle', 'title')) 13433 { 13434 my $thing_texi = $Texi2HTML::THISDOC{$doc_thing . '_texi'}; 13435 $Texi2HTML::THISDOC{$doc_thing} = substitute_line($thing_texi); 13436 $Texi2HTML::THISDOC{$doc_thing . '_no_texi'} = 13437 remove_texi($thing_texi); 13438 $Texi2HTML::THISDOC{$doc_thing . '_simple_format'} = 13439 simple_format(undef, $thing_texi); 13440 } 13441 13442 for my $key (keys %Texi2HTML::THISDOC) 13443 { 13444 next if (ref($Texi2HTML::THISDOC{$key})); 13445print STDERR "!!$key\n" if (!defined($Texi2HTML::THISDOC{$key})); 13446 $Texi2HTML::THISDOC{$key} =~ s/\s*$//; 13447 } 13448 $Texi2HTML::THISDOC{'program'} = $THISPROG; 13449 $Texi2HTML::THISDOC{'program_homepage'} = $T2H_HOMEPAGE; 13450 $Texi2HTML::THISDOC{'program_authors'} = $T2H_AUTHORS; 13451 $Texi2HTML::THISDOC{'user'} = $T2H_USER; 13452 $Texi2HTML::THISDOC{'user'} = $Texi2HTML::Config::USER if (defined($Texi2HTML::Config::USER)); 13453# $Texi2HTML::THISDOC{'documentdescription'} = $documentdescription; 13454 $Texi2HTML::THISDOC{'copying'} = $copying_comment; 13455 $Texi2HTML::THISDOC{'destination_directory'} = $docu_rdir; 13456 $Texi2HTML::THISDOC{'authors'} = [] if (!defined($Texi2HTML::THISDOC{'authors'})); 13457 $Texi2HTML::THISDOC{'subtitles'} = [] if (!defined($Texi2HTML::THISDOC{'subtitles'})); 13458 $Texi2HTML::THISDOC{'titles'} = [] if (!defined($Texi2HTML::THISDOC{'titles'})); 13459 foreach my $element (('authors', 'subtitles', 'titles')) 13460 { 13461 my $i; 13462 for ($i = 0; $i < $#{$Texi2HTML::THISDOC{$element}} + 1; $i++) 13463 { 13464 chomp ($Texi2HTML::THISDOC{$element}->[$i]); 13465 $Texi2HTML::THISDOC{$element}->[$i] = substitute_line($Texi2HTML::THISDOC{$element}->[$i]); 13466 #print STDERR "$element:$i: $Texi2HTML::THISDOC{$element}->[$i]\n"; 13467 } 13468 } 13469 # prepare TOC, OVERVIEW... 13470 my ($toc_file, $stoc_file, $foot_file, $about_file); 13471 # if not split the references are to the same file 13472 $toc_file = $stoc_file = $foot_file = $about_file = ''; 13473 if ($Texi2HTML::Config::SPLIT) 13474 { 13475 $toc_file = $docu_toc; 13476 $stoc_file = $docu_stoc; 13477 if ($Texi2HTML::Config::INLINE_CONTENTS) 13478 { 13479 $toc_file = $content_element{'contents'}->{'file'} if (defined($content_element{'contents'})); 13480 $stoc_file = $content_element{'shortcontents'}->{'file'} if (defined($content_element{'shortcontents'})); 13481 } 13482 $foot_file = $docu_foot; 13483 $about_file = $docu_about; 13484 } 13485 $Texi2HTML::THISDOC{'toc_file'} = $toc_file; 13486 $Texi2HTML::HREF{'Contents'} = $toc_file.'#'.$content_element{'contents'}->{'id'} if @{$Texi2HTML::TOC_LINES}; 13487 $Texi2HTML::HREF{'Overview'} = $stoc_file.'#'.$content_element{'shortcontents'}->{'id'} if @{$Texi2HTML::OVERVIEW}; 13488 $Texi2HTML::HREF{'Footnotes'} = $foot_file. '#SEC_Foot'; 13489 $Texi2HTML::HREF{'About'} = $about_file . '#SEC_About' unless ($one_section or (not $Texi2HTML::Config::SPLIT and not $Texi2HTML::Config::SECTION_NAVIGATION)); 13490 13491 $Texi2HTML::NAME{'First'} = $element_first->{'text'}; 13492 $Texi2HTML::NAME{'Last'} = $element_last->{'text'}; 13493 $Texi2HTML::NAME{'About'} = &$I('About This Document'); 13494 $Texi2HTML::NAME{'Contents'} = &$I('Table of Contents'); 13495 $Texi2HTML::NAME{'Overview'} = &$I('Short Table of Contents'); 13496 $Texi2HTML::NAME{'Top'} = $top_name; 13497 $Texi2HTML::NAME{'Footnotes'} = &$I('Footnotes'); 13498 $Texi2HTML::NAME{'Index'} = $element_chapter_index->{'text'} if (defined($element_chapter_index)); 13499 $Texi2HTML::NAME{'Index'} = $Texi2HTML::Config::INDEX_CHAPTER if ($Texi2HTML::Config::INDEX_CHAPTER ne ''); 13500 13501 $Texi2HTML::NO_TEXI{'First'} = $element_first->{'no_texi'}; 13502 $Texi2HTML::NO_TEXI{'Last'} = $element_last->{'no_texi'}; 13503 $Texi2HTML::NO_TEXI{'About'} = &$I('About This Document', {}, {'remove_texi' => 1} ); 13504 $Texi2HTML::NO_TEXI{'Contents'} = &$I('Table of Contents', {}, {'remove_texi' => 1} ); 13505 $Texi2HTML::NO_TEXI{'Overview'} = &$I('Short Table of Contents', {}, {'remove_texi' => 1} ); 13506 $Texi2HTML::NO_TEXI{'Top'} = $top_no_texi; 13507 $Texi2HTML::NO_TEXI{'Footnotes'} = &$I('Footnotes', {}, {'remove_texi' => 1} ); 13508 $Texi2HTML::NO_TEXI{'Index'} = $element_chapter_index->{'no_texi'} if (defined($element_chapter_index)); 13509 13510 $Texi2HTML::SIMPLE_TEXT{'First'} = $element_first->{'simple_format'}; 13511 $Texi2HTML::SIMPLE_TEXT{'Last'} = $element_last->{'simple_format'}; 13512 $Texi2HTML::SIMPLE_TEXT{'About'} = &$I('About This Document', {}, {'simple_format' => 1}); 13513 $Texi2HTML::SIMPLE_TEXT{'Contents'} = &$I('Table of Contents',{}, {'simple_format' => 1}); 13514 $Texi2HTML::SIMPLE_TEXT{'Overview'} = &$I('Short Table of Contents', {}, {'simple_format' => 1}); 13515 $Texi2HTML::SIMPLE_TEXT{'Top'} = $top_simple_format; 13516 $Texi2HTML::SIMPLE_TEXT{'Footnotes'} = &$I('Footnotes', {},{'simple_format' => 1}); 13517 13518 $Texi2HTML::SIMPLE_TEXT{'Index'} = $element_chapter_index->{'simple_format'} if (defined($element_chapter_index)); 13519 # must be after toc_body, but before titlepage 13520 for my $element_tag ('contents', 'shortcontents') 13521 { 13522 my $toc_lines = &$Texi2HTML::Config::inline_contents(undef, $element_tag, $content_element{$element_tag}); 13523 @{$Texi2HTML::THISDOC{'inline_contents'}->{$element_tag}} = @$toc_lines if (defined($toc_lines)); 13524 } 13525 $Texi2HTML::TITLEPAGE = ''; 13526 $Texi2HTML::TITLEPAGE = substitute_text({}, @{$region_lines{'titlepage'}}) 13527 if (@{$region_lines{'titlepage'}}); 13528 &$Texi2HTML::Config::titlepage(); 13529 13530 &$Texi2HTML::Config::init_out(); 13531 $to_encoding = $Texi2HTML::Config::OUT_ENCODING; 13532 13533 ############################################################################ 13534 # print frame and frame toc file 13535 # 13536 if ( $Texi2HTML::Config::FRAMES ) 13537 { 13538 my $FH = open_out($docu_frame_file); 13539 print STDERR "# Creating frame in $docu_frame_file ...\n" if $T2H_VERBOSE; 13540 &$Texi2HTML::Config::print_frame($FH, $docu_toc_frame_file, $docu_top_file); 13541 close_out($FH, $docu_frame_file); 13542 13543 $FH = open_out($docu_toc_frame_file); 13544 print STDERR "# Creating toc frame in $docu_frame_file ...\n" if $T2H_VERBOSE; 13545 &$Texi2HTML::Config::print_toc_frame($FH, $Texi2HTML::OVERVIEW); 13546 close_out($FH, $docu_toc_frame_file); 13547 } 13548 13549 ############################################################################ 13550 # 13551 # 13552 13553 my $FH; 13554 my $index_pages; 13555 my $index_pages_nr; 13556 my $index_nr = 0; 13557 my $line_nr; 13558 my $first_section = 0; # 1 if it is the first section of a page 13559 while (@doc_lines) 13560 { 13561 unless ($index_pages) 13562 { # not in a index split over sections 13563 $_ = shift @doc_lines; 13564 my $chomped_line = $_; 13565 if (!chomp($chomped_line) and @doc_lines) 13566 { # if the line has no end of line it is concatenated with the next 13567 $doc_lines[0] = $_ . $doc_lines[0]; 13568 next; 13569 } 13570 $line_nr = shift (@doc_numbers); 13571 #print STDERR "$line_nr->{'file_name'}($line_nr->{'macro'},$line_nr->{'line_nr'}) $_" if ($line_nr); 13572 } 13573 #print STDERR "PASS_TEXT: $_"; 13574 #dump_stack(\$text, \@stack, \%state); 13575 if (!$state{'raw'} and !$state{'verb'}) 13576 { 13577 my $tag = ''; 13578 $tag = $1 if (/^\@(\w+)/ and !$index_pages); 13579 13580 if (($tag eq 'node') or defined($sec2level{$tag}) or $index_pages) 13581 { 13582 if (@stack or (defined($text) and $text ne '')) 13583 {# in pass text node and section shouldn't appear in formats 13584 #print STDERR "close_stack before \@$tag\n"; 13585 #print STDERR "text!$text%" if (! @stack); 13586 close_stack(\$text, \@stack, \%state, $line_nr); 13587 push @section_lines, $text; 13588 $text = ''; 13589 } 13590 $sec_num++ if ($sec2level{$tag}); 13591 my $new_element; 13592 my $current_element; 13593 if ($tag =~ /heading/) 13594 {# handle headings, they are not in element lists 13595 $current_element = $sections{$sec_num}; 13596 #print STDERR "HEADING $_"; 13597 if (! $element) 13598 { 13599 $new_element = shift @elements_list; 13600 } 13601 else 13602 { 13603 push (@section_lines, &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n"); 13604 push @section_lines, &$Texi2HTML::Config::heading($current_element); 13605 next; 13606 } 13607 } 13608 elsif (!$index_pages) 13609 {# handle node and structuring elements 13610 $current_element = shift (@all_elements); 13611 ########################## begin debug section 13612 if ($current_element->{'node'}) 13613 { 13614 print STDERR 'NODE ' . "$current_element->{'texi'}($current_element->{'file'})" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 13615 print STDERR "($current_element->{'section_ref'}->{'texi'})" if ($current_element->{'section_ref'} and ($T2H_DEBUG & $DEBUG_ELEMENTS)); 13616 } 13617 else 13618 { 13619 print STDERR 'SECTION ' . $current_element->{'texi'} if ($T2H_DEBUG & $DEBUG_ELEMENTS); 13620 } 13621 print STDERR ": $_" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 13622 ########################## end debug section 13623 13624 # The element begins a new section if there is no previous 13625 # or it is an element and not the current one or the 13626 # associated section (in case of node) is not the current 13627 # one 13628 if (!$element 13629 or ($current_element->{'element'} and ($current_element ne $element)) 13630 or ($current_element->{'section_ref'} and ($current_element->{'section_ref'} ne $element))) 13631 { 13632 $new_element = shift @elements_list; 13633 } 13634 ########################### begin debug 13635 my $section_element = $new_element; 13636 $section_element = $element unless ($section_element); 13637 if (!$current_element->{'node'} and !$current_element->{'index_page'} and ($section_element ne $current_element)) 13638 { 13639 print STDERR "NODE: $element->{'texi'}\n" if ($element->{'node'}); 13640 warn "elements_list and all_elements not in sync (elements $section_element->{'texi'}, all $current_element->{'texi'}): $_"; 13641 } 13642 ########################### end debug 13643 } 13644 else 13645 { # this is a new index section 13646 $new_element = $index_pages->[$index_pages_nr]->{'element'}; 13647 $current_element = $index_pages->[$index_pages_nr]->{'element'}; 13648 print STDERR "New index page '$new_element->{'texi'}' nr: $index_pages_nr\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 13649 my $list_element = shift @elements_list; 13650 die "element in index_pages $new_element->{'texi'} and in list $list_element->{'texi'} differs\n" unless ($list_element eq $new_element); 13651 } 13652 if ($new_element) 13653 { 13654 $index_nr = 0; 13655 my $old = 'NO_OLD'; 13656 $old = $element->{'texi'} if (defined($element)); 13657 print STDERR "NEW: $new_element->{'texi'}, OLD: $old\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS); 13658 # print the element that just finished 13659 $Texi2HTML::THIS_SECTION = \@section_lines; 13660 $Texi2HTML::THIS_HEADER = \@head_lines; 13661 if ($element) 13662 { 13663 finish_element($FH, $element, $new_element, $first_section); 13664 $first_section = 0; 13665 @section_lines = (); 13666 @head_lines = (); 13667 } 13668 else 13669 { 13670 print STDERR "# Writing elements:" if ($T2H_VERBOSE); 13671 if ($Texi2HTML::Config::IGNORE_PREAMBLE_TEXT) 13672 { 13673 @section_lines = (); 13674 @head_lines = (); 13675 } 13676 # remove empty line at the beginning of @section_lines 13677 shift @section_lines while (@section_lines and ($section_lines[0] =~ /^\s*$/)); 13678 } 13679 # begin new element 13680 my $previous_file; 13681 $previous_file = $element->{'file'} if (defined($element)); 13682 $element = $new_element; 13683 $state{'element'} = $element; 13684 $Texi2HTML::THIS_ELEMENT = $element; 13685 #print STDERR "Doing hrefs for $element->{'texi'} First "; 13686 $Texi2HTML::HREF{'First'} = href($element_first, $element->{'file'}); 13687 #print STDERR "Last "; 13688 $Texi2HTML::HREF{'Last'} = href($element_last, $element->{'file'}); 13689 #print STDERR "Index "; 13690 $Texi2HTML::HREF{'Index'} = href($element_chapter_index, $element->{'file'}) if (defined($element_chapter_index)); 13691 #print STDERR "Top "; 13692 $Texi2HTML::HREF{'Top'} = href($element_top, $element->{'file'}); 13693 if ($Texi2HTML::Config::INLINE_CONTENTS) 13694 { 13695 $Texi2HTML::HREF{'Contents'} = href($content_element{'contents'}, $element->{'file'}); 13696 $Texi2HTML::HREF{'Overview'} = href($content_element{'shortcontents'}, $element->{'file'}); 13697 } 13698 foreach my $direction (@element_directions) 13699 { 13700 my $elem = $element->{$direction}; 13701 $Texi2HTML::NODE{$direction} = undef; 13702 $Texi2HTML::HREF{$direction} = undef; 13703 next unless (defined($elem)); 13704 #print STDERR "$direction "; 13705 if ($elem->{'node'} or $elem->{'external_node'} or $elem->{'index_page'} or !$elem->{'seen'}) 13706 { 13707 $Texi2HTML::NODE{$direction} = $elem->{'text'}; 13708 } 13709 elsif ($elem->{'node_ref'}) 13710 { 13711 $Texi2HTML::NODE{$direction} = $elem->{'node_ref'}->{'text'}; 13712 } 13713 if (!$elem->{'seen'}) 13714 { 13715 $Texi2HTML::HREF{$direction} = do_external_href($elem->{'texi'}); 13716 } 13717 else 13718 { 13719 $Texi2HTML::HREF{$direction} = href($elem, $element->{'file'}); 13720 } 13721 $Texi2HTML::NAME{$direction} = $elem->{'text'}; 13722 $Texi2HTML::NO_TEXI{$direction} = $elem->{'no_texi'}; 13723 $Texi2HTML::SIMPLE_TEXT{$direction} = $elem->{'simple_format'}; 13724 #print STDERR "$direction ($element->{'texi'}): \n NO_TEXI: $Texi2HTML::NO_TEXI{$direction}\n NAME $Texi2HTML::NAME{$direction}\n NODE $Texi2HTML::NODE{$direction}\n HREF $Texi2HTML::HREF{$direction}\n\n"; 13725 } 13726 #print STDERR "\nDone hrefs for $element->{'texi'}\n"; 13727 $files{$element->{'file'}}->{'counter'}--; 13728 if (!defined($previous_file) or ($element->{'file'} ne $previous_file)) 13729 { 13730 my $file = $element->{'file'}; 13731 print STDERR "\n" if ($T2H_VERBOSE and !$T2H_DEBUG); 13732 print STDERR "# Writing to $docu_rdir$file " if $T2H_VERBOSE; 13733 my $do_page_head = 0; 13734 if ($files{$file}->{'filehandle'}) 13735 { 13736 $FH = $files{$file}->{'filehandle'}; 13737 } 13738 else 13739 { 13740 $FH = open_out("$docu_rdir$file"); 13741#print STDERR "OPEN $docu_rdir$file, $FH". scalar($FH)."\n"; 13742 $files{$file}->{'filehandle'} = $FH; 13743 $do_page_head = 1; 13744 } 13745 if ($element->{'top'}) 13746 { 13747 &$Texi2HTML::Config::print_Top_header($FH, $do_page_head); 13748 } 13749 else 13750 { 13751 &$Texi2HTML::Config::print_page_head($FH) if ($do_page_head); 13752 &$Texi2HTML::Config::print_chapter_header($FH) if $Texi2HTML::Config::SPLIT eq 'chapter'; 13753 &$Texi2HTML::Config::print_section_header($FH) if $Texi2HTML::Config::SPLIT eq 'section'; 13754 } 13755 $first_section = 1; 13756 } 13757 print STDERR "." if ($T2H_VERBOSE); 13758 print STDERR "\n" if ($T2H_DEBUG); 13759 } 13760 my $label = &$Texi2HTML::Config::anchor($current_element->{'id'}) . "\n"; 13761 if (@section_lines) 13762 { 13763 push (@section_lines, $label); 13764 } 13765 else 13766 { 13767 push @head_lines, $label; 13768 } 13769 if ($index_pages) 13770 { 13771 push @section_lines, &$Texi2HTML::Config::heading($element); 13772 #print STDERR "Do index page $index_pages_nr\n"; 13773 my $page = do_index_page($index_pages, $index_pages_nr); 13774 push @section_lines, $page; 13775 if (defined ($index_pages->[$index_pages_nr + 1])) 13776 { 13777 $index_pages_nr++; 13778 } 13779 else 13780 { 13781 $index_pages = undef; 13782 } 13783 next; 13784 } 13785 push @section_lines, &$Texi2HTML::Config::heading($current_element) if ($current_element->{'element'} and !$current_element->{'top'}); 13786 next; 13787 } 13788 elsif ($tag eq 'printindex') 13789 { 13790 s/\s+(\w+)\s*//; 13791 my $name = $1; 13792 close_paragraph(\$text, \@stack, \%state); 13793 next if (!$index_names{$name} or $empty_indices{$name}); 13794 $printed_indices{$name} = 1; 13795 print STDERR "print index $name($index_nr) in `$element->{'texi'}', element->{'indices'}: $element->{'indices'},\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS or $T2H_DEBUG & $DEBUG_INDEX); 13796 print STDERR "element->{'indices'}->[index_nr]: $element->{'indices'}->[$index_nr] (@{$element->{'indices'}->[$index_nr]})\n" if ($T2H_DEBUG & $DEBUG_ELEMENTS or $T2H_DEBUG & $DEBUG_INDEX); 13797 $index_pages = $element->{'indices'}->[$index_nr] if (@{$element->{'indices'}->[$index_nr]} > 1); 13798 $index_pages_nr = 0; 13799 add_prev(\$text, \@stack, do_index_page($element->{'indices'}->[$index_nr], 0)); 13800 $index_pages_nr++; 13801 $index_nr++; 13802 begin_paragraph (\@stack, \%state) if ($state{'preformatted'}); 13803 next if (@stack); 13804 push @section_lines, $text; 13805 $text = ''; 13806 next; 13807 } 13808 elsif (($tag eq 'contents') or ($tag eq 'summarycontents') or ($tag eq 'shortcontents')) 13809 { 13810 my $element_tag = $tag; 13811 $element_tag = 'shortcontents' if ($element_tag ne 'contents'); 13812 if ($Texi2HTML::Config::INLINE_CONTENTS and !$content_element{$element_tag}->{'aftertitlepage'}) 13813 { 13814 if (@stack or (defined($text) and $text ne '')) 13815 {# in pass text contents shouldn't appear in formats 13816 close_stack(\$text, \@stack, \%state, $line_nr); 13817 push @section_lines, $text; 13818 $text = ''; 13819 } 13820 my $toc_lines = &$Texi2HTML::Config::inline_contents($FH, $tag, $content_element{$element_tag}); 13821 push (@section_lines, @$toc_lines) if (defined($toc_lines)) ; 13822 } 13823 next; 13824 } 13825 } 13826 scan_line($_, \$text, \@stack, \%state, $line_nr); 13827 #print STDERR "after scan_line: $_"; 13828 #dump_stack(\$text, \@stack, \%state); 13829 next if (@stack); 13830 if ($text ne '' ) 13831 { 13832 push @section_lines, $text; 13833 $text = ''; 13834 } 13835 } 13836 if (@stack) 13837 {# close stack at the end of pass text 13838 close_stack(\$text, \@stack, \%state, $line_nr); 13839 } 13840 if (defined($text)) 13841 { 13842 push @section_lines, $text; 13843 } 13844 print STDERR "\n" if ($T2H_VERBOSE); 13845 13846 $Texi2HTML::THIS_SECTION = \@section_lines; 13847 # if no sections, then simply print document as is 13848 if ($one_section) 13849 { 13850 if (@foot_lines) 13851 { 13852 &$Texi2HTML::Config::foot_section (\@foot_lines); 13853 push @section_lines, @foot_lines; 13854 } 13855 $Texi2HTML::THIS_HEADER = \@head_lines; 13856 if ($element->{'top'}) 13857 { 13858 print STDERR "Bug: `$element->{'texi'}' level undef\n" if (!$element->{'node'} and !defined($element->{'level'})); 13859 $element->{'level'} = 1 if (!defined($element->{'level'})); 13860 $element->{'node'} = 0; # otherwise Texi2HTML::Config::heading may uses the node level 13861 $element->{'text'} = $Texi2HTML::NAME{'Top'}; 13862 print STDERR "[Top]" if ($T2H_VERBOSE); 13863 unless ($element->{'titlefont'} or $element->{'index_page'}) 13864 { 13865 unshift @section_lines, &$Texi2HTML::Config::heading($element); 13866 } 13867 } 13868 print STDERR "# Write the section $element->{'texi'}\n" if ($T2H_VERBOSE); 13869 &$Texi2HTML::Config::one_section($FH); 13870 close_out($FH); 13871 return; 13872 } 13873 13874 finish_element ($FH, $element, undef, $first_section); 13875 13876 ############################################################################ 13877 # Print ToC, Overview, Footnotes 13878 # 13879 foreach my $direction (@element_directions) 13880 { 13881 $Texi2HTML::HREF{$direction} = undef; 13882 delete $Texi2HTML::HREF{$direction}; 13883 # it is better to undef in case the references to these hash entries 13884 # are used, as if deleted, the 13885 # references are still refering to the old, undeleted element 13886 # (we could do both) 13887 $Texi2HTML::NAME{$direction} = undef; 13888 $Texi2HTML::NO_TEXI{$direction} = undef; 13889 $Texi2HTML::SIMPLE_TEXT{$direction} = undef; 13890 $Texi2HTML::NODE{$direction} = undef; 13891 13892 $Texi2HTML::THIS_ELEMENT = undef; 13893 } 13894 if (@foot_lines) 13895 { 13896 print STDERR "# writing Footnotes in $docu_foot_file\n" if $T2H_VERBOSE; 13897 $FH = open_out ($docu_foot_file) 13898 if $Texi2HTML::Config::SPLIT; 13899 $Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{'Footnotes'}; 13900 $Texi2HTML::HREF{'Footnotes'} = '#' . $footnote_element->{'id'}; 13901 $Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{'Footnotes'}; 13902 $Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{'Footnotes'}; 13903 $Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{'Footnotes'}; 13904 $Texi2HTML::THIS_SECTION = \@foot_lines; 13905 $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor($footnote_element->{'id'}) . "\n" ]; 13906 &$Texi2HTML::Config::print_Footnotes($FH); 13907 close_out($FH, $docu_foot_file) 13908 if ($Texi2HTML::Config::SPLIT); 13909 $Texi2HTML::HREF{'Footnotes'} = $Texi2HTML::HREF{'This'}; 13910 } 13911 13912 if (@{$Texi2HTML::TOC_LINES} and !$Texi2HTML::Config::INLINE_CONTENTS) 13913 { 13914 print STDERR "# writing Toc in $docu_toc_file\n" if $T2H_VERBOSE; 13915 $FH = open_out ($docu_toc_file) 13916 if $Texi2HTML::Config::SPLIT; 13917 $Texi2HTML::HREF{'This'} = $Texi2HTML::HREF{'Contents'}; 13918 $Texi2HTML::HREF{'Contents'} = "#SEC_Contents"; 13919 $Texi2HTML::NAME{'This'} = $Texi2HTML::NAME{'Contents'}; 13920 $Texi2HTML::NO_TEXI{'This'} = $Texi2HTML::NO_TEXI{'Contents'}; 13921 $Texi2HTML::SIMPLE_TEXT{'This'} = $Texi2HTML::SIMPLE_TEXT{'Contents'}; 13922 $Texi2HTML::THIS_SECTION = $Texi2HTML::TOC_LINES; 13923 $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_Contents") . "\n" ]; 13924 &$Texi2HTML::Config::print_Toc($FH); 13925 close_out($FH, $docu_toc_file) 13926 if ($Texi2HTML::Config::SPLIT); 13927 $Texi2HTML::HREF{'Contents'} = $Texi2HTML::HREF{'This'}; 13928 } 13929 13930 if (@{$Texi2HTML::OVERVIEW} and !$Texi2HTML::Config::INLINE_CONTENTS) 13931 { 13932 print STDERR "# writing Overview in $docu_stoc_file\n" if $T2H_VERBOSE; 13933 $FH = open_out ($docu_stoc_file) 13934 if $Texi2HTML::Config::SPLIT; 13935 $Texi2HTML::HREF{This} = $Texi2HTML::HREF{Overview}; 13936 $Texi2HTML::HREF{Overview} = "#SEC_Overview"; 13937 $Texi2HTML::NAME{This} = $Texi2HTML::NAME{Overview}; 13938 $Texi2HTML::NO_TEXI{This} = $Texi2HTML::NO_TEXI{Overview}; 13939 $Texi2HTML::SIMPLE_TEXT{This} = $Texi2HTML::SIMPLE_TEXT{Overview}; 13940 $Texi2HTML::THIS_SECTION = $Texi2HTML::OVERVIEW; 13941 $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_Overview") . "\n" ]; 13942 &$Texi2HTML::Config::print_Overview($FH); 13943 close_out($FH,$docu_stoc_file) 13944 if ($Texi2HTML::Config::SPLIT); 13945 $Texi2HTML::HREF{Overview} = $Texi2HTML::HREF{This}; 13946 } 13947 my $about_body; 13948 if ($about_body = &$Texi2HTML::Config::about_body()) 13949 { 13950 print STDERR "# writing About in $docu_about_file\n" if $T2H_VERBOSE; 13951 $FH = open_out ($docu_about_file) 13952 if $Texi2HTML::Config::SPLIT; 13953 13954 $Texi2HTML::HREF{This} = $Texi2HTML::HREF{About}; 13955 $Texi2HTML::HREF{About} = "#SEC_About"; 13956 $Texi2HTML::NAME{This} = $Texi2HTML::NAME{About}; 13957 $Texi2HTML::NO_TEXI{This} = $Texi2HTML::NO_TEXI{About}; 13958 $Texi2HTML::SIMPLE_TEXT{This} = $Texi2HTML::SIMPLE_TEXT{About}; 13959 $Texi2HTML::THIS_SECTION = [$about_body]; 13960 $Texi2HTML::THIS_HEADER = [ &$Texi2HTML::Config::anchor("SEC_About") . "\n" ]; 13961 &$Texi2HTML::Config::print_About($FH); 13962 close_out($FH, $docu_stoc_file) 13963 if ($Texi2HTML::Config::SPLIT); 13964 $Texi2HTML::HREF{About} = $Texi2HTML::HREF{This}; 13965 } 13966 13967 unless ($Texi2HTML::Config::SPLIT) 13968 { 13969 &$Texi2HTML::Config::print_page_foot($FH); 13970 close_out ($FH); 13971 } 13972} 13973 13974# print section, close file if needed. 13975sub finish_element($$$$) 13976{ 13977 my $FH = shift; 13978 my $element = shift; 13979 my $new_element = shift; 13980 my $first_section = shift; 13981#print STDERR "FINISH_ELEMENT($FH)($element->{'texi'})[$element->{'file'}] counter $files{$element->{'file'}}->{'counter'}\n"; 13982 13983 # handle foot notes 13984 if ($Texi2HTML::Config::SPLIT and scalar(@foot_lines) 13985 and !$Texi2HTML::Config::SEPARATED_FOOTNOTES 13986 and (! $new_element or 13987 ($element and ($new_element->{'file'} ne $element->{'file'}))) 13988 ) 13989 { 13990 if ($files{$element->{'file'}}->{'counter'}) 13991 {# there are other elements in that page we are not on its foot 13992 $files{$element->{'file'}}->{'relative_foot_num'} 13993 = $relative_foot_num; 13994 push @{$files{$element->{'file'}}->{'foot_lines'}}, 13995 @foot_lines; 13996 } 13997 else 13998 {# we output the footnotes as we are at the file end 13999 unshift @foot_lines, @{$files{$element->{'file'}}->{'foot_lines'}}; 14000 &$Texi2HTML::Config::foot_section (\@foot_lines); 14001 push @{$Texi2HTML::THIS_SECTION}, @foot_lines; 14002 } 14003 if ($new_element) 14004 { 14005 $relative_foot_num = 14006 $files{$new_element->{'file'}}->{'relative_foot_num'}; 14007 } 14008 @foot_lines = (); 14009 } 14010 if ($element->{'top'}) 14011 { 14012 my $top_file = $docu_top_file; 14013 #print STDERR "TOP $element->{'texi'}, @section_lines\n"; 14014 print STDERR "[Top]" if ($T2H_VERBOSE); 14015 $Texi2HTML::HREF{'Top'} = href($element_top, $element->{'file'}); 14016 &$Texi2HTML::Config::print_Top($FH, ($element->{'titlefont'} or $element->{'index_page'})); 14017 my $end_page = 0; 14018 if ($Texi2HTML::Config::SPLIT) 14019 { 14020 if (!$files{$element->{'file'}}->{'counter'}) 14021 { 14022 $end_page = 1; 14023 } 14024 } 14025 &$Texi2HTML::Config::print_Top_footer($FH, $end_page); 14026 close_out($FH, $top_file) if ($end_page); 14027 } 14028 else 14029 { 14030 print STDERR "# do element $element->{'texi'}\n" 14031 if ($T2H_DEBUG & $DEBUG_ELEMENTS); 14032 &$Texi2HTML::Config::print_section($FH, $first_section); 14033 if (defined($new_element) and ($new_element->{'file'} ne $element->{'file'})) 14034 { 14035 if (!$files{$element->{'file'}}->{'counter'}) 14036 { 14037 &$Texi2HTML::Config::print_chapter_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'chapter'); 14038 &$Texi2HTML::Config::print_section_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'section'); 14039 #print STDERR "Close file after $element->{'texi'}\n"; 14040 &$Texi2HTML::Config::print_page_foot($FH); 14041 close_out($FH); 14042 } 14043 else 14044 { 14045 print STDERR "counter $files{$element->{'file'}}->{'counter'} ne 0, file $element->{'file'}\n" if ($T2H_DEBUG); 14046 } 14047 } 14048 elsif (!defined($new_element)) 14049 { 14050 if ($Texi2HTML::Config::SPLIT) 14051 { # end of last splitted section 14052 &$Texi2HTML::Config::print_chapter_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'chapter'); 14053 &$Texi2HTML::Config::print_section_footer($FH) if ($Texi2HTML::Config::SPLIT eq 'section'); 14054 &$Texi2HTML::Config::print_page_foot($FH); 14055 close_out($FH); 14056 } 14057 else 14058 { 14059 &$Texi2HTML::Config::end_section($FH, 1); 14060 } 14061 } 14062 elsif ($new_element->{'top'}) 14063 { 14064 &$Texi2HTML::Config::end_section($FH, 1); 14065 } 14066 else 14067 { 14068 &$Texi2HTML::Config::end_section($FH); 14069 } 14070 } 14071} 14072 14073# write to files with name the node name for cross manual references. 14074sub do_node_files() 14075{ 14076 foreach my $key (keys(%nodes)) 14077 { 14078 my $node = $nodes{$key}; 14079 next unless ($node->{'node_file'}); 14080 my $redirection_file = $docu_doc; 14081 $redirection_file = $node->{'file'} if ($Texi2HTML::Config::SPLIT); 14082 if (!$redirection_file) 14083 { 14084 print STDERR "Bug: file for redirection for `$node->{'texi'}' don't exist\n" unless ($novalidate); 14085 next; 14086 } 14087 next if ($redirection_file eq $node->{'node_file'}); 14088 my $file = "${docu_rdir}$node->{'node_file'}"; 14089 $Texi2HTML::NODE{'This'} = $node->{'text'}; 14090 $Texi2HTML::NO_TEXI{'This'} = $node->{'no_texi'}; 14091 $Texi2HTML::SIMPLE_TEXT{'This'} = $node->{'simple_format'}; 14092 $Texi2HTML::NAME{'This'} = $node->{'text'}; 14093 $Texi2HTML::HREF{'This'} = "$node->{'file'}#$node->{'id'}"; 14094 my $NODEFILE = open_out ($file); 14095 &$Texi2HTML::Config::print_redirection_page ($NODEFILE); 14096 close $NODEFILE || die "$ERROR: Can't close $file: $!\n"; 14097 } 14098} 14099 14100#+++############################################################################ 14101# # 14102# Low level functions # 14103# # 14104#---############################################################################ 14105 14106sub locate_include_file($) 14107{ 14108 my $file = shift; 14109 14110 # APA: Don't implicitely search ., to conform with the docs! 14111 # return $file if (-e $file && -r $file); 14112 foreach my $dir (@Texi2HTML::Config::INCLUDE_DIRS) 14113 { 14114 return "$dir/$file" if (-e "$dir/$file" && -r "$dir/$file"); 14115 } 14116 return undef; 14117} 14118 14119sub open_file($$) 14120{ 14121 my $name = shift; 14122 my $line_number = shift; 14123 local *FH; 14124 if (open(*FH, "<$name")) 14125 { 14126 if (defined($Texi2HTML::Config::IN_ENCODING) and $Texi2HTML::Config::USE_UNICODE) 14127 { 14128 binmode(*FH, ":encoding($Texi2HTML::Config::IN_ENCODING)"); 14129 } 14130 my $file = { 'fh' => *FH, 14131 'input_spool' => { 'spool' => [], 14132 'macro' => '' }, 14133 'name' => $name, 14134 'line_nr' => 0 }; 14135 unshift(@fhs, $file); 14136 $input_spool = $file->{'input_spool'}; 14137 $line_number->{'file_name'} = $name; 14138 $line_number->{'line_nr'} = 1; 14139 } 14140 else 14141 { 14142 warn "$ERROR Can't read file $name: $!\n"; 14143 } 14144} 14145 14146sub open_out($) 14147{ 14148 my $file = shift; 14149 local *FILE; 14150 if ($file eq '-') 14151 { 14152 binmode(STDOUT, ":encoding($to_encoding)") if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE); 14153 return \*STDOUT; 14154 } 14155 14156 unless (open(FILE, ">$file")) 14157 { 14158 die "$ERROR Can't open $file for writing: $!\n"; 14159 } 14160 if (defined($to_encoding) and $Texi2HTML::Config::USE_UNICODE) 14161 { 14162 if ($to_encoding eq 'utf8' or $to_encoding eq 'utf-8-strict') 14163 { 14164 binmode(FILE, ':utf8'); 14165 } 14166 else 14167 { 14168 binmode(FILE, ':bytes'); 14169 } 14170 binmode(FILE, ":encoding($to_encoding)"); 14171 } 14172 return *FILE; 14173} 14174 14175# FIXME not used when split 14176sub close_out($;$) 14177{ 14178 my $FH = shift; 14179 my $file = shift; 14180 $file = '' if (!defined($file)); 14181 return if ($Texi2HTML::Config::OUT eq ''); 14182 close ($FH) || die "$ERROR: Error occurred when closing $file: $!\n"; 14183} 14184 14185sub next_line($) 14186{ 14187 my $line_number = shift; 14188 while (@fhs) 14189 { 14190 my $file = $fhs[0]; 14191 $line_number->{'file_name'} = $file->{'name'}; 14192 $input_spool = $file->{'input_spool'}; 14193 if (@{$input_spool->{'spool'}}) 14194 { 14195 $line_number->{'macro'} = $file->{'input_spool'}->{'macro'}; 14196 $line_number->{'line_nr'} = $file->{'line_nr'}; 14197 my $line = shift(@{$input_spool->{'spool'}}); 14198 print STDERR "# unspooling $line" if ($T2H_DEBUG & $DEBUG_MACROS); 14199 return($line); 14200 } 14201 else 14202 { 14203 $file->{'input_spool'}->{'macro'} = ''; 14204 $line_number->{'macro'} = ''; 14205 } 14206 my $fh = $file->{'fh'}; 14207 no strict "refs"; 14208 my $line = <$fh>; 14209 use strict "refs"; 14210 my $chomped_line = $line; 14211 $file->{'line_nr'}++ if (defined($line) and chomp($chomped_line)); 14212 $line_number->{'line_nr'} = $file->{'line_nr'}; 14213 return($line) if (defined($line)); 14214 no strict "refs"; 14215 close($fh); 14216 use strict "refs"; 14217 shift(@fhs); 14218 } 14219 return(undef); 14220} 14221 14222# echo a warning 14223sub echo_warn($;$) 14224{ 14225 my $text = shift; 14226 chomp ($text); 14227 my $line_number = shift; 14228 warn "$WARN $text " . format_line_number($line_number) . "\n"; 14229} 14230 14231sub echo_error($;$) 14232{ 14233 my $text = shift; 14234 chomp ($text); 14235 my $line_number = shift; 14236 warn "$ERROR $text " . format_line_number($line_number) . "\n"; 14237} 14238 14239sub format_line_number($) 14240{ 14241 my $line_number = shift; 14242 my $macro_text = ''; 14243 #$line_number = undef; 14244 return '' unless (defined($line_number)); 14245 $macro_text = " in $line_number->{'macro'}" if ($line_number->{'macro'} ne ''); 14246 my $file_text = '('; 14247 $file_text = "(in $line_number->{'file_name'} " if ($line_number->{'file_name'} ne $docu); 14248 return "${file_text}l. $line_number->{'line_nr'}" . $macro_text . ')'; 14249} 14250 14251# to debug, dump the result of pass_texi and pass_structure in a file 14252sub dump_texi($$;$$) 14253{ 14254 my $lines = shift; 14255 my $pass = shift; 14256 my $numbers = shift; 14257 my $file = shift; 14258 $file = "$docu_rdir$docu_name" . ".pass$pass" if (!defined($file)); 14259 unless (open(DMPTEXI, ">$file")) 14260 { 14261 warn "Can't open $file for writing: $!\n"; 14262 } 14263 print STDERR "# Dump texi\n" if ($T2H_VERBOSE); 14264 my $index = 0; 14265 foreach my $line (@$lines) 14266 { 14267 my $number_information = ''; 14268 my $chomped_line = $line; 14269 $number_information = "$numbers->[$index]->{'file_name'}($numbers->[$index]->{'macro'},$numbers->[$index]->{'line_nr'}) " if (defined($numbers)); 14270 print DMPTEXI "${number_information}$line"; 14271 $index++ if (chomp($chomped_line)); 14272 } 14273 close DMPTEXI; 14274} 14275 14276# return next tag on the line 14277sub next_tag($) 14278{ 14279 my $line = shift; 14280 # macro_regexp 14281 if ($line =~ /^\s*\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])/o or $line =~ /^\s*\@([a-zA-Z][\w-]*)([\s\{\}\@])/ or $line =~ /^\s*\@([a-zA-Z][\w-]*)$/) 14282 { 14283 return ($1); 14284 } 14285 return ''; 14286} 14287 14288sub top_stack($) 14289{ 14290 my $stack = shift; 14291 return undef unless(@$stack); 14292 return $stack->[-1]; 14293} 14294 14295# return the next element with balanced {} 14296sub next_bracketed($$) 14297{ 14298 my $line = shift; 14299 my $line_nr = shift; 14300 my $opened_braces = 0; 14301 my $result = ''; 14302 my $spaces; 14303 if ($line =~ /^(\s*)$/) 14304 { 14305 return ('','',$1); 14306 } 14307 while ($line !~ /^\s*$/) 14308 { 14309#print STDERR "next_bracketed($opened_braces): $result !!! $line"; 14310 if (!$opened_braces) 14311 { # beginning of item 14312 $line =~ s/^(\s*)//; 14313 $spaces = $1; 14314 #if ($line =~ s/^([^\{\}\s]+)//) 14315 if ($line =~ s/^([^\{\}]+?)(\s+)/$2/ or $line =~ s/^([^\{\}]+?)$//) 14316 { 14317 $result = $1; 14318 $result =~ s/\s*$//; 14319 return ($result, $line, $spaces); 14320 } 14321 elsif ($line =~ s/^([^\{\}]+?)([\{\}])/$2/) 14322 { 14323 $result = $1; 14324 } 14325 } 14326 elsif($line =~ s/^([^\{\}]+)//) 14327 { 14328 $result .= $1; 14329 } 14330 if ($line =~ s/^([\{\}])//) 14331 { 14332 my $brace = $1; 14333 $opened_braces++ if ($brace eq '{'); 14334 $opened_braces-- if ($brace eq '}'); 14335 14336 if ($opened_braces < 0) 14337 { 14338 echo_error("too much '}' in specification", $line_nr); 14339 $opened_braces = 0; 14340 next; 14341 } 14342 $result .= $brace; 14343 return ($result, $line, $spaces) if ($opened_braces == 0); 14344 } 14345 } 14346 if ($opened_braces) 14347 { 14348 echo_error("'{' not closed in specification", $line_nr); 14349 return ($result . ( '}' x $opened_braces), '', $spaces); 14350 } 14351 print STDERR "BUG: at the end of next_bracketed\n"; 14352 return undef; 14353} 14354 14355# do a href using file and id and taking care of ommitting file if it is 14356# the same 14357# element: structuring element to point to 14358# file: current file 14359sub href($$) 14360{ 14361 my $element = shift; 14362 my $file = shift; 14363 return '' unless defined($element); 14364 my $href = ''; 14365 print STDERR "Bug: $element->{'texi'}, id undef\n" if (!defined($element->{'id'})); 14366 print STDERR "Bug: $element->{'texi'}, file undef\n" if (!defined($element->{'file'})); 14367#foreach my $key (keys(%{$element})) 14368#{ 14369# my $value = 'UNDEF'; $value = $element->{$key} if defined($element->{$key}); 14370# print STDERR "$key: $value\n"; 14371#}print STDERR "\n"; 14372 $href .= $element->{'file'} if (defined($element->{'file'}) and $file ne $element->{'file'}); 14373 $href .= "#$element->{'id'}" if (defined($element->{'id'})); 14374 return $href; 14375} 14376 14377sub normalise_space($) 14378{ 14379 return undef unless (defined ($_[0])); 14380 my $text = shift; 14381 $text =~ s/\s+/ /go; 14382 $text =~ s/ $//; 14383 $text =~ s/^ //; 14384 return $text; 14385} 14386 14387sub normalise_node($) 14388{ 14389 return undef unless (defined ($_[0])); 14390 my $text = shift; 14391 $text = normalise_space($text); 14392 $text =~ s/^top$/Top/i; 14393 return $text; 14394} 14395 14396sub do_anchor_label($$$$) 14397{ 14398 my $command = shift; 14399 #my $anchor = shift; 14400 my $args = shift; 14401 my $anchor = $args->[0]; 14402 my $style_stack = shift; 14403 my $state = shift; 14404 my $line_nr = shift; 14405 14406 return '' if ($state->{'multiple_pass'}); 14407 $anchor = normalise_node($anchor); 14408 if (!exists($nodes{$anchor}) or !defined($nodes{$anchor}->{'id'})) 14409 { 14410 print STDERR "Bug: unknown anchor `$anchor'\n"; 14411 } 14412 return &$Texi2HTML::Config::anchor($nodes{$anchor}->{'id'}); 14413} 14414 14415sub get_format_command($) 14416{ 14417 my $format = shift; 14418 my $command = ''; 14419 my $format_name = ''; 14420 my $term = 0; 14421 my $item_nr; 14422 my $paragraph_number; 14423 my $enumerate_type; 14424 my $number; 14425 14426 $command = $format->{'command'} if (defined($format->{'command'})); 14427 $format_name = $format->{'format'} if (defined($format->{'format'})); 14428 $term = 1 if ($format->{'term'}); #This should never happen 14429 14430 return ($format_name,$command,\$format->{'paragraph_number'},$term, 14431 $format->{'item_nr'}, $format->{'spec'}, $format->{'number'}, 14432 $format->{'stack_at_beginning'}); 14433} 14434 14435sub do_paragraph($$) 14436{ 14437 my $text = shift; 14438 my $state = shift; 14439 my ($format, $paragraph_command, $paragraph_number, $term, $item_nr, 14440 $enumerate_type, $number,$stack_at_beginning) 14441 = get_format_command ($state->{'paragraph_context'}); 14442 delete $state->{'paragraph_context'}; 14443 14444 my $indent_style = ''; 14445 if (exists($state->{'paragraph_indent'})) 14446 { 14447 $indent_style = $state->{'paragraph_indent'}; 14448 $state->{'paragraph_indent'} = undef; 14449 delete $state->{'paragraph_indent'}; 14450 } 14451 my $paragraph_command_formatted; 14452 $state->{'paragraph_nr'}--; 14453 (print STDERR "Bug text undef in do_paragraph", return '') unless defined($text); 14454 my $align = ''; 14455 $align = $state->{'paragraph_style'}->[-1] if ($state->{'paragraph_style'}->[-1]); 14456 14457 if (exists($::style_map_ref->{$paragraph_command}) and 14458 !exists($Texi2HTML::Config::special_list_commands{$format}->{$paragraph_command})) 14459 { 14460 if ($format eq 'itemize') 14461 { 14462 chomp ($text); 14463 $text = do_simple($paragraph_command, $text, $state, [$text]); 14464 $text = $text . "\n"; 14465 } 14466 } 14467 elsif (exists($::things_map_ref->{$paragraph_command})) 14468 { 14469 $paragraph_command_formatted = do_simple($paragraph_command, '', $state); 14470 } 14471 return &$Texi2HTML::Config::paragraph($text, $align, $indent_style, $paragraph_command, $paragraph_command_formatted, $paragraph_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning); 14472} 14473 14474sub do_preformatted($$) 14475{ 14476 my $text = shift; 14477 my $state = shift; 14478 my ($format, $leading_command, $preformatted_number, $term, $item_nr, 14479 $enumerate_type, $number,$stack_at_beginning) 14480 = get_format_command($state->{'preformatted_context'}); 14481 delete ($state->{'preformatted_context'}); 14482 my $leading_command_formatted; 14483 my $pre_style = ''; 14484 my $class = ''; 14485 $pre_style = $state->{'preformatted_stack'}->[-1]->{'pre_style'} if ($state->{'preformatted_stack'}->[-1]->{'pre_style'}); 14486 $class = $state->{'preformatted_stack'}->[-1]->{'class'}; 14487 print STDERR "BUG: !state->{'preformatted_stack'}->[-1]->{'class'}\n" unless ($class); 14488 if (exists($::style_map_ref->{$leading_command}) and 14489 !exists($Texi2HTML::Config::special_list_commands{$format}->{$leading_command}) and ($style_type{$leading_command} eq 'style')) 14490 { 14491 $text = do_simple($leading_command, $text, $state,[$text]) if ($format eq 'itemize'); 14492 } 14493 elsif (exists($::things_map_ref->{$leading_command})) 14494 { 14495 $leading_command_formatted = do_simple($leading_command, '', $state); 14496 } 14497 return &$Texi2HTML::Config::preformatted($text, $pre_style, $class, $leading_command, $leading_command_formatted, $preformatted_number, $format, $item_nr, $enumerate_type, $number,$state->{'command_stack'},$stack_at_beginning); 14498} 14499 14500sub do_external_href($) 14501{ 14502 # node_id is a unique node identifier with only letters, digits, - and _ 14503 # node_xhtml_id is almost the same, but xhtml id can only begin with 14504 # letters, so a prefix has to be appended 14505 my $texi_node = shift; 14506 my $file = ''; 14507 my $node_file = ''; 14508 my $node_id = ''; 14509 my $node_xhtml_id = ''; 14510 14511#print STDERR "do_external_href $texi_node\n"; 14512 14513 if ($texi_node =~ s/^\((.+?)\)//) 14514 { 14515 $file = $1; 14516 } 14517 $texi_node = normalise_node($texi_node); 14518 if ($texi_node ne '') 14519 { 14520 if (exists($nodes{$texi_node}) and ($nodes{$texi_node}->{'cross_manual_target'})) 14521 { 14522 $node_id = $nodes{$texi_node}->{'cross_manual_target'}; 14523 if ($Texi2HTML::Config::TRANSLITERATE_NODE) 14524 { 14525 $node_file = $nodes{$texi_node}->{'cross_manual_file'}; 14526 } 14527 } 14528 else 14529 { 14530 if ($Texi2HTML::Config::TRANSLITERATE_NODE) 14531 { 14532 ($node_id, $node_file) = cross_manual_line($texi_node,1); 14533 } 14534 else 14535 { 14536 $node_id = cross_manual_line($texi_node); 14537 } 14538 } 14539 $node_xhtml_id = node_to_id($node_id); 14540 $node_file = $node_id unless ($Texi2HTML::Config::TRANSLITERATE_NODE); 14541 } 14542 return &$Texi2HTML::Config::external_href($texi_node, $node_file, 14543 $node_xhtml_id, $file); 14544} 14545 14546# transform node for cross ref name to id suitable for xhtml: an xhtml id 14547# must begin with a letter. 14548sub node_to_id($) 14549{ 14550 my $cross_ref_node_name = shift; 14551 $cross_ref_node_name =~ s/^([0-9_])/g_t$1/; 14552 return $cross_ref_node_name; 14553} 14554 14555# return 1 if the following tag shouldn't begin a line 14556sub no_line($) 14557{ 14558 my $line = shift; 14559 my $next_tag = next_tag($line); 14560 return 1 if (($line =~ /^\s*$/) or $no_line_macros{$next_tag} or 14561 (($next_tag =~ /^(\w+?)index$/) and ($1 ne 'print')) or 14562 (($line =~ /^\@end\s+(\w+)/) and $no_line_macros{"end $1"})); 14563 return 0; 14564} 14565 14566sub no_paragraph($$) 14567{ 14568 my $state = shift; 14569 my $line = shift; 14570 return ($state->{'paragraph_context'} or $state->{'preformatted'} or $state->{'remove_texi'} or no_line($line) or $state->{'no_paragraph'}); 14571} 14572 14573# We restart the preformatted format which was stopped 14574# by the format if in preformatted, and start a paragraph 14575# for the text following the end of the format, if needed 14576sub begin_paragraph_after_command($$$$) 14577{ 14578 my $state = shift; 14579 my $stack = shift; 14580 my $command = shift; 14581 my $text_following = shift; 14582 14583 if (($state->{'preformatted'} 14584 and !$Texi2HTML::Config::format_in_paragraph{$command}) 14585 or (!no_paragraph($state,$text_following))) 14586 { 14587 begin_paragraph($stack, $state); 14588 } 14589} 14590 14591# handle raw formatting, ignored regions... 14592sub do_text_macro($$$$$) 14593{ 14594 my $type = shift; 14595 my $line = shift; 14596 my $state = shift; 14597 my $stack = shift; 14598 my $line_nr = shift; 14599 my $value; 14600 #print STDERR "do_text_macro $type\n"; 14601 14602 if ($text_macros{$type} eq 'raw') 14603 { 14604 $state->{'raw'} = $type; 14605 #print STDERR "RAW\n"; 14606 if ($state->{'raw'}) 14607 { 14608 push @$stack, { 'style' => $type, 'text' => '' }; 14609 } 14610 } 14611 elsif ($text_macros{$type} eq 'value') 14612 { 14613 if (($line =~ s/(\s+)($VARRE)$//) or ($line =~ s/(\s+)($VARRE)(\s)//)) 14614 { 14615 $value = $1 . $2; 14616 $value .= $3 if defined($3); 14617 if ($state->{'ignored'}) 14618 { 14619 if ($type eq $state->{'ignored'}) 14620 { 14621 $state->{'ifvalue_inside'}++; 14622 } 14623 # if 'ignored' we don't care about the command as long as 14624 # the nesting is correct 14625 return ($line,''); 14626 } 14627 my $open_ifvalue = 0; 14628 if ($type eq 'ifclear') 14629 { 14630 if (defined($value{$2})) 14631 { 14632 $open_ifvalue = 1; 14633 } 14634 else 14635 { 14636 push @{$state->{'text_macro_stack'}}, $type; 14637 } 14638 } 14639 elsif ($type eq 'ifset') 14640 { 14641 unless (defined($value{$2})) 14642 { 14643 $open_ifvalue = 1; 14644 } 14645 else 14646 { 14647 push @{$state->{'text_macro_stack'}}, $type; 14648 } 14649 } 14650 if ($open_ifvalue) 14651 { 14652 $state->{'ignored'} = $type; 14653 $state->{'ifvalue'} = $type; 14654 $state->{'ifvalue_inside'} = 1; 14655 # We add at the top of the stack to be able to close all 14656 # opened comands when closing the ifset/ifclear (and ignore 14657 # everything that is in those commands) 14658 push @$stack, { 'style' => 'ifvalue', 'text' => '' }; 14659 } 14660 14661 } 14662 else 14663 { # we accept a lone @ifset or @ifclear if it is inside an 14664 if ($type eq $state->{'ifvalue'}) 14665 { 14666 $state->{'ifvalue_inside'}++; 14667 return ($line,''); 14668 } 14669 echo_error ("Bad $type line: $line", $line_nr) unless ($state->{'ignored'}); 14670 } 14671 } 14672 elsif (not $text_macros{$type}) 14673 { # ignored text 14674 $state->{'ignored'} = $type; 14675 #print STDERR "IGNORED\n"; 14676 } 14677 else 14678 { 14679 push @{$state->{'text_macro_stack'}}, $type unless($state->{'ignored'}) ; 14680 } 14681 my $text = "\@$type"; 14682 $text .= $value if defined($value); 14683 return ($line, $text); 14684} 14685 14686# do regions handled specially, currently only tex, going through latex2html 14687sub init_special($$) 14688{ 14689 my $style = shift; 14690 my $text = shift; 14691 if (defined($Texi2HTML::Config::command_handler{$style}) and 14692 defined($Texi2HTML::Config::command_handler{$style}->{'init'})) 14693 { 14694 $special_commands{$style}->{'count'} = 0 if (!defined($special_commands{$style})); 14695 if ($Texi2HTML::Config::command_handler{$style}->{'init'}($style,$text, 14696 $special_commands{$style}->{'count'} +1)) 14697 { 14698 $special_commands{$style}->{'count'}++; 14699 return "\@special_${style}_".$special_commands{$style}->{'count'}."{}"; 14700 } 14701 return ''; 14702 } 14703} 14704 14705sub do_insertcopying($) 14706{ 14707 my $state = shift; 14708 return '' unless @{$region_lines{'copying'}}; 14709 my $insert_copying_state = duplicate_state($state); 14710 $insert_copying_state->{'multiple_pass'} = 1; 14711 return substitute_text($insert_copying_state, @{$region_lines{'copying'}}); 14712} 14713 14714sub get_deff_index($$$) 14715{ 14716 my $tag = shift; 14717 my $line = shift; 14718 my $line_nr = shift; 14719 14720 $tag =~ s/x$//; 14721 my ($style, $category, $name, $type, $class, $arguments); 14722 ($style, $category, $name, $type, $class, $arguments) = parse_def($tag, $line, $line_nr); 14723 $name = &$Texi2HTML::Config::definition_category($name, $class, $style); 14724 return ($style, '') if (!defined($name) or ($name =~ /^\s*$/)); 14725 return ($style, $name, $arguments); 14726} 14727 14728sub parse_def($$$) 14729{ 14730 my $command = shift; 14731 my $line = shift; 14732 my $line_nr = shift; 14733 14734 my $tag = $command; 14735 14736 if (!ref ($Texi2HTML::Config::def_map{$tag})) 14737 { 14738 # substitute shortcuts for definition commands 14739 my $substituted = $Texi2HTML::Config::def_map{$tag}; 14740 $substituted =~ s/(\w+)//; 14741 $tag = $1; 14742 $line = $substituted . $line; 14743 } 14744#print STDERR "PARSE_DEF($command,$tag) $line"; 14745 my ($category, $name, $type, $class, $arguments); 14746 my @args = @{$Texi2HTML::Config::def_map{$tag}}; 14747 my $style = shift @args; 14748 while (@args) 14749 { 14750 my $arg = shift @args; 14751 if (defined($arg)) 14752 { 14753 # backward compatibility, it was possible to have a { in front. 14754 $arg =~ s/^\{//; 14755 my $item; 14756 my $spaces; 14757 ($item, $line,$spaces) = next_bracketed($line, $line_nr); 14758 last if (!defined($item)); 14759 $item =~ s/^\{(.*)\}$/$1/ if ($item =~ /^\{/); 14760 if ($arg eq 'category') 14761 { 14762 $category = $item; 14763 } 14764 elsif ($arg eq 'name') 14765 { 14766 $name = $item; 14767 } 14768 elsif ($arg eq 'type') 14769 { 14770 $type = $item; 14771 } 14772 elsif ($arg eq 'class') 14773 { 14774 $class = $item; 14775 } 14776 elsif ($arg eq 'arg') 14777 { 14778 $line = $spaces . $item . $line; 14779 } 14780 } 14781 else 14782 { 14783 last; 14784 } 14785 } 14786#print STDERR "PARSE_DEF (style $style, category $category, name $name, type $type, class $class, line $line)\n"; 14787 return ($style, $category, $name, $type, $class, $line); 14788} 14789 14790sub begin_deff_item($$;$) 14791{ 14792 my $stack = shift; 14793 my $state = shift; 14794 my $no_paragraph = shift; 14795 #print STDERR "DEF push deff_item for $state->{'deff'}\n"; 14796 push @$stack, { 'format' => 'deff_item', 'text' => '', 'deff_line' => $state->{'deff_line'}}; 14797 # there is no paragraph when a new deff just follows the deff we are 14798 # opening 14799 begin_paragraph($stack, $state) 14800 if ($state->{'preformatted'} and !$no_paragraph); 14801 delete($state->{'deff_line'}); 14802 #dump_stack(undef, $stack, $state); 14803} 14804 14805sub begin_paragraph($$) 14806{ 14807 my $stack = shift; 14808 my $state = shift; 14809 14810 my $command = 1; 14811 my $top_format = top_format($stack); 14812 if (defined($top_format)) 14813 { 14814 $command = $top_format; 14815 } 14816 else 14817 { 14818 $command = { }; 14819 } 14820 $command->{'stack_at_beginning'} = [ @{$state->{'command_stack'}} ]; 14821 if ($state->{'preformatted'}) 14822 { 14823 push @$stack, {'format' => 'preformatted', 'text' => '' }; 14824 $state->{'preformatted_context'} = $command; 14825 push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'}; 14826 delete $state->{'paragraph_macros'}; 14827 return; 14828 } 14829 $state->{'paragraph_context'} = $command; 14830 $state->{'paragraph_nr'}++; 14831 push @$stack, {'format' => 'paragraph', 'text' => '' }; 14832 # if there are macros which weren't closed when the previous 14833 # paragraph was closed we reopen them here 14834 push @$stack, @{$state->{'paragraph_macros'}} if $state->{'paragraph_macros'}; 14835 delete $state->{'paragraph_macros'}; 14836} 14837 14838sub parse_format_command($$) 14839{ 14840 my $line = shift; 14841 my $tag = shift; 14842 my $command = 'asis'; 14843 # macro_regexp 14844 if (($line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?$/ or $line =~ /^\s*\@([A-Za-z][\w-]*)(\{\})?\s/) and ($::things_map_ref->{$1} or defined($::style_map_ref->{$1}))) 14845 { 14846 # macro_regexp 14847 $line =~ s/^\s*\@([A-Za-z][\w-]*)(\{\})?\s*//; 14848 $command = $1; 14849 } 14850 return ('', $command) if ($line =~ /^\s*$/); 14851 chomp $line; 14852 $line = substitute_text ({'keep_nr' => 1, 'keep_texi' => 1, 'check_item' => $tag}, $line); 14853 return ($line, $command); 14854} 14855 14856sub parse_enumerate($) 14857{ 14858 my $line = shift; 14859 my $spec; 14860 if ($line =~ /^\s*(\w)\b/ and ($1 ne '_')) 14861 { 14862 $spec = $1; 14863 $line =~ s/^\s*(\w)\s*//; 14864 } 14865 return ($line, $spec); 14866} 14867 14868sub parse_multitable($$) 14869{ 14870 my $line = shift; 14871 my $line_nr = shift; 14872 # first find the table width 14873 my $table_width = 0; 14874 if ($line =~ s/^\s+\@columnfractions\s+//) 14875 { 14876 my @fractions = split /\s+/, $line; 14877 $table_width = $#fractions + 1; 14878 while (@fractions) 14879 { 14880 my $fraction = shift @fractions; 14881 unless ($fraction =~ /^(\d*\.\d+)|(\d+)\.?$/) 14882 { 14883 echo_error ("column fraction not a number: $fraction", $line_nr); 14884 #warn "$ERROR column fraction not a number: $fraction"; 14885 } 14886 } 14887 } 14888 else 14889 { 14890 my $element; 14891 my $line_orig = $line; 14892 while ($line !~ /^\s*$/) 14893 { 14894 my $spaces; 14895 ($element, $line, $spaces) = next_bracketed($line, $line_nr); 14896 if ($element =~ /^\{/) 14897 { 14898 $table_width++; 14899 } 14900 else 14901 { 14902 echo_error ("garbage in multitable specification: $element", $line_nr); 14903 } 14904 } 14905 } 14906 return ($table_width); 14907} 14908 14909sub end_format($$$$$) 14910{ 14911 my $text = shift; 14912 my $stack = shift; 14913 my $state = shift; 14914 my $format = shift; 14915 my $line_nr = shift; 14916 #print STDERR "END FORMAT $format\n"; 14917 #dump_stack($text, $stack, $state); 14918 #sleep 1; 14919 if ($format_type{$format} eq 'menu') 14920 { 14921 $state->{'menu'}--; 14922 close_menu($text, $stack, $state, $line_nr); 14923 } 14924 if (($format_type{$format} eq 'list') or ($format_type{$format} eq 'table')) 14925 { # those functions return if they detect an inapropriate context 14926 add_item($text, $stack, $state, $line_nr, '', 1); # handle lists 14927 add_term($text, $stack, $state, $line_nr, 1); # handle table 14928 add_line($text, $stack, $state, $line_nr, 1); # handle table 14929 add_row($text, $stack, $state, $line_nr); # handle multitable 14930 } 14931 14932 #print STDERR "END_FORMAT\n"; 14933 #dump_stack($text, $stack, $state); 14934 14935 # set to 1 if there is a mismatch between the closed format and format 14936 # opened before 14937 my $format_mismatch = 0; 14938 14939 my $format_ref = pop @$stack; 14940 14941 ######################### debug 14942 if (!defined($format_ref->{'text'})) 14943 { 14944 push @$stack, $format_ref; 14945 print STDERR "Bug: text undef in end_format $format\n"; 14946 dump_stack($text, $stack, $state); 14947 pop @$stack; 14948 } 14949 ######################### end debug 14950 14951 if (defined($Texi2HTML::Config::def_map{$format})) 14952 { 14953 close_stack($text, $stack, $state, $line_nr, undef, 'deff_item') 14954 unless ($format_ref->{'format'} eq 'deff_item'); 14955 add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'})); 14956 $format_ref = pop @$stack; # pop deff 14957 ######################################### debug 14958 if (!defined($format_ref->{'format'}) or !defined($Texi2HTML::Config::def_map{$format_ref->{'format'}})) 14959 { 14960 print STDERR "Bug: not a def* under deff_item\n"; 14961 push (@$stack, $format_ref); 14962 dump_stack($text, $stack, $state); 14963 pop @$stack; 14964 } 14965 ######################################### end debug 14966 elsif ($format_ref->{'format'} ne $format) 14967 { 14968 $format_mismatch = 1; 14969 echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format", $line_nr); 14970 } 14971 add_prev($text, $stack, &$Texi2HTML::Config::def($format_ref->{'text'})); 14972 } 14973 elsif ($format_type{$format} eq 'cartouche') 14974 { 14975 add_prev($text, $stack, &$Texi2HTML::Config::cartouche($format_ref->{'text'},$state->{'command_stack'})); 14976 } 14977 elsif ($format eq 'float') 14978 { 14979 unless (defined($state->{'float'})) 14980 { 14981 print STDERR "Bug: state->{'float'} not defined in float\n"; 14982 next; 14983 } 14984 my ($caption_lines, $shortcaption_lines) = &$Texi2HTML::Config::caption_shortcaption($state->{'float'}); 14985 my ($caption_text, $shortcaption_text); 14986 $caption_text = substitute_text(duplicate_state($state), @$caption_lines) if (defined($caption_lines)); 14987 $shortcaption_text = substitute_text(duplicate_state($state), @$shortcaption_lines) if (defined($shortcaption_lines)); 14988 add_prev($text, $stack, &$Texi2HTML::Config::float($format_ref->{'text'}, $state->{'float'}, $caption_text, $shortcaption_text)); 14989 delete $state->{'float'}; 14990 } 14991 elsif (exists ($Texi2HTML::Config::complex_format_map->{$format})) 14992 { 14993 $state->{'preformatted'}--; 14994 pop @{$state->{'preformatted_stack'}}; 14995 # debug 14996 if (!defined($Texi2HTML::Config::complex_format_map->{$format_ref->{'format'}}->{'begin'})) 14997 { 14998 print STDERR "Bug undef $format_ref->{'format'}" . "->{'begin'} (for $format...)\n"; 14999 dump_stack ($text, $stack, $state); 15000 } 15001 #print STDERR "before $format\n"; 15002 #dump_stack ($text, $stack, $state); 15003 add_prev($text, $stack, &$Texi2HTML::Config::complex_format($format_ref->{'format'}, $format_ref->{'text'})); 15004 #print STDERR "after $format\n"; 15005 #dump_stack ($text, $stack, $state); 15006 } 15007 elsif (($format_type{$format} eq 'table') or ($format_type{$format} eq 'list')) 15008 { 15009 #print STDERR "CLOSE $format ($format_ref->{'format'})\n$format_ref->{'text'}\n"; 15010 pop @{$state->{'table_list_stack'}}; 15011 #dump_stack($text, $stack, $state); 15012 if ($format_ref->{'format'} ne $format) 15013 { # for example vtable closing a table. Cannot be known 15014 # before if in a cell 15015 $format_mismatch = 1; 15016 echo_warn ("Waiting for \@end $format_ref->{'format'}, found \@end $format ", $line_nr); 15017 } 15018 if ($Texi2HTML::Config::format_map{$format}) 15019 { # table or list has a simple format 15020 add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'})); 15021 } 15022 else 15023 { # table or list handler defined by the user 15024 add_prev($text, $stack, &$Texi2HTML::Config::table_list($format_ref->{'format'}, $format_ref->{'text'}, $format_ref->{'command'})); 15025 } 15026 } 15027 elsif ($format_type{$format} eq 'menu') 15028 { 15029 # it should be short-circuited if $Texi2HTML::Config::SIMPLE_MENU 15030 if ($state->{'preformatted'}) 15031 { 15032 # end the fake complex format 15033 $state->{'preformatted'}--; 15034 pop @{$state->{'preformatted_stack'}}; 15035 pop @$stack; 15036 } 15037 add_prev($text, $stack, &$Texi2HTML::Config::menu($format_ref->{'text'})); 15038 } 15039 elsif ($format eq 'quotation') 15040 { 15041 my $quotation_args = pop @{$state->{'quotation_stack'}}; 15042 #add_prev($text, $stack, &$Texi2HTML::Config::quotation($format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'style_texi'}, $quotation_args->{'style_id'})); 15043 add_prev($text, $stack, &$Texi2HTML::Config::quotation($format_ref->{'text'}, $quotation_args->{'text'}, $quotation_args->{'text_texi'})); 15044 } 15045 elsif ($Texi2HTML::Config::paragraph_style{$format}) 15046 { 15047 if ($state->{'paragraph_style'}->[-1] eq $format) 15048 { 15049 pop @{$state->{'paragraph_style'}}; 15050 } 15051 add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command($format_ref->{'format'},$format_ref->{'text'})); 15052 } 15053 elsif (exists($Texi2HTML::Config::format_map{$format})) 15054 { 15055 add_prev($text, $stack, end_simple_format($format_ref->{'format'}, $format_ref->{'text'})); 15056 } 15057 else 15058 { 15059 echo_warn("Unknown format $format", $line_nr); 15060 } 15061 # special case for center as it is at the bottom of the stack 15062 my $removed_from_stack; 15063 if ($format eq 'center') 15064 { 15065 $removed_from_stack = shift @{$state->{'command_stack'}}; 15066 } 15067 else 15068 { 15069 $removed_from_stack = pop @{$state->{'command_stack'}}; 15070 } 15071 if ($removed_from_stack ne $format and !$format_mismatch) 15072 { 15073 print STDERR "Bug: removed_from_stack $removed_from_stack ne format $format\n"; 15074 } 15075} 15076 15077sub do_text($;$) 15078{ 15079 my $text = shift; 15080 my $state = shift; 15081 return $text if ($state->{'keep_texi'}); 15082 my $remove_texi = 1 if ($state->{'remove_texi'} and !$state->{'simple_format'}); 15083 return (&$Texi2HTML::Config::normal_text($text, $remove_texi, $state->{'preformatted'}, $state->{'code_style'},$state->{'command_stack'})); 15084} 15085 15086sub end_simple_format($$) 15087{ 15088 my $tag = shift; 15089 my $text = shift; 15090 15091 my $element = $Texi2HTML::Config::format_map{$tag}; 15092 return &$Texi2HTML::Config::format($tag, $element, $text); 15093} 15094 15095sub close_menu($$$$) 15096{ 15097 my $text = shift; 15098 my $stack = shift; 15099 my $state = shift; 15100 my $line_nr = shift; 15101 if ($state->{'menu_comment'}) 15102 { 15103 #print STDERR "close MENU_COMMENT\n"; 15104 #dump_stack($text, $stack, $state); 15105 close_stack($text, $stack, $state, $line_nr, undef, 'menu_comment'); 15106 # close_paragraph isn't needed in most cases, but a preformatted may 15107 # appear after close_stack if we closed a format, as formats reopen 15108 # preformatted. However it is empty and close_paragraph will remove it 15109 close_paragraph($text, $stack, $state); 15110 my $menu_comment = pop @$stack; 15111 if (!$menu_comment->{'format'} or $menu_comment->{'format'} ne 'menu_comment') 15112 { 15113 warn "Bug waiting for menu_comment, got $menu_comment->{'format'}\n"; 15114 dump_stack($text, $stack, $state); 15115 } 15116 add_prev($text, $stack, &$Texi2HTML::Config::menu_comment($menu_comment->{'text'})); 15117 unless ($Texi2HTML::Config::SIMPLE_MENU) 15118 { 15119 pop @{$state->{'preformatted_stack'}}; 15120 $state->{'preformatted'}--; 15121 } 15122 $state->{'menu_comment'}--; 15123 } 15124 if ($state->{'menu_entry'}) 15125 { 15126 close_stack($text, $stack,$state, $line_nr, undef, 'menu_description'); 15127 my $descr = pop(@$stack); 15128 print STDERR "# close_menu: close description\n" if ($T2H_DEBUG & $DEBUG_MENU); 15129 add_prev($text, $stack, do_menu_description($descr->{'text'}, $state)); 15130 delete $state->{'menu_entry'}; 15131 } 15132} 15133 15134# Format menu link 15135sub do_menu_link($$;$) 15136{ 15137 my $state = shift; 15138 my $line_nr = shift; 15139 my $simple = shift; 15140 my $menu_entry = $state->{'menu_entry'}; 15141 my $file = $state->{'element'}->{'file'}; 15142 my $node_name = normalise_node($menu_entry->{'node'}); 15143 15144 my $substitution_state = duplicate_state($state); 15145 my $name = substitute_line($menu_entry->{'name'}, $substitution_state); 15146 my $node_formatted = substitute_line($menu_entry->{'node'}, $substitution_state); 15147 15148 my $entry = ''; 15149 my $href; 15150 my $element = $nodes{$node_name}; 15151 15152 # menu points to an unknown node 15153 if (!$element->{'seen'}) 15154 { 15155 if ($menu_entry->{'node'} =~ /^\s*\(.*\)/o or $novalidate) 15156 { 15157 # menu entry points to another info manual or invalid nodes 15158 # and novalidate is set 15159 #$href = $nodes{$node_name}->{'file'}; 15160 $href = do_external_href($node_name); 15161 } 15162 else 15163 { 15164 echo_error ("Unknown node in menu entry `$node_name'", $line_nr); 15165 # try to find an equivalent node 15166 my @equivalent_nodes = equivalent_nodes($node_name); 15167 my $node_seen; 15168 foreach my $equivalent_node (@equivalent_nodes) 15169 { 15170 if ($nodes{$equivalent_node}->{'seen'}) 15171 { 15172 $node_seen = $equivalent_node; 15173 last; 15174 } 15175 } 15176 if (defined($node_seen)) 15177 { 15178 echo_warn (" ---> but equivalent node `$node_seen' found"); 15179 $element = $nodes{$node_seen}; 15180 } 15181 } 15182 } 15183 15184 # the original node or an equivalent node was seen 15185 if ($element->{'seen'}) 15186 { 15187 if ($element->{'reference_element'}) 15188 { 15189 $element = $element->{'reference_element'}; 15190 } 15191 15192 #print STDERR "SUBHREF in menu for `$element->{'texi'}'\n"; 15193 $href = href($element, $file); 15194 if (! $element->{'node'}) 15195 { 15196 $entry = $element->{'text'}; # this is the section/node name 15197 $entry = "$Texi2HTML::Config::MENU_SYMBOL $entry" if (($entry ne '') and (!defined($element->{'number'}) or ($element->{'number'} =~ /^\s*$/)) and $Texi2HTML::Config::UNNUMBERED_SYMBOL_IN_MENU); 15198 } 15199 } 15200 # save the element used for the href for the description 15201 $menu_entry->{'menu_reference_element'} = $element; 15202 15203 return &$Texi2HTML::Config::menu_link($entry, $substitution_state, $href, $node_formatted, $name, $menu_entry->{'ending'}) unless ($simple); 15204 return &$Texi2HTML::Config::simple_menu_link($entry, $state->{'preformatted'}, $href, $node_formatted, $name, $menu_entry->{'ending'}); 15205} 15206 15207sub do_menu_description($$) 15208{ 15209 my $descr = shift; 15210 my $state = shift; 15211 my $menu_entry = $state->{'menu_entry'}; 15212 15213 my $element = $menu_entry->{'menu_reference_element'}; 15214 15215 return &$Texi2HTML::Config::menu_description($descr, duplicate_state($state),$element->{'text_nonumber'}); 15216} 15217 15218sub do_xref($$$$) 15219{ 15220 my $macro = shift; 15221 my $args = shift; 15222 my $style_stack = shift; 15223 my $state = shift; 15224 my $line_nr = shift; 15225 15226 my $result = ''; 15227 my @args = @$args; 15228 #print STDERR "DO_XREF: $macro\n"; 15229 my $j = 0; 15230 for ($j = 0; $j <= $#$args; $j++) 15231 { 15232 $args[$j] = normalise_space($args[$j]); 15233 # print STDERR " ($j)$args[$j]\n"; 15234 } 15235 $args[0] = '' if (!defined($args[0])); 15236 my $node_texi = normalise_node($args[0]); 15237 # a ref to a node in an info manual 15238 if ($args[0] =~ s/^\(([^\)]+)\)\s*//) 15239 { 15240 if ($macro eq 'inforef') 15241 { 15242 $args[2] = $1 unless ($args[2]); 15243 } 15244 else 15245 { 15246 $args[3] = $1 unless ($args[3]); 15247 } 15248 } 15249 if (($macro ne 'inforef') and $args[3]) 15250 { 15251 $node_texi = "($args[3])" . normalise_node($args[0]); 15252 } 15253 15254 if ($macro eq 'inforef') 15255 { 15256 if ((@args < 1) or ($args[0] eq '')) 15257 { 15258 echo_error ("Need a node name for \@$macro", $line_nr); 15259 return ''; 15260 } 15261 if (@args > 3) 15262 { 15263 echo_warn ("Too much arguments for \@$macro", $line_nr); 15264 } 15265 $args[2] = '' if (!defined($args[2])); 15266 $args[1] = '' if (!defined($args[1])); 15267 $node_texi = "($args[2])$args[0]"; 15268 } 15269 15270 my $i; 15271 my $new_state = duplicate_state($state); 15272 $new_state->{'keep_texi'} = 0; 15273 $new_state->{'keep_nr'} = 0; 15274 for ($i = 0; $i < 5; $i++) 15275 { 15276 $args[$i] = substitute_line($args[$i], $new_state); 15277 } 15278 #print STDERR "(@args)\n"; 15279 15280 if (($macro eq 'inforef') or ($args[3] ne '') or ($args[4] ne '')) 15281 {# external ref 15282 if ($macro eq 'inforef') 15283 { 15284 $macro = 'xref'; 15285 $args[3] = $args[2]; 15286 } 15287 my $href = ''; 15288 my $node_file = ''; 15289 if ($args[3] ne '') 15290 { 15291 $href = do_external_href($node_texi); 15292 $node_file = "($args[3])$args[0]"; 15293 } 15294 my $section = ''; 15295 if ($args[4] ne '') 15296 { 15297 $section = $args[0]; 15298 if ($args[2] ne '') 15299 { 15300 $section = $args[2]; 15301 } 15302 } 15303 $result = &$Texi2HTML::Config::external_ref($macro, $section, $args[4], $node_file, $href, $args[1]); 15304 } 15305 else 15306 { 15307 my $element = $nodes{$node_texi}; 15308 if ($element and $element->{'seen'}) 15309 { 15310 if ($element->{'reference_element'}) 15311 { 15312 $element = $element->{'reference_element'}; 15313 } 15314 my $file = ''; 15315 if (defined($state->{'element'})) 15316 { 15317 $file = $state->{'element'}->{'file'}; 15318 } 15319 else 15320 { 15321 echo_warn ("\@$macro not in text (in anchor, node, section...)", $line_nr); 15322 # if Texi2HTML::Config::SPLIT the file is '' which ensures 15323 # a href with the file name. if ! Texi2HTML::Config::SPLIT 15324 # the 2 file will be the same thus there won't be the file name 15325 $file = $element->{'file'} unless ($Texi2HTML::Config::SPLIT); 15326 } 15327 #print STDERR "SUBHREF in ref to node `$node_texi': $_"; 15328 my $href = href($element, $file); 15329 my $section = $args[2]; 15330 $section = $args[1] if ($section eq ''); 15331 my $name = $section; 15332 my $short_name = $section; 15333 if ($section eq '') 15334 { 15335 # FIXME maybe one should use 'text' instead of 'text_nonumber' 15336 # However the real fix would be to have an internal_ref call 15337 # with more informations 15338 $name = $element->{'text_nonumber'}; 15339 $short_name = $args[0]; 15340 } 15341 $result = &$Texi2HTML::Config::internal_ref ($macro, $href, $short_name, $name, $element->{'section'}); 15342 } 15343 else 15344 { 15345 if (($node_texi eq '') or !$novalidate) 15346 { 15347 echo_error ("Undefined node `$node_texi' in \@$macro", $line_nr); 15348 my $text = ''; 15349 for (my $i = 0; $i < @$args -1; $i++) 15350 { 15351 $text .= $args->[$i] .','; 15352 } 15353 $text .= $args->[-1]; 15354 $result = "\@$macro"."{${text}}"; 15355 } 15356 else 15357 { 15358 $result = &$Texi2HTML::Config::external_ref($macro, '', '', $args[0], do_external_href($node_texi), $args[1]); 15359 } 15360 } 15361 } 15362 return $result; 15363} 15364 15365sub do_acronym_like($$$$$) 15366{ 15367 my $command = shift; 15368 my $args = shift; 15369 my $acronym_texi = shift @$args; 15370 my $explanation = shift @$args; 15371 my $style_stack = shift; 15372 my $state = shift; 15373 my $line_nr = shift; 15374 15375 my $explanation_lines; 15376 my $explanation_text; 15377 my $explanation_simple_format; 15378 15379 if (defined($explanation)) 15380 { 15381 $explanation =~ s/^\s*//; 15382 $explanation =~ s/\s*$//; 15383 $explanation = undef if ($explanation eq ''); 15384 } 15385 $acronym_texi =~ s/^\s*//; 15386 $acronym_texi =~ s/\s*$//; 15387 15388 return '' if ($acronym_texi eq ''); 15389 15390 my $with_explanation = 0; 15391 my $normalized_text = cross_manual_line(normalise_node($acronym_texi)); 15392 if (defined($explanation)) 15393 { 15394 $with_explanation = 1; 15395 $acronyms_like{$command}->{$normalized_text} = $explanation; 15396 } 15397 elsif (exists($acronyms_like{$command}->{$normalized_text})) 15398 { 15399 $explanation = $acronyms_like{$command}->{$normalized_text}; 15400 } 15401 15402 if (defined($explanation)) 15403 { 15404 @$explanation_lines = map {$_ = $_."\n"} split (/\n/, $explanation); 15405 my $text = ''; 15406 foreach my $line(@$explanation_lines) 15407 { 15408 $line .= ' ' if (chomp ($line)); 15409 $text .= $line 15410 } 15411 $text =~ s/ $//; 15412 my $simple_format_state = duplicate_state($state); 15413 $explanation_simple_format = simple_format($simple_format_state,$text); 15414 $explanation_text = substitute_line($text, duplicate_state($state)); 15415 } 15416 return &$Texi2HTML::Config::acronym_like($command, $acronym_texi, substitute_line($acronym_texi, duplicate_state($state)), 15417 $with_explanation, $explanation_lines, $explanation_text, $explanation_simple_format); 15418} 15419 15420sub do_caption_shortcaption($$$$$) 15421{ 15422 my $command = shift; 15423 my $args = shift; 15424 my $text = $args->[0]; 15425 my $style_stack = shift; 15426 my $state = shift; 15427 my $line_nr = shift; 15428 15429 if (!exists($state->{'float'})) 15430 { 15431#dump_stack(\"", [], $state); 15432 echo_error("\@$command outside of float", $line_nr); 15433 return ''; 15434 } 15435 my $float = $state->{'float'}; 15436 my @texi_lines = map {$_ = $_."\n"} split (/\n/, $text); 15437 $float->{"${command}_texi"} = \@texi_lines; 15438 return ''; 15439} 15440 15441# function called when a @float is encountered. Don't do any output 15442# but prepare $state->{'float'} 15443sub do_float_line($$$$$) 15444{ 15445 my $command = shift; 15446 my $args = shift; 15447 my @args = @$args; 15448 my $style_texi = shift @args; 15449 my $label_texi = shift @args; 15450 my $style_stack = shift; 15451 my $state = shift; 15452 my $line_nr = shift; 15453 15454 $style_texi = undef if (defined($style_texi) and $style_texi=~/^\s*$/); 15455 $label_texi = undef if (defined($label_texi) and $label_texi=~/^\s*$/); 15456 if (defined($label_texi)) 15457 { # the float is considered as a node as it may be a target for refs. 15458 # it was entered as a node in the pass_structure and the float 15459 # line was parsed at that time 15460 $state->{'float'} = $nodes{normalise_node($label_texi)}; 15461 #print STDERR "float: $state->{'float'}, $state->{'float'}->{'texi'}\n"; 15462 } 15463 else 15464 { # a float without label. It can't be the target for refs. 15465 $state->{'float'} = { 'float' => 1 }; 15466 if (defined($style_texi)) 15467 { 15468 $state->{'float'}->{'style_texi'} = normalise_space($style_texi); 15469 $state->{'float'}->{'style_id'} = 15470 cross_manual_line($state->{'float'}->{'style_texi'}); 15471 $state->{'float'}->{'style'} = substitute_line($style_texi); 15472 } 15473 #print STDERR "float: (no label) $state->{'float'}\n"; 15474 } 15475 return ''; 15476} 15477 15478sub do_quotation_line($$$$$) 15479{ 15480 my $command = shift; 15481 my $args = shift; 15482 my @args = @$args; 15483 my $text_texi = shift @args; 15484 my $style_stack = shift; 15485 my $state = shift; 15486 my $line_nr = shift; 15487 my $text; 15488 15489 $text_texi = undef if (defined($text_texi) and $text_texi=~/^\s*$/); 15490 if (defined($text_texi)) 15491 { 15492 $text = substitute_line($text_texi, duplicate_state($state)); 15493 $text =~ s/\s*$//; 15494 } 15495 my $quotation_args = { 'text' => $text, 'text_texi' => $text_texi }; 15496 push @{$state->{'quotation_stack'}}, $quotation_args; 15497 $state->{'prepend_text'} = &$Texi2HTML::Config::quotation_prepend_text($text_texi); 15498 return ''; 15499} 15500 15501sub do_def_line($$$$$) 15502{ 15503 my $command = shift; 15504 my $args = shift; 15505 my @args = @$args; 15506 my $arguments = shift @args; 15507 my $style_stack = shift; 15508 my $state = shift; 15509 my $line_nr = shift; 15510 15511 $state->{'deff_line'}->{'arguments'} = $arguments; 15512 return ''; 15513} 15514 15515sub do_footnote($$$$) 15516{ 15517 my $command = shift; 15518 my $args = shift; 15519 my $text = $args->[0]; 15520 my $style_stack = shift; 15521 my $state = shift; 15522 my $line_nr = shift; 15523 15524 $text .= "\n"; 15525 $foot_num++; 15526 $relative_foot_num++; 15527 my $docid = "DOCF$foot_num"; 15528 my $footid = "FOOT$foot_num"; 15529 my $from_file = ''; 15530 if ($state->{'element'} and $Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SEPARATED_FOOTNOTES) 15531 { 15532 $from_file = $state->{'element'}->{'file'}; 15533 } 15534 my %state; 15535 initialise_state(\%state); 15536 if ($Texi2HTML::Config::SEPARATED_FOOTNOTES) 15537 { 15538 $state{'element'} = $footnote_element; 15539 } 15540 else 15541 { 15542 $state{'element'} = $state->{'element'}; 15543 } 15544 my $file = ''; 15545 $file = $docu_foot if ($Texi2HTML::Config::SPLIT and $Texi2HTML::Config::SEPARATED_FOOTNOTES); 15546 15547 # FIXME use split_lines ? It seems to work like it is now ? 15548 my @lines = substitute_text(\%state, map {$_ = $_."\n"} split (/\n/, $text)); 15549 my ($foot_lines, $foot_label) = &$Texi2HTML::Config::foot_line_and_ref ($foot_num, 15550 $relative_foot_num, $footid, $docid, $from_file, $file, \@lines, $state); 15551 push(@foot_lines, @{$foot_lines}); 15552 return $foot_label; 15553} 15554 15555sub do_image($$$$) 15556{ 15557 # replace images 15558 my $command = shift; 15559 my $args = shift; 15560 my $text = $args->[0]; 15561 my $style_stack = shift; 15562 my $state = shift; 15563 my $line_nr = shift; 15564 $text =~ s/\s+/ /gos; # remove useless spaces and newlines 15565 my @args = split (/\s*,\s*/, $text); 15566 my $base = $args[0]; 15567 if ($base eq '') 15568 { 15569 echo_error ("no file argument for \@image", $line_nr); 15570 #warn "$ERROR no file argument for \@image\n"; 15571 return ''; 15572 } 15573 $args[4] = '' if (!defined($args[4])); 15574 $args[3] = '' if (!defined($args[3])); 15575 my $image; 15576 my $file_name; 15577 my @file_names = &$Texi2HTML::Config::image_files($base,$args[4]); 15578# $image = locate_include_file("$base.$args[4]") if ($args[4] ne ''); 15579 foreach my $file (@file_names) 15580 { 15581 if ($image = locate_include_file($file)) 15582 { 15583 $file_name = $file; 15584 last; 15585 } 15586 } 15587 $image = '' if (!defined($image)); 15588 15589 my $alt; 15590 if ($args[3] =~ /\S/) 15591 { 15592 # makeinfo don't do that. Maybe it should be remove_texi or 15593 # simple_format... The raw alt is also given in argument 15594 $alt = do_text($args[3]); 15595 $alt = $alt if ($alt =~ /\S/); 15596 } 15597 return &$Texi2HTML::Config::image($path_to_working_dir . $image, $base, 15598 $state->{'preformatted'}, $file_name, $alt, $args[1], $args[2], 15599 $args[3], $args[4], $path_to_working_dir, $image); 15600} 15601 15602sub duplicate_state($) 15603{ 15604 my $state = shift; 15605 my $new_state = { 'element' => $state->{'element'}, 15606 'preformatted' => $state->{'preformatted'}, 15607 'code_style' => $state->{'code_style'}, 15608 'keep_texi' => $state->{'keep_texi'}, 15609 'keep_nr' => $state->{'keep_nr'}, 15610 'preformatted_stack' => $state->{'preformatted_stack'}, 15611 'multiple_pass' => $state->{'multiple_pass'}, 15612# this is needed for preformatted 15613 'command_stack' => [ @{$state->{'command_stack'}} ], 15614 'preformatted_context' => 15615 {'stack_at_beginning' => [ @{$state->{'command_stack'}} ] } 15616 }; 15617 return $new_state; 15618} 15619 15620sub expand_macro($$$$$) 15621{ 15622 my $name = shift; 15623 my $args = shift; 15624 my $end_line = shift; 15625 my $line_nr = shift; 15626 my $state = shift; 15627 15628 # we dont expand macros when in ignored environment. 15629 return if ($state->{'ignored'}); 15630 my $index = 0; 15631 foreach my $arg (@$args) 15632 { # expand @macros in arguments. It is complicated because we must be 15633 # carefull not to expand macros in @ignore section or the like, and 15634 # still keep every single piece of text (including the @ignore macros). 15635 $args->[$index] = substitute_text({'texi' => 1, 'arg_expansion' => 1}, split_lines($arg)); 15636 $index++; 15637 } 15638 # retrieve the macro definition 15639 my $macrobody = $macros->{$name}->{'body'}; 15640 my $formal_args = $macros->{$name}->{'args'}; 15641 my $args_index = $macros->{$name}->{'args_index'}; 15642 my $i; 15643 15644 die "Bug end_line not defined" if (!defined($end_line)); 15645 15646 for ($i=0; $i<=$#$formal_args; $i++) 15647 { 15648 $args->[$i] = "" unless (defined($args->[$i])); 15649 print STDERR "# arg($i): $args->[$i]\n" if ($T2H_DEBUG & $DEBUG_MACROS); 15650 } 15651 echo_error ("too much arguments for macro $name", $line_nr) if (defined($args->[$i + 1])); 15652 my $result = ''; 15653 while ($macrobody) 15654 { 15655 if ($macrobody =~ s/^([^\\]*)\\//o) 15656 { 15657 $result .= $1 if defined($1); 15658 if ($macrobody =~ s/^\\//) 15659 { 15660 $result .= '\\'; 15661 } 15662 elsif ($macrobody =~ s/^(\@end\sr?macro)$// or $macrobody =~ s/^(\@end\sr?macro\s)// or $macrobody =~ s/^(\@r?macro\s+\w+\s*.*)//) 15663 { # \ protect @end macro 15664 $result .= $1; 15665 } 15666 elsif ($macrobody =~ s/^([^\\]*)\\//) 15667 { 15668 my $arg = $1; 15669 if (defined($args_index->{$arg})) 15670 { 15671 $result .= $args->[$args_index->{$arg}]; 15672 } 15673 else 15674 { 15675 warn "$ERROR \\ not followed by \\ or an arg but by $arg in macro\n"; 15676 $result .= '\\' . $arg; 15677 } 15678 } 15679 next; 15680 } 15681 $result .= $macrobody; 15682 last; 15683 } 15684 my @result = split(/^/m, $result); 15685 # Add the result of the macro expansion back to the input_spool. 15686 # Set the macro name if in the outer macro 15687 if ($state->{'arg_expansion'}) 15688 { 15689 unshift @{$state->{'spool'}}, (@result, $end_line); 15690 } 15691 else 15692 { 15693 unshift @{$input_spool->{'spool'}}, (@result, $end_line); 15694 $input_spool->{'macro'} = $name if ($input_spool->{'macro'} eq ''); 15695 } 15696 if ($T2H_DEBUG & $DEBUG_MACROS) 15697 { 15698 print STDERR "# macro expansion result:\n"; 15699 #print STDERR "$first_line"; 15700 foreach my $line (@result) 15701 { 15702 print STDERR "$line"; 15703 } 15704 print STDERR "# macro expansion result end\n"; 15705 } 15706} 15707 15708sub do_index_summary_file($) 15709{ 15710 my $name = shift; 15711 my ($pages, $entries) = get_index($name); 15712 &$Texi2HTML::Config::index_summary_file_begin ($name, $printed_indices{$name}); 15713 print STDERR "# writing $name index summary\n" if $T2H_VERBOSE; 15714 15715 foreach my $key (sort keys %$entries) 15716 { 15717 my $entry = $entries->{$key}; 15718 my $indexed_element = $entry->{'element'}; 15719 my $entry_element = $indexed_element; 15720 # notice that we use the section associated with a node even when 15721 # there is no with_section, i.e. when there is another node preceding 15722 # the sectionning command. 15723 # However when it is the Top node, we use the node instead. 15724 # (for the Top node, 'top_as_section' is true) 15725 $entry_element = $entry_element->{'section_ref'} if ($entry_element->{'section_ref'} and !$entry_element->{'top_as_section'}); 15726 my $origin_href = $entry->{'file'}; 15727 #print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n"; 15728 if ($entry->{'label'}) 15729 { 15730 $origin_href .= '#' . $entry->{'label'}; 15731 } 15732 else 15733 { 15734 # If the $indexed_element element and the $index entry are on 15735 # the same 15736 # file the real element is prefered. If they aren't on the same file 15737 # the entry id is choosed as it means that the real element 15738 # and the index entry are separated by a printindex. 15739 print STDERR "id undef ($entry) entry: $entry->{'entry'}, label: $indexed_element->{'text'}\n" if (!defined($entry->{'id'})); 15740 if ($entry->{'file'} eq $indexed_element->{'file'}) 15741 { 15742 $origin_href .= '#' . $indexed_element->{'id'}; 15743 } 15744 else 15745 { 15746 $origin_href .= '#' . $entry->{'id'} ; 15747 } 15748 } 15749 &$Texi2HTML::Config::index_summary_file_entry ($name, 15750 $key, $origin_href, 15751 substitute_line($entry->{'entry'}), $entry->{'entry'}, 15752 href($entry_element, ''), 15753 $entry_element->{'text'}, 15754 $printed_indices{$name}); 15755 } 15756 &$Texi2HTML::Config::index_summary_file_end ($name, $printed_indices{$name}); 15757} 15758 15759sub do_index_page($$;$) 15760{ 15761 my $index_elements = shift; 15762 my $nr = shift; 15763 my $page = shift; 15764 my $index_element = $index_elements->[$nr]; 15765 my $summary = do_index_summary($index_element->{'element'}, $index_elements); 15766 my $entries = do_index_entries($index_element->{'element'}, $index_element->{'page'}, $index_element->{'name'}); 15767 return $summary . $entries . $summary; 15768} 15769 15770sub do_index_summary($$) 15771{ 15772 my $element = shift; 15773 my $index_elements = shift; 15774 15775 my @letters; 15776 my @symbols; 15777 15778 for my $index_element_item (@$index_elements) 15779 { 15780 my $index_element = $index_element_item->{'element'}; 15781 my $file = ''; 15782 $file .= $index_element->{'file'} if ($index_element->{'file'} ne $element->{'file'}); 15783 my $index = 0; 15784 for my $letter (@{$index_element_item->{'page'}->{'letters'}}) 15785 { 15786 if ($letter =~ /^[A-Za-z]/) 15787 { 15788 push @letters, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index"); 15789 } 15790 else 15791 { 15792 push @symbols, &$Texi2HTML::Config::summary_letter($letter, $file, "$index_element->{'id'}" . "_$index"); 15793 } 15794 $index++; 15795 } 15796 } 15797 return &$Texi2HTML::Config::index_summary(\@letters, \@symbols); 15798} 15799 15800sub do_index_entries($$$) 15801{ 15802 my $element = shift; 15803 my $page = shift; 15804 my $name = shift; 15805 15806 my $letters = ''; 15807 my $index = 0; 15808 foreach my $letter (@{$page->{'letters'}}) 15809 { 15810 my $entries = ''; 15811 foreach my $entry (@{$page->{'entries_by_letter'}->{$letter}}) 15812 { 15813 my $indexed_element = $entry->{'element'}; 15814 my $entry_element = $indexed_element; 15815 # notice that we use the section associated with a node even when 15816 # there is no with_section, i.e. when there is another node preceding 15817 # the sectionning command. 15818 # However when it is the Top node, we use the node instead. 15819 # (for the Top node, 'top_as_section' is true) 15820 $entry_element = $entry_element->{'section_ref'} if ($entry_element->{'section_ref'} and !$entry_element->{'top_as_section'}); 15821 my $origin_href = ''; 15822 $origin_href = $entry->{'file'} if ($Texi2HTML::Config::SPLIT and $entry->{'file'} ne $element->{'file'}); 15823 #print STDERR "$entry $entry->{'entry'}, real elem $indexed_element->{'texi'}, section $entry_element->{'texi'}, real $indexed_element->{'file'}, entry file $entry->{'file'}\n"; 15824 if ($entry->{'label'}) 15825 { 15826 $origin_href .= '#' . $entry->{'label'}; 15827 } 15828 else 15829 { 15830 # If the $indexed_element element and the $index entry are 15831 # in the same file the indexed_element is prefered. If they 15832 # aren't in the same file the entry id is choosed as it means 15833 # that the indexed_element element and the index entry are 15834 # separated by a printindex. 15835 print STDERR "id undef ($entry) entry: $entry->{'entry'}, label: $indexed_element->{'text'}\n" if (!defined($entry->{'id'})); 15836 if ($entry->{'file'} eq $indexed_element->{'file'}) 15837 { 15838 $origin_href .= '#' . $indexed_element->{'id'}; 15839 } 15840 else 15841 { 15842 $origin_href .= '#' . $entry->{'id'} ; 15843 } 15844 } 15845 #print STDERR "SUBHREF in index entry `$entry->{'entry'}' for `$entry_element->{'texi'}'\n"; 15846 $entries .= &$Texi2HTML::Config::index_entry ($origin_href, 15847 substitute_line($entry->{'entry'}), 15848 href($entry_element, $element->{'file'}), 15849 $entry_element->{'text'}); 15850 } 15851 $letters .= &$Texi2HTML::Config::index_letter ($letter, "$element->{'id'}" . "_$index", $entries); 15852 $index++; 15853 } 15854 return &$Texi2HTML::Config::print_index($letters, $name); 15855} 15856 15857# remove texi commands, replacing with what seems adequate. see simple_map_texi 15858# and texi_map. 15859# Doesn't protect html 15860sub remove_texi(@) 15861{ 15862 return substitute_text ({ 'remove_texi' => 1}, @_); 15863} 15864 15865# Same as remove texi but protect text and use special maps for @-commands 15866sub simple_format($@) 15867{ 15868 my $state = shift; 15869 $state = {} if (!defined($state)); 15870 $state->{'remove_texi'} = 1; 15871 $state->{'simple_format'} = 1; 15872 # WARNING currently it is only used for lines. It may change in the future. 15873 $state->{'no_paragraph'} = 1; 15874 $::simple_map_texi_ref = \%Texi2HTML::Config::simple_format_simple_map_texi; 15875 $::style_map_texi_ref = \%Texi2HTML::Config::simple_format_style_map_texi; 15876 $::texi_map_ref = \%Texi2HTML::Config::simple_format_texi_map; 15877 my $text = substitute_text($state, @_); 15878 $::simple_map_texi_ref = \%Texi2HTML::Config::simple_map_texi; 15879 $::style_map_texi_ref = \%Texi2HTML::Config::style_map_texi; 15880 $::texi_map_ref = \%Texi2HTML::Config::texi_map; 15881 return $text; 15882} 15883 15884sub enter_table_index_entry($$$$) 15885{ 15886 my $text = shift; 15887 my $stack = shift; 15888 my $state = shift; 15889 my $line_nr = shift; 15890 if ($state->{'item'} and ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/)) 15891 { 15892 my $index = $1; 15893 my $macro = $state->{'item'}; 15894 delete $state->{'item'}; 15895 close_stack($text, $stack, $state, $line_nr, undef, 'index_item'); 15896 my $item = pop @$stack; 15897 my $element = $state->{'element'}; 15898 $element = $state->{'node_ref'} unless ($element); 15899 enter_index_entry($index, $line_nr, $item->{'text'}, 15900 $state->{'place'}, $element, 0, $state->{'table_stack'}->[-1]); 15901 add_prev($text, $stack, "\@$macro" . $item->{'text'}); 15902 } 15903} 15904 15905sub scan_texi($$$$;$) 15906{ 15907 my $line = shift; 15908 my $text = shift; 15909 my $stack = shift; 15910 my $state = shift; 15911 my $line_nr = shift; 15912 15913 die "stack not an array ref" unless (ref($stack) eq "ARRAY"); 15914 local $_ = $line; 15915 15916 while(1) 15917 { 15918 # scan_texi 15919 #print STDERR "WHILE:$_"; 15920 #print STDERR "ARG_EXPANSION: $state->{'arg_expansion'}\n" if ($state->{'arg_expansion'}); 15921 #dump_stack($text, $stack, $state); 15922 #print STDERR "ifvalue_inside $state->{'ifvalue_inside'}\n"; 15923 15924 15925 # first we handle special cases: 15926 # macro definition: $state->{'macro_inside'} 15927 # macro arguments: $state->{'macro_name'} 15928 # raw format: $state->{'raw'} 15929 # @verb: $state->{'verb'} 15930 # ignored: $state->{'ignored'} 15931 # and then the remaining text/macros. 15932 15933 # in macro definition 15934 if ($state->{'macro_inside'}) 15935 { 15936 if (s/^([^\\\@]*\\)//) 15937 {# protected character or @end macro 15938 $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'}); 15939 if (s/^\\//) 15940 { 15941 $state->{'macro'}->{'body'} .= '\\' unless ($state->{'ignored'}); 15942 next; 15943 } 15944 # I believe it is correct, although makeinfo don't do that. 15945 elsif (s/^(\@end\sr?macro)$//o or s/^(\@end\sr?macro\s)//o 15946 or s/^(\@r?macro\s+\w+\s*.*)//o) 15947 { 15948 $state->{'macro'}->{'body'} .= $1 unless ($state->{'ignored'}); 15949 next; 15950 } 15951 } 15952 #if (s/^(.*?)\@end\sr?macro$//o or s/^(.*?)\@end\sr?macro\s+//o) 15953 if (s/^(\@end\sr?macro)$//o or s/^(\@end\sr?macro\s+)//o) 15954 { 15955 $state->{'macro_inside'}--; 15956 next if ($state->{'ignored'}); 15957 if ($state->{'macro_inside'}) 15958 { 15959 $state->{'macro'}->{'body'} .= $1; 15960 next; 15961 } 15962 chomp $state->{'macro'}->{'body'}; 15963 print STDERR "# end macro def. Body:\n$state->{'macro'}->{'body'}" 15964 if ($T2H_DEBUG & $DEBUG_MACROS); 15965 delete $state->{'macro'}; 15966 return if (/^\s*$/); 15967 next; 15968 } 15969 elsif(/^(\@r?macro\s+\w+\s*.*)/) 15970 { 15971 $state->{'macro'}->{'body'} .= $_ unless ($state->{'ignored'}); 15972 $state->{'macro_inside'}++; 15973 return; 15974 } 15975 elsif (s/^\@(.)//) 15976 { 15977 $state->{'macro'}->{'body'} .= '@' . $1 unless ($state->{'ignored'}); 15978 next; 15979 } 15980 elsif (s/^\@//) 15981 { 15982 $state->{'macro'}->{'body'} .= '@' unless ($state->{'ignored'}); 15983 next; 15984 } 15985 else 15986 { 15987 s/([^\@\\]*)//; 15988 if ($state->{'ignored'}) 15989 { 15990 return if (/^$/); 15991 next; 15992 } 15993 $state->{'macro'}->{'body'} .= $1 if (defined($1)); 15994 if (/^$/) 15995 { 15996 $state->{'macro'}->{'body'} .= $_; 15997 return; 15998 } 15999 next; 16000 } 16001 } 16002 # in macro arguments parsing/expansion. Here \ { } and , if this is a 16003 # multi args macro have a signification, the remaining is passed 16004 # unmodified 16005 if (defined($state->{'macro_name'})) 16006 { 16007 my $special_chars = quotemeta ('\{}'); 16008 my $multi_args = 0; 16009 my $formal_args = $macros->{$state->{'macro_name'}}->{'args'}; 16010 $multi_args = 1 if ($#$formal_args >= 1); 16011 $special_chars .= quotemeta(',') if ($multi_args); 16012 if ($state->{'macro_args'}->[-1] eq '') 16013 {# remove space at the very beginning 16014 s/^\s*//o; 16015 } 16016 if (s/^([^$special_chars]*)([$special_chars])//) 16017 { 16018 $state->{'macro_args'}->[-1] .= $1 if defined($1); 16019 # \ protects any character in macro arguments 16020 if ($2 eq '\\') 16021 { 16022 print STDERR "# macro call: protected char\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16023 if (s/^(.)//) 16024 { 16025 $state->{'macro_args'}->[-1] .= $1; 16026 } 16027 else 16028 { 16029 $state->{'macro_args'}->[-1] .= '\\'; 16030 } 16031 } 16032 elsif ($2 eq ',') 16033 { # in texinfo 4.8.90 a comma in braces is protected 16034 if ($state->{'macro_depth'} > 1) 16035 { 16036 $state->{'macro_args'}->[-1] .= ','; 16037 } 16038 else 16039 { # separate args 16040 print STDERR "# macro call: new arg\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16041 s/^\s*//o; 16042 push @{$state->{'macro_args'}}, ''; 16043 } 16044 } 16045 elsif ($2 eq '}') 16046 { # balanced } ends the macro call, otherwise it is in the arg 16047 $state->{'macro_depth'}--; 16048 if ($state->{'macro_depth'} == 0) 16049 { 16050 print STDERR "# expanding macro $state->{'macro_name'}\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16051 $_ = expand_macro($state->{'macro_name'}, $state->{'macro_args'}, $_, $line_nr, $state); 16052 delete $state->{'macro_name'}; 16053 delete $state->{'macro_depth'}; 16054 delete $state->{'macro_args'}; 16055 return; 16056 } 16057 else 16058 { 16059 print STDERR "# macro call: closing }\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16060 add_text('}', \$state->{'macro_args'}->[-1]); 16061 } 16062 } 16063 elsif ($2 eq '{') 16064 { 16065 print STDERR "# macro call: opening {\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16066 $state->{'macro_depth'}++; 16067 add_text('{', \$state->{'macro_args'}->[-1]); 16068 } 16069 next; 16070 } 16071 print STDERR "# macro call: end of line\n" if ($T2H_DEBUG & $DEBUG_MACROS); 16072 $state->{'macro_args'}->[-1] .= $_; 16073 return; 16074 } 16075 # in a raw format, verbatim, tex or html 16076 if ($state->{'raw'}) 16077 { 16078 my $tag = $state->{'raw'}; 16079 16080 # debugging 16081 if (! @$stack or ($stack->[-1]->{'style'} ne $tag)) 16082 { 16083 print STDERR "Bug: raw or special: $tag but not on top of stack\n"; 16084 print STDERR "line: $_"; 16085 dump_stack($text, $stack, $state); 16086 exit 1; 16087 } 16088 16089 if (s/^(.*?)(\@end\s$tag)$// or s/^(.*?)(\@end\s$tag\s)//) 16090 {# we add it even if 'ignored', it'll be discarded when there is 16091 # the @end 16092 add_prev ($text, $stack, $1); 16093 my $end = $2; 16094 my $style = pop @$stack; 16095 if ($style->{'text'} !~ /^\s*$/ or $state->{'arg_expansion'}) 16096 # FIXME if 'arg_expansion' and also 'ignored' is true, 16097 # theoretically we should keep 16098 # what is in the raw format however 16099 # it will be removed later anyway 16100 {# ARG_EXPANSION 16101 my $after_macro = ''; 16102 $after_macro = ' ' unless (/^\s*$/); 16103 add_prev ($text, $stack, $style->{'text'} . $end . $after_macro) unless ($state->{'ignored'}); 16104 delete $state->{'raw'}; 16105 } 16106 next; 16107 } 16108 else 16109 {# we add it even if 'ignored', it'll be discarded when there is 16110 # the @end 16111 add_prev ($text, $stack, $_); 16112 last; 16113 } 16114 } 16115 16116 # in a @verb{ .. } macro 16117 if (defined($state->{'verb'})) 16118 { 16119 #dump_stack($text, $stack, $state); 16120 my $char = quotemeta($state->{'verb'}); 16121 #print STDERR "VERB $char\n"; 16122 if (s/^(.*?)$char\}/\}/) 16123 {# we add it even if 'ignored', it'll be discarded when closing 16124 add_prev($text, $stack, $1 . $state->{'verb'}); 16125 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; 16126 delete $state->{'verb'}; 16127 next; 16128 } 16129 else 16130 {# we add it even if 'ignored', it'll be discarded when closing 16131 add_prev($text, $stack, $_); 16132 last; 16133 } 16134 } 16135 # In ignored region 16136 if ($state->{'ignored'}) 16137 { 16138 #print STDERR "IGNORED(ifvalue($state->{'ifvalue_inside'})): $state->{'ignored'}\n"; 16139 if (/^.*?\@end(\s+)([a-zA-Z]\w+)/) 16140 { 16141 if ($2 eq $state->{'ignored'}) 16142 { 16143 s/^(.*?\@end)(\s+)([a-zA-Z]\w+)//; 16144 my $end_ignore = $1.$2.$3; 16145 if (($state->{'ifvalue_inside'}) and $state->{'ignored'} eq $state->{'ifvalue'}) 16146 { 16147 if ($state->{'ifvalue_inside'} == 1) 16148 {# closing still opened @-commands with braces 16149 pop (@$stack) while (@$stack and $stack->[-1]->{'style'} ne 'ifvalue') 16150 } 16151 pop (@$stack); 16152 $state->{'ifvalue_inside'}--; 16153 } 16154 $state->{'ignored'} = undef; 16155 delete $state->{'ignored'}; 16156 # We are stil in the ignored ifset or ifclear section 16157 $state->{'ignored'} = $state->{'ifvalue'} if ($state->{'ifvalue_inside'}); 16158 #dump_stack($text, $stack, $state); 16159 # MACRO_ARG => keep ignored text 16160 if ($state->{'arg_expansion'}) 16161 {# this may not be very usefull as it'll be remove later 16162 add_prev ($text, $stack, $end_ignore); 16163 next; 16164 } 16165 return if /^\s*$/o; 16166 next; 16167 } 16168 } 16169 add_prev ($text, $stack, $_) if ($state->{'arg_expansion'}); 16170 # we could theoretically continue for ignored commands other 16171 # than ifset or ifclear, however it isn't usefull. 16172 return unless ($state->{'ifvalue_inside'} and ($state->{'ignored'} eq $state->{'ifvalue'})); 16173 } 16174 16175 16176 # an @end tag 16177 # macro_regexp 16178 if (s/^([^{}@]*)\@end(\s+)([a-zA-Z][\w-]*)//) 16179 { 16180 my $leading_text = $1; 16181 my $space = $2; 16182 my $end_tag = $3; 16183 # when 'ignored' we don't open environments that aren't associated 16184 # with ignored regions, so we don't need to close them. 16185 next if ($state->{'ignored'});# ARG_EXPANSION 16186 add_prev($text, $stack, $leading_text); 16187 if (defined($state->{'text_macro_stack'}) 16188 and @{$state->{'text_macro_stack'}} 16189 and ($end_tag eq $state->{'text_macro_stack'}->[-1])) 16190 { 16191 pop @{$state->{'text_macro_stack'}}; 16192 # we keep menu and titlepage for the following pass 16193 if ((($end_tag eq 'menu') and $text_macros{'menu'}) or ($region_lines{$end_tag}) or $state->{'arg_expansion'}) 16194 { 16195 add_prev($text, $stack, "\@end${space}$end_tag"); 16196 } 16197 else 16198 { 16199 #print STDERR "End $end_tag\n"; 16200 #dump_stack($text, $stack, $state); 16201 return if (/^\s*$/); 16202 } 16203 } 16204 elsif ($text_macros{$end_tag}) 16205 { 16206 echo_error ("\@end $end_tag without corresponding element", $line_nr); 16207 } 16208 else 16209 {# ARG_EXPANSION 16210 add_prev($text, $stack, "\@end${space}$end_tag"); 16211 } 16212 next; 16213 } 16214 # macro_regexp 16215 elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o) 16216 {# ARG_EXPANSION 16217 add_prev($text, $stack, $1) unless $state->{'ignored'}; 16218 my $macro = $2; 16219 #print STDERR "MACRO $macro\n"; 16220 # handle skipped @-commands 16221 $state->{'bye'} = 1 if ($macro eq 'bye' and !$state->{'ignored'} and !$state->{'arg_expansion'}); 16222 if (defined($Texi2HTML::Config::misc_command{$macro}) and 16223 !$Texi2HTML::Config::misc_command{$macro}->{'texi'} 16224 and $macro ne 'documentencoding') 16225 {# ARG_EXPANSION 16226 my ($line, $args); 16227 ($_, $line, $args) = preserve_command($_, $macro); 16228 add_prev ($text, $stack, "\@$macro" . $line) unless $state->{'ignored'}; 16229 } 16230 # pertusus: it seems that value substitution are performed after 16231 # macro argument expansions: if we have 16232 # @set comma , 16233 # and a call to a macro @macro {arg1 @value{comma} arg2} 16234 # the macro arg is arg1 , arg2 and the comma don't separate 16235 # args. Likewise it seems that the @value are not expanded 16236 # in macro definitions 16237 16238 # track variables 16239 elsif($macro eq 'set' or $macro eq 'clear') 16240 { 16241 if ($macro eq 'set') 16242 { 16243 if (s/^(\s+)($VARRE)(\s+)(.*)$//o) 16244 { 16245 if ($state->{'arg_expansion'}) 16246 { 16247 my $line = "\@$macro" . $1.$2.$3; 16248 $line .= $4 if (defined($4)); 16249 add_prev($text, $stack, $line); 16250 next; 16251 } 16252 next if $state->{'ignored'}; 16253 $value{$2} = $4; 16254 } 16255 else 16256 { 16257 echo_warn ("Missing argument for \@$macro", $line_nr); 16258 } 16259 } 16260 elsif ($macro eq 'clear') 16261 { 16262 if (s/^(\s+)($VARRE)//o) 16263 { 16264 if ($state->{'arg_expansion'}) 16265 { 16266 add_prev($text, $stack, "\@$macro" . $1 . $2); 16267 next; 16268 } 16269 next if $state->{'ignored'}; 16270 delete $value{$2}; 16271 } 16272 else 16273 { 16274 echo_warn ("Missing argument for \@$macro", $line_nr); 16275 } 16276 } 16277 return if (/^\s*$/); 16278 } 16279 elsif ($macro =~ /^r?macro$/) 16280 { #FIXME what to do if 'arg_expansion' is true (ie within another 16281 # macro call arguments? 16282 if (/^\s+(\w[\w-]*)\s*(.*)/) 16283 { 16284 my $name = $1; 16285 unless ($state->{'ignored'}) 16286 { 16287 if (exists($macros->{$name})) 16288 { 16289 echo_warn ("macro `$name' allready defined " . 16290 format_line_number($macros->{$name}->{'line_nr'}) . " redefined", $line_nr); 16291 } 16292 16293 } 16294 $state->{'macro_inside'} = 1; 16295 next if ($state->{'ignored'}); 16296 # if in 'arg_expansion' we really want to take into account 16297 # that we are in an ignored ifclear. 16298 my @args = (); 16299 @args = split(/\s*,\s*/ , $1) 16300 if ($2 =~ /^\s*{\s*(.*?)\s*}\s*/); 16301 # keep the context information of the definition 16302 $macros->{$name}->{'line_nr'} = { 'file_name' => $line_nr->{'file_name'}, 16303 'line_nr' => $line_nr->{'line_nr'}, 'macro' => $line_nr->{'macro'} } if (defined($line_nr)); 16304 $macros->{$name}->{'args'} = \@args; 16305 my $arg_index = 0; 16306 my $debug_msg = ''; 16307 foreach my $arg (@args) 16308 { # when expanding macros, the argument index is retrieved 16309 # with args_index 16310 $macros->{$name}->{'args_index'}->{$arg} = $arg_index; 16311 $debug_msg .= "$arg($arg_index) "; 16312 $arg_index++; 16313 } 16314 $macros->{$name}->{'body'} = ''; 16315 $state->{'macro'} = $macros->{$name}; 16316 print STDERR "# macro def $name: $debug_msg\n" 16317 if ($T2H_DEBUG & $DEBUG_MACROS); 16318 } 16319 else 16320 {# it means we have a macro without a name 16321 echo_error ("Macro definition without macro name $_", $line_nr) 16322 unless ($state->{'ignored'}); 16323 } 16324 return; 16325 } 16326 elsif (defined($text_macros{$macro})) 16327 { 16328 my $tag; 16329 ($_, $tag) = do_text_macro($macro, $_, $state, $stack, $line_nr); 16330 # if it is a raw formatting command or a menu command 16331 # we must keep it for later, unless we are in an 'ignored'. 16332 # if in 'arg_expansion' we keep everything. 16333 my $macro_kept; 16334 if ((($state->{'raw'} or (($macro eq 'menu') and $text_macros{'menu'}) or (exists($region_lines{$macro}))) and !$state->{'ignored'}) or $state->{'arg_expansion'}) 16335 { 16336 add_prev($text, $stack, $tag); 16337 $macro_kept = 1; 16338 } 16339 #dump_stack ($text, $stack, $state); 16340 next if $macro_kept; 16341 return if (/^\s*$/); 16342 } 16343 elsif ($macro eq 'documentencoding') 16344 { 16345 my $spaces = ''; 16346 my $encoding = ''; 16347 if (s/(\s+)([0-9\w\-]+)//) 16348 { 16349 $spaces = $1; 16350 $encoding = $2; 16351 next if ($state->{'ignored'}); 16352 if (!$state->{'arg_expansion'} and !$state->{'ignored'}) 16353 { 16354 $Texi2HTML::Config::DOCUMENT_ENCODING = $encoding; 16355 my $from_encoding = encoding_alias($encoding); 16356 $Texi2HTML::Config::IN_ENCODING = $from_encoding if 16357 defined($from_encoding); 16358 if (defined($from_encoding) and $Texi2HTML::Config::USE_UNICODE) 16359 { 16360 foreach my $file (@fhs) 16361 { 16362 binmode($file->{'fh'}, ":encoding($from_encoding)"); 16363 } 16364 } 16365 } 16366 }# ARG_EXPANSION 16367 add_prev($text, $stack, "\@$macro" . $spaces . $encoding) unless ($state->{'ignored'}); 16368 } 16369 elsif ($macro eq 'definfoenclose') 16370 { 16371 # FIXME if 'ignored' or 'arg_expansion' maybe we could parse 16372 # the args anyway and don't take away the whole line? 16373 16374 # as in the makeinfo doc 'definfoenclose' may override 16375 # texinfo @-commands like @i. It is what we do here. 16376 if ($state->{'arg_expansion'}) 16377 { 16378 add_prev($text, $stack, "\@$macro" . $_); 16379 return; 16380 } 16381 return if ($state->{'ignored'}); 16382 if (s/^\s+([a-z]+)\s*,\s*([^\s]+)\s*,\s*([^\s]+)//) 16383 { 16384 $info_enclose{$1} = [ $2, $3 ]; 16385 } 16386 else 16387 { 16388 echo_error("Bad \@$macro", $line_nr); 16389 } 16390 return if (/^\s*$/); 16391 s/^\s*//; 16392 } 16393 elsif ($macro eq 'include') 16394 { 16395 if ($state->{'arg_expansion'}) 16396 { 16397 add_prev($text, $stack, "\@$macro" . $_); 16398 return; 16399 } 16400 return if ($state->{'ignored'}); 16401 #if (s/^\s+([\/\w.+-]+)//o) 16402 if (s/^(\s+)(.*)//o) 16403 { 16404 my $file_name = $2; 16405 $file_name =~ s/\s*$//; 16406 my $file = locate_include_file($file_name); 16407 if (defined($file)) 16408 { 16409 open_file($file, $line_nr); 16410 print STDERR "# including $file\n" if $T2H_VERBOSE; 16411 } 16412 else 16413 { 16414 echo_error ("Can't find $file_name, skipping", $line_nr); 16415 } 16416 } 16417 else 16418 { 16419 echo_error ("Bad include line: $_", $line_nr); 16420 return; 16421 } 16422 return; 16423 } 16424 elsif ($macro eq 'value') 16425 { 16426 if (s/^{($VARRE)}//) 16427 { 16428 my $value = $1; 16429 if ($state->{'arg_expansion'}) 16430 { 16431 add_prev($text, $stack, "\@$macro" .'{'. $value .'}'); 16432 next; 16433 } 16434 next if ($state->{'ignored'}); 16435 my $expansion = "No value for $value"; 16436 $expansion = $value{$value} if (defined($value{$value})); 16437 $_ = $expansion . $_; 16438 } 16439 else 16440 { 16441 if ($state->{'arg_expansion'}) 16442 { 16443 add_prev($text, $stack, "\@$macro"); 16444 next; 16445 } 16446 next if ($state->{'ignored'}); 16447 echo_error ("bad \@value macro", $line_nr); 16448 } 16449 } 16450 elsif ($macro eq 'unmacro') 16451 { #FIXME with 'arg_expansion' should it be passed unmodified ? 16452 if ($state->{'ignored'}) 16453 { 16454 s/^\s+(\w+)//; 16455 } 16456 else 16457 { 16458 delete $macros->{$1} if (s/^\s+(\w+)//); 16459 } 16460 return if (/^\s*$/); 16461 s/^\s*//; 16462 } 16463 elsif (exists($macros->{$macro})) 16464 {# it must be before the handling of {, otherwise it is considered 16465 # to be regular texinfo @-command. Maybe it could be placed higher 16466 # if we want user defined macros to override texinfo @-commands 16467 16468 # in 'ignored' we parse macro defined args anyway as it removes 16469 # some text, but we don't expand the macro 16470 16471 my $ref = $macros->{$macro}->{'args'}; 16472 # we remove any space/new line before the argument 16473 if (s/^\s*{\s*//) 16474 { # the macro has args 16475 $state->{'macro_args'} = [ "" ]; 16476 $state->{'macro_name'} = $macro; 16477 $state->{'macro_depth'} = 1; 16478 } 16479 elsif (($#$ref >= 1) or ($#$ref <0)) 16480 { # no brace -> no arg 16481 $_ = expand_macro ($macro, [], $_, $line_nr, $state); 16482 return; 16483 } 16484 else 16485 { # macro with one arg on the line 16486 chomp $_; 16487 $_ = expand_macro ($macro, [$_], "\n", $line_nr, $state); 16488 return; 16489 } 16490 } 16491 elsif ($macro eq ',') 16492 {# the @, causes problems when `,' separates things (in @node, @ref) 16493 $_ = "\@m_cedilla" . $_; 16494 } # handling of @, must be done before handling of { 16495 elsif (s/^{//) 16496 {# we add nested commands in a stack. verb is also on the stack 16497 # but handled specifically. 16498 # we add it the comands even in 'ignored' as their result is 16499 # discarded when the closing brace appear, or the ifset or 16500 # iclear is closed. 16501 if ($macro eq 'verb') 16502 { 16503 if (/^$/) 16504 { 16505 echo_error ("without associated character", $line_nr); 16506 #warn "$ERROR verb at end of line"; 16507 } 16508 else 16509 { 16510 s/^(.)//; 16511 $state->{'verb'} = $1; 16512 } 16513 } 16514 push (@$stack, { 'style' => $macro, 'text' => '' }); 16515 } 16516 else 16517 { 16518 add_prev($text, $stack, "\@$macro") unless($state->{'ignored'}); 16519 } 16520 next; 16521 } 16522 #elsif(s/^([^{}@]*)\@(.)//o) 16523 elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o) 16524 {# ARG_EXPANSION 16525 # No need to warn here for @ followed by a character that 16526 # is not in any @-command and it is done later 16527 add_prev($text, $stack, $1 . "\@$2") unless($state->{'ignored'}); 16528 next; 16529 } 16530 elsif (s/^([^{}]*)([{}])//o) 16531 { 16532 # in ignored section we cannot be sure that there is an @-command 16533 # allready opened so we must discard the text. 16534 # ARG_EXPANSION 16535 add_prev($text, $stack, $1) unless($state->{'ignored'}); 16536 if ($2 eq '{') 16537 { 16538 # this empty style is for a lone brace. 16539 # we add it even in 'ignored' as it is discarded when the closing 16540 # brace appear, or the ifset or iclear is closed. 16541 push @$stack, { 'style' => '', 'text' => '' }; 16542 } 16543 else 16544 { 16545 if (@$stack) 16546 { 16547 my $style = pop @$stack; 16548 my $result; 16549 if (($style->{'style'} ne '') and exists($info_enclose{$style->{'style'}}) and !$state->{'arg_expansion'}) 16550 { 16551 $result = $info_enclose{$style->{'style'}}->[0] . $style->{'text'} . $info_enclose{$style->{'style'}}->[1]; 16552 } 16553 elsif ($style->{'style'} ne '') 16554 { 16555 $result = '@' . $style->{'style'} . '{' . $style->{'text'} . '}'; 16556 } 16557 else 16558 { 16559 $result = '{' . $style->{'text'}; 16560 # don't close { if we are closing stack as we are not 16561 # sure this is a { ... } construct. i.e. we are 16562 # not sure that the user properly closed the matching 16563 # brace, so we don't close it ourselves 16564 $result .= '}' unless ($state->{'close_stack'} or $state->{'arg_expansion'}); 16565 } 16566 if ($state->{'ignored'}) 16567 {# ARG_EXPANSION 16568 print STDERR "# Popped `$style->{'style'}' in ifset/ifclear\n" if ($T2H_DEBUG); 16569 next; 16570 } 16571 add_prev ($text, $stack, $result); 16572 #print STDERR "MACRO end $style->{'style'} remaining: $_"; 16573 next; 16574 } 16575 else 16576 {# ARG_EXPANSION 16577 # we warn in the last pass that there is a } without open 16578 add_prev ($text, $stack, '}') unless($state->{'ignored'}); 16579 } 16580 } 16581 } 16582 else 16583 {# ARG_EXPANSION 16584 #print STDERR "END_LINE $_"; 16585 add_prev($text, $stack, $_) unless($state->{'ignored'}); 16586 last; 16587 } 16588 } 16589 return undef if ($state->{'ignored'}); 16590 return 1; 16591} 16592 16593sub close_structure_command($$$$) 16594{ 16595 my $cmd_ref = shift; 16596 my $state = shift; 16597 my $unclosed_commands = shift; 16598 my $line_nr = shift; 16599 my $result; 16600 16601 if ($cmd_ref->{'style'} eq 'anchor') 16602 { 16603 my $anchor = $cmd_ref->{'text'}; 16604 $anchor = normalise_node($anchor); 16605 if ($nodes{$anchor}) 16606 { 16607 echo_error ("Duplicate node for anchor found: $anchor", $line_nr); 16608 return ''; 16609 } 16610 $anchor_num++; 16611 $nodes{$anchor} = { 'anchor' => 1, 'seen' => 1, 'texi' => $anchor, 'id' => 'ANC' . $anchor_num}; 16612 push @{$state->{'place'}}, $nodes{$anchor}; 16613 } 16614 elsif ($cmd_ref->{'style'} eq 'footnote') 16615 { 16616 if ($Texi2HTML::Config::SEPARATED_FOOTNOTES) 16617 { 16618 $state->{'element'} = $state->{'footnote_element'}; 16619 $state->{'place'} = $state->{'footnote_place'}; 16620 } 16621 } 16622 elsif ($cmd_ref->{'style'} eq 'caption' or $cmd_ref->{'style'} 16623 eq 'shortcaption' and $state->{'float'}) 16624 { 16625 my @texi_lines = map {$_ = $_."\n"} split (/\n/, $cmd_ref->{'text'}); 16626 $state->{'float'}->{$cmd_ref->{'style'} . "_texi"} = \@texi_lines; 16627 } 16628 if (($cmd_ref->{'style'} eq 'titlefont') and ($cmd_ref->{'text'} =~ /\S/)) 16629 { 16630 $state->{'element'}->{'titlefont'} = $cmd_ref->{'text'} unless ((exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} eq 'titlepage')) or defined($state->{'element'}->{'titlefont'})) ; 16631 } 16632 if (defined($Texi2HTML::Config::command_handler{$cmd_ref->{'style'}})) 16633 { 16634 $result = init_special($cmd_ref->{'style'},$cmd_ref->{'text'}); 16635 if ($unclosed_commands) 16636 { 16637 $result .= "\n"; # the end of line is eaten by init_special 16638 echo_error("Closing specially handled \@-command $cmd_ref->{'style'}",$line_nr); 16639 } 16640 } 16641 elsif ($cmd_ref->{'style'}) 16642 { 16643 $result = '@' . $cmd_ref->{'style'} . '{' . $cmd_ref->{'text'}; 16644 $result .= '}' unless ($unclosed_commands); 16645 } 16646 else 16647 { 16648 $result = '{' . $cmd_ref->{'text'}; 16649 # don't close { if we are closing stack as we are not 16650 # sure this is a licit { ... } construct. 16651 $result .= '}' unless ($unclosed_commands); 16652 } 16653 return $result; 16654} 16655 16656sub scan_structure($$$$;$) 16657{ 16658 my $line = shift; 16659 my $text = shift; 16660 my $stack = shift; 16661 my $state = shift; 16662 my $line_nr = shift; 16663 16664 die "stack not an array ref" unless (ref($stack) eq "ARRAY"); 16665 local $_ = $line; 16666 #print STDERR "SCAN_STRUCTURE: $line"; 16667 #dump_stack ($text, $stack, $state); 16668 if (!$state->{'raw'} and (!exists($state->{'region_lines'}))) 16669 { 16670 if (!$state->{'verb'} and $state->{'menu'} and /^\*/o) 16671 { 16672 # new menu entry 16673 delete ($state->{'after_element'}); 16674 my $menu_line = $_; 16675 my $node; 16676 if (/^\*\s+($NODERE)::/) 16677 { 16678 $node = $1; 16679 } 16680 elsif (/^\*\s+([^:]+):\s*([^\t,\.\n]+)[\t,\.\n]/) 16681 { 16682 #$name = $1; 16683 $node = $2; 16684 } 16685 if ($node) 16686 { 16687 menu_entry_texi(normalise_node($node), $state, $line_nr); 16688 } 16689 } 16690 unless (no_line($_)) 16691 { 16692 delete $state->{'after_element'}; 16693 } 16694 } 16695 16696 while(1) 16697 { 16698 # scan structure 16699 #print STDERR "WHILE (s):$_"; 16700 #dump_stack($text, $stack, $state); 16701 16702 # as texinfo 4.5 16703 # verbatim might begin at another position than beginning 16704 # of line, and end verbatim might too. To end a verbatim section 16705 # @end verbatim must have exactly one space between end and verbatim 16706 # things following end verbatim are not ignored. 16707 # 16708 # html might begin at another position than beginning 16709 # of line, but @end html must begin the line, and have 16710 # exactly one space. Things following end html are ignored. 16711 # tex and ignore works like html 16712 # 16713 # ifnothtml might begin at another position than beginning 16714 # of line, and @end ifnothtml might too, there might be more 16715 # than one space between @end and ifnothtml but nothing more on 16716 # the line. 16717 # @end itemize, @end ftable works like @end ifnothtml. 16718 # except that @item on the same line than @end vtable doesn't work 16719 # 16720 # text right after the itemize before an item is displayed. 16721 # @item might be somewhere in a line. 16722 # strangely @item on the same line than @end vtable doesn't work 16723 # there should be nothing else than a command following @itemize... 16724 # 16725 # see more examples in formatting directory 16726 16727 if ($state->{'raw'}) 16728 { 16729 my $tag = $state->{'raw'}; 16730 ################# debug 16731 if (! @$stack or ($stack->[-1]->{'style'} ne $tag)) 16732 { 16733 print STDERR "Bug: raw or special: $tag but not on top of stack\n"; 16734 print STDERR "line: $_"; 16735 dump_stack($text, $stack, $state); 16736 exit 1; 16737 } 16738 ################# end debug 16739 if (s/^(.*?)\@end\s$tag$// or s/^(.*?)\@end\s$tag\s//) 16740 { 16741 add_prev ($text, $stack, $1); 16742 delete $state->{'raw'}; 16743 my $style = pop @$stack; 16744 if (defined($Texi2HTML::Config::command_handler{$tag})) 16745 { # replace the special region by what init_special give 16746 if ($style->{'text'} !~ /^\s*$/) 16747 { 16748 add_prev ($text, $stack, init_special($style->{'style'}, $style->{'text'})); 16749 } 16750 16751 } 16752 else 16753 { 16754 my $after_macro = ''; 16755 $after_macro = ' ' unless (/^\s*$/); 16756 add_prev ($text, $stack, $style->{'text'} . "\@end $tag" . $after_macro); 16757 } 16758 unless (no_line($_)) 16759 { 16760 delete ($state->{'after_element'}); 16761 } 16762 next; 16763 } 16764 else 16765 { 16766 add_prev ($text, $stack, $_); 16767 return if (defined($Texi2HTML::Config::command_handler{$tag})); 16768 last; 16769 } 16770 } 16771 16772 if (defined($state->{'verb'})) 16773 { 16774 my $char = quotemeta($state->{'verb'}); 16775 if (s/^(.*?)$char\}/\}/) 16776 { 16777 add_prev($text, $stack, $1 . $state->{'verb'}); 16778 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; 16779 delete $state->{'verb'}; 16780 next; 16781 } 16782 else 16783 { 16784 add_prev($text, $stack, $_); 16785 last; 16786 } 16787 } 16788 16789 unless (no_line($_)) 16790 { 16791 delete $state->{'after_element'}; 16792 } 16793 # macro_regexp 16794 if (s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//) 16795 { 16796 add_prev($text, $stack, $1); 16797 my $end_tag = $2; 16798 #print STDERR "END STRUCTURE $end_tag\n"; 16799 $state->{'detailmenu'}-- if ($end_tag eq 'detailmenu' and $state->{'detailmenu'}); 16800 if (defined($state->{'text_macro_stack'}) 16801 and @{$state->{'text_macro_stack'}} 16802 and ($end_tag eq $state->{'text_macro_stack'}->[-1])) 16803 { 16804 pop @{$state->{'text_macro_stack'}}; 16805 if (exists($region_lines{$end_tag})) 16806 { # end a region_line macro, like documentdescription, copying 16807 print STDERR "Bug: end_tag $end_tag ne $state->{'region_lines'}->{'format'}" 16808 if ( $end_tag ne $state->{'region_lines'}->{'format'}); 16809 $state->{'region_lines'}->{'number'}--; 16810 if ($state->{'region_lines'}->{'number'} == 0) 16811 { 16812 close_region($state); 16813 } 16814 #dump_stack($text, $stack, $state); 16815 } 16816 if ($end_tag eq 'menu') 16817 { 16818 add_prev($text, $stack, "\@end $end_tag"); 16819 $state->{'menu'}--; 16820 } 16821 else 16822 { 16823 #print STDERR "End $end_tag\n"; 16824 #dump_stack($text, $stack, $state); 16825 return if (/^\s*$/); 16826 } 16827 } 16828 elsif ($text_macros{$end_tag}) 16829 { 16830 echo_error ("\@end $end_tag without corresponding element", $line_nr); 16831 #dump_stack($text, $stack, $state); 16832 } 16833 else 16834 { 16835 if ($end_tag eq 'float' and $state->{'float'}) 16836 { 16837 delete $state->{'float'}; 16838 } 16839 elsif ($end_tag eq $state->{'table_stack'}->[-1]) 16840 { 16841 enter_table_index_entry($text, $stack, $state, $line_nr); 16842 pop @{$state->{'table_stack'}}; 16843 } 16844 #add end tag 16845 add_prev($text, $stack, "\@end $end_tag"); 16846 } 16847 next; 16848 } 16849 #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o) 16850 # macro_regexp 16851 elsif (s/^([^{}@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{}@]*)\@([a-zA-Z][\w-]*)$//o) 16852 { 16853 add_prev($text, $stack, $1); 16854 my $macro = $2; 16855 #print STDERR "MACRO $macro\n"; 16856 if (defined($Texi2HTML::Config::misc_command{$macro})) 16857 { 16858 my $line; 16859 ($_, $line) = misc_command_structure($_, $macro, $state, 16860 $line_nr); 16861 add_prev ($text, $stack, "\@$macro".$line); 16862 next; 16863 } 16864 16865 if ($macro =~ /^(\w+?)index/ and ($1 ne 'print') and ($1 ne 'syncode') and ($1 ne 'syn') and ($1 ne 'def') and ($1 ne 'defcode')) 16866 { 16867 my $index_prefix = $1; 16868 my $key = $_; 16869 $key =~ s/^\s*//; 16870 $_ = substitute_texi_line($_); 16871 enter_index_entry($index_prefix, $line_nr, $key, $state->{'place'}, $state->{'element'}, $state->{'after_element'}, $macro); 16872 add_prev ($text, $stack, "\@$macro" . $_); 16873 last; 16874 } 16875 elsif (defined($text_macros{$macro})) 16876 { 16877 #print STDERR "TEXT_MACRO: $macro\n"; 16878 if ($text_macros{$macro} eq 'raw') 16879 { 16880 $state->{'raw'} = $macro; 16881 #print STDERR "RAW\n"; 16882 } 16883 elsif ($format_type{$macro} and $format_type{$macro} eq 'menu') 16884 { 16885 $state->{'menu'}++; 16886 delete ($state->{'prev_menu_node'}); 16887 push @{$state->{'text_macro_stack'}}, $macro; 16888 #print STDERR "MENU (text_macro_stack: @{$state->{'text_macro_stack'}})\n"; 16889 } 16890 elsif (exists($region_lines{$macro})) 16891 { 16892 if (exists($state->{'region_lines'}) and ($state->{'region_lines'}->{'format'} ne $macro)) 16893 { 16894 echo_error("\@$macro not allowed within $state->{'region_lines'}->{'format'}", $line_nr); 16895 next; 16896 } 16897 if (!exists($state->{'region_lines'})) 16898 { 16899 $state->{'region_lines'}->{'format'} = $macro; 16900 $state->{'region_lines'}->{'number'} = 1; 16901 $state->{'region_lines'}->{'after_element'} = 1 if ($state->{'after_element'}); 16902 $state->{'region_lines'}->{'kept_place'} = $state->{'place'}; 16903 $state->{'place'} = $region_place; 16904 } 16905 else 16906 { 16907 $state->{'region_lines'}->{'number'}++; 16908 } 16909 push @{$state->{'text_macro_stack'}}, $macro; 16910 } 16911 # if it is a raw formatting command or a menu command 16912 # we must keep it for later 16913 my $macro_kept; 16914 if (($state->{'raw'} and (!defined($Texi2HTML::Config::command_handler{$macro}))) or ($macro eq 'menu')) 16915 { 16916 add_prev($text, $stack, "\@$macro"); 16917 $macro_kept = 1; 16918 } 16919 if ($state->{'raw'}) 16920 { 16921 push @$stack, { 'style' => $macro, 'text' => '' }; 16922 } 16923 next if $macro_kept; 16924 #dump_stack ($text, $stack, $state); 16925 return if (/^\s*$/); 16926 } 16927 elsif ($macro eq 'float') 16928 { 16929 my ($style_texi, $label_texi) = split(/,/, $_); 16930 $style_texi = normalise_space($style_texi); 16931 $label_texi = undef if (defined($label_texi) and ($label_texi =~ /^\s*$/)); 16932 if (defined($label_texi)) 16933 { # The float may be a target for refs if it has a label 16934 $label_texi = normalise_node($label_texi); 16935 if (exists($nodes{$label_texi}) and defined($nodes{$label_texi}) 16936 and $nodes{$label_texi}->{'seen'}) 16937 { 16938 echo_error ("Duplicate label found: $label_texi", $line_nr); 16939 while ($_ =~ /,/) 16940 { 16941 $_ =~ s/,.*$//; 16942 } 16943 } 16944 else 16945 { 16946 my $float = { }; 16947 if (exists($nodes{$label_texi}) and defined($nodes{$label_texi})) 16948 { # float appeared in a menu 16949 $float = $nodes{$label_texi}; 16950 } 16951 else 16952 { 16953 $nodes{$label_texi} = $float; 16954 } 16955 $float->{'float'} = 1; 16956 $float->{'tag'} = 'float'; 16957 $float->{'texi'} = $label_texi; 16958 $float->{'seen'} = 1; 16959 $float->{'id'} = $label_texi; 16960#print STDERR "FLOAT: $float $float->{'texi'}, place $state->{'place'}\n"; 16961 push @{$state->{'place'}}, $float; 16962 $float->{'element'} = $state->{'element'}; 16963 $state->{'float'} = $float; 16964 $float->{'style_texi'} = $style_texi; 16965 push @floats, $float; 16966 } 16967 } 16968 add_prev($text, $stack, "\@$macro" . $_); 16969 last; 16970 } 16971 elsif (defined($Texi2HTML::Config::def_map{$macro})) 16972 { 16973 #We must enter the index entries 16974 my ($prefix, $entry, $argument) = get_deff_index($macro, $_, $line_nr); 16975 # use deffn instead of deffnx for @-command record 16976 # associated with index entry 16977 my $idx_macro = $macro; 16978 $idx_macro =~ s/x$//; 16979 enter_index_entry($prefix, $line_nr, $entry, $state->{'place'}, 16980 $state->{'element'}, 0, $idx_macro) if ($prefix); 16981 s/(.*)//; 16982 add_prev($text, $stack, "\@$macro" . $1); 16983 # the text is discarded but we must handle correctly bad 16984 # texinfo with 2 @def-like commands on the same line 16985 substitute_text({'structure' => 1, 'place' => $state->{'place'} },($argument)); 16986 } 16987 elsif ($macro =~ /^itemx?$/) 16988 { 16989 enter_table_index_entry($text, $stack, $state, $line_nr); 16990 if ($state->{'table_stack'}->[-1] =~ /^(v|f)table$/) 16991 { 16992 $state->{'item'} = $macro; 16993 push @$stack, { 'format' => 'index_item', 'text' => "" }; 16994 } 16995 else 16996 { 16997 add_prev($text, $stack, "\@$macro"); 16998 } 16999 } 17000 elsif ($format_type{$macro} and ($format_type{$macro} eq 'table' or $format_type{$macro} eq 'list')) 17001 { # We must enter the index entries of (v|f)table thus we track 17002 # in which table we are 17003 push @{$state->{'table_stack'}}, $macro; 17004 add_prev($text, $stack, "\@$macro"); 17005 } 17006 elsif (s/^{//) 17007 { 17008 if ($macro eq 'verb') 17009 { 17010 if (/^$/) 17011 { 17012 # We allready warned in pass texi 17013 #warn "$ERROR verb at end of line"; 17014 } 17015 else 17016 { 17017 s/^(.)//; 17018 $state->{'verb'} = $1; 17019 } 17020 } 17021 elsif ($macro eq 'footnote' and $Texi2HTML::Config::SEPARATED_FOOTNOTES) 17022 { 17023 $state->{'footnote_element'} = $state->{'element'}; 17024 $state->{'footnote_place'} = $state->{'place'}; 17025 $state->{'element'} = $footnote_element; 17026 $state->{'place'} = $footnote_element->{'place'}; 17027 } 17028 push (@$stack, { 'style' => $macro, 'text' => '' }); 17029 } 17030 else 17031 { 17032 add_prev($text, $stack, "\@$macro"); 17033 } 17034 next; 17035 } 17036 #elsif(s/^([^{}@]*)\@(.)//o) 17037 elsif(s/^([^{}@]*)\@([^\s\}\{\@]*)//o) 17038 { 17039 add_prev($text, $stack, $1 . "\@$2"); 17040 next; 17041 } 17042 elsif (s/^([^{}]*)([{}])//o) 17043 { 17044 add_prev($text, $stack, $1); 17045 if ($2 eq '{') 17046 { 17047 push @$stack, { 'style' => '', 'text' => '' }; 17048 } 17049 else 17050 { 17051 if (@$stack) 17052 { 17053 my $style = pop @$stack; 17054 my $result; 17055 add_prev ($text, $stack, close_structure_command($style, 17056 $state, 0, $line_nr)); 17057 next; 17058 } 17059 else 17060 { 17061 # We warn in the last pass 17062 #warn "$ERROR '}' without opening '{' line: $line"; 17063 #echo_error ("'}' without opening '{' line: $line", $line_nr); 17064 add_prev ($text, $stack, '}'); 17065 } 17066 } 17067 } 17068 else 17069 { 17070 #print STDERR "END_LINE $_"; 17071 add_prev($text, $stack, $_); 17072 enter_table_index_entry($text, $stack, $state, $line_nr); 17073 last; 17074 } 17075 } 17076 return 1; 17077} 17078 17079sub scan_line($$$$;$) 17080{ 17081 my $line = shift; 17082 my $text = shift; 17083 my $stack = shift; 17084 my $state = shift; 17085 my $line_nr = shift; 17086 17087 die "stack not an array ref" unless (ref($stack) eq "ARRAY"); 17088 local $_ = $line; 17089 #print STDERR "SCAN_LINE (@{$state->{'command_stack'}}): $line"; 17090 #dump_stack($text, $stack, $state ); 17091 my $new_menu_entry; # true if there is a new menu entry 17092 my $menu_description_in_format; # true if we are in a menu description 17093 # but in another format section (@table....) 17094 if (defined($state->{'prepend_text'})) 17095 { 17096 $_ = $state->{'prepend_text'} . $_; 17097 $state->{'prepend_text'} = undef; 17098 delete $state->{'prepend_text'}; 17099 } 17100 17101 unless ($state->{'end_of_line_protected'} and $state->{'deff_line'}) 17102 { # end of lines are really protected only for @def* 17103 if (!$state->{'raw'} and !$state->{'verb'} and $state->{'menu'}) 17104 { # new menu entry 17105 my ($node, $name, $ending); 17106 if (s/^\*(\s+$NODERE)(::)//o) 17107 { 17108 $node = $1; 17109 $ending = $2; 17110 } 17111 elsif (s/^\*(\s+[^:]+):(\s*[^\t,\.\n]+)([\t,\.\n])//o) 17112 { 17113 $name = $1; 17114 $node = $2; 17115 $ending = $3; 17116 } 17117 if ($node) 17118 { 17119 my $top_stack = top_stack($stack); 17120 if ($top_stack and $top_stack->{'format'} and 17121 ( 17122 ($top_stack->{'format'} eq 'menu_description') or 17123 ($top_stack->{'format'} eq 'menu') or 17124 (($top_stack->{'format'} eq 'preformatted') and (stack_order($stack, 'preformatted', 'menu_comment'))) or 17125 ($top_stack->{'format'} eq 'menu_preformatted') or 17126 ($top_stack->{'format'} eq 'menu_comment') 17127 ) 17128 ) 17129 { # we are in a normal menu state. 17130 close_menu($text, $stack, $state, $line_nr); 17131 $new_menu_entry = 1; 17132 $state->{'menu_entry'} = { 'name' => $name, 'node' => $node, 17133 'ending' => $ending }; 17134 add_prev ($text, $stack, do_menu_link($state, $line_nr)); 17135 print STDERR "# New menu entry: $node\n" if ($T2H_DEBUG & $DEBUG_MENU); 17136 push @$stack, {'format' => 'menu_description', 'text' => ''}; 17137 } 17138 else 17139 { # we are within a macro or a format. In that case we use 17140 # a simplified formatting of menu which should be right whatever 17141 # the context 17142 my $menu_entry = $state->{'menu_entry'}; 17143 $state->{'menu_entry'} = { 'name' => $name, 'node' => $node, 17144 'ending' => $ending }; 17145 add_prev ($text, $stack, do_menu_link($state, $line_nr, 1)); 17146 $state->{'menu_entry'} = $menu_entry; 17147 } 17148 } 17149 } 17150 # we're in a menu entry description 17151 if ($state->{'menu_entry'} and !$new_menu_entry) 17152 { 17153 my $top_stack = top_stack($stack); 17154 if (/^\s+\S.*$/ or (!$top_stack->{'format'} or ($top_stack->{'format'} ne 'menu_description'))) 17155 { # description continues 17156 $menu_description_in_format = 1 if ($top_stack->{'format'} and ($top_stack->{'format'} ne 'menu_description')); 17157 print STDERR "# Description continues\n" if ($T2H_DEBUG & $DEBUG_MENU); 17158 } 17159 else 17160 { # enter menu comment after menu entry 17161 ################################ begin debug 17162 if (!$top_stack->{'format'} or ($top_stack->{'format'} ne 'menu_description')) 17163 { 17164 print STDERR "Bug: begin menu comment but previous isn't menu_description\n"; 17165 dump_stack ($text, $stack, $state); 17166 } 17167 print STDERR "# Menu comment begins\n" if ($T2H_DEBUG & $DEBUG_MENU); 17168 ################################ end debug 17169 my $descr = pop(@$stack); 17170 17171 add_prev ($text, $stack, do_menu_description($descr->{'text'}, $state)); 17172 delete $state->{'menu_entry'}; 17173 unless (/^\s*\@end\s+menu\b/) 17174 { 17175 $state->{'menu_comment'}++; 17176 push @$stack, {'format' => 'menu_comment', 'text' => ''}; 17177 unless ($Texi2HTML::Config::SIMPLE_MENU) 17178 { 17179 push @{$state->{'preformatted_stack'}}, {'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE, 'class' => 'menu-comment' }; 17180 $state->{'preformatted'}++; 17181 begin_paragraph($stack, $state); 17182 } 17183 } 17184 } 17185 } 17186 if (($state->{'menu_entry'} and !$menu_description_in_format) or $state->{'raw'} or $state->{'preformatted'} or $state->{'no_paragraph'} or $state->{'keep_texi'} or $state->{'remove_texi'}) 17187 { # empty lines are left unmodified 17188 if (/^\s*$/) 17189 { 17190 add_prev($text, $stack, $_); 17191 return; 17192 } 17193 elsif (!$state->{'raw'}) 17194 { 17195 my $next_tag = next_tag($_); 17196 if ($state->{'deff_line'} and !defined($Texi2HTML::Config::def_map{$next_tag})) 17197 { 17198 begin_deff_item($stack, $state); 17199 } 17200 } 17201 } 17202 else 17203 { 17204 if (/^\s*$/) 17205 { 17206 if ($state->{'paragraph_context'}) 17207 { # An empty line ends a paragraph 17208 close_paragraph($text, $stack, $state, $line_nr); 17209 } 17210 add_prev($text, $stack, &$Texi2HTML::Config::empty_line($_,$state)); 17211 return 1; 17212 } 17213 else 17214 { 17215 #print STDERR "a line not empty and not in no paragraph format\n"; 17216 my $next_tag = next_tag($_); 17217 if ($state->{'deff_line'} and !defined($Texi2HTML::Config::def_map{$next_tag})) 17218 { # finish opening the deff, as this is not a deff tag, it can't be 17219 # a deff macro with x 17220 begin_deff_item($stack, $state); 17221 } 17222 if (!no_paragraph($state,$_)) 17223 { # open a paragraph, unless the line begins with a macro that 17224 # shouldn't trigger a paragraph opening 17225 begin_paragraph($stack, $state); 17226 } 17227 } 17228 } 17229 } 17230 delete $state->{'end_of_line_protected'} 17231 if ($state->{'end_of_line_protected'}); 17232 17233 while(1) 17234 { 17235 # scan_line 17236 #print STDERR "WHILE (l): $_|"; 17237 #dump_stack($text, $stack, $state); 17238 # we're in a raw format (html, tex if !L2H, verbatim) 17239 if (defined($state->{'raw'})) 17240 { 17241 (dump_stack($text, $stack, $state), die "Bug for raw ($state->{'raw'})") if (! @$stack or ! ($stack->[-1]->{'style'} eq $state->{'raw'})); 17242 if (s/^(.*?)\@end\s$state->{'raw'}$// or s/^(.*?)\@end\s$state->{'raw'}\s+//) 17243 # don't protect html, it is done by Texi2HTML::Config::raw if needed 17244 { 17245 print STDERR "# end raw $state->{'raw'}\n" if ($T2H_DEBUG & $DEBUG_FORMATS); 17246 add_prev ($text, $stack, $1); 17247 my $style = pop @$stack; 17248 if ($style->{'text'} !~ /^\s*$/) 17249 { 17250 if ($state->{'keep_texi'}) 17251 { 17252 add_prev ($text, $stack, $style->{'text'} . "\@end $state->{'raw'}"); 17253 } 17254 elsif ($state->{'remove_texi'}) 17255 { 17256 add_prev ($text, $stack, &$Texi2HTML::Config::raw_no_texi($style->{'style'}, $style->{'text'})); 17257 } 17258 else 17259 { 17260 add_prev($text, $stack, &$Texi2HTML::Config::raw($style->{'style'}, $style->{'text'})); 17261 } 17262 } 17263 if (!$state->{'keep_texi'} and !$state->{'remove_texi'}) 17264 { 17265 # reopen preformatted if it was interrupted by the raw format 17266 # if raw format is html the preformatted wasn't interrupted 17267 begin_paragraph($stack, $state) if ($state->{'preformatted'} and (!$Texi2HTML::Config::format_in_paragraph{$state->{'raw'}})); 17268 delete $state->{'raw'}; 17269 return if (/^\s*$/); 17270 } 17271 delete $state->{'raw'}; 17272 next; 17273 } 17274 else 17275 { 17276 print STDERR "#within raw $state->{'raw'}:$_" if ($T2H_DEBUG & $DEBUG_FORMATS); 17277 add_prev ($text, $stack, $_); 17278 last; 17279 } 17280 } 17281 17282 # we are within a @verb 17283 if (defined($state->{'verb'})) 17284 { 17285 my $char = quotemeta($state->{'verb'}); 17286 if (s/^(.*?)$char\}/\}/) 17287 { 17288 if ($state->{'keep_texi'}) 17289 { 17290 add_prev($text, $stack, $1 . $state->{'verb'}); 17291 $stack->[-1]->{'text'} = $state->{'verb'} . $stack->[-1]->{'text'}; 17292 } 17293 elsif ($state->{'remove_texi'}) 17294 { 17295 add_prev($text, $stack, $1); 17296 } 17297 else 17298 { 17299 add_prev($text, $stack, do_text($1, $state)); 17300 } 17301 delete $state->{'verb'}; 17302 next; 17303 } 17304 else 17305 { 17306 add_prev($text, $stack, $_); 17307 last; 17308 } 17309 } 17310 17311 # a special case for @ followed by an end of line in deff 17312 # FIXME this is similar with makeinfo, but shouldn't that 17313 # be done for @floats and @quotations too? and @item, @center? 17314 # this piece of code is required, to avoid the 'cmd_line' to be 17315 # closed below 17316 if ($state->{'end_of_line_protected'} and $state->{'deff_line'}) 17317 { 17318 print STDERR "Bug: 'end_of_line_protected' with text following: $_\n" 17319 unless /^$/; 17320 return; 17321 } 17322 17323 # We handle now the end tags 17324 # macro_regexp 17325 if ($state->{'keep_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//) 17326 { 17327 my $end_tag = $2; 17328 add_prev($text, $stack, $1 . "\@end $end_tag"); 17329 next; 17330 } 17331 # macro_regexp 17332 elsif ($state->{'remove_texi'} and s/^([^{}@]*)\@end\s+([a-zA-Z][\w-]*)//) 17333 { 17334 add_prev($text, $stack, $1); 17335 next; 17336 } 17337 # macro_regexp 17338 if (s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)\s//o or s/^([^{}@,]*)\@end\s+([a-zA-Z][\w-]*)$//o) 17339 { 17340 add_prev($text, $stack, do_text($1, $state)); 17341 my $end_tag = $2; 17342 #print STDERR "END_MACRO $end_tag\n"; 17343 #dump_stack ($text, $stack, $state); 17344 17345 # First we test if the stack is not empty. 17346 # Then we test if the end tag is a format tag. 17347 # We then close paragraphs and preformatted at top of the stack. 17348 # We handle the end tag (even when it was not the tag which appears 17349 # on the top of the stack; in that case we close anything 17350 # until that element) 17351 $state->{'detailmenu'}-- if ($end_tag eq 'detailmenu' and $state->{'detailmenu'}); 17352 # FIXME handle below (look for misc_command) to let the user 17353 # keep that end tag. On the other hand it is only used for 17354 # end detailmenu, so maybe it should just go and detailmenu 17355 # could be handled like a normal format. Last there could be 17356 # something similar than what is done for other misc_commands. 17357 next if (defined($Texi2HTML::Config::misc_command{"end $end_tag"})); 17358 my $top_stack = top_stack($stack); 17359 if (!$top_stack) 17360 { 17361 echo_error ("\@end $end_tag without corresponding opening", $line_nr); 17362 add_prev($text, $stack, "\@end $end_tag"); 17363 next; 17364 } 17365 17366 if (!$format_type{$end_tag}) 17367 { 17368 echo_warn ("Unknown \@end $end_tag", $line_nr); 17369 #warn "$ERROR Unknown \@end $end_tag\n"; 17370 add_prev($text, $stack, "\@end $end_tag"); 17371 next; 17372 } 17373 unless ($Texi2HTML::Config::format_in_paragraph{$end_tag}) 17374 { # If the $end_tag is wrong we may be keeping paragraph 17375 # for a format with paragraphs on the stack 17376 close_paragraph($text, $stack, $state, $line_nr); 17377 } 17378 17379 $top_stack = top_stack($stack); 17380 if (!$top_stack or (!defined($top_stack->{'format'}))) 17381 { 17382 echo_error ("\@end $end_tag without corresponding opening element", $line_nr); 17383 add_prev($text, $stack, "\@end $end_tag"); 17384 dump_stack ($text, $stack, $state) if ($T2H_DEBUG); 17385 next; 17386 } 17387 # Warn if the format on top of stack is not compatible with the 17388 # end tag, and find the end tag. 17389 unless ( 17390 ($top_stack->{'format'} eq $end_tag) 17391 or 17392 ( 17393 ($format_type{$end_tag} eq 'menu') and 17394 ( 17395 ($top_stack->{'format'} eq 'menu_preformatted') or 17396 ($top_stack->{'format'} eq 'menu_comment') or 17397 ($top_stack->{'format'} eq 'menu_description') 17398 ) 17399 ) or 17400 ( 17401 ($end_tag eq 'multitable') and 17402 ( 17403 ($top_stack->{'format'} eq 'cell') or 17404 ($top_stack->{'format'} eq 'null') 17405 ) 17406 ) or 17407 ( 17408 ($format_type{$end_tag} eq 'list' ) and 17409 ($top_stack->{'format'} eq 'item') 17410 ) or 17411 ( 17412 ( 17413 ($format_type{$end_tag} eq 'table') and 17414 ($end_tag ne 'multitable') 17415 ) and 17416 ( 17417 ($top_stack->{'format'} eq 'term') or 17418 ($top_stack->{'format'} eq 'line') 17419 ) 17420 ) or 17421 ( 17422 (defined($Texi2HTML::Config::def_map{$end_tag})) and 17423 ($top_stack->{'format'} eq 'deff_item') 17424 ) or 17425 ( 17426 ($end_tag eq 'row') and 17427 ($top_stack->{'format'} eq 'cell') 17428 ) 17429 ) 17430 { 17431 # this is not the right format. We try to close other 17432 # formats to find the format we are searching for. 17433 # First we close paragraphs, as with a wrong $end_format 17434 # they may not be closed properly. 17435 close_paragraph($text, $stack, $state, $line_nr); 17436 $top_stack = top_stack($stack); 17437 if (!$top_stack or (!defined($top_stack->{'format'}))) 17438 { 17439 echo_error ("\@end $end_tag without corresponding opening element", $line_nr); 17440 add_prev($text, $stack, "\@end $end_tag"); 17441 dump_stack ($text, $stack, $state) if ($T2H_DEBUG); 17442 next; 17443 } 17444 my $waited_format = $top_stack->{'format'}; 17445 $waited_format = $fake_format{$top_stack->{'format'}} if ($format_type{$top_stack->{'format'}} eq 'fake'); 17446 echo_error ("waiting for end of $waited_format, found \@end $end_tag", $line_nr); 17447 close_stack($text, $stack, $state, $line_nr, undef, $end_tag); 17448 # an empty preformatted may appear when closing things as 17449 # when closed, formats reopen the preformatted environment 17450 # in case there is some text following, but we know it isn't 17451 # the case here, thus we can close paragraphs. 17452 close_paragraph($text, $stack, $state); 17453 my $new_top_stack = top_stack($stack); 17454 next unless ($new_top_stack and defined($new_top_stack->{'format'}) and (($new_top_stack->{'format'} eq $end_tag) 17455 or (($format_type{$new_top_stack->{'format'}} eq 'fake') and ($fake_format{$new_top_stack->{'format'}} eq $format_type{$end_tag})))); 17456 } 17457 # We should now be able to handle the format 17458 if (defined($format_type{$end_tag}) and $format_type{$end_tag} ne 'fake') 17459 { 17460 end_format($text, $stack, $state, $end_tag, $line_nr); 17461 begin_paragraph_after_command($state,$stack,$end_tag,$_); 17462 } 17463 else 17464 { # this is a fake format, ie a format used internally, inside 17465 # a real format. We do nothing, hoping the real format will 17466 # get closed, closing the fake internal formats 17467 #print STDERR "FAKE \@end $end_tag\n"; 17468 } 17469 next; 17470 } 17471 # This is a macro 17472 #elsif (s/^([^{}@]*)\@([a-zA-Z]\w*|["'~\@\}\{,\.!\?\s\*\-\^`=:\/])//o) 17473 # macro_regexp 17474 elsif (s/^([^{},@]*)\@(["'~\@\}\{,\.!\?\s\*\-\^`=:\|\/])//o or s/^([^{}@,]*)\@([a-zA-Z][\w-]*)([\s\{\}\@])/$3/o or s/^([^{},@]*)\@([a-zA-Z][\w-]*)$//o) 17475 { 17476 add_prev($text, $stack, do_text($1, $state)); 17477 my $macro = $2; 17478 #print STDERR "MACRO $macro\n"; 17479 #print STDERR "LINE $_"; 17480 #dump_stack ($text, $stack, $state); 17481 # This is a macro added by close_stack to mark paragraph end 17482 if ($macro eq 'end_paragraph') 17483 { 17484 s/^\{\}//; 17485 my $top_stack = top_stack($stack); 17486 #################################### debug 17487 if (!$top_stack or !$top_stack->{'format'} 17488 or ($top_stack->{'format'} ne 'paragraph')) 17489 { 17490 print STDERR "Bug: end_paragraph but no paragraph to end\n"; 17491 dump_stack ($text, $stack, $state); 17492 next; 17493 } 17494 #################################### end debug 17495 s/^\s//; 17496 my $paragraph = pop @$stack; 17497 add_prev ($text, $stack, do_paragraph($paragraph->{'text'}, $state)); 17498 next; 17499 } 17500 # Handle macro added by close_stack to mark preformatted region end 17501 elsif ($macro eq 'end_preformatted') 17502 { 17503 #print STDERR "END_PREFORMATTED\n"; 17504 s/^\{\}//; 17505 my $top_stack = top_stack($stack); 17506 #################################### debug 17507 if (!$top_stack or !$top_stack->{'format'} 17508 or ($top_stack->{'format'} ne 'preformatted')) 17509 { 17510 print STDERR "Bug: end_preformatted but no preformatted to end\n"; 17511 dump_stack ($text, $stack, $state); 17512 next; 17513 } 17514 #################################### end debug 17515 my $paragraph = pop @$stack; 17516 s/^\s//; 17517 add_prev ($text, $stack, do_preformatted($paragraph->{'text'}, $state)); 17518 next; 17519 } 17520 if (defined($Texi2HTML::Config::misc_command{$macro})) 17521 { 17522 # The strange condition associated with 'keep_texi' is 17523 # there because for an argument appearing on an @itemize 17524 # line (we're in 'check_item'), meant to be prepended to an 17525 # @item we don't want to keep @c or @comment as otherwise it 17526 # eats the @item line. Other commands could do that too but 17527 # then the user deserves what he gets. 17528 if ($state->{'keep_texi'} and 17529 (!$state->{'check_item'} or ($macro ne 'c' and $macro ne 'comment'))) 17530 { 17531 my ($line, $args); 17532 ($_, $line, $args) = preserve_command($_, $macro); 17533 add_prev($text, $stack, "\@$macro". $line); 17534 next; 17535 } 17536 17537 # Handle the misc command 17538 $_ = misc_command_text($_, $macro, $stack, $state, $text, $line_nr); 17539 return unless (defined($_)); 17540 unless ($Texi2HTML::Config::misc_command{$macro}->{'keep'}) 17541 { 17542 begin_paragraph($stack, $state) if 17543 (!no_paragraph($state,$_)); 17544 next; 17545 } 17546 } 17547 if ($macro eq 'listoffloats') 17548 { 17549 if ($state->{'keep_texi'}) 17550 { 17551 if (s/(.*)//o) 17552 { 17553 add_prev($text, $stack, "\@$macro" . $1); 17554 } 17555 next; 17556 } 17557 return undef if ($state->{'remove_texi'}); 17558 17559 if (s/^(\s+)(.*)//o) 17560 { 17561 my $arg = $2; 17562 my $style_id = cross_manual_line(normalise_space($arg)); 17563 my $style = substitute_line (&$Texi2HTML::Config::listoffloats_style($arg)); 17564 if (exists ($floats{$style_id})) 17565 { 17566 close_paragraph($text, $stack, $state, $line_nr); 17567 my @listoffloats_entries = (); 17568 foreach my $float (@{$floats{$style_id}->{'floats'}}) 17569 { 17570 my $float_style = substitute_line(&$Texi2HTML::Config::listoffloats_float_style($arg, $float)); 17571 my $caption_lines = &$Texi2HTML::Config::listoffloats_caption($float); 17572 # we set 'multiple_pass' such that index entries 17573 # and anchors are not handled one more time; 17574 # the caption has allready been formatted, 17575 # and these have been handled at the right place 17576 my $caption = substitute_text({ 'multiple_pass' => 1 }, @$caption_lines); 17577 push @listoffloats_entries, &$Texi2HTML::Config::listoffloats_entry($arg, $float, $float_style, $caption, href($float, $state->{'element'}->{'file'})); 17578 } 17579 add_prev($text, $stack, &$Texi2HTML::Config::listoffloats($arg, $style, \@listoffloats_entries)); 17580 } 17581 else 17582 { 17583 echo_warn ("Unknown float style $arg", $line_nr); 17584 } 17585 } 17586 else 17587 { 17588 echo_error ("Bad \@$macro line: $_", $line_nr); 17589 } 17590 return undef; 17591 } 17592 # This is a @macroname{...} construct. We add it on top of stack 17593 # It will be handled when we encounter the '}' 17594 # There is a special case for def macros as @deffn{def} is licit 17595 if (!$Texi2HTML::Config::def_map{$macro} and s/^{//) 17596 { 17597 if ($macro eq 'verb') 17598 { 17599 if (/^$/) 17600 { 17601 # Allready warned 17602 #warn "$ERROR verb at end of line"; 17603 } 17604 else 17605 { 17606 s/^(.)//; 17607 $state->{'verb'} = $1; 17608 } 17609 } 17610 elsif ($macro eq 'm_cedilla' and !$state->{'keep_texi'}) 17611 { 17612 $macro = ','; 17613 } 17614 # currently if remove_texi and anchor/ref/footnote 17615 # the text within the command is ignored 17616 # see t2h_remove_command in texi2html.init 17617 push (@$stack, { 'style' => $macro, 'text' => '', 'arg_nr' => 0 }); 17618 $state->{'no_paragraph'}++ if ($no_paragraph_macro{$macro}); 17619 open_arg($macro, 0, $state); 17620 if (defined($style_type{$macro}) and (($style_type{$macro} eq 'style') or ($style_type{$macro} eq 'accent'))) 17621 { 17622 push (@{$state->{'command_stack'}}, $macro); 17623 #print STDERR "# Stacked $macro (@{$state->{'command_stack'}})\n" if ($T2H_DEBUG); 17624 } 17625 next; 17626 } 17627 17628 # special case if we are checking itemize line. In that case 17629 # we want to make sure that there is no @item on the @itemize 17630 # line, otherwise it will be added on the front of another @item, 17631 # leading to an infinite loop... 17632 17633 if ($state->{'check_item'} and ($macro =~ /^itemx?$/ or $macro eq 'headitem')) 17634 { 17635 echo_error("\@$macro on \@$state->{'check_item'} line", $line_nr); 17636 next; 17637 } 17638 17639 # if we're keeping texi unmodified we can do it now 17640 if ($state->{'keep_texi'}) 17641 { 17642 # We treat specially formats accepting {} on command line 17643 if ($macro eq 'multitable' or defined($Texi2HTML::Config::def_map{$macro})) 17644 { 17645 add_prev($text, $stack, "\@$macro" . $_); 17646 $_ = ''; 17647 next; 17648 } 17649 # @ at the end of line may protect the end of line even when 17650 # keeping texi 17651 if ($macro eq "\n") 17652 { 17653 $state->{'end_of_line_protected'} = 1; 17654 #print STDERR "PROTECTING END OF LINE\n"; 17655 } 17656 17657 add_prev($text, $stack, "\@$macro"); 17658 if ($text_macros{$macro} and $text_macros{$macro} eq 'raw') 17659 { 17660 $state->{'raw'} = $macro; 17661 push (@$stack, {'style' => $macro, 'text' => ''}); 17662 } 17663 next; 17664 } 17665 17666 # If we are removing texi, the following macros are not removed 17667 # as is but modified. So they are collected first, as if we were 17668 # in normal text 17669 17670 # a raw macro beginning 17671 if ($text_macros{$macro} and $text_macros{$macro} eq 'raw') 17672 { 17673 if (!$Texi2HTML::Config::format_in_paragraph{$macro}) 17674 { # close paragraph before verbatim (and tex if !L2H) 17675 close_paragraph($text, $stack, $state, $line_nr); 17676 } 17677 $state->{'raw'} = $macro; 17678 push (@$stack, {'style' => $macro, 'text' => ''}); 17679 return if (/^\s*$/); 17680 next; 17681 } 17682 my $simple_macro = 1; 17683 # An accent macro 17684 if (exists($Texi2HTML::Config::accent_map{$macro})) 17685 { 17686 push (@{$state->{'command_stack'}}, $macro); 17687 if (s/^(\S)//o) 17688 { 17689 add_prev($text, $stack, do_simple($macro, $1, $state, [ $1 ], $line_nr)); 17690 } 17691 else 17692 { # The accent is at end of line 17693 add_prev($text, $stack, do_text($macro, $state)); 17694 } 17695 pop @{$state->{'command_stack'}}; 17696 } 17697 # an @-command which should be like @command{}. We handle it... 17698 elsif ($::things_map_ref->{$macro}) 17699 { 17700 echo_warn ("$macro requires {}", $line_nr); 17701 add_prev($text, $stack, do_simple($macro, '', $state)); 17702 } 17703 # an @-command like @command 17704 elsif (defined($::simple_map_ref->{$macro})) 17705 { 17706 add_prev($text, $stack, do_simple($macro, '', $state)); 17707 } 17708 else 17709 { 17710 $simple_macro = 0; 17711 } 17712 if ($simple_macro) 17713 {# if the macro didn't triggered a paragraph start it might now 17714 begin_paragraph($stack, $state) if 17715 ($no_line_macros{$macro} and !no_paragraph($state,$_)); 17716 next; 17717 } 17718 # the following macros are modified or ignored if we are 17719 # removing texi, and they are not handled like macros in text 17720 if ($state->{'remove_texi'}) 17721 { 17722 # handle specially some macros 17723 if ((($macro =~ /^(\w+?)index$/) and ($1 ne 'print')) or 17724 ($macro eq 'itemize') or ($macro =~ /^(|v|f)table$/) 17725 or ($macro eq 'multitable') or ($macro eq 'quotation')) 17726 { 17727 return; 17728 } 17729 elsif ($macro eq 'enumerate') 17730 { 17731 my $spec; 17732 ($_, $spec) = parse_enumerate ($_); 17733 return if (/^\s*$/); 17734 next; 17735 } 17736 elsif (defined($Texi2HTML::Config::def_map{$macro})) 17737 { 17738 my ($style, $category, $name, $type, $class, $arguments); 17739 ($style, $category, $name, $type, $class, $arguments) = parse_def($macro, $_, $line_nr); 17740 # FIXME -- --- ''... lead to simple text in texi2html 17741 # while they are kept as is in html coments by makeinfo 17742 $category = remove_texi($category) if (defined($category)); 17743 $name = remove_texi($name) if (defined($name)); 17744 $type = remove_texi($type) if (defined($type)); 17745 $class = remove_texi($class) if (defined($class)); 17746 $arguments = remove_texi($arguments) if (defined($arguments)); 17747 chomp($arguments); 17748 add_prev($text, $stack, &$Texi2HTML::Config::def_line_no_texi($category, $name, $type, $arguments)); 17749 return; 17750 } 17751 17752 # ignore other macros 17753 next; 17754 } 17755 17756 # handle the other macros, in the context of some normal text 17757 if (($macro =~ /^(\w+?)index$/) and ($1 ne 'print')) 17758 { 17759 add_prev($text, $stack, do_index_entry_label($macro,$state,$line_nr)); 17760 return; 17761 } 17762 if ($macro eq 'insertcopying') 17763 { 17764 close_paragraph($text, $stack, $state, $line_nr); 17765 add_prev($text, $stack, do_insertcopying($state)); 17766 # reopen a preformatted format if it was interrupted by the macro 17767 begin_paragraph ($stack, $state) if ($state->{'preformatted'}); 17768 return; 17769 } 17770 if ($macro =~ /^itemx?$/o or ($macro eq 'headitem')) 17771 { 17772 #print STDERR "ITEM: $_"; 17773 #dump_stack($text, $stack, $state); 17774 abort_empty_preformatted($stack, $state); 17775 # FIXME let the user be able not to close the paragraph 17776 close_paragraph($text, $stack, $state, $line_nr); 17777 # these functions return the format if in the right context 17778 my $format; 17779 if ($format = add_item($text, $stack, $state, $line_nr, $_)) 17780 { # handle lists 17781 } 17782 elsif ($format = add_term($text, $stack, $state, $line_nr)) 17783 {# handle table @item line 17784 } 17785 elsif ($format = add_line($text, $stack, $state, $line_nr)) 17786 {# handle table text 17787 } 17788 if ($format) 17789 { 17790 if (defined($format->{'prepended'})) 17791 { 17792 $_ = $format->{'prepended'} . ' ' . $_ if ($format->{'prepended'} ne ''); 17793 } 17794 if (defined($format->{'command'})) 17795 { 17796 open_arg($format->{'command'},0, $state); 17797 } 17798 next; 17799 } 17800 $format = add_row ($text, $stack, $state, $line_nr); # handle multitable 17801 unless ($format) 17802 { 17803 echo_warn ("\@$macro outside of table or list", $line_nr); 17804 next; 17805 } 17806 push @$stack, {'format' => 'row', 'text' => '', 'item_cmd' => $macro }; 17807 if ($format->{'max_columns'}) 17808 { 17809 push @$stack, {'format' => 'cell', 'text' => ''}; 17810 $format->{'cell'} = 1; 17811 17812 begin_paragraph_after_command($state,$stack,$macro,$_); 17813 } 17814 else 17815 { 17816 echo_warn ("\@$macro in empty multitable", $line_nr); 17817 } 17818 next; 17819 } 17820 if ($macro eq 'tab') 17821 { 17822 abort_empty_preformatted($stack, $state); 17823 # FIXME let the user be able not to close the paragraph 17824 close_paragraph($text, $stack, $state, $line_nr); 17825 my $format = add_cell ($text, $stack, $state); 17826 #print STDERR "tab, $format->{'cell'}, max $format->{'max_columns'}\n"; 17827 if (!$format) 17828 { 17829 echo_warn ("\@$macro outside of multitable", $line_nr); 17830 } 17831 elsif (!$format->{'max_columns'}) 17832 { 17833 echo_warn ("\@$macro in empty multitable", $line_nr); 17834 push @$stack, {'format' => 'null', 'text' => ''}; 17835 next; 17836 } 17837 elsif ($format->{'cell'} > $format->{'max_columns'}) 17838 { 17839 echo_warn ("too much \@$macro (multitable has only $format->{'max_columns'} column(s))", $line_nr); 17840 push @$stack, {'format' => 'null', 'text' => ''}; 17841 next; 17842 } 17843 else 17844 { 17845 push @$stack, {'format' => 'cell', 'text' => ''}; 17846 } 17847 begin_paragraph_after_command($state,$stack,$macro,$_); 17848 next; 17849 } 17850 # Macro opening a format (table, list, deff, example...) 17851 if ($format_type{$macro} and ($format_type{$macro} ne 'fake')) 17852 { 17853 unless ($Texi2HTML::Config::format_in_paragraph{$macro}) 17854 { 17855 close_paragraph($text, $stack, $state, $line_nr); 17856 } 17857 push (@{$state->{'command_stack'}}, $macro); 17858 if ($format_type{$macro} eq 'menu') 17859 { 17860 close_menu($text, $stack, $state, $line_nr); 17861 $state->{'menu'}++; 17862 } 17863 # A deff like macro 17864 if (defined($Texi2HTML::Config::def_map{$macro})) 17865 { 17866 my $top_format = top_format($stack); 17867 if (defined($top_format) and ("$top_format->{'format'}x" eq $macro)) 17868 { 17869 # the @DEFx macro has been put at the top of the 17870 # command_stack, although there is no real format opening 17871 pop @{$state->{'command_stack'}}; 17872 $macro =~ s/x$//o; 17873 if (!$state->{'deff_line'}) 17874 {# DEFx macro within a DEF paragraph 17875 close_stack($text, $stack, $state, $line_nr, undef, 'deff_item'); 17876 my $format_ref = pop @$stack; 17877 add_prev($text, $stack, &$Texi2HTML::Config::def_item($format_ref->{'text'})); 17878 } 17879 #print STDERR "DEFx $macro\n"; 17880 } 17881 else 17882 { 17883 # The previous @def command isn't the same @def 17884 # command. We begin the item for the previous @def 17885 # command and immediately open the new one. 17886 begin_deff_item($stack, $state, 1) if ($state->{'deff_line'}); 17887 $macro =~ s/x$//o; 17888 # we remove what is on the stack and put it back, 17889 # to make sure that it is the form without x. 17890 pop @{$state->{'command_stack'}}; 17891 push @{$state->{'command_stack'}}, $macro; 17892 #print STDERR "DEF begin $macro\n"; 17893 push @$stack, { 'format' => $macro, 'text' => '' }; 17894 } 17895 #print STDERR "BEGIN_DEFF $macro\n"; 17896 #dump_stack ($text, $stack, $state); 17897 $state->{'deff_line'}->{'command'} = $macro; 17898 my ($style, $category, $name, $type, $class, $arguments); 17899 ($style, $category, $name, $type, $class, $_) = parse_def($macro, $_, $line_nr); 17900 #print STDERR "AFTER parse_def $_"; 17901 # duplicate_state? 17902 $state->{'deff_line'}->{'style'} = $style; 17903 $state->{'deff_line'}->{'category'} = substitute_line($category) if (defined($category)); 17904 $state->{'deff_line'}->{'category'} = '' if (!defined($category)); 17905 # FIXME -- --- ''... are transformed to entities by 17906 # makeinfo. It may be wrong. 17907 $state->{'deff_line'}->{'name'} = substitute_line($name) if (defined($name)); 17908 $state->{'deff_line'}->{'name'} = '' if (!defined($name)); 17909 $state->{'deff_line'}->{'type'} = substitute_line($type) if (defined($type)); 17910 $state->{'deff_line'}->{'class'} = substitute_line($class) if (defined($class)); 17911 # the remaining of the line (the argument) 17912 #print STDERR "DEFF: open_cmd_line do_def_line $_"; 17913 open_cmd_line($stack, $state, ['keep'], \&do_def_line); 17914 next; 17915 } 17916 elsif (exists ($Texi2HTML::Config::complex_format_map->{$macro})) 17917 { # handle menu if SIMPLE_MENU. see texi2html.init 17918 $state->{'preformatted'}++; 17919 my $complex_format = $Texi2HTML::Config::complex_format_map->{$macro}; 17920 my $format = { 'format' => $macro, 'text' => '', 'pre_style' => $complex_format->{'pre_style'} }; 17921 my $class = $macro; 17922 $class = $complex_format->{'class'} if (defined($complex_format->{'class'})); 17923 push @{$state->{'preformatted_stack'}}, {'pre_style' =>$complex_format->{'pre_style'}, 'class' => $class }; 17924 push @$stack, $format; 17925 unless ($Texi2HTML::Config::format_in_paragraph{$macro}) 17926 { 17927 begin_paragraph($stack, $state); 17928 } 17929 } 17930 elsif ($Texi2HTML::Config::paragraph_style{$macro}) 17931 { 17932 push (@$stack, { 'format' => $macro, 'text' => '' }); 17933 begin_paragraph_after_command($state,$stack,$macro,$_); 17934 push @{$state->{'paragraph_style'}}, $macro; 17935 if ($macro eq 'center') 17936 { 17937 # @center may be in a weird state with regard with 17938 # nesting, so we put it on the bottom of the stack 17939 pop @{$state->{'command_stack'}}; 17940 unshift @{$state->{'command_stack'}}, $macro; 17941 # for similar reasons, we may have a bad stack nesting 17942 # which results in } after a closing. For example 17943 # @center @samp{something @center end of samp} 17944 # results to samp being kept in the 'command_stack' 17945 17946 # we keep the end of line for @center, to 17947 # avoid the return in case there is only spaces 17948 # which occurs for all the format commmands followed by 17949 # spaces only 17950 next; 17951 } 17952 } 17953 elsif ($format_type{$macro} eq 'menu') 17954 { 17955 # if $Texi2HTML::Config::SIMPLE_MENU we won't get there 17956 # as the menu is a complex format in that case, so it 17957 # is handled above 17958 push @$stack, { 'format' => $macro, 'text' => '' }; 17959 if ($state->{'preformatted'}) 17960 { 17961 # Start a fake complex format in order to have a given pre style 17962 $state->{'preformatted'}++; 17963 push @$stack, { 'format' => 'menu_preformatted', 'text' => '', 'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE }; 17964 push @{$state->{'preformatted_stack'}}, {'pre_style' => $Texi2HTML::Config::MENU_PRE_STYLE, 'class' => 'menu-preformatted' }; 17965 } 17966 } 17967 elsif (($format_type{$macro} eq 'list') or ($format_type{$macro} eq 'table')) 17968 { 17969 my $format; 17970 #print STDERR "LIST_TABLE $macro\n"; 17971 #dump_stack($text, $stack, $state); 17972 if (($macro eq 'itemize') or ($macro =~ /^(|v|f)table$/)) 17973 { 17974 my $command; 17975 my $prepended; 17976 ($prepended, $command) = parse_format_command($_,$macro); 17977 $format = { 'format' => $macro, 'text' => '', 'command' => $command, 'prepended' => $prepended, 'term' => 0 }; 17978 $_ = ''; 17979 } 17980 elsif ($macro eq 'enumerate') 17981 { 17982 my $spec; 17983 ($_, $spec) = parse_enumerate ($_); 17984 $spec = 1 if (!defined($spec)); 17985 $format = { 'format' => $macro, 'text' => '', 'spec' => $spec, 'item_nr' => 0 }; 17986 } 17987 elsif ($macro eq 'multitable') 17988 { 17989 my $max_columns = parse_multitable ($_, $line_nr); 17990 if (!$max_columns) 17991 { 17992 echo_warn ("empty multitable", $line_nr); 17993 $max_columns = 0; 17994 } 17995 $format = { 'format' => $macro, 'text' => '', 'max_columns' => $max_columns, 'cell' => 1 }; 17996 } 17997 $format->{'first'} = 1; 17998 $format->{'paragraph_number'} = 0; 17999 push @$stack, $format; 18000 push @{$state->{'table_list_stack'}}, $format; 18001 if ($macro =~ /^(|v|f)table$/) 18002 { 18003 push @$stack, { 'format' => 'line', 'text' => ''}; 18004 } 18005 elsif ($macro eq 'multitable') 18006 { 18007 if ($format->{'max_columns'}) 18008 { 18009 push @$stack, { 'format' => 'row', 'text' => '', 'item_cmd' => $macro }; 18010 push @$stack, { 'format' => 'cell', 'text' => ''}; 18011 } 18012 else 18013 { 18014 # multitable without row... We use the special null 18015 # format which content is ignored 18016 push @$stack, { 'format' => 'null', 'text' => ''}; 18017 push @$stack, { 'format' => 'null', 'text' => ''}; 18018 } 18019 } 18020 if ($format_type{$macro} eq 'list') 18021 { 18022 push @$stack, { 'format' => 'item', 'text' => ''}; 18023 } 18024 begin_paragraph_after_command($state,$stack,$macro,$_) 18025 if ($macro ne 'multitable'); 18026 return if ($format_type{$macro} eq 'table' or $macro eq 'itemize'); 18027 } 18028 elsif ($macro eq 'float' or $macro eq 'quotation') 18029 { 18030 push @$stack, {'format' => $macro, 'text' => '' }; 18031 if ($macro eq 'float') 18032 { 18033 open_cmd_line($stack, $state, ['keep','keep'], \&do_float_line); 18034 } 18035 elsif ($macro eq 'quotation') 18036 { 18037 open_cmd_line($stack, $state, ['keep'], \&do_quotation_line); 18038 } 18039 #dump_stack($text, $stack, $state); 18040 next; 18041 } 18042 # keep this one at the end as there are some other formats 18043 # which are also in format_map 18044 elsif (defined($Texi2HTML::Config::format_map{$macro}) or ($format_type{$macro} eq 'cartouche')) 18045 { 18046 push @$stack, { 'format' => $macro, 'text' => '' }; 18047 begin_paragraph_after_command($state,$stack,$macro,$_); 18048 } 18049 return if (/^\s*$/); 18050 next; 18051 } 18052 $_ = do_unknown ($macro, $_, $text, $stack, $state, $line_nr); 18053 next; 18054 } 18055 elsif(s/^([^{}@,]*)\@([^\s\}\{\@]*)//o) 18056 { # A macro with a character which shouldn't appear in macro name 18057 add_prev($text, $stack, do_text($1, $state)); 18058 $_ = do_unknown ($2, $_, $text, $stack, $state, $line_nr); 18059 next; 18060 } 18061 elsif (s/^([^{},]*)([{}])//o or (@$stack and 18062 defined($stack->[-1]->{'style'}) and 18063 ($stack->[-1]->{'style'} eq 'cmd_line') and /^([^{},]*)$/o)) 18064 { 18065 my $leading_text = $1; 18066 my $brace = $2; 18067 add_prev($text, $stack, do_text($leading_text, $state)); 18068 if (defined($brace) and ($brace eq '{')) 18069 { 18070 add_prev($text, $stack, do_text('{',$state)); 18071 unless ($state->{'keep_texi'} or $state->{'remove_texi'}) 18072 { 18073 echo_error ("'{' without macro. Before: $_", $line_nr); 18074 } 18075 } 18076 elsif (defined($brace) and ($brace eq '}') and 18077 (!@$stack or (!defined($stack->[-1]->{'style'})) 18078 # a non empty stack, but with 'cmd_line' as first item on the stack 18079 # is like an empty stack 18080 or ($stack->[-1]->{'style'} eq 'cmd_line'))) 18081 { 18082 if ($state->{'keep_texi'}) 18083 { 18084 add_prev($text, $stack, '}'); 18085 } 18086 else 18087 { 18088 echo_error("'}' without opening '{' before: $_", $line_nr); 18089 } 18090 } 18091 else 18092 { # A @-command{ ...} is closed 18093 my $style = pop @$stack; 18094 my $command = $style->{'style'}; 18095 my $result; 18096 if (ref($::style_map_ref->{$command}) eq 'HASH') 18097 { 18098 push (@{$style->{'args'}}, $style->{'text'}); 18099 $style->{'fulltext'} .= $style->{'text'}; 18100 #my $number = 0; 18101 #foreach my $arg(@{$style->{'args'}}) 18102 #{ 18103 #print STDERR " $number: $arg\n"; 18104 # $number++; 18105 #} 18106 $style->{'text'} = $style->{'fulltext'}; 18107 $state->{'keep_texi'} = 0 if ( 18108 ($::style_map_ref->{$command}->{'args'}->[$style->{'arg_nr'}] eq 'keep') 18109 and ($state->{'keep_nr'} == 1)); 18110 } 18111 $state->{'no_paragraph'}-- if ($no_paragraph_macro{$command}); 18112 if ($command) 18113 { 18114 $style->{'no_close'} = 1 if ($state->{'no_close'}); 18115 if ($::style_map_ref->{$command} and (defined($style_type{$command})) and ((!$style->{'no_close'} and ($style_type{$command} eq 'style')) or ($style_type{$command} eq 'accent'))) 18116 { 18117 my $style_command = pop @{$state->{'command_stack'}}; 18118 if ($style_command ne $command) 18119 { 18120 print STDERR "Bug: $style_command on 'command_stack', not $command\n"; 18121 push @$stack, $style; 18122 push @{$state->{'command_stack'}}, $style_command; 18123 print STDERR "Stacks before pop top:\n"; 18124 dump_stack($text, $stack, $state); 18125 pop @$stack; 18126 } 18127 } 18128 if ($state->{'keep_texi'}) 18129 { # don't expand @-commands in anchor, refs... 18130 close_arg ($command, $style->{'arg_nr'}, $state); 18131 $result = '@' . $command . '{' . $style->{'text'} . '}'; 18132 } 18133 else 18134 { 18135 $result = do_simple($command, $style->{'text'}, $state, $style->{'args'}, $line_nr, $style->{'no_open'}, $style->{'no_close'}); 18136 if ($state->{'code_style'} < 0) 18137 { 18138 echo_error ("Bug: negative code_style: $state->{'code_style'}, line:$_", $line_nr); 18139 } 18140 } 18141 } 18142 else 18143 { 18144 print STDERR "Bug: empty style in pass_text\n"; 18145 } 18146 add_prev($text, $stack, $result); 18147 if ($command eq 'cmd_line') 18148 { 18149 if ($state->{'deff_line'}) 18150 { 18151#print STDERR "DO DEFF $state->{'deff_line'}->{'command'} $state->{'deff_line'}->{'arguments'}\n"; 18152 my $command = $state->{'deff_line'}->{'command'}; 18153 my $def_style = $state->{'deff_line'}->{'style'}; 18154 my $category = $state->{'deff_line'}->{'category'}; 18155 my $class = $state->{'deff_line'}->{'class'}; 18156 my $type = $state->{'deff_line'}->{'type'}; 18157 my $name = $state->{'deff_line'}->{'name'}; 18158 #my $arguments = $state->{'deff'}->{'arguments'}; 18159 my $arguments; 18160 $arguments = substitute_line($state->{'deff_line'}->{'arguments'}) if (defined($state->{'deff_line'}->{'arguments'})); 18161 18162 $category = &$Texi2HTML::Config::definition_category($category, $class, $def_style); 18163 my $index_label = do_index_entry_label($command, $state,$line_nr); 18164 add_prev($text, $stack, &$Texi2HTML::Config::def_line($category, $name, $type, $arguments, $index_label)); 18165 } 18166 elsif ($state->{'preformatted'}) 18167 { # inconditionally begin a preformatted section for 18168 # non @def* commands (currently @float and @quotation) 18169 # for @def* it is done in begin_deff_item 18170 begin_paragraph($stack, $state); 18171 } 18172 $state->{'no_paragraph'}--; 18173 return; 18174 } 18175 } 18176 } 18177 elsif (s/^([^,]*)[,]//o) 18178 { 18179 add_prev($text, $stack, do_text($1, $state)); 18180 if (@$stack and defined($stack->[-1]->{'style'}) 18181 and (ref($::style_map_ref->{$stack->[-1]->{'style'}}) eq 'HASH')) 18182 { 18183 my $macro = $stack->[-1]->{'style'}; 18184 my $style_args = $::style_map_ref->{$macro}->{'args'}; 18185 if (defined($style_args->[$stack->[-1]->{'arg_nr'} + 1])) 18186 { 18187 push (@{$stack->[-1]->{'args'}}, $stack->[-1]->{'text'}); 18188 $stack->[-1]->{'fulltext'} .= $stack->[-1]->{'text'} . do_text(',', $state); 18189 $stack->[-1]->{'text'} = ''; 18190 close_arg ($macro, $stack->[-1]->{'arg_nr'}, $state); 18191 $stack->[-1]->{'arg_nr'}++; 18192 open_arg ($macro, $stack->[-1]->{'arg_nr'}, $state); 18193 next; 18194 } 18195 } 18196 add_prev($text, $stack, do_text(',', $state)); 18197 } 18198 else 18199 { # no macro nor '}', but normal text 18200 add_prev($text, $stack, do_text($_, $state)); 18201 #print STDERR "END LINE:$_!!!\n"; 18202 #dump_stack($text, $stack, $state); 18203 18204 # @item line is closed by end of line 18205 add_term($text, $stack, $state, $line_nr); 18206 18207 # @center is closed at the end of line. When a @-command which 18208 # keeps the texi as is happens on the @center line, the @center 18209 # is closed at the end of line appearing after the @-command 18210 # closing (for example @ref, @footnote). 18211 18212 # when 'closing_center' is true we don't retry to close 18213 # the @center line. 18214 if ($state->{'paragraph_style'}->[-1] eq 'center' 18215 and !$state->{'closing_center'} and !$state->{'keep_texi'}) 18216 { 18217 $state->{'closing_center'} = 1; 18218 unless ($Texi2HTML::Config::format_in_paragraph{'center'}) 18219 { 18220 close_paragraph($text, $stack, $state, $line_nr); 18221 } 18222 close_stack($text, $stack, $state, $line_nr, undef, 'center'); 18223 delete $state->{'closing_center'}; 18224 my $center = pop @$stack; 18225 add_prev($text, $stack, &$Texi2HTML::Config::paragraph_style_command('center',$center->{'text'})); 18226 my $top_paragraph_style = pop @{$state->{'paragraph_style'}}; 18227 # center is at the bottom of the comand_stack because it 18228 # may be nested in many way 18229 my $bottom_command_stack = shift @{$state->{'command_stack'}}; 18230 print STDERR "Bug: closing center, top_paragraph_style: $top_paragraph_style, bottom_command_stack: $bottom_command_stack.\n" 18231 if ($bottom_command_stack ne 'center' or $top_paragraph_style ne 'center'); 18232 $_ = ''; 18233 next; 18234 } 18235 last; 18236 } 18237 } 18238 return 1; 18239} 18240 18241sub open_arg($$$) 18242{ 18243 my $macro = shift; 18244 my $arg_nr = shift; 18245 my $state = shift; 18246 if (ref($::style_map_ref->{$macro}) eq 'HASH') 18247 { 18248 my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr]; 18249 if ($arg eq 'code' and !$state->{'keep_texi'}) 18250 { 18251 $state->{'code_style'}++; 18252 } 18253 elsif ($arg eq 'keep') 18254 { 18255 $state->{'keep_nr'}++; 18256 $state->{'keep_texi'} = 1; 18257 } 18258 } 18259 elsif ($code_style_map{$macro} and !$state->{'keep_texi'}) 18260 { 18261 $state->{'code_style'}++; 18262 } 18263} 18264 18265sub close_arg($$$) 18266{ 18267 my $macro = shift; 18268 my $arg_nr = shift; 18269 my $state = shift; 18270 if (ref($::style_map_ref->{$macro}) eq 'HASH') 18271 { 18272 my $arg = $::style_map_ref->{$macro}->{'args'}->[$arg_nr]; 18273 if ($arg eq 'code' and !$state->{'keep_texi'}) 18274 { 18275 $state->{'code_style'}--; 18276 } 18277 elsif ($arg eq 'keep') 18278 { 18279 $state->{'keep_nr'}--; 18280 $state->{'keep_texi'} = 0 if ($state->{'keep_nr'} == 0); 18281 } 18282#print STDERR "c $arg_nr $macro $arg $state->{'code_style'}\n"; 18283 } 18284 elsif ($code_style_map{$macro} and !$state->{'keep_texi'}) 18285 { 18286 $state->{'code_style'}--; 18287 } 18288} 18289 18290# add a special style on the top of the stack. This is used for commands 18291# that extend until the end of the line 18292sub open_cmd_line($$$$) 18293{ 18294 my $stack = shift; 18295 my $state = shift; 18296 my $args = shift; 18297 my $function = shift; 18298 push @$stack, {'style' => 'cmd_line', 'text' => '', 'arg_nr' => 0}; 18299 foreach my $hash (\%Texi2HTML::Config::style_map, \%Texi2HTML::Config::style_map_pre, \%Texi2HTML::Config::style_map_texi, \%Texi2HTML::Config::simple_format_style_map_texi) 18300 { 18301 $hash->{'cmd_line'}->{'args'} = $args; 18302 $hash->{'cmd_line'}->{'function'} = $function; 18303 } 18304 $state->{'no_paragraph'}++; 18305 open_arg ('cmd_line', 0, $state); 18306} 18307 18308# finish @item line in @*table 18309sub add_term($$$$;$) 18310{ 18311 my $text = shift; 18312 my $stack = shift; 18313 my $state = shift; 18314 my $line_nr = shift; 18315 my $end = shift; 18316 return unless (exists ($state->{'table_list_stack'})); 18317 my $format = $state->{'table_list_stack'}->[-1]; 18318 return unless (($format_type{$format->{'format'}} eq 'table') and ($format->{'format'} ne 'multitable' ) and $format->{'term'}); 18319 #print STDERR "ADD_TERM\n"; 18320 # we set 'term' = 0 early such that if we encounter an end of line 18321 # during close_stack we don't try to do the term once more 18322 $state->{'table_list_stack'}->[-1]->{'term'} = 0; 18323 # it is the first paragraph for the term. 18324 $format->{'paragraph_number'} = 0; 18325 18326 #dump_stack($text, $stack, $state); 18327 close_stack($text, $stack, $state, $line_nr, undef, 'term'); 18328 my $term = pop @$stack; 18329 my $command_formatted; 18330 chomp ($term->{'text'}); 18331 if (exists($::style_map_ref->{$format->{'command'}}) and 18332 !exists($Texi2HTML::Config::special_list_commands{$format->{'format'}}->{$format->{'command'}}) and ($style_type{$format->{'command'}} eq 'style')) 18333 { 18334 my $leading_spaces = ''; 18335 my $trailing_spaces = ''; 18336 $term->{'text'} =~ s/^(\s*)//o; 18337 $leading_spaces = $1 if (defined($1)); 18338 $term->{'text'} =~ s/(\s*)$//o; 18339 $trailing_spaces = $1 if (defined($1)); 18340 $term->{'text'} = do_simple($format->{'command'}, $term->{'text'}, $state, [$term->{'text'}]); 18341 $term->{'text'} = $leading_spaces. $term->{'text'} .$trailing_spaces; 18342 } 18343 elsif (exists($::things_map_ref->{$format->{'command'}})) 18344 { 18345 $command_formatted = do_simple($format->{'command'}, '', $state); 18346 } 18347 my $index_label; 18348 if ($format->{'format'} =~ /^(f|v)/o) 18349 { 18350 $index_label = do_index_entry_label($format->{'format'}, $state,$line_nr); 18351 print STDERR "Bug: no index entry for $text" unless defined($index_label); 18352 } 18353 add_prev($text, $stack, &$Texi2HTML::Config::table_item($term->{'text'}, $index_label,$format->{'format'},$format->{'command'}, $command_formatted,$state->{'command_stack'})); 18354 unless ($end) 18355 { 18356 push (@$stack, { 'format' => 'line', 'text' => '' }); 18357 begin_paragraph($stack, $state) if ($state->{'preformatted'}); 18358 } 18359 return $format; 18360} 18361 18362sub add_row($$$$) 18363{ 18364 my $text = shift; 18365 my $stack = shift; 18366 my $state = shift; 18367 my $line_nr = shift; 18368 my $format = $state->{'table_list_stack'}->[-1]; 18369 return unless ($format->{'format'} eq 'multitable'); 18370 if ($format->{'cell'} > $format->{'max_columns'}) 18371 { 18372 close_stack($text, $stack, $state, $line_nr, undef, 'null'); 18373 pop @$stack; 18374 } 18375 unless ($format->{'max_columns'}) 18376 { # empty multitable 18377 pop @$stack; # pop 'row' 18378 return $format; 18379 } 18380 if ($format->{'first'}) 18381 { # first row 18382 $format->{'first'} = 0; 18383 #dump_stack($text, $stack, $state); 18384 #if ($stack->[-1]->{'format'} and ($stack->[-1]->{'format'} eq 'paragraph') and ($stack->[-1]->{'text'} =~ /^\s*$/) and ($format->{'cell'} == 1)) 18385 if ($stack->[-1]->{'format'} and ($stack->[-1]->{'format'} eq 'cell') and ($stack->[-1]->{'text'} =~ /^\s*$/) and ($format->{'cell'} == 1)) 18386 { 18387 pop @$stack; 18388 pop @$stack; 18389 #pop @$stack; 18390 return $format; 18391 } 18392 } 18393 add_cell($text, $stack, $state); 18394 my $row = pop @$stack; 18395 add_prev($text, $stack, &$Texi2HTML::Config::row($row->{'text'}, $row->{'item_cmd'})); 18396 return $format; 18397} 18398 18399sub add_cell($$$$) 18400{ 18401 my $text = shift; 18402 my $stack = shift; 18403 my $state = shift; 18404 my $line_nr = shift; 18405 my $format = $state->{'table_list_stack'}->[-1]; 18406 return unless ($format->{'format'} eq 'multitable'); 18407 if ($format->{'cell'} <= $format->{'max_columns'}) 18408 { 18409 close_stack($text, $stack, $state, $line_nr, undef, 'cell'); 18410 my $cell = pop @$stack; 18411 my $row = top_stack($stack); 18412 print STDERR "Bug: top_stack of cell not a row\n" if (!defined($row) or !defined($row->{'format'}) or ($row->{'format'} ne 'row')); 18413 add_prev($text, $stack, &$Texi2HTML::Config::cell($cell->{'text'}, $row->{'item_cmd'})); 18414 $format->{'cell'}++; 18415 } 18416 return $format; 18417} 18418 18419sub add_line($$$$;$) 18420{ 18421 my $text = shift; 18422 my $stack = shift; 18423 my $state = shift; 18424 my $line_nr = shift; 18425 my $end = shift; 18426 my $format = $state->{'table_list_stack'}->[-1]; 18427 return unless ($format_type{$format->{'format'}} eq 'table' and ($format->{'format'} ne 'multitable') and ($format->{'term'} == 0)); 18428 #print STDERR "ADD_LINE\n"; 18429 #dump_stack($text, $stack, $state); 18430 # as in pre the end of line are kept, we must explicitely abort empty 18431 # preformatted, close_stack doesn't abort the empty preformatted regions. 18432 abort_empty_preformatted($stack, $state) if ($format->{'first'}); 18433 close_stack($text, $stack, $state, $line_nr, undef, 'line'); 18434 my $line = pop @$stack; 18435 $format->{'paragraph_number'} = 0; 18436 my $first = 0; 18437 $first = 1 if ($format->{'first'}); 18438 if ($first) 18439 { 18440 $format->{'first'} = 0; 18441 # we must have <dd> or <dt> following <dl> thus we do a 18442 # &$Texi2HTML::Config::table_line here too, although it could have 18443 # been a normal paragraph. 18444 add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'})) if ($line->{'text'} =~ /\S/o); 18445 } 18446 else 18447 { 18448 add_prev($text, $stack, &$Texi2HTML::Config::table_line($line->{'text'})); 18449 } 18450 unless($end) 18451 { 18452 push (@$stack, { 'format' => 'term', 'text' => '' }); 18453 } 18454 $format->{'term'} = 1; 18455 return $format; 18456} 18457 18458# finish @enumerate or @itemize @item 18459sub add_item($$$$;$) 18460{ 18461 my $text = shift; 18462 my $stack = shift; 18463 my $state = shift; 18464 my $line_nr = shift; 18465 my $line = shift; 18466 my $end = shift; 18467 my $format = $state->{'table_list_stack'}->[-1]; 18468 return unless ($format_type{$format->{'format'}} eq 'list'); 18469 #print STDERR "ADD_ITEM: \n"; 18470 # as in pre the end of line are kept, we must explicitely abort empty 18471 # preformatted, close_stack doesn't do that. 18472 abort_empty_preformatted($stack, $state) if ($format->{'first'}); 18473 close_stack($text, $stack, $state, $line_nr, undef, 'item'); 18474 $format->{'paragraph_number'} = 0; 18475 if ($format->{'format'} eq 'enumerate') 18476 { 18477 $format->{'number'} = ''; 18478 my $spec = $format->{'spec'}; 18479 $format->{'item_nr'}++; 18480 if ($spec =~ /^[0-9]$/) 18481 { 18482 $format->{'number'} = $spec + $format->{'item_nr'} - 1; 18483 } 18484 else 18485 { 18486 my $base_letter = ord('a'); 18487 $base_letter = ord('A') if (ucfirst($spec) eq $spec); 18488 18489 my @letter_ords = decompose(ord($spec) - $base_letter + $format->{'item_nr'} - 1, 26); 18490 foreach my $ord (@letter_ords) 18491 {# WARNING we go directly to 'ba' after 'z', and not 'aa' 18492 #because 'ba' is 1,0 and 'aa' is 0,0. 18493 $format->{'number'} = chr($base_letter + $ord) . $format->{'number'}; 18494 } 18495 } 18496 } 18497 18498 #dump_stack ($text, $stack, $state); 18499 my $item = pop @$stack; 18500 # the element following ol or ul must be li. Thus even though there 18501 # is no @item we put a normal item. 18502 18503 # don't do an item if it is the first and it is empty 18504 if (!$format->{'first'} or ($item->{'text'} =~ /\S/o)) 18505 { 18506 my $formatted_command; 18507 if (defined($format->{'command'}) and exists($::things_map_ref->{$format->{'command'}})) 18508 { 18509 $formatted_command = do_simple($format->{'command'}, '', $state); 18510 } 18511 #chomp($item->{'text'}); 18512 add_prev($text, $stack, &$Texi2HTML::Config::list_item($item->{'text'},$format->{'format'},$format->{'command'}, $formatted_command, $format->{'item_nr'}, $format->{'spec'}, $format->{'number'})); 18513 } 18514 if ($format->{'first'}) 18515 { 18516 $format->{'first'} = 0; 18517 } 18518 18519 # Now prepare the new item 18520 unless($end) 18521 { 18522 push (@$stack, { 'format' => 'item', 'text' => '' }); 18523 begin_paragraph($stack, $state) unless (!$state->{'preformatted'} and no_line($line)); 18524 } 18525 return $format; 18526} 18527 18528# format ``simple'' macros, that is macros without arg or style macros 18529sub do_simple($$$;$$$$) 18530{ 18531 my $macro = shift; 18532 my $text = shift; 18533 my $state = shift; 18534 my $args = shift; 18535 my $line_nr = shift; 18536 my $no_open = shift; 18537 my $no_close = shift; 18538 18539 my $arg_nr = 0; 18540 $arg_nr = @$args - 1 if (defined($args)); 18541 18542#print STDERR "DO_SIMPLE $macro $arg_nr $args @$args\n" if (defined($args)); 18543 if (defined($::simple_map_ref->{$macro})) 18544 { 18545 # \n may in certain circumstances, protect end of lines 18546 if ($macro eq "\n") 18547 { 18548 $state->{'end_of_line_protected'} = 1; 18549 #print STDERR "PROTECTING END OF LINE\n"; 18550 } 18551 if ($state->{'keep_texi'}) 18552 { 18553 return "\@$macro"; 18554 } 18555 elsif ($state->{'remove_texi'}) 18556 { 18557#print STDERR "DO_SIMPLE remove_texi $macro\n"; 18558 return $::simple_map_texi_ref->{$macro}; 18559 } 18560 elsif ($state->{'preformatted'}) 18561 { 18562 return $::simple_map_pre_ref->{$macro}; 18563 } 18564 else 18565 { 18566 return $::simple_map_ref->{$macro}; 18567 } 18568 } 18569 if (defined($::things_map_ref->{$macro})) 18570 { 18571 my $result; 18572 if ($state->{'keep_texi'}) 18573 { 18574 $result = "\@$macro" . '{}'; 18575 } 18576 elsif ($state->{'remove_texi'}) 18577 { 18578 $result = $::texi_map_ref->{$macro}; 18579#print STDERR "DO_SIMPLE remove_texi texi_map $macro\n"; 18580 } 18581 elsif ($state->{'preformatted'}) 18582 { 18583 $result = $::pre_map_ref->{$macro}; 18584 } 18585 else 18586 { 18587 $result = $::things_map_ref->{$macro}; 18588 } 18589 return $result . $text; 18590 } 18591 elsif (defined($::style_map_ref->{$macro})) 18592 { 18593 if ($state->{'keep_texi'}) 18594 { 18595 return "\@$macro" . '{' . $text . '}'; 18596 } 18597 else 18598 { 18599 my $style; 18600 my $result; 18601 if ($state->{'remove_texi'}) 18602 { 18603#print STDERR "REMOVE $macro, $style_map_texi_ref->{$macro}, fun $style_map_texi_ref->{$macro}->{'function'} remove cmd " . \&Texi2HTML::Config::t2h_remove_command . " ascii acc " . \&t2h_default_ascii_accent; 18604 $style = $::style_map_texi_ref->{$macro}; 18605 } 18606 elsif ($state->{'preformatted'}) 18607 { 18608 $style = $::style_map_pre_ref->{$macro}; 18609 } 18610 else 18611 { 18612 $style = $::style_map_ref->{$macro}; 18613 } 18614 if (defined($style)) 18615 { # known style 18616 $result = &$Texi2HTML::Config::style($style, $macro, $text, $args, $no_close, $no_open, $line_nr, $state, $state->{'command_stack'}); 18617 } 18618 if (!$no_close) 18619 { 18620 close_arg($macro,$arg_nr, $state); 18621 } 18622 return $result; 18623 } 18624 } 18625 elsif ($macro =~ /^special_(\w+)_(\d+)$/o) 18626 { 18627 my $style = $1; 18628 my $count = $2; 18629 print STDERR "Bug? text in \@$macro not empty.\n" if ($text ne ''); 18630 if ($state->{'keep_texi'}) 18631 {# text should be empty 18632 return "\@$macro" . '{' . $text . '}'; 18633 } 18634 if (defined($Texi2HTML::Config::command_handler{$style}) and 18635 defined($Texi2HTML::Config::command_handler{$style}->{'expand'})) 18636 { 18637 my $struct_count = 1+ $special_commands{$style}->{'max'} - $special_commands{$style}->{'count'}; 18638 if (($count != $struct_count) and $T2H_DEBUG) 18639 { 18640 print STDERR "count $count in \@special $style and structure $struct_count differ\n"; 18641 } 18642 $special_commands{$style}->{'count'}--; 18643 } 18644 my $result = $Texi2HTML::Config::command_handler{$style}->{'expand'} 18645 ($style,$count,$state,$text); 18646 $result = '' if (!defined($result)); 18647 return $result; 18648 } 18649 # Unknown macro 18650 my $result = ''; 18651 my ($done, $result_text, $message) = &$Texi2HTML::Config::unknown_style($macro, $text,$state); 18652 if ($done) 18653 { 18654 echo_warn($message, $line_nr) if (defined($message)); 18655 if (defined($result_text)) 18656 { 18657 $result = $result_text; 18658 } 18659 } 18660 else 18661 { 18662 unless ($no_open) 18663 { # we warn only if no_open is true, i.e. it is the first time we 18664 # close the macro for a multiline macro 18665 echo_warn ("Unknown command with braces `\@$macro'", $line_nr); 18666 $result = do_text("\@$macro") . "{"; 18667 } 18668 $result .= $text; 18669 $result .= '}' unless ($no_close); 18670 } 18671 return $result; 18672} 18673 18674sub do_unknown($$$$$$) 18675{ 18676 my $macro = shift; 18677 my $line = shift; 18678 my $text = shift; 18679 my $stack = shift; 18680 my $state = shift; 18681 my $line_nr = shift; 18682 #print STDERR "do_unknown: $macro ::: $line"; 18683 my ($result_line, $result, $result_text, $message) = &$Texi2HTML::Config::unknown($macro, $line,$stack,$state); 18684 if ($result) 18685 { 18686 add_prev ($text, $stack, $result_text) if (defined($result_text)); 18687 echo_warn($message, $line_nr) if (defined($message)); 18688 return $result_line; 18689 } 18690 else 18691 { 18692 echo_warn ("Unknown command `\@$macro' (left as is)", $line_nr); 18693 add_prev ($text, $stack, do_text("\@$macro")); 18694 return $line; 18695 } 18696} 18697 18698# used only during @macro processing 18699sub add_text($@) 18700{ 18701 my $string = shift; 18702 18703 return if (!defined($string)); 18704 foreach my $scalar_ref (@_) 18705 { 18706 next unless defined($scalar_ref); 18707 if (!defined($$scalar_ref)) 18708 { 18709 $$scalar_ref = $string; 18710 } 18711 else 18712 { 18713 $$scalar_ref .= $string; 18714 } 18715 return; 18716 } 18717} 18718 18719sub add_prev ($$$) 18720{ 18721 my $text = shift; 18722 my $stack = shift; 18723 my $string = shift; 18724 18725 unless (defined($text) and ref($text) eq "SCALAR") 18726 { 18727 die "text not a SCALAR ref: " . ref($text) . ""; 18728 } 18729 #if (!defined($stack) or (ref($stack) ne "ARRAY")) 18730 #{ 18731 # $string = $stack; 18732 # $stack = []; 18733 #} 18734 18735 return if (!defined($string)); 18736 if (@$stack) 18737 { 18738 $stack->[-1]->{'text'} .= $string; 18739 return; 18740 } 18741 18742 if (!defined($$text)) 18743 { 18744 $$text = $string; 18745 } 18746 else 18747 { 18748 $$text .= $string; 18749 } 18750} 18751 18752sub close_stack_texi_structure($$$$) 18753{ 18754 my $text = shift; 18755 my $stack = shift; 18756 my $state = shift; 18757 my $line_nr = shift; 18758 18759 return undef unless (@$stack or $state->{'raw'} or $state->{'macro'} or $state->{'macro_name'} or $state->{'ignored'}); 18760 18761 #print STDERR "close_stack_texi_structure\n"; 18762 #dump_stack ($text, $stack, $state); 18763 my $stack_level = $#$stack + 1; 18764 my $string = ''; 18765 18766 if ($state->{'ignored'}) 18767 { 18768 $string .= "\@end $state->{'ignored'} "; 18769 echo_warn ("closing $state->{'ignored'}", $line_nr); 18770 } 18771 if ($state->{'texi'}) 18772 { 18773 if ($state->{'macro'}) 18774 { 18775 $string .= "\@end macro "; 18776 echo_warn ("closing macro", $line_nr); 18777 } 18778 elsif ($state->{'macro_name'}) 18779 { 18780 $string .= ('}' x $state->{'macro_depth'}) . " "; 18781 echo_warn ("closing $state->{'macro_name'} ($state->{'macro_depth'} braces missing)", $line_nr); 18782 } 18783 elsif ($state->{'verb'}) 18784 { 18785 echo_warn ("closing \@verb", $line_nr); 18786 $string .= $state->{'verb'} . '}'; 18787 } 18788 elsif ($state->{'raw'}) 18789 { 18790 echo_warn ("closing \@$state->{'raw'} raw format", $line_nr); 18791 $string .= "\@end $state->{'raw'} "; 18792 } 18793 if ($string ne '') 18794 { 18795 #print STDERR "close_stack scan_texi ($string)\n"; 18796 scan_texi ($string, $text, $stack, $state, $line_nr); 18797 $string = ''; 18798 } 18799 } 18800 elsif ($state->{'verb'}) 18801 { 18802 $string .= $state->{'verb'}; 18803 } 18804 18805 while ($stack_level--) 18806 { 18807 my $stack_text = $stack->[$stack_level]->{'text'}; 18808 $stack_text = '' if (!defined($stack_text)); 18809 if ($stack->[$stack_level]->{'format'}) 18810 { 18811 my $format = $stack->[$stack_level]->{'format'}; 18812 if ($format eq 'index_item') 18813 { 18814 enter_table_index_entry($text, $stack, $state, $line_nr); 18815 next; 18816 } 18817 elsif (!defined($format_type{$format}) or ($format_type{$format} ne 'fake')) 18818 { 18819 $stack_text = "\@$format\n" . $stack_text; 18820 } 18821 } 18822 elsif (defined($stack->[$stack_level]->{'style'})) 18823 { 18824 if ($state->{'structure'}) 18825 { 18826 $stack_text = close_structure_command($stack->[$stack_level], 18827 $state,1,$line_nr) 18828 } 18829 else 18830 { 18831 my $style = $stack->[$stack_level]->{'style'}; 18832 if ($style ne '') 18833 { 18834 $stack_text = "\@$style\{" . $stack_text; 18835 } 18836 else 18837 {# this is a lone opened brace. We readd it there. 18838 $stack_text = "\{" . $stack_text; 18839 } 18840 } 18841 } 18842 pop @$stack; 18843 add_prev($text, $stack, $stack_text); 18844 } 18845 $stack = [ ]; 18846 18847 $state->{'close_stack'} = 1; 18848 if ($string ne '') 18849 { 18850 if ($state->{'texi'}) 18851 { 18852 #print STDERR "scan_texi in close_stack ($string)\n"; 18853 scan_texi($string, $text, $stack, $state, $line_nr); 18854 } 18855 elsif ($state->{'structure'}) 18856 { 18857 #print STDERR "scan_structure in close_stack ($string)\n"; 18858 scan_structure($string, $text, $stack, $state, $line_nr); 18859 } 18860 } 18861 delete $state->{'close_stack'}; 18862} 18863 18864# close region like @insertcopying, titlepage... 18865# restore $state->{'after_element'} and delete the structure 18866sub close_region($) 18867{ 18868 my $state = shift; 18869 $state->{'after_element'} = 1; 18870 delete $state->{'after_element'} unless 18871 ($state->{'region_lines'}->{'after_element'}); 18872 $state->{'place'} = $state->{'region_lines'}->{'kept_place'}; 18873 delete $state->{'region_lines'}->{'number'}; 18874 delete $state->{'region_lines'}->{'format'}; 18875 delete $state->{'region_lines'}->{'after_element'}; 18876 delete $state->{'region_lines'}->{'kept_place'}; 18877 delete $state->{'region_lines'}; 18878} 18879 18880# close the stack, closing macros and formats left open. 18881# the precise behavior of the function depends on $close_paragraph: 18882# undef -> close everything 18883# defined -> remove empty paragraphs, close until the first format or 18884# paragraph. don't close styles, duplicate stack of styles not closed 18885 18886# if a $format is given the stack is closed according to $close_paragraph but 18887# if $format is encountered the closing stops 18888 18889sub close_stack($$$$;$$) 18890{ 18891 my $text = shift; 18892 my $stack = shift; 18893 my $state = shift; 18894 my $line_nr = shift; 18895 my $close_paragraph = shift; 18896 my $format = shift; 18897 my $new_stack; 18898 18899 #print STDERR "sub_close_stack\n"; 18900 return $new_stack unless (@$stack); 18901 18902 my $stack_level = $#$stack + 1; 18903 my $string = ''; 18904 my $verb = ''; 18905 18906 if ($state->{'verb'}) 18907 { 18908 $string .= $state->{'verb'}; 18909 $verb = $state->{'verb'}; 18910 } 18911 18912 #debugging 18913 #my $print_format = 'NO FORMAT'; 18914 #$print_format = $format if ($format); 18915 #my $print_close_paragraph = 'close everything'; 18916 #$print_close_paragraph = 'close paragraph without duplicating' if (defined($close_paragraph)); 18917 #$print_close_paragraph = $close_paragraph if ($close_paragraph); 18918 #print STDERR "Close_stack: format $print_format, close_paragraph: $print_close_paragraph\n"; 18919 18920 while ($stack_level--) 18921 { 18922 if ($stack->[$stack_level]->{'format'}) 18923 { 18924 my $stack_format = $stack->[$stack_level]->{'format'}; 18925 last if (defined($close_paragraph) or (defined($format) and $stack_format eq $format)); 18926 # We silently close paragraphs, preformatted sections and fake formats 18927 if ($stack_format eq 'paragraph') 18928 { 18929 $string .= "\@end_paragraph{}"; 18930 } 18931 elsif ($stack_format eq 'preformatted') 18932 { 18933 $string .= "\@end_preformatted{}"; 18934 } 18935 else 18936 { 18937 if ($fake_format{$stack_format}) 18938 { 18939 warn "# Closing a fake format `$stack_format'\n" if ($T2H_VERBOSE); 18940 } 18941 elsif ($stack_format ne 'center') 18942 { # we don't warn, but add an @end center 18943 echo_warn ("closing `$stack_format'", $line_nr); 18944 #dump_stack ($text, $stack, $state); 18945 } 18946 $string .= "\@end $stack_format "; 18947 } 18948 } 18949 else 18950 { 18951 my $style = $stack->[$stack_level]->{'style'}; 18952 # FIXME images, footnotes, xrefs, anchors with $close_paragraphs? 18953 # seems that it is not possible, as it is triggered by 18954 # close_paragraph which shouldn't be called with keep_texi 18955 # and when the arguments are expanded, there is a 18956 # substitute_line or similar with a new stack. 18957 if ($close_paragraph) 18958 { #duplicate the stack 18959 # the !exists($style_type{$style}) condition catches the unknown 18960 # @-commands: by default they are considered as style commands 18961 if ((exists($style_type{$style}) and ($style_type{$style} eq 'style')) or (!exists($style_type{$style}))) 18962 { 18963 push @$new_stack, { 'style' => $style, 'text' => '', 'no_open' => 1, 'arg_nr' => 0 }; 18964 $string .= '}'; 18965 } 18966 elsif (($style_type{$style} eq 'simple_style') or ($style_type{$style} eq 'accent')) 18967 { 18968 $string .= '}'; 18969 } 18970 else 18971 { 18972 print STDERR "$style while closing paragraph\n"; 18973 } 18974 } 18975 else 18976 { 18977 dump_stack ($text, $stack, $state) if (!defined($style)); # bug 18978 $string .= '}'; 18979 echo_warn ("closing \@-command $style", $line_nr) if ($style); 18980 } 18981 } 18982 } 18983 $state->{'no_close'} = 1 if ($close_paragraph); 18984 $state->{'close_stack'} = 1; 18985 if ($string ne '') 18986 { 18987 #print STDERR "scan_line in CLOSE_STACK ($string)\n"; 18988 #dump_stack ($text, $stack, $state); 18989 scan_line($string, $text, $stack, $state, $line_nr); 18990 } 18991 delete $state->{'no_close'}; 18992 delete $state->{'close_stack'}; 18993 $state->{'verb'} = $verb if (($verb ne '') and $close_paragraph); 18994 # cancel paragraph states and command_stack 18995 # FIXME this seems to be unusefull, see formatting/center.texi 18996 unless (defined($close_paragraph) or defined($format)) 18997 { 18998 $state->{'paragraph_style'} = [ '' ]; 18999 $state->{'command_stack'} = [ '' ]; 19000 } 19001 return $new_stack; 19002} 19003 19004# given a stack and a list of formats, return true if the stack contains 19005# these formats, first on top 19006sub stack_order($@) 19007{ 19008 my $stack = shift; 19009 my $stack_level = $#$stack + 1; 19010 while (@_) 19011 { 19012 my $format = shift; 19013 while ($stack_level--) 19014 { 19015 if ($stack->[$stack_level]->{'format'}) 19016 { 19017 if ($stack->[$stack_level]->{'format'} eq $format) 19018 { 19019 $format = undef; 19020 last; 19021 } 19022 else 19023 { 19024 return 0; 19025 } 19026 } 19027 } 19028 return 0 if ($format); 19029 } 19030 return 1; 19031} 19032 19033sub top_format($) 19034{ 19035 my $stack = shift; 19036 my $stack_level = $#$stack + 1; 19037 while ($stack_level--) 19038 { 19039 if ($stack->[$stack_level]->{'format'} and !$fake_format{$stack->[$stack_level]->{'format'}}) 19040 { 19041 return $stack->[$stack_level]; 19042 } 19043 } 19044 return undef; 19045} 19046 19047sub close_paragraph($$$;$) 19048{ 19049 my $text = shift; 19050 my $stack = shift; 19051 my $state = shift; 19052 my $line_nr = shift; 19053 #my $macro = shift; 19054 #print STDERR "CLOSE_PARAGRAPH\n"; 19055 #dump_stack($text, $stack, $state); 19056 my $new_stack = close_stack($text, $stack, $state, $line_nr, 1); 19057 my $top_stack = top_stack($stack); 19058 if ($top_stack and !defined($top_stack->{'format'})) 19059 { #debug 19060 print STDERR "Bug: no format on top stack\n"; 19061 dump_stack($text, $stack, $state); 19062 } 19063 if ($top_stack and ($top_stack->{'format'} eq 'paragraph')) 19064 { 19065 my $paragraph = pop @$stack; 19066 add_prev($text, $stack, do_paragraph($paragraph->{'text'}, $state)); 19067 $state->{'paragraph_macros'} = $new_stack; 19068 return 1; 19069 } 19070 elsif ($top_stack and ($top_stack->{'format'} eq 'preformatted')) 19071 { 19072 my $paragraph = pop @$stack; 19073 add_prev($text, $stack, do_preformatted($paragraph->{'text'}, $state)); 19074 $state->{'paragraph_macros'} = $new_stack; 19075 return 1; 19076 } 19077 return; 19078} 19079 19080sub abort_empty_preformatted($$) 19081{ 19082 my $stack = shift; 19083 my $state = shift; 19084 if (@$stack and $stack->[-1]->{'format'} 19085 and ($stack->[-1]->{'format'} eq 'preformatted') 19086 and ($stack->[-1]->{'text'} !~ /\S/)) 19087 { 19088 pop @$stack; 19089 } 19090} 19091 19092# for debugging 19093sub dump_stack($$$) 19094{ 19095 my $text = shift; 19096 my $stack = shift; 19097 my $state = shift; 19098 19099 if (defined($$text)) 19100 { 19101 print STDERR "text: $$text\n"; 19102 } 19103 else 19104 { 19105 print STDERR "text: UNDEF\n"; 19106 } 19107 my $in_remove = 0; 19108 my $in_simple_format = 0; 19109 my $in_keep = 0; 19110 $in_keep = 1 if ($state->{'keep_texi'}); 19111 if (!$in_keep) 19112 { 19113 $in_simple_format = 1 if ($state->{'simple_format'}); 19114 $in_remove = 1 if ($state->{'remove_texi'} and !$in_simple_format); 19115 } 19116 print STDERR "state(k${in_keep}s${in_simple_format}r${in_remove}): "; 19117 foreach my $key (keys(%$state)) 19118 { 19119 my $value = 'UNDEF'; 19120 $value = $state->{$key} if (defined($state->{$key})); 19121 print STDERR "$key: $value " if (!ref($value)); 19122 } 19123 print STDERR "\n"; 19124 my $stack_level = $#$stack + 1; 19125 while ($stack_level--) 19126 { 19127 print STDERR " $stack_level-> "; 19128 foreach my $key (keys(%{$stack->[$stack_level]})) 19129 { 19130 my $value = 'UNDEF'; 19131 $value = $stack->[$stack_level]->{$key} if 19132 (defined($stack->[$stack_level]->{$key})); 19133 print STDERR "$key: $value "; 19134 } 19135 print STDERR "\n"; 19136 } 19137 if (defined($state->{'table_list_stack'})) 19138 { 19139 print STDERR "table_list_stack: "; 19140 foreach my $format (@{$state->{'table_list_stack'}}) 19141 { 19142 print STDERR "$format->{'format'} "; 19143 } 19144 print STDERR "\n"; 19145 } 19146 if (defined($state->{'command_stack'})) 19147 { 19148 print STDERR "command_stack: "; 19149 foreach my $style (@{$state->{'command_stack'}}) 19150 { 19151 print STDERR "($style) "; 19152 } 19153 print STDERR "\n"; 19154 } 19155 if (defined($state->{'region_lines'})) 19156 { 19157 print STDERR "region_lines($state->{'region_lines'}->{'number'}): $state->{'region_lines'}->{'format'}\n"; 19158 } 19159 if (defined($state->{'text_macro_stack'}) and @{$state->{'text_macro_stack'}}) 19160 { 19161 print STDERR "text_macro_stack: (@{$state->{'text_macro_stack'}})\n"; 19162 } 19163} 19164 19165# for debugging 19166sub print_elements($) 19167{ 19168 my $elements = shift; 19169 foreach my $elem(@$elements) 19170 { 19171 if ($elem->{'node'}) 19172 { 19173 print STDERR "node-> $elem "; 19174 } 19175 else 19176 { 19177 print STDERR "chap=> $elem "; 19178 } 19179 foreach my $key (keys(%$elem)) 19180 { 19181 my $value = "UNDEF"; 19182 $value = $elem->{$key} if (defined($elem->{$key})); 19183 print STDERR "$key: $value "; 19184 } 19185 print STDERR "\n"; 19186 } 19187} 19188 19189sub substitute_line($;$) 19190{ 19191 my $line = shift; 19192 my $state = shift; 19193 $state = {} if (!defined($state)); 19194 $state->{'no_paragraph'} = 1; 19195 # this is usefull when called from &$I 19196 return simple_format($state, $line) if ($state->{'simple_format'}); 19197 return substitute_text($state, $line); 19198} 19199 19200sub substitute_text($@) 19201{ 19202 my $state = shift; 19203 my @stack = (); 19204 my $text = ''; 19205 my $result = ''; 19206 if ($state->{'structure'}) 19207 { 19208 initialise_state_structure($state); 19209 } 19210 elsif ($state->{'texi'}) 19211 { 19212 initialise_state_texi($state); 19213 } 19214 else 19215 { 19216 initialise_state($state); 19217 } 19218 $state->{'spool'} = []; 19219 #print STDERR "SUBST_TEXT begin\n"; 19220 19221 while (@_ or @{$state->{'spool'}}) 19222 { 19223 my $line; 19224 if (@{$state->{'spool'}}) 19225 { 19226 $line = shift @{$state->{'spool'}}; 19227 } 19228 else 19229 { 19230 $line = shift @_; 19231 } 19232 next unless (defined($line)); 19233 if ($state->{'structure'}) 19234 { 19235 scan_structure ($line, \$text, \@stack, $state); 19236 } 19237 elsif ($state->{'texi'}) 19238 { 19239 scan_texi ($line, \$text, \@stack, $state); 19240 } 19241 else 19242 { 19243 scan_line($line, \$text, \@stack, $state); 19244 } 19245 next if (@stack); 19246 $result .= $text; 19247 $text = ''; 19248 } 19249 # FIXME could we have the line number ? 19250 # close stack in substitute_text 19251 if ($state->{'texi'} or $state->{'structure'}) 19252 { 19253 close_stack_texi_structure(\$text, \@stack, $state, undef); 19254 } 19255 else 19256 { 19257 close_stack(\$text, \@stack, $state, undef); 19258 } 19259 #print STDERR "SUBST_TEXT end\n"; 19260 return $result . $text; 19261} 19262 19263# this function does the second pass formatting. It is not obvious that 19264# it is usefull as in that pass the collected things 19265sub substitute_texi_line($) 19266{ 19267 my $text = shift; 19268 return $text if $text =~ /^\s*$/; 19269 #print STDERR "substitute_texi_line $text\n"; 19270 my @text = substitute_text({'structure' => 1}, $text); 19271 my @result = (); 19272 while (@text) 19273 { 19274 push @result, split (/\n/, shift (@text)); 19275 } 19276 return '' unless (@result); 19277 my $result = shift @result; 19278 return $result . "\n" unless (@result); 19279 foreach my $line (@result) 19280 { 19281 chomp $line; 19282 $result .= ' ' . $line; 19283 } 19284 return $result . "\n"; 19285} 19286 19287sub print_lines($;$) 19288{ 19289 my ($fh, $lines) = @_; 19290 $lines = $Texi2HTML::THIS_SECTION unless $lines; 19291 my @cnt; 19292 my $cnt; 19293 for my $line (@$lines) 19294 { 19295 print $fh $line; 19296 if (defined($Texi2HTML::Config::WORDS_IN_PAGE) and ($Texi2HTML::Config::SPLIT eq 'node')) 19297 { 19298 @cnt = split(/\W*\s+\W*/, $line); 19299 $cnt += scalar(@cnt); 19300 } 19301 } 19302 return $cnt; 19303} 19304 19305sub do_index_entry_label($$$) 19306{ 19307 my $command = shift; 19308 my $state = shift; 19309 my $line_nr = shift; 19310 return '' if ($state->{'multiple_pass'}); 19311 my $entry = shift @index_labels; 19312 if (!defined($entry)) 19313 { 19314 echo_warn ("Not enough index entries !", $line_nr); 19315 return ''; 19316 } 19317 if ($command ne $entry->{'command'}) 19318 { 19319 # happens with bad texinfo with a line like 19320 # @deffn func aaaa args @defvr c--ategory d--efvr_name 19321 echo_warn ("Waiting for index cmd \@$entry->{'command'}, got \@$command", $line_nr); 19322 } 19323 19324 print STDERR "[(index $command) $entry->{'entry'} $entry->{'label'}]\n" 19325 if ($T2H_DEBUG & $DEBUG_INDEX); 19326 return &$Texi2HTML::Config::index_entry_label ($entry->{'label'}, $state->{'preformatted'}, substitute_line($entry->{'entry'}), 19327 $index_prefix_to_name{$prefix}, 19328 $command); 19329} 19330 19331# decompose a decimal number on a given base. The algorithm looks like 19332# the division with growing powers (division suivant les puissances 19333# croissantes) ? 19334sub decompose($$) 19335{ 19336 my $number = shift; 19337 my $base = shift; 19338 my @result = (); 19339 19340 return (0) if ($number == 0); 19341 my $power = 1; 19342 my $remaining = $number; 19343 19344 while ($remaining) 19345 { 19346 my $factor = $remaining % ($base ** $power); 19347 $remaining -= $factor; 19348 push (@result, $factor / ($base ** ($power - 1))); 19349 $power++; 19350 } 19351 return @result; 19352} 19353 19354# main processing is called here 19355set_document_language('en') unless ($lang_set); 19356# APA: There's got to be a better way: 19357$T2H_USER = &$I('unknown'); 19358 19359if ($Texi2HTML::Config::TEST) 19360{ 19361 # to generate files similar to reference ones to be able to check for 19362 # real changes we use these dummy values if -test is given 19363 $T2H_USER = 'a tester'; 19364 $THISPROG = 'texi2html'; 19365 setlocale( LC_ALL, "C" ); 19366} 19367else 19368{ 19369 # the eval prevents this from breaking on system which do not have 19370 # a proper getpwuid implemented 19371 eval { ($T2H_USER = (getpwuid ($<))[6]) =~ s/,.*//;}; # Who am i 19372 # APA: Provide Windows NT workaround until getpwuid gets 19373 # implemented there. 19374 $T2H_USER = $ENV{'USERNAME'} unless defined $T2H_USER; 19375} 19376 19377open_file($docu, $texi_line_number); 19378#Texi2HTML::LaTeX2HTML::init() if ($Texi2HTML::Config::L2H); 19379if ($Texi2HTML::Config::L2H) 19380{ 19381 push @Texi2HTML::Config::command_handler_init, \&Texi2HTML::LaTeX2HTML::init; 19382 push @Texi2HTML::Config::command_handler_process, \&Texi2HTML::LaTeX2HTML::latex2html; 19383 push @Texi2HTML::Config::command_handler_finish, \&Texi2HTML::LaTeX2HTML::finish; 19384 $Texi2HTML::Config::command_handler{'math'} = 19385 { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, 19386 'expand' => \&Texi2HTML::LaTeX2HTML::do_tex 19387 }; 19388 $Texi2HTML::Config::command_handler{'tex'} = 19389 { 'init' => \&Texi2HTML::LaTeX2HTML::to_latex, 19390 'expand' => \&Texi2HTML::LaTeX2HTML::do_tex 19391 }; 19392} 19393foreach my $handler(@Texi2HTML::Config::command_handler_init) 19394{ 19395 &$handler; 19396} 19397 19398my @css_import_lines; 19399my @css_rule_lines; 19400 19401# process css files 19402foreach my $file (@Texi2HTML::Config::CSS_FILES) 19403{ 19404 my $css_file_fh; 19405 my $css_file; 19406 if ($file eq '-') 19407 { 19408 $css_file_fh = \*STDIN; 19409 $css_file = '-'; 19410 } 19411 else 19412 { 19413 $css_file = locate_init_file ($file); 19414 unless (defined($css_file)) 19415 { 19416 warn "css file $file not found\n"; 19417 next; 19418 } 19419 unless (open (CSSFILE, "$css_file")) 19420 { 19421 warn "Cannot open ${css_file}: $!"; 19422 next; 19423 } 19424 $css_file_fh = \*CSSFILE; 19425 } 19426 my ($import_lines, $rules_lines); 19427 ($import_lines, $rules_lines) = process_css_file ($css_file_fh, $css_file); 19428 push @css_import_lines, @$import_lines; 19429 push @css_rule_lines, @$rules_lines; 19430} 19431 19432$Texi2HTML::THISDOC{'css_import_lines'} = \@css_import_lines; 19433$Texi2HTML::THISDOC{'css_lines'} = \@css_rule_lines; 19434 19435if ($T2H_DEBUG & $DEBUG_USER) 19436{ 19437 if (@css_import_lines) 19438 { 19439 print STDERR "# css import lines\n"; 19440 foreach my $line (@css_import_lines) 19441 { 19442 print STDERR "$line"; 19443 } 19444 } 19445 if (@css_rule_lines) 19446 { 19447 print STDERR "# css rule lines\n"; 19448 foreach my $line (@css_rule_lines) 19449 { 19450 print STDERR "$line"; 19451 } 19452 } 19453} 19454 19455pass_texi(); 19456dump_texi(\@lines, 'texi', \@lines_numbers) if ($T2H_DEBUG & $DEBUG_TEXI); 19457if (defined($Texi2HTML::Config::MACRO_EXPAND)) 19458{ 19459 my @texi_lines = (@first_lines, @lines); 19460 dump_texi(\@texi_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND); 19461} 19462pass_structure(); 19463if ($T2H_DEBUG & $DEBUG_TEXI) 19464{ 19465 dump_texi(\@doc_lines, 'first', \@doc_numbers); 19466 if (defined($Texi2HTML::Config::MACRO_EXPAND and $Texi2HTML::Config::DUMP_TEXI)) 19467 { 19468 unshift (@doc_lines, @first_lines); 19469 push (@doc_lines, "\@bye\n"); 19470 dump_texi(\@doc_lines, '', undef, $Texi2HTML::Config::MACRO_EXPAND . ".first"); 19471 } 19472} 19473exit(0) if ($Texi2HTML::Config::DUMP_TEXI or defined($Texi2HTML::Config::MACRO_EXPAND)); 19474 19475foreach my $style (keys(%special_commands)) 19476{ 19477 $special_commands{$style}->{'max'} = $special_commands{$style}->{'count'}; 19478} 19479 19480rearrange_elements(); 19481do_names(); 19482 19483#Texi2HTML::LaTeX2HTML::latex2html(); 19484foreach my $handler(@Texi2HTML::Config::command_handler_process) 19485{ 19486 &$handler; 19487} 19488 19489if (@{$region_lines{'documentdescription'}} and (!defined($Texi2HTML::Config::DOCUMENT_DESCRIPTION))) 19490{ 19491 my $documentdescription = remove_texi(@{$region_lines{'documentdescription'}}); 19492 my @documentdescription = split (/\n/, $documentdescription); 19493 $Texi2HTML::Config::DOCUMENT_DESCRIPTION = shift @documentdescription; 19494 chomp $Texi2HTML::Config::DOCUMENT_DESCRIPTION; 19495 foreach my $line (@documentdescription) 19496 { 19497 chomp $line; 19498 $Texi2HTML::Config::DOCUMENT_DESCRIPTION .= ' ' . $line; 19499 } 19500} 19501# do copyright notice inserted in comment at the beginning of the files 19502if (@{$region_lines{'copying'}}) 19503{ 19504 $copying_comment = &$Texi2HTML::Config::copying_comment($region_lines{'copying'}); 19505} 19506&$Texi2HTML::Config::toc_body(\@elements_list); 19507$sec_num = 0; 19508 19509 19510&$Texi2HTML::Config::css_lines(\@css_import_lines, \@css_rule_lines); 19511 19512pass_text(); 19513print STDERR "BUG: " . scalar(@index_labels) . " index entries pending\n" 19514 if (scalar(@index_labels)); 19515foreach my $special (keys(%special_commands)) 19516{ 19517 my $count = $special_commands{$special}->{'count'}; 19518 if (($count != 0) and $T2H_VERBOSE) 19519 { 19520 echo_warn ("$count special \@$special were not processed.\n"); 19521 } 19522} 19523if ($Texi2HTML::Config::IDX_SUMMARY) 19524{ 19525 foreach my $entry (keys(%index_names)) 19526 { 19527 do_index_summary_file($entry) unless ($empty_indices{$entry}); 19528 } 19529} 19530do_node_files() if ($Texi2HTML::Config::NODE_FILES); 19531#l2h_FinishFromHtml() if ($Texi2HTML::Config::L2H); 19532#l2h_Finish() if($Texi2HTML::Config::L2H); 19533#Texi2HTML::LaTeX2HTML::finish(); 19534foreach my $handler(@Texi2HTML::Config::command_handler_finish) 19535{ 19536 &$handler; 19537} 19538&$Texi2HTML::Config::finish_out(); 19539print STDERR "# that's all folks\n" if $T2H_VERBOSE; 19540 19541exit(0); 19542 19543 19544############################################################################## 19545 19546# These next few lines are legal in both Perl and nroff. 19547 19548.00 ; # finish .ig 19549 19550'di \" finish diversion--previous line must be blank 19551.nr nl 0-1 \" fake up transition to first page again 19552.nr % 0 \" start at page 1 19553'; __END__ ############# From here on it's a standard manual page ############ 19554 .so ${prefix}/man/man1/texi2html.1 19555