#!/usr/bin/env perl $^W = 1; # # $Id: pp2html,v 1.21 2001/12/19 21:04:43 lorenz Exp $ # $Revision: 1.21 $ - Patches 01 (reverted), 02-08 + 10 + 11 by JSTENZEL # - Patch 14 by JC and JSTENZEL, # - Patch 15-23 by JSTENZEL. # $Date: 2001/12/19 21:04:43 $ # # $Author: lorenz $ # # Revision History: See end of file #=================================================================== # declare script package package PerlPoint::Converter::pp2html; use Cwd; # BEGIN {eval join('', "use PAR '", cwd(), "/PerlPointCD/PerlPoint-0.39.par'");} # JSTENZEL, patch 1.01-21 (for PerlPointCD) use Pod::Text; use Getopt::ArgvFile qw(argvFile); use Getopt::Long; #use Data::Dumper; use POSIX qw(strftime); # JSTENZEL, 1.01-?? use Storable qw(nstore retrieve); # JSTENZEL, 1.01-20 # pragmata use strict; use subs "flush", "push_page", "pp_warn"; use vars qw (%OPT); # load modules use Carp; use Digest::MD5 qw(md5_hex); # ste use File::Basename; use File::Copy; use File::Path; use Safe; use PerlPoint::Constants 0.15; use PerlPoint::Tags; use PerlPoint::Tags::Basic; use PerlPoint::Tags::HTML; use PerlPoint::Tags::LaTeX; use PerlPoint::Backend; use PerlPoint::Parser 0.39; use PerlPoint::Converters qw(replace_keywords copy_file update_file relative_path return_abs_path is_abs_path); # my $me = basename($0); my $VERSION = sprintf("%d.%02d", q/$Revision: 1.21 $/ =~ /(\d+)\.(\d+)/); my $PACK_VERSION = $PerlPoint::Converters::VERSION; $main::VERSION = $VERSION; my $nix = ""; # for using RCS keys in Usage, ... my $Date = "Date "; my $lcnt = 0; #TODO Sanieren my %TR = ( # Translation Table "\334" => "Ü", "\374" => "ü", "\326" => "Ö", "\366" => "ö", "\304" => "Ä", "\344" => "ä", "\337" => "ß", ); # # Bullets for the masses ... my @BULLETS=("DUMMY"); my $default_li_start = "
  • "; my $default_li_end = "
  • \n"; #============================================================= Usage sub Usage { #--------------------------------------------------- no strict; my $tmpdir = "/tmp"; $^W = 0; #my $parser = Pod::Text->new (sentence => 0, loose => 0, width => 78); if (defined $ENV{TMP}){ $tmpdir = $ENV{TMP}; } elsif (defined $ENV{TEMP}) { $tmpdir = $ENV{TEMP}; } my $tmpfile = "$tmpdir/$me.$$"."_help"; $SIG{INT} = $SIG{QUIT} = $SIG{HUP} = $SIG{ABRT} = $SIG{PIPE} = sub { unlink $tmpfile }; open(ME, "< $0") or die "Can't open $me: $!\n"; open(TMP, "> $tmpfile") or die "Can't open $tmpfile: $!\n"; my $skip = 1; while(){ if (/^=cut/){ $skip = 1 ; print TMP $_; next; } $skip = 0 if /^=/; next if $skip; s/PROGRAM/$me/g; s/P_VERSION/$VERSION/g; print TMP $_; } close(TMP); #$parser->parse_from_file( $tmpfile ); pod2text($tmpfile ); unlink $tmpfile; exit; } # Usage #==================================================== Parameter Loop my %OPT_MAIN; my %OPT_STYLE; %OPT = ( # define => [], no_contents_indent => 0, contents_indent => 0, alinkcolor => "#FF0000", top_alinkcolor => "#FF0000", bot_alinkcolor => "#FF0000", toc_alinkcolor => "#FF0000", idx_alinkcolor => "#FF0000", contents_target => "Index", contents_table_widht => 0, contents_css_id_index => '', # patch 1.01-17, JSTENZEL contents_css_id_start => '', # patch 1.01-17, JSTENZEL bgcolor => "#FFFFFF", idx_bgcolor => "#FFFFFF", idx_fgcolor => "#000000", top_bgcolor => "#FFFFFF", top_fgcolor => "#000000", bot_bgcolor => "#FFFFFF", bot_fgcolor => "#000000", toc_bgcolor => "#FFFFFF", toc_fgcolor => "#000000", back_image => "", top_back_image => "", bot_back_image => "", toc_back_image => "", idx_back_image => "", bottom_template => "", box_color => "#E5E5E5", boxtext_bold => "ON", boxtext_color => "#000000", center_headers => 0, hide_headers => 0, # ste, patch 1.01-06 contents_header => "Contents", fgcolor => "#000000", frame_set => "", frame_start => "frame_set.html", index_bot => 2, index_dat => 1, index_header => "Index", index_top => 0, java_script_navigation => 1, java_script_controls => 0, linear_mode => 0, linkcolor => "#0000CC", top_linkcolor => "#0000CC", bot_linkcolor => "#0000CC", toc_linkcolor => "#0000CC", idx_linkcolor => "#0000CC", no_index => 0, num_headers => 0, trailing_point => 0, slide_dir => ".", style_dir => ["."], slide_prefix => "slide", slide_suffix => "htm", start_page => "index.htm", title => "XXXXX", top_template => "", trans_table => "", tree_app_height => 500, tree_app_width => 250, tree_applet => 0, headline_shortcuts => 0, # JSTENZEL, patch 1.01-07 label_next => "Next", label_prev => "Previous", label_index => "Index", label_contents => "Contents", vlinkcolor => "#AAAAAA", top_vlinkcolor => "#AAAAAA", bot_vlinkcolor => "#AAAAAA", toc_vlinkcolor => "#AAAAAA", idx_vlinkcolor => "#AAAAAA", base_left_txt => "BASE_LEFT_TXT", base_right_txt => "BASE_RIGHT_TXT", base_middle_txt => "BASE_MIDDLE_TXT", bullets_align_middle => 0, bot_left_txt => "BOT_LEFT_TXT", bot_right_txt => "BOT_RIGHT_TXT", bot_middle_txt => "BOT_MIDDLE_TXT", top_left_txt => "TOP_LEFT_TXT", top_right_txt => "TOP_RIGHT_TXT", top_middle_txt => "TOP_MIDDLE_TXT", logo_image_filename => "LOGO_IMAGE_FILENAME", mv2targetdir => 0, # patch 1.01-09, JSTENZEL charset => 'iso-8859-1', # patch 1.01-10, JSTENZEL use_css_for_toc => 0, ); ## END DEFAULTS if (defined $ARGV[0] and $ARGV[0] eq "-h") { Usage() } argvFile( home => 1, default => 1); if (defined $ARGV[0] and $ARGV[0] =~ /-v$/){ @ARGV =("-version"); # to avoid ambiguities } my $verbose = 1; ## NOTE: The comments in the @OPTIONS parameter list are used for ## creating the menues in the interactive config file editor ## (which will soon be available :-) my @OPTIONS = ( # ## ------------------------- General "activeContents", "cache", "cacheCleanup", "safeOpcode=s@", "set=s@", "trans_table=s", "filter=s", "nocopyright", "noinfo", "nowarn", "mv2targetdir", "quiet", "count_only", "streamBuffer=s", # patch 1.01-20: stream caching "reloadStream", # and stream reload (JSTENZEL) ## ------------------------- document (added by JSTENZEL, patch 10, 15, 16) "title=s", # (moved) "author=s", "description=s", "charset=s", "norobots", "nosmarttags", "linknavigation", "bootstrapaddress=s", "validate", "startaddress=s", "no_html_header", "no_html_bodytags", "includelib=s@", "critical_semantics", ## ------------------------- Colors "define=s@", # generic color definition for options file and templates "box_color=s", "boxtext_color=s", "fgcolor=s", "bgcolor=s", "idx_fgcolor=s", "idx_bgcolor=s", "toc_fgcolor=s", "toc_bgcolor=s", "top_fgcolor=s", "top_bgcolor=s", "bot_fgcolor=s", "bot_bgcolor=s", "back_image=s", "toc_back_image=s", "idx_back_image=s", "top_back_image=s", "bot_back_image=s", ## ------------------------- Link Colors "linkcolor=s", "top_linkcolor=s", "bot_linkcolor=s", "toc_linkcolor=s", "idx_linkcolor=s", "vlinkcolor=s", "top_vlinkcolor=s", "bot_vlinkcolor=s", "toc_vlinkcolor=s", "idx_vlinkcolor=s", "alinkcolor=s", "top_alinkcolor=s", "bot_alinkcolor=s", "toc_alinkcolor=s", "idx_alinkcolor=s", ## ------------------------- Templates "top_template=s", "top_idx_template=s", "top_toc_template=s", "bottom_template=s", "bottom_idx_template=s", "bottom_toc_template=s", "nav_template=s", "nav_top_template=s", "nav_bottom_template=s", ## ------------------------- Layout "contents_header=s", "contents_table_width=s", "contents_css_id_index=s", # patch 1.01-17, JSTENZEL "contents_css_id_start=s", # patch 1.01-17, JSTENZEL "index_header=s", "style=s", "style_dir=s@", "label_next=s", "label_prev=s", "label_index=s", "label_contents=s", "bullet=s@", "bullets_align_middle", "box_border=s", "box_width=s", "boxtext_bold=s", "contents_target=s", "contents_indent=i", "no_contents", # JSTENZEL, 1-20 "no_contents_indent", "no_contents_bullets", "block_indent=i", "no_index", "linear_mode", "num_headers", "trailing_point", "nonum_headers", "center_headers", "hide_headers", "headline_shortcuts", ## ------------------------- Layout2 "style_sheet=s", "base_left_txt=s", "base_right_txt=s", "base_middle_txt=s", "bot_left_txt=s", "bot_right_txt=s", "bot_middle_txt=s", "top_left_txt=s", "top_right_txt=s", "top_middle_txt=s", "logo_image_filename=s", ## ------------------------- Directories, Filenames "start_page=s", "frame_set=s", "frame_start=s", "slide_dir=s", "target_dir=s", "slide_prefix=s", "slide_suffix=s", "image_dir=s", "image_ref=s", "applet_dir=s", "applet_ref=s", "slide_md5", "reverse_order", "index_bot=s", "index_dat=s", "index_top=s", "use_css_for_toc", ## ------------------------ Tree Applet "tree_applet", "tree_app_height=s", "tree_app_width=s", "tree_base=s", "java_script_navigation=s", "java_script_controls=s", ## ------------------------ Special "debug", "trace:i", "help", "version", ); ##----------- END OPTIONS die unless GetOptions( \%OPT_MAIN, @OPTIONS ); # build and configure a Safe object my $safe = new Safe; if (exists $OPT_MAIN{safeOpcode}){ unless (grep($_ eq 'ALL', @{$OPT_MAIN{safeOpcode}})) { # configure compartment $safe->permit(@{$OPT_MAIN{safeOpcode}}); } else { # simply flag that we want to execute active contents $safe=1; } } delete $OPT_MAIN{safeOpcode}; # der Mohr hat seine Schuldigkeit getan! # if we do not delete this option we will get warnings in the # subsequent call to GetOptions ... # propagate options as necessary @OPT_MAIN{qw(nocopyright noinfo nowarn)}=(1,1,1) if exists $OPT_MAIN{quiet}; $OPT_MAIN{trace}=$ENV{SCRIPTDEBUG} if not exists $OPT_MAIN{trace} and exists $ENV{SCRIPTDEBUG}; #======================================================= Script Body Usage(1) if ($OPT_MAIN{help}); print STDERR "This is $me, build $VERSION from PerlPoint::Converters $PACK_VERSION (patches 01-16)\n" unless $OPT_MAIN{quiet}; print STDERR "$Date: 2002/11/15 13:02:15 $nix\n" unless $OPT_MAIN{quiet}; print STDERR "(c) Lorenz Domke 2002.\n\n" unless $OPT_MAIN{nocopyright}; exit if $OPT_MAIN{version}; $verbose = 0 if ($OPT_MAIN{quiet} or $OPT_MAIN{noinfo}); # handle define options: my %OPT_DEFINE; # check slide dir and create it if necessary: # TODO test on Win9X and NT systems (problems with path names?) if (defined $OPT_MAIN{define}){ #use Data::Dumper; #print Dumper $OPT_MAIN{define}; foreach my $define (@{$OPT_MAIN{define}}) { # add this color option: if ($define =~ /^\s*(\w+)\s+(\S+)\s*$/){ $OPT_DEFINE{$1} = $2; print " found define: $1 --> $2\n"; } } } # define options if ($OPT_MAIN{target_dir}) { $OPT_MAIN{slide_dir} = $OPT_MAIN{target_dir}; } $OPT_MAIN{slide_dir} = defined $OPT_MAIN{slide_dir} ? $OPT_MAIN{slide_dir} : "."; if (! -d $OPT_MAIN{slide_dir}) { print STDERR "creating slide dir $OPT_MAIN{slide_dir} ...\n" if $verbose; mkpath($OPT_MAIN{slide_dir}, 1, oct(755)) or die "Cannot creat $OPT_MAIN{slide_dir}: $!\n"; } $OPT_MAIN{image_dir} = $OPT_MAIN{slide_dir} unless defined $OPT_MAIN{image_dir}; if(! defined $OPT_MAIN{image_ref}){ if ($OPT_MAIN{image_dir} eq $OPT_MAIN{slide_dir}){ $OPT_MAIN{image_ref} = "."; # images are in the slides dir } else { if ( is_abs_path($OPT_MAIN{image_dir}) ){ $OPT_MAIN{image_ref} = $OPT_MAIN{image_dir}; # absolute path name } else { ### we must figure out, where the image_dir is relative to the slide_dir !!! $OPT_MAIN{image_ref} = relative_path($OPT_MAIN{image_dir}, $OPT_MAIN{slide_dir}); #TODO: remove abs_path if relative path works $OPT_MAIN{image_ref} = return_abs_path($OPT_MAIN{image_dir}); } } } $OPT_MAIN{applet_dir} = $OPT_MAIN{slide_dir} unless defined $OPT_MAIN{applet_dir}; if(! defined $OPT_MAIN{applet_ref}){ if ($OPT_MAIN{applet_dir} eq $OPT_MAIN{slide_dir}){ $OPT_MAIN{applet_ref} = "."; # applets are in the slides dir } else { if ( is_abs_path($OPT_MAIN{applet_dir}) ){ $OPT_MAIN{applet_ref} = $OPT_MAIN{applet_dir}; # absolute path name } else { ### we must figure out, where the applet_dir is relative to the slide_dir !!! #TODO: remove abs_path if relative path works $OPT_MAIN{applet_ref} = relative_path($OPT_MAIN{applet_dir}, $OPT_MAIN{slide_dir}); $OPT_MAIN{applet_ref} = return_abs_path($OPT_MAIN{applet_dir}); } } } my $style_dir = "."; ## handle style options; in this case we must load additional ## options files ... if (defined $OPT_MAIN{style}){ # try to find the style directory print STDERR "using style $OPT_MAIN{style}\n" if $verbose; my $style = $OPT_MAIN{style}; my $found = 0; foreach my $mstyle_dir (@{$OPT_MAIN{style_dir}}) { if (-e "$mstyle_dir/$style/$style.cfg"){ $style_dir = $mstyle_dir; $found = 1; last; } } if (! $found){ die "*** ERROR: style directory $style not found ...\n"; } # load the options file from the style directory: my $style_opts = "$style_dir/$style/$style.cfg"; if (! -e $style_opts) { die "*** ERROR: cannot find options file $style_opts !\n"; } { local @ARGV = ( "\@$style_opts" ); argvFile(); die unless GetOptions( \%OPT_STYLE, # get new options from style @OPTIONS ); # merge main options into style options # (main options have higher priority !!) @OPT{ keys %OPT_STYLE } = values %OPT_STYLE if %OPT_STYLE; @OPT{ keys %OPT_MAIN } = values %OPT_MAIN; $OPT{txt_contents} = $OPT{contents_header}; $OPT{txt_index} = $OPT{index_header}; } $style_dir = "$style_dir/$style"; ## used as prefix for all template files !! # now copy all images from the style dir to target_dir (slide_dir): opendir(STYLE, "$style_dir") or die "Can't open directory $style_dir: $!\n"; foreach my $img (readdir(STYLE)){ if ($img =~ /\.jpg$|\.gif$|\.png$/i) { update_file("$style_dir/$img", "$OPT_MAIN{image_dir}/$img", $verbose, \%OPT, 0); } if ($img =~ /\.htm$|\.html$|\.css$/i) { update_file("$style_dir/$img", "$OPT_MAIN{slide_dir}/$img", $verbose, \%OPT, 0); } } closedir(STYLE); } # end --style option else { # merge main options into %OPT @OPT{ keys %OPT_MAIN } = values %OPT_MAIN; $OPT{txt_contents} = $OPT{contents_header}; $OPT{txt_index} = $OPT{index_header}; } # merge define options: @OPT{ keys %OPT_DEFINE } = values %OPT_DEFINE; if ($OPT{tree_applet}){ #--------------------- TreeApplet # now update tree applet files in target directory # first find tree applet sources # There MUST be a subdirectoy called "applet_src" in one of the style directories my $applet_source_dir; foreach my $mstyle_dir (@{$OPT{style_dir}}) { if (-d "$mstyle_dir/applet_src"){ $applet_source_dir = "$mstyle_dir/applet_src"; last; } } # now update: if (! defined $applet_source_dir){ die "*** ERROR: TreeApplet source directory not found!\n" . " Perhaps you have not specified a --style_dir option.\n" . " This is now mandatory if you use the tree applet.\n" . " There must be a directory called 'applet_src' in one of your\n" . " style collections (i. e. one of the directories which are \n" . " specified with the --style_dir option).\n" ; } opendir(TR, $applet_source_dir) or die "cannot open $applet_source_dir:$!\n"; foreach my $f (readdir(TR)){ next unless $f =~ /\.class$/; update_file("$applet_source_dir/$f", "$OPT{applet_dir}/$f", $verbose, \%OPT, 0); } # fix the tree_base if (! defined $OPT{tree_base}){ $OPT{tree_base} = $OPT{applet_ref}; } } # tree_applet my $block_width = ""; # width for code block tables if(exists $OPT{box_width}){ $block_width = " WIDTH=$OPT{box_width}"; } my $box_border = ""; if(exists $OPT{box_border}){ $box_border = " BORDER=$OPT{box_border}"; } my $java_script_src = "java_navigation.js"; # script for java script navigation my $LIST; my ($li_start, $li_end) = ($default_li_start, $default_li_end); my ($lo_start, $lo_end) = ($li_start, $li_end); my $pwd = cwd; my $shift_level = 0; my $missing_bullets_cnt = 0; my $img_dir = return_abs_path($OPT{image_dir}); # set up @BULLEST array and copy bullet images to target dir {{{ ------------------------------ foreach my $bull (@{$OPT{bullet}}) { $shift_level++; if ($bull !~ /^
  • ) { # skip empty and comment lines next if /^\s*$/ or /^\s*#/; # remove leading and trailing whitespaces chomp; s/^\s+//; # extract and store translation data my @fields=split; $TR{$fields[0]}=$fields[1] if @fields>=2; } } # end if $OPT{trans_table) if ( ! $OPT{frame_set}){ $OPT{java_script_navigation} = 0; # in this case we do NOT need java script navigation } if (! defined($OPT{top_idx_template})){ $OPT{top_idx_template} = $OPT{top_template} } if (! defined($OPT{top_toc_template})){ $OPT{top_toc_template} = $OPT{top_template} } if (! defined($OPT{bottom_idx_template})){ $OPT{bottom_idx_template} = $OPT{bottom_template} } if (! defined($OPT{bottom_toc_template})){ $OPT{bottom_toc_template} = $OPT{bottom_template} } my ($block_indent_0, $block_indent_1) = ("",""); if (defined($OPT{block_indent})){ for (my $i=0; $i < $OPT{block_indent}; $i++){ $block_indent_0 .= "
      "; $block_indent_1 .= "
    "; } } if ($OPT{frame_set} ne "") { print "Creating frame set ...\n"; my $fset = "$style_dir/$OPT{frame_set}"; if (! -e $fset or -d $fset) { die "*** ERROR: frame set template $fset does not exist or is a directory!\n"; } copy_file($fset, "$OPT{slide_dir}/$OPT{frame_start}", $verbose, \%OPT); copy_file($fset, "$OPT{slide_dir}/$OPT{start_page}", $verbose, \%OPT) if $OPT{start_page}; } my $embedded_html = 0; ## ## disable options if noxxx options are set: if (defined $OPT{nonum_headers}){ $OPT{num_headers} = 0; # allows overwriting of style option by main option `nonum_headers' } # declare variables # Data Structures # 000000000000000 my (@streamData, %variables); # ste: added %variables my $page_ref; # pointer to current page buffer my @PAGES; # Array of pointers to PAGE structures # PAGES[0] is table of contents # $PAGES[ $m ] = { # BODY => [ ... ], # LEVEL => ..., # NUMBER => ..., # HD => ..., # FILENAME => ..., # PREV => ..., # NEXT => ..., # UP => ..., # DOWN => ..., # FIRST => ..., # LAST => ..., # LOC => ..., # } $OPT{page_cnt} = 0; my $imge_cnt = 0; my $idx_page_cnt = 1; $PAGES[0] -> {HD} = $OPT{contents_header}; $PAGES[0] -> {FILENAME} = "$OPT{slide_prefix}0000.$OPT{slide_suffix}"; $PAGES[0] -> {LEVEL} = 0; $PAGES[0] -> {NUMBER} = "0"; $PAGES[0] -> {UP} = -1; $PAGES[0] -> {DOWN} = 1; $PAGES[0] -> {PREV} = -1; $PAGES[0] -> {NEXT} = 1; $PAGES[0] -> {FIRST} = 0; $PAGES[0] -> {LAST} = 0; my @TABLE_COLUMN_ALIGN; # alignmen for table columns my $table_column; # index of table column my $xref_open = 0; # for images in XREFs ... my @image_buffer; my ($f0, $f1, $f2) = ($OPT{index_top}, $OPT{index_dat}, $OPT{index_bot}); # window indices for javascript my %ANCHOR; # $ANCHOR{a_name} = $OPT{page_cnt} my (@HEADLINE_PATH, @HEADLINE_PATHS); # ste: headline path parts (first element unused!), modified again for patch 1.01-08 my %INDEX; # index entries my %IDX_; # index entries available my $idx_cnt = 0; my ($center_header_start, $center_header_end) = ("",""); my $table_hl_bgcolor=""; my $td_was_empty = 0; # set to 1 if an empty table entry is detected if ($OPT{center_headers}){ $center_header_start = "
    "; $center_header_end = "
    "; } my @PG_COLOR; # can we reload a stream? if (exists $OPT{reloadStream} && exists $OPT{streamBuffer}) { warn "\n[Info] Loading cached stream.\n" if $verbose; @streamData=@{retrieve($OPT{streamBuffer})}; } else { # build parser my ($parser)=new PerlPoint::Parser; # and call it $parser->run( # stream => \@streamData, files => \@ARGV, safe => exists $OPT{activeContents} ? $safe : undef, filter => exists $OPT{filter} ? $OPT{filter} : "html|perl", exists $OPT{critical_semantics} ? (criticalSemanticErrors => 1) : (), activeBaseData => { targetLanguage => 'HTML', userSettings => {map {$_=>1} exists $OPT{set} ? @{$OPT{set}} : ()}, }, vispro => 1, nestedTables => 1, var2stream => 1, predeclaredVars => { CONVERTER_NAME => basename($0), CONVERTER_VERSION => $main::VERSION, }, headlineLinks => 1, trace => TRACE_NOTHING + ((exists $OPT{trace} and $OPT{trace} & 1) ? TRACE_PARAGRAPHS : 0) + ((exists $OPT{trace} and $OPT{trace} & 2) ? TRACE_LEXER : 0) + ((exists $OPT{trace} and $OPT{trace} & 4) ? TRACE_PARSER : 0) + ((exists $OPT{trace} and $OPT{trace} & 8) ? TRACE_SEMANTIC : 0) + ((exists $OPT{trace} and $OPT{trace} & 16) ? TRACE_ACTIVE : 0), display => DISPLAY_ALL + (exists $OPT{noinfo} ? DISPLAY_NOINFO : 0) + (exists $OPT{nowarn} ? DISPLAY_NOWARN : 0), cache => (exists $OPT{cache} ? CACHE_ON : CACHE_OFF) + (exists $OPT{cacheCleanup} ? CACHE_CLEANUP : 0), exists $OPT{includelib} ? (libpath => $OPT{includelib}) : (), ) or exit 1; # # store new stream data, if required nstore(\@streamData, $OPT{streamBuffer}) if exists $OPT{streamBuffer}; } # build a backend my $backend=new PerlPoint::Backend( # name => $me, trace => TRACE_NOTHING, display => DISPLAY_ALL + (exists $OPT{noinfo} ? DISPLAY_NOINFO : 0) + (exists $OPT{nowarn} ? DISPLAY_NOWARN : 0), vispro => 1); # # register backend handlers $backend->register(DIRECTIVE_BLOCK, \&handleBlock); $backend->register(DIRECTIVE_COMMENT, \&handleComment); $backend->register(DIRECTIVE_DOCUMENT, \&handleDocument); $backend->register(DIRECTIVE_HEADLINE, \&handleHeadline); $backend->register(DIRECTIVE_LIST_LSHIFT, \&handleLShift); $backend->register(DIRECTIVE_LIST_RSHIFT, \&handleRShift); $backend->register(DIRECTIVE_ULIST, \&handleList); $backend->register(DIRECTIVE_UPOINT, \&handlePoint); $backend->register(DIRECTIVE_OLIST, \&handleList); $backend->register(DIRECTIVE_OPOINT, \&handlePoint); $backend->register(DIRECTIVE_DLIST, \&handleList); $backend->register(DIRECTIVE_DPOINT, \&handleDPoint); $backend->register(DIRECTIVE_DPOINT_ITEM, \&handleDPointItem); $backend->register(DIRECTIVE_SIMPLE, \&handleSimple); $backend->register(DIRECTIVE_TAG, \&handleTag); $backend->register(DIRECTIVE_TEXT, \&handleText); $backend->register(DIRECTIVE_VARRESET, \&handleVarReset); # ste $backend->register(DIRECTIVE_VARSET, \&handleVarSet); # ste $backend->register(DIRECTIVE_VERBATIM , \&handleVerbatim); # my @BUFFER; # buffer for current text my @ERRBUFFER; # buffer for context of error my $box_bg_color= "blue"; my $box_fg_color= "white"; if (defined $OPT{box_color}){ $box_bg_color = $OPT{box_color}; } if (defined $OPT{boxtext_color}){ $box_fg_color= $OPT{boxtext_color}; } my $default_box_bg_color= $box_bg_color; my $default_box_fg_color= $box_fg_color; my $cellpadding = 5; # and run it $backend->run(\@streamData); gen_navigation(); reverse_order() if $OPT{reverse_order} and ! $OPT{slide_md5}; if ($OPT{debug}){ pr_navigation_table(); # exit; } if ($idx_cnt and ! $OPT{no_index}) { # define last page as index page: $idx_page_cnt = $OPT{page_cnt} +1; $PAGES[$idx_page_cnt] -> {HD} = $OPT{index_header}; $PAGES[$idx_page_cnt] -> {FILENAME} = "$OPT{slide_prefix}_idx.$OPT{slide_suffix}"; $PAGES[$idx_page_cnt] -> {LEVEL} = 0; $PAGES[$idx_page_cnt] -> {NUMBER} = "idx"; $PAGES[$idx_page_cnt] -> {UP} = 0; $PAGES[$idx_page_cnt] -> {DOWN} = -1; $PAGES[$idx_page_cnt] -> {PREV} = 0; $PAGES[$idx_page_cnt] -> {NEXT} = 1; $PAGES[$idx_page_cnt] -> {FIRST} = 0; $PAGES[$idx_page_cnt] -> {LAST} = -1; # } # init index page ## Now do your job: output the pages ... if ($OPT{java_script_navigation}){ # create java script navigation file open(JS, "> $OPT{slide_dir}/$java_script_src") or die "Cannot open $java_script_src: $!\n"; print JS <{FILENAME}; $slide = "$OPT{slide_dir}/$slide"; if ($OPT{count_only}){ printf STDERR "\r ... creating slide %4d/%d", $i, $OPT{page_cnt} if $verbose; } else { print STDERR " creating $slide ..." if $verbose; print STDERR " Level ", $PAGES[$i]->{LEVEL}, " ===> ", $PAGES[$i]->{HD}, , " <===\n" if $verbose; } # open file open(SLIDE, "> $slide") or die "Can't open file $slide: $!\n"; # include header template and replace KEYWORDS print_HTML_HEAD(*SLIDE, $i) unless exists $OPT{no_html_header}; # JSTENZEL, 1.01-15 my $gl_fgcolor = defined $PG_COLOR[$i]{fgcolor} ? $PG_COLOR[$i]{fgcolor} : $OPT{fgcolor}; my $gl_bgcolor = defined $PG_COLOR[$i]{bgcolor} ? $PG_COLOR[$i]{bgcolor} : $OPT{bgcolor}; my $gl_linkcolor = defined $PG_COLOR[$i]{linkcolor} ? $PG_COLOR[$i]{linkcolor} : $OPT{linkcolor}; my $gl_alinkcolor = defined $PG_COLOR[$i]{alinkcolor} ? $PG_COLOR[$i]{alinkcolor} : $OPT{alinkcolor}; my $gl_vlinkcolor = defined $PG_COLOR[$i]{vlinkcolor} ? $PG_COLOR[$i]{vlinkcolor} : $OPT{vlinkcolor}; print_HTML_BODY(*SLIDE, $i, $OPT{back_image}, $gl_bgcolor, $gl_fgcolor, $gl_linkcolor, $gl_alinkcolor, $gl_vlinkcolor, ) unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 if ($OPT{frame_set}){ if ($OPT{java_script_navigation}){ create_top_page($i); } } else { insert_template(*SLIDE, $i, $OPT{top_template}); } if ($OPT{nav_top_template}){ insert_template(*SLIDE, $i, $OPT{nav_top_template}); } elsif ($OPT{nav_template}){ insert_template(*SLIDE, $i, $OPT{nav_template}); } # print page body foreach my $line ( @{$PAGES[$i]->{BODY}} ){ # number the headers if option is set if ($OPT{num_headers}){ my $num= $PAGES[$i] -> {NUMBER}; my $point = $OPT{trailing_point} ? "." : ""; $line =~ s/_PG_NUM_/$num$point /; } else { $line =~ s/_PG_NUM_//; } # Replace _INTERNAL_SECTION with correct hyperlink $line = replace_internal_links($line, "_INTERN_SECTION", "HD"); # Replace _INTERNAL_PAGE with correct hyperlink $line = replace_internal_links($line, "_INTERN_PAGE","NUMBER"); # Replace _INTERNAL_XREF with correct hyperlink $line = replace_internal_links($line, "_INTERN_XREF"); print SLIDE $line; } # loop over body lines if ($OPT{nav_bottom_template}){ insert_template(*SLIDE, $i, $OPT{nav_bottom_template}); } elsif ($OPT{nav_template}){ insert_template(*SLIDE, $i, $OPT{nav_template}); } # include footer template and replace KEYWORDS (navigation ...) if ($OPT{frame_set}){ if ($OPT{java_script_navigation}){ create_bot_page($i); } } else { insert_template(*SLIDE, $i, $OPT{bottom_template}); } print SLIDE "\n\n" unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 # close file close(SLIDE); } # loop over $PAGES[$i] if ($OPT{count_only}){ print "\n"; } # there are two contents pages, build them both as necessary (1.01-17, JSTENZEL) gen_contents("$OPT{slide_dir}/$PAGES[0]->{FILENAME}", $OPT{contents_css_id_index}); gen_contents("$OPT{slide_dir}/$OPT{start_page}", $OPT{contents_css_id_start}) if $OPT{frame_set} eq "" and $OPT{start_page}; # build index gen_index() unless $OPT{no_index}; if ($OPT{frame_set} eq "" and $OPT{start_page}) { my $contents = $PAGES[0]->{FILENAME}; $contents = "$OPT{slide_dir}/$contents"; copy($contents, "$OPT{slide_dir}/$OPT{start_page}"); } if ($verbose){ # write statistics print STDERR "\n Statistics:\n"; print STDERR " -----------\n"; print STDERR " $OPT{page_cnt} pages\n"; print STDERR " $idx_cnt index entries\n"; print STDERR " $imge_cnt images\n"; print STDERR " $missing_bullets_cnt missing bullet images\n" if $missing_bullets_cnt; print STDERR " $missing_backgrounds_cnt missing background images\n" if $missing_backgrounds_cnt; } # $verbose exit 0; # SUBROUTINES ###################################################### # helper function sub create_top_page { #----------------------------------------- my ($i) = @_; return unless $OPT{top_template}; # no need to create "empty" files ... my $fname = "$OPT{slide_dir}/top_" . $PAGES[$i]->{FILENAME}; open(TT, "> $fname") or die "cannot open $fname: $!\n"; print_HTML_HEAD(*TT, $i) unless exists $OPT{no_html_header}; # JSTENZEL, 1.01-15 print_HTML_BODY(*TT, $i, $OPT{top_back_image}, $OPT{top_bgcolor}, $OPT{top_fgcolor}, $OPT{top_linkcolor}, $OPT{top_alinkcolor}, $OPT{top_vlinkcolor}, ) unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 insert_template(*TT, $i, $OPT{top_template}); print TT "\n\n"; close(TT); } # create_top_page sub create_bot_page { #----------------------------------------- my ($i) = @_; return unless $OPT{bottom_template}; # no need to create "empty" files ... my $fname = "$OPT{slide_dir}/bot_" . $PAGES[$i]->{FILENAME}; open(TT, "> $fname") or die "cannot open $fname: $!\n"; print_HTML_HEAD(*TT, $i) unless exists $OPT{no_html_header}; # JSTENZEL, 1.01-15 print_HTML_BODY(*TT, $i, $OPT{bot_back_image}, $OPT{bot_bgcolor}, $OPT{bot_fgcolor}, $OPT{bot_linkcolor}, $OPT{bot_alinkcolor}, $OPT{bot_vlinkcolor}, ) unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 insert_template(*TT, $i, $OPT{bottom_template}); print TT "\n\n"; close(TT); } # create_bot_page sub gen_contents { #-------------------------------------------- # get parameters my ($file, $id)=@_; ($li_start, $li_end) = set_bullet(); my ($c_indent_0, $c_indent_1) = ("", ""); for (my $i=0; $i < $OPT{contents_indent}; $i++){ $c_indent_0 .= "
      "; $c_indent_1 .= "
    "; } open(CTX, "> $file") or die "Can't open contents slide $file: $!\n"; if (! $OPT{count_only}){ print STDERR " creating $file ... ===> $OPT{contents_header} <===\n" if $verbose; } my $hd; my @TREE; my $c_li_start = $OPT{no_contents_bullets} ? "

    " : $li_start; my $c_li_end = $OPT{no_contents_bullets} ? "

    " : $li_end; my $contents_list_start = $OPT{num_headers} ? "" : $c_li_start; my $contents_list_end = $OPT{num_headers} ? "
    " : $c_li_end; print_HTML_HEAD(*CTX, 0) unless exists $OPT{no_html_header}; # JSTENZEL, 1.01-15 print_HTML_BODY(*CTX, 0, $OPT{toc_back_image}, $OPT{toc_bgcolor}, $OPT{toc_fgcolor}, $OPT{toc_linkcolor}, $OPT{toc_alinkcolor}, $OPT{toc_vlinkcolor}, ) unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 if (!$OPT{frame_set}) { insert_template(*CTX, 0, $OPT{top_toc_template}); } else { create_top_page(0); } print CTX <<"EOT"; $center_header_start

    $OPT{contents_header}

    $center_header_end EOT if ($OPT{tree_applet}){ (my $bgcol = $OPT{toc_bgcolor}) =~ s/#//; print CTX <<"EOT"; $c_indent_0 EOT } else { my $width = $OPT{contents_table_width} ? " width=$OPT{contents_table_width}" : ""; my $tocid = $id ? " id=$id" : ""; print CTX "\n"; print CTX "$c_indent_0\n" unless $OPT{no_contents_indent}; } my $num = ""; for (my $i=1; $i <= $OPT{page_cnt}; $i++) { if ($OPT{num_headers}){ # $hd = $PAGES[$i]->{NUMBER} . " " . $PAGES[$i]->{HD}; $hd = $PAGES[$i]->{HD}; $num = $PAGES[$i]->{NUMBER} . " "; } else { $hd = $PAGES[$i]->{HD}; } my $file = $PAGES[$i]->{FILENAME}; if ($OPT{tree_applet}){ #--------------------- TreeApplet my $level = $PAGES[$i]->{LEVEL}; $TREE[$level] = $hd; # workaround for TreeApplet bug (no / possible ...) $TREE[$level] =~ s#<[UBI]>##ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s###ig; $TREE[$level] =~ s#/#,#g; #my $title = join('/', @TREE[1 .. $level]); my $title = ""; my $slash = ""; foreach my $ww (@TREE[1 .. $level]) { $title .= "$slash$ww" if defined $ww; $slash = "/"; } if ($OPT{frame_set}) { print CTX "\n"; } else { print CTX "\n"; } } else { #--------------------- simple version my $lnk; if ($OPT{java_script_navigation}) { $lnk = "javascript:Nav('top_$file', '$file', 'bot_$file')"; } else { $lnk = $file; } if ($OPT{frame_set}) { $hd = "$hd"; } else { $hd = "$hd"; } if ($OPT{use_css_for_toc}){ $contents_list_end = "

    "; $contents_list_start = "

    {LEVEL}.">"; } print CTX "$contents_list_start $num $hd $contents_list_end\n"; } } # for $i=1; $i <= $OPT{page_cnt}; $i++ if ($OPT{tree_applet}){ #--------------------- TreeApplet if ($idx_cnt and ! $OPT{no_index}){ my $file = "$OPT{slide_prefix}_idx.$OPT{slide_suffix}"; $hd = $OPT{index_header}; if ($OPT{frame_set}) { print CTX "\n"; } else { print CTX "\n"; } } print CTX "\n

    \n$c_indent_1\n"; } else { #----------------------simple version if ($idx_cnt and ! $OPT{no_index}){ $hd = "
    $OPT{index_header}"; if ($OPT{use_css_for_toc}){ $contents_list_end = "

    "; $contents_list_start = "

    "; } print CTX "$contents_list_start $hd $contents_list_end\n"; } print CTX "\n$c_indent_1\n" unless $OPT{no_contents_indent}; print CTX "\n"; } if (!$OPT{frame_set}) { insert_template(*CTX, 0, $OPT{bottom_toc_template}); } print CTX "\n\n"; close(CTX); } # gen_contents sub gen_index { #----------------------------------------------- return unless $idx_cnt; my $index = $PAGES[$idx_page_cnt]->{FILENAME}; $index = "$OPT{slide_dir}/$index"; open(IDX, "> $index") or die "Can't open index slide $index: $!\n"; if (! $OPT{count_only}){ print STDERR " creating $index ... ===> $OPT{index_header} <===\n" if $verbose; } print_HTML_HEAD(*IDX, $idx_page_cnt) unless exists $OPT{no_html_header}; # JSTENZEL, 1.01-15 print_HTML_BODY(*IDX, $idx_page_cnt, $OPT{idx_back_image}, $OPT{idx_bgcolor}, $OPT{idx_fgcolor}, $OPT{idx_linkcolor}, $OPT{idx_alinkcolor}, $OPT{idx_vlinkcolor}, ) unless exists $OPT{no_html_bodytags}; # JSTENZEL, 1.01-15 if (!$OPT{frame_set}) { insert_template(*IDX, $idx_page_cnt, $OPT{top_idx_template}); } print IDX <<"EOT"; $center_header_start

    $OPT{index_header}

    $center_header_end EOT print IDX "

    \n"; foreach my $LL ('A'..'Z'){ # proposal: simplifying list (ste) if (defined $IDX_{$LL}){ print IDX " $LL"; } else { print IDX " $LL"; } } print IDX "

    \n"; my $file_toc = $PAGES[0]->{FILENAME}; print IDX "$OPT{contents_header}\n"; print IDX "\n
    \n"; my $last_LETTER = ""; my $LETTER = ""; my $LIST_END = ""; #print STDERR join "\n", sort keys %INDEX, "\n" if $verbose; foreach my $idx (sort keys %INDEX) { my $file; my $anchor; my $sep = " "; my $mfirst = 1; for (my $ii=0; $ii < @{$INDEX{$idx}->{A}}; $ii++){ $anchor = ${$INDEX{$idx}->{A}}[$ii]; my $val = "
    " . ${$INDEX{$idx}->{V}}[$ii]; if ($anchor =~ /index_(\d+)/){ my $pg = $1; $LETTER = uc substr($idx,0,1); if ($LETTER ne $last_LETTER){ print IDX $LIST_END; $LIST_END = "\n"; print IDX "\n"; my $ltr; if ($LETTER eq "-"){ $ltr = "special"; } elsif ($LETTER eq "1"){ $ltr = "0-9"; } else { $ltr = $LETTER; } print IDX "

    $ltr

    \n"; print IDX "
      \n"; } $last_LETTER = $LETTER; $file = $PAGES[$pg]->{FILENAME}; print IDX $val if ($mfirst); $mfirst = 0; my $seite = "$sep$pg"; if ($OPT{num_headers}){ $seite = $sep . $PAGES[$pg]->{NUMBER}; } $sep=", "; my $lnk; if ($OPT{java_script_navigation} and !$OPT{tree_applet}) { $lnk = "javascript:Nav('top_$file', '$file#$anchor', 'bot_$file')"; } else { $lnk = $file; } if ($OPT{frame_set}){ if ($OPT{tree_applet}){ print IDX "$seite\n"; } else { print IDX "$seite\n"; # anchor is inside java script call } } else { print IDX "$seite\n"; } } } # values for $idx } print IDX "\n
    \n"; if (!$OPT{frame_set}) { insert_template(*IDX, $idx_page_cnt, $OPT{bottom_idx_template}); } print IDX "\n"; close(IDX); } # gen_index sub reverse_order { #------------------------------------------- # use FILENAMEs in reverse order my $max = $OPT{page_cnt}; for (my $i=1; $i < $max/2; $i++){ ($PAGES[$i]->{FILENAME}, $PAGES[$max+1-$i]->{FILENAME}) = ($PAGES[$max+1-$i]->{FILENAME}, $PAGES[$i]->{FILENAME}) } } # reverse_order sub gen_navigation { #------------------------------------------ # caclulate navigation: next, prev, up and down page numbers my $k; my ($up, $down, $first, $last); my ($prev_level, $level); my @NUM = (-999, 0); # page numbers have the form $NUM[1].$NUM[2].$NUM[3] ... my @NFIRST; # page index of current first page in level $k my @NLAST; # page index of current last page in level $k my @NUP; # page index of current up page in level $k $prev_level = 0; foreach (my $i = 1; $i <= $OPT{page_cnt}; $i++){ $level = $PAGES[$i] -> {LEVEL}; if ($level == $prev_level){ $NUM[$level]++; $PAGES[$i] -> {UP} = $up; $PAGES[$i] -> {DOWN} = -1; $PAGES[$i] -> {LAST} = -1; $PAGES[$i] -> {NEXT} = -1; $PAGES[$i] -> {FIRST} = $first; $PAGES[$i] -> {PREV} = $i-1; $PAGES[$i-1] -> {NEXT} = $i; } elsif ($level > $prev_level) { $NUM[$level] = 1; $NUM[$level + 1] = 0; # prepare next level $up = $i-1; $first = $i; $NUP[$level] = $up; $NFIRST[$level] = $first; $PAGES[$up] -> {DOWN} = $i; $PAGES[$i] -> {UP} = $up; $PAGES[$i] -> {DOWN} = -1; $PAGES[$i] -> {LAST} = -1; $PAGES[$i] -> {FIRST} = $first; if ($OPT{linear_mode}){ $PAGES[$i] -> {PREV} = $i-1; $PAGES[$i-1] -> {NEXT} = $i; } else { $PAGES[$i] -> {PREV} = -1; $PAGES[$i] -> {NEXT} = -1; } } else { $NUM[$level]++; for (my $l = $prev_level; $l >= $level; $l--){ $last = $NLAST[$l]; if (defined($NFIRST[$l])){ # TODO check, Problem ?? for ($k=$NFIRST[$l]; $k<=$last; $k++){ if ($PAGES[$k]->{LEVEL} == $l){ $PAGES[$k] -> {LAST} = $last; } } } } $first = $NFIRST[$level]; $up = $NUP[$level]; $PAGES[$i] -> {DOWN} = -1; $PAGES[$i] -> {UP} = $up; $PAGES[$i] -> {FIRST} = $first; $PAGES[$i] -> {LAST} = -1; if ($OPT{linear_mode}){ $PAGES[$i] -> {PREV} = $i-1; $PAGES[$i-1] -> {NEXT} = $i; } else { $PAGES[$i] -> {PREV} = $NLAST[$level]; $PAGES[$NLAST[$level]] -> {NEXT} = $i; } } $NLAST[$level] = $i; my $number = $NUM[1]; for ($k=2; $k<=$level; $k++){ $number = "$number.$NUM[$k]"; } $PAGES[$i] -> {NUMBER} = $number; $prev_level = $level; } # fix last pointers $NFIRST[0] = 0; $NLAST[0] = $OPT{page_cnt}; # print STDERR "NFIRST @NFIRST\n" if $verbose; # print STDERR "NLAST @NLAST\n" if $verbose; for (my $l=$prev_level; $l >= 0; $l--){ my $lst = $NLAST[$l]; # TODO: check, if defined $k, $lst IF NOT: header level missing ?? # warn user with a meaningfull message! for ($k=$NFIRST[$l]; $k<=$lst; $k++){ if ($PAGES[$k]->{LEVEL} == $l){ $PAGES[$k] -> {LAST} = $lst; } } } } # gen_navgation # test print sub pr_navigation_table { #------------------------------------- print STDERR " i number next prev up down first last\n" if $verbose; for (my $i=1; $i <= $OPT{page_cnt}; $i++){ printf( STDERR "%4d %7s %6s %6s %6s %6s %6s %6s %s\n", $i, $PAGES[$i] -> {NUMBER}, $PAGES[$i] -> {NEXT}, $PAGES[$i] -> {PREV}, $PAGES[$i] -> {UP}, $PAGES[$i] -> {DOWN}, $PAGES[$i] -> {FIRST}, $PAGES[$i] -> {LAST}, $PAGES[$i] -> {HD} ); } } # pr_navigation_table sub start_new_page { #------------------------------------------ my ($level, $shortcut, @BF) = @_; # modified interface: added shortcut (ste, patch 1.01-07) $OPT{page_cnt} ++; my $headline = join('', @BF); # ste # now handle special escapes: #$HEADLINE_PATH[$level]=escapes($headline); #print "$headline\n"; #$headline =~ s!\\E<([^>]+)>!\&$1;!g; $HEADLINE_PATH[$level]=$headline; $shift_level=1; my $pgn = sprintf("%04d", $OPT{page_cnt}); my $filename=join('', $OPT{slide_prefix}, exists $OPT{slide_md5} ? md5_hex(join('|', @HEADLINE_PATH[1..$level])) : $pgn, '.', $OPT{slide_suffix}, ); # ste $HEADLINE_PATHS[$level]=join('', qq(), ($OPT{headline_shortcuts} and $shortcut) ? $shortcut : $headline, ''); # ste, patch 1.01-08 $PAGES[$OPT{page_cnt}] = { BODY => [], LEVEL => $level, FILENAME => $filename, HD => $HEADLINE_PATH[$level], # ste HDS => ($OPT{headline_shortcuts} and $shortcut) ? $shortcut : $HEADLINE_PATH[$level], # (ste, patch 1.01-07) LOC => join(' / ', exists $OPT{bootstrapaddress} ? qq(Start) : (), @HEADLINE_PATHS[1..($level-1)]), # (JSTENZEL, patch 1.01-08, patch 1.01-10) }; $page_ref = $PAGES[$OPT{page_cnt}] -> {BODY}; my $hd = $PAGES[$OPT{page_cnt}] -> {HD}; $ANCHOR{$hd} = $OPT{page_cnt}; # insert anchor for this page #$ANCHOR{join('|', @HEADLINE_PATH[1..$level])}=$OPT{page_cnt}; # ste: insert a composite anchor for this page # my $gg=""; # my $slash = ""; # foreach my $ww(@HEADLINE_PATH[1..$level]) { # $gg .= "$slash$ww" if defined $ww; # $slash = "|"; # } my $gg = _mk_composite_hd($level); $ANCHOR{$gg}=$OPT{page_cnt}; # ste: insert a composite anchor for this page push @{$PAGES[$OPT{page_cnt}]->{BODY}}, ""; # 1.01-18, JSTENZEL } # start_new_page sub _mk_composite_hd{ # ---------------------------------------- my ($level) = @_; my $gg = ""; my $slash = ""; foreach my $ww(@HEADLINE_PATH[1..$level]) { $gg .= "$slash$ww" if defined $ww; $slash = "|"; } return $gg; } # _mk_composite_hd sub handleSimple { #-------------------------------------------- # simple directive handlers if ($xref_open) { push @image_buffer, escapes($_[2]); } else { push @BUFFER, escapes($_[2]); } } # handleSimple { # scopy (ste, patch 1.01-07) my $shortcut; sub handleHeadline { #----------------------------------------- # $_[2] contains the level number of this header, $_[4] the headline shortcut if ($_[1]==DIRECTIVE_START) { $shortcut=$_[4]; flush; } else { start_new_page($_[2], $shortcut, @BUFFER); # (ste, patch 1.01-07) # add headline unless suppressed (ste, patch 1.01-06) unless ($OPT{hide_headers}) { push_page $page_ref, "\n$center_header_start\n

    _PG_NUM_"; my $headline = join('', @BUFFER); $headline =~ s!\\E<([^>]+)>!\&$1;!g; push_page $page_ref, "$headline\n

    $center_header_end\n"; } @BUFFER = (); } } # handleHeadline } sub handleVarSet { #-------------------------------------------- # ste # store new value push(@{$variables{$_[2]{var}}}, [$OPT{page_cnt}, $_[2]{value}]); } # handleVarset sub handleVarReset { #------------------------------------------ # ste # flag that all declared variables were deleted # (flag it by an array reference, which cannot be passed as # a variable value) push(@{$variables{$_}}, [$OPT{page_cnt}, []]) foreach keys %variables; } # handleVarReset sub set_bullet { #---------------------------------------------- my ($li_start, $li_end) = ($default_li_start, $default_li_end); if (defined $BULLETS[$shift_level]) { if ($BULLETS[$shift_level] !~ /^
  • *\n); $li_end = "\n\n"; } } return ($li_start, $li_end); } # set_bullet # TODO Anfangswert bei fortgefuehrten OL setzen sub handleList { #---------------------------------------------- flush; # print Dumper @_; if ($_[0]==DIRECTIVE_ULIST){ $LIST = "UL"; } elsif ($_[0]==DIRECTIVE_OLIST){ if (defined $_[2] and $_[1] == DIRECTIVE_START) { $lcnt = $_[2]; } $LIST = "OL"; } elsif ($_[0]==DIRECTIVE_DLIST){ $LIST = "DL"; } if ($_[1]==DIRECTIVE_START){ push_page $page_ref, "\n<$LIST>\n"; } else { push_page $page_ref, "\n"; @BUFFER = (); } } # handleList sub end_list_indentation { #------------------------------------ # to be used before each paragarph which is not a list ## ## THIS IS NOT PERFECT: it breaks continued shifted lists which are ## interrupted by text or examples ... ## I would prefer to be able to use a 1; $i--){ push_page $page_ref, "\n"; } } # end_list_indentation sub handlePoint { #--------------------------------------------- flush; ($li_start, $li_end) = set_bullet(); if ($_[1]==DIRECTIVE_START){ if ($LIST eq "OL"){ # if (defined $_[2]) { # push_page $page_ref, "
  • "; # } else { # push_page $page_ref, $lo_start; # } if ($lcnt) { push_page $page_ref, "
  • "; $lcnt = 0; } else { push_page $page_ref, "
  • "; } } else { push_page $page_ref, $li_start; } } else { if ($LIST eq "OL"){ push_page $page_ref, $lo_end; } else { push_page $page_ref, $li_end; } @BUFFER = (); } } # handlePoint sub handleDPoint { #-------------------------------------------- flush; if ($_[1]==DIRECTIVE_START){ push_page $page_ref, "
    \n"; } else { push_page $page_ref, "\n\n"; @BUFFER = (); } } # handleDPoint sub handleDPointItem { #---------------------------------------- flush; if ($_[1]==DIRECTIVE_START){ # no action } else { push_page $page_ref, "
    \n
    \n"; @BUFFER = (); } } # handleDPointItem sub handleText { #---------------------------------------------- flush; if ($_[1]==DIRECTIVE_START){ end_list_indentation(); push_page $page_ref, "\n\n

    \n"; } else { push_page $page_ref, "\n

    \n"; } } # handleText sub handleBlock { #--------------------------------------------- # code block with TAG recognition handleVerbatim( $_[0], $_[1], $_[2]); } # handleBlock sub handleLShift { #-------------------------------------------- my $level = defined $_[2] ? $_[2] : 0; if ($_[1]==DIRECTIVE_START){ for (my $i=1; $i<= $level; $i++){ push_page $page_ref, "\n"; $shift_level --; } } } # handleLShift sub handleRShift { #-------------------------------------------- my $level = defined $_[2] ? $_[2] : 0; if ($_[1]==DIRECTIVE_START){ for (my $i=1; $i<= $level; $i++){ push_page $page_ref, "
      \n"; $shift_level ++; if (@BULLETS>1){ if (! defined $BULLETS[$shift_level]){ # set last image my $bull = $BULLETS[-1]; $BULLETS[$shift_level] = $bull; } } } } } # handleRShift sub handleVerbatim { #------------------------------------------ # verbatim block without TAG recognition flush; my $bld_on = ""; my $bld_off = ""; if (uc($OPT{boxtext_bold}) eq "OFF"){ $bld_on = ""; $bld_off = ""; } if ($_[1]==DIRECTIVE_START){ end_list_indentation(); push_page $page_ref, "\n$block_indent_0\n
      \n";
          push_page $page_ref, "$bld_on\n";
        } else {
          push_page $page_ref, "$bld_off
      $block_indent_1\n"; } } # handleVerbatim sub handleComment { #------------------------------------------- @BUFFER = (); # skip buffer contents } # handleComment sub handleTag { #----------------------------------------------- # special tags if ($_[2] eq "C") { # if ($_[1]==DIRECTIVE_COMPLETE) { push @BUFFER , ""; } else { push @BUFFER , ""; } return; } # if ($_[2] eq "E") { # if ($_[1]==DIRECTIVE_COMPLETE) { push @BUFFER , ";"; } else { push @BUFFER , "\&"; } return; } # if ($_[2] eq "MBOX"){ # flush; # if ($_[1]==DIRECTIVE_START){ # push_page $page_ref, "\\mbox{"; # } else { # push_page $page_ref, "}\$"; # } return; } # # character formatting Tags: handle B I U SUP SUB if ($_[2] eq "B" or $_[2] eq "I" or $_[2] eq "U" or $_[2] eq "SUB" or $_[2] eq "SUP" ){ # if ($_[1]==DIRECTIVE_START){ push @BUFFER , "<$_[2]>"; } else { push @BUFFER , ""; } return; } # if ($_[2] eq "LINE_BREAK" or $_[2] eq "BR") { # if ($_[1]==DIRECTIVE_COMPLETE) { @BUFFER = (); push_page $page_ref, "
      \n"; } else { flush; } return; } # if ($_[2] eq "HR" ) { # horizontal line if ($_[1]==DIRECTIVE_COMPLETE) { @BUFFER = (); push_page $page_ref, "
      \n"; } else { flush; } return; } # if ($_[2] eq "BOXCOLORS") { # box color flush; if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'fg'} and !defined $_[3]->{'bg'} and !defined $_[3]->{'set'} ) { die "*** ERROR: BOXCOLORS without 'fg' or 'bg' or 'set' parameter\n"; } if (defined $_[3]->{'fg'}){ $box_fg_color = $_[3]->{'fg'}; } if (defined $_[3]->{'bg'}){ $box_bg_color = $_[3]->{'bg'}; } if (defined $_[3]->{'set'} and $_[3]->{'set'} eq "default") { $box_bg_color = $default_box_bg_color; $box_fg_color = $default_box_fg_color; } } return; } # if ($_[2] eq "BOXCOLOR") { # box color if ($_[1]==DIRECTIVE_COMPLETE) { $box_bg_color = $BUFFER[0]; @BUFFER = (); } else { warn "Obsolete \\BOXCOLOR tag detected. Please use the new\n". " \\BOXCOLORS{fg=xxx bg=yyy} tag instead!\n"; flush; } return; } # if ($_[2] eq "BOXTEXT") { # box text color if ($_[1]==DIRECTIVE_COMPLETE) { $box_fg_color = $BUFFER[0]; @BUFFER = (); } else { warn "Obsolete \\BOXTEXT tag detected. Please use the new\n". " \\BOXCOLORS{fg=xxx bg=yyy} tag instead!\n"; flush; } return; } # if ($_[2] eq "PAGE_COLORS") { # page color flush; if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'fg'} and !defined $_[3]->{'bg'} and !defined $_[3]->{'link'} and !defined $_[3]->{'alink'} and !defined $_[3]->{'vlink'} ) { die "*** ERROR: PAGE_COLORS without valid color parameter\n"; } if (defined $_[3]->{'fg'}){ $PG_COLOR[$OPT{page_cnt}]{fgcolor} = $_[3]->{'fg'}; } if (defined $_[3]->{'bg'}){ $PG_COLOR[$OPT{page_cnt}]{bgcolor} = $_[3]->{'bg'}; } if (defined $_[3]->{'link'}){ $PG_COLOR[$OPT{page_cnt}]{linkcolor} = $_[3]->{'link'}; } if (defined $_[3]->{'alink'}){ $PG_COLOR[$OPT{page_cnt}]{alinkcolor} = $_[3]->{'alink'}; } if (defined $_[3]->{'vlink'}){ $PG_COLOR[$OPT{page_cnt}]{vlinkcolor} = $_[3]->{'vlink'}; } } return; } # if ($_[2] eq "IMAGE") { # image flush; if ($_[1]==DIRECTIVE_COMPLETE) { $imge_cnt++; if ( !defined $_[3]->{'src'}) { die "*** ERROR: Image without 'src' parameter\n"; } my $img; my $source = $_[3]->{'src'}; # pathname of image # if ( defined $_[3]->{'__loaderpath__'}) { # if ( $_[3]->{'src'} =~ /^\//){ # $source = $_[3]->{'src'}; # absolute source path ... # } else { # $source = $_[3]->{'__loaderpath__'}. "/". $_[3]->{'src'}; # relative to __loaderpath__ # } my $cwd = cwd(); $img = basename($source); if ( is_abs_path($source)){ # ok: seems to be absolute path; # do not change } elsif (-e "$cwd/$source") { $source = "$cwd/$source"; # $source seems to be relative to cwd } else { # not ok: seems to be absolute path warn "\m*** image source could not be located: $source\n"; } # print "\nX img: $img\nX source: $source\n"; update_file($source, "$OPT{image_dir}/$img", $verbose, \%OPT, $OPT{mv2targetdir}); # } #my $file = $_[3]->{'src'}; my $file = "$OPT{image_ref}/$img"; # print "OPT image_ref: ", $OPT{image_ref}, "\n"; # print "img: $img, --> file: $file\n"; my $opt = ""; if ( defined $_[3]->{'height'}) { my $height = $_[3]->{'height'}; $opt .= " HEIGHT=\"$height\""; } if ( defined $_[3]->{'border'}) { my $border = $_[3]->{'border'}; $opt .= " BORDER=\"$border\""; } if ( defined $_[3]->{'width'}) { my $width = $_[3]->{'width'}; $opt .= " WIDTH=\"$width\""; } if ( defined $_[3]->{'align'}) { my $align = $_[3]->{'align'}; $opt .= " ALIGN=\"$align\""; } if ( defined $_[3]->{'alt'}) { my $alt = $_[3]->{'alt'}; $opt .= " ALT=\"$alt\""; } else { $opt .= " ALT=\"$file\""; } if ($xref_open){ push @image_buffer, ""; } else { push_page $page_ref, ""; } } return; } # if ($_[2] eq "F" ) { # set color and size flush; if ($_[1]==DIRECTIVE_START){ my $params = ""; if ( defined $_[3]->{'face'}) { $params = "$params FACE=$_[3]->{'face'}"; } if ( defined $_[3]->{'color'}) { $params = "$params COLOR=$_[3]->{'color'}"; } if ( defined $_[3]->{'size'}) { $params = "$params SIZE=$_[3]->{'size'}"; } push_page $page_ref, ""; } else { push_page $page_ref, ""; } return; } # if ($_[2] eq "A") { # Anchor Tag flush; # print STDERR "@_\n" if $verbose; # print STDERR Dumper($_[3]) if $verbose; if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'name'}) { die "*** ERROR: Anchor without 'name' parameter\n"; } my $a_name = escapes($_[3]->{'name'}); push_page $page_ref, ""; # Remember page number for later reference: if (defined $ANCHOR{$a_name}){ pp_warn "anchor name $a_name used twice !!\n"; } else { $ANCHOR{$a_name} = $OPT{page_cnt}; } } return; } # if ($_[2] eq "L") { # general URL if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'url'}) { pp_warn "*** ERROR: Hyperlink \\L without 'url' parameter\n"; } my $link_text = join("",@BUFFER); @BUFFER = (); my $target = ""; push_page $page_ref, "$link_text"; } else { flush; my $url = $_[3]->{'url'} || ""; my $target = ""; if (defined $_[3]->{target}){ $target = $_[3]->{target}; $target = " target=\"$target\""; } push_page $page_ref, ""; } return; } # if ($_[2] eq "URL") { # general URL if ($_[1]==DIRECTIVE_START) { if ( !defined $_[3]->{'url'}) { pp_warn "*** ERROR: Hyperlink \\URL without 'url' parameter\n"; } flush; my $url = $_[3]->{'url'} || ""; my $target = ""; if (defined $_[3]->{target}){ $target = $_[3]->{target}; $target = " target=\"$target\""; } push_page $page_ref, ""; push_page $page_ref, "$url"; } return; } # if ($_[2] eq "PAGEREF") { # page reference if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'name'}) { pp_warn "*** ERROR: PAGEREF without 'name' parameter\n"; } my $a_name = escapes($_[3]->{'name'}); push_page $page_ref, "_INTERN_PAGE:$a_name:_END"; # to be replaced later ... } else { flush; } return; } # if ($_[2] eq "SECTIONREF") { # section header reference if ($_[1]==DIRECTIVE_COMPLETE) { if ( !defined $_[3]->{'name'}) { pp_warn "*** ERROR: SECTIONEREF without 'name' parameter\n"; } my $a_name = escapes($_[3]->{'name'}); push_page $page_ref, "_INTERN_SECTION:$a_name:_END"; # to be replaced later ... } else { flush; } return; } # if ($_[2] eq "XREF") { # internal cross reference if ($_[1]==DIRECTIVE_COMPLETE) { $xref_open = 0; if ( !defined $_[3]->{'name'}) { pp_warn "*** ERROR: XREF without 'name' parameter\n"; } my $ref_text = join("", @image_buffer, @BUFFER); @BUFFER = (); @image_buffer = (); my $a_name = escapes($_[3]->{'name'}); push_page $page_ref, "_INTERN_XREF:$a_name:TXT:$ref_text:_END"; # to be replaced later ... } else { flush; $xref_open = 1; } return; } # if ($_[2] eq "REF") { # (cross) reference # plain text? (never has a body) if ($_[3]->{type} eq 'plain') { # insert just the referenced value present($_[3]->{__value__}) if $_[1]==DIRECTIVE_START; # link? } elsif ($_[3]->{type} eq 'linked') { # catch target my $target=$_[3]->{name}; $target=~s/\s*\|\s*/\|/g; # is there a body? if ($_[3]->{__body__}) { # Yes, there is a body. This is equal to XREF. Act mode dependend. if ($_[1]==DIRECTIVE_COMPLETE) { $xref_open = 0; my $ref_text = join("", @image_buffer, @BUFFER); @BUFFER = (); @image_buffer = (); $target = escapes($target); # ste, patch 1.01-05 push_page $page_ref, "_INTERN_XREF:$target:TXT:$ref_text:_END"; # to be replaced later ... } else { flush; $xref_open = 1; } } else { # No body: this means the referenced value becomes the linked text. push_page $page_ref, "" . $_[3]->{__value__} . "" if $_[1]==DIRECTIVE_START; } } else {die "[BUG] Unhandled case $_[3]->{type}."} return; } # REF if ($_[2] eq "SEQ") { # # act mode dependend (all we have to do is to present a number) # (patch 1.01-02 applied by ste) if ($_[1]==DIRECTIVE_START) { unless (exists $_[3]->{name}) {push_page $page_ref, $_[3]->{__nr__};} else { # copied from "A" handling my $a_name = escapes($_[3]->{'name'}); push_page $page_ref, "$_[3]->{__nr__}"; # Remember page number for later reference: if (defined $ANCHOR{$a_name}){ pp_warn "anchor name $a_name used twice !!\n"; } else { # $ANCHOR{$a_name} = $OPT{page_cnt}; } # } } return; } # SEQ #TODO: \X in Ueberschriften fuehrt zu falscher Position des Anker if ($_[2] eq "X") { # index entry if ($_[1]==DIRECTIVE_COMPLETE) { my $idx = join("",@BUFFER); # text of index entry $idx_cnt ++; my $key_idx = $idx; # key $key_idx =~ s/Ä/Ae/g; $key_idx =~ s/Ü/Ue/g; $key_idx =~ s/Ö/Oe/g; $key_idx =~ s/ä/ae/g; $key_idx =~ s/ü/ue/g; $key_idx =~ s/ö/oe/g; $key_idx =~ s/ß/ss/g; $key_idx =~ tr/A-Z/a-z/; $key_idx = htm2char($key_idx); # translate to char for sorting purpose if ($key_idx =~ /^[0-9]/){ $key_idx = "1$key_idx"; } elsif ($key_idx =~ /^[a-zA-Z]/){ # no action } else { $key_idx = "-$key_idx"; } my $index_anchor = "index_$OPT{page_cnt}" . "_$idx_cnt"; # uniq anchor name if (!defined ($INDEX{$key_idx}->{A})){ $INDEX{$key_idx}->{A} = [$index_anchor]; $INDEX{$key_idx}->{V} = [$idx]; } else { push @{$INDEX{$key_idx}->{A}}, $index_anchor; push @{$INDEX{$key_idx}->{V}}, $idx; } $IDX_{ uc substr($key_idx,0,1) } = 1; push_page $page_ref, ""; if ( defined $_[3]->{'mode'} and $_[3]->{'mode'} eq "index_only"){ @BUFFER = (); } } else { flush; } return; } # if ($_[2] eq "TABLE") { # TABLE flush; if ($_[1]==DIRECTIVE_START) { if ( !defined $_[3]->{'separator'}) { # pp_warn "*** ERROR: TABLE without 'separator' parameter\n"; } my $sep = $_[3]->{'separator'}; my $table_bgcolor=""; my $border="border=2"; if ( defined $_[3]->{'border'}) { $border="BORDER=\"$_[3]->{'border'}\""; } if ( defined $_[3]->{'class'}) { $border="class=\"$_[3]->{'class'}\""; } if ( defined $_[3]->{'bgcolor'}) { $table_bgcolor=" BGCOLOR=\"$_[3]->{'bgcolor'}\""; } push_page $page_ref, ""; if ( defined $_[3]->{'head_bgcolor'}) { $table_hl_bgcolor=" BGCOLOR=\"$_[3]->{'head_bgcolor'}\""; } undef @TABLE_COLUMN_ALIGN; if ( defined $_[3]->{'column_align'}) { @TABLE_COLUMN_ALIGN = split "", $_[3]->{'column_align'}; foreach my $al (@TABLE_COLUMN_ALIGN){ if ($al !~ /^[lcr]$/){ pp_warn "*** WARNING: wrong alignment character in 'column_align' paramter ... ignored\n"; $al = ""; } } } } else { push_page $page_ref, "
      \n

      \n"; } return; } # if ($_[2] eq "TABLE_HL") { # TABLE Headline if ( join("", @BUFFER) =~ /^\s*$/){ $td_was_empty = 1; } else { $td_was_empty = 0; } flush; if ($_[1]==DIRECTIVE_START) { $table_column ++ ; # column counter my $align = ""; if (defined $TABLE_COLUMN_ALIGN[$table_column] and $TABLE_COLUMN_ALIGN[$table_column]){ $align = " " . tab_align($TABLE_COLUMN_ALIGN[$table_column]); } push_page $page_ref, ""; } else { if ($td_was_empty) { push_page $page_ref, "\ "; } push_page $page_ref, ""; } return; } # if ($_[2] eq "TABLE_ROW") { # TABLE Row flush; if ($_[1]==DIRECTIVE_START) { push_page $page_ref, "\n"; $table_column = -1; # column counter } else { push_page $page_ref, "\n"; $table_hl_bgcolor=""; } return; } # if ($_[2] eq "TABLE_COL") { # TABLE Column if ( join("", @BUFFER) =~ /^\s*$/){ $td_was_empty = 1; } else { $td_was_empty = 0; } flush; if ($_[1]==DIRECTIVE_START) { $table_column ++ ; # column counter my $align = ""; if (defined $TABLE_COLUMN_ALIGN[$table_column] and $TABLE_COLUMN_ALIGN[$table_column]){ $align = " " . tab_align($TABLE_COLUMN_ALIGN[$table_column]); } push_page $page_ref, ""; } else { if ($td_was_empty) { push_page $page_ref, "\ "; } push_page $page_ref, ""; } return; } # if ($_[2] eq "EMBED") { # embeded HTML flush; if ($_[1]==DIRECTIVE_START) { if ( !defined $_[3]->{'lang'}) { pp_warn "*** ERROR: EMBED without 'lang' parameter\n"; } elsif ($_[3]->{'lang'} =~ /HTML/i){ $embedded_html = 1; } } else { $embedded_html = 0; } @BUFFER=(); return; } # if ($_[2] eq "INDEXRELATIONS") { # index relation based cross reference, first trial implementation, jstenzel if ($_[1]==DIRECTIVE_START) { # get headline data my $data=$backend->headlineIds2Data([map {$_->[0]} @{$_[3]->{__data}}]); # write intro text, if necessary push_page($page_ref, "\n$_[3]->{intro}\n") if $_[3]->{intro}; # make it into a list: open list push_page($page_ref, "\n\n", $_[3]->{format} eq 'numbers' ? '' : $_[3]->{format} eq 'enumerated' ? '

        ': '
          ', "\n" ); # transform data into the format feed to LOCALTOC @$data=map {[@{$_}[3, 4]]} @$data; # fill list for (@$data){ my $link = escapes($_->[1]); push_page($page_ref, $_[3]->{format} eq 'numbers' ? "_INTERN_PAGE:".$link.":_END" : '
        • ', ' ', $_[3]->{type} eq 'linked' ? "_INTERN_SECTION:".$link.":_END" : $_->[1], # ste $_[3]->{format} eq 'numbers' ? "
          " : '
        • ', ) } # close list push_page($page_ref, "\n", $_[3]->{format} eq 'numbers' ? '' : $_[3]->{format} eq 'enumerated' ? '
      ': '
    ', "\n\n" ); } return; } # if ($_[2] eq 'LOCALTOC') { # ste, ldo # act mode dependend - we only need to handle this once, there is no tag body if ($_[1]==DIRECTIVE_START) { # get local toc my $toc=$backend->toc( $backend->currentChapterNr, exists $_[3]->{depth} ? $_[3]->{depth} : 0, ); # anything found? (following code patched by ste, patch 1.01-03) if (@$toc) { # make it into a list: open list push_page($page_ref, "\n\n", $_[3]->{format} eq 'numbers' ? '' : $_[3]->{format} eq 'enumerated' ? '
      ': '
        ', "\n" ); # fill list # print STDERR "================\n", Dumper @HEADLINE_PATH; # print STDERR "^^^^^^^^^^^^^^^^\n", Dumper %ANCHOR; # print STDERR "----------------\nTOC:\n", Dumper(@$toc); for (@$toc){ my $lvl = $_->[0] - 1; my $composite_hd = _mk_composite_hd($lvl); # print STDERR "COMPOSITE $lvl: $composite_hd\n"; my $link = $composite_hd.'|'.escapes($_->[1]); if (! exists $ANCHOR{$link}){ # insert $composite_hd SOMETHING_IN_BETWEEN $_->[1] as reference .... will be completed later $link = $composite_hd. " SOMETHING_IN_BETWEEN|".escapes($_->[1]); } push_page($page_ref, $_[3]->{format} eq 'numbers' ? "_INTERN_PAGE:".$link.":_END" : '
      • ', ' ', $_[3]->{type} eq 'linked' ? "_INTERN_SECTION:".$link.":_END" : $_->[1], # ste $_[3]->{format} eq 'numbers' ? "
        " : '
      • ', ) } # close list push_page($page_ref, "\n", $_[3]->{format} eq 'numbers' ? '' : $_[3]->{format} eq 'enumerated' ? '
    ': '', "\n\n" ); } } # ok, well done return(1); } # pp_warn "unknown or not yet implemented tag: $_[2], $_[1]\n"; } # handleTag sub tab_align { #----------------------------------------------- my $c = shift; if ($c eq "c"){ return 'align="center"'; } elsif ($c eq "r"){ return 'align="right"'; } elsif ($c eq "l"){ return 'align="left"'; } else { return "" } } # tab_align sub handleDocument { #------------------------------------------ if ($_[1]==DIRECTIVE_START) { warn "\n[Info] Document start ($_[2]).\n" if $verbose; } else { warn "\n[Info] Document end ($_[2]).\n" if $verbose; } } # handleDocument sub flush { #--------------------------------------------------- push_page $page_ref, @BUFFER; push @ERRBUFFER, @BUFFER; @BUFFER = (); # trim ERRBUFFER: @ERRBUFFER = grep (!/^\s*$/ ,@ERRBUFFER); for (my $k=1;$k/g; $key_idx =~ s/\</!\>!g; $line =~ s!"!\"!g; foreach my $k (keys %TR) { $line =~ s!$k!$TR{$k}!eg; } return $line; } #" escapes # modified by JSTENZEL, patch 10+11 sub print_HTML_HEAD { #----------------------------------------- my ($f, $page_no) = @_; my ($url_index); if ($idx_cnt and ! $OPT{no_index}) { $url_index = $PAGES[$idx_page_cnt]->{FILENAME}; } else { $url_index = ""; } # patch 1.01-22: ZOOMSTOP/ZOOMRESTART hints for ZoomIndexer, should become optional of course ... print $f <<"EOT"; EOT # add navigation if required if ($OPT{linknavigation}) { # scopy my $tmp; # activate available elements print $f qq( \n) if $tmp=makeLink($page_no, 'FIRST'); print $f qq( \n) if $tmp=makeLink($page_no, 'PREV'); print $f qq( \n) if $tmp=makeLink($page_no, 'NEXT'); print $f qq( \n) if $tmp=makeLink($page_no, 'UP'); print $f qq( \n) if $tmp=makeLink($page_no, 'LAST'); # the contents link is alway available print $f qq( \n); # add the index link a special way, if possible print $f qq( \n) if $idx_cnt and !$OPT{no_index} and $tmp=$PAGES[$idx_page_cnt]->{FILENAME} } # add further meta information, if necessary print $f qq( \n) if $OPT{author}; print $f qq( \n) if $OPT{description}; print $f qq( \n) if $OPT{norobots}; print $f qq( \n) if $OPT{nosmarttags}; print $f "\n\n"; if ($OPT{frame_set} and $OPT{java_script_navigation}) { java($f); } print $f <<"EOT"; $PAGES[$page_no]->{HD} EOT my $xyz = <<"EOT"; EOT if ($OPT{style_sheet}) { # patched: JSTENZEL, 1.01-12-WS2004, 1.01-23-WS2005 print $f < EOT } my $l_prev = makeLink($page_no, 'PREV'); my $l_next = makeLink($page_no, 'NEXT'); my $l_start = makeLink($page_no, 'FIRST'); print $f &javascript_controls($l_start, $l_prev, $l_next, "slide_idx.htm") if $OPT{java_script_controls}; # some perl versions need the & prefix in this case ... print $f < EOT } # print_HTML_HEAD sub print_HTML_BODY { #----------------------------------------- my ($f, $page_no, $back, $bgcolor, $fgcolor, $linkcolor, $alinkcolor, $vlinkcolor) = @_; if ($back) { print $f <<"EOT"; EOT } else { print $f <<"EOT"; EOT } # add validation links, if requested (temporarily disabled) if (exists $OPT{validate} && 0) { print $f <

    Generated ${\( strftime("%c", localtime) )}. Validate: HTML, CSS, Links.

    EOV } } # print_HTML_BODY sub insert_template { #----------------------------------------- my ($f, $page_no, $tpl) = @_; if ($tpl){ open(TPL, "$style_dir/$tpl") or die "Can't open template $style_dir/$tpl: $!\n"; # insert contents of template and replace KEYWORDS my ($txt_first, $txt_last, $txt_next, $txt_prev, $txt_up, $txt_down, $txt_index, $txt_cont); my ($url_first, $url_last, $url_next, $url_prev, $url_up, $url_down, $url_index, $url_cont); ($txt_next, $url_next) = mk_url($page_no, "NEXT"); ($txt_prev, $url_prev) = mk_url($page_no, "PREV"); ($txt_first, $url_first) = mk_url($page_no, "FIRST"); ($txt_last, $url_last) = mk_url($page_no, "LAST"); ($txt_up, $url_up) = mk_url($page_no, "UP"); ($txt_down, $url_down) = mk_url($page_no, "DOWN"); # $url_cont = $OPT{frame_set} ? # $url_cont.'" target="Data' # : $url_cont; #$url_cont = ""; unless (exists $OPT{no_contents}) { $url_cont = $PAGES[0]->{FILENAME}; if ($OPT{java_script_navigation}){ # $url_cont = "javascript:Nav('top_$url_cont', '$url_cont', 'bot_$url_cont')" $url_cont = $url_cont."\" target=\"$OPT{contents_target}" unless $OPT{contents_target} eq ""; } else { if ($OPT{frame_set}){ $url_cont = $url_cont."\" target=\"$OPT{contents_target}" unless $OPT{contents_target} eq ""; } else { $url_cont = $url_cont; } } $url_cont = ""; } else { $url_cont = ''; } # full path (ste, patch 1.01-08) my $pagePath=$PAGES[$page_no]{LOC}||''; #TODO: option index_target $txt_index = ""; if ($idx_cnt and ! $OPT{no_index}) { $url_index = $PAGES[$idx_page_cnt]->{FILENAME}; $url_index = ""; } else { $url_index = ""; } my $pgno; $pgno = $PAGES[$page_no]->{NUMBER}; while(){ # Navigation / Text s/<[\s\w="]*URL_FIRST[\s"]*?>/$url_first/g; s/TXT_FIRST/$txt_first/g; s/<[\s\w="]*URL_LAST[\s"]*?>/$url_last/g; s/TXT_LAST/$txt_last/g; s/<[\s\w="]*URL_PREV[\s"]*?>/$url_prev/g; s/TXT_PREV/$txt_prev/g; s/<[\s\w="]*URL_NEXT[\s"]*?>/$url_next/g; s/TXT_NEXT/$txt_next/g; s/<[\s\w="]*URL_UP[\s"]*?>/$url_up/g; s/TXT_UP/$txt_up/g; s/<[\s\w="]*URL_DOWN[\s"]*?>/$url_down/g; s/TXT_DOWN/$txt_down/g; s/<[\s\w="]*URL_CONTENTS[\s"]*?>/$url_cont/g; s/<[\s\w="]*URL_INDEX[\s"]*?>/$url_index/g; s/\bPAGE_CNT\b/$OPT{page_cnt}/g; s/\bPAGE\b/$pgno/g; s/PAGE_PATH/$pagePath/g; # (JSTENZEL, patch 1.01-08) s/URL_HERE/$PAGES[$page_no]->{FILENAME}/g; # JSTENZEL, patch 1.01-13 $_ = replace_keywords($_, \%OPT); # replace HD Text: # my $hdln = $PAGES[$page_no]->{NUMBER} . " " . $PAGES[$page_no]->{HD}; my $hdln = " " . $PAGES[$page_no]->{HD}; $_ =~ s/HEADLINE/$hdln/; # variables s/VAR\((.+?)\)/variableValue($1, $page_no-1)/ge; print $f $_; } close(TPL); } } # insert_template sub mk_url { #-------------------------------------------------- my ($page_no, $DIR) = @_; my ($txt, $url) = ("", ""); if (defined $PAGES[$page_no]->{$DIR} and $PAGES[$page_no] ->{$DIR} >= 0) { $txt = $PAGES[$PAGES[$page_no] ->{$DIR}] -> {HDS} || ''; # # ste applied patch 1.01-07 $url = $PAGES[$PAGES[$page_no] ->{$DIR}] -> {FILENAME}; if ($page_no == 1 and $DIR eq "PREV" ){ # link to contents page if ($OPT{frame_set} and not $OPT{java_script_navigation}){ #$url = $url.'" target="Index' $url = $url."\" target=\"$OPT{contents_target}" } } $url = $OPT{java_script_navigation} ? "javascript:Nav('top_$url', '$url', 'bot_$url')" : $url; $url = ""; } return ($txt, $url); }# mk_url # make a -Tag / JSTENZEL, patch 1.01-11 sub makeLink { #-------------------------------------------------- # get parameters my ($page_no, $DIR)=@_; # declare variable my $url; if (defined $PAGES[$page_no]->{$DIR} and $PAGES[$page_no]->{$DIR}>=0) { $url=$PAGES[$PAGES[$page_no]->{$DIR}]->{FILENAME}; # link to contents page, if necessary $url=$url."\" target=\"$OPT{contents_target}" if $page_no==1 and $DIR eq "PREV"; } # supply result return ($url); }# makeLink sub replace_internal_links { #---------------------------------- my ($line, $INTERN_TYPE, $REF) = @_; my ($a_name, $txt); # Replace INTERN_TYPE with correct hyperlink while (1) { if ($INTERN_TYPE eq "_INTERN_XREF"){ last if ($line !~ /$INTERN_TYPE:(.*?):TXT:(.*?):_END/); $a_name = $1; $txt = $2 || "UNDEF XREF TEXT"; # ste: clean up composite anchor names $a_name=~s/\s*\|\s*/\|/g; $a_name=_complete_composite($a_name); } else { last if ($line !~ /$INTERN_TYPE:(.*?):_END/); $a_name = $1; # ste: clean up composite anchor names $a_name=~s/\s*\|\s*/\|/g; $a_name=_complete_composite($a_name); $txt = $PAGES[$ANCHOR{$a_name}] -> {$REF}; } if (! defined $ANCHOR{$a_name}) { (my $tag = $INTERN_TYPE) =~ s/_INTERN_/\\/; pp_warn "$tag with undefined anchor name '$a_name' detected\n"; $line =~ s/$INTERN_TYPE:.*?:_END/UNDEF<\/A>/; next; } my $filename = $PAGES[$ANCHOR{$a_name}] -> {FILENAME}; if ( $OPT{java_script_navigation} ) { $line =~ s/$INTERN_TYPE:.*?:_END/$txt<\/A>/; } else { $line =~ s/$INTERN_TYPE:.*?:_END/$txt<\/A>/; } } return $line; } # replace_internal_links sub _complete_composite{ # ------------------------------------- my ($a_name) = @_; # ste: try to complete an incomplete composite anchor if (not defined($ANCHOR{$a_name}) and $a_name=~/\|/) { my $pattern; my @HARR; if ($a_name =~ /(.*) SOMETHING_IN_BETWEEN\|(.*)/){ my $comp_head = $1; my $p1 = quotemeta($comp_head); $pattern=quotemeta($2); @HARR = grep(/^$p1.*\|$pattern$/, sort keys %ANCHOR); } else { $pattern=quotemeta($a_name); @HARR = grep(/\|$pattern$/, sort keys %ANCHOR); } # my $completed=(grep(/\|$pattern$/, sort keys %ANCHOR))[0]; my $completed=defined $HARR[0] ? $HARR[0] : 0; $a_name=$completed if $completed; } return $a_name; } # _complete_composite sub java { #---------------------------------------------------- my $f = shift; print $f < EOT } # java sub variableValue { #------------------------------------------- # ste: resolve a variable # get parameters my ($name, $page)=@_; # declare return value, initialize with empty string my $value=''; # known variable? if (exists $variables{$name}) { # walk through the variables settings # and follow the hints (this is straight # forward, both algorithm and data structure # might be worth to be improved) foreach my $hint (@{$variables{$name}}) { # all done if the hint was stored by # a page with a greater number than ours last if $hint->[0]>$page; # setting or reset? unless (ref($hint->[1])) { # update variable $value=$hint->[1]; } else { # reset variable $value=''; } } } # supply result $value; } # variableValue sub javascript_controls { my ($start, $prev, $next, $index) = @_; # filenames of corresponding slides # outputs javascript code for navigation with mouse click and keyboard # my $code = < // BEGIN controls.js function nextSlide() { EOS if ($next) { $code .= < EOS return $code; } # javascript_controls # end package 1; __END__ # = POD SECTION ============================================== =head1 NAME B - PerlPoint to HTML converter =head1 VERSION This man page describes $Revision: 1.22 $ from PerlPoint::Converters Package 1.0205 =head1 SYNOPSIS pp2html --help pp2html [@options_file] [options] slide_text =head1 DESCRIPTION C creates a set of HTML files for a foilset based on a simple textfile F. Due to its formatting features and the capability of creating navigation, table of contents and index pages, C is also a suitable tool for writing online documentation. A slide is normally made up by a header and a number of bullet items: =Example of a Slide * Contains a head line ("Example of a Slide") * Should have some bullet items * May have footer and/or header section with company logo and navigation links The intention of C is to simply write down your headers and bullet items just like above in an ASCII file and then automatically create a set of HTML files ready for presentation. The main features of C are: =over 4 =item * Simple ASCII input file for your text =item * Optional templates for header and footer of the slides (e.g. for company logo, hyperlinks for navigation, copyright note etc.) =item * Rudimentary formatting capabilities =item * Creation of a contents page with links to all slides =item * Creation of an index page with links to all keywords which have been indexed =item * Optional layout as HTML frame set (header frame, contents frame, footer frame and eventually index frame). The footer frame has always the same position on the screen. =item * The index frame may use a TreeApplet which provides convenient access to all pages. For more information see: http://www.naturallyj.com The PerlPoint-Converters package contains an older version of the tree applet. The new release of the tree applet is not yet supported. =back The following documentation describes in detail the syntax of a pp2html input file and all options of C. =head1 SYNTAX of PerlPoint Files The format for the C input files is called C-Format. For a detailed and possibly more up-to-date description of the C language please refer to the excellent POD documentation of the B Module by Jochen Stenzel. There are the following main components of an input file for C: =over 4 =item * Comments =item * Headers =item * Bullet Items =item * Numbered Lists =item * Definition Lists =item * Paragraphs =item * Blocks =item * Verbatim Blocks =back =head2 Comments Lines which start with a double slash C are treated as comments. They are not included in the slides. =head2 Headers Headers are lines which start with one or more C<=> signs. The number of C<=> signs determines the level of the header: =This is a level 1 header ==This is a level 2 header It is necessary to put a blank line after the header. If you use headers of different levels then you get a structured document with chapter numbering e.g. 1 First chapter 1.1 Subsection 1 1.2 Subsection 2 2 Second chapter The chapter numbers depend on the position of the page and the level of its header. =head2 Bullet Items and Numbered Lists A bullet item is indicated by an asterisk C<*> in the first column. * Item one is very long and continued on the next line * Item 2 * Item Three If you use hash signs C<#> instead of asterisks, the list will autmatically be a numbered list: # First # Second B It is important to put a blank line after each bullet item, otherwise the text on the following line belongs to the same bullet. =head2 Paragraphs Text which is not indented is treated as a normal paragraph. In HTML terminology this is a

    ...

    container. =head2 Blocks Text which is indented by one ore more blanks will be put in a colored box. The text will be treated as I
    .
    Special formatting tags (see below) are still applied.
    
    The HTML representation is a  with colored background
    and the text itself is put into a 
     ... 
    container. =head2 Verbatim Blocks Verbatim Blocks are copied I into the HTML page. Special formatting tags (see below) are not applied. (Only HTML meta characters are escaped, for example the "E" or "E" sign.) This means that Verbatim Blocks are suitable for code examples: Just cut and paste your piece of code into the C input file and put the verbatim box markers around: <EMARK' and ends with the text C on a separate line. This is like a C in perl or in a C-shell. Note: There must not be white space between EE and MARK. Alternatively you can use the \INCLUDE tag with the example option: \INCLUDE{type=example file="filename"} =head2 Special Formatting Tags Some rudimentary formatting is also supported by C. It is similar syntax as in POD: \C \B \I \E \E \E \U \SUP \SUB Note that the tags are preceeded by a backslash. This is necessary because the C format knows several tags that are longer than one character. The general form of C tags is \TAGNAME{param1=value1 param2=value2 ...} The parameter list is optional and enclosed in curly braces. It is possible to switch the box color from case to case with the following tags: \BOXCOLORS{bg=yellow} \BOXCOLORS{fg=blue} or in short: \BOXCOLORS{bg=yellow fg=blue} =head2 Color and text size There is a special tag \F{color=value size=value face=typeface} which allows to set color and size and the typeface for a text. This is translated to the HTML EFONTE tag. =head2 Using Hyperlinks In order to use internal hyperlinks there must be targets for those links. A link target or C is defined by the following tag: \A{name="target_name"} An internal link to this target is written in the form: \PAGEREF{name=target_name} \SECTIONREF{name=target_name} The first link is replaced with the page number of the page which contains the target. The second link is replaced with the page header of the corresponding page. NOTE: Each page automatically gets an anchor with the page header as target name. For this reason it is possible to use SECTIONREF tags with the name=page_title parameter to get inernal links to each page. External hyperlinks have the form: \L{url=http://wwwpixel.de} =head2 Index and Cross References A cross reference to an internal target has the form: \XREF{name=target_name} Index entries are defined by \X \X{mode=index_only} The latter form creates an index entry which appears only in the index. The "word" from the the first form appears in the current text and in the index. B The I form is useful, for example, if you want to have a word from a heading included in the index. The index tag is not allowed inside of a heading. =head1 OPTIONS =over 4 =item --activeContents PerlPoint sources can embed Perl code which is evaluated while the source is parsed. For reasons of security this feature is deactivated by default. Set this option to activate it. You can use I<--safeOpcode> to fine tune which operations shall be permitted. =item --cache parsing of one and the same document several times can be accelerated by activating the PerlPoint parser cache by this option. The performance boost depends on your document structure. Cache files are written besides the source and named "..ppcache". It can be useful to (temporarily) deactivate the cache to get correct line numbers in parser error messages (currently numbers cannot always reported correctly with activated cache because of a special perl behaviour). =item --cacheCleanup PerlPoint parser cache files grow (with every modified version of a source parsed) because they store expressions for every parsed variant of a paragraph. This is usually uncritical but you may wish to clean up the cache occasionally. Use this option to perform the task (or remove the cache file manually). =item --safeOpcode=opcode If active contents is enabled (I<--activeContents>), Perl code embedded into the translated PerlPoint sources will be evaluated. To keep security this is done via an object of class B which restricts code to permitted operations. By this option you can declare which opcode (or opcode tag) is permitted. Please see the B and B manual pages for further details. (These modules come with perl.) Pass C to allow I. This option can be used multiply. You may want to store these options in default option files, see below for details. For the examples used in I you should use --safeOpcode=:filesys_open --safeOpcode=:still_to_be_decided --safeOpcode=:browse =item --set=flag This option allows you to pass certain settings - of your choice - to active contents (like conditions) where it can be accessed via the $PerlPoint hash reference. For example, your PerlPoint code could contain a condition like ? $PerlPoint->{userSettings}{special} Special part. ? 1 The special part enclosed by the two conditions would then be processed I if you call C with --set special and if active contents was enabled by I<-active>, of course. This option can be used multiply. =item --trans_table=filename The C<--trans_table> option specifies a the filename of a tanslation table for non ASCII characters like german Umlaute etc. The characters are specifed as octal numbers as in the folowing example: #Translation Table for German Umlaute (this is the default) \334 Ü \374 ü \326 Ö \366 ö \304 Ä \344 ä \337 ß =item --filter=regexp This specifies a regular expression C which should match all allowed languages for EMBEDed code. The expression is evaluated caseinsensitively. Example: --filter="perl|html" =item --nocopyright suppresses the copyright message; =item --noinfo supresses runtime informations; =item --nowarn supresses warnings; =item --quiet a shortcut for "--nocopyright --noinfo --nowarn": all non critical runtime messages are suppressed; =item --count_only If this option is set, only a counter will indicate that slides are created. Otherwise for all slides the full header is printed while generating the slides. =item --box_color=color =item --boxtext_color=color Set background and forground colors for block paragraphs =item --bgcolor=color =item --fgcolor=color =item --idx_bgcolor=color =item --idx_fgcolor=color =item --toc_bgcolor=color =item --toc_fgcolor=color =item --top_bgcolor=color =item --top_fgcolor=color =item --bot_bgcolor=color =item --bot_fgcolor=color =item --linkcolor=color =item --alinkcolor=color =item --vlinkcolor=color Set the background and foreground color for all HTML pages. The C and C options are for the index page and table of contents respectively. The last three options set the colors for hyperlinks, active links and followed links. The linkcolor options can also be prefixed with C, C, C and C for example C<--toc_linkcolor white>. =item --back_image =item --toc_back_image =item --idx_back_image =item --top_back_image =item --bot_back_image Set background image for nomal slides, table of contents, index, top frame or bottom frame. =item --top_template=filename =item --top_idx_template=filename =item --top_toc_template=filename =item --bottom_template=filename =item --bottom_idx_template=filename =item --bottom_toc_template=filename =item --nav_template=filename =item --nav_top_template=filename =item --nav_bottom_template=filename Filenames for template files (in HTML format). The bottom template is appended to each slide. Can be used to create footers with navigation, copyright note etc. The top template is inserted at the top of each slide. The C<_idx_> templates are used for the index slide and the C<_toc_> templates are used for the table of contents slide. The C and C templates are included in all pages on top, just below the C and at the bottom just before the C. If the C<--nav_template> option is set, the C will be used on top and at the bottom unless you specify C<--nav_top_template> or C<--nav_bottom_template>. The latter both will overwrite the C<--nav_template> option. B Templates should not contain EHTMLE, EHEADE, ETITLEE or EBODYE tags. These tags are always written by C. There is, however, one exception: If you use the C<--frame_set> option without java script navigation (see below), then the top and bottom HTML templates should be directly included in the frame set template and should be full HTML files with HEAD and BODY lines. The following keywords and "function calls" are substituted with corresponding values when the templates are included. (Everything should be completed in the line of its beginning, there's no multiline support built in yet.) TITLE text specified by --title option URL_HERE hyperlink to the current page URL_NEXT hyperlink to next page TXT_NEXT header of next page URL_PREV hyperlink to previous page TXT_PREV header of previous page URL_FIRST hyperlink to first page TXT_FIRST header of first page URL_LAST hyperlink to last page TXT_LAST header of last page URL_UP hyperlink to upper page TXT_UP header of upper page URL_DOWN hyperlink to subsection page TXT_DOWN header of subsection page URL_CONTENTS hyperlink to contents page TXT_CONTENTS text specified by --contents_header URL_INDEX hyperlink to index page TXT_INDEX text specified by --index_header LABEL_NEXT label text for "next" link LABEL_PREV label text for "previous" link LABEL_CONTENTS label text for "contents" link LABEL_INDEX label text for "index" link PAGE page or chapter number PAGE_CNT number of pages PAGE_PATH a clickable "path" of parent slides intended for navigation in deeply nested documents TOP_LEFT_TXT text for left side in top templates, see --top_left_txt TOP_RIGHT_TXT text for right side in top templates, see --top_right_txt TOP_MIDDLE_TXT text for middle in top templates, see --top_middle_txt BOT_LEFT_TXT text for left side in bottom templates, see --bot_left_txt BOT_RIGHT_TXT text for right side in bottom templates, see --bot_right_txt BOT_MIDDLE_TXT text for middle in bottom templates, see --bot_middle_txt LOGO_IMAGE_FILENAME text for the logo image filename in template files, see --logo_image_filename START_ADDRESS start address URL as specified --startaddress DATE() date (and/or time) in the specified C format, (e.g. "DATE(%s)") VAR() insert the current value of the PerlPoint variable $ (e.g. "VAR(version)") OPT(