mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-01-30 16:41:05 +08:00
New PS/PDF backend: first attempt at generating the index
This commit is contained in:
parent
f1f1fa7148
commit
916c52e376
@ -42,7 +42,7 @@ nasmdoc.texi: nasmdoc.dip
|
|||||||
|
|
||||||
new: nasmdocx.ps nasmdocx.pdf
|
new: nasmdocx.ps nasmdocx.pdf
|
||||||
|
|
||||||
nasmdocx.ps: nasmdoc.dip nasmlogo.eps genps.pl psfonts.ph pswidth.pl head.ps
|
nasmdocx.ps: nasmdoc.dip nasmlogo.eps genps.pl psfonts.ph pswidth.ph head.ps
|
||||||
$(PERL) $(srcdir)/genps.pl > nasmdocx.ps
|
$(PERL) $(srcdir)/genps.pl > nasmdocx.ps
|
||||||
|
|
||||||
nasmdocx.pdf: nasmdocx.ps
|
nasmdocx.pdf: nasmdocx.ps
|
||||||
|
442
doc/genps.pl
442
doc/genps.pl
@ -27,6 +27,7 @@ require 'pswidth.ph'; # PostScript string width
|
|||||||
idxspace => 24, # Minimum space between index title and pg#
|
idxspace => 24, # Minimum space between index title and pg#
|
||||||
idxindent => 32, # How much to indent a subindex entry
|
idxindent => 32, # How much to indent a subindex entry
|
||||||
idxgutter => 24, # Space between index columns
|
idxgutter => 24, # Space between index columns
|
||||||
|
idxcolumns => 2, # Number of index columns
|
||||||
);
|
);
|
||||||
|
|
||||||
# US-Letter paper
|
# US-Letter paper
|
||||||
@ -99,9 +100,21 @@ sub int2base($$) {
|
|||||||
#
|
#
|
||||||
# Take a crossreference name and generate the PostScript name for it.
|
# Take a crossreference name and generate the PostScript name for it.
|
||||||
#
|
#
|
||||||
|
# This hack produces a somewhat smaller PDF...
|
||||||
|
#%ps_xref_list = ();
|
||||||
|
#$ps_xref_next = 0;
|
||||||
|
#sub ps_xref($) {
|
||||||
|
# my($s) = @_;
|
||||||
|
# my $q = $ps_xref_list{$s};
|
||||||
|
# return $q if ( defined($ps_xref_list{$s}) );
|
||||||
|
# $q = 'X'.int2base($ps_xref_next++, 52);
|
||||||
|
# $ps_xref_list{$s} = $q;
|
||||||
|
# return $q;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Somewhat bigger PDF, but one which obeys # URLs
|
||||||
sub ps_xref($) {
|
sub ps_xref($) {
|
||||||
my($s) = @_;
|
return @_[0];
|
||||||
return $s; # Identity transform should be OK for now
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -111,7 +124,8 @@ sub ps_xref($) {
|
|||||||
# arrays of pairs: [<size>, <metricref>]
|
# arrays of pairs: [<size>, <metricref>]
|
||||||
#
|
#
|
||||||
# Each line is represented as:
|
# Each line is represented as:
|
||||||
# [ [type,first|last,aux,fontset,page,ypos], [rendering array] ]
|
# [ [type,first|last,aux,fontset,page,ypos,optional col],
|
||||||
|
# [rendering array] ]
|
||||||
#
|
#
|
||||||
# A space character may be "squeezed" by up to this much
|
# A space character may be "squeezed" by up to this much
|
||||||
# (as a fraction of the normal width of a space.)
|
# (as a fraction of the normal width of a space.)
|
||||||
@ -126,17 +140,28 @@ sub ps_flow_lines($$$@) {
|
|||||||
my(@l) = (); # Current line
|
my(@l) = (); # Current line
|
||||||
my(@ls) = (); # Accumulated output lines
|
my(@ls) = (); # Accumulated output lines
|
||||||
my(@xd) = (); # Metadata that goes with subsequent text
|
my(@xd) = (); # Metadata that goes with subsequent text
|
||||||
|
my $hasmarker = 0; # Line has -6 marker
|
||||||
|
my $pastmarker = 0; # -6 marker found
|
||||||
|
|
||||||
|
# If there is a -6 marker anywhere in the paragraph,
|
||||||
|
# *each line* output needs to have a -6 marker
|
||||||
|
foreach $e ( @data ) {
|
||||||
|
$hasmarker = 1 if ( $$e[0] == -6 );
|
||||||
|
}
|
||||||
|
|
||||||
$w = 0;
|
$w = 0;
|
||||||
foreach $e ( @data ) {
|
foreach $e ( @data ) {
|
||||||
if ( $$e[0] < 0 ) {
|
if ( $$e[0] < 0 ) {
|
||||||
# Type is metadata. Zero width.
|
# Type is metadata. Zero width.
|
||||||
if ( $$e[0] < -1 ) {
|
if ( $$e[0] == -6 ) {
|
||||||
# -1 (end anchor) goes with the preceeding text, otherwise
|
$pastmarker = 1;
|
||||||
# with the subsequent text
|
}
|
||||||
push(@xd, $e);
|
if ( $$e[0] == -1 || $$e[0] == -6 ) {
|
||||||
} else {
|
# -1 (end anchor) or -6 (marker) goes with the preceeding
|
||||||
|
# text, otherwise with the subsequent text
|
||||||
push(@l, $e);
|
push(@l, $e);
|
||||||
|
} else {
|
||||||
|
push(@xd, $e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
my $ew = ps_width($$e[1], $fontset->{fonts}->[$$e[0]][1]) *
|
my $ew = ps_width($$e[1], $fontset->{fonts}->[$$e[0]][1]) *
|
||||||
@ -152,7 +177,11 @@ sub ps_flow_lines($$$@) {
|
|||||||
my $lx = scalar(@l)-1;
|
my $lx = scalar(@l)-1;
|
||||||
my @rm = ();
|
my @rm = ();
|
||||||
while ( $lx >= 0 ) {
|
while ( $lx >= 0 ) {
|
||||||
while ( $lx >= 0 && $l[$lx]->[0] < 0 ) { $lx-- }; # Skip metadata
|
while ( $lx >= 0 && $l[$lx]->[0] < 0 ) {
|
||||||
|
# Skip metadata
|
||||||
|
$pastmarker = 0 if ( $l[$lx]->[0] == -6 );
|
||||||
|
$lx--;
|
||||||
|
};
|
||||||
if ( $lx >= 0 ) {
|
if ( $lx >= 0 ) {
|
||||||
if ( $l[$lx]->[1] eq ' ' ) {
|
if ( $l[$lx]->[1] eq ' ' ) {
|
||||||
splice(@l, $lx, 1);
|
splice(@l, $lx, 1);
|
||||||
@ -165,20 +194,33 @@ sub ps_flow_lines($$$@) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Now @l contains the stuff to remain on the old line
|
# Now @l contains the stuff to remain on the old line
|
||||||
# If we broke the line inside a link of type -2 or -3,
|
# If we broke the line inside a link, then split the link
|
||||||
# then split the link into two.
|
# into two.
|
||||||
my $lkref = undef;
|
my $lkref = undef;
|
||||||
foreach my $lc ( @l ) {
|
foreach my $lc ( @l ) {
|
||||||
if ( $$lc[0] == -2 || $$lc[0] == -3 ) {
|
if ( $$lc[0] == -2 || $$lc[0] == -3 || $lc[0] == -7 ) {
|
||||||
$lkref = $lc;
|
$lkref = $lc;
|
||||||
} elsif ( $$lc[0] == -1 ) {
|
} elsif ( $$lc[0] == -1 ) {
|
||||||
undef $lkref;
|
undef $lkref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
push(@l, [-1,undef]) if ( defined($lkref) );
|
|
||||||
|
if ( defined($lkref) ) {
|
||||||
|
push(@l, [-1,undef]); # Terminate old reference
|
||||||
|
unshift(@rm, $lkref); # Duplicate reference on new line
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $hasmarker ) {
|
||||||
|
if ( $pastmarker ) {
|
||||||
|
unshift(@rm,[-6,undef]); # New line starts with marker
|
||||||
|
} else {
|
||||||
|
push(@l,[-6,undef]); # Old line ends with marker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
push(@ls, [[$type,0,undef,$fontset,0,0],[@l]]);
|
push(@ls, [[$type,0,undef,$fontset,0,0],[@l]]);
|
||||||
@l = @rm;
|
@l = @rm;
|
||||||
unshift(@l, $lkref) if ( defined($lkref) );
|
|
||||||
$w = $sw = 0;
|
$w = $sw = 0;
|
||||||
# Compute the width of the remainder array
|
# Compute the width of the remainder array
|
||||||
for my $le ( @l ) {
|
for my $le ( @l ) {
|
||||||
@ -247,6 +289,8 @@ sub ps_merge_chunks(@) {
|
|||||||
# -3 begin weblink
|
# -3 begin weblink
|
||||||
# -4 index item anchor
|
# -4 index item anchor
|
||||||
# -5 crossref anchor
|
# -5 crossref anchor
|
||||||
|
# -6 left/right marker (used in the index)
|
||||||
|
# -7 page link (used in the index)
|
||||||
# 0 normal
|
# 0 normal
|
||||||
# 1 empatic (italic)
|
# 1 empatic (italic)
|
||||||
# 2 code (fixed spacing)
|
# 2 code (fixed spacing)
|
||||||
@ -260,11 +304,11 @@ sub mkparaarray($@) {
|
|||||||
my $chunk;
|
my $chunk;
|
||||||
|
|
||||||
if ( $ptype =~ /^code/ ) {
|
if ( $ptype =~ /^code/ ) {
|
||||||
foreach $chunk ( @{$paras[$i]} ) {
|
foreach $chunk ( @chunks ) {
|
||||||
push(@para, [2, $chunk]);
|
push(@para, [2, $chunk]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach $chunk ( @{$paras[$i]} ) {
|
foreach $chunk ( @chunks ) {
|
||||||
my $type = substr($chunk,0,2);
|
my $type = substr($chunk,0,2);
|
||||||
my $text = substr($chunk,2);
|
my $text = substr($chunk,2);
|
||||||
|
|
||||||
@ -393,10 +437,15 @@ for ( $i = 0 ; $i < $npara ; $i++ ) {
|
|||||||
#
|
#
|
||||||
# Add TOC to beginning of paragraph list
|
# Add TOC to beginning of paragraph list
|
||||||
#
|
#
|
||||||
unshift(@paras, @tocparas);
|
unshift(@paras, @tocparas); undef @tocparas;
|
||||||
unshift(@ptypes, @tocptypes);
|
unshift(@ptypes, @tocptypes); undef @tocptypes;
|
||||||
$npara = scalar(@paras);
|
$npara = scalar(@paras);
|
||||||
|
|
||||||
|
#
|
||||||
|
# No lines generated, yet.
|
||||||
|
#
|
||||||
|
@pslines = ();
|
||||||
|
|
||||||
#
|
#
|
||||||
# Line Auxilliary Information Types
|
# Line Auxilliary Information Types
|
||||||
#
|
#
|
||||||
@ -407,150 +456,204 @@ $AuxXRef = 4; # Cross reference as a name
|
|||||||
$AuxNum = 5; # Number
|
$AuxNum = 5; # Number
|
||||||
|
|
||||||
#
|
#
|
||||||
# Break or convert paragraphs into lines.
|
# Break or convert paragraphs into lines, and push them
|
||||||
|
# onto the @pslines array.
|
||||||
#
|
#
|
||||||
@pslines = ();
|
sub ps_break_lines($$) {
|
||||||
@pslinedata = ();
|
my ($paras,$ptypes) = @_;
|
||||||
$linewidth = $psconf{pagewidth}-$psconf{lmarg}-$psconf{rmarg};
|
|
||||||
$bullwidth = $linewidth-$psconf{bulladj};
|
|
||||||
|
|
||||||
for ( $i = 0 ; $i < $npara ; $i++ ) {
|
my $linewidth = $psconf{pagewidth}-$psconf{lmarg}-$psconf{rmarg};
|
||||||
my $xtype = $ptypes[$i];
|
my $bullwidth = $linewidth-$psconf{bulladj};
|
||||||
my $ptype = substr($xtype,0,4);
|
my $indxwidth = ($linewidth-$psconf{idxgutter})/$psconf{idxcolumns}
|
||||||
my @data = @{$paras[$i]};
|
-$psconf{idxspace};
|
||||||
my @ls = ();
|
|
||||||
if ( $ptype eq 'code' ) {
|
|
||||||
my $p;
|
|
||||||
# Code paragraph; each chunk is a line
|
|
||||||
foreach $p ( @data ) {
|
|
||||||
push(@ls, [[$ptype,0,undef,\%TextFont,0,0],[$p]]);
|
|
||||||
}
|
|
||||||
$ls[0]->[0]->[1] |= 1; # First in para
|
|
||||||
$ls[-1]->[0]->[1] |= 2; # Last in para
|
|
||||||
} elsif ( $ptype eq 'chap' || $ptype eq 'appn' ) {
|
|
||||||
# Chapters are flowed normally, but in an unusual font
|
|
||||||
@ls = ps_flow_lines($linewidth, \%ChapFont, $ptype, @data);
|
|
||||||
} elsif ( $ptype eq 'head' || $ptype eq 'subh' ) {
|
|
||||||
unless ( $xtype =~ /^\S+ (\S+) :(.*)$/ ) {
|
|
||||||
die "Bad para";
|
|
||||||
}
|
|
||||||
my $secn = $1;
|
|
||||||
my $sech = $2;
|
|
||||||
my $font = ($ptype eq 'head') ? \%HeadFont : \%SubhFont;
|
|
||||||
@ls = ps_flow_lines($linewidth, $font, $ptype, @data);
|
|
||||||
# We need the heading number as auxillary data
|
|
||||||
$ls[0]->[0]->[2] = [[$AuxStr,$secn]];
|
|
||||||
} elsif ( $ptype eq 'norm' ) {
|
|
||||||
@ls = ps_flow_lines($linewidth, \%TextFont, $ptype, @data);
|
|
||||||
} elsif ( $ptype eq 'bull' ) {
|
|
||||||
@ls = ps_flow_lines($bullwidth, \%TextFont, $ptype, @data);
|
|
||||||
} elsif ( $ptype =~ /^toc/ ) {
|
|
||||||
unless ( $xtype =~/^\S+ :([^:]*):(.*)$/ ) {
|
|
||||||
die "Bad para";
|
|
||||||
}
|
|
||||||
my $xref = $1;
|
|
||||||
my $refname = $2.' ';
|
|
||||||
my $ntoc = substr($ptype,3,1)+0;
|
|
||||||
my $refwidth = ps_width($refname, $TextFont{fonts}->[0][1]) *
|
|
||||||
($TextFont{fonts}->[0][0]/1000);
|
|
||||||
|
|
||||||
@ls = ps_flow_lines($linewidth-$ntoc*$psconf{tocind}-
|
|
||||||
$psconf{tocpnz}-$refwidth,
|
|
||||||
\%TextFont, $ptype, @data);
|
|
||||||
|
|
||||||
# Auxilliary data: for the first line, the cross reference symbol
|
my $npara = scalar(@{$paras});
|
||||||
# and the reference name; for all lines but the first, the
|
my $i;
|
||||||
# reference width; and for the last line, the page number
|
|
||||||
# as a string.
|
for ( $i = 0 ; $i < $npara ; $i++ ) {
|
||||||
my $nl = scalar(@ls);
|
my $xtype = $ptypes->[$i];
|
||||||
$ls[0]->[0]->[2] = [[$AuxStr,$refname], [$AuxXRef,$xref]];
|
my $ptype = substr($xtype,0,4);
|
||||||
for ( $j = 1 ; $j < $nl ; $j++ ) {
|
my @data = @{$paras->[$i]};
|
||||||
$ls[$j]->[0]->[2] = [[$AuxNum,$refwidth]];
|
my @ls = ();
|
||||||
|
if ( $ptype eq 'code' ) {
|
||||||
|
my $p;
|
||||||
|
# Code paragraph; each chunk is a line
|
||||||
|
foreach $p ( @data ) {
|
||||||
|
push(@ls, [[$ptype,0,undef,\%TextFont,0,0],[$p]]);
|
||||||
|
}
|
||||||
|
$ls[0]->[0]->[1] |= 1; # First in para
|
||||||
|
$ls[-1]->[0]->[1] |= 2; # Last in para
|
||||||
|
} elsif ( $ptype eq 'chap' || $ptype eq 'appn' ) {
|
||||||
|
# Chapters are flowed normally, but in an unusual font
|
||||||
|
@ls = ps_flow_lines($linewidth, \%ChapFont, $ptype, @data);
|
||||||
|
} elsif ( $ptype eq 'head' || $ptype eq 'subh' ) {
|
||||||
|
unless ( $xtype =~ /^\S+ (\S+) :(.*)$/ ) {
|
||||||
|
die "Bad para";
|
||||||
|
}
|
||||||
|
my $secn = $1;
|
||||||
|
my $sech = $2;
|
||||||
|
my $font = ($ptype eq 'head') ? \%HeadFont : \%SubhFont;
|
||||||
|
@ls = ps_flow_lines($linewidth, $font, $ptype, @data);
|
||||||
|
# We need the heading number as auxillary data
|
||||||
|
$ls[0]->[0]->[2] = [[$AuxStr,$secn]];
|
||||||
|
} elsif ( $ptype eq 'norm' ) {
|
||||||
|
@ls = ps_flow_lines($linewidth, \%TextFont, $ptype, @data);
|
||||||
|
} elsif ( $ptype eq 'bull' ) {
|
||||||
|
@ls = ps_flow_lines($bullwidth, \%TextFont, $ptype, @data);
|
||||||
|
} elsif ( $ptype =~ /^toc/ ) {
|
||||||
|
unless ( $xtype =~/^\S+ :([^:]*):(.*)$/ ) {
|
||||||
|
die "Bad para";
|
||||||
|
}
|
||||||
|
my $xref = $1;
|
||||||
|
my $refname = $2.' ';
|
||||||
|
my $ntoc = substr($ptype,3,1)+0;
|
||||||
|
my $refwidth = ps_width($refname, $TextFont{fonts}->[0][1]) *
|
||||||
|
($TextFont{fonts}->[0][0]/1000);
|
||||||
|
|
||||||
|
@ls = ps_flow_lines($linewidth-$ntoc*$psconf{tocind}-
|
||||||
|
$psconf{tocpnz}-$refwidth,
|
||||||
|
\%TextFont, $ptype, @data);
|
||||||
|
|
||||||
|
# Auxilliary data: for the first line, the cross reference symbol
|
||||||
|
# and the reference name; for all lines but the first, the
|
||||||
|
# reference width; and for the last line, the page number
|
||||||
|
# as a string.
|
||||||
|
my $nl = scalar(@ls);
|
||||||
|
$ls[0]->[0]->[2] = [[$AuxStr,$refname], [$AuxXRef,$xref]];
|
||||||
|
for ( $j = 1 ; $j < $nl ; $j++ ) {
|
||||||
|
$ls[$j]->[0]->[2] = [[$AuxNum,$refwidth]];
|
||||||
|
}
|
||||||
|
push(@{$ls[$nl-1]->[0]->[2]}, [$AuxPageStr,$xref]);
|
||||||
|
} elsif ( $ptype =~ /^idx/ ) {
|
||||||
|
my $lvl = substr($ptype,3,1)+0;
|
||||||
|
|
||||||
|
@ls = ps_flow_lines($indxwidth-$lvl*$psconf{idxindent},
|
||||||
|
\%TextFont, $ptype, @data);
|
||||||
|
} else {
|
||||||
|
die "Unknown para type: $ptype";
|
||||||
}
|
}
|
||||||
push(@{$ls[$nl-1]->[0]->[2]}, [$AuxPageStr,$xref]);
|
# Merge adjacent identical chunks
|
||||||
} else {
|
foreach $l ( @ls ) {
|
||||||
die "Unknown para type: $ptype";
|
@{$$l[1]} = ps_merge_chunks(@{$$l[1]});
|
||||||
|
}
|
||||||
|
push(@pslines,@ls);
|
||||||
}
|
}
|
||||||
# Merge adjacent identical chunks
|
|
||||||
foreach $l ( @ls ) {
|
|
||||||
@{$$l[1]} = ps_merge_chunks(@{$$l[1]});
|
|
||||||
}
|
|
||||||
push(@pslines,@ls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Break the main body text into lines.
|
||||||
|
ps_break_lines(\@paras, \@ptypes);
|
||||||
|
|
||||||
#
|
#
|
||||||
# Break lines in to pages
|
# Break lines in to pages
|
||||||
#
|
#
|
||||||
|
|
||||||
# Paragraph types which should never be broken
|
|
||||||
$nobreakregexp = "^(chap|appn|head|subh|toc.)\$";
|
|
||||||
# Paragraph types which are heading (meaning they should not be broken
|
|
||||||
# immediately after)
|
|
||||||
$headingregexp = "^(chap|appn|head|subh)\$";
|
|
||||||
|
|
||||||
$curpage = 3; # First text page is page 3
|
$curpage = 3; # First text page is page 3
|
||||||
$curypos = 0; # Space used on this page
|
$curypos = 0; # Space used on this page
|
||||||
|
undef $columnstart; # Not outputting columnar text
|
||||||
|
undef $curcolumn; # Current column
|
||||||
$nlines = scalar(@pslines);
|
$nlines = scalar(@pslines);
|
||||||
|
|
||||||
$upageheight = $psconf{pageheight}-$psconf{topmarg}-$psconf{botmarg};
|
#
|
||||||
|
# This formats lines inside the global @pslines array into pages,
|
||||||
for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
# updating the page and y-coordinate entries. Start at the
|
||||||
my $linfo = $pslines[$i]->[0];
|
# $startline position in @pslines and go to but not including
|
||||||
if ( ($$linfo[0] eq 'chap' || $$linfo[0] eq 'appn')
|
# $endline. The global variables $curpage, $curypos, $columnstart
|
||||||
&& ($$linfo[1] & 1) ) {
|
# and $curcolumn are updated appropriately.
|
||||||
# First line of a new chapter heading. Start a new line.
|
#
|
||||||
$curpage++ if ( $curypos > 0 );
|
sub ps_break_pages($$) {
|
||||||
$curypos = $chapstart;
|
my($startline, $endline) = @_;
|
||||||
}
|
|
||||||
|
|
||||||
# Adjust position by the appropriate leading
|
# Paragraph types which should never be broken
|
||||||
$curypos += $$linfo[3]->{leading};
|
my $nobreakregexp = "^(chap|appn|head|subh|toc.|idx.)\$";
|
||||||
|
# Paragraph types which are heading (meaning they should not be broken
|
||||||
|
# immediately after)
|
||||||
|
my $headingregexp = "^(chap|appn|head|subh)\$";
|
||||||
|
# Paragraph types which are set in columnar format
|
||||||
|
my $columnregexp = "^idx.\$";
|
||||||
|
|
||||||
# Record the page and y-position
|
my $upageheight = $psconf{pageheight}-$psconf{topmarg}-$psconf{botmarg};
|
||||||
$$linfo[4] = $curpage;
|
|
||||||
$$linfo[5] = $curypos;
|
|
||||||
|
|
||||||
if ( $curypos > $upageheight ) {
|
my $i;
|
||||||
# We need to break the page before this line.
|
|
||||||
my $broken = 0; # No place found yet
|
|
||||||
while ( !$broken && $pslines[$i]->[0]->[4] == $curpage ) {
|
|
||||||
my $linfo = $pslines[$i]->[0];
|
|
||||||
my $pinfo = $pslines[$i-1]->[0];
|
|
||||||
|
|
||||||
if ( $$linfo[1] == 2 ) {
|
for ( $i = $startline ; $i < $endline ; $i++ ) {
|
||||||
# This would be an orphan, don't break.
|
my $linfo = $pslines[$i]->[0];
|
||||||
} elsif ( $$linfo[1] & 1 ) {
|
if ( ($$linfo[0] eq 'chap' || $$linfo[0] eq 'appn' )
|
||||||
# Sole line or start of paragraph. Break unless
|
&& ($$linfo[1] & 1) ) {
|
||||||
# the previous line was part of a heading.
|
# First line of a new chapter heading. Start a new page.
|
||||||
$broken = 1 if ( $$pinfo[0] !~ /$headingregexp/o );
|
undef $columnstart;
|
||||||
} else {
|
$curpage++ if ( $curypos > 0 || defined($columnstart) );
|
||||||
# Middle of paragraph. Break unless we're in a
|
$curypos = $chapstart;
|
||||||
# no-break paragraph, or the previous line would
|
} elsif ( defined($columnstart) && $$linfo[0] !~ /$columnregexp/o ) {
|
||||||
# end up being a widow.
|
undef $columnstart;
|
||||||
$broken = 1 if ( $$linfo[0] !~ /$nobreakregexp/o &&
|
$curpage++;
|
||||||
$$pinfo[1] != 1 );
|
$curypos = 0;
|
||||||
}
|
|
||||||
$i--;
|
|
||||||
}
|
}
|
||||||
die "Nowhere to break page $curpage\n" if ( !$broken );
|
|
||||||
# Now $i should point to line immediately before the break, i.e.
|
|
||||||
# the next paragraph should be the first on the new page
|
|
||||||
$curpage++;
|
|
||||||
$curypos = 0;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add end of paragraph skip
|
if ( $$linfo[0] =~ /$columnregexp/o && !defined($columnstart) ) {
|
||||||
if ( $$linfo[1] & 2 ) {
|
$columnstart = $curypos;
|
||||||
$curypos += $skiparray{$$linfo[0]};
|
$curcolumn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Adjust position by the appropriate leading
|
||||||
|
$curypos += $$linfo[3]->{leading};
|
||||||
|
|
||||||
|
# Record the page and y-position
|
||||||
|
$$linfo[4] = $curpage;
|
||||||
|
$$linfo[5] = $curypos;
|
||||||
|
$$linfo[6] = $curcolumn if ( defined($columnstart) );
|
||||||
|
|
||||||
|
if ( $curypos > $upageheight ) {
|
||||||
|
# We need to break the page before this line.
|
||||||
|
my $broken = 0; # No place found yet
|
||||||
|
while ( !$broken && $pslines[$i]->[0]->[4] == $curpage ) {
|
||||||
|
my $linfo = $pslines[$i]->[0];
|
||||||
|
my $pinfo = $pslines[$i-1]->[0];
|
||||||
|
|
||||||
|
if ( $$linfo[1] == 2 ) {
|
||||||
|
# This would be an orphan, don't break.
|
||||||
|
} elsif ( $$linfo[1] & 1 ) {
|
||||||
|
# Sole line or start of paragraph. Break unless
|
||||||
|
# the previous line was part of a heading.
|
||||||
|
$broken = 1 if ( $$pinfo[0] !~ /$headingregexp/o );
|
||||||
|
} else {
|
||||||
|
# Middle of paragraph. Break unless we're in a
|
||||||
|
# no-break paragraph, or the previous line would
|
||||||
|
# end up being a widow.
|
||||||
|
$broken = 1 if ( $$linfo[0] !~ /$nobreakregexp/o &&
|
||||||
|
$$pinfo[1] != 1 );
|
||||||
|
}
|
||||||
|
$i--;
|
||||||
|
}
|
||||||
|
die "Nowhere to break page $curpage\n" if ( !$broken );
|
||||||
|
# Now $i should point to line immediately before the break, i.e.
|
||||||
|
# the next paragraph should be the first on the new page
|
||||||
|
if ( defined($columnstart) &&
|
||||||
|
++$curcolumn < $psconf{idxcolumns} ) {
|
||||||
|
# We're actually breaking text into columns, not pages
|
||||||
|
$curypos = $columnstart;
|
||||||
|
} else {
|
||||||
|
undef $columnstart;
|
||||||
|
$curpage++;
|
||||||
|
$curypos = 0;
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add end of paragraph skip
|
||||||
|
if ( $$linfo[1] & 2 ) {
|
||||||
|
$curypos += $skiparray{$$linfo[0]};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ps_break_pages(0,$nlines); # Break the main text body into pages
|
||||||
|
|
||||||
#
|
#
|
||||||
# Find the page number of all the indices
|
# Find the page number of all the indices
|
||||||
#
|
#
|
||||||
%ps_xref_page = (); # Crossref anchor pages
|
%ps_xref_page = (); # Crossref anchor pages
|
||||||
%ps_index_pages = (); # Index item pages
|
%ps_index_pages = (); # Index item pages
|
||||||
|
$nlines = scalar(@pslines);
|
||||||
for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
||||||
my $linfo = $pslines[$i]->[0];
|
my $linfo = $pslines[$i]->[0];
|
||||||
foreach my $c ( @{$pslines[$i]->[1]} ) {
|
foreach my $c ( @{$pslines[$i]->[1]} ) {
|
||||||
@ -569,6 +672,48 @@ for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Emit index paragraphs
|
||||||
|
#
|
||||||
|
$startofindex = scalar(@pslines);
|
||||||
|
@ixparas = ([[-5,'index'],[0,'Index']]);
|
||||||
|
@ixptypes = ('chap');
|
||||||
|
|
||||||
|
foreach $k ( @ixentries ) {
|
||||||
|
my $n,$i;
|
||||||
|
my $ixptype = 'idx0';
|
||||||
|
my @ixpara = mkparaarray('idx0',@{$ixterms{$k}});
|
||||||
|
|
||||||
|
push(@ixpara, [-6,undef]); # Left/right marker
|
||||||
|
$i = 1; $n = scalar(@{$ps_index_pages{$k}});
|
||||||
|
foreach $p ( @{$ps_index_pages{$k}} ) {
|
||||||
|
if ( $i++ == $n ) {
|
||||||
|
push(@ixpara,[-7,$p],[0,"$p"],[-1,undef]);
|
||||||
|
} else {
|
||||||
|
push(@ixpara,[-7,$p],[0,"$p,"],[-1,undef],[0,' ']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push(@ixparas, [@ixpara]);
|
||||||
|
push(@ixptypes, $ixptype);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flow index paragraphs into lines
|
||||||
|
#
|
||||||
|
ps_break_lines(\@ixparas, \@ixptypes);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Format index into pages
|
||||||
|
#
|
||||||
|
$nlines = scalar(@pslines);
|
||||||
|
ps_break_pages($startofindex, $nlines);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Push index onto bookmark list
|
||||||
|
#
|
||||||
|
push(@bookmarks, ['index', 0, 'Index']);
|
||||||
|
|
||||||
# Get the list of fonts used
|
# Get the list of fonts used
|
||||||
%ps_all_fonts = ();
|
%ps_all_fonts = ();
|
||||||
foreach $fset ( @AllFonts ) {
|
foreach $fset ( @AllFonts ) {
|
||||||
@ -655,6 +800,7 @@ sub ps_start_page() {
|
|||||||
print "%%BeginPageSetup\n";
|
print "%%BeginPageSetup\n";
|
||||||
print "save\n";
|
print "save\n";
|
||||||
print "%%EndPageSetup\n";
|
print "%%EndPageSetup\n";
|
||||||
|
print '/', $ps_page, " pa\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
# End a PostScript page
|
# End a PostScript page
|
||||||
@ -711,19 +857,19 @@ ps_end_page(0);
|
|||||||
|
|
||||||
$curpage = 3;
|
$curpage = 3;
|
||||||
ps_start_page();
|
ps_start_page();
|
||||||
for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
foreach $line ( @pslines ) {
|
||||||
my $linfo = $pslines[$i]->[0];
|
my $linfo = $line->[0];
|
||||||
|
|
||||||
if ( $$linfo[4] != $curpage ) {
|
if ( $$linfo[4] != $curpage ) {
|
||||||
ps_end_page(1);
|
ps_end_page(1);
|
||||||
ps_start_page();
|
ps_start_page();
|
||||||
$curpage = $$linfo[4];
|
$curpage = $$linfo[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
print '[';
|
print '[';
|
||||||
my $curfont = 0;
|
my $curfont = 0;
|
||||||
foreach my $c ( @{$pslines[$i]->[1]} ) {
|
foreach my $c ( @{$line->[1]} ) {
|
||||||
if ( $$c[0] >= 0 ) {
|
if ( $$c[0] >= 0 ) {
|
||||||
if ( $curfont != $$c[0] ) {
|
if ( $curfont != $$c[0] ) {
|
||||||
print ($curfont = $$c[0]);
|
print ($curfont = $$c[0]);
|
||||||
}
|
}
|
||||||
@ -738,6 +884,11 @@ for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
|||||||
# Index anchor -- ignore
|
# Index anchor -- ignore
|
||||||
} elsif ( $$c[0] == -5 ) {
|
} elsif ( $$c[0] == -5 ) {
|
||||||
print '{/',$$c[1],' xa}'; #xref anchor
|
print '{/',$$c[1],' xa}'; #xref anchor
|
||||||
|
} elsif ( $$c[0] == -6 ) {
|
||||||
|
print ']['; # Start a new array
|
||||||
|
$curfont = 0;
|
||||||
|
} elsif ( $$c[0] == -7 ) {
|
||||||
|
print '{/',$$c[1],' pl}'; # page link
|
||||||
} else {
|
} else {
|
||||||
die "Unknown annotation";
|
die "Unknown annotation";
|
||||||
}
|
}
|
||||||
@ -761,16 +912,9 @@ for ( $i = 0 ; $i < $nlines ; $i++ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
print ($psconf{pageheight}-$psconf{topmarg}-$$linfo[5]);
|
print ($psconf{pageheight}-$psconf{topmarg}-$$linfo[5]);
|
||||||
|
print ' ', $$linfo[6] if ( defined($$linfo[6]) );
|
||||||
print ' ', $$linfo[0].$$linfo[1], "\n";
|
print ' ', $$linfo[0].$$linfo[1], "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
ps_end_page(1);
|
ps_end_page(1);
|
||||||
print "%%EOF\n";
|
print "%%EOF\n";
|
||||||
|
|
||||||
# Emit index as comments for now
|
|
||||||
foreach $k ( sort(keys(%ps_index_pages)) ) {
|
|
||||||
print "% ",$k, ' ', join(',', @{$ps_index_pages{$k}});
|
|
||||||
print ' [prefix]' if ( defined($ixhasprefix{$k}) );
|
|
||||||
print ' [first]' if ( defined($ixcommafirst{$k}) );
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
|
72
doc/head.ps
72
doc/head.ps
@ -26,7 +26,7 @@
|
|||||||
/max { 2 copy lt { exch } if pop } def
|
/max { 2 copy lt { exch } if pop } def
|
||||||
|
|
||||||
/lkbegun 0 def
|
/lkbegun 0 def
|
||||||
/lkisuri false def
|
/lktype null def
|
||||||
/lkury 0 def
|
/lkury 0 def
|
||||||
/lkurx 0 def
|
/lkurx 0 def
|
||||||
/lklly 0 def
|
/lklly 0 def
|
||||||
@ -35,22 +35,28 @@
|
|||||||
/lkymarg 1 def % Extra space for link in y dir
|
/lkymarg 1 def % Extra space for link in y dir
|
||||||
/lktarget () def
|
/lktarget () def
|
||||||
|
|
||||||
% target --
|
% target type --
|
||||||
/linkbegin {
|
/linkbegin {
|
||||||
userdict begin
|
userdict begin
|
||||||
/lkbegun 1 def
|
/lkbegun 1 def
|
||||||
/lkisuri false def
|
/lktype exch def
|
||||||
/lktarget exch def
|
/lktarget exch def
|
||||||
end
|
end
|
||||||
} def
|
} def
|
||||||
|
|
||||||
|
% target --
|
||||||
|
/linkbegindest {
|
||||||
|
/Dest linkbegin
|
||||||
|
} def
|
||||||
|
|
||||||
% uristring --
|
% uristring --
|
||||||
/linkbeginuri {
|
/linkbeginuri {
|
||||||
userdict begin
|
/URI linkbegin
|
||||||
/lkbegun 1 def
|
} def
|
||||||
/lkisuri true def
|
|
||||||
/lktarget exch def
|
% pageno --
|
||||||
end
|
/linkbeginpage {
|
||||||
|
/Page linkbegin
|
||||||
} def
|
} def
|
||||||
|
|
||||||
% string spacepadding --
|
% string spacepadding --
|
||||||
@ -79,12 +85,17 @@
|
|||||||
% --
|
% --
|
||||||
/linkend {
|
/linkend {
|
||||||
userdict begin
|
userdict begin
|
||||||
[ lkisuri {
|
[ lktype /Dest eq {
|
||||||
/Action
|
/Dest lktarget
|
||||||
% << .. >> would be languagelevel 2 :(
|
|
||||||
2 dict dup /Subtype /URI put dup /URI lktarget put
|
|
||||||
} {
|
} {
|
||||||
/Dest lktarget
|
lktype /URI eq {
|
||||||
|
/Action
|
||||||
|
% << .. >> would be languagelevel 2 :(
|
||||||
|
2 dict dup /Subtype /URI put dup /URI lktarget put
|
||||||
|
} {
|
||||||
|
/Dest lktarget
|
||||||
|
% /Page lktarget /View [ /XYZ 0 pageheight null ]
|
||||||
|
} ifelse
|
||||||
} ifelse
|
} ifelse
|
||||||
/Border [0 0 0]
|
/Border [0 0 0]
|
||||||
/Rect [ lkllx lkxmarg sub
|
/Rect [ lkllx lkxmarg sub
|
||||||
@ -278,27 +289,46 @@
|
|||||||
|
|
||||||
/toc00 { tocx0 exch moveto 0 rmoveto tfont showstream } def
|
/toc00 { tocx0 exch moveto 0 rmoveto tfont showstream } def
|
||||||
/toc01 { tocx0 exch moveto
|
/toc01 { tocx0 exch moveto
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream } def
|
||||||
/toc02 { tocx0 exch moveto 3 1 roll
|
/toc02 { tocx0 exch moveto 3 1 roll
|
||||||
0 rmoveto tfont showstream tocpn } def
|
0 rmoveto tfont showstream tocpn } def
|
||||||
/toc03 { tocx0 exch moveto 4 1 roll
|
/toc03 { tocx0 exch moveto 4 1 roll
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
||||||
|
|
||||||
/toc10 { tocx1 exch moveto 0 rmoveto tfont showstream } def
|
/toc10 { tocx1 exch moveto 0 rmoveto tfont showstream } def
|
||||||
/toc11 { tocx1 exch moveto
|
/toc11 { tocx1 exch moveto
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream } def
|
||||||
/toc12 { tocx1 exch moveto 3 1 roll
|
/toc12 { tocx1 exch moveto 3 1 roll
|
||||||
0 rmoveto tfont showstream tocpn } def
|
0 rmoveto tfont showstream tocpn } def
|
||||||
/toc13 { tocx1 exch moveto 4 1 roll
|
/toc13 { tocx1 exch moveto 4 1 roll
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
||||||
|
|
||||||
/toc20 { tocx2 exch moveto 0 rmoveto tfont showstream } def
|
/toc20 { tocx2 exch moveto 0 rmoveto tfont showstream } def
|
||||||
/toc21 { tocx2 exch moveto
|
/toc21 { tocx2 exch moveto
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream } def
|
||||||
/toc22 { tocx2 exch moveto 3 1 roll
|
/toc22 { tocx2 exch moveto 3 1 roll
|
||||||
0 rmoveto tfont showstream tocpn } def
|
0 rmoveto tfont showstream tocpn } def
|
||||||
/toc23 { tocx2 exch moveto 4 1 roll
|
/toc23 { tocx2 exch moveto 4 1 roll
|
||||||
linkbegin tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
linkbegindest tfont0 setfont 0 linkshow tfont showstream tocpn } def
|
||||||
|
|
||||||
|
% Spacing between index columns
|
||||||
|
/indexcolumn pagewidth lmarg sub rmarg sub idxgutter add idxcolumns div def
|
||||||
|
% Width of an individual index column
|
||||||
|
/indexcolwid indexcolumn idxgutter sub def
|
||||||
|
|
||||||
|
/idx03 {
|
||||||
|
2 dict begin
|
||||||
|
indexcolumn mul lmarg add
|
||||||
|
/x exch def /y exch def x y moveto
|
||||||
|
exch tfont showstream
|
||||||
|
dup tfont streamwidth
|
||||||
|
x indexcolwid add exch sub exch pop y moveto
|
||||||
|
tfont showstream
|
||||||
|
end
|
||||||
|
} def
|
||||||
|
/idx00 {idx03} def
|
||||||
|
/idx01 {idx03} def
|
||||||
|
/idx02 {idx03} def
|
||||||
|
|
||||||
%
|
%
|
||||||
% Page numbers
|
% Page numbers
|
||||||
@ -315,8 +345,10 @@
|
|||||||
% Functions invoked during parsing
|
% Functions invoked during parsing
|
||||||
%
|
%
|
||||||
/xa { linkdest } def
|
/xa { linkdest } def
|
||||||
/xl { linkbegin } def
|
/pa { 0 pageheight moveto linkdest } def
|
||||||
|
/xl { linkbegindest } def
|
||||||
/wl { linkbeginuri } def
|
/wl { linkbeginuri } def
|
||||||
|
/pl { linkbeginpage } def
|
||||||
/el { linkend } def
|
/el { linkend } def
|
||||||
|
|
||||||
%
|
%
|
||||||
|
Loading…
Reference in New Issue
Block a user