Next: The Implicit Page Trap, Up: Vertical Position Traps [Contents][Index]
A
page location trap
is a vertical position trap that applies to the page;
that is,
to the top-level diversion.
Many can be present;
manage them with the
wh
and
ch
requests.
Plant macro
name
as page location trap at
dist.
The default scaling unit is
‘v’.
Non-negative values for
dist
set the trap relative to the top of the page;
negative values set the trap relative to the bottom of the page.
It is not possible to plant a trap
less than one basic unit from the page bottom:
the formatter interprets a
dist
of -0
as 0,
the top of the page.
wh
removes any existing
visible
trap
(see below)
at
dist
is removed;
this is its sole function if
name
is missing.
A trap springs only if it is visible, meaning that its location is reachable on the page164 and it is not hidden by another trap at the same location already planted there.
A macro package might set headers and footers as follows; this example
configures vertical margins of one inch to the body text, and one
half-inch to the titles. Observe the use of the no-break control
character with the sp and bp requests to position our text
baselines and prevent a partially collected line from being written
outside the body text, and the page number character ‘%’ used with
the tl request.
.\" hdfo.roff .de hd \" page header ' sp .5i . tl '\\*(Ti''\\*(Da' \" title and date strings ' sp |1i .. .de fo \" page footer ' sp .5i-1v . tl ''%'' ' bp .. .wh 0 hd \" trap at top of the page .wh -1i fo \" trap 1 inch from bottom
Caution: A word about measurements is in order. Recall that
the sp request vertically spaces such that the next text baseline
(of one vee in height by definition) sets with the amount of space given
to sp’s argument above it. Thus in the example above,
when the ‘hd’ trap springs at vertical position ‘0’,
invoking ‘sp .5i’, we get the desired half-inch of top margin.
With the ‘ft’ trap, we space after the body text by one half-inch
minus one vee to leave a half-inch bottom margin. The footer
title, if taller than a baseline rule, thus “encroaches” into
the half-inch margin between the body text and the bottom margin, just
as the header title symmetrically intrudes into the half-inch of space
between its own cap-height and that of the top of the body text.
To use these traps, copy the above (or load it from a file with the
so or mso requests), then set up the strings it uses.
.so hdfo.roff .ds Ti Final Report\" .ds Da 21 May 2023\" .ti On 5 August of last year, this committee tasked me with the investigation of the CFIT (controlled flight into terrain) incident of .\" ...and so on...
A trap above the top or at or below the bottom of the page
can be made visible
by either moving it into the page area
or increasing the page length so that the trap is on the page.
A negative trap value always uses the
current
page length;
the formatter does not convert it to an absolute vertical position.
We can use the
pwh
request to dump page location traps to the standard error stream
(see Debugging).
GNU
troff reports their positions in basic units,
and includes empty slots in the list,
where a trap had been planted
but subsequently (re)moved,
because they can affect the visibility of subsequently planted traps.
An
nroff
device example follows.
.pl 5i
.wh -1i xx
.pwh
error→ xx -240
.pl 100i
.pwh
error→ xx -240
It is possible to have more than one trap at the same location (although
only one at a time can be visible); to achieve this, the traps must be
defined at different locations, then moved to the same place with the
ch request. In the following example, the many empty lines
caused by the bp request are not shown in the output.
.de a
. nop a
..
.de b
. nop b
..
.de c
. nop c
..
.
.wh 1i a
.wh 2i b
.wh 3i c
.bp
⇒ a b c
.ch b 1i
.ch c 1i
.bp
⇒ a
.ch a 0.5i
.bp
⇒ a b
The read-only register .t holds the distance to the next vertical
position trap. If no such traps exist between the drawing position and
the bottom of the page, it contains the distance to the page bottom.
Within a diversion, in the absence of a diversion trap, this distance is
the maximum possible vertical position supported by the output device.
Change the location of a trap by moving macro name to new location
dist, or by unplanting it altogether if dist is absent. The
default scaling unit is ‘v’. Parameters to ch are specified
in the opposite order from wh. If name is the earliest
planted macro of multiple traps at the same location, (re)moving it from
that location exposes the macro next least recently planted at the same
place.165
Changing a trap’s location is useful for building up footnotes in a diversion to allow more space at the bottom of the page for them.
The same macro can be installed simultaneously at multiple locations;
however, only the earliest-planted instance—that has not yet been
deleted with wh—will be moved by ch. The following
example (using an nroff device) illustrates this behavior. Blank
lines have been elided from the output.
.de T Trap sprung at \\n(nlu. .br .. .wh 1i T .wh 2i T foo .sp 11i .bp .ch T 4i bar .sp 11i .bp .ch T 5i baz .sp 11i .bp .wh 5i .ch T 6i qux .sp 11i
⇒ foo
⇒ Trap sprung at 240u.
⇒ Trap sprung at 480u.
⇒ bar
⇒ Trap sprung at 480u.
⇒ Trap sprung at 960u.
⇒ baz
⇒ Trap sprung at 480u.
⇒ Trap sprung at 1200u.
⇒ qux
⇒ Trap sprung at 1440u.
The read-only register .ne contains the amount of space that was
needed in the last ne request that caused a trap to be sprung;
it is useful in conjunction with the .trunc register. See Page Control. Since the .ne register is set only by traps, it
doesn’t make sense to interpolate it outside of macros called by traps.
A read-only register containing the amount of vertical space truncated
from an sp request by the most recently sprung vertical
position trap, or, if the trap was sprung by an ne request,
minus the amount of vertical motion produced by the ne
request. In other words, at the point a trap is sprung, it
represents the difference of what the vertical position would have
been but for the trap, and what the vertical position actually is.
Since the .trunc register is set only by traps, it doesn’t make
sense to interpolate it outside of macros called by traps.
This read-only, string-valued register interpolates the name of the next vertical position trap that will be sprung.
This Boolean-valued, read-only register interpolates 1 while a page is being ejected, and 0 otherwise.
In the following example, we plant the same trap at the top and the bottom of the page. We also make the trap report its name and the vertical drawing position.
.de T
.tm \\$0: page \\n%, nl=\\n[nl] .pe=\\n[.pe]
..
.ll 46n
.wh 0 T
.wh -1v T
Those who can make you believe absurdities can make you
commit atrocities. \[em] Voltaire
error→ T: page 1, nl=0 .pe=0
error→ T: page 1, nl=2600 .pe=1
⇒ Those who can make you believe absurdities can
⇒ make you commit atrocities. -- Voltaire
When designing macros, keep in mind that diversions and traps do not
normally interact. For example, if a trap calls a header macro (while
outputting a diversion) that tries to change the font on the current
page, the effect is not visible before the diversion has completely been
printed (except for input protected with \! or \?) since
the data in the diversion is already formatted. In most cases, this is
not the expected behaviour.
Next: The Implicit Page Trap, Up: Vertical Position Traps [Contents][Index]