# -*-perl-*-
#+##############################################################################
#
# tex4ht.pm: use tex4ht to convert tex to html
#
# Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Originally written by Patrice Dumas.
#
#-##############################################################################
# To customize the command and the options, you could set
# $Texi2HTML::TeX4HT::STYLE_MATH to latex/tex
# $Texi2HTML::TeX4HT::STYLE_TEX to latex/texi
# and/or change
# $Texi2HTML::TeX4HT::tex4ht_command_math
# and $Texi2HTML::TeX4HT::tex4ht_options_math
# $Texi2HTML::TeX4HT::tex4ht_command_tex
# and $Texi2HTML::TeX4HT::tex4ht_options_tex
use strict;
if (defined($OUTPUT_FORMAT) and $OUTPUT_FORMAT eq 'html')
{
push @command_handler_init, \&Texi2HTML::TeX4HT::tex4ht_init;
push @command_handler_process, \&Texi2HTML::TeX4HT::tex4ht_process;
# do it once here to have something ready for special regions formatting
push @command_handler_process, \&Texi2HTML::TeX4HT::tex4ht_output;
# do it once more if the file was modified (for example see mediawiki.pm)
push @command_handler_output, \&Texi2HTML::TeX4HT::tex4ht_output;
push @command_handler_finish, \&Texi2HTML::TeX4HT::tex4ht_finish;
$command_handler{'math'} =
{ 'init' => \&Texi2HTML::TeX4HT::tex4ht_to_latex,
'expand' => \&Texi2HTML::TeX4HT::tex4ht_do_tex
};
$command_handler{'tex'} =
{ 'init' => \&Texi2HTML::TeX4HT::tex4ht_to_latex,
'expand' => \&Texi2HTML::TeX4HT::tex4ht_do_tex
};
}
{
use Cwd;
package Texi2HTML::TeX4HT;
use vars qw(
$STYLE_MATH
$STYLE_TEX
$tex4ht_command_math
$tex4ht_command_tex
$tex4ht_options_math
$tex4ht_options_tex
);
$STYLE_MATH = 'texi' if (!defined($STYLE_MATH));
$STYLE_TEX = 'tex' if (!defined($STYLE_TEX));
if (!defined($tex4ht_command_math))
{
$tex4ht_command_math = 'httexi';
$tex4ht_command_math = 'htlatex' if ($STYLE_MATH eq 'latex');
$tex4ht_command_math = 'httex' if ($STYLE_MATH eq 'tex');
}
if (!defined($tex4ht_command_tex))
{
$tex4ht_command_tex = 'httex';
$tex4ht_command_tex = 'htlatex' if ($STYLE_TEX eq 'latex');
$tex4ht_command_tex = 'httexi' if ($STYLE_TEX eq 'texi');
}
my %commands = ();
my $tex4ht_initial_dir;
my $tex4ht_out_dir;
my $tex4ht_latex_failed = 0;
my %tex4ht_results;
sub tex4ht_init
{
# set file names
$tex4ht_initial_dir = Cwd::abs_path;
if ($Texi2HTML::Config::null_device_file{$Texi2HTML::THISDOC{'filename'}->{'top'}})
{
# when output is a null device we skip entirely the tex4ht stuff.
$tex4ht_latex_failed = 1;
return;
}
$tex4ht_out_dir = "$Texi2HTML::THISDOC{'destination_directory'}";
$tex4ht_out_dir = './' if (!defined($tex4ht_out_dir) or $tex4ht_out_dir =~ /^\s*$/);
my $tex4ht_basename = "$Texi2HTML::THISDOC{'file_base_name'}_tex4ht";
%tex4ht_results = ();
$tex4ht_latex_failed = 0;
# this initialization doesn't seems to be needed, but it is cleaner anyway
%commands = ();
$commands{'math'}->{'style'} = $STYLE_MATH;
$commands{'tex'}->{'style'} = $STYLE_TEX;
$commands{'math'}->{'exec'} = $tex4ht_command_math;
$commands{'tex'}->{'exec'} = $tex4ht_command_tex;
foreach my $command ('math', 'tex')
{
my $style = $commands{$command}->{'style'};
$commands{$command}->{'basename'} = $tex4ht_basename . "_$command";
my $suffix = '.tex';
$suffix = '.texi' if ($style eq 'texi');
$commands{$command}->{'basefile'} = $commands{$command}->{'basename'} . $suffix;
$commands{$command}->{'html_file'} = $commands{$command}->{'basename'} . '.html';
$commands{$command}->{'rfile'} = $tex4ht_out_dir . $commands{$command}->{'basefile'};
my $rfile = $commands{$command}->{'rfile'};
local *TEX4HT_TEXFILE;
unless (open (*TEX4HT_TEXFILE, ">$rfile"))
{
main::document_warn ("t2h_tex4ht error opening $rfile: $!");
$tex4ht_latex_failed = 1;
return;
}
$commands{$command}->{'handle'} = *TEX4HT_TEXFILE;
}
foreach my $command ('math', 'tex')
{
$commands{$command}->{'counter'} = 0;
my $style = $commands{$command}->{'style'};
my $fh = $commands{$command}->{'handle'};
my $comment = '@c';
$comment = '%' if ($style ne 'texi');
$comment .= " Automatically generated\n";
if ($style eq 'texi')
{
print $fh "\\input texinfo
\@setfilename $commands{$command}->{'basename'}.info\n";
print $fh "$comment";
}
else
{
print $fh "$comment";
if ($style eq 'latex')
{
print $fh "\\documentstyle{article}\n\\begin{document}\n";
}
elsif ($style eq 'tex')
{
print $fh "\\csname tex4ht\\endcsname\n";
}
}
}
$Texi2HTML::THISDOC{'extensions'}->{'tex4ht'} = 1;
}
sub tex4ht_to_latex
{
my $command = shift;
my $text = shift;
my $counter = shift;
my $style = $commands{$command}->{'style'};
my $fh = $commands{$command}->{'handle'};
# write to tex file
my $before_comment_open = "\@verbatim\n\n";
my $after_comment_open = "\n\@end verbatim\n";
my $before_comment_close = "\@verbatim\n";
my $after_comment_close = "\n\n\@end verbatim\n";
if ($style ne 'texi')
{
$before_comment_open = "\\HCode{\\Hnewline \\Hnewline ";
$after_comment_open = "\\Hnewline}\n";
$before_comment_close = "\\HCode{\\Hnewline ";
$after_comment_close = "\\Hnewline \\Hnewline}\n";
}
my $begin_comment = "";
print $fh "$before_comment_open$begin_comment$after_comment_open";
if ($command eq 'tex')
{
print $fh $text;
}
elsif ($command eq 'math')
{
if ($style eq 'texi')
{
print $fh '@math{' . $text . "}\n";
}
else
{
print $fh "\\IgnorePar \$" . $text . "\$";
}
}
my $end_comment = "";
print $fh "$before_comment_close$end_comment$after_comment_close";
$commands{$command}->{'counter'}++;
return 1;
}
sub tex4ht_process
{
foreach my $command ('math', 'tex')
{
tex4ht_finish_latex($command);
}
unless (chdir $tex4ht_out_dir)
{
main::document_warn ("t2h_tex4ht chdir to $tex4ht_out_dir failed");
$tex4ht_latex_failed = 1;
return;
}
print STDERR "cwd($tex4ht_out_dir):" . Cwd::cwd() ."\n" if (Texi2HTML::Config::get_conf('VERBOSE'));
foreach my $command ('math', 'tex')
{
tex4ht_process_command($command);
}
tex4ht_return_to_dir();
}
my $tex4ht_output_counter;
sub tex4ht_output
{
$tex4ht_output_counter = 0;
unless (chdir $tex4ht_out_dir)
{
main::document_warn ("t2h_tex4ht chdir to $tex4ht_out_dir failed");
$tex4ht_latex_failed = 1;
return;
}
foreach my $command ('math', 'tex')
{
tex4ht_output_command($command);
}
tex4ht_return_to_dir();
}
sub tex4ht_finish_latex
{
#print STDERR "$style $tex4ht_latex_failed $tex4ht_counter\n";
my $command = shift;
return if ($tex4ht_latex_failed);
my $style = $commands{$command}->{'style'};
my $fh = $commands{$command}->{'handle'};
# finish the tex file
if ($style eq 'latex')
{
print $fh "\\end{document}\n";
}
elsif ($style eq 'tex')
{
print $fh "\n\\bye\n";
}
else
{
print $fh "\n\@bye\n";
}
close ($fh);
}
sub tex4ht_process_command($)
{
my $command = shift;
return unless ($commands{$command}->{'counter'});
main::document_warn ("t2h_tex4ht $commands{$command}->{'basefile'} missing") unless (-f $commands{$command}->{'basefile'});
my $style = $commands{$command}->{'style'};
# now run tex4ht
my $options = '';
$options = $tex4ht_options_math if (($style eq 'math') and defined($tex4ht_options_math));
$options = $tex4ht_options_tex if (($style eq 'tex') and defined($tex4ht_options_tex));
my $cmd = "$commands{$command}->{'exec'} $commands{$command}->{'basefile'} $options";
print STDERR "tex4ht command: $cmd\n" if (Texi2HTML::Config::get_conf('VERBOSE'));
if (system($cmd))
{
main::document_warn ("t2h_tex4ht command: $cmd failed");
tex4ht_return_to_dir();
$tex4ht_latex_failed = 1;
return;
}
# this have to be done during the 'process' phase, in 'output' it is
# too late.
push @{$Texi2HTML::THISDOC{'css_import_lines'}}, "\@import \"$commands{$command}->{'basename'}.css\";\n";
}
sub tex4ht_output_command($)
{
my $command = shift;
return unless ($commands{$command}->{'counter'});
# extract the html from the file created by tex4ht
my $html_basefile = $commands{$command}->{'html_file'};
unless (open (TEX4HT_HTMLFILE, $html_basefile))
{
main::document_warn ("t2h_tex4ht error opening $html_basefile: $!");
tex4ht_return_to_dir();
$tex4ht_latex_failed = 1;
return;
}
my $got_count = 0;
my $line;
while ($line = )
{
#print STDERR "$html_basefile: while $line";
if ($line =~ /!-- tex4ht_begin $commands{$command}->{'basename'} (\w+) (\d+) --/)
{
my $command = $1;
my $count = $2;
my $text = '';
my $end_found = 0;
while ($line = )
{
#print STDERR "while search $command $count $line";
if ($line =~ /!-- tex4ht_end $commands{$command}->{'basename'} $command $count --/)
{
$got_count++;
chomp($text);
$tex4ht_results{"${command}_$count"} = $text;
$end_found = 1;
last;
}
else
{
$text .= $line;
}
}
unless ($end_found)
{
main::document_warn ("t2h_tex4ht: end of $command $count not found");
}
}
}
if ($got_count != $commands{$command}->{'counter'} and (Texi2HTML::Config::get_conf('VERBOSE')))
{
main::document_warn ("t2h_tex4ht: got $got_count for $commands{$command}->{'counter'} items entered");
}
close (TEX4HT_HTMLFILE);
}
sub tex4ht_return_to_dir
{
unless (chdir $tex4ht_initial_dir)
{
die "* t2h_tex4ht unable to return to the initial dir\n";
}
}
sub tex4ht_do_tex
{
my $command = shift;
my $counter = shift;
# return the resulting html
if (exists ($tex4ht_results{"${command}_$counter"}) and defined($tex4ht_results{"${command}_$counter"}))
{
$tex4ht_output_counter++;
return $tex4ht_results{"${command}_$counter"};
}
else
{
main::document_warn ("t2h_tex4ht: cannot find text to output for $command number $counter");
return '';
}
}
sub tex4ht_finish
{
my $tex4ht_in_counter = 0;
foreach my $command (keys(%commands))
{
$tex4ht_in_counter += $commands{$command}->{'counter'};
}
if (($tex4ht_output_counter != $tex4ht_in_counter) and (Texi2HTML::Config::get_conf('VERBOSE')))
{
main::document_warn ("t2h_tex4ht: output $tex4ht_output_counter for $tex4ht_in_counter items entered");
}
}
}
1;