|
Packit |
e4b6da |
# vim:sw=4 et sta showmatch
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# db2x_texixml - convert Texi-XML to Texinfo
|
|
Packit |
e4b6da |
# (See docbook2X documentation for details)
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# (C) 2000-2004 Steve Cheng <stevecheng@users.sourceforge.net>
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# See the COPYING file in the docbook2X distribution
|
|
Packit |
e4b6da |
# for the copyright status of this software.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Note: db2x_texixml.pl does not run by itself!
|
|
Packit |
e4b6da |
# It must be configured by including a config.pl file
|
|
Packit |
e4b6da |
# which is done when building docbook2X.
|
|
Packit |
e4b6da |
# In addition, the non-standard module
|
|
Packit |
e4b6da |
# XML::Handler::SGMLSpl must be explicitly loaded
|
|
Packit |
e4b6da |
# when docbook2X is not installed.
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
package main;
|
|
Packit |
e4b6da |
use strict;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Option parsing
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
use Getopt::Long;
|
|
Packit |
e4b6da |
Getopt::Long::Configure('bundling');
|
|
Packit |
e4b6da |
my $cmdoptions = {
|
|
Packit |
e4b6da |
'encoding' => 'us-ascii',
|
|
Packit |
e4b6da |
'list-files' => 0,
|
|
Packit |
e4b6da |
'to-stdout' => 0,
|
|
Packit |
e4b6da |
'output-dir' => '',
|
|
Packit |
e4b6da |
'info' => 0,
|
|
Packit |
e4b6da |
'plaintext' => 0,
|
|
Packit |
e4b6da |
'utf8trans-program' => $db2x_config{'utf8trans-program'},
|
|
Packit |
e4b6da |
'utf8trans-map' => $db2x_config{'utf8trans-map-texi'},
|
|
Packit |
e4b6da |
'iconv-program' => $db2x_config{'iconv-program'},
|
|
Packit |
e4b6da |
'makeinfo-program' => $db2x_config{'makeinfo-program'},
|
|
Packit |
e4b6da |
};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub options_help {
|
|
Packit |
e4b6da |
print "Usage: $0 [OPTION]... [FILE]...\n";
|
|
Packit |
e4b6da |
print <<'end';
|
|
Packit |
e4b6da |
Make Texinfo documents from Texi-XML
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
--encoding=ENCODING Character encoding for Texinfo files
|
|
Packit |
e4b6da |
Default is US-ASCII
|
|
Packit |
e4b6da |
--list-files Write list of output files to stdout
|
|
Packit |
e4b6da |
--to-stdout Write output to stdout instead of to files
|
|
Packit |
e4b6da |
--output-dir Directory to write the output files
|
|
Packit |
e4b6da |
Default is current working directory
|
|
Packit |
e4b6da |
--info Pipe output to makeinfo, creating Info files directly
|
|
Packit |
e4b6da |
--plaintext Pipe output to makeinfo, creating plain text files
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
These options set the location of auxiliary programs:
|
|
Packit |
e4b6da |
--utf8trans-program=PATH, --utf8trans-map=PATH,
|
|
Packit |
e4b6da |
--iconv-program=PATH, --makeinfo-program=PATH
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
--help Show this help and exit
|
|
Packit |
e4b6da |
--version Show version and exit
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
See the db2x_texixml(1) manual page and the docbook2X documentation for
|
|
Packit |
e4b6da |
more details.
|
|
Packit |
e4b6da |
end
|
|
Packit |
e4b6da |
exit 0;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub options_version
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
print "db2x_texixml (part of docbook2X " .
|
|
Packit |
e4b6da |
$db2x_config{'docbook2X-version'} . ")\n";
|
|
Packit |
e4b6da |
print <<'end';
|
|
Packit |
e4b6da |
$Revision: 1.49 $ $Date: 2006/04/20 03:02:31 $
|
|
Packit |
e4b6da |
<URL:http://docbook2x.sourceforge.net/>
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
Copyright (C) 2000-2004 Steve Cheng
|
|
Packit |
e4b6da |
This is free software; see the source for copying conditions. There is NO
|
|
Packit |
e4b6da |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
e4b6da |
end
|
|
Packit |
e4b6da |
exit 0;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$SIG{__WARN__} = sub { print STDERR "$0: " . $_[0]; };
|
|
Packit |
e4b6da |
if(!GetOptions($cmdoptions,
|
|
Packit |
e4b6da |
'encoding=s',
|
|
Packit |
e4b6da |
'list-files',
|
|
Packit |
e4b6da |
'to-stdout',
|
|
Packit |
e4b6da |
'output-dir=s',
|
|
Packit |
e4b6da |
'info',
|
|
Packit |
e4b6da |
'plaintext',
|
|
Packit |
e4b6da |
'utf8trans-program=s',
|
|
Packit |
e4b6da |
'utf8trans-map=s',
|
|
Packit |
e4b6da |
'iconv-program=s',
|
|
Packit |
e4b6da |
'makeinfo-program=s',
|
|
Packit |
e4b6da |
'help', \&options_help,
|
|
Packit |
e4b6da |
'version', \&options_version))
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
print STDERR "Try \"$0 --help\" for more information.\n";
|
|
Packit |
e4b6da |
exit 1;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$SIG{__WARN__} = undef;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#use XML::Handler::SGMLSpl; # we link to this explicitly during building
|
|
Packit |
e4b6da |
my $texixmldata = { 'options' => $cmdoptions };
|
|
Packit |
e4b6da |
$texixml::templates = XML::Handler::SGMLSpl->new($texixmldata);
|
|
Packit |
e4b6da |
$texixml::templates->push_mode('file-unselected');
|
|
Packit |
e4b6da |
$texixml::templates->{namespaces}->{''}="http://docbook2x.sourceforge.net/xmlns/Texi-XML";
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# TexiWriter: output routines
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
package TexiWriter;
|
|
Packit |
e4b6da |
require Exporter;
|
|
Packit |
e4b6da |
@TexiWriter::ISA = qw(Exporter);
|
|
Packit |
e4b6da |
@TexiWriter::EXPORT_OK = qw(texi_escape texi_arg_escape);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Use TexiWriter on specified file
|
|
Packit |
e4b6da |
# Params: fh - an IO::Handle to send the output
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub new {
|
|
Packit |
e4b6da |
my ($class, $fh) = @_;
|
|
Packit |
e4b6da |
my $self = { fh => $fh, line_start => 1, output_buffers => [] };
|
|
Packit |
e4b6da |
return bless($self, $class);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Print text with whitespace folding
|
|
Packit |
e4b6da |
# (actually only newline folding)
|
|
Packit |
e4b6da |
# Usually need to escape text first
|
|
Packit |
e4b6da |
# Params: text - string to print
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub print_ws {
|
|
Packit |
e4b6da |
my ($self, $text) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $line (split(/(\n)/, $text)) {
|
|
Packit |
e4b6da |
if($line eq "\n") {
|
|
Packit |
e4b6da |
# Don't leave a blank line
|
|
Packit |
e4b6da |
$self->{fh}->print("\n")
|
|
Packit |
e4b6da |
unless $self->{line_start}++;
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
# Don't put any spaces at the beginning
|
|
Packit |
e4b6da |
# of a line. These cause makeinfo
|
|
Packit |
e4b6da |
# to erroneously indent the text.
|
|
Packit |
e4b6da |
$line =~ s/^[ \t]+// if $self->{line_start};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Collapse whitespace
|
|
Packit |
e4b6da |
$line =~ tr/ \t/ /;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($line ne '') {
|
|
Packit |
e4b6da |
$self->{fh}->print($line);
|
|
Packit |
e4b6da |
$self->{line_start} = 0;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# This is basically just a print, but
|
|
Packit |
e4b6da |
# with the special instruction that,
|
|
Packit |
e4b6da |
# if a '\n' is present at the beginning
|
|
Packit |
e4b6da |
# of the string, this means to start a new line,
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# i.e. if we are already at the beginning of the line
|
|
Packit |
e4b6da |
# we do not emit another '\n' and therefore create
|
|
Packit |
e4b6da |
# a blank line.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# This routine is useful for emitting "block" Texinfo
|
|
Packit |
e4b6da |
# commands that have to start at the beginning of the
|
|
Packit |
e4b6da |
# line. (Note: unlike RoffWriter's request method,
|
|
Packit |
e4b6da |
# TexiWriter does not provide an explicit "do command"
|
|
Packit |
e4b6da |
# method --- they are cumbersome and not necessary
|
|
Packit |
e4b6da |
# for the Texinfo format.)
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# No escaping of the text is done.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Params: text - string to print
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub output {
|
|
Packit |
e4b6da |
my ($self, $text) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($text =~ s/^\n//) {
|
|
Packit |
e4b6da |
$self->{fh}->print("\n") unless $self->{line_start}++;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return if $text eq '';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{fh}->print($text);
|
|
Packit |
e4b6da |
$self->{line_start} = ($text =~ /\n$/);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# The following functions implement a simple stack
|
|
Packit |
e4b6da |
# of output buffers. These are used to handle the arguments
|
|
Packit |
e4b6da |
# of a Texinfo @-command, when the content of the arguments
|
|
Packit |
e4b6da |
# is not immediately accessible in stream XML processing.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# The line-breaking semantics of regular output() are not implemented,
|
|
Packit |
e4b6da |
# because they do not make sense on strings.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub output_buffer_push
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self) = @_;
|
|
Packit |
e4b6da |
unshift(@{$self->{output_buffers}}, "");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub output_buffer_pop
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self) = @_;
|
|
Packit |
e4b6da |
return shift(@{$self->{output_buffers}});
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub savable_output {
|
|
Packit |
e4b6da |
my ($self, $text) = @_;
|
|
Packit |
e4b6da |
if(scalar(@{$self->{output_buffers}}) == 0) {
|
|
Packit |
e4b6da |
return output($self, $text);
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{output_buffers}->[0] .= $text;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Print text without folding whitespace
|
|
Packit |
e4b6da |
# Usually need to escape text first
|
|
Packit |
e4b6da |
# Params: text - string to print
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub print {
|
|
Packit |
e4b6da |
my ($self, $text) = @_;
|
|
Packit |
e4b6da |
$self->{fh}->print($text);
|
|
Packit |
e4b6da |
$self->{line_start} = ($text =~ /\n$/);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Escape Texinfo syntax chars
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub texi_escape
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my $s = shift;
|
|
Packit |
e4b6da |
$s =~ s/([\@\{\}])/\@$1/g;
|
|
Packit |
e4b6da |
return $s;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub texi_arg_escape
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my $s = shift;
|
|
Packit |
e4b6da |
$s =~ s/,/\@comma\{\}/g;
|
|
Packit |
e4b6da |
return $s;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Escape the ',' when output buffering is activated,
|
|
Packit |
e4b6da |
# because output buffering is typically used to handle
|
|
Packit |
e4b6da |
# arguments, and a literal ',' would be misinterpreted
|
|
Packit |
e4b6da |
# as an argument delimeter.
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub texi_arg_escape_conditional
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $text) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(scalar(@{$self->{output_buffers}}) > 0) {
|
|
Packit |
e4b6da |
$text =~ s/,/\@comma\{\}/g;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return $text;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Template rules
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
package texixml;
|
|
Packit |
e4b6da |
import TexiWriter qw(texi_escape texi_arg_escape);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
use IO::File;
|
|
Packit |
e4b6da |
use vars qw($templates);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# A clean solution to the extra-newlines problem
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# In essence, texi_xml usually puts newlines only where you
|
|
Packit |
e4b6da |
# expect a human editing a Texinfo file directly would.
|
|
Packit |
e4b6da |
# The heuristic works by checking if we are at the beginning
|
|
Packit |
e4b6da |
# of a line or not in our output ($texixml::newline_last),
|
|
Packit |
e4b6da |
# and if so, refrain from putting too many newlines
|
|
Packit |
e4b6da |
# (which would actually produce 2 or more blank lines).
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# texi_xml also keeps track of what type of element (block, inline
|
|
Packit |
e4b6da |
# or neither) it just processed, then makes line breaks only
|
|
Packit |
e4b6da |
# if it is required to separate them.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# This is not complete "whitespace collapsing", but since Texinfo
|
|
Packit |
e4b6da |
# is reasonably tolerant in its whitespace handling we don't need
|
|
Packit |
e4b6da |
# to have a model that collapses whitespace perfectly in every case.
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
sub block_start
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $elem) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(scalar(@{$self->{tw}->{output_buffers}}) > 0) {
|
|
Packit |
e4b6da |
die "$0: block_start called while saving output (this is a bug)";
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\n")
|
|
Packit |
e4b6da |
unless ($elem->in('listitem') and
|
|
Packit |
e4b6da |
$elem->parent->ext->{lastchild} eq '')
|
|
Packit |
e4b6da |
or ($elem->in('entry') and
|
|
Packit |
e4b6da |
$elem->parent->ext->{lastchild} eq '');
|
|
Packit |
e4b6da |
# Don't put blank before the first block in
|
|
Packit |
e4b6da |
# varlistentries and entries of a multitable.
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->parent->ext->{lastchild} = 'block';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub mixed_inline_start
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $node) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(scalar(@{$self->{tw}->{output_buffers}}) > 0) {
|
|
Packit |
e4b6da |
return;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Example:
|
|
Packit |
e4b6da |
# <para>Warning<itemize>...</itemize>Do not indent this text
|
|
Packit |
e4b6da |
# since it's part of the same paragraph</para>
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\n\@noindent\n")
|
|
Packit |
e4b6da |
if $node->parent->ext->{lastchild} eq 'block';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$node->parent->ext->{lastchild} = 'inline';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Texinfo preamble and eof
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub shell_quote
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
join(' ', map { my $u = $_;
|
|
Packit |
e4b6da |
$u =~ s#([\$`"\\\n])#\\$1#g;
|
|
Packit |
e4b6da |
'"' . $u . '"' } @_);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub texi_openfile {
|
|
Packit |
e4b6da |
my ($self, $basename) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $dir = $self->{options}->{'output-dir'};
|
|
Packit |
e4b6da |
$dir =~ s/([^\/])$/$1\//; # terminate with slash
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $encoding = $self->{options}->{encoding};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $openstr = '';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(($encoding !~ /^utf|ucs/i or $encoding =~ s/\/\/TRANSLIT$//i)
|
|
Packit |
e4b6da |
and $self->{options}->{'utf8trans-program'} ne '')
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$openstr .= '| ' .
|
|
Packit |
e4b6da |
shell_quote($self->{options}->{'utf8trans-program'}) . ' -- ' .
|
|
Packit |
e4b6da |
shell_quote($self->{options}->{'utf8trans-map'}) . ' ';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($encoding !~ /^utf-?8$/i
|
|
Packit |
e4b6da |
and $self->{options}->{'iconv-program'} ne '')
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$openstr .= '| ' .
|
|
Packit |
e4b6da |
shell_quote($self->{options}->{'iconv-program'},
|
|
Packit |
e4b6da |
'-f', 'utf-8',
|
|
Packit |
e4b6da |
'-t', $encoding)
|
|
Packit |
e4b6da |
. ' ';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($self->{options}->{'plaintext'}) {
|
|
Packit |
e4b6da |
my $filename = "${dir}${basename}.txt";
|
|
Packit |
e4b6da |
$openstr .= '| ' .
|
|
Packit |
e4b6da |
shell_quote($self->{options}->{'makeinfo-program'},
|
|
Packit |
e4b6da |
'--no-headers');
|
|
Packit |
e4b6da |
if(not $self->{options}->{'to-stdout'}) {
|
|
Packit |
e4b6da |
print "$filename\n"
|
|
Packit |
e4b6da |
if $self->{options}->{'list-files'};
|
|
Packit |
e4b6da |
$openstr .= ' > ' . shell_quote($filename);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
} elsif($self->{options}->{'info'}) {
|
|
Packit |
e4b6da |
if(not $self->{options}->{'to-stdout'}) {
|
|
Packit |
e4b6da |
$openstr .= '| ( cd '
|
|
Packit |
e4b6da |
. shell_quote($dir) . ' && exec '
|
|
Packit |
e4b6da |
. shell_quote($self->{options}->{'makeinfo-program'})
|
|
Packit |
e4b6da |
. ' )';
|
|
Packit |
e4b6da |
print "${dir}${basename}.info\n"
|
|
Packit |
e4b6da |
if $self->{options}->{'list-files'};
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$openstr .= '| ' . shell_quote(
|
|
Packit |
e4b6da |
$self->{options}->{'makeinfo-program'})
|
|
Packit |
e4b6da |
. ' -o -';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
my $filename = "${dir}${basename}.texi";
|
|
Packit |
e4b6da |
if($openstr eq '') {
|
|
Packit |
e4b6da |
if(not $self->{options}->{'to-stdout'}) {
|
|
Packit |
e4b6da |
$openstr = $filename;
|
|
Packit |
e4b6da |
# Trick from Perl FAQ to open file with arbitrary characters
|
|
Packit |
e4b6da |
$openstr =~ s#^(\s)#./$1#;
|
|
Packit |
e4b6da |
$openstr = ">${openstr}\0";
|
|
Packit |
e4b6da |
print "$filename\n"
|
|
Packit |
e4b6da |
if $self->{options}->{'list-files'};
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$openstr = '>-';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$openstr .= '> ' . shell_quote($filename);
|
|
Packit |
e4b6da |
print "$filename\n"
|
|
Packit |
e4b6da |
if $self->{options}->{'list-files'};
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $iof = new IO::File($openstr)
|
|
Packit |
e4b6da |
or die "$0: error opening $openstr: $!\n";
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Set output encoding to UTF-8 on Perl >=5.8.0
|
|
Packit |
e4b6da |
# so it doesn't complain
|
|
Packit |
e4b6da |
binmode($iof, ":utf8") unless $] < 5.008;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return $iof;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('texinfoset<', 'file-unselected', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{node2id_map} = {};
|
|
Packit |
e4b6da |
$self->{id2node_map} = {};
|
|
Packit |
e4b6da |
$self->{id2file_map} = {};
|
|
Packit |
e4b6da |
$self->{id_counter} = 1;
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('texinfoset>', 'file-unselected', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('texinfo<', 'file-unselected', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $basename;
|
|
Packit |
e4b6da |
if($elem->attr('file') ne '') {
|
|
Packit |
e4b6da |
$basename = filename_escape($elem->attr('file'));
|
|
Packit |
e4b6da |
} elsif($self->{inputfile} ne '-') {
|
|
Packit |
e4b6da |
$basename = $self->{inputfile};
|
|
Packit |
e4b6da |
# strip the path component, and extension
|
|
Packit |
e4b6da |
$basename = $1 if $basename =~ /([^\/]+)$/;
|
|
Packit |
e4b6da |
$basename =~ s/\.txml$//;
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$basename = 'untitled';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{fh} = texi_openfile($self, $basename);
|
|
Packit |
e4b6da |
$self->{tw} = new TexiWriter($self->{fh});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{basename} = $basename;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\\input texinfo\n");
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@setfilename ${basename}.info\n");
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $encoding = $self->{options}->{encoding};
|
|
Packit |
e4b6da |
$encoding =~ s#//TRANSLIT$##i;
|
|
Packit |
e4b6da |
$self->{tw}->output("\@documentencoding $encoding\n");
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('texinfo>', 'file-unselected', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\n\@bye\n");
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{fh}->close
|
|
Packit |
e4b6da |
or die $! ? "$0: error closing file/pipe: $!\n"
|
|
Packit |
e4b6da |
: "$0: program in pipeline exited with an error\n";
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{fh} = undef;
|
|
Packit |
e4b6da |
$self->{tw} = undef;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->push_mode('file-unselected');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'file-unselected', \&illegal_text_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'file-unselected', \&illegal_element_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub illegal_text_handler {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($node->{Data} =~ /[^ \t\r\n]/) {
|
|
Packit |
e4b6da |
$templates->warn_location($node, "character data is not allowed here");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Node name maps
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodenamemap<', 'file-unselected', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->push_mode('nodenamemap-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodenamemap>', 'file-unselected', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodenamemapentry<', 'nodenamemap-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$elem->ext->{nodenames} = [];
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodenamemapentry>', 'nodenamemap-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $id = $elem->attr('id');
|
|
Packit |
e4b6da |
my $f = filename_escape($elem->attr('file'));
|
|
Packit |
e4b6da |
my $nodename;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $s (@{$elem->ext->{nodenames}}) {
|
|
Packit |
e4b6da |
if(not exists $self->{node2id_map}->{"${f}/$s"}) {
|
|
Packit |
e4b6da |
$nodename = $s;
|
|
Packit |
e4b6da |
last;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(not defined $nodename) {
|
|
Packit |
e4b6da |
if(scalar(@{$elem->ext->{nodenames}}) > 0) {
|
|
Packit |
e4b6da |
for(my $i = 1; ; $i++) {
|
|
Packit |
e4b6da |
$nodename = $elem->ext->{nodenames}->[0] .
|
|
Packit |
e4b6da |
' <' . $i . '>';
|
|
Packit |
e4b6da |
last if not
|
|
Packit |
e4b6da |
exists $self->{node2id_map}->{"${f}/$nodename"};
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
} elsif(not exists $self->{node2id_map}->{
|
|
Packit |
e4b6da |
$f . '/' . ($nodename = nodename_escape($id))}) {
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$nodename = 'untitled node <' . $self->{id_counter}++ . '>';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{node2id_map}->{"${f}/$nodename"} = $id;
|
|
Packit |
e4b6da |
$self->{id2node_map}->{$id} = $nodename;
|
|
Packit |
e4b6da |
$self->{id2file_map}->{$id} = $f;
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodename<', 'nodenamemap-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$elem->ext->{nodename} = '';
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('nodename>', 'nodenamemap-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
my $nodenames = $elem->parent->ext->{nodenames};
|
|
Packit |
e4b6da |
my $s = nodename_escape($elem->ext->{nodename});
|
|
Packit |
e4b6da |
push(@$nodenames, $s) unless $s eq '';
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'nodenamemap-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
if($node->in('nodename')) {
|
|
Packit |
e4b6da |
$node->parent->ext->{nodename} .= $node->{Data};
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
&illegal_text_handler;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'nodenamemap-mode', \&illegal_element_handler);;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub get_nodename
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $elem, $nodename_attr, $id_attr, $optional) = @_;
|
|
Packit |
e4b6da |
if($nodename_attr ne '') {
|
|
Packit |
e4b6da |
return nodename_escape($nodename_attr);
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
my $f = $self->{id2file_map}->{$id_attr};
|
|
Packit |
e4b6da |
if($f ne '' and $f ne $self->{basename}) {
|
|
Packit |
e4b6da |
# Error, we expect this node to be in the same
|
|
Packit |
e4b6da |
# file.
|
|
Packit |
e4b6da |
$templates->warn_location($elem, "fatal error: node belongs to a different file");
|
|
Packit |
e4b6da |
die;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return undef if($optional and $id_attr eq '');
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($id_attr eq '') {
|
|
Packit |
e4b6da |
$templates->warn_location($elem, "fatal error: neither a node name nor an ID was specified");
|
|
Packit |
e4b6da |
die;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
if(not exists($self->{id2node_map}->{$id_attr})) {
|
|
Packit |
e4b6da |
$templates->warn_location($elem, "ID \"${id_attr}\" does not exist");
|
|
Packit |
e4b6da |
return nodename_escape($id_attr);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return $self->{id2node_map}->{$id_attr};
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub get_nodename_filename
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $elem, $nodename_attr, $file_attr, $id_attr, $optional) = @_;
|
|
Packit |
e4b6da |
if($nodename_attr ne '' or $file_attr ne '') {
|
|
Packit |
e4b6da |
return (nodename_escape($nodename_attr), filename_escape($file_attr));
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
return undef if $optional and $id_attr eq '';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($id_attr eq '') {
|
|
Packit |
e4b6da |
$templates->warn_location($elem, "fatal error: neither a node name nor an ID was specified");
|
|
Packit |
e4b6da |
die;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
if(not exists($self->{id2node_map}->{$id_attr})) {
|
|
Packit |
e4b6da |
$templates->warn_location($elem, "fatal error: ID \"${id_attr}\" does not exist");
|
|
Packit |
e4b6da |
return (nodename_escape($id_attr), '')
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return ($self->{id2node_map}->{$id_attr},
|
|
Packit |
e4b6da |
$self->{id2file_map}->{$id_attr});
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Simple title pages
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('settitle<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@settitle ");
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('settitle>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('titlepage<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@titlepage\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('titlepage>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end titlepage\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('title<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@title ");
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('title>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('subtitle<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@subtitle ");
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('subtitle>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('author<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@author ");
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('author>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Menus, nodes
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Do escaping for nodenames:
|
|
Packit |
e4b6da |
# NOTE: stylesheets should do this if possible
|
|
Packit |
e4b6da |
# since there can be rare name clashes.
|
|
Packit |
e4b6da |
sub nodename_escape
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my $name = shift;
|
|
Packit |
e4b6da |
for ($name) {
|
|
Packit |
e4b6da |
tr/().,:/[]_;;/;
|
|
Packit |
e4b6da |
tr/ \t\n/ /s;
|
|
Packit |
e4b6da |
s/^ +//g;
|
|
Packit |
e4b6da |
s/ +$//g;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
return $name;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub filename_escape
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my $s = shift;
|
|
Packit |
e4b6da |
$s =~ tr/\//_/;
|
|
Packit |
e4b6da |
return $s;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('node<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
my $node = texi_escape(
|
|
Packit |
e4b6da |
get_nodename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('name'), $elem->attr('id')));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $next = texi_escape(get_nodename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('next'), $elem->attr('nextid'), 'optional'));
|
|
Packit |
e4b6da |
my $previous = texi_escape(get_nodename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('previous'), $elem->attr('previousid'), 'optional'));
|
|
Packit |
e4b6da |
my $up = texi_escape(get_nodename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('up'), $elem->attr('upid'), 'optional'));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(defined($next) or defined($previous) or defined($up)) {
|
|
Packit |
e4b6da |
if($node =~ /^[Tt]op$/ and $elem->attr('up') eq '') {
|
|
Packit |
e4b6da |
$up = '(dir)';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output(
|
|
Packit |
e4b6da |
"\n\n\@node ${node}, ${next}, ${previous}, ${up}\n");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\n\@node $node\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('menu<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output("\@menu\n");
|
|
Packit |
e4b6da |
$templates->push_mode('menu-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('menu>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end menu\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('detailmenu<', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output("\@detailmenu\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('detailmenu>', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end detailmenu\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('menuline<', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->push_mode('menu-saved-text-mode');
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('menuline>', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $s = $self->{tw}->output_buffer_pop();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output($s . "\n");
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\n") if($s eq '');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('menuentry<', 'menu-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule('menuentry>', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('menuentrytitle<', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->push_mode('menu-saved-text-mode');
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('menuentrytitle>', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $entry = $self->{tw}->output_buffer_pop();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Since the contents of @menu is supposed to be "pre-formatted",
|
|
Packit |
e4b6da |
# Texinfo will be picky about extra spaces.
|
|
Packit |
e4b6da |
# Eliminate them here.
|
|
Packit |
e4b6da |
$entry =~ tr/ / /s;
|
|
Packit |
e4b6da |
$entry =~ s/^ //;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Although the menu entry is not constrained to the set
|
|
Packit |
e4b6da |
# of characters allowed for node names, the use of ':'
|
|
Packit |
e4b6da |
# to separate the parts of menu entry implies that it
|
|
Packit |
e4b6da |
# is not an allowed character.
|
|
Packit |
e4b6da |
$entry =~ tr/:/;/;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my ($node,$file) = get_nodename_filename($self, $elem->parent,
|
|
Packit |
e4b6da |
$elem->parent->attr('node'),
|
|
Packit |
e4b6da |
$elem->parent->attr('file'),
|
|
Packit |
e4b6da |
$elem->parent->attr('idref'),
|
|
Packit |
e4b6da |
$elem->parent->in('directory'));
|
|
Packit |
e4b6da |
$node = texi_escape($node);
|
|
Packit |
e4b6da |
$file = texi_escape($file);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# The eventual output
|
|
Packit |
e4b6da |
my $s;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($file ne '' and ($node eq '' or $file ne $self->{basename})) {
|
|
Packit |
e4b6da |
$s = "* ${entry}: (${file})${node}.";
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
if($entry eq $node) {
|
|
Packit |
e4b6da |
$s = "* ${entry}::";
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$s = "* ${entry}: ${node}.";
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output($s);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->parent->ext->{'entry_length'} = length($s);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
use Text::Wrap ();
|
|
Packit |
e4b6da |
$templates->add_rule('menuentrydescrip<', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->push_mode('menu-saved-text-mode');
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('menuentrydescrip>', 'menu-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $text = $self->{tw}->output_buffer_pop();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Since the contents of @menu is supposed to be "pre-formatted",
|
|
Packit |
e4b6da |
# Texinfo will be picky about extra spaces.
|
|
Packit |
e4b6da |
# Eliminate them here.
|
|
Packit |
e4b6da |
$text =~ tr/ / /s;
|
|
Packit |
e4b6da |
$text =~ s/^ //;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $entry_length = $elem->parent->ext->{'entry_length'};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $first_line_padding =
|
|
Packit |
e4b6da |
$entry_length<32 ? 32-$entry_length : 3;
|
|
Packit |
e4b6da |
my $first_line_overflow = 0;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $start_column =
|
|
Packit |
e4b6da |
$entry_length + $first_line_padding + 2;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($start_column > 50) {
|
|
Packit |
e4b6da |
$first_line_overflow = 1;
|
|
Packit |
e4b6da |
$start_column = 50;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$Text::Wrap::columns = 78 - $start_column;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my @lines = split(/(\n)/, Text::Wrap::wrap("", "", $text));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(!$first_line_overflow) {
|
|
Packit |
e4b6da |
my $first_line = shift @lines;
|
|
Packit |
e4b6da |
if($first_line) {
|
|
Packit |
e4b6da |
$self->{tw}->output((' ' x $first_line_padding) . $first_line);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $line (@lines) {
|
|
Packit |
e4b6da |
if($line eq "\n") {
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->output((' ' x $start_column) . $line);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'menu-mode', \&illegal_text_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'menu-mode', \&illegal_element_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Info directory
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('directory<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# If creating plain text files, suppress the directory.
|
|
Packit |
e4b6da |
# Really, makeinfo ought to do this, but it doesn't.
|
|
Packit |
e4b6da |
if($self->{options}->{'plaintext'}) {
|
|
Packit |
e4b6da |
$templates->push_mode('directory-suppress');
|
|
Packit |
e4b6da |
return;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(defined $elem->attr('category')) {
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@dircategory " .
|
|
Packit |
e4b6da |
texi_escape($elem->attr('category')) . "\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@direntry\n");
|
|
Packit |
e4b6da |
$templates->push_mode('menu-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('directory>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
return if $self->{options}->{'plaintext'};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end direntry\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'directory-suppress', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'directory-suppress', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Internationalization
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('documentlanguage<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
my $lstack = $self->{'language-stack'};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(defined $elem->attr('lang')) {
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@documentlanguage " . $elem->attr('lang') . "\n");
|
|
Packit |
e4b6da |
push(@$lstack, $elem->attr('lang'));
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
pop(@$lstack);
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@documentlanguage " . $lstack->[-1] . "\n")
|
|
Packit |
e4b6da |
if scalar(@$lstack);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Inline elements
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub inline_start_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->savable_output('@'. $elem->name . '{');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
sub inline_end_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->savable_output('}');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $gi
|
|
Packit |
e4b6da |
(qw(code samp cite email dfn file sc acronym emph strong key kbd var
|
|
Packit |
e4b6da |
env command option
|
|
Packit |
e4b6da |
i b r t
|
|
Packit |
e4b6da |
footnote))
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", \&inline_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", \&inline_end_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'single-line-mode', \&inline_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'single-line-mode', \&inline_end_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'saved-text-mode', \&inline_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'saved-text-mode', \&inline_end_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub anchor_start {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->savable_output('@anchor{'
|
|
Packit |
e4b6da |
. texi_escape(get_nodename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('node'), $elem->attr('id')))
|
|
Packit |
e4b6da |
. '}');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('anchor<', \&anchor_start);
|
|
Packit |
e4b6da |
$templates->add_rule('anchor<', 'single-line-mode', \&anchor_start);
|
|
Packit |
e4b6da |
$templates->add_rule('anchor<', 'saved-text-mode', \&anchor_start);
|
|
Packit |
e4b6da |
$templates->add_rule('anchor<', 'menu-saved-text-mode', \&anchor_start);
|
|
Packit |
e4b6da |
$templates->add_rule('anchor<', 'verbatim-mode', \&anchor_start);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'single-line-mode', \&illegal_element_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'saved-text-mode', \&illegal_element_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'menu-saved-text-mode', \&illegal_element_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Cross references, links
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub crossref_start_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
$templates->push_mode('saved-text-mode');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub crossref_end_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Syntax:
|
|
Packit |
e4b6da |
# @ref{$node,$infolabel,$label,$file,$printmanual}
|
|
Packit |
e4b6da |
# node - required
|
|
Packit |
e4b6da |
# infolabel, label - optional
|
|
Packit |
e4b6da |
# label is actually the inline content of this element
|
|
Packit |
e4b6da |
# infofile, printmanual - optional
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my ($node, $file) = get_nodename_filename($self, $elem,
|
|
Packit |
e4b6da |
$elem->attr('node'),
|
|
Packit |
e4b6da |
$elem->attr('file'),
|
|
Packit |
e4b6da |
$elem->attr('idref'));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $infolabel = $elem->attr('infolabel');
|
|
Packit |
e4b6da |
my $label = $self->{tw}->output_buffer_pop();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# If the node and cross reference label turn out to be
|
|
Packit |
e4b6da |
# the same, make the latter empty so info won't display it
|
|
Packit |
e4b6da |
# twice.
|
|
Packit |
e4b6da |
$label = '' if $node eq $label;
|
|
Packit |
e4b6da |
$infolabel = '' if $node eq $infolabel;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Note:
|
|
Packit |
e4b6da |
# 1. Node names cannot contain commas anyway, so no
|
|
Packit |
e4b6da |
# texi_arg_escape needed.
|
|
Packit |
e4b6da |
# 2. label is not escaped here, because it already IS escaped.
|
|
Packit |
e4b6da |
$node = texi_escape($node);
|
|
Packit |
e4b6da |
$infolabel = texi_arg_escape(texi_escape($infolabel));
|
|
Packit |
e4b6da |
$file = texi_arg_escape(texi_escape($file));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $printmanual = texi_arg_escape(
|
|
Packit |
e4b6da |
texi_escape($elem->attr('printmanual')));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->savable_output('@' . $elem->name . '{' . $node);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($file ne '' and $file ne $self->{basename}) {
|
|
Packit |
e4b6da |
# Reference to another file
|
|
Packit |
e4b6da |
$self->{tw}->savable_output(",$infolabel,$label,$file,$printmanual}");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
else {
|
|
Packit |
e4b6da |
# Same file
|
|
Packit |
e4b6da |
if($label eq '' and $infolabel eq '') {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output("}");
|
|
Packit |
e4b6da |
return;
|
|
Packit |
e4b6da |
} elsif($label eq '') {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output(",$infolabel}");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output(",$infolabel,$label}");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $gi (qw(xref ref pxref)) {
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", \&crossref_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", \&crossref_end_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'single-line-mode', \&crossref_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'single-line-mode', \&crossref_end_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'saved-text-mode', \&crossref_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'saved-text-mode', \&crossref_end_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# URI references
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('uref<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
$templates->push_mode('saved-text-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('uref>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $url = texi_escape($elem->attr('url'));
|
|
Packit |
e4b6da |
my $text = $self->{tw}->output_buffer_pop();
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($text eq '') {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output("\@uref{$url}");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output("\@uref{$url,$text}");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# FIXME
|
|
Packit |
e4b6da |
$templates->add_rule("uref<", 'single-line-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref>", 'single-line-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref<", 'saved-text-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref>", 'saved-text-mode', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule("uref<", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref>", 'verbatim-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref<", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
$templates->add_rule("uref>", 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Sectioning elements
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub section_start_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$elem->parent->ext->{'lastchild'} = 'block';
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@" . $elem->name . ' ');
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub section_end_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $gi
|
|
Packit |
e4b6da |
(qw(chapter section subsection subsubsection
|
|
Packit |
e4b6da |
majorheading chapheading heading subheading subsubheading
|
|
Packit |
e4b6da |
top unnumbered unnumberedsec unnumberedsubsec unnumberedsubsubsec
|
|
Packit |
e4b6da |
appendix appendixsec appendixsubsec appendixsubsubsec))
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", \§ion_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", \§ion_end_handler);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Paragraph
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('para<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('para>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Verbatim displays
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub verbatim_block_start_handler
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output('@' . $elem->name . "\n");
|
|
Packit |
e4b6da |
$templates->push_mode('verbatim-mode');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
sub verbatim_block_end_handler
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end " . $elem->name . "\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $gi
|
|
Packit |
e4b6da |
(qw(example display format)) {
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", \&verbatim_block_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", \&verbatim_block_end_handler);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('*<', 'verbatim-mode', \&illegal_element_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Quotation blocks
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub quotation_block_start_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output('@' . $elem->name . "\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
sub quotation_block_end_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end " . $elem->name . "\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $gi
|
|
Packit |
e4b6da |
(qw(quotation cartouche flushleft flushright)) {
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}<", \"ation_block_start_handler);
|
|
Packit |
e4b6da |
$templates->add_rule("${gi}>", \"ation_block_end_handler);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Lists
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('enumerate<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output("\@enumerate " . $elem->attr('begin') . "\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('enumerate>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end enumerate\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('itemize<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($elem->attr('markchar') ne '') {
|
|
Packit |
e4b6da |
$self->{tw}->output("\@itemize ")
|
|
Packit |
e4b6da |
. texi_escape($elem->attr('markchar'))
|
|
Packit |
e4b6da |
. "\n";
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->output("\@itemize \@w\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('itemize>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end itemize\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('varlist<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output("\@table \@asis\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('varlist>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end table\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('varlistentry<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('term<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
if($elem->parent->ext->{numterms}++) {
|
|
Packit |
e4b6da |
$self->{tw}->output("\@itemx ");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$self->{tw}->output("\@item ");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('term>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('listitem<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# listitem is used in both varlistentry and plain lists,
|
|
Packit |
e4b6da |
# but the @item markup is supplied by <term> in the former
|
|
Packit |
e4b6da |
# case already.
|
|
Packit |
e4b6da |
if($elem->parent->name ne 'varlistentry') {
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$self->{tw}->output("\@item\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Tables
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('multitable<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
$elem->ext->{total_cols} = $elem->attr('cols');
|
|
Packit |
e4b6da |
$elem->ext->{column_data} = [];
|
|
Packit |
e4b6da |
$elem->ext->{colspec_current_colnum} = 0;
|
|
Packit |
e4b6da |
$elem->ext->{colnames} = {};
|
|
Packit |
e4b6da |
$elem->ext->{spannames} = {};
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('colspec<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $col;
|
|
Packit |
e4b6da |
if($elem->attr('colnum')) {
|
|
Packit |
e4b6da |
$col = $elem->attr('colnum');
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$col = $elem->parent->ext->{colspec_current_colnum} + 1;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$elem->parent->ext->{colspec_current_colnum} = $col;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($elem->attr('colname') ne '') {
|
|
Packit |
e4b6da |
$elem->parent->ext->{colnames}->{$elem->attr('colname')} = $col;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->parent->ext->{column_data}->[$col-1] =
|
|
Packit |
e4b6da |
'' . $elem->attr('colwidth');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('spanspec<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->parent->ext->{spannames}->{$elem->attr('spanname')}
|
|
Packit |
e4b6da |
= [ $elem->attr('namest'), $elem->attr('nameend') ];
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('tbody<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $column_data = $elem->parent->ext->{column_data};
|
|
Packit |
e4b6da |
my $totalcols = $elem->parent->ext->{total_cols};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my @vspans = ();
|
|
Packit |
e4b6da |
for(my $i = 0; $i < $totalcols; $i++) {
|
|
Packit |
e4b6da |
push(@vspans, 0);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$elem->ext->{current_vspans} = \@vspans;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $proportsum = 0;
|
|
Packit |
e4b6da |
for(my $i = 0; $i < $totalcols; $i++) {
|
|
Packit |
e4b6da |
my $colwidth = $column_data->[$i];
|
|
Packit |
e4b6da |
if($colwidth eq '') {
|
|
Packit |
e4b6da |
$colwidth = $column_data->[$i] = '1*';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Later we may support other types of width measure,
|
|
Packit |
e4b6da |
# so proportional measures should be written
|
|
Packit |
e4b6da |
# as "r*".
|
|
Packit |
e4b6da |
$colwidth =~ s/\*\s*$//;
|
|
Packit |
e4b6da |
$proportsum += $colwidth;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $columnfractions = '';
|
|
Packit |
e4b6da |
for(my $i = 0; $i < $totalcols; $i++) {
|
|
Packit |
e4b6da |
my $colwidth = $column_data->[$i];
|
|
Packit |
e4b6da |
$colwidth =~ s/\*\s*$//;
|
|
Packit |
e4b6da |
$columnfractions .= $colwidth/$proportsum . ' ';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$columnfractions =~ s/ $//;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@multitable \@columnfractions $columnfractions\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('tbody>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@end multitable\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('row<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@item\n");
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->ext->{current_colnum} = 0;
|
|
Packit |
e4b6da |
tbl_advance_column($elem, $self->{tw}, 0, 1);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('row>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
my $vspans = $elem->parent->ext->{current_vspans};
|
|
Packit |
e4b6da |
for(my $i = 0; $i < @$vspans; $i++) {
|
|
Packit |
e4b6da |
$vspans->[$i]-- if $vspans->[$i] > 0;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('entry<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $tableext = $elem->parent->parent->parent->ext;
|
|
Packit |
e4b6da |
my $namest; my $nameend;
|
|
Packit |
e4b6da |
if($elem->attr('spanname')) {
|
|
Packit |
e4b6da |
$namest = $tableext->{spannames}->{$elem->attr('spanname')}->[0];
|
|
Packit |
e4b6da |
$nameend = $tableext->{spannames}->{$elem->attr('spanname')}->[1];
|
|
Packit |
e4b6da |
} elsif($elem->attr('namest')) {
|
|
Packit |
e4b6da |
$namest = $elem->attr('namest');
|
|
Packit |
e4b6da |
$nameend = $elem->attr('nameend');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $relative_advance = 1;
|
|
Packit |
e4b6da |
my $colnum;
|
|
Packit |
e4b6da |
if(defined $namest) {
|
|
Packit |
e4b6da |
my $col_st = $colnum = $tableext->{colnames}->{$namest};
|
|
Packit |
e4b6da |
my $col_end = $tableext->{colnames}->{$nameend};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$relative_advance = $col_end - $col_st + 1;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
elsif($elem->attr('colname')) {
|
|
Packit |
e4b6da |
$colnum = $tableext->{colnames}->{$elem->attr('colname')};
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(defined $colnum) {
|
|
Packit |
e4b6da |
tbl_advance_column($elem->parent, $self->{tw}, $colnum);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$elem->ext->{relative_advance} = $relative_advance;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($elem->attr('morerows')) {
|
|
Packit |
e4b6da |
if($elem->attr('morerows') !~ /^\d+$/) {
|
|
Packit |
e4b6da |
warn_location($elem, "invalid morerows value --- ignoring\n");
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
for(my $i = 0; $i < $relative_advance; $i++) {
|
|
Packit |
e4b6da |
$elem->parent->parent->ext->{current_vspans}->[
|
|
Packit |
e4b6da |
$elem->parent->ext->{current_colnum} - 1 + $i]
|
|
Packit |
e4b6da |
= $elem->attr('morerows') + 1;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('entry>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
tbl_advance_column($elem->parent, $self->{tw},
|
|
Packit |
e4b6da |
0, $elem->ext->{relative_advance});
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub tbl_advance_column
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($row, $tw, $new_colnum, $relative_advance) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $old_colnum = $row->ext->{current_colnum};
|
|
Packit |
e4b6da |
my $total_cols = $row->parent->parent->ext->{total_cols};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($relative_advance) {
|
|
Packit |
e4b6da |
my $vspans = $row->parent->ext->{current_vspans};
|
|
Packit |
e4b6da |
for($new_colnum = $old_colnum + $relative_advance;
|
|
Packit |
e4b6da |
$new_colnum <= $total_cols && ($vspans->[$new_colnum - 1] > 0);
|
|
Packit |
e4b6da |
$new_colnum++)
|
|
Packit |
e4b6da |
{}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
elsif($new_colnum == -1) {
|
|
Packit |
e4b6da |
$new_colnum = $total_cols + 1;
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$row->ext->{current_colnum} = $new_colnum;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$new_colnum = $total_cols if $new_colnum > $total_cols;
|
|
Packit |
e4b6da |
$old_colnum = 1 if $old_colnum == 0;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$tw->output('@tab ' x ($new_colnum - $old_colnum));
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Graphics
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub image_handler {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $filename = texi_escape($elem->attr('filename'));
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# The @image command has to have the basename and extension
|
|
Packit |
e4b6da |
# separated, so do that.
|
|
Packit |
e4b6da |
my $basename; my $extension;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($filename =~ /^(.+)(\.[^\.]+)$/) {
|
|
Packit |
e4b6da |
$basename = $1;
|
|
Packit |
e4b6da |
$extension = $2;
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$basename = $filename;
|
|
Packit |
e4b6da |
$extension = '';
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if(defined $elem->attr('width') or
|
|
Packit |
e4b6da |
defined $elem->attr('height'))
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$self->{tw}->savable_output('@image{' . $basename . ',' .
|
|
Packit |
e4b6da |
texi_escape($elem->attr('width')) .
|
|
Packit |
e4b6da |
',' .
|
|
Packit |
e4b6da |
texi_escape($elem->attr('height')) .
|
|
Packit |
e4b6da |
',,' .
|
|
Packit |
e4b6da |
$extension .
|
|
Packit |
e4b6da |
'}');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
else {
|
|
Packit |
e4b6da |
$self->{tw}->savable_output(
|
|
Packit |
e4b6da |
'@image{' . $basename . ',,,,' . $extension . '}');
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('image<', \&image_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('image<', 'single-line-mode', \&image_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('image<', 'saved-text-mode', \&image_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('image<', 'verbatim-mode', \&image_handler);
|
|
Packit |
e4b6da |
$templates->add_rule('image<', 'menu-saved-text-mode', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Vertical spacing
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('sp<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@sp " . $elem->attr('lines') . "\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('page<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@page\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Indices
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('indexterm<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# We allow indexterm at block level just like
|
|
Packit |
e4b6da |
# DocBook. When that happens, don't treat
|
|
Packit |
e4b6da |
# it as an inline (hence no @noindent mantra).
|
|
Packit |
e4b6da |
if($elem->parent->ext->{lastchild} ne 'block') {
|
|
Packit |
e4b6da |
mixed_inline_start($self, $elem);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $class = $elem->attr('class');
|
|
Packit |
e4b6da |
$class = 'c' if $class eq 'cp';
|
|
Packit |
e4b6da |
$class = 'f' if $class eq 'fn';
|
|
Packit |
e4b6da |
$class = 'v' if $class eq 'vr';
|
|
Packit |
e4b6da |
$class = 'k' if $class eq 'ky';
|
|
Packit |
e4b6da |
$class = 'p' if $class eq 'pg';
|
|
Packit |
e4b6da |
$class = 't' if $class eq 'tp';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# @cindex has to start on a new line.
|
|
Packit |
e4b6da |
# I don't know if we are in a middle of an inline
|
|
Packit |
e4b6da |
# command (eg @{code}) that @cindex would work
|
|
Packit |
e4b6da |
# and not disrupt the inline. I'm just hoping it works.
|
|
Packit |
e4b6da |
# If it doesn't, then it is a dumb limitation!
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@" . $class . 'index ');
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Are @-commands allowed for indexed terms?
|
|
Packit |
e4b6da |
$templates->push_mode('single-line-mode');
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
$templates->add_rule('indexterm>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode();
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('printindex<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
block_start($self, $elem);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $class = $elem->attr('class');
|
|
Packit |
e4b6da |
$class = 'cp' if $class eq 'c';
|
|
Packit |
e4b6da |
$class = 'fn' if $class eq 'f';
|
|
Packit |
e4b6da |
$class = 'vr' if $class eq 'v';
|
|
Packit |
e4b6da |
$class = 'ky' if $class eq 'k';
|
|
Packit |
e4b6da |
$class = 'pg' if $class eq 'p';
|
|
Packit |
e4b6da |
$class = 'tp' if $class eq 't';
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->output("\n\@printindex " . $class . "\n");
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Character data
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'single-line-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
my $s = texi_escape($node->{Data});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Collapse spaces, no newlines.
|
|
Packit |
e4b6da |
$s =~ tr/ \t\n/ /s;
|
|
Packit |
e4b6da |
$s = $self->{tw}->texi_arg_escape_conditional($s);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->savable_output($s);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub saved_text_mode_handler
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
my $s = texi_escape($node->{Data});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Collapse spaces, no newlines.
|
|
Packit |
e4b6da |
$s =~ tr/ \t\n/ /s;
|
|
Packit |
e4b6da |
$s = $self->{tw}->texi_arg_escape_conditional($s);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->savable_output($s);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
sub menu_saved_text_mode_handler
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
my $s = texi_escape($node->{Data});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
# Collapse spaces, no newlines.
|
|
Packit |
e4b6da |
$s =~ tr/ \t\n/ /s;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->savable_output($s);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'saved-text-mode',
|
|
Packit |
e4b6da |
\&saved_text_mode_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'menu-saved-text-mode',
|
|
Packit |
e4b6da |
\&menu_saved_text_mode_handler);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'menu-mode', sub {});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'verbatim-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
my $s = texi_escape($node->{Data});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->print($s);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
my $s = texi_escape($node->{Data});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
mixed_inline_start($self, $node)
|
|
Packit |
e4b6da |
unless $s =~ /^[ \t\r\n]+$/;
|
|
Packit |
e4b6da |
# Whitespace used to separate element
|
|
Packit |
e4b6da |
# in a non-mixed content model should
|
|
Packit |
e4b6da |
# not cause any spurious breaks.
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$self->{tw}->print_ws($s);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Comments
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('comment<', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$self->{tw}->output("\n");
|
|
Packit |
e4b6da |
$self->{tw}->output_buffer_push();
|
|
Packit |
e4b6da |
$templates->push_mode('comment-mode');
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('comment>', sub {
|
|
Packit |
e4b6da |
my ($self, $elem, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->pop_mode('comment-mode');
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $line (split(/\n/, $self->{tw}->output_buffer_pop())) {
|
|
Packit |
e4b6da |
$self->{tw}->output("\@c $line\n");
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('text()', 'comment-mode', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
my $s = $node->{Data};
|
|
Packit |
e4b6da |
$self->{tw}->savable_output($s);
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Processing instructions
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('processing-instruction()', sub {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
if($node->{Target} eq 'texinfo') {
|
|
Packit |
e4b6da |
my $data = $node->{Data};
|
|
Packit |
e4b6da |
$data =~ s/\
/\n/g;
|
|
Packit |
e4b6da |
$data =~ s/\
/\n/g;
|
|
Packit |
e4b6da |
$self->{tw}->output($data);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
});
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Catch unknown elements
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
##################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
$templates->add_rule('*<', \&illegal_element_handler);
|
|
Packit |
e4b6da |
sub illegal_element_handler {
|
|
Packit |
e4b6da |
my ($self, $node, $templates) = @_;
|
|
Packit |
e4b6da |
$templates->warn_location($node, "element not allowed here");
|
|
Packit |
e4b6da |
};
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
# Main
|
|
Packit |
e4b6da |
#
|
|
Packit |
e4b6da |
#############################################################################
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
package main;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
use XML::SAX::ParserFactory;
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
unshift(@ARGV, '-') unless @ARGV;
|
|
Packit |
e4b6da |
my $parser = XML::SAX::ParserFactory->parser(
|
|
Packit |
e4b6da |
DocumentHandler => $texixml::templates);
|
|
Packit |
e4b6da |
|
|
Packit |
e4b6da |
foreach my $file (@ARGV)
|
|
Packit |
e4b6da |
{
|
|
Packit |
e4b6da |
$texixmldata->{inputfile} = $file;
|
|
Packit |
e4b6da |
if($file eq '-') {
|
|
Packit |
e4b6da |
$parser->parse_file(\*STDIN);
|
|
Packit |
e4b6da |
} else {
|
|
Packit |
e4b6da |
$parser->parse_uri($file);
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
}
|
|
Packit |
e4b6da |
|