.ig

pdfmark.ms

$Id: pdfmark.ms,v 387d581077bd 2026/04/28 18:24:23 keith $

This file is part of the groff-pdfmark extension for the GNU roff
type-setting system.

Copyright (C) 2004-2026 Free Software Foundation, Inc.
written by Keith Marshall <keith.d.marshall@ntlworld.com>

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation, with the
Front-Cover Text being "A GNU MANUAL", with no Back-Cover Texts, and
with no Invariant Sections.

A copy of the Free Documentation License is included as Appendix A
of the document produced by processing this file with pdfroff, with
content as specified in file fdl-v1.3.ms; this is generated from a
verbatim copy of the original GNU plain-text source, which may be
found, as file fdl-v1.3.txt, in groff-pdfmark's fdl directory.
..
.
.\" Add document identification meta-data
.\"
.mso cover-info.ms
.
.CS
Portable Document Format
Publishing with GNU Troff
.AU Keith Marshall
.ie d author@address .AI <\*[author@address]>
.el .AI <keith.d.marshall@ntlworld.com>
.ASSERT-RIGHTS his UK
.FDL-REFERENCE "Appendix A,"
.PUB 2005 2009 2009 2010 2012 2013 2014 2018 \" groff releases
.PUB 2021 2021 2021 2021 2022 2022 2022 2022 \" groff-pdfmark updates
.PUB 2023 2024 2025 2026
.CE
.
.pdfinfo /Subject   Tips and Techniques for Exploiting PDF Features with GNU Troff
.pdfinfo /Keywords  groff troff PDF pdfmark
.
.\" Specify the Internet address for the groff web site.
.\"
.ds GROFF-WEBSITE http://www.gnu.org/software/groff
.
.\" Set the PDF default document view attribute, to ensure that the document
.\" outline is visible, each time the document is opened in Acrobat Reader.
.\"
.pdfview /PageMode /UseOutlines
.pdfview /Page 1 /View [/FitH \n(.p u]
.\"
.\" Initialize the outline view to show only three heading levels,
.\" with additional subordinate level headings folded.
.\"
.nr PDFOUTLINE.FOLDLEVEL 3
.
.\" Set the default cross reference format to indicate section numbers,
.\" rather than page numbers, when we insert a reference pointer; (note
.\" that we preserve the default setting, for later use in examples).
.\"
.rn PDFHREF.INFO PDFHREF.INFO.DEFAULT
.ds PDFHREF.INFO.LOCAL section \\*[SN-NO-DOT] \\$*
.als PDFHREF.INFO PDFHREF.INFO.LOCAL
.
.\" Establish a default format for styling of references to appendices.
.\"
.ds PDFHREF.APPENDIX Appendix \\$1,
.ds PDFHREF.INFO.APPENDIX appendix \\n[XH-APPENDIX-NUMBER] section \\$@
.pdfhref K appendix PDFHREF.APPENDIX
.
.\" Arrange to replace "\h..." escape sequences with a single space,
.\" when filtering text for inclusion in the PDF outline.
.\"
.als sanitize:esc-h sanitize:esc-delimited
.ds  sanitize:esc-h.subst " \"
.
.\" Define a macro, to print reference links WITHOUT the usual "see" prefix.
.\"
.de XR-NO-PREFIX
.rn PDFHREF.PREFIX xx
.XR \\$@
.rn xx PDFHREF.PREFIX
..
.
.\" Define a string, to insert a Registered Trade Mark symbol as
.\" a superscript...
.\"
.ds rg \*{\(rg\*}
.\"
.\" ...and use it to define strings, representing frequently used
.\" registered trade marks.
.\"
.ds Adobe "Adobe\Z'\\$1'\*(rg\"
.ds Acrobat "Acrobat\Z'\\$1'\*(rg\"
.ds Distiller "Distiller\Z'\\$1'\*(rg\"
.ds PostScript "PostScript\Z'\\$1'\*(rg\"
.\"
.ds Microsoft "Microsoft\Z'\\$1'\*(rg\"
.
.\" Define a string to facilitate interpolation of em-dash punctuation,
.\" with spacing in accordance with the British style.
.\"
.ds em \\$1\h'0.6n'\(em\h'0.6n'\\$2
.
.\" Establish the page layout.
.\"
.nr LL 17.0c
.nr LT 17.0c
.nr DI  3n
.nr PI  3n
.nr QI  3n
.nr HY  0
.
.\" Compute the page offset, to distribute the widths of left-hand
.\" and right-hand margins equally, on either side of the specified
.\" line length, within the page width established at groff startup;
.\" note that the page width is not available directly, but must be
.\" deduced from the initial default line length, which groff sets
.\" as two inches less than the actual page width as specified in
.\" papersize.tmac
.\"
.nr PO (2i+\n[.l]u-\n[LL]u)/2
.
.if duplex \{\
.\" When duplex printing layout has been specified, we alternate the
.\" left and right margin settings, as we move from odd to even page
.\" numbers, and back; groff-ms calls the "BT" hook macro within the
.\" scope of a bottom-of-page trap, so we may augment this to adjust
.\" the margins if, and as, required.
.\"
.   nr duplex.balanced \n[PO]
.   if \B'\*[uplex]' .nr PO \*[uplex]
.   ie \n[PO]=\n[duplex.balanced] .ds duplex.printing.hook ig
.   el .ds duplex.printing.hook am BT
.   if \n[PO]>2.5c .nr PO 2.5c
.
.   \*[duplex.printing.hook]
.   \" groff doesn't provide any specific indicator for right margin
.   \" width, or indeed for overall paper width; however, we may get
.   \" the paper width by inference, from papersize.tmac, which sets
.   \" it to two inches more than the initial default value of \n(.l
.   \"
.   \" When advancing from an odd numbered to an even numbered page,
.   \" adjust the PO register to the original right margin width, as
.   \" inferred by subtraction of the original effective left margin
.   \" setting, as established by the initial setting of PO, and the
.   \" effective line length, as established by the initial setting
.   \" of LL, from the inferred paper width.
.   \"
.      ie o .nr PO 2i+\n[.l]u-\n[PO]u-\n[LL]u
.
.   \" Conversely, when advancing from an even numbered page to an
.   \" odd numbered page, we simply revert PO to its initial value.
.   \"
.      el .nr PO \n[PO]u
.   .
.\" Additionally, for duplex printing, it may be best to request the
.\" preservation of blank pages within the document body.
.\"
.   if d pdfroff .pdfroff option preserve_blank_pages=body
.   rm duplex.printing.hook
.   rr duplex.balanced
.\}
.
.\" Generate headers in larger point sizes, for NH levels < 4,
.\" with point size increasing by 1.5p, for each lesser NH level.
.\"
.nr GROWPS 4
.nr PSINCR 1.5p
.
.\" Do not allow fewer than two initial lines of any paragraph
.\" to be orphaned at the bottom of any page.
.\"
.nr PORPHANS 2
.
.\" Immediately following the cover sheet, and front-matter, is the
.\" conventional placement for the table of contents; we begin this
.\" on a new page, with a centred heading, which we have choosen to
.\" set at a font size 2pts greater than that of normal paragraphs,
.\" (thus matching standard "ms" convention), with lower case roman
.\" numerals for page numbering, with its own entry within the PDF
.\" document outline, and with the equivalent of two blank lines
.\" separating the heading from the TOC references.
.\"
.LP
.ce 1
.af % i
.pdfhref O 1 \*[TOC]
.B "\s'+2z'\*[TOC]\s'-2z'"
.sp 2v
.
.\" The front-matter occupies two pages, so the physical first
.\" page number for the TOC, although not printed, will be three,
.\" and if it extends to a second page, where the number will be
.\" printed, this should become page number four.
.\"
.pn 4
.\"
.\" The traditional mechanism, supported by "ms", for generation of
.\" tables of contents, relies on post-press collation, to print the
.\" table of contents AFTER the document body, and then to relocate
.\" it to its conventional position, BEFORE the body content.
.\"
.\" While pdfroff DOES support such post-press collation, it is not
.\" the most effective method for placement of the tables of contents
.\" within PDF documents.  Although a method for use of the technique
.\" is described, in Section 3 of this document, it is not the actual
.\" method employed; in particular, it has been found to be unsuited
.\" to the creation of a table of contents which is actively linked
.\" to its corresponding body content.  Consequently, the preferred
.\" method of table of contents generation is now to save relevant
.\" reference data during the pdfroff pre-press phase, and then to
.\" reimport it during the body content publication phase, using
.\" the groff_toc macros, integrated with pdfroff, and imported
.\" via the spdf-toc.tmac binding macro file.
.\"
.mso spdf-toc.tmac
.\"
.\" Within the table of contents, structural layout will be achieved,
.\" under the direction of the following spacing control constants:
.\"
.TC-DEFINE VS1 1.00v   \" leading for top level
.TC-DEFINE VS2 0.15v   \" leading at nesting level increment
.TC-DEFINE VS3 0.25v   \" leading following nested group
.\"
.TC-DEFINE HS0 1.50n   \" indentation adjustment at top level
.TC-DEFINE HS1 1.50n   \" space between section number and text
.TC-DEFINE HS2 0.50n   \" space between text and following leader
.\"
.\" Additionally, the width of the right-hand margin, in which space
.\" is reserved for the display of page numbers, and the appearance of
.\" the leaders which precede it, are controlled by:-
.\"
.nr TC-MARGIN 8*\w'0'
.char \[TC-LEADER] \h'0.5n'.
.lc \[TC-LEADER]
.\"
.\" Although the TOC is to be entirely populated by active PDFHREF
.\" links, we prefer to not over-emphasize this by use of the link
.\" highlight colour; thus, after breaking the PDFHREF.TEXT.COLOUR
.\" to PDFHREF.TEXT.COLOR equivalence, we may adjust the effective
.\" link colour, to match the normal body text colour.
.\"
.rm PDFHREF.TEXT.COLOUR
.ds PDFHREF.TEXT.COLOUR \n(.m
.\"
.\" Actual content for the TOC has been dynamically captured in the
.\" pdfmark.toc file; simply include it here, then restart TOC data
.\" collection, for use in subsequent formatting passes.
.\"
.toc load pdfmark.toc
.toc file pdfmark.toc
.\"
.\" Finally, reset the page numbering style, and prepare for output
.\" of the document body from the first odd numbered page, following
.\" the physical number of the last page of the TOC.  To achieve this,
.\" we use the NEW-RECTO-PAGE macro, from the newpage.tmac package of
.\" locally defined macros, nominating a register named "%%" to track
.\" the true page number, while an effective page number of one will
.\" be assigned, to suppress numbering on the first new page; also,
.\" declining to specify a particular page number format, results
.\" in adoption of the arabic numeral page numbering style.
.\"
.mso newpage.tmac
.NEW-RECTO-PAGE %%
.
.\" Implement an interface with the FS macro (from s.tmac) to facilitate
.\" placement of footnote reference marks, with each serving as an active
.\" pdfhref link to the associated footnote itself.
.\"
.de pdf:fn.mark nr
.\" Macro to replace original duty performed by "\**"; must be invoked
.\" at point of footnote mark placement, e.g. by FS, BEFORE recording of
.\" the associated text within the footnote diversion is commenced.
.\"
.ie \\n[.$] \{\
.   pdfhref L -D pdf:fn\\$1 -- \\$2
.   pdfhref M -N pdf:fn\\$1r
.\}
.\" s.tmac does not publicly expose its auto-incrementing footnote index;
.\" to avoid a dependency on this undocumented internal feature, we create
.\" our own counter, which we increment as each footnote is marked, while
.\" also concurrently interpolating a renamed "\**" string reference, to
.\" maintain synchronization with the internal s.tmac index.
.\"
.el .\\$0 \\n+[pdf:fn.index.count] \\*[pdf:fn.index]
.nr pdf:fn.index.count 0 1
.rn * pdf:fn.index
.ds * \c
.
.\" For versions of s.tmac which support the FS-MARK callback hook, it
.\" is sufficient for us to answer the callback request.
.\"
.\" FIXME: in time, we may be able to unconditionally assume that this
.\" callback hook will be supported...
.\"
.ie d FS-MARK .als FS-MARK pdf:fn.mark
.el \{\
.\" ...but in the interim, we may need to redefine s.tmac's FS macro,
.\" (actually the @FS internal macro, rather than FS itself), to gain
.\" an effect equivalent to taking control of FS-MARK, to achieve the
.\" placement of a footnote mark as an active pdfhref link.
.\"
.rn @FS pdf:fn.record
.de @FS
.pdf:fn.mark
.pdf:fn.record
..
.\}
.\" Override s.tmac's (undocumented) footnote output hook; this emulates
.\" the default output style for \n[FF] == 3 footnotes, with the footnote
.\" number formatted as a pdfhref link back to the position at which the
.\" footnote marker appears, within the document text.
.\"
.de FP
.LP
.nr pdf:fn.tag.width (u;2*\\n[FI])
.ds pdf:fn.tag \s'-1.5z'\\$1.\s'+1.5z'
.pdfhref M -N pdf:fn\\$1
.in +\\n[pdf:fn.tag.width]u
.ti -\\n[pdf:fn.tag.width]u
.nr pdf:fn.tag.width -\\w'\\*[pdf:fn.tag]'u
.pdfhref L -D pdf:fn\\$1r -A \\h'\\n[pdf:fn.tag.width]u'\c -- \\*[pdf:fn.tag]
..
.\" When a footnote marker is placed adjacent to punctuation which would
.\" normally end a sentence, the normal end-of-sentence spacing effect is
.\" suppressed; this alternative footnote termination macro augments the
.\" effect of the normal FE macro, to reactivate sentence spacing.
.\"
.de FZ
.FE
.\" Without arguments, this becomes equivalent to FE alone; there is no
.\" more to do.  However, WITH arguments, we emit them invisibly, without
.\" spacing, such that if they exhibit the semantics of end-of-sentence
.\" punctuation, the sentence spacing effect is reactivated.
.\"
.if \\n[.$] \O0\Z'\\$*'\O\\n[OPMODE]
..
.de pdfhref-nobreak
.\" FIXME: I've only noticed this anomaly when planting pdfhref links
.\" within footnotes; if the start of the link text is placed near the
.\" line length limit, and all of it is moved to the start of the next
.\" line, the "hot-spot" region is computed to be one line higher than
.\" it should be; ending the preceding input line with "\c", and then
.\" invoking pdfhref via this wrapper, works around this issue.
.\"
.ie \\n[.l]-\\n[.i]-\\n[.k]-\\w'\\$\\n[.$]' \&
.el \p
.pdfhref \\$*
..
.
.\" Define a local macro to facilitate choice of style for emphasis;
.\" by default, make it equivalent to the ms standard "I" macro, but
.\" with a 0.3 point size increment in italicized text.
.\"
.de EM
.   I "\s'+0.3z'\\$1\s'-0.3z'" "\\$2" "\\$3"
..
.\" Also, define variations on the ms standard "CW" macro, to add
.\" bold, italic, and both styles to constant width text; note that
.\" each of these accept two additional arguments, in comparison to
.\" standard "CW", such that \$1 specifies the text which is to be
.\" styled, \$2 and \$3 specify inner after/before bracketting, to
.\" set as regular "CW" text,  while \$4 and \$5 become equivalent
.\" to \$2 and \$3 of standard "CW", acting as outer bracketting.
.\"
.de CWB
.   nop \\$5\f(CR\\$3\fP\f(CB\\$1\fP\f(CB\\$2\fP\\$4
..
.de CWI
.   nop \\$5\f(CR\\$3\fP\f(CI\\$1\fP\f(CR\\$2\fP\\$4
..
.de CWBI
.   nop \\$5\f(CR\\$3\fP\f[CBI]\\$1\fP\f(CR\\$2\fP\\$4
..
.\" Finally, augment this group with a variant string, which may be
.\" used to set constant width tags on "IP" paragraphs, with \$1 set
.\" as if by "CWB", followed by an optional suffix set as if by "CWBI",
.\" and with the suffix bracketted by \$3 after and \$4 before, each
.\" set in the regular "CW" style.
.\"
.ds = \f(CB\\$1\f(CR\\$4\f[CBI]\\$2\f(CR\\$3
.
.\" Additionally, add a cross-reference convenience macro, emulating
.\" the style of the "ms" font change macros...
.\"
.\"  .XR <dest-name> [<affixed> [<prefix>]]
.\"
.\" ...such that, when invoked with one, two, or three arguments, this
.\" expands to the equivalent of:
.\"
.\"  .pdfhref L -D <dest-name> [-A <affixed> [-P <prefix>]]
.\"
.\" to place a pdfhref reference link, to a named destination, within
.\" the same document, using the reference text which is predefined in
.\" the reference dictionary entry associated with the destination.
.\"
.de XR
.if \\n(.$ \{\
.   if \\n[OPMODE] \{\
.         ds xr!argv -D "\\$1"
.         if \\n(.$>1 .as xr!argv " -A "\\$2"
.         if \\n(.$>2 .as xr!argv " -P "\\$3"
.         pdfhref L \\*[xr!argv]
.         rm xr!argv
.      \}
.   \}
..
.
.\" Enable enhanced support for the placement of floating keeps, in
.\" relation to the flow of surrounding text.
.\"
.mso float.tmac
.
.
.\" Begin text of document.
.\"
.NH 1
.XN Introduction
.\"
.\" If using an old s.tmac, without the SN-NO-DOT extension, ensure
.\" that we get SOMETHING in section number references.
.\"
.if !d SN-NO-DOT .als SN-NO-DOT SN
.LP
It might appear that it is a fairly simple matter to
produce documents in \*[Adobe]\~\(lqPortable\~Document\~Format\(rq,
commonly known as PDF, using
.CW groff ) GNU\~Troff\~(
as the document formatter.
Indeed,
.CW groff 's
default output format is the native \*[Adobe]\~\*[PostScript] format,
which PDF producers such as \*[Adobe] \*[Acrobat] \*[Distiller ,]
or Ghostscript, expect as their input format.
Thus, the PDF production process would seem to entail simply
formatting the document source with
.CW groff ,
to produce a \*[PostScript] version of the document,
which can subsequently be processed by \*[Acrobat] \*[Distiller]
or Ghostscript, to generate the final PDF document.
.LP
For many PDF production requirements,
the production cycle described above may be sufficient.
However, this is a limited PDF production method,
in which the resultant PDF document represents no more than
an on screen image of the printed form of the document, if
.CW groff 's
\*[PostScript] output were printed directly.
.LP
The Portable Document Format provides a number of features,
which significantly enhance the experience of reading a document on screen,
but which are of little or no value to a document which is merely printed.
It
.EM is
possible to exploit these PDF features, which are described in the \*[Adobe]
.de pdfmark-manual pdfmark-manual
.\" This is an example of a resource reference specified by URI ...
.\" We may need to refer often to the Adobe pdfmark Reference Manual,
.\" so we create the internet link definition using a macro, to make
.\" it reusable.
.\"
.\" Note also, that we protect the description of the reference by
.\" preceding it with "--", to avoid "invalid character in name" type
.\" error messages from groff (caused by the use of "\~").
.\"
.pdfhref W -D https://www.adobe.com/go/acrobatsdk_pdfmark \
    -P \(lq -A \(rq\\$1 -- pdfmark\~Reference\~Manual
.pdfmark-manual ,
with some refinement of the simple PDF production method, provided
appropriate \(lqfeature implementing\(rq instructions can be embedded into
.CW groff 's
\*[PostScript] rendering of the document.
This, of course, implies that the original document source, which
.CW groff
will process to generate the \*[PostScript] description of the document,
must include appropriate markup to exploit the desired PDF features.
It is this preparation of the
.CW groff
document source to exploit a number of these features,
which provides the principal focus of this document.
.LP
The markup techniques to be described have been utilized in the production of
the PDF version of this document itself.
This has been formatted using
.CW groff 's
.CW ms
macro package;
thus, usage examples may be found in the document source file,
.CW pdfmark.ms ,
to which copious comments have been added,
to help identify appropriate markup examples for implementing PDF features,
such as:\(en
.QS
.sp -\n[PD]u
.IP \(bu 2n
Selecting a default document view, which defines how the document will appear
when opened in the reader application; for example, when this document is
opened in \*[Acrobat]\~Reader, it should display the top of the cover sheet,
in the document view pane, while a document outline should appear to the left,
in the \(lqBookmarks\(rq pane.
.IP \(bu
Adding document identification \%\(lqmeta\(hydata\(rq,
which can be accessed, in \*[Acrobat]\~Reader,
by inspecting the \(lqFile\^/\^Document\~Properties\^/\^Summary\(rq.
.IP \(bu
Creating a document outline, which will be displayed in the \(lqBookmarks\(rq
pane of \*[Acrobat]\~Reader, such that readers may quickly navigate to any
section of the document, simply by clicking on the associated heading
in the outline view.
.IP \(bu
Embedding active links in the body of the document, such that readers may
quickly navigate to related material at another location within the same
document, or in another PDF document, or even to a related Internet resource,
specified by its URI.
.IP \(bu
Adding annotations, in the form of \(lqsticky notes\(rq, at strategic
points within the PDF document.
.QE
.sp -\n[PD]u
.LP
All of the techniques described have been tested on
.EM both
GNU/Linux, and on \*[Microsoft] Windows\(tm2000 operating platforms, using
.CW groff
.CW 1.19.1 \Z','\|\**
.FS
Later versions should, and some earlier versions may, be equally suitable.
See\c
.pdfhref-nobreak W \*[GROFF-WEBSITE]
for information and availability of the latest version.
.FE
in association with
.CW AFPL
.CW Ghostscript
.CW 8.14 \Z'.'\|\**
.FS
Again, other versions may be suitable.
See\c
.pdfhref-nobreak W http://ghostscript.com
for information and availability.
.FZ Ghostscript 8.14.
Other tools employed, which should be readily available on
.EM any
Unix\(tm
or GNU/Linux system, are
.CW sed ,
.CW awk
and
.CW make ,
together with an appropriate text editor, for creating and marking up the
.CW groff
input files.
These additional utilities are not provided, as standard,
on the \*[Microsoft] Windows\(tm platform,
but several third party implementations are available.
Some worth considering include the MKS\*(rg\~Toolkit\Z','\|\**
.FS
A commercial offering; see\c
.pdfhref-nobreak W http://mkssoftware.com/products/tk/default.asp
for information.
.FE
Cygwin\Z','\|\**
.FS
A
.EM free
but comprehensive
.SM
POSIX
.LG
emulation environment and
Unix\(tm
toolkit for \%32\(hybit \*[Microsoft] Windows\(tm platforms; see\c
.pdfhref-nobreak W http://cygwin.com
for information and download.
.FE
or MSYS\Z'.'\|\**
.FS
Another free, but minimal suite of common
Unix\(tm
tools for \%32\(hybit \*[Microsoft] Windows\(tm, available for download from\c
.pdfhref-nobreak W -A ; https://mingw.osdn.io
it
.EM does
include those tools listed above,
and is the package which was actually used when performing the Windows\(tm2000
platform tests referred to in the text.
.FZ MSYS.
This list is by no means exhaustive, and should in no way be construed as an
endorsement of any of these packages, nor to imply that other similar packages,
which may be available, are in any way inferior to them.
.bp
.
.NH 1
.\" We may wish a section heading to represent a named destination,
.\" so that we can create a linked reference to it, from some other
.\" part of the PDF document, (or even from another PDF document).
.\"
.\" Here we use the "-N" option of the "XN" macro, to create a named
.\" PDF link destination, at the location of the heading.  Notice that
.\" we also use the "--" marker to separate the heading text from the
.\" preceding option specification; it is not strictly necessary in
.\" this case, but it does help to set off the heading text from the
.\" option specification.
.\"
.XN -N pdf-features -- Exploiting PDF Document Features
.LP
To establish a consistent framework for adding PDF features, a
.CW groff
macro package, named
.CW pdfmark.tmac ,
has been provided.
Thus, to incorporate PDF features in a document,
the appropriate macro calls, as described below, may be placed in the
.CW groff
document source, which should then be processed with a
.CW groff
command of the form\**
.FS
.pdfhref M pdf-features-fn
.nr pdf-features-fn \n[fn*text-num]
Note that,
if any
.CW -T \^\c
.CWI dev
option is specified,
it should be either
.CW -T \^\c
.CW ps ,
or
.CW -T \^\c
.CW pdf ;
any other explicit choice is unlikely to be compatible with
.CW -m \|\|\c
.CW pdfmark ,
and will have an unpredictable
(possibly erroneous)
effect on the output.
If no
.CW -T \^\c
.CWI dev
option is specified,
(in which case
.CW -T \^\c
.CW ps
is implicitly assumed),
or if
.CW -T \^\c
.CW ps
is explicitly specified,
then the output will be produced in \*[PostScript] format,
and will require conversion to PDF,
(e.g. by using Ghostscript tools);
explicit specification of
.CW -T \^\c
.CW pdf
will result in direct output in PDF format,
thus obviating the need for conversion.
.FE
.QP
.fam C
groff [-Tps\h'0.2p'|\h'0.2p'-Tpdf] [-m\F[]\|\|\FC\c
.I name ]
-m\F[]\|\|\FC\c
.B pdfmark
.I options \F[]\|\|\FC\c [-
.I file \F[]\|\|\FC\c "...] "
\&...
.LP
It may be noted that the
.CW pdfmark
macros have no dependencies on, and no known conflicts with,
any other
.CW groff
macro package;  thus, users are free to use any other macro package,
of their choice, to format their documents, while also using the
.CW pdfmark
macros to add PDF features.
.
.NH 2
.XN -S -N pdfmark-operator -- The \F[C]pdfmark\F[] Operator
.LP
All PDF features are implemented by embedding instances of the
.B \F[C]pdfmark\F[]
operator, as described in the \*[Adobe]
.pdfmark-manual ,
into
.CW groff 's
\*[PostScript] output stream.
To facilitate the use of this operator, the
.CW pdfmark
macro package defines the primitive
.CW pdfmark
macro; it simply emits its argument list,
as arguments to a
.CW pdfmark
operator, in the \*[PostScript] output stream.
.LP
.pdfhref M -N pdfmark-example
To illustrate the use of the
.CW pdfmark
macro, the following is a much simplified example of how a bookmark
may be added to a PDF document outline
.QP
.CW ".pdfmark \e"
.RS 4
.nf
.fam C
/Count 2 \e
/Title (An Example of a Bookmark with Two Children) \e
/View  [/FitH \en[PDFPAGE.Y]] \e
/OUT
.RE
.LP
In general, users should rarely need to use the
.CW pdfmark
macro directly.
In particular, the above example is too simple for general use; it
.EM will
create a bookmark, but it does
.EM not
address the issues of setting the proper value for the
.CW /Count
key, nor of computing the
.CW PDFPAGE.Y
value used in the
.CW /View
key. The
.CW pdfmark
macro package includes a more robust mechanism for creating bookmarks,
.\"
.\" Here is an example of how a local reference may be planted,
.\" using the automatic formatting feature of the "pdfhref" macro.
.\"
.\" This is a forward reference to the named destination "add-outline",
.\" which is defined below, using the "XN" wrapper macro, from the
.\" "spdf.tmac" macro package.  The automatically formatted reference
.\" will be enclosed in parentheses, as specified by the use of
.\" "-P" and "-A" options.
.\"
.pdfhref L -P ( -A ), -D add-outline
.\"
which addresses these issues automatically.
Nevertheless, the
.CW pdfmark
macro may be useful to users wishing to implement more advanced PDF features,
than those currently supported directly by the
.CW pdfmark
macro package.
.
.NH 2
.XN -N docview -- Selecting an Initial Document View
.LP
By default,
when a PDF document is opened,
the first page will be displayed,
at the default magnification set for the reader,
and outline and thumbnail views will be hidden.
When using a PDF reader,
such as \*[Acrobat]\~Reader,
which supports the
.CW /DOCVIEW
class of the
.CW pdfmark
operator,
these default initial view settings may be overridden,
using the
.CW pdfview
macro.
For example
.QP
.CW ".pdfview /PageMode /UseOutlines"
.LP
will cause \*[Acrobat]\~Reader to open the document outline view,
to the left of the normal page view,
while
.QP
.CW ".pdfview /PageMode /UseThumbs"
.LP
will open the thumbnail view instead.
.LP
Note that the two
.CW /PageMode
examples, above, are mutually exclusive\*[em]it is not possible to have
.EM both
outline and thumbnail views open simultaneously.
However, it
.EM is
permitted to add
.CW /Page
and
.CW /View
keys, to force the document to open at a page other than the first,
or to change the magnification at which the document is initially displayed;
see the
.pdfmark-manual
for more information.
.LP
It should be noted that the view controlling \%meta\(hydata, defined by the
.CW pdfview
macro, is not written immediately to the \*[PostScript] output stream,
but is stored in an internal \%meta\(hydata \(lqcache\(rq,
(simply implemented as a
.CW groff
diversion).
This \(lqcached\(lq \%meta\(hydata must be written out later, by invoking the
.CW pdfsync
macro,
.\"
.\" Here is another example of how we may introduce a forward reference.
.\" This time we are using the shorter notation afforded by the "XR" macro
.\" provided by "spdf.tmac"; this example is equivalent to the native
.\" "pdfmark.tmac" form
.\"     .pdfhref L -D pdfsync -P ( -A ).
.\"
.XR pdfsync ). (
.
.NH 2
.XN -N docinfo -- Adding Document Identification Meta-Data
.LP
In addition to the
.CW /DOCVIEW
class of \%meta\(hydata described above,
.XR docview ), (
we may also wish to include document identification \%meta\(hydata,
which belongs to the PDF
.CW /DOCINFO
class.
.LP
To do this, we use the
.CW pdfinfo
macro.
As an example of how it is used,
the identification \%meta\(hydata attached to this document
was specified using a macro sequence similar to:\(en
.DS I
.fam C
\&.pdfinfo /Title     PDF Document Publishing with GNU Troff
\&.pdfinfo /Author    Keith Marshall
\&.pdfinfo /Subject   How to Exploit PDF Features with GNU Troff
\&.pdfinfo /Keywords  groff troff PDF pdfmark
.DE
Notice that the
.CW pdfinfo
macro is repeated, once for each
.CW /DOCINFO
record to be placed in the document.
In each case, the first argument is the name of the applicable
.CW /DOCINFO
key, which
.EM must
be named with an initial solidus character;
all additional arguments are collected together,
to define the value to be associated with the specified key.
.LP
As is the case with the
.CW pdfview
macro,
.XR docview ), (
the
.CW /DOCINFO
records specified with the
.CW pdfinfo
macro are not immediately written to the \*[PostScript] output stream;
they are stored in the same \%meta\(hydata cache as
.CW /DOCVIEW
specifications, until this cache is explicitly flushed,
by invoking the
.CW pdfsync
macro,
.XR pdfsync ). (
.
.NH 2
.XN -N add-outline -- Creating a Document Outline
.LP
A PDF document outline comprises a table of references,
to \(lqbookmarked\(rq locations within the document.
When the document is viewed in an \(lqoutline\~aware\(rq PDF document reader,
such as \*[Adobe] \*[Acrobat] Reader,
this table of \(lqbookmarks\(rq may be displayed in a document outline pane,
or \(lqBookmarks\(rq pane, to the left of the main document view.
Individual references in the outline view may then be selected,
by clicking with the mouse,
to jump directly to the associated marked location in the document view.
.LP
The document outline may be considered as a collection of \(lqhypertext\(rq
references to \(lqbookmarked\(rq locations within the document.
The
.CW pdfmark
macro package provides a single generalized macro,
.CW pdfhref ,
for creating and linking to \(lqhypertext\(rq reference marks.
This macro will be described more comprehensively in a later section,
.XR pdfhref ); (
the description here is restricted to its use for defining document outline entries.
.
.NH 3
.XN -N basic-outline -- A Basic Document Outline
.LP
In its most basic form, the document outline comprises a structured list of headings,
each associated with a marked location, or \(lqbookmark\(rq, in the document text,
and a specification for how that marked location should be displayed,
when this bookmark is selected.
.LP
To create a PDF bookmark, the
.CW pdfhref
macro is used,
at the point in the document where the bookmark is to be placed,
in the form
.QP
.fam C
.B ".pdfhref O"
.I level > <
.I "descriptive text ..."
.LP
in which the reference class
.CWB O \& \& \(rq \(lq
stipulates that this is an outline reference.
.LP
Alternatively, for those users who may prefer to think of a document outline
simply as a collection of bookmarks, the
.CW pdfbookmark
macro is also provided\*[em]indeed,
.CW pdfhref
invokes it, when processing the
.CWB O \& \& \(rq \(lq
reference class operator.
It may be invoked directly, in the form
.QP
.fam C
.B .pdfbookmark
.I level > <
.I "descriptive text ..."
.LP
Irrespective of which of the above macro forms is employed, the
.CWI level > <
argument is required.
It is a numeric argument, defining the nesting level of the \(lqbookmark\(rq
in the outline hierarchy, with one being the topmost level.
Its function may be considered analogous to the
.EM "heading level"
of the document's section headings,
for example, as specified with the
.CW NH
macro, if using the
.CW ms
macros to format the document.
.LP
All further arguments, following the
.CWI level > <
argument, are collected together, to specify the heading text which will appear
in the document's outline view.
Thus, the outline entry for this section of this document,
which has a level three heading,
might be specified as
.QP
.fam C
\&.pdfhref O 3 \*(SN A Basic Document Outline
.LP
or, in the alternative form using the
.CW pdfbookmark
macro, as
.QP
.fam C
\&.pdfbookmark 3 \*(SN A Basic Document Outline
.
.NH 3
.XN Hierarchical Structure in a Document Outline
.LP
When a document outline is created, using the
.CW pdfhref
macro as described in
.\"
.\" Here is an example of how we can temporarily modify the format of
.\" a reference link, in this case to indicate only the section number
.\" of the link target, in the form "section #", (or, if we define
.\" "SECREF.BEGIN" before the call, its content followed by the
.\" section number).
.\"
.\" We first define a macro, which will get the reference data from
.\" pdfhref, as arguments, and will return the formatted output, as we
.\" require it, the string "PDFHREF.TEXT".
.\"
.de SECREF
.while \\n(.$ \{\
.   ie '\\$1'section' \{\
.      if !dSECREF.BEGIN .ds SECREF.BEGIN \\$1
.      ds PDFHREF.TEXT \\*[SECREF.BEGIN]\~\\$2
.      rm SECREF.BEGIN
.      shift \\n(.$
.      \}
.   el \{\
.      shift
.      if \\n(.$ .shift
.      \}
.   \}
..
.\" We now tell "pdfhref" to use our formatting macro, in place of
.\" its builtin default formatter, before we specify the reference.
.\"
.pdfhref F SECREF
.pdfhref L -A , -D basic-outline
.\"
.\" At this point, we would normally revert the "pdfhref" formatter
.\" to use its default, built in macro.  However, in this particular
.\" case, we want to use our custom format one more time, before we
.\" revert it, so we will omit the reversion step this time.
.\"
and any entry is added at a nesting level greater than one,
then a hierarchical structure is automatically defined for the outline.
However, as was noted in the simplified
.pdfhref L -D pdfmark-example -- example
in
.pdfhref L -A , -D pdfmark-operator
.\"
.\" And now, we revert to default "pdfhref" formatting behaviour,
.\" by completing the call we delayed above.
.\"
.pdfhref F
.\"
the data required by the
.CW pdfmark
operator to create the outline entry may not be fully defined,
when the outline reference is defined in the
.CW groff
document source.
Specifically, when the outline entry is created, its
.CW /Count
key must be assigned a value equal to the number of its subordinate entries,
at the next inner level of the outline hierarchy;
typically however,
these subordinate entries will be defined
.EM later
in the document source, and the appropriate
.CW /Count
value will be unknown, when defining the parent entry.
.LP
To resolve this paradox, the
.CW pdfhref
macro creates the outline entry in two distinct phases\*[em]a
destination marker is placed in the \*[PostScript] output stream immediately,
when the outline reference is defined,
but the actual outline entry is stored in an internal \(lqoutline cache\(rq,
until its subordinate hierarchy has been fully defined;
it can then be inserted in the output stream, with its
.CW /Count
value correctly assigned.
Effectively, to ensure integrity of the document outline structure,
this means that each top level outline entry, and
.EM all
of its subordinates, are retained in the cache, until the
.EM next
top level entry is defined.
.LP
One potential problem, which arises from the use of the \(lqoutline cache\(rq,
is that, at the end of any document formatting run, the last top level outline entry,
and any subordinates defined after it, will remain in the cache, and will
.EM not
be automatically written to the output stream.
To avoid this problem, the user should follow the guidelines given in
.\"
.\" Here is a more conventional example of how to temporarily change
.\" to the format used to display reference links.  We will again use
.\" the "SECREF" format, which we defined above, but on this occasion
.\" we will immediately revert to the default format, after the link
.\" has been placed.
.\"
.pdfhref F SECREF
.pdfhref L -D pdfsync -A ,
.pdfhref F
.\"
to synchronize the output state with the cache state,
.XR pdfsync ), (
at the end of the
.CW groff
formatting run.
.
.NH 3
.XN -N outline-view -- Associating a Document View with an Outline Reference
.LP
Each \(lqbookmark\(rq entry, in a PDF document outline,
is associated with a specific document view.
When the reader selects any outline entry,
the document view changes to display the document context
associated with that entry.
.LP
The document view specification,
to be associated with any document outline entry,
is established at the time when the outline entry is created.
However, rather than requiring that each individual use of the
.CW pdhref
macro, to create an outline entry,
should include its own view specification,
the actual specification assigned to each entry is derived from
a generalized specification defined in the string
.CW PDFBOOKMARK.VIEW ,
together with the setting of the numeric register
.CW PDFHREF.VIEW.LEADING ,
which determine the effective view specification as follows:\(en
.QS
.sp -\n[PD]u
.IP \*[= PDFBOOKMARK.VIEW]
Establishes the magnification at which the document will be viewed,
at the location of the \(lqbookmark\(rq; by default, it is defined by
.RS
.QP
.CW ".ds PDFBOOKMARK.VIEW /FitH \e\en[PDFPAGE.Y] u"
.RE
.IP
which displays the associated document view,
with the \(lqbookmark\(rq location positioned at the top of the display window,
and with the magnification set to fit the page width to the width of the window.
.IP \*[= PDFHREF.VIEW.LEADING]
Specifies additional spacing,
to be placed between the top of the display window
and the actual location of the \(lqbookmark\(rq on the displayed page view.
By default, it is set as
.RS
.QP
.CW ".nr PDFHREF.VIEW.LEADING 5.0p"
.RE
.IP
Note that
.CW PDFHREF.VIEW.LEADING
does not represent true \(lqleading\(rq, in the typographical sense,
since any preceding text, set in the specified display space,
will be visible at the top of the document viewing window,
when the reference is selected.
.IP
Also note that the specification of
.CW PDFHREF.VIEW.LEADING
is shared by
.EM all
reference views defined by the
.CW pdfhref
macro; whereas
.CW PDFBOOKMARK.VIEW
is applied exclusively to outline references,
there is no independent
.CW PDFBOOKMARK.VIEW.LEADING
specification.
.QE
.LP
If desired, the view specification may be changed, by redefining the string
.CW PDFBOOKMARK.VIEW ,
and possibly also the numeric register
.CW PDFHREF.VIEW.LEADING .
Any alternative definition for
.CW PDFBOOKMARK.VIEW
.EM must
be specified in terms of valid view specification parameters,
as described in the \*[Adobe]
.pdfmark-manual .
.LP
Note the use of the register
.CW PDFPAGE.Y ,
in the default definition of
.CW PDFBOOKMARK.VIEW
above.
This register is computed by
.CW pdfhref ,
when creating an outline entry;
it specifies the vertical position of the \(lqbookmark\(rq,
in basic
.CW groff
units, relative to the
.EM bottom
edge of the document page on which it is defined,
and is followed, in the
.CW PDFBOOKMARK.VIEW
definition, by the
.CW grops
.CW u \(rq \(lq
operator, to convert it to \*[PostScript] units on output.
It may be used in any redefined specification for
.CW PDFBOOKMARK.VIEW ,
(or in the analogous definition of
.CW PDFHREF.VIEW ,
described in
.ne 2v
.XR-NO-PREFIX pdfhref-view ),
but
.EM not
in any other context,
since its value is undefined outside the scope of the
.CW pdfhref
macro.
.LP
Since
.CW PDFPAGE.Y
is computed relative to the
.EM bottom
of the PDF output page,
it is important to ensure that the page length specified to
.CW troff
correctly matches the size of the logical PDF page.
This is most effectively ensured,
by providing
.EM identical
page size specifications to
.CW groff ,
.CW grops
and to the \*[PostScript] to PDF converter employed,
and avoiding any page length changes within the document source.
.LP
Also note that
.CW PDFPAGE.Y
is the only automatically computed \(lqbookmark\(rq location parameter;
if the user redefines
.CW PDFBOOKMARK.VIEW ,
and the modified view specification requires any other positional parameters,
then the user
.EM must
ensure that these are computed
.EM before
invoking the
.CW pdfhref
macro.
.
.NH 3
.XN -N outline-folding -- Folding the Outline to Conceal Less Significant Headings
.LP
When a document incorporates many subheadings,
at deeply nested levels,
it may be desirable to \(lqfold\(rq the outline
such that only the major heading levels are initially visible,
yet making the inferior subheadings accessible,
by allowing the reader to expand the view of any heading branch on demand.
.LP
The
.CW pdfmark
macros support this capability,
through the setting of the
.CW PDFOUTLINE.FOLDLEVEL
register.
This register should be set to the number of heading levels
which it is desired to show in expanded form, in the
.EM initial
document outline display;
all subheadings at deeper levels will still be added to the outline,
but will not become visible until the outline branch containing them is expanded.
.ne 5
For example, the setting used in this document:
.DS I
.fam C
\&.\e" Initialize the outline view to show only three heading levels,
\&.\e" with additional subordinate level headings folded.
\&.\e"
\&.nr PDFOUTLINE.FOLDLEVEL 3
.DE
.sp -\n[PD]u
.LP
results in only the first three levels of headings being displayed
in the document outline,
.EM until
the reader chooses to expand the view,
and so reveal the lower level headings in any outline branch.
.LP
The initial default setting of
.CW PDFOUTLINE.FOLDLEVEL ,
if the document author does not choose to change it,
is 10,000.
This is orders of magnitude greater than the maximum heading level
which is likely to be used in any document;
thus the default behaviour will be to show document outlines fully expanded,
to display all headings defined,
at all levels within each document.
.LP
The setting of
.CW PDFOUTLINE.FOLDLEVEL
may be changed at any time;
however, the effect of each such change may be difficult to predict,
since it is applied not only to outline entries which are defined
.EM after
the setting is changed,
but also to any entries which remain in the outline cache,
.EM at
this time.
Therefore, it is recommended that
.CW PDFOUTLINE.FOLDLEVEL
should be set
.EM once ,
at the start of each document;
if it
.EM is
deemed necessary to change it at any other time,
the outline cache should be flushed,
.XR pdfsync ), (
.EM immediately
before the change,
which should immediately precede a level one heading.
.
.NH 3
.XN -N multipart-outline -- Outlines for Multipart Documents
.LP
When a document outline is created, using the
.CW pdfhref
macro, each reference mark is automatically assigned a name,
composed of a fixed stem followed by a serially generated numeric qualifier.
This ensures that, for each single part document, every outline reference
has a uniquely named destination.
.LP
As the overall size of the PDF document increases,
it may become convenient to divide it into smaller,
individually formatted \*[PostScript] components,
which are then assembled, in the appropriate order,
to create a composite PDF document.
While this strategy may simplify the overall process of creating and
editing larger documents, it does introduce a problem in creating
an overall document outline,
since each individual \*[PostScript] component will be assigned
duplicated sequences of \(lqbookmark\(rq names,
with each name ultimately referring to multiple locations in the composite document.
To avoid such reference naming conflicts, the
.CW pdfhref
macro allows the user to specify a \(lqtag\(rq,
which is appended to the automatically generated \(lqbookmark\(rq name;
this may be used as a discriminating mark, to distinguish otherwise
similarly named destinations, in different sections of the composite document.
.LP
To create a \(lqtagged\(rq document outline,
the syntax for invocation of the
.CW pdfhref
macro is modified, by the inclusion of an optional \(lqtag\(rq specification,
.EM before
the nesting level argument, i.e.
.QP
.fam C
.B ".pdfhref O"
.B -T \& [
.I tag >] <
.I level > <
.I "descriptive text ..."
.LP
The optional
.CWI tag > <
argument may be composed of any characters of the user's choice;
however, its initial character
.EM "must not"
be any decimal digit, and ideally it should be kept short\*[em]one
or two characters at most.
.LP
By employing a different tag in each section,
the user can ensure that \(lqbookmark\(rq names remain unique,
throughout all the sections of a composite document.
For example, when using the
.CW spdf.tmac
macro package, which adds
.CW pdfmark
capabilities to the standard
.CW ms
package,
.XR using-spdf ), (
the table of contents is collected into a separate \*[PostScript] section
from the main body of the document.
In the \(lqbody\(rq section, the document outline is \(lquntagged\(rq,
but in the \(lqTable\~of\~Contents\(rq section, a modified version of the
.CW TC
macro adds an outline entry for the start of the \(lqTable\~of\~Contents\(rq,
invoking the
.CW pdfhref
macro as
.QP
.CW ".pdfhref O -T T 1 \e\e*[TOC]"
.LP
to tag the associated outline destination name with the single character suffix,
.CW T \(rq. \(lq
Alternatively, as in the case of the basic outline,
.XR basic-outline ), (
this may equally well be specified as
.QP
.CW ".pdfbookmark -T T 1 \e\e*[TOC]"
.
.NH 3
.XN Delegation of the Outline Definition
.LP
Since the most common use of a document outline
is to provide a quick method of navigating through a document,
using active \(lqhypertext\(rq links to chapter and section headings,
it may be convenient to delegate the responsibility of creating the outline
to a higher level macro, which is itself used to
define and format the section headings.
This approach has been adopted in the
.CW spdf.tmac
package, to be described later,
.XR using-spdf ). (
.LP
When such an approach is adopted,
the user will rarely, if ever, invoke the
.CW pdfhref
macro directly, to create a document outline.
For example, the structure and content of the outline for this document
has been exclusively defined, using a combination of the
.CW NH
macro, from the
.CW ms
package, to establish the structure, and the
.CW XN
macro from
.CW spdf.tmac ,
to define the content.
In this case,
the responsibility for invoking the
.CW pdfhref
macro, to create the document outline,
is delegated to the
.CW XN
macro.
.
.NH 2
.XN -N pdfhref -- Adding Reference Marks and Links
.LP
.pdfhref F SECREF
.ds SECREF.BEGIN Section
.pdfhref L -D add-outline
.pdfhref F
has shown how the
.CW pdfhref
macro may be used to create a PDF document outline.
While this is undoubtedly a powerful capability,
it is by no means the only trick in the repertoire of this versatile macro.
.LP
The macro name,
.CW pdfhref ,
which is a contraction of \(lqPDF HyperText Reference\(rq,
indicates that the general purpose of this macro is to define
.EM any
type of dynamic reference mark, within a PDF document.
Its generalized usage syntax takes the form
.QP
.fam C
.B .pdfhref
.BI class > <
.I "-options ...\&" ] [
[--]
.I "descriptive text ...\&" ] [
.LP
where
.CW <\f(CIclass\fP>
represents a required single character argument,
which defines the specific reference operation to be performed,
and may be selected from:\(en
.QS
.sp -\n[PD]u
.IP \*[= O]
Add an entry to the document outline.
This operation has been described earlier,
.XR add-outline ). (
.IP \*[= M]
Place a \(lqnamed destination\(rq reference mark at the current output position,
in the current PDF document,
.XR mark-dest ). (
.IP \*[= D]
Specify the content of a PDF document reference dictionary entry;
typically, such entries are generated automatically,
by transformation of the intermediate output resulting from the use of
.CW pdfhref
.CWB M \& \& \(rq, \(lq
with the
.CWB -X \& \& \(rq \(lq
modifier,
.XR create-map ); (
however, it is also possible to specify such entries manually,
.XR user-format ). (
.IP \*[= L]
Insert an active link to a named destination,
.XR link-named ), (
at the current output position in the current PDF document,
such that when the reader clicks on the link text,
the document view changes to show the location of the named destination.
.IP \*[= W]
Insert an active link to a \(lqweb\(rq resource,
.XR add-weblink ), (
at the current output position in the current PDF document.
This is effectively the same as using the
.CWB L \& \& \(rq \(lq
operator to establish a link to a named destination in another PDF document,
.XR link-extern ), (
except that in this case, the destination is specified by a
\(lquniform resource identifier\(rq, or
.CW URI ;
this may represent any Internet or local resource
which can be specified in this manner.
.IP \*[= F]
Specify a user defined macro, to be called by
.CW pdfhref ,
when formatting the text in the active region of a link,
.XR set-format ). (
.IP \*[= K]
Define one or more location keywords,
and associated \%format\(hystring names,
which should be interpreted by the
.CW pdfhref
reference text formatting routine,
.XR custom-format ). (
.IP \*[= Z]
Define the absolute position on the physical PDF output page,
where the \%\(lqhot\(hyspot\(rq associated with an active link is to be placed.
Invoked in pairs, marking the starting and ending PDF page \%co\(hyordinates
for each link \%\(lqhot\(hyspot\(rq, this operator is rarely, if ever,
specified directly by the user;
rather, appropriate
.CW pdfhref
.CWB Z \& \& \(rq \(lq
specifications are inserted automatically into the document reference map
during the PDF document formatting process,
.XR create-map ). (
.IP \*[= I]
Initialize support for
.CW pdfhref
features.
The current
.CW pdfhref
implementation provides only one such feature which requires
initialization\*[em]a helper macro which must be attached to
a user supplied page trap handler,
in order to support mapping of reference \%\(lqhot\(hyspots\(rq
which extend through a page transition;
.XR page-trap ). (
.QE
.
.NH 3
.XN -S -- Optional Features of the \F[C]pdfhref\F[] Macro
.LP
The behaviour of a number of the
.CW pdfhref
macro operations can be modified,
by including
.EM "option specifiers" \(rq \(lq
after the operation specifying argument,
but
.EM before
any other arguments normally associated with the operation.
In
.EM all
cases, an option is specified by an
.EM "option flag" \(rq, \(lq
comprising an initial hyphen,
followed by one or two option identifying characters.
Additionally,
.EM some
options require
.EM "exactly one"
option argument;
for these options, the argument
.EM must
be specified, and it
.EM must
be separated from the preceding option flag by one or more
.EM spaces ,
(tabs
.EM "must not"
be used).
It may be noted that this paradigm for specifying options
is reminiscent of most
Unix\(tm
shells; however, in the case of the
.CW pdfhref
macro, omission of the space separating an option flag from its argument is
.EM never
permitted.
.LP
A list of
.EM all
general purpose options supported by the
.CW pdfhref
macro is given below.
Note that not all options are supported for all
.CW pdfhref
operations; the operations affected by each option are noted in the list.
For
.EM most
operations, if an unsupported option is specified,
it will be silently ignored; however, this behaviour should
not be relied upon.
.LP
The general purpose options, supported by the
.CW pdfhref
macro, are:\(en
.QS
.sp -\n[PD]u
.IP \*[= -N\0 name > <] 4n
Allows the
.CWI name > <
associated with a PDF reference destination
to be defined independently from the following text,
which describes the reference.
This option affects only the
.CWB M \& \& \(rq \(lq
operation of the
.CW pdfhref
macro,
.XR mark-dest ). (
.IP \*[= -E]
Also used exclusively with the
.CWB M \& \& \(rq \(lq
operator, the
.CWB -E
option causes any specified
.CWI descriptive \& \& \~\c
.CWI text
arguments,
.XR mark-dest ), (
to be copied, or
.EM echoed ,
in the body text of the document,
at the point where the reference mark is defined;
(without the
.CWB -E
option, such
.CWI descriptive \& \& \~\c
.CWI text
will appear
.EM only
at points where links to the reference mark are placed,
and where the standard reference display format,
.XR set-format ), (
is used).
.IP \*[= -D\0 dest > <]
Specifies the
.CW URI ,
or the destination name associated with a PDF active link,
independently of the following text,
which describes the link and demarcates the link \%\(lqhot\(hyspot\(rq.
This option affects the behaviour of the
.CW pdfhref
macro's
.CWB L \& \& \(rq \(lq
and
.CWB W \& \& \(rq \(lq
operations.
.IP
When used with the
.CWB L \& \& \(rq \(lq
operator, the
.CWI dest > <
argument must specify a PDF \(lqnamed destination\(rq,
as defined using
.CW pdfhref
with the
.CWB M \& \& \(rq \(lq
operator.
.IP
When used with the
.CWB W \& \& \(rq \(lq
operator,
.CWI dest > <
must specify a link destination in the form of a
\(lquniform resource identifier\(rq, or
.CW URI ,
.XR add-weblink ). (
.IP \*[= -F\0 file > <]
When used with the
.CWB L \& \& \(rq \(lq
.CW pdfhref
operator,
.CWI file > <
specifies an external PDF file in which the named destination
for the link reference is defined.
This option
.EM must
be specified with the
.CWB L \& \& \(rq \(lq
operator,
to create a link to a destination in a different PDF document;
when the
.CWB L \& \& \(rq \(lq
operator is used
.EM without
this option, the link destination is assumed to be defined
within the same document.
.
.IP \*[= -P\0 \(dqprefix\(hytext\(dq > <]
.ne 4v
Specifies
.CWI \(dqprefix\(hytext\(dq > \%<
to be attached to the
.EM start
of the text describing an active PDF document link,
with no intervening space, but without itself being included in the
active area of the link \%\(lqhot\(hyspot\(rq;
it is effective with the
.CWB L \& \& \(rq \(lq
and
.CWB W \& \& \(rq \(lq
.CW pdfhref
operators.
.
.IP
.ne 3v
Typically, this option would be used to insert punctuation before
the link \%\(lqhot\(hyspot\(rq.
Thus, there is little reason for the inclusion of spaces in
.CWI \(dqprefix\(hytext\(dq > \%< ;
however, if such space is required, then the enclosing double quotes
.EM must
be specified, as indicated.
.
.IP \*[= -A\0 \(dqaffixed\(hytext\(dq > <]
Specifies
.CWI \(dqaffixed\(hytext\(dq > \%<
to be attached to the
.EM end
of the text describing an active PDF document link,
with no intervening space,
.ne 2v
but without itself being included in the
active area of the link \%\(lqhot\(hyspot\(rq;
it is effective with the
.CWB L \& \& \(rq \(lq
and
.CWB W \& \& \(rq \(lq
.CW pdfhref
operators.
.
.IP
.ne 3v
Typically, this option would be used to insert punctuation after
the link \%\(lqhot\(hyspot\(rq.
Thus, there is little reason for the inclusion of spaces in
.CWI \(dqaffixed\(hytext\(dq > \%< ;
however, if such space is required, then the enclosing double quotes
.EM must
be specified, as indicated.
.
.IP \*[= -T\0 tag > <]
When specified with the
.CWB O \& \& \(rq \(lq
operator,
.CWI tag > <
is appended to the \(lqbookmark\(rq name assigned to the generated outline entry.
This option is
.EM required ,
to distinguish between the series of \(lqbookmark\(rq names generated in
individual passes of the
.CW groff
formatter, when the final PDF document is to be assembled
from a number of separately formatted components;
.XR multipart-outline ). (
.IP \*[= -X]
This
.CW pdfhref
option is used with either the
.CWB M \& \& \(rq \(lq
operator, or with the
.CWB L \& \& \(rq \(lq
operator.
.IP
When used with the
.CWB M \& \& \(rq \(lq
operator,
.XR mark-dest ), (
it ensures that a cross reference record for the marked destination
will be included in the document reference map,
.XR export-map ). (
.IP
When used with the
.CWB L \& \& \(rq \(lq
operator,
.XR link-named ), (
it causes the reference to be displayed in the standard cross reference format,
.XR set-format ), (
but substituting the
.CWI descriptive \& \& \~\c
.CWI text
specified in the
.CW pdfhref \& \(lq
.CW L \(rq
argument list,
for the description specified in the document reference map.
.IP \*[= --]
Marks the end of the option specifiers.
This may be used with all
.CW pdfhref
operations which accept options, to prevent
.CW pdfhref
from interpreting any following arguments as option specifiers,
even if they would otherwise be interpreted as such.
It is also useful when the argument list to
.CW pdfhref
contains special characters\*[em]any special character,
which is not valid in a
.CW groff
macro name, will cause a parsing error, if
.CW pdfhref
attempts to match it as a possible option flag;
using the
.CW -- \(rq \(lq
flag prevents this, so suppressing the
.CW groff
warning message, which would otherwise ensue.
.IP
Using this flag after
.EM all
sequences of macro options is recommended,
even when it is not strictly necessary,
if only for the entirely cosmetic benefit of visually separating
the main argument list from the sequence of preceding options.
.QE
.sp -\n[PD]u
.LP
In addition to the
.CW pdfhref
options listed above, a supplementary set of two character options are defined.
These supplementary options, listed below, are intended for use with the
.CWB L \& \& \(rq \(lq
operator, in conjunction with the
.CWB -F \& \& \~\c
.CWBI file > <
option, to specify alternate file names,
in formats compatible with the file naming conventions
of alternate operating systems;
they will be silently ignored, if used in any other context.
.LP
The supported alternate file name options,
which are ignored if the
.CWB -F \& \& \~\c
.CWBI file > <
option is not specified, are:\(en
.QS
.sp -\n[PD]u
.IP \*[= -DF\0 dos\(hyfile > <] 5n
Specifies the name of the file in which a link destination is defined,
using the file naming semantics of the
.CW \%MS\(hyDOS \*(rg
operating system.
When the PDF document is read on a machine
where the operating system uses the
.CW \%MS\(hyDOS \*(rg
file system, then
.CWI dos\(hyfile > \%<
is used as the name of the file containing the reference destination,
overriding the
.CWI file > <
argument specified with the
.CWB -F
option.
.IP \*[= -MF\0 mac\(hyfile > <]
Specifies the name of the file in which a link destination is defined,
using the file naming semantics of the
.CW Apple \*(rg
.CW Macintosh \*(rg
operating system.
When the PDF document is read on a machine
where the operating system uses the
.CW Macintosh \*(rg
file system, then
.CWI mac\(hyfile > \%<
is used as the name of the file containing the reference destination,
overriding the
.CWI file > <
argument specified with the
.CWB -F
option.
.IP \*[= -UF\0 unix\(hyfile > <]
Specifies the name of the file in which a link destination is defined,
using the file naming semantics of the
.CW Unix \(tm
operating system.
When the PDF document is read on a machine
where the operating system uses
.CW POSIX
file naming semantics, then
.CWI unix\(hyfile > \%<
is used as the name of the file containing the reference destination,
overriding the
.CWI file > <
argument specified with the
.CWB -F
option.
.IP \*[= -WF\0 win\(hyfile > <]
Specifies the name of the file in which a link destination is defined,
using the file naming semantics of the
.CW \%MS\(hyWindows \*(rg
\%32\(hybit operating system.
When the PDF document is read on a machine
where the operating system uses any of the
.CW \%MS\(hyWindows \*(rg
file systems, with long file name support, then
.CWI win\(hyfile > \%<
is used as the name of the file containing the reference destination,
overriding the
.CWI file > <
argument specified with the
.CWB -F
option.
.QE
.
.NH 3
.XN -N mark-dest -- Marking a Reference Destination
.LP
The
.CW pdfhref
macro may be used to create active links to any Internet resource,
specified by its
.CW URI ,
or to any \(lqnamed destination\(rq,
either within the same document, or in another PDF document.
Although the PDF specification allows link destinations to be defined
in terms of a page number, and an associated view specification,
this style of reference is not currently supported by the
.CW pdfhref
macro, because it is not possible to adequately bind the specification
for the destination with the intended reference context.
.LP
References to Internet resources are interpreted in accordance with the
.CW W3C
standard for defining a
.CW URI ;
hence the only prerequisite, for creating a link to any Internet resource,
is that the
.CW URI
be properly specified, when declaring the reference;
.XR add-weblink ). (
In the case of references to \(lqnamed destinations\(rq in PDF documents,
however, it is necessary to provide a mechanism for creating such
\(lqnamed destinations\(rq.
This may be accomplished, by invoking the
.CW pdfhref
macro in the form
.QP
.fam C
.B ".pdfhref M"
.B -N \& [
.I name >] <
.B -X ] [
.B -E ] [
.I "descriptive text ...\&" ] [
.LP
This creates a \(lqnamed destination\(rq reference mark, with its name specified by
.CWI name > < ,
or, if the
.CWB -N
option is not specified, by the first word of
.CWI descriptive \& \& \~\c
.CWI text \& \& ;
(note that this imposes the restriction that,
if the
.CWB -N
option is omitted, then
.EM "at least"
one word of
.CWI descriptive \& \& \~\c
.CWI text
.EM must
be specified).
Additionally, a reference view will be automatically defined,
and associated with the reference mark,
.XR pdfhref-view ), (
.\" and, if any
.\" .CWI descriptive
.\" .CWI text
.\" is specified, or the
and, if the
.CWB -X
option is specified, and no document cross reference map has been imported,
.XR import-map ), (
then a cross reference mapping record,
.XR export-map ), (
will be written to the
.CW stdout
stream;
this may be captured, and subsequently used to generate a cross reference map
for the document,
.XR create-map ). (
.LP
When a \(lqnamed destination\(rq reference mark is created, using the
.CW pdfhref
macro's
.CWB M \& \& \(rq \(lq
operator, there is normally no visible effect in the formatted document; any
.CWI descriptive \& \& \~\c
.CWI text
which is specified will simply be stored in the cross reference map,
for use when a link to the reference mark is created.
This default behaviour may be changed, by specifying the
.CWB -E
option, which causes any specified
.CWI descriptive \& \& \~\c
.CWI text
to be \(lqechoed\(rq in the document text,
at the point where the reference mark is placed,
in addition to its inclusion in the cross reference map.
.
.NH 4
.XN -N export-map -- Mapping a Destination for Cross Referencing
.LP
Effective cross referencing of
.EM any
document formatted by
.CW groff
requires multiple pass formatting.
Details of how this multiple pass formatting may be accomplished,
when working with the
.CW pdfmark
macros, will be discussed later,
.XR do-xref ); (
at this stage, the discussion will be restricted to the initial preparation,
which is required at the time when the cross reference destinations are defined.
.LP
The first stage, in the process of cross referencing a document,
is the generation of a cross reference map.
Again, the details of
.EM how
the cross reference map is generated will be discussed in
.pdfhref F SECREF L -D do-xref -A ;
.pdfhref F
however, it is important to recognize that
.EM what
content is included in the cross reference map is established
when the reference destination is defined\*[em]it is derived
from the reference data exported on the
.CW stderr
stream by the
.CW pdfhref
macro, when it is invoked with the
.CWB M \& \& \(rq \(lq
operator, and is controlled by whatever definition of the string
.CW PDFHREF.INFO
is in effect, when the
.CW pdfhref
macro is invoked.
.LP
The initial default setting of
.CW PDFHREF.INFO
is
.QP
.CW ".ds PDFHREF.INFO page \e\en% \e\e$*"
.LP
which ensures that the cross reference map will contain
at least a page number reference, supplemented by any
.CWI descriptive \& \& \~\c
.CWI text
which is specified for the reference mark, as defined by the
.CW pdfhref
macro, with its
.CWB M \& \& \(rq \(lq
operator; this may be redefined by the user,
to export additional cross reference information,
or to modify the default format for cross reference links,
.XR set-format ). (
.
.NH 4
.ne 4v+\n[PD]u
.XN -N pdfhref-view -- Associating a Document View with a Reference Mark
.LP
In the same manner as each document outline reference, defined by the
.CW pdfhref
macro with the
.CWB O \& \& \(rq \(lq
operator,
.XR add-outline ), (
has a specific document view associated with it,
each reference destination marked by
.CW pdfhref
with the
.CWB M \& \& \(rq \(lq
operator, requires an associated document view specification.
.LP
The mechanism whereby a document view is associated with a reference mark
is entirely analogous to that employed for outline references,
.XR outline-view ), (
except that the
.CW PDFHREF.VIEW
string specification is used, in place of the
.CW PDFBOOKMARK.VIEW
specification.
.ne 2v
Thus, the reference view is defined in terms of:\(en
.QS
.sp -\n[PD]u
.IP \*[= PDFHREF.VIEW]
A string,
establishing the position of the reference mark within the viewing window,
and the magnification at which the document will be viewed,
at the location of the marked reference destination;
by default, it is defined by
.RS
.QP
.CW ".ds PDFHREF.VIEW /FitH \e\en[PDFPAGE.Y] u"
.RE
.IP
which displays the reference destination at the top of the viewing window,
with the magnification set to fit the page width to the width of the window.
.IP \*[= PDFHREF.VIEW.LEADING]
A numeric register,
specifying additional spacing, to be placed between the top of the display
window and the actual position at which the location of the reference
destination appears within the window.
This register is shared with the view specification for outline references,
and thus has the same default initial setting,
.RS
.QP
.CW ".nr PDFHREF.VIEW.LEADING 5.0p"
.RE
.IP
as in the case of outline reference views.
.IP
Again, notice that
.CW PDFHREF.VIEW.LEADING
does not represent true typographic \(lqleading\(rq,
since any preceding text, set in the specified display space,
will be visible at the top of the viewing window,
when the reference is selected.
.QE
Just as the view associated with outline references may be changed,
by redefining
.CW PDFBOOKMARK.VIEW ,
so the view associated with marked reference destinations may be changed,
by redefining
.CW PDFHREF.VIEW ,
and, if desired,
.CW PDFHREF.VIEW.LEADING ;
such changes will become effective for all reference destinations marked
.EM after
these definitions are changed.
(Notice that, since the specification of
.CW PDFHREF.VIEW.LEADING
is shared by both outline reference views and marked reference views,
if it is changed, then the views for
.EM both
reference types are changed accordingly).
.LP
It may again be noted, that the
.CW PDFPAGE.Y
register is used in the definition of
.CW PDFHREF.VIEW ,
just as it is in the definition of
.CW PDFBOOKMARK.VIEW ;
all comments in
.pdfhref F SECREF L -D outline-view
.pdfhref F
relating to its use, and indeed to page position computations in general,
apply equally to marked reference views and to outline reference views.
.
.NH 3
.XN -N link-named -- Linking to a Marked Reference Destination
.LP
Any named destination, such as those marked by the
.CW pdfhref
macro, using it's
.CWB M \& \& \(rq \(lq
operator, may be referred to from any point in
.EM any
PDF document, using an
.EM "active link" ;
such active links are created by again using the
.CW pdfhref
macro, but in this case, with the
.CWB L \& \& \(rq \(lq
operator.
This operator provides support for two distinct cases,
depending on whether the reference destination is defined in
the same document as the link,
.XR link-intern ), (
or is defined as a named destination in a different PDF document,
.XR link-extern ). (
.
.NH 4
.XN -N link-intern -- References within a Single PDF Document
.LP
The general syntactic form for invoking the
.CW pdfhref
macro,
when creating a link to a named destination within the same PDF document is
.QP
.fam C
.B .pdfhref
.B L
.B -D \& [
.BI dest-name >] <
.B -P \& [
.BI prefix-text >] <
.B -A \& [
.BI affixed-text >] <
\e
.br
\0\0\0
.B -X ] [
.B -- ] [
.I "descriptive text ...\&" ] [
.LP
where
.CWI dest-name > <
specifies the name of the link destination,
as specified using the
.CW pdfhref
.CWB M \& \& \(rq \(lq
operation; (it may be defined either earlier in the document,
to create a backward reference, or later, to create a forward reference).
.\"
.\" Here's a example of how to add an iconic annotation.
.\"
.\".pdfnote -T "Internal Cross References" \
.\"   This description is rather terse, and could benefit from \
.\"   the inclusion of an example.
.LP
If any
.CWI descriptive \& \& \~\c
.CWI text
arguments are specified, then they will be inserted into the
.CW groff
output stream, to define the text appearing in the \%\(lqhot\(hyspot\(rq
region of the link;
this will be printed in the link colour specified by the string,
.CW PDFHREF.TEXT.COLOUR ,
which is described in
.XR-NO-PREFIX set-colour .
If the
.CWB -X
option is also specified, then the
.CWI descriptive \& \& \~\c
.CWI text
will be augmented, by prefacing it with page and section number indicators,
in accordance with the reference formatting rules which are in effect,
.XR set-format ); (
such indicators will be included within the active link region,
and will also be printed in the link colour.
.LP
Note that
.EM either
the
.CWB -D \& \& \~\c
.CWBI dest\(hyname > \%<
option,
.EM or
the
.CWI descriptive \& \& \~\c
.CWI text
arguments,
.EM "but not both" ,
may be omitted.
If the
.CWB -D \& \& \~\c
.CWBI dest\(hyname > \%<
option is omitted, then the first word of
.CWI descriptive \& \& \~\c
.CWI text \& \& ,
i.e.\~all text up to but not including the first space,
will be interpreted as the
.CWBI dest\(hyname > \%<
for the link; this text will also appear in the running text of the document,
within the active region of the link.
Alternatively, if the
.CWB -D \& \& \~\c
.CWBI dest\(hyname > \%<
option
.EM is
specified, and
.CWI descriptive \& \& \~\c
.CWI text
is not,
then the running text which defines the reference,
and its active region,
will be derived from the reference description which is specified
when the named destination is marked,
.XR mark-dest ), (
and will be formatted according to the reference formatting rules
which are in effect, when the reference is placed,
.XR set-format ); (
in this case, it is not necessary to specify the
.CWB -X
option to activate automatic formatting of the reference\*[em]it is implied,
by the omission of all
.CWI descriptive \& \& \~\c
.CWI text
arguments.
.LP
The
.CWB -P \& \& \~\c
.CWBI prefix\(hytext > \%<
and
.CWB -A \& \& \~\c
.CWBI affixed\(hytext > \%<
options may be used to specify additional text
which will be placed before and after the linked text respectively,
with no intervening space.
Such prefixed and affixed text will be printed in the normal text colour,
and will not be included within the active region of the link.
This feature is mostly useful for creating parenthetical references,
or for placing punctuation adjacent to,
but not included within,
the text which defines the active region of the link.
.LP
The operation of the
.CW pdfhref
macro, when used with its
.CWB L \& \& \(rq \(lq
operator to place a link to a named PDF destination,
may best be illustrated by an example.
However, since the appearance of the link will be influenced by
factors established when the named destination is marked,
.XR mark-dest ), (
and also by the formatting rules in effect when the link is placed,
the presentation of a suitable example will be deferred,
until the formatting mechanism has been explained,
.XR set-format ). (
.
.NH 4
.XN -N link-extern -- References to Destinations in Other PDF Documents
.LP
The
.CW pdfhref
macro's
.CWB L \& \& \(rq \(lq
operator is not restricted to creating reference links
within a single PDF document.
When the link destination is defined in a different document,
then the syntactic form for invoking
.CW pdfhref
is modified, by the addition of options to specify the
name and location of the PDF file in which the destination is defined.
Thus, the extended
.CW pdfhref
syntactic form becomes
.QP
.fam C
.B .pdfhref
.B L
.B -F
.BI file > <
.B -D \& [
.BI dest-name >] <
\e
.br
\0\0\0
.B -DF \& [
.BI dos-file >] <
.B -MF \& [
.BI mac-file >] <
.B -UF \& [
.BI unix-file >] <
\e
.br
\0\0\0
.B -WF \& [
.BI win-file >] <
.B -P \& [
.BI prefix-text >] <
.B -A \& [
.BI affixed-text >] <
\e
.br
\0\0\0
.B -X ] [
.B -- ] [
.I "descriptive text ...\&" ] [
.LP
where the
.CWB -F \& \& \~\c
.CWBI file > <
option serves
.EM two
purposes: it both indicates to the
.CW pdfhref
macro that the specified reference destination
is defined in an external PDF file,
and it also specifies the normal path name,
which is to be used to locate this file,
when a user selects the reference.
.LP
In addition to the
.CWB -F \& \& \~\c
.CWBI file > <
option, which
.EM must
be specified when referring to a destination in an external PDF file,
the
.CWB -DF \& \& \~\c
.CWBI dos\(hyfile > \%< ,
.CWB -MF \& \& \~\c
.CWBI mac\(hyfile > \%< ,
.CWB -UF \& \& \~\c
.CWBI unix\(hyfile > \%<
and
.CWB -WF \& \& \~\c
.CWBI win\(hyfile > \%<
options may be used to specify the location of the file
containing the reference destination,
in a variety of operating system dependent formats.
These options assign their arguments to the
.CW /DosFile ,
.CW /MacFile ,
.CW /UnixFile
and
.CW /WinFile
keys of the generated
.CW pdfmark
respectively; thus when any of these options are specified,
.EM "in addition to"
the
.CWB -F \& \& \~\c
.CWBI file > <
option, and the document is read on the appropriate operating systems,
then the path names specified by
.CWBI dos\(hyfile > \%< ,
.CWBI mac\(hyfile > \%< ,
.CWBI unix\(hyfile > \%<
and
.CWBI win\(hyfile > \%<
will be searched,
.EM instead
of the path name specified by
.CWBI file > < ,
for each of the
.CW \%MS\(hyDOS \*(rg,
.CW Apple \*(rg
.CW Macintosh \*(rg,
.CW Unix \(tm
and
.CW \%MS\(hyWindows \*(rg
operating systems, respectively; see the
.pdfmark-manual ,
for further details.
.LP
Other than the use of these additional options,
which specify that the reference destination is in an external PDF file,
the behaviour of the
.CW pdfhref
.CWB L \& \& \(rq \(lq
operator, with the
.CWB -F \& \& \~\c
.CWBI file > <
option, remains identical to its behaviour
.EM without
this option,
.XR link-intern ), (
with respect to the interpretation of other options,
the handling of the
.CWI descriptive \& \& \~\c
.CWI text
arguments, and the formatting of the displayed reference.
.LP
Once again, since the appearance of the reference is determined by
factors specified in the document reference map,
and also by the formatting rules in effect when the reference is placed,
the presentation of an example of the placing of
a reference to an external destination will be deferred,
until the formatting mechanism has been explained,
.XR set-format ). (
.
.NH 3
.XN -N add-weblink -- Linking to Internet Resources
.LP
In addition to supporting the creation of cross references
to named destinations in PDF documents, the
.CW pdfhref
macro also has the capability to create active links to Internet resources,
or indeed to
.EM any
resource which may be specified by a Uniform Resource Identifier,
(which is usually abbreviated to the acronym \(lqURI\(rq,
and sometimes also referred to as a Uniform Resource Locator,
or \(lqURL\(rq).
.LP
.ne 7v+(u;2*\n[PD])
Since the mechanism for creating a link to a URI differs somewhat
from that for creating PDF references, the
.CW pdfhref
macro is invoked with the
.CWB W \& \& \(rq \(lq
(for \%\(lqweb\(hylink\(rq) operator, rather than the
.CWB L \& \& \(rq \(lq
operator; nevertheless, the invocation syntax is similar, having the form
.QP
.fam C
.B .pdfhref
.B W
.B -D \& [
.BI URI >] <
.B -P \& [
.BI prefix-text >] <
.B -A \& [
.BI affixed-text >] <
\e
.br
\0\0\0
.B -- ] [
.I "descriptive text ...\&"
.LP
where the optional
.CWB -D
.CWBI URI > <
modifier specifies the address for the target Internet resource,
in any appropriate
.EM "Uniform Resource Identifier"
format, while the
.CWI descriptive
.CWI text
argument specifies the text which is to appear in the \%\(lqhot\(hyspot\(rq
region, and the
.CWB -P
.CWBI prefix\(hytext > \%<
and
.CWB -A
.CWBI affixed\(hytext > \%<
options have the same effect as in the case of local document links,
.XR link-intern ). (
.LP
Notice that it is not mandatory to include the
.CWB -D
.CWBI URI > <
in the link specification; if it
.EM is
specified, then it is not necessary for the URI to appear,
in the running text of the document\*[em]the
.CWI descriptive
.CWI text
argument exactly defines the text
which will appear within the \%\(lqhot\(hyspot\(rq region,
and this need not include the URI.
However, if the
.CWB -D \& \& \~\c
.CWBI URI > <
specification is omitted, then the
.CWI descriptive
.CWI text
argument
.EM must
be an
.EM exact
representation of the URI, which
.EM will ,
therefore, appear as the entire content of the \%\(lqhot\(hyspot\(rq.
For example, we could introduce a reference to
.pdfhref W -D \*[GROFF-WEBSITE] -A , the groff web site
in which the actual URI is concealed, by using mark up such as:\(en
.DS I
.fam C
For example, we could introduce a reference to
\&.pdfhref W -D \*[GROFF-WEBSITE] -A , the groff web site
in which the actual URI is concealed,
.DE
Alternatively,
to refer the reader to the groff web site,
making it obvious that the appropriate URI is
.pdfhref W -A , \*[GROFF-WEBSITE]
the requisite mark up might be:\(en
.DS I
.fam C
to refer the reader to the groff web site,
making it obvious that the appropriate URI is
\&.pdfhref W -A , \*[GROFF-WEBSITE]
the requisite mark up might be:\e(en
.DE
.
.NH 3
.XN -N set-format -- Establishing a Format for References
.LP
There are two principal aspects to be addressed,
when defining the format to be used when displaying references.
Firstly, it is desirable to provide a visual cue,
to indicate that the text describing the reference is imbued
with special properties\*[em]it is dynamically linked to the reference
destination\*[em]and secondly, the textual content should
describe where the link leads, and ideally,
it should also describe the content of the reference destination.
.LP
The visual cue,
that a text region defines a dynamically linked reference,
is most commonly provided by printing the text within the active
region in a distinctive colour.
This technique will be employed automatically by the
.CW pdfhref
.XR set-colour \*[em]unless macro\*[em]
the user specifically chooses to adopt, and implement,
some alternative strategy.
.
.NH 4
.\" The following section will serve as a convenient example for
.\" the default reference text formatting capabilities of pdfhref;
.\" thus, mark it, and store PDFHREF.INFO records in both original
.\" default format, and our preferred section reference format.
.\"
.nr chapter 2
.ds PDFHREF.INFO.KLUDGE section \\n[chapter] \\*[PDFHREF.INFO.DEFAULT]
.ds PDFHREF.INFO.CHAPTER chapter \\n[chapter] page \\n% \\*[PDFHREF.INFO.LOCAL]
.ds set-colour-heading Using Colour to Demarcate Link Regions
.
.als PDFHREF.INFO PDFHREF.INFO.CHAPTER
.pdfhref M -X -N set-colour-chapter -- \*[set-colour-heading]
.
.als PDFHREF.INFO PDFHREF.INFO.KLUDGE
.pdfhref M -X -N set-colour-chapter-kludge -- \*[set-colour-heading]
.
.als PDFHREF.INFO PDFHREF.INFO.DEFAULT
.pdfhref M -X -N set-colour-default -- \*[set-colour-heading]
.
.als PDFHREF.INFO PDFHREF.INFO.LOCAL
.XN -N set-colour -- \*[set-colour-heading]
.rm set-colour-heading
.
.LP
Typically, when a PDF document contains
.EM active
references to other locations, either within the same document,
or even in other documents, or on the World Wide Web,
it is usually desirable to make the regions
where these active links are placed stand out from the surrounding text.
.LP
The mechanism,
which is apparently advocated by \*[Adobe ,]
as the default for indicating any active link region,
is to draw a coloured border around the region.
This is a most unfortunate default choice:
not only does it look hideously ugly,
but it also seems very distracting to the reader!
Consequently,
while it does support this mechanism for link visualization,
.CW groff 's
.CW pdfmark
macros disable it,
by default;
it is controlled by a pair of strings:\(en
.QS
.sp -\n[PD]u
.IP \*[= PDFHREF.BORDER]
This string comprises a \%space\(hyseparated triplet of numeric values,
optionally followed by a further \%space\(hyseparated
.CW pdfmark "\ \c"
.CW array ,
(see the \*[Adobe]
.pdfmark-manual
for details),
which together specify the link border style,
in terms of its elliptical corner horizontal radius,
vertical radius,
line thickness,
and line style \%mark\(hyto\(hyspace ratio array;
.ne 2v+\n[PD]u
by default,
it is defined as
.RS
.QP
.CW ".ds PDFHREF.BORDER 0 0 0"
.RE
.IP
which has the effect of specifying an invisible link border,
(a solid \%zero\(hywidth line,
with rectanuglar corners),
thus appearing to disable the use of borders
for link visualization.
This differs from the \*[Adobe] default,
which represents a solid (visible) line,
one pixel in width,
and with rectangular corners;
.ne 4v+(u;2*\n[PD])
this \*[Adobe] default may be reinstated,
by explicitly defining
.RS
.QP
.CW ".ds PDFHREF.BORDER 0 0 1"
.RE
.IP
.EM before
specifying any link references,
which it is desired to have rendered in the \*[Adobe] style.
.
.IP \*[= PDFHREF.COLOUR]
This string\**
.FS
For authors who may prefer American English spelling,
.CW PDFHREF.COLOR
will be recognized as an alias for
.CW PDFHREF.COLOUR .
However,
should the alias be broken,
(by deletion of either of the alternative names,
prior to redefining it),
it is the World English spelling,
.CW PDFHREF.COLOUR ,
which will be honoured when rendering links.
.FE
comprises a triplet of \%space\(hyseparated decimal numeric values,
each in the range 0.0\^..\^1.0;
together,
they represent,
in RGB colour space,
the colour in which link borders should be rendered,
in the event that the
.CW PDFHREF.BORDER
property is specified to make them visible;
by default,
it is defined as
.RS
.QP
.CW ".ds PDFHREF.COLOUR 0.35 0.00 0.60"
.RE
.IP
which represents a deep lilac colour.
.QE
.LP
While the foregoing discussion of
.CW PDFHREF.BORDER ,
and
.CW PDFHREF.COLOUR ,
may seem sufficient for those users who are willing
to adopt the \*[Adobe] convention of drawing a border
to offset links from the surrounding text,
it is
.EM not
the preferred way of doing so,
in
.CW groff 's
.CW pdfmark
implementation.
Given the perceived ugliness of the \*[Adobe] convention,
the preferred technique for visualizing links is to disable
the rendition of the link border,
(by making it invisible,
as
.CW groff 's
.CW pdfmark
implementation does by default),
and to simply print the text,
within the link \%\(lqhot\(hyspot\(rq region,
in a colour which contrasts with that of the surrounding text.
.LP
It may noted that,
whereas the preceding
.CW PDFHREF.BORDER ,
and
.CW PDFHREF.COLOUR
properties exert their influence within the \*[Adobe]
.CW pdfmark
infrastructure,
that infrastructure provides no mechanism for control of
the text colour within a link \%\(lqhot\(hyspot\(rq region;
however,
the desired effect may be readily achieved,
simply by assignment of
.CW groff
colour properties.
In
.CW groff 's
.CW pdfmark
implementation,
the text colour,
for use within link \%\(lqhot\(hyspot\(rq regions,
is established by a further string assignment,
viz.:\(en
.QS
.sp -\n[PD]u
.IP \*[= PDFHREF.TEXT.COLOUR]
Specifies the text colour,
for rendition of PDF reference links.
.IP
Unlike
.CW PDFHREF.COLOUR ,
this string\**
.FS
Just as
.CW PDFHREF.COLOR
is defined as an alias for
.CW PDFHREF.COLOUR ,
the alias
.CW PDFHREF.TEXT.COLOR
may be used as an American English spelling alternative
to World English
.CW PDFHREF.TEXT.COLOUR ;
once again,
should the alias be broken,
the World English spelling will prevail.
.FE
must be assigned a value which represents a
.CW groff
colour name,
rather than an RGB \%colour\(hyspace triplet;
by default,
it is assigned the name of a custom colour,
which is internally derived from,
and is thus chromatically identical to the deep lilac colour\Z','\|\**
.FS
This deep lilac colour has been chosen
on the basis that it will provide sufficient contrast,
when the PDF document is viewed on a colour display screen,
to be discernable by readers with normal colour perception,
but not so much contrast as to be distracting;
conversely,
if the document is printed on a monochrome \%hard\(hycopy device,
since links cannot then be clicked,
it is anticipated that the contrast will be barely discernable,
if at all.
.FE
as represented by the default RGB \%colour\(hyspace triplet
which is specified as the default value of
.CW PDFHREF.COLOUR .
.QE
.
.NH 4
.XN -N user-format -- Specifying Reference Text Explicitly
.LP
Although the
.pdfhref L -D set-colour -- use of colour
within,
and/or borders around,
.CW pdfhref
link \%\(lqhot\(hyspot\(rq regions may be considered
to be a necessary visual indication of the location
of such \%\(lqhot\(hyspots\(rq,
for users of \%on\(hyscreen\(rq PDF readers,
such visual indicators alone are insufficient
to convey any necessary information regarding the context
to which the link refers;
neither do they offer any particular benefit
to readers of documents in printed \%hard\(hycopy formats.
To address these limitations,
it is necessary to specify appropriate text
within each \%\(lqhot\(hyspot\(rq region,
to identify the link context.
.LP
Depending on the type of contextual information,
which it is desired to include
within any link \%\(lqhot\(hyspot\(rq region,
.CW groff 's
.CW pdfmark
macro suite provides a variety of mechanisms
to specify it;
the simplest of these
is to simply specify the desired text
.EM explicitly ,
at the point of insertion of the reference.
For example,
given that the
.pdfhref L -D set-colour -P \(lq -A \(rq -- use of colour
reference,
in the initial paragraph of
.ne 4v+(u;3*\n[PD])
.pdfhref L -D user-format -A , -- this section
points to a destination named by mark up similar to:\(en
.QP
.CW ".pfdhref M -X -N \%set-colour -- ..."
.LP
the reference text was specified explicitly,
(ignoring recorded location information),
using the mark up:\(en
.QP
.CW ".pdfhref L -D set-colour -- use of colour"
.
.NH 4
.ne 3v+(u;2*\n[PD])
.XN -N auto-format -- Using Automatically Formatted Reference Text
.LP
When the text within a link \%\(lqhot\(hyspot\(rq is specified explicitly,
using a
.CW pdfhref
macro call of the form
.QP
.fam C
\&.pdfhref L -D
.CWI dest-name > <
--
.CWI explicit-text > <
.fam
.ne 2v+\n[PD]u
.LP
as described in
.pdfhref L -D user-format -A , -- the preceding section
then
.CWI explicit-text > <
will appear in the formatted document,
.EM exactly
as specified.
This may be the author's intent,
but it does suffer from the disadvantage that,
in spite of location information having been recorded when
.CWI dest-name > <
was marked,
none is included in
.CWI explicit-text > < ,
.EM unless
the author
.EM explicitly
includes it;
this places the onus on the author,
if inclusion of such location information is desired,
to track it
.EM manually ,
and to specify it within
.CWI explicit-text > < ,
in the desired format.
.LP
To mitigate this limitation,
of
.EM explicitly
specified reference text,
.CW groff 's
.CW pdfmark
macro suite provides a capability for
.EM automatic
formatting of reference text,
based on the content of a
.CW PDFHREF.INFO \& \(lq
record\(rq\Z','\|\**
.FS
The conceptual nomenclature
.CW PDFHREF.INFO \& \(lq
record\(rq has been adopted here,
since the content of the record is dictated by the definition of the
.CW PDFHREF.INFO
string,
as described in
.XR-NO-PREFIX export-map .
.FE
which is generated by,
and is specific to any named \%link\(hydestination marked by a
.CW pdfhref
macro request of the form
.QP
.fam C
\&.pdfhref M -X -N
.CWI dest-name > <
[[--]
.CWI default-text >] <
.fam
.LP
When a
.CW pdfhref
link destination has been marked by a macro request of this form\Z','\|\**
.FS
The specification of the
.CWB -X
option is imperative,
within this
.CW pdfhref
macro request;
without it,
no
.CW PDFHREF.INFO \& \(lq
record\(rq will be generated.
.FE
a subsequent request of the simplified form
.QP
.fam C
\&.pdfhref L -D
.CWI dest-name > <
.fam
.LP
(excluding
.EM any
.CWI explicit-text > <
specification),
then the reference text will be generated
.EM automatically ,
by passing the content of the
.CW PDFHREF.INFO \& \(lq
record\(rq associated with
.CWI dest-name > < ,
as arguments to a designated\**
.FS
A suitable
.CW pdfhref
reference text formatting macro is provided,
within
.CW groff 's
.CW pdfmark
macro suite;
it will be used by default,
unless the author has designated an alternative,
as described in
.XR-NO-PREFIX custom-format .
.FE
.CW pdfhref
reference text formatting macro.
.LP
.pdfhref M -N auto-format-example
To illustrate this capability,
if we revisit the example offered in
.XR-NO-PREFIX user-format ,
but instead of specifying the reference as
.QP
.CW ".pdfhref L -D set-colour -- use of colour"
.LP
we simply specify it,
.EM without
the explict reference text arguments,
as
.QP
.CW ".pdfhref L -D set-colour"
.LP
and if neither
.CW PDFHREF.INFO ,
nor the designated
.CW pdfhref
reference text formatting macro,
have been changed from their original default settings,
then we should see a reference formatted as
.QP
.pdfhref L -D set-colour-default
.LP
Alternatively,
location data from the
.CW PDFHREF.INFO \& \(lq
record\(rq may be combined with explicitly specified text,
by adding the
.CWB -X
option to the explicit form of the
.CW pdfhref
macro request,
e.g.
.QP
.CW ".pdfhref L -X -D set-colour -- Using Colour ..."
.LP
will cause the reference to be displayed as
.QP
.pdfhref L -X -D set-colour-default -- Using Colour ...
.LP
Notice that,
when the displayed form of the reference incorporates the assigned
.CWI default-text > < ,
as derived from the
.CW PDFHREF.INFO \& \(lq
record\(rq,
this is enclosed in double quotation marks,
but explicitly specified text is not;
if quotation of explicitly specified text is desired,
then appropriate quotation marks should simply be included within the
.CWI explicit-text > <
arguments specification.
.LP
Finally,
to conclude this introduction to
the automatic reference text formatting capabilities of
.CW groff 's
.CW pdfmark
macro suite,
it may be noted that,
while the default provisions may be adequate,
in many cases,
this will not always be so.
In the event of these default provisions being inadequate,
customization is readily supported,
as explained in
.pdfhref L -D custom-format -A . -- the following section
.
.NH 4
.ne 5v+(u;3*\n[PD])
.XN -N custom-format -- Customizing Automatically Formatted Reference Text
.LP
\(lqAutomatically formatted\(rq reference text is interpolated,
within the running text of a published PDF document,
when the
.CW pdfhref
macro is invoked with its
.CWB L \& \& \(rq \(lq
operator,
to refer to a destination named by the
.CWB -D \& \& \(rq \(lq
option,
.EM "and either" \^:\(en
.QS
.sp -\n[PD]u
.IP \(bu
no explicit reference text is specified,
(in which case,
specification of the
.CWB -X \& \& \(rq \(lq
option is implied),
.EM or ,
.IP \(bu
the
.CWB -X \& \& \(rq \(lq
option is specified,
in conjunction with explicit reference text.
.QE
.sp -\n[PD]u
.LP
In each of these cases,
the reference text is derived,
(in its entirety,
in the first case,
or partially,
in the second),
from a reference dictionary record for the named destination.
.LP
The reference dictionary,
itself,
comprises a collection of
.CW PDFHREF.INFO
records,
one per destination,
indexed by destination name.
While it is possible to create a reference dictionary record manually,
using a macro call of the form:\(en
.QP
.CW .pdfhref\ D\ -N \c
.CWI dest-name > \ < \c
.CWI keyword > \ [< \c
.CWI value >] \ < \^\c
.CW ...\  \c
.CWI text > < \|\c
.CW ...
.LP
(in which the \%in\(hyorder aggregate of all specified
.CWI keyword > <
.CWI value > <
pairs,
and all following
.CWI text > <
arguments,
comprises the
.CW PDFHREF.INFO
record,
and
.CWI dest-name > <
represents the destination name
on which it is indexed),
it is generally more convenient to have the dictionary compiled automatically,
by specifying the
.CWB -X \& \& \(rq \(lq
option,
when using a macro call of the form:\(en
.QP
.CW ".pdfhref M -X -N" \c
.CWI dest-name > \ < \c
.CW " -- " \c
.CWI text > < \|\c
.CW ...
.LP
to mark the location of each named destination;
the procedure is described,
in detail,
in
.XR-NO-PREFIX create-map .
.LP
Interpolation of automatically formatted reference text
is delegated to a specialized formatting macro,
which assumes responsibility for storing the formatted representation
of the reference text,
into the
.CW PDFHREF.TEXT
string;
this formatting macro may be defined by the user,
(if specialized formatting is required),
or,
in most cases,
a standardized default macro,
provided by
.CW pdfmark.tmac ,
may be used.
In either case,
the content of the
.CW PDFHREF.INFO
record,
which is associated with the named reference destination,
will be passed to the formatting macro as a sequence of macro arguments,
while any explicit reference text,
which has been specified in the initiating
.CW .pdfhref\ L\ ... \(rq \(lq
call,
will be passed in the
.CW PDFHREF.DESC
string;
(if no reference text is explicitly specified,
then any \%pre\(hyexisting definition of
.CW PDFHREF.DESC
is explicitly deleted,
prior to calling the formatting macro).
.LP
.pdfhref M -N default-format
When the
.CW pdfmark.tmac
default formatting macro is used,
formatting progresses as follows:\(en
.QS
.sp -\n[PD]u
.nr ITEM 0 1
.de ITEMIZE ITEMIZE
.IP \s'-2.5z'\\n+[ITEM]\s'+2.5z'.
.ITEMIZE
.CW PDFHREF.TEXT
is initialized to the content of the
.CW PDFHREF.PREFIX
string;
this has a default value of \(lqsee\(rq,
but may be redefined by the user,
to any suitable alternative content,
(including the empty string,
if desired).
.
.ITEMIZE
The
.CW PDFHREF.INFO
record,
as passed in the argument list,
is inspected to determine whether the first argument
.CW \e$1 ) (
matches any of the known formatting keywords,
or otherwise it,
and any additional arguments which follow it,
will be interpreted as representing the text
of an implicit reference description.
.
.ITEMIZE
If
.CW \e$1
.EM does
match any of the known formatting keywords,
the argument which follows
.CW \e$2 ) (
is interpreted as the
.CWI value > < ,
(which completes a
.CWI keyword > < \h'0.5n'\c
.CWI value > <
pair);
.CW \e$2
is interpolated into the format string
which is associated with keyword
.CW \e$1 ,
and the result is appended to
.CW PDFHREF.TEXT .
The matched
.CW \e$1 ,
and accompanying
.CW \e$2 ,
are then shifted out of the argument list,
promoting
.CW \e$3 ,
(if any further arguments are present),
to the
.CW \e$1
position,
and the keyword matching process is repeated,
from step \s'-1.5z'2\s'+1.5z'.
.
.ITEMIZE
If,
during
.EM any
execution cycle of step \s'-1.5z'2\s'+1.5z',
.CW \e$1
is found
.EM not
to match any known formatting keyword,
.EM and
.CW PDFHREF.DESC
has
.EM not
been assigned any explicit content,
then any remaining arguments are assigned to
.CW PDFHREF.DESC ;
thus,
.CW PDFHREF.DESC
becomes the descriptive component of the reference text,
either as explicitly specified by the originating
.CW .pdfhref\ L\ ... \(rq \(lq
call,
or implicitly deduced from the reference dictionary
.CW PDFHREF.INFO
record for the named link destination.
.
.ITEMIZE
Finally,
an interpolating reference to
.CW PDFHREF.DESC
is appended to
.CW PDFHREF.TEXT ,
from which any accumulated initial spaces are then removed,
and the resultant
.CW PDFHREF.TEXT
string is handed back to the originating
.CW .pdfhref\ L\ ... \(rq \(lq
call,
for interpolation as the formatted content within,
and which defines the extent of,
the link \%\(lqhot\(hyspot\(rq region.
.QE
.sp -\n[PD]u
.LP
From the foregoing,
it may be deduced that reference text,
formatted by the default formatting macro,
will commence with the content of the
.CW PDFHREF.PREFIX
string,
followed by the result of interpolation of any
.CW keyword/value
pairs found in the
.CW PDFHREF.INFO
record component of the relevant reference dictionary entry,
and ends with a
.CW PDFHREF.DESC
component,
either as implicitly defined within that same
.CW PDFHREF.INFO
record,
or as explicitly specified as final arguments to
.CW .pdfhref\ L\ ... \(rq. \(lq
Within the formatted text,
the keyword/value pair interpolations appear
in the order in which \(lqknown\(rq keywords are found,
.ne 7v+\n[PD]u
while parsing the
.CW PDFHREF.INFO
record;
the default set of known formatting keywords comprises:\(en
.QS
\h'0.45n'\Z'Keyword'\h'0.9i'\Z'Format Name'\h'1.5i'Default Format
.sp -0.5v
\l'0.7i'\h'0.2i'\l'1.3i'\h'0.2i'\l'1.2i'
.de keyword keyword
.br
.ta 0.9i 2.4i
.ti +0.45n
.CW "\\$1\t\\$2\t" \\$3
.keyword page PDFHREF.PAGEREF page
.CW \e\e$1,
.keyword section PDFHREF.SECTREF section
.CW \e\e$1,
.keyword file PDFHREF.FILEREF \c
.CW \e\e$1
.QE
.LP
The format of any of these known keyword interpolations may be customized,
by redefinition of their corresponding \(lqFormat Name\(rq strings;
each may incorporate any text of the user's choice\*[em]inclusion of
the keyword itself is
.EM not
necessary,
however,
inclusion of the
.CW \e\e$1
placeholder,
while not mandatory,
.EM is
a necessary prerequisite for interpolation of the
.CW value
component of the
.CW keyword/value
pair,
from the
.CW PDFHREF.INFO
record.
.
.LP
In the case of any
.CW PDFHREF.INFO
record which originates from a
.CW .pdfhref\ M\ -X\ ... \(rq \(lq
call,
the precise gamut of keyword interpolations which do,
and the order in which they will,
appear within automatically formatted reference text,
may be manipulated by redefinition of the
.CW PDFHREF.INFO
string itself.
For example,
with the default
.CW PDFHREF.PREFIX ,
.CW PDFHREF.PAGEREF ,
.CW PDFHREF.SECTREF ,
and
.CW PDFHREF.INFO
definitions:\(en
.DS I
.fam C
\&.ds PDFHREF.PREFIX see
\&.ds PDFHREF.PAGEREF page \e\e$1,
\&.ds PDFHREF.SECTREF section \e\e$1,
\&.ds PDFHREF.INFO page \e\en% \e\e$*
.DE
.LP
a request such as
.IP
.CW ".pdfhref L -D set-colour"
.LP
may,
(as indicated in
.XR-NO-PREFIX auto-format ),
result in formatted reference text similar to:\(en
.QP
.XR set-colour-default
.LP
whereas,
a simple redefinition of
.CW PDFHREF.INFO ,
.EM before
the
.CW set-colour \(rq \(lq
destination is marked:\(en
.IP
.CW ".ds PDFHREF.INFO section \e\e*[SN-NO-DOT] \e\e$*"
.LP
may\**
.FS
Assuming that the
.CW SN-NO-DOT
string represents the effective section number,
at the point where the link destination is marked,
as it does when formatting with the
.CW ms
macros provided with
.CW \%groff-1.19.2
and later.
.FE
result in alternative formatting similar to:\(en
.QP
.XR set-colour
.LP
(as is used in this document itself).
.
.LP
In addition to these default formatting capabilities,
.CW pdfmark.tmac
also offers support\**
.FS
Available only in versions of
.CW pdfmark.tmac
as distributed with
.CW groff-pdfmark
from
.CW \%groff-pdfmark-20230317.1
onwards.
.FE
for interpolation of \%user\(hydefined
.CW keyword/value
pairs;
these may be defined,
using a macro call of the form:\(en
.IP
.CW ".pdfhref K <" \c
.CWI keyword >\ < \& \c
.CWI \%format-name >\ [< \& \c
.CWI keyword >\ < \& \c
.CWI \%format-name >]
.CW ...
.LP
accompanied by string definitions,
similar to that for
.CW PDFHREF.PAGEREF ,
for each
.CW \%format-name
argument specified;
.CW keyword/value
pairs,
corresponding to such \%user\(hydefined keywords,
may be incorporated into the
.CW PDFHREF.INFO
record definition,
and they will be interpreted by the default formatting macro,
in the same manner as the default set of keywords.
For example,
we might wish to add add a chapter reference capability.
We
.EM could
accomplish this by subverting the effect of one the default keywords;\**
.FS
We might choose to implement the effect of a
.CW chapter
keyword by subverting the default behaviour of,
e.g. the
.CW section
keyword;
we could achieve this by redefining the associated
.CW PDFHREF.SECTREF
format string,
in conjunction with a modified
.CW PDFHREF.INFO
template:\(en
.nr zz \n[.i]
.QP
.in +\n[pdf:fn.tag.width]u
.CW ".ds PDFHREF.SECTREF chapter \e\e$1,"
.br
.CW ".ds PDFHREF.INFO section \e\en[chapter] page \e\en% \e\e$*"
.LP
.in \n[zz]u
and,
(assuming for the purpose of this example,
that the
.CW chapter
number matches the current \%top\(hylevel section heading number),
.QP
.in +\n[pdf:fn.tag.width]u
.CW ".pdfhref L -D set-colour"
.LP
.in \n[zz]u
would be expected to yield a reference similar to:\(en
.QP
.in +\n[pdf:fn.tag.width]u
.rn PDFHREF.SECTREF xx
.ds PDFHREF.SECTREF chapter \\$1,
.pdfhref L -D set-colour-chapter-kludge
.rn xx PDFHREF.SECTREF
.FE
however,
as a (possibly undesirable) side effect of such a customization,
we would lose the normal behaviour of the selected default keyword,
while also introducing an element of obfuscation around
the use of that keyword;
we may prefer not to do this.
.
.LP
If we wish to avoid subversion of any default keyword,
with the attendant obfuscation of intent for the chosen keyword,
(and we have a sufficiently recent version of
.CW pdfmark.tmac ),
then the preferred method for implementing a custom keyword feature,
such as automatic interpretation of a
.CW chapter
reference keyword,
would be to make use of the
.CW .pdfhref\ K\ ... \(rq \(lq
capability;
e.g.:\(en
.DS I
.fam C
\&.ds PDFHREF.CHAPTER chapter \(rs\(rs$1,
\&.pdfhref K chapter PDFHREF.CHAPTER
.DE
.LP
With these definitions in place,
and assuming that,
at the point where the named destination is marked,
the effective chapter number is made available in the
.CW \en[CH]
numeric register,
and also that the effective
.CW PDFHREF.INFO
definition has been preset to:\(en
.QP
.CW ".ds PDFHREF.INFO chapter \e\en[CH] page \e\en%" \c
.CW " section \e\e*[SN-NO-DOT] \e\e$*"
.LP
(assuming that
.CW SN-NO-DOT
represents a section number,
as it does when the
.CW -ms
macros are used for document formatting),
.pdfhref L -D auto-format-example -A , -- \
the example from the preceding section
viz.:\(en
.QP
.CW ".pdfhref L -D set-colour"
.LP
might now,
subject to limitations which will be discussed in
.\"pdfhref F SECREF
.XR-NO-PREFIX keyword-map ,
.\"pdfhref F
produce a reference similar to
.QP
.ds PDFHREF.CHAPTER chapter \\$1,
.pdfhref K chapter PDFHREF.CHAPTER
.pdfhref L -D set-colour-chapter
.
.LP
Finally,
in the event that the default reference text formatting macro,
combined with any \%user\(hydefined
.CW PDFHREF.INFO
specification,
\%user\(hydefined \%keyword\(hyspecific format strings,
and combination of default or \%user\(hydefined keywords,
is insufficient to achieve a required formatting effect,
the
.CW .pdfhref\ F\ [<\f(CImacro-name\fP>] \(rq \(lq
facility allows the user to define an alternative formatting macro,
and substitute it in place of the default.
For example,
within this document itself,
some internal references are displayed as a section number reference alone;
such references are derived from the associated
.CW PDFHREF.INFO
record,
but are formatted by the document\(hylocal
.CW SECREF
macro:\(en
.DS I
.fam C
\&.de SECREF
\&.   while \e\en(.$ \e{\e
\&.      ie \(aq\e\e$1\(aqsection\(aq \e{\e
\&.            if !dSECREF.BEGIN .ds SECREF.BEGIN \e\e$1
\&.            ds PDFHREF.TEXT \e\e*[SECREF.BEGIN]\e\(ti\e\e$2
\&.            rm SECREF.BEGIN
\&.            shift \e\en(.$
\&.         \e}
\&.      el \e{\e
\&.            shift
\&.            if \e\en(.$ shift
\&.         \e}
\&.      \e}
\&..
.DE
.LP
to filter all but the \(lqsection\(rq reference out of the
.CW PDFHREF.INFO
record,
which is then displayed as the reference text;
used thus:\(en
.DS I
.fam C
\&.pdfhref F SECREF
\&.pdfhref L -D <\f(CIreference-name\fP>
\&.pdfhref F
.DE
.LP
it will emit reference text similar to:\(en
.QP
.pdfhref F SECREF L -D custom-format
.LP
while,
when used with the additional qualifying definition of
.CW SECREF.BEGIN :\(en
.DS I
.fam C
\&.pdfhref F SECREF
\&.ds SECREF.BEGIN Section
\&.pdfhref L -D <\f(CIreference-name\fP>
\&.pdfhref F
.DE
.KS
.LP
it will capitalize the emitted reference text,
such that it becomes suitable for use at the beginning of a sentence:\(en
.QP
.ds SECREF.BEGIN Section
.pdfhref L -D custom-format
.pdfhref F
.KE
.LP
Notice that the preceding
.CW SECREF
macro exhibits
.EM identical
semantics to those of the default reference formatting macro,
.pdfhref L -A , -D default-format -- as described above
(and as
.EM any
\%user\(hydefined reference formatting macro
.EM must ),
insofar as it expects to be passed the content of a
.CW PDFHREF.INFO
record as its arguments,
and it returns the formatted reference text as the definition of the
.CW PDFHREF.TEXT
string;
however,
while the
.CW PDFHREF.DESC ,
.CW PDFHREF.PREFIX ,
.CW PDFHREF.PAGEREF ,
.CW PDFHREF.SECTREF ,
and
.CW PDFHREF.FILEREF
strings
(and any other custom format strings which the user may have defined)
remain available,
the
.CW SECREF
macro simply ignores them.
.LP
Further note that the effect of invoking
.CW .pdfhref\ F\  \c \(lq
.CWI macro-name > < \(rq
is persistent;
if it is desired to revert to use of the default reference formatting macro,
after temporary use of a \%user\(hydefined alternative,
this may be accomplished by invoking
.CW .pdfhref\ F \(rq \(lq
.EM without
specifying any
.CWI macro-name > < \(rq \(lq
argument,
as shown in each of the two preceding usage examples.
.
.NH 3
.XN Problematic Links
.LP
Irrespective of whether a
.CW pdfhref
reference is placed using the
.CWB L \& \& \(rq \(lq
operator, or the
.CWB W \& \& \(rq \(lq
operator, there may be occasions when the resulting link
does not function as expected.
A number of scenarios, which are known to be troublesome,
are described below.
.
.NH 4
.XN -N page-trap -- Links with a Page Transition in the Active Region
.LP
When a link is placed near the bottom of a page,
it is possible that its active region, or \%\(lqhot\(hyspot\(rq,
may extend on to the next page.
In this situation, a page trap macro is required
to intercept the page transition, and to restart the mapping of
the \%\(lqhot\(hyspot\(rq boundary on the new page.
.LP
The
.CW pdfmark
macro package includes a suitable page trap macro, to satisfy this requirement.
However, to avoid \%pre\(hyempting any other requirement the user may have for
a page transition trap, this is
.EM not
installed as an active page trap,
unless explicitly requested by the user.
.LP
To enable proper handling of page transitions,
which occur within the active regions of reference links,
the user should:\(en
.QS
.nr ITEM 0 1
.sp -\n[PD]u
.ITEMIZE
Define a page transition macro, to provide whatever features may be required,
when a page transition occurs\*[em]e.g.\& printing footnotes,
adding page footers and headers, etc.
This macro should end by setting the output position at the correct
vertical page offset, where the printing of running text is to restart,
following the page transition.
.
.ITEMIZE
Plant a trap to invoke this macro, at the appropriate vertical position
marking the end of normal running text on each page.
.
.ITEMIZE
.ne 4v+(u;2*\n[PD])
Initialize the
.CW pdfhref
hook into this page transition trap, by invoking
.RS
.IP
.fam C
.B ".pdfhref I -PT"
.BI macro-name > <
.LP
where
.CWBI macro-name > <
is the name of the user supplied page trap macro,
to ensure that
.CW pdfhref
will correctly restart mapping of active link regions,
at the start of each new page.
.RE
.QE
.LP
It may be observed that this initialization of the
.CW pdfhref
page transition hook is, typically, required only once
.EM before
document formatting begins.
Users of document formatting macro packages may reasonably expect that
this initialization should be performed by the macro package itself.
Thus, writers of such macro packages which include
.CW pdfmark
bindings, should provide appropriate initialization,
so relieving the end user of this responsibility.
The following example, abstracted from the sample
.CW ms
binding package,
.CW spdf.tmac ,
illustrates how this may be accomplished:\(en
.DS I
.fam C
\&.\e" groff "ms" provides the "pg@bottom" macro, which has already
\&.\e" been installed as a page transition trap.  To ensure proper
\&.\e" mapping of "pdfhref" links which overflow the bottom of any
\&.\e" page, we need to install the "pdfhref" page transition hook,
\&.\e" as an addendum to this macro.
\&.
\&.pdfhref I -PT pg@bottom
.DE
.
.KS
.NH 2
.XN -N add-note -- Annotating a PDF Document using Pop-Up Notes
.LP
The \*[Adobe] PDF specification defines several types of annotation,
which may be associated with a PDF document;
of these defined annotation types,
.EM two
are
.EM explicitly
supported by
.CW groff 's
.CW pdfmark
macros.
Of these,
although it is not explicitly identified as such,
in the preceding discussion,
it is the
.CW Link \(rq \(lq
annotation type which underpins the operation of the
.CW pdfhref
macro,
as it is extensively described in
.XR-NO-PREFIX pdfhref .
.KE
.
.LP
In addition to supporting the
.CW Link \(rq \(lq
annotation type,
through the use of the
.CW pdfhref
macro,
.XR pdfhref ), (
the
.CW pdfmark
macros offer support for the
.CW Text \(rq \(lq
annotation type;
primarily useful as a means of adding editorial comments,
this creates an annotation similar to a \(lqsticky note\(rq,
attached to the document page,
and represented by an icon,
at the attachment point,
which, when clicked, opens the annotation itself,
in a \%pop\(hyup window.
.
.LP
It may be noted that some\*[em]but not all\**
.FS
Indeed,
Adobe's own Acrobat Reader\*{\(tm\*} application
may be found wanting, in this respect.
.FE
\h'-0.8n'\*[em]PDF viewer applications may provide support for adding,
and editing
.CW Text \(rq \(lq
annotations.
While such support,
within a viewer application,
may be convenient for \%3rd\(hyparty editorial annotation,
it may not be the most convenient method for the document author,
should he, or she, wish to insert such annotations
at the point of document origin.
Thus, the
.CW pdfmark
macros provide the
.CW pdfnote
macro, for direct insertion of
.CW Text \(rq \(lq
annotations,
such as this,
.pdfnote -T "An Example Text Annotation" -PD 1 \# continued/...
Please do not move, modify, or remove this note; doing \#
so may invalidate the example to which it refers.\#
\*[PDFNOTE.PILCROW]\#
This is an illustration of an editorial comment, \#
placed directly by the document author, \#
using the exact markup, as specified in \#
the example of the usage of the pdfnote macro, \# .../continuation ends
which immediately follows the note's icon.\"          here.
\h'5n'created as in the following example:\**
.FS
It may be noted that the
.EM entire
content of any
.CW pdfnote
.EM must
be entered as a
.EM "single logical"
input line;
this may be achieved,
most effectively,
and
.EM without
necessitating an excessively long,
and unwieldy,
.EM physical
input line,
by folding the
.CW .pdfnote
call over multiple input lines,
with each,
.EM excluding
the last,
terminated by a line continuation escape,
(either a single
.CW \(rs \(rq \(lq
escape at the bitter end of each line,
or a
escape,
followed by an optional comment).
.IP \& 5n
Furthermore,
note that the continuation of the running text,
following interpolation of the
.CW .pdfnote
in this example,
commences with an
.CW \(rsh\(aq5n\(aq \(rq \(lq
escape;
this to leave sufficient space for the placement of the icon,
associated with the
.CW pdfnote ,
.EM without
occlusion of the initial few glyphs
of this continued running text.
.FE
.
.DS I
.fam C
Thus, the
\&.CW pdfmark
macros provide the
\&.CW pdfnote
macro, for direct insertion of
\&.CW Text \(rs(rq \(rs(lq
annotations,
such as this,
\&.pdfnote -T \(dqAn Example Text Annotation\(dq -PD 1 \(rs# continued/...
Please do not move, modify, or remove this note; doing \(rs#
so may invalidate the example to which it refers.\(rs#
\(rs*[PDFNOTE.PILCROW]\(rs#
This is an illustration of an editorial comment, \(rs#
placed directly by the document author, \(rs#
using the exact markup as specified in \(rs#
the example of the usage of the pdfnote macro, \(rs# .../continuation ends
which immediately follows the note\[aq]s icon.\(rs\(dq          here.
\(rsh\(aq5n\(aqcreated as in the following example:
.DE
In addition to illustrating the technique
for spreading the
.CW pdfnote
text content over several
.EM input
lines,
this example of
.CW pdfnote
usage gratuituously introduces some of the available
options for setting
.CW pdfnote
attributes,
and the
.CW \(rs*[PDFNOTE.PILCROW]
control,
for manipulation of text layout within the
.CW pdfnote
\%pop\(hyup window;
further discussion of these may be found below, in
.XR-NO-PREFIX pdfnote-options ,
and
.XR-NO-PREFIX pdfnote-layout ,
respectively.
.
.NH 3
.XN -S -N pdfnote-placement -- Controlling \F[C]pdfnote\F[] Icon Placement
.LP
The placement of each
.CW pdfnote
annotation,
on its respective document page,
is determined from its
.CW Rect
attribute;
(this is a
.EM required
attribute,
comprising an array of
.EM four
numeric values, representing, in order, the
.EM "lower left x" ,
.EM "lower left y" ,
.EM "upper right x" ,
and
.EM "upper right y"
\%co\(hyordinates of the page region
in which the
.CW pdfnote
annotation is to be placed).
The
.CW pdfnote
macro computes these four \%co\(hyordinate values,
relative to the current text
.EM output
position on the page,
and specifies the required
.CW Rect
attribute accordingly,
.ne 4v+\n[PD]u
in terms of the following numeric register,
and string assignments:
.QS
.sp -\n[PD]u
.IP \*[= PDFNOTE.OFFSET]
A string,
defined such that it may be evaluated as a numeric expression;
its evaluation is interpreted as the
.EM "lower left x"
ordinate, (and hence, implicitly, the
.EM "upper left x"
ordinate), of the
.CW pdfnote
placement region.
By default,
.ne 2v+\n[DD]u
it is defined as
.DS I
.fam C
\&.ds PDFNOTE.OFFSET  \(dq\(rs\(rsn[.k]+\(rs\(rsn[.o]+\(rs\(rsn[.in]\(rs\(dq
.DE
which, when evaluated,
will result in placement of the
.EM "left edge"
of the
.CW pdfnote
region
.EM immediately
to the
.EM right
of the last running text glyph
written to the output stream.
.
.IP
.ne 3v+\n[PD]u
Users may redefine
.CW PDFNOTE.OFFSET ,
to achieve a different left edge placement for any
.CW pdfnote
annotations which follow;
for example, the definition
.DS I
.fam C
\&.ds PDFNOTE.OFFSET  \(dq\(rs\(rsn[.o]-\(rs\(rsn[PDFNOTE.WIDTH]-1m
.DE
.ds PDFNOTE.OFFSET  "\\n[.o]-\\n[PDFNOTE.WIDTH]-1m
will place
.CW pdfnote
annotations into the left hand page margin, with
.CW 1em
separation from the running text,
as in this example:
.br
.pdfnote -T "Marginal Placement Example" \
This note illustrates placement of pdfnote annotations \
in the left hand page margin, following redefinition of \
the PDFNOTE.OFFSET string.\
\*[PDFNOTE.PILCROW]\
As in the case of the previous pdfnote example, \
moving, modifying, or removing this annotation may \
invalidate the example to which it refers; please \
do not do this!
.DS I
.fam C
\&.pdfnote -T \(dqMarginal Placement Example\(dq \(rs
This note illustrates placement of pdfnote annotations \(rs
in the left hand page margin, following redefinition of \(rs
the PDFNOTE.OFFSET string.\(rs
\(rs*[PDFNOTE.PILCROW]\(rs
As in the case of the previous pdfnote example, \(rs
moving, modifying, or removing this annotation may \(rs
invalidate the example to which it refers; please \(rs
do not do this!
.DE
.
.IP \*[= PDFNOTE.LEADING]
The value of this numeric register
is added to the value retrieved by invocation of the
.CW .mk
request,
to establish the vertical distance,
from the top of the current document page,
at which the top edge of each
.CW pdfnote
icon is to be placed.
By default,
it is defined with a value of
.CW 0.3v ,
which will result in placement of
.CW pdfnote
icons at 30% of the line spacing,
below the
.EM top
of the output line which is currently being composed,
at the insertion point of each
.CW pdfnote
annotation.
This may be redefined by the user;
positive values will push the icons further down the page,
while negative values will pull them upwards,
towards the top of the page.
.
.IP \*[= PDFNOTE.HEIGHT]
Combination of the effects of
.CW PDFNOTE.OFFSET
and
.CW PDFNOTE.LEADING
serves to specify the
.CW (x, \^\c
.CW y)
page \%co\(hyordinates of the
.EM "upper left"
vertex of the placement region for a
.CW pdfnote
annotation;
the value of the
.CW PDFNOTE.HEIGHT
numeric register is added to the
.CW y
ordinate of this upper left \%co\(hyordinate pair,
to determine the corresponding
.EM "lower left"
.CW (x, \^\c
.CW y)
\%co\(hyordinate pair,
which is
.EM required
for the specification of the
.CW Rect
attribute of the
.CW pdfnote
annotation
.CW pdfmark .
.
.IP
The default value specified for
.CW PDFNOTE.HEIGHT
is
.CW 9 \h'0.6n'\c
.CW millimetres ;
this corresponds,
approximately,
to the height of
.CW Text \(rq \(lq
annotation icons in many PDF viewer applications.
The user
.EM may
choose to define an alternative value;
however,
the usefulness of doing so may be questionable.
.
.IP \*[= PDFNOTE.WIDTH]
As in the case of addition of the value of
.CW PDFNOTE.HEIGHT
to the
.CW y
ordinate of the upper left
.CW pdfnote
placement \%co\(hyordinate pair,
to compute the
.EM lower
left \%co\(hyordinate pair,
the value of the
.CW PDFNOTE.WIDTH
numeric register is added to the upper left
.CW x
ordinate,
to compute the corresponding
.EM "upper right"
.CW (x, \^\c
.CW y)
\%co\(hyordinate pair;
this is
.EM required
to complete the
.CW Rect
attribute specification for the annotation
.CW pdfmark .
.
.IP
The default value specified for
.CW PDFNOTE.WIDTH
is
.CW 8 \h'0.6n'\c
.CW millimetres ;
this corresponds,
approximately,
to the width of
.CW Text \(rq \(lq
annotation icons in many PDF viewer applications.
The user
.EM may
choose to define an alternative value;
however,
as in the case of
.CW PDFNOTE.HEIGHT ,
the usefulness of such an alternative definition may be questionable.
.QE
It may be worthy of note that
the \*[Adobe] PDF Specification is rather vague,
with respect to how the
.CW Rect
attribute of
.CW Text \(rq \(lq
annotations should be interpreted,
(simply stating that this attribute specifies the placement
of such annotations on their respective pages),
and there is substantial inconsistency among PDF viewer applications,
in their respective interpretations.
Whereas the \*[Adobe]
.pdfmark-manual
states that the
.CW Rect
attribute specifies the vertex \%co\(hyordinates
\(lqof the rectangle defining the open note window\(rq,
(which might be construed as referring to the \%pop\(hyup
window in its open state),
it appears that few\*[em]if indeed any\*[em]of
of the currently available PDF viewer applications
have adopted this interpretation.
All
.EM do
appear to agree that the
.EM "upper left corner"
of the annotation
.EM icon
should be placed at the page \%co\(hyordinates
which are derived by combination of the
.EM "lower left x"
ordinate, and the
.EM "upper right y"
ordinate, as specified for the
.CW Rect
attribute;
there is significantly less agreement on what effect,
if any, the width, and height of the rectangle,
which may be deduced from the
.CW Rect
attribute specification,
should have.
All viewers appear to use a fixed size icon,
and an arbitrarily chosen size, and placement,
for the associated \%pop\(hyup window;
at least one viewer
.EM does
appear to interpret the derived annotation width,
and height, as a specification of the extent
to which the effective clickable region covers,
or extends beyond,
the region occupied by the icon itself,
but most appear to ignore them altogether.
.
.NH 3
.XN -S -N pdfnote-options -- Options for Manipulating \
\F[C]pdfnote\F[] Annotation Attributes
.LP
To the extent to which various PDF viewing applications
may support them, the
.CW pdfnote
macro will interpret the following optional argments,
(which
.EM must
be placed
.EM before
any text specifying the content of the annotation),
to affect the style of
.CW pdfnote
annotations:
.QS
.IP "\*[= -O]" 4n
Select
.EM open \(rq \(lq
as the preferred initial state for the associated
.CW pdfnote
\%pop\(hyup window;
no additional arguments are parsed, beyond
.CW -O
itself, when interpreting this option.
.
.IP
This option sets the
.CW Open
attribute for the associated
.CW pdfnote
annotation to
.CW true ;
some PDF viewer applications may not
reliably interpret this attribute.
.pdfnote -O -T "A Pop-Up Note in Initially Open State" \
This note should be displayed in the open state, when the \
document itself is opened, if the PDF viewer supports \
this capability.
.
The example to the left is specified thus:
.DS I
.fam C
\&.pdfnote -O -T \(dqA Pop-Up Note in Initially Open State\(dq \(rs
This note should be displayed in the open state, when the \(rs
document itself is opened, if the PDF viewer supports \(rs
this capability.
.DE
it should be displayed in the initially open state,
when this document is opened in a PDF viewer application which
.EM does
correctly interpret the attribute.
.
.IP "\*[= -T] \*[= \& Title\~Bar\~Text\~... \(dq \(dq]"
Define text to be displayed within the title bar
of the \%pop\(hyup window which is associated with a
.CW pdfnote
annotation;
requires
.EM "exactly one"
following argument,
in addition to the
.CW -T
itself;
this argument should be a text string,
and should be enclosed in programming quotes (ASCII 34),
if spaces are to be included.
Any of the preceding
.CW pdfnote
annotation examples illustrate how this option is used.
.
.IP
This option causes its text string argument to be passed as
the value of the
.CW Title
attribute,
when invoking the
.CW pdfmark
macro to create the associated
.CW pdfnote
annotation;
this appears to enjoy better support than the
.CW Open
attribute, among PDF viewer applications,
but support is by no means universal.
.
.IP "\*[= -C] \
\*[= \& red-value > <] \*[= \& green-value > <] \*[= \& blue-value > <]"
Specifies the background colour, which is to be used for the
.CW pdfnote
annotation's icon,
and also, if supported by the PDF viewer application,
for the frame, and title bar, of the associated
.CW pdfnote
\%pop\(hyup window.
This option requires
.EM "exactly three"
additional arguments,
following the
.CW -C
itself; each of these
.EM must
be a decimal number, in the range
.CW 0.0\h'0.5n'...\h'0.5n'1.0 ,
representing the intensity,
in RGB colour space,
for each of the red, green, and blue components of the desired colour,
respectively.
.
.IP
If this option is not specified,
the PDF viewer application will assign a default colour,
for both the
.CW pdfnote
icon background, and, if supported,
for the \%pop\(hyup window's frame.
.
.IP
Specification of this option causes a
.CW Color
attribute assignment to be included within the
.CW pdfmark
invocation, which is used to place the associated
.CW pdfnote
annotation.
Differing PDF viewer applications vary
in the extent to which they support this attribute.
The example to the left
.pdfnote -C 0.7 1.0 0.7 \
-T "Icon Background Colour Example" \
This example specifies a pale green colour, for the icon \
background and pop-up window frame, and serves to illustrate \
the extent to which text annotation colours are supported by \
the current PDF viewer application.
has been specified thus:
.DS I
.fam C
\&.pdfnote -C 0.7 1.0 0.7 \(rs
-T \(dqIcon Background Colour Example\(dq \(rs
This example specifies a pale green colour, for the icon \(rs
background and pop-up window frame, and serves to illustrate \(rs
the extent to which text annotation colours are supported by \(rs
the current PDF viewer application.
.DE
which may serve as an illustration of the current
PDF viewer application's level of support for colour attributes,
when applied to
.CW Text \(rq \(lq
annotations defined using the
.CW pdfnote
macro.
.
.IP "\*[= -I] \*[= \& icon-name > <]"
Assigns an alternative icon,
to indicate placement of a
.CW pdfnote
annotation; requires one additional argument following the
.CW -I ,
indicating the style of icon which is to be assigned;
the selected style is assigned, via the
.CW pdfmark
macro, to the
.CW Name
attribute of the annotation.
.
.IP
Icon styles are identified by name.
The particular set of named icons, which are available,
depends on the PDF viewer application which is in use;
however, regardless of any \%non\(hystandard choices,
which a particular viewer might support,
the \*[Adobe] PDF Specification requires, as minimum, that icons named
.CW Note ,
.CW Comment ,
.CW Help ,
.CW Insert ,
.CW Key ,
.CW NewParagraph ,
and
.CW Paragraph
should be available.
If no explicit icon style is selected, the
.CW Note
style is used, by default.
.
.IP
.ne 8v
As an example of how an alternative icon style might be used\Z','\|\**
.FS
While this example serves, primarily,
to illustrate the the selection of the
.CW Key \(rq \(lq
icon style, for the associated
.CW pdfnote
annotation,
it also illustrates the use of
.CW PDFNOTE.QUOTED
interpolation,
(with aliasing to \(rs*[\(dq\(dq ...text...]
as \%document\(hylocal shorthand),
to introduce double quoted text within
the content of the annotation.
.FE
.als "" PDFNOTE.QUOTED
.pdfnote -I Key -T "An Example Keynote Annotation" \
This is an example of a \*["" keynote annotation], which has been \
defined using the pdfnote macro, using its optional \*["" Key] \
icon selection.
a keynote annotation may be placed thus:
.DS I
.fam C
\&.als \(dq\(dq PDFNOTE.QUOTED
\&...
\&.pdfnote -I Key -T \(dqAn Example Keynote Annotation\(dq \(rs
This is an example of a \(rs*[\(dq\(dq keynote annotation], which has been \(rs
defined using the pdfnote macro, using its optional \(rs*[\(dq\(dq Key] \(rs
icon selection.
.DE
.
.IP "\*[= -PD] \*[= \& line-count > <]"
Set the number of blank lines which should be inserted,
to serve as paragraph separators within
.CW pdfnote
content,
following an \%end\(hyof\(hyparagraph
.CW PDFNOTE.PILCROW
mark,
.XR pdfnote-layout ), (
within the content of
.CW pdfnote
annotations.
Requires
.EM "exactly one"
additional argument, following
.CW -PD
itself; this should be an
.EM "integer numeric"
value, indicating the number of
.EM additional
newlines which should be inserted,
.EM following
the one which is normally placed at
the \%end\(hyof\(hyparagraph mark.
.
.IP
Unlike each of the preceding
.CW pdfnote
options,
(each of which assigns annotation attributes,
and applies only to the individual
.CW pdfnote
instance for which it is specified),
the
.CW -PD
option\*[em]so named by analogy with the similarly named
.CW ms
macro, which has a similar effect\*[em]\c
.EM "does not"
assign annotation attributes;
rather, it sets a count initializer,
which is internal to the
.CW pdfnote
macro itself.
Its effect is \(lqsticky\(rq:
that is, it applies not only to the
.CW pdfnote
instance which specifies it,
but also to any
.CW pdfnote
instances which follow it,
unless it is specified again,
with a different\*[em]or even (albeit redundantly)
with the same\*[em]\c
.CW \%line-count
value, for any such following instance.
.
.IP "\*[= --]"
Suppresses interpretation of any further
.CW pdfnote
macro arguments as options.
This is
.EM not ,
strictly, an option
.EM "per se" ,
but may be required in any case
where the following argument is intended to begin
the annotation content,
when it could be mistaken for an optional feature specification.
.QE
.
.NH 3
.XN -S -N pdfnote-layout -- Controlling \F[C]pdfnote\F[] Text Layout
.LP
The \*[Adobe] PDF and pdfmark specifications make
very little provision for control of the layout
of the content of \%pop\(hyup windows which are associated with
.CW Text \(rq \(lq
annotations,
stipulating only that the size and font should be chosen
by the PDF viewer application, which usually offers little,
or no opportunity for user participation in these choices.
.
.LP
Generally,
PDF viewer applications will open annotation \%pop\(hyup windows
when required, each with default width and height as specified by
the viewer application itself.
The annotation content is displayed in a font
which is also specified by the viewer application;
this is usually a proportionally spaced font,
and there is no mechanism for choosing an alternative.
The content is nominally interpreted as a \%single\(hyline of text,
which flows to fit the width of the window;
text flow is facilitated by insertion of \(lqsoft\(rq line breaks,
coincident with white space,
resulting is a flush left, ragged right layout.
The extent to which the author of the annotation may influence this layout
is limited to insertion of \(lqhard\(rq line breaks;
these will always be rendered as such,
when the text is displayed in the \%pop\(hyup window,
producing the effect of a paragraph break.
.
.LP
When placing an annotation,
using the
.CW pdfnote
macro,
if the author wishes to affect the text layout
by inserting a hard line break, this
.EM must
be represented by the literal
.CW \(rsn \(rq \(lq
character sequence.
Unfortunately,
simply specifying this character sequence within any argument to the
.CW pdfnote
macro, (as is necessary to include it within the annotation content),
presents a \%non\(hytrivial challenge to the author: the
.CW \(rs \(rq \(lq
character introduces a
.CW troff
escape, and when it is followed by the
.CW n \(rq \(lq
character,
the escape is interpreted as a reference to a numeric register,
which is resolved according to whatever follows.
Simply escaping the
.CW \(rs \(rq \(lq
character itself,
at the point of the
.CW pdfnote
macro call, does
.EM not
present a satisfactory solution to this challenge, since
.EM "multiple levels"
of escaping are required,
to survive interpretation through an indeterminate number
of internal macro call levels.
Thus, to circumvent this challenge,
and to robustly facilitate inclusion of the literal
.CW \(rsn \(rq \(lq
character sequence within the
.CW pdfmark
output stream, the
.CW pdfmark
macros define the following named strings:
.QS
.IP \*[= PDFNOTE.NEWLINE]
A string representation of the
.CW \(rsn \(rq \(lq
character sequence, which is encoded in a manner which,
when interpreted within the immediate arguments to the
.CW pdfnote
macro, \%re\(hyencodes the sequence such that
its ultimate interpretation is deferred,
until it is eventually written,
as a literal representation of a
.EM single
.CW \(rsn \(rq \(lq
character sequence, to the
.CW pdfmark
output stream.
Use of
.CW PDFNOTE.NEWLINE
is analogous to that of
.CW PDFNOTE.PILCROW ,
which is described below,
and is illustrated in previous examples within
.XR-NO-PREFIX add-note .
.
.IP \*[= PDFNOTE.PILCROW]
So named for its association with the typographer's pilcrow mark,
when interpreted within the immediate arguments to the
.CW pdfnote
macro, this marks the end of a logical paragraph,
and is \%re\(hyencoded as a (possibly recurring) sequence of
.CW \(rs*[PDFNOTE.NEWLINE]
\%re\(hyencodings.
At least one such \%re\(hyencoding is
.EM always
inserted; this is then repeated as many times as specified by the
.CW \%<line-count>
argument to the \%last\(hyspecified, if any,
.CW -PD
option\*(em\c
.XR pdfnote-options \c
\*[em]to the immediate, or any preceding, instance of
.CW pdfnote
macro use.
The effect is to introduce a new logical paragraph,
within the content of the
.CW pdfnote
annotation,
separated from the preceding paragraph,
of which the end is indicated by the
.CW \(rs*[PDFNOTE.PILCROW]
mark, by
.CW \%<line-count>
blank lines.
.
.IP
In the absence of any preceding
.CW -PD
option specification,
the effect of
.CW \(rs*[PDFNOTE.PILCROW]
becomes
.EM identical
to that of a single instance of
.CW \(rs*[PDFNOTE.NEWLINE] .\**
.FS
Neither
.CW PDFNOTE.NEWLINE ,
nor
.CW PDFNOTE.PILCROW
were provided in any version of the
.CW pdfmark
macros, which was published before \%Feb\(hy2023.
Earlier versions provided
.CW PDFLB ,
(for PDF \%line\(hybreak),
as an alternative;
it offered a similar capability to
.CW PDFNOTE.NEWLINE ,
but its implementation was flawed,
and was not robust.
The flawed implementation of
.CW PDFLB
is still supported, but it is now considered to be deprecated,
and using it is not recommended;
either
.CW PDFNOTE.NEWLINE ,
or
.CW PDFNOTE.PILCROW
should be used instead.
.FE
.QE
.
.NH 2
.XN -S -N pdfsync -- Synchronizing Output and \F[C]pdfmark\F[] Contexts
.LP
It has been noted previously, that the
.CW pdfview
macro,
.XR docview ), (
the
.CW pdfinfo
macro,
.XR docinfo ), (
and the
.CW pdfhref
macro, when used to create a document outline,
.XR add-outline ), (
do not immediately write their
.CW pdfmark
output to the \*[PostScript] data stream;
instead, they cache their output, in a
.CW groff
diversion, in the case of the
.CW pdfview
and
.CW pdfinfo
macros, or in an ordered collection of strings and numeric registers,
in the case of the document outline,
until a more appropriate time for copying it out.
In the case of
.CW pdfview
and
.CW pdfinfo
\%\(lqmeta\(hydata\(rq,
this \(lqmore appropriate time\(rq is explicitly chosen by the user;
in the case of document outline data,
.EM some
cached data may be implicitly written out as the document outline is compiled,
but there will
.EM always
be some remaining data, which must be explicitly flushed out, before the
.CW groff
formatting process is allowed to complete.
.LP
.ne 4v+\n[PD]u
To allow the user to choose when cached
.CW pdfmark
data is to be flushed to the output stream, the
.CW pdfmark
macro package provides the
.CW pdfsync
macro, (to synchronize the cache and output states).
In its simplest form, it is invoked without arguments, i.e.
.QP
.fam C
.B .pdfsync
.LP
This form of invocation ensures that
.EM both
the \%\(lqmeta\(hydata cache\(rq, containing
.CW pdfview
and
.CW pdfinfo
data,
.EM and
the \(lqoutline cache\(rq,
containing any previously uncommitted document outline data,
are flushed; ideally, this should be included in a
.CW groff
\(lqend macro\(rq, to ensure that
.EM both
caches are flushed, before
.CW groff
terminates.
.KS
.LP
Occasionally,
it may be desirable to flush either the \%\(lqmeta\(hydata cache\(rq,
without affecting the \(lqoutline cache\(rq, or \%vice\(hyversa,
at a user specified time, prior to reaching the end of the document.
This may be accomplished, by invoking the
.CW pdfsync
macro with an argument, i.e.
.QP
.fam C
.B ".pdfsync M"
.LP
to flush only the \%\(lqmeta\(hydata cache\(rq, or
.QP
.fam C
.B ".pdfsync O"
.LP
to flush only the \(lqoutline cache\(rq.
.LP
The \%\(lqmeta\(hydata cache\(rq can normally be safely flushed
in this manner, at any time
.EM after
output of the first page has started;
(it may cause formatting problems,
most notably the appearance of unwanted white space, if flushed earlier,
or indeed, if flushed immediately after a page transition,
but before the output of the content on the new page has commenced).
Caution is required, however, when explicitly flushing the
\(lqoutline cache\(rq, since if the outline is to be
subsequently extended, then the first outline entry after flushing
.EM must
be specified at level 1.
Nevertheless, such explicit flushing may occasionally be necessary;
for example, the
.CW TC
macro in the
.CW spdf.tmac
package,
.XR using-spdf ), (
invokes
.CW ".pdfsync\ O" \(rq \(lq
to ensure that the outline for the \(lqbody\(rq section of the document
is terminated,
.EM before
it commences the formatting of the table of contents section.
.KE
.bp
.
.NH 1
.XN -N pdf-layout -- PDF Document Layout
.LP
The
.CW pdfmark
macros described in the preceding section,
.XR pdf-features ), (
provide no inherent document formatting capability of their own.
However,
they may be used in conjunction with any other
.CW groff
macro package of the user's choice\Z','\|\**
.FS
Any of the standard
.CW groff
\%\(lqfull\(hyservice\(rq
macro packages,
.CW me ,
.CW mm ,
.CW mom ,
or
.CW ms ,
or indeed,
any \%\(lqhome\(hybrew\(rq macro package provided by the user,
should be suitable for the purpose;
regardless of the chosen \%\(lqfull\(hyservice\(rq macro package,
it is likely that a binding package,
specific to this choice,
will be required.
.FE
to add such capability.
.LP
In preparing this document, the standard
.CW ms
macro package, supplied as a component of the GNU Troff distribution,
has been employed.
To facilitate the use of the
.CW pdfmark
macros with the
.CW ms
macros,
a binding macro package,
.CW spdf.tmac ,
has been created.
The use of this binding macro package is described in the following section,
.XR using-spdf ); (
it may also serve as an example to users of other standard
.CW groff
macro packages,
as to how the
.CW pdfmark
macros may be employed with their chosen primary macro package.
.
.NH 2
.XN -S -N using-spdf -- Using \F[C]pdfmark\F[] Macros with the \F[C]ms\F[] Macro Package
.LP
The use of the binding macro package,
.CW spdf.tmac ,
allows for the use of the
.CW pdfmark
macros in conjunction with the
.CW ms
macros,
simply by issuing a
.CW groff
command of the form\**
.FS
Once again,
.pdfhref L -D pdf-features-fn -- as noted in footnote\*{\n[pdf-features-fn]\*}
to
.XR-NO-PREFIX pdf-features ,
do not specify any
.CW -T \^\c
.CWI dev
option,
other than
.CW -T \^\c
.CW ps ,
or
.CW -T \^\c
.CW pdf ;
specify
.CW -T \^\c
.CW pdf ,
if you wish to avoid the conversion of \*[PostScript] output to PDF,
which will be required if you specify
.CW -T \^\c
.CW ps ,
or if you omit the
.CW -T \^\c
.CWI dev
option entirely.
.FE
.QP
.fam C
groff [-T\F[]\|\FCps\h'0.2p'|\h'0.2p'-T\F[]\|\FCpdf] -m\F[]\|\FC\c
.B spdf
.I options \F[]\|\|\FC\c [-
.I file \F[]\|\|\FC\c "...] "
\&...
.LP
When using the
.CW spdf.tmac
package, the
.CW groff
input files may be marked up using any of the standard
.CW ms
macros to specify document formatting,
while PDF features may be added,
using any of the
.CW pdfmark
macros described previously,
.XR pdf-features ). (
Additionally,
.CW spdf.tmac
defines a number of convenient extensions to the
.CW ms
macro set, to better accommodate the use of PDF features within the
.CW ms
formatting framework,
and to address a number of
.CW ms
document layout issues,
which require special handling when producing PDF documents.
These additional macros,
and the issues they are intended to address,
are described below.
.
.NH 3
.XN -S -- Document Structuring Considerations when using \F[C]ms\F[] Macros
.LP
Every published document
.EM must
incorporate,
as a minimum,
a document body;
additionally,
many documents may include
.EM \%front\(hymatter ,
which precedes the body,
and
.EM \%end\(hymatter ,
which follows the body.
Additionally,
when publishing as a PDF document,
it may be desired to incorporate a document outline,
referring to chapter,
or section headings,
within the document body.
.LP
Conventionally,
when a document is to include a
.EM "table of contents" ,
this should be placed at the end of the
.EM \%front\(hymatter .
.LP
Traditional
.CW AT&T
implementations of
.CW ms
provide a number of macros to control \%front\(hymatter style,
(of which only the \(lqreleased paper\(rq style,
selected by use of the
.CW RP
macro,
is supported by
.CW groff
.CW ms ),
accompanied by several macros to specify \%front\(hymatter content,
(also supported by
.CW groff
.CW ms ).
Both traditional,
and
.CW groff
.CW ms
implementations also provide a small set of macros
to facilitate compilation of a table of contents;
they do not,
however,
offer any standard facilities for creation
of a corresponding document outline.
.LP
Unfortunately,
the traditional
.CW ms
method of compiling the table of contents
results in it being printed at the end of the document,
rather than in its normal position,
at the end of the \%front\(hymatter.
Traditionally,
this unusual placement of the table of contents would be corrected,
by manual collation,
after printing;
emulation of this mechanical collation technique presents a challenge,
when the document is to be published in PDF format.
.LP
Taking up the challenge of collating the various document sections
into the correct order,
when producing any PDF document,
will necessitate special consideration during the PDF publication process;
this will be discussed in greater depth,
in
.XR-NO-PREFIX pdf-publishing .
To accommodate any specialized processing which may be required,
.CW spdf.tmac
provides:\(en
.QS
.sp -\n[PD]u
.IP \(bu 2n
Macros to isolate the
.EM \%front\(hymatter ,
(excluding the
.EM "table of contents" ),
from the body of the document.
.IP \(bu
Further macros to compile a table of contents,
and a corresponding PDF document outline,
deriving both from section headings,
.XR xh-xn-macros ). (
.IP \(bu
A redefined implementation of the
.CW TC
macro,
(to be invoked at the end of the document,
as in traditional
.CW ms
usage);
this isolates the table of contents
from its preceding \%front\(hymatter (if any),
and from the document body,
to facilitate the collation process.
.\"nr PD +0.1v
.QE
.
.NH 3
.XN -S -- Using \F[C]ms\F[] Section Headings in PDF Documents
.LP
Traditionally,
.CW ms
provides the
.CW NH
and
.CW SH
macros to introduce section headings.
However,
in traditional
.CW ms
implementations,
there is no standard mechanism for generating a
table of contents entry based on the text of the section heading;
neither is there any recognized standard method
for establishing a cross reference link,
or a document outline reference,
to the section.
.LP
To address this limitation of traditional
.CW ms
implementations,
the
.CW spdf.tmac
binding macro package provides the
.CW XH
and
.CW XN
macros\Z','\|\**
.FS
On a technical note,
since
.CW \%groff-1.23 ,
the
.CW groff
implementation of
.CW ms
itself has incorporated basic infrastructure providing
.CW XH
and
.CW XN
macros,
to facilitate duplication of section heading text
into the table of contents;
.CW spdf.tmac
builds on top of this infrastructure,
.EM indirectly
redefining
.CW XH
and
.CW XN ,
by provision of macros
.CW \%XH-REPLACEMENT
and
.CW \%XN-REPLACEMENT
respectively,
to accommodate the duplication of section heading text
into the PDF document outline,
in addition to the table of contents.
Use of this indirect technique is recommended,
whenever redefinition of
.CW XH ,
or
.CW XN ,
is desired.
.FE
.XR xh-xn-macros ), (
to be used in conjunction with the
.CW SH
and
.CW NH
macros respectively;
each of these identifies,
by specification of appropriate arguments,
text which is to be incorporated into the section heading,
duplicated within the PDF document outline,
and in the table of contents.
.
.NH 4
.XN -S -N xh-xn-macros -- The \F[C]XH\F[] and \F[C]XN\F[] Macros
.LP
Formalized from the release of
.CW \%groff-1.23
onwards\Z','\|\**
.FS
Prior to the release of
.CW \%groff-1.23 ,
a prototypical implementation of
.CW spdf.tmac
was introduced with
.CW \%groff-1.19.2 ;
this prototype included an implementation of the
.CW XN
macro,
but it did
.EM not
provide
.CW XH ,
nor did it support the
.CW \%XH-INIT ,
.CW \%XN-INIT ,
and
.CW \%XH-UPDATE-TOC
\%call\(hyback features,
nor the
.CW \%XH-REPLACEMENT ,
and
.CW \%XN-REPLACEMENT
capabilities.
.FE
and nominally intended to be used following
.CW SH
and
.CW NH
respectively,
the calling syntax for this pair of
.CW spdf.tmac
macros is specified as:\(en
.DS I
.sp -\n[PD]u
.CWB .SH
.CWB .XH \& \& \0\c
.CWB -N \& [ \ \c
.CWI name >] < \ \c
.CWB -S ] [ \ \c
.CWB -X ] [ \0\c
.CWI outline-level > < \0\c
.CWI heading-text > < \ \c
.CW ...
.DE
.DS I
.sp -\n[PD]u
.CWB .NH \& \& \0\c
.CWI outline-level > <
.CWB .XN \& \& \0\c
.CWB -N \& [ \ \c
.CWI name >] < \ \c
.CWB -S ] [ \ \c
.CWB -X ] [ \0\c
.CWI heading-text > < \ \c
.CW ...
.DE
.sp -\n[PD]u
.LP
In either case,
the
.CWI heading-text >... < \&
arguments are incorporated into the document body,
formatted as section heading text.
Additionally,
these same
.CWI heading-text >... < \&
arguments,
(prefixed by the content of the
.CW SN
string,
in the
.CW XN
case),
are incorporated into the PDF document outline,
at the level specified by the
.CWI outline-level > <
argument,
and they are made available to the \%user\(hydefinable
.CW \%XH-UPDATE-TOC
\%call\(hyback macro,
.XR xh-update-toc-macro ), (
to support creation of a corresponding entry in
the document's table of contents.
.LP
In both cases,
the supported macro options\**
.FS
.EM None
of these options are supported by the underlying
.CW ms
implementations of
.CW XH
or
.CW XN ,
as implemented from
.CW \%groff-1.23
onwards.
Prior to
.CW \%groff-1.23 ,
only the
.CW -N \ \c
.CWI name > <
and
.CW -X
options are supported by the prototypical
.CW spdf.tmac
implementation of
.CW XN ,
as provided from
.CW \%groff-1.19.2
onwards.
.FE
are:\(en
.QS
.sp -\n[PD]u
.IP "\f(CB-N\fP\0\FC<\fIname\fP>\F[]" 4n
Create a
.CW pdfhref
destination,
with the specified
.CWI name > < ,
and associate it with the corresponding section heading,
as designated by
.CWI heading-text > \%< .
.IP \*[= -S]
Strip any \%font\(hyfamily selection escape sequences,
which may have been specified,
from a copy of
.CWI heading-text > \%< ,
before incorporating this into the document outline;
(this is necessary when such escape sequences are present,
to avoid verbatim rendition of the escape sequences themselves,
within the text of the document outline).
.IP \*[= -X]
Ensure that any
.CW pdfhref
destination name,
specified by the
.CWB -N
.CWI name > <
option,
is included within the document's \%cross\(hyreference dictionary.
.QE
.
.NH 4
.XN -S -N xh-xn-init-macros -- The \F[C]XH\-INIT\F[] and \F[C]XN\-INIT\F[] Macros
.LP
This pair of macros serve as context initialization hooks;
called by the default implementations of the
.CW XH
and
.CW XN
macros respectively,
without arguments,
.EM before
.CW \%XH\-UPDATE\-TOC
is called.
By default,
both return immediately,
.EM without
performing
.EM any
action.
However,
users may override either,
or both,
to perform any desired activity\ ...\ e.g. to save context
for subsequent use by any user\(hydefined macro,
which may have been provided to override the default implementation of
.CW \%XH\-UPDATE\-TOC .
.
.NH 4
.XN -S -N xh-update-toc-macro -- The \F[C]XH\-UPDATE\-TOC\F[] Macro
.LP
This macro is called by both
.CW XH
and
.CW XN ,
(there is no corresponding
.CW \%XN\-UPDATE\-TOC
equivalent,
since none is required to support the default
.CW XH
and
.CW XN
implementations),
to propagate content from the specified section heading arguments
to the document's table of contents.
From
.CW \%groff\-1.23
onwards,
a rudimentary default implementation of
.CW \%XH\-UPDATE\-TOC
is provided within the standard
.CW ms
macro suite;
.ne 2v
however,
it is anticipated that the user will override this default implementation,
in order to achieve more effective control of table of contents formatting.
.LP
When writing a replacement for the
.CW \%XH\-UPDATE\-TOC
macro,
it should be implemented such that it will interpret arguments
as specified in the prototype
.DS I
.CWB \%.XH\-UPDATE\-TOC \& \& \c
.CWI outline\-level > \ \%< \c
.CWI section\-number >] \ \%[< \c
.CWI heading\-text > \ \%< \ \c
.CWI ...
.DE
in which the
.CWI outline\-level > \%<
and
.CWI heading\-text > \%<
arguments are the same as those specified for the
.CW XH ,
or the
.CW NH \^/\^\c
.CW XN
call sequence,
from which
.CW \%XH\-UPDATE\-TOC
itself is called;
the
.CWI section\-number > \%<
argument is
.EM always
specified,
when
.CW \%XH\-UPDATE\-TOC
is called by
.CW XN ,
(and
.EM never
when called by
.CW XH );
when present,
it represents the value of the
.CW SN
string,
which prevails at the time of the invoking
.CW XN
call,
and is simply processed as a prefix to the
.CWI heading\-text > \%<
argument.
.LP
The default implementation of
.CW \%XH\-UPDATE\-TOC
offers only rudimentary formatting of
the resultant table of contents entry;
the
.CWI outline\-level > \%<
argument is simply ignored,
and the remaining arguments are passed to the standard
.CW ms
table of contents generating capability,
in a form which is equivalent to
.DS I
.CW .XS
.CWI section\-number >\ ] \(rs&[< \c
.CWI heading\-text >\ ... \%<
.CW .XE
.DE
As an example (with abridged comments) of how
.CW \%XH\-UPDATE\-TOC
may be redefined,
to achieve more creative formatting of a table of contents,
prior to adopting an alternative table of contents generation technique,
as described in
.pdfhref F SECREF
.XR-NO-PREFIX toc-alternatives ,
.pdfhref F
this publication substituted the following document\(hylocal
implementation:
.DS I
.fam C
\&.ds XNVS1 0.50v  \(rs" leading for top level
\&.ds XNVS2 0.15v  \(rs" leading at nesting level increment
\&.ds XNVS3 0.30v  \(rs" leading following nested group
\&.
\&.de XH-UPDATE-TOC
\&.   XS
\&.      if r tc*hl \(rs{\(rs
\&.      \(rs" Compute additional leading at <outline-level> change
\&.      \(rs"
\&.         ie \(rs\(rs$1>1 \(rs{\(rs
\&.            ie \(rs\(rs$1>\(rs\(rsn[tc*hl] .sp \(rs\(rs*[XNVS2]
\&.            el .if \(rs\(rsn[tc*hl]>\(rs\(rs$1 .sp \(rs\(rs*[XNVS3]
\&.         \(rs}
\&.         el .sp \(rs\(rs*[XNVS1]
\&.      \(rs}
\&.
\&.      \(rs" Record <outline-level> of this entry, to compare with next
\&.      \(rs"
\&.      ie \(rs\(rs$1 .nr tc*hl \(rs\(rs$1
\&.      el .nr tc*hl 1
\&.
\&.      \(rs" Set indentation, and insert <section-number> for this entry
\&.      \(rs"
\&.      nop \(rsh\(aq\(rs\(rsn[tc*hl]-1m\(aq\(rs\(rs$2\(rsc
\&.
\&.      \(rs" Append <heading-text> for this entry
\&.      \(rs"
\&.      shift 2
\&.      nop \(rsh\(aq1.5n\(aq\(rs\(rs$*\(rsh\(aq0.5n\(aq
\&.   XE
\&..
.DE
Used in conjunction with
.CW NH
and
.CW XN ,
this uses document\(hylocal register
.CW \%tc*hl
to track,
group,
and indent the table of contents entries for this document,
on the basis of their specified
.CWI outline\-level > \%<
specifications,
separating
.CWI outline\-level > \%<
groups by additional line spacing,
(having an effect similar to that of increased leading),
as controlled by the
.CW XNVS1 ,
.CW XNVS2 ,
and
.CW XNVS3
document\(hylocal strings,
at each change in
.CWI outline\-level > \%< .
.
.NH 4
.XN -S -- The \F[C]XH\-REPLACEMENT\F[] and \F[C]XN\-REPLACEMENT\F[] Macros
.LP
The default
.CW XH
and
.CW XN
macro implementations
.EM reserve
this pair of macro names,
to facilitate
.EM redefinition
of
.CW XH
and
.CW XN
behaviour respectively,
while retaining the ability to take advantage
of first\(hytime\(hyof\(hyuse infrastructure initialization logic,
which is incorporated within the respective default implementations.
.LP
It is important to understand that,
in conventional usage,
neither of these macros should ever be called directly.
Rather,
either one,
or both,
should be defined,
.EM after
loading
.CW s.tmac ,
and
.EM before
calling either
.CW XH ,
or
.CW XN
for the first time;
the defined implementations are then invoked when
.CW XH ,
or
.CW XN
are called,
respectively.
.
.LP
User\(hywritten
.CW \%XH\-REPLACEMENT
and
.CW \%XN\-REPLACEMENT
macros may implement
.EM any
desired functionality.
They are not constrained to emulation of the default
.CW XH
and
.CW XN
capabilities;
however,
it is
.EM strongly
recommended that they do so,
while adding any required extended features.
For example,
.CW spdf.tmac
defines both replacement macros thus:\**
.FS
An important consideration,
in the design of such replacement macros,
is that they will ultimately be invoked as
.CW XH ,
and
.CW XN
respectively;
thus,
they
.EM must
interpret their arguments
.EM exactly
as they would be passed to
.CW XH
and
.CW XN ,
and within the macro bodies,
.CW \%\(rs\(rs$0
will be interpreted as
.CW XH
or
.CW XN ,
as appropriate.
.FE
.DS I
.fam C
\&.de XH\-REPLACEMENT als
\&.als XN\-REPLACEMENT XH-REPLACEMENT
\&.am XH-REPLACEMENT
\&.   \(rs\(rs$0\-INIT
\&.   rm spdf:refname
\&.   als spdf:bm.define spdf:bm.basic
\&.   while d spdf:XH\(rs\(rs$1 \(rs{\(rs
\&.         spdf:XH\(rs\(rs$1 \(rs\(rs$*
\&.         shift \(rs\(rsn[spdf:argc]
\&.      \(rs}
\&.   rr spdf:argc
\&.   if \(aq\(rs\(rs$1\(aq\-\-\(aq .shift
\&.   spdf:\(rs\(rs$0.format \(rs\(rs$@
\&..
.DE
with macros
.CW \%XH\-N ,
.CW \%XH\-S ,
and
.CW \%XH\-X
defined locally,
extending the default behaviour,
such that the non\(hydefault
.CW \-N ,
.CW \-S ,
and
.CW \-X
option flags are interpreted,
(and register
.CW \%spdf:argc
is set,
to control the
.CW while
loop which does so);
it further extends the default behaviour,
by using locally defined macros,
.CW \%spdf:XH.format ,
and
.CW \%spdf:XN.format ,
(dynamically modified by
.CW \%spdf:bm.basic ,
.CW \%spdf:bm.define ,
and
.CW \%spdf:refname ),
to propagate the specified section heading text
to the PDF document outline,
in addition to reproducing the default
propagation to the document's table of contents,
by calling
.CW \%XH\-UPDATE\-TOC .
.
.NH 3
.XN -N duplex-layout -- Layout Adjustment to Support Duplex Printing
.LP
When formatting a PDF document for \%on\(hyscreen viewing,
there is no particular need to distinguish between the layouts
for \%even\(hynumbered and \%odd\(hynumbered pages; thus,
it is common to set the page offset and line length to
establish equal width pargins margins to left
and right of the displayed text;
for example, in
.CW ms :
.DS I
.fam C
.sp -\n(PDu
\&.nr PO  2.0c
\&.nr LL 17.0c
.DE
.sp -\n(PDu
will create two centimetre wide margins on both sides of the page,
when formatting for display on the equivalent of A4 paper,
in portrait orienation.
.
.LP
Conversely,
if preparing output for a \%hard\(hycopy device,
which supports duplex printing,
it may be desirable to reduce the effective page width
by a \(lqbinding allowance\(rq,
which should then be added to the \%left\(hyhand page margin width,
when formatting \%odd\(hynumbered pages,
and to the \%right\(hyhand page margin width,
when formatting \%even\(hynumbered pages.
Although
.CW ms
does not provide any standard settings,
for specification of alternating page offsets for \%odd\(hynumbered
and \%even\(hynumbered pages,
it
.EM does
implement a \%bottom\(hyof\(hypage \%trap\(hyinvoked macro,
.CW BT ,
which may be exploited to achieve the desired effect.
To illustrate this,
the preceding example,
which set equal width \%left\(hyhand and \%right\(hyhand page margins,
of two centimetres each,
when formatting for the twenty one centimetre width of A4 paper,
may be extended to accommodate the addition of an optional
specification on the formatter command line:
.QP
.fam C
groff [-T\F[]\|\FCps\h'0.2p'|\h'0.2p'-T\F[]\|\FCpdf] -m\F[]\|\FCspdf
.I options "\F[]\|\|\FC...] \c" [-
.B -duplex= <\c
.I width "> \c"
.I file \F[]\|\|\FC\c
\&...
.LP
This additional option might then be interpreted,
within the document source,
such that, if unspecified, it leaves the original layout unchanged,
but when specified, it changes the initial page offset setting
to the value of its
.CWI width > <
argument,
while leaving the line length unchanged;
this modified page offset is then propagated,
through the augmented
.CW BT
macro,
to become effective on \%odd\(hynumbered pages,
while an alternative page offset is calculated,
(as the effective value of the residual \%right\(hyhand page margin,
as it will become on \%odd\(hynumbered pages,
deduced by subtraction of the modified initial page offset,
and the specified line length,
from the inferred page width),
for use on \%even\(hynumbered pages;
a possible implementation,
for
.CW ms ,
might look like this:
.DS I
.fam C
\&.if duplex \(rs{\(rs
\&.\(rs" Prepare to format for duplex printing; first reset the initial
\&.\(rs" value of the page offset, to specify the effective value which
\&.\(rs" is to be used on odd-numbered pages.
\&.\(rs"
\&.   if \(rsB\(aq\(rs*[uplex]\(aq .nr PO \(rs*[uplex]
\&.\(rs"
\&.\(rs" Next, augment the bottom-of-page trap macro, to swap widths of
\&.\(rs" left-hand and right-hand page margins, on each transition from
\&.\(rs" odd-numbered to even-numbered page, and vice versa.
\&.\(rs"
\&.   am BT
\&.   \(rs" When advancing from an odd-numbered page, compute the value
\&.   \(rs" of the original right-hand page margin width, which will be
\&.   \(rs" used as the PO value on the following even-numbered page.
\&.   \(rs"
\&.      ie o .nr PO 2i+\(rsn[.l]u-\(rsn[PO]u-\(rsn[LL]u
\&.
\&.   \(rs" Conversely, when advancing from an even-numbered page to an
\&.   \(rs" odd-numbered page, we simply revert PO to its initial value.
\&.   \(rs"
\&.      el .nr PO \(rsn[PO]u
\&.   .
\&.\(rs}
.DE
With code,
such as the foregoing,
in place
.EM before
.CW ms
output begins,
a
.CW groff
invocation similar to:
.QP
.fam C
groff [-T\F[]\|\FCps\h'0.2p'|\h'0.2p'-T\F[]\|\FCpdf] -m\F[]\|\FCspdf
.I options "\F[]\|\|\FC...] \c" [-
-d\F[]\|\FCpaper=a4
.B -duplex=2.5c
.I file \F[]\|\|\FC\c
\&...
.LP
will set the initial
.CW PO
value to
.de VAL VAL
.CW \\$1 \|\c
.CW \\$2 \\$3
.VAL 2.5 cm ,
which, in conjunction with the initial
.CW LL
setting of
.VAL 17.0 cm ,
accounts for
.VAL 19.5 cm
of the
.VAL 21.0 cm
page width,
leaving an effective \%right\(hyhand page margin of
.VAL 1.5 cm ,
implying that
.VAL 1.0 cm
of the initial
.VAL 2.5 cm
\%left\(hyhand page margin represents the \(lqbinding allowance\(rq;
this will then alternate between \%left\(hyhand
and \%right\(hyhand page margins,
on \%odd\(hynumbered and \%even\(hynumbered pages,
respectively.
.LP
To assist in understanding the foregoing duplex printing initialization code,
some further explanation may be useful:
.QS
.sp -\n(PDu
.IP \(bu 2n
This code is intended to be interpreted at
.CW groff 's
outer processing level; it
.EM must
be defined,
within the input stream,
to ensure that is interpreted
.EM before
any output is generated.
.
.IP \(bu
Although it may appear to be a specially defined option,
.CW -duplex
is nothing more than an exploitation of
.CW groff 's
standard
.CW -d \(rq \(lq
option,
used to define a string named
.CW uplex \(rq. \(lq
Similarly,
.CW .if \& \(lq
.CW duplex \(rq
is
.CW groff 's
.CW d \(rq \(lq
logical operator,
used to determine whether,
or not,
this
.CW uplex \(rq \(lq
register has been defined;
if it has,
it's content is expected to represent a numeric expression,
which is evaluated either as a new absolute value for assignment as,
or an increment to be added to, or subtracted from the initial
.CW PO
register value.
.
.IP \(bu
Within this code,
all string and numeric references,
as they are used in
.CW PO
register assignments,
are evaluated
.EM immediately ;
this is particularly important within the augmentation of the
.CW BT
macro,
where evaluation of initial values is required,
and thus this evaluation is
.EM "deliberately not"
deferred until this \%bottom\(hyof\(hypage trap macro is executed,
(as may be more commonly expected within macro definitions).
.
.IP \(bu
The derivation of the expression,
used to set the new value of the
.CW PO
register,
when the trap is sprung at the bottom of an \%odd\(hynumbered page,
(so that it takes effect on the following \%even\(hynumbered page),
may not be obvious.
The total page width is
.EM not
represented
.EM directly ,
in any
.CW groff
register;
however,
at start up,
.CW groff
initializes the line length,
as represented by the
.CW .l \(rq \(lq
register,
to a value which is two inches less than the page width,
as defined in
.CW groff 's
.CW papersize.tmac
file;
thus,
.CW 2i+\(rsn[.l]u \(rq \(lq
yields the value of the actual page width,
and subsequent subtraction of both the user specified initial
.CW PO
and
.CW LL
values yields the effective initial width of
the \%right\(hyhand page margin;
when this is subsequently assigned as a new
.CW PO
value,
it has the effect of interchanging the \%left\(hyhand
and \%right\(hyhand margin widths,
and thus,
moves the binding allowance alternately to the \%left\(hyhand side
of \%odd\(hynumbered pages,
and to the \%right\(hyhand side of \%even\(hynumbered pages.
.sp -\n(PDu
.QE
.
.bp
.NH 1
.XN -N pdf-publishing -- The PDF Publishing Process
.LP
GNU
.CW troff ,
in common with other
.CW troff
implementations,
is a
.EM single\ pass
document formatter;
while this may support a high level of operational performance,
it does impose certain restrictions on formatting capability.
In particular,
when any computed content is to be interpolated
into the formatted output stream,
that content
.EM must
have been computed
.EM before
the point at which interpolation is to occur.\"\Z'.'\|\**
.ig
.FS
With only a single formatting pass,
an innocuous feature such as \(lqPage
.EM n
of
.EM nn \(rq
annotations within page headers,
or footers,
is unachievable;
the value of the last page number,
.EM nn ,
is unknown,
until the final page has been formatted,
yet is required
.EM before
the first such annotation is to be interpolated.
At least
.EM two
formatting passes are required,
to interpolate such annotations.
.FZ .
..
Some examples of such computed content,
which
.EM cannot
be interpolated with only a single formatting pass,
include:\(en
.
.QS
.sp -\n[PD]u
.IP \(bu 2n
Interpolation of \(lqPage
.EM n
of
.EM nn \(rq
annotations within page headers,
or footers;
the value of the
.EM last
page number,
.EM nn ,
is unknown until the final page has been formatted,
yet it is required
.EM before
the first such annotation is to be interpolated,
(typically,
when formatting the
.EM first
page).
At least
.EM two
formatting passes are required,
to interpolate such annotations.
.
.IP \(bu
Placement of a \(lqTable of Contents\(rq in its traditional location,
.EM without
the need for manual collation,
(or other \%post\(hyprocessing operation),
.EM after
completion of
.CW troff
formatting.
\%In\(hyplace formatting of a table of contents requires
knowledge of the page numbers,
to which the table of contents entries refer,
at the point of interpolation;
this requires an initial formatting pass,
to collect the references into an auxiliary file,
which can then be included at the appopriate location,
during a further formatting pass.
.
.IP \(bu
Interpolation of \%intra\(hydocument cross references,
(especially in the case of forward references),
in which the references include page numbers,
or a section numbers;
as in the case of \%in\(hyplace table of contents interpolation,
this requires one (or more) initial formatting passes,
in which reference data is collected into an auxiliary file,
for inclusion in subsequent passes.
Furthermore,
when publishing a PDF document,
in which cross references are to be represented as dynamic
.CW pdfhref
links,
the bounding box \%co\(hyordinates for such links
.EM must
be computed
.EM before
the link text is interpolated;
this computation is most conveniently performed during
preliminary formatting passes,
captured in an auxiliary file,
and subsequently reinterpreted during a final
publication formatting pass.
.QE
.sp -\n[PD]u
.LP
These single pass formatting limitations
.EM can
be mitigated,
by adoption of a
.EM multiple\ pass
formatting strategy.
To facilitate this,
for publication of PDF documents,
the
.CW groff
program suite includes the
.CW pdfroff
program;\**
.FS
The
.CW pdfroff
program was developed in tandem with the
.CW pdfmark
macros themselves,
and is the tool which has been used
to format this document itself.
Unavailable at the publication time
of early releases of this document,
later releases of
.CW groff
include support for the
.CW -T \|\c
.CW pdf
\%post\(hyprocessor,
which provides similar mitigating features.
Unlike
.CW pdfroff ,
which requires only a Bourne shell operating environment,
the
.CW -T \|\c
.CW pdf
\%back\(hyend is written in Perl,
and thus requires an operating environment with
a functional Perl interpreter;
this may limit its suitability for use
on some host platforms.
.FE
.XR pdfroff ). (
This provides a wrapper around
.CW groff
itself;
it performs multiple preliminary formatting passes,
capturing reference data by filtering it from the
.CW stderr
output stream,
and storing it to a temporary intermediate file.
This intermediate file is then reinterpreted;
along with the original document source,
during each successive pass,
either until its content stabilizes,
or it becomes apparent that stability is unlikely to be achieved,
before ultimate reinterpretation to produce the finished PDF document.
.
.LP
It may be noted that,
in the absence of a mechanism for passing collected reference data
from one formatting pass to the next,
multiple pass processing would serve no useful purpose.
Fortunately,
this is not a problem,
because
.CW groff
supports two possible mechanisms for collection,
and passing of reference data between passes:\(en
.QS
.IP \(bu 2n
The data may be recorded,
using
.CW groff 's
.CW write
request,
in an intermediate file which has been
.EM explicitly
initialized by the
.CW open ,
(or
.CW opena ),
request.
This technique requires
.CW groff
to be run in its \(lqunsafe\(rq mode,
(enabled by the
.CW -U \(rq \(lq
option),
and is not supported by traditional
.CW troff
implementations.
Neither
.CW groff 's
.CW pdfmark
macros,
nor the
.CW pdfroff
command,
depend on the use of this mechanism;
however,
users may choose to adopt it for their own purposes,
\%(e.g.\~in\(hyline interpolation of a table of contents).
.
.IP \(bu
The data may be written\*[em]either by use of the
.CW tm
request,
or a construct such as
.CW groff 's
.CW \(rsO
escape\*[em]to,
and filtered from,
the
.CW stderr
data stream.
This technique
.EM is
used by
.CW groff 's
.CW pdfmark
macros,
to report
.CW pdfhref
data,
and by
.CW pdfroff ,
to make this available in subsequent formatting passes.
.sp -\n[PD]u
.QE
.
.NH 2
.XN -N pdfroff -S -- The \F[C]pdfroff\F[] Program
.LP
Implemented as a Bourne shell script,
and thus suitable for deployment on POSIX platforms
such as GNU/Linux and contemporary Unix systems\Z','\|\**
.FS
As a Bourne shell script,
.CW pdfroff
is not
.EM natively
supported on \%MS\(hyWindows;
on this platform,
it may be supported by use of a third party application suite,
such as Cygwin or MSYS, (or other alternative),
which provides a Bourne shell command line interpreter.
.FE
.CW pdfroff
serves as a \%multi\(hypass \%front\(hyend driver for
.CW groff
itself;
as such,
it offers mitigation of those limitations of \%single\(hypass processing
which have been identified in
.pdfhref L -D pdf-publishing -A . -- the preceding introduction
.
.LP
Besides external dependencies on some standard POSIX utilities,
including
.CW cat ,
.CW grep ,
.CW sed ,
.CW awk ,
and
.CW diff ,
together with
.CW groff ,
and the Ghostscript interpreter,
for final production of PDF output,
the implementation of
.CW pdfroff
assumes only standard Bourne shell interpreter syntax,
(subject to a requirement that the shell itself
.EM must
support shell functions,
expressed in terms of the original
.EM standard
Bourne shell function syntax\*[em]i.e.\~support for interpretation of the
.CW function
keyword, as introduced by the Korn shell,
and subsequently adopted by the GNU Bourne Again Shell, is
.EM not
required).
.
.LP
Formal documentation for
.CW pdfroff
is provided in its accompanying
.ds groff-pdfmark.domain https://download-mirror.savannah.nongnu.org
.ds groff-pdfmark.uri \*[groff-pdfmark.domain]/releases/groff-pdfmark
.ds pdfroff.1.uri \*[groff-pdfmark.uri]/pdfroff.1.pdf
.pdfhref W -D \*[pdfroff.1.uri] -A \Z'.'\|\** -- \f(CRpdfroff(1)\fP Unix manual page
.FS
See
.pdfhref W -- \*[pdfroff.1.uri]
for a PDF rendition of this manual page.
.FZ .
In common with the majority of Unix manual pages,
this documentation may be found to be rather terse;
thus, a more informal discussion,
supported by examples relating to
the publication of this document itself,
may be found below.
.
.NH 3
.XN -S -N pdfroff-operation -- Principles of \F[C]pdfroff\F[] Operation
.LP
The operation of
.CW pdfroff
may be characterized as a sequence of
.EM six
distinct processing phases:\(en
.QS
.sp -\n[PD]u
.nr ITEM 0 1
.ITEMIZE
Initialization:
on commencement of
.CW pdfroff
processing,
the script sets up its shell environment,
checks for availability of each of the required
.CW cat ,
.CW grep ,
.CW sed ,
.CW awk ,
.CW groff ,
.CW diff ,
and Ghostscript helper programs,
and then parses the command line
with which it was invoked.
Options which are documented,
within the
.CW pdfroff(1)
manual page,
as being specific to
.CW pdfroff ,
are interpreted in place,
recording their effects within the shell environment;
other options,
and \%non\(hyoption arguments are collected into
a deferred options list,
and an input files list,
respectively,
to be passed on for repeated processing by
.CW groff .
.IP
In the event that standard input is
.EM explicitly
enumerated within the list of input files,
or the input files list is empty,
(in which case standard input is considered to have been
.EM implicitly
enumerated),
then standard input is read by
.CW cat ,
and redirected to a temporary file,
whence it my be replayed,
as required,
into the input stream for each subsequent
.CW groff
processing pass.
.
.ITEMIZE
Reference analysis:
following initialization,
and provided the
.CW \%\-\-no\-reference\-dictionary
option has
.EM not
been specified,
.CW pdfroff
enters a loop in which
.CW groff
is executed at least twice,
and at most three times,
(a fourth cycle of the loop may be initiated, but
.CW groff
will not be executed within it),
to compile a reference map for the PDF document,
which is to become the ultimate
.CW pdfroff
output.
During each of these reference analysis passes,
the ultimate
.CW groff
output is discarded,
while the standard error stream is captured in a temporary file,
whence reference data is filtered,
to produce a reference map which is specific to the discarded
.CW groff
output;
this will eventually become a reference map
which reflects the final state of the ultimate
.CW pdfroff
output document.
.
.IP
A further,
more comprehensive,
description of this phase of
.CW pdfroff
operation may be found in the later
.XR-NO-PREFIX pdfroff-xref .
.
.ITEMIZE
\%Front\(hymatter layout:
executed
.EM only
when the
.CW \%\-\-stylesheet=<\f[CI]\,filename\fP\/>
option
.EM has
been specified,
and the
.CW \%\-\-no\-pdf\-output
option
.EM "has not"
been specified,
within the list of arguments passed to the
.CW pdfroff
command,
in this processing phase the specified stylesheet file,
optionally augmented by additional information
which is embedded within the document input file stream,
is processed by
.CW groff ,
to produce a \*[PostScript] rendition of an optional cover sheet,
and additional (optional) \%front\(hymatter,
which is to be placed at the beginning of the
eventual PDF output document.
.
.IP
Once again,
this phase of operation will be explored further,
in the later
.XR-NO-PREFIX use-stylesheet .
.
.ITEMIZE
Table of contents generation:
this phase is
.EM always
executed,
.EM unless
either the
.CW \%\-\-no\-pdf\-output
option,
or the
.CW \%\-\-no\-toc\-relocation
option is specified,
on the
.CW pdfroff
command line,
or as a result of evaluation of hints
within the document input file stream,
this phase of operation implements
a rudimentary mechanism for collation
of the final PDF output document,
emulating the traditional
.CW groff
technique,
whereby table of contents entries
are collected into a diversion,
printed at the end of the document,
and subsequently relocated manually,
to their normal position between the \%front\(hymatter, (if any),
and the body of the document.
Methods for controlling this phase of operation
are further developed,
and explained in
.XR-NO-PREFIX toc-generation .
.
.ITEMIZE
Document body formatting:
this phase is also
.EM always
executed,
.EM unless
the
.CW \%\-\-no\-pdf\-output
option is specified;
it is responsible for formatting the body of the document,
compiling it to \*[PostScript] code,
in preparation for combination with the \%front\(hymatter,
and table of contents components from the preceding two phases,
to produce the final output document.
Further details of this phase of
.CW pdfroff
operation may be found in
.XR-NO-PREFIX body-formatting .
.
.ITEMIZE
Final PDF document production:
unless suppressed,
by specification of the
.CW \%\-\-no\-pdf\-output
option,
completion of phases 3, 4, and 5
results in the production of between one and three
intermediate output files,
each of which in in \*[PostScript] format.
Regardless of whether the final output is desired in \*[PostScript] format,
or is to be converted to PDF,
this final processing phase uses the Ghostscript \%post\(hyprocessor
to combine\**
.FS
Strictly,
if there is
.EM "only one"
intermediate output file,
and the
.CW \%\-\-emit\-ps
option is in effect,
no combination is actually required;
however,
the single intermediate output file is reprocessed through Ghostscript,
regardless.
.FE
the intermediate files,
creating a single output document file,
as described in
.XR-NO-PREFIX document-assembly .
.
.IP
On completion of this processing phase,
.EM unless
the
.CW \%\-\-keep\-temporary\-files
option is in effect,
all intermediate files\Z','\|\**
.FS
If the
.CW \%\-\-reference\-dictionary=<\f(CIfilename\fP>
option has been specified,
the reference dictionary ceases to be classified
as an intermediate file,
and is not deleted when
.CW pdfroff
terminates.
.FE
created during the earlier phases of operation,
are deleted,
and
.CW pdfroff
terminates.
.sp -\n[PD]u
.QE
.
.NH 3
.XN -S -N pdfroff-xref -- How \F[C]pdfroff\F[] Resolves Cross References
.LP
As has already been noted, in
.XR-NO-PREFIX pdfroff-operation ,
(with the proviso that this entire phase of operation will be suppressed,
if the
.CW \%\-\-no\-reference\-dictionary
option has been specified),
.CW pdfroff
performs iterative resolution of cross references
during the second phase of its operation;
a maximum of four iterations are performed,
in accordance with the following procedure:
.QS
.sp -\n[PD]u
.IP \(bu 2n
.EM Before
entering the first cycle of the iterative loop,
the three internal shell variables,
.CW WRKFILE ,
.CW REFCOPY ,
and
.CW REFFILE ,
are defined to represent the names of three working files;
the first two of these represent temporary files,
which will be named,
and created using the best practicable mechanism
afforded by the operating system,
to support secure read/write access for files created,
and used,
by shell script processes.
The third may also represent a similarly created temporary file;
however,
it may equally well become a permanent output file,
if the
.CW \%\-\-reference\-dictionary=<\f(CIfilename\fP>
option is specified,
in which case it will be named accordingly.
.
.IP \(bu
Having specified appropriate working file names,
the file identified by the
.CW REFFILE
variable is created with no content,
and that identified by
.CW REFCOPY
is created with arbitrary \%(non\(hyempty) content;
the
.CW pdfroff
process then enters the iterative reference resolving loop.
.
.IP \(bu
At the start of each cycle of the reference resolving loop,
the content of the two files identified by
.CW REFCOPY ,
and
.CW REFFILE
is compared;
if the two compare as
.EM identical ,
all references are deemed to have been resolved,
and the loop is terminated.
(Note that this loop termination condition
.EM cannot
be satisfied at commencement of the first cycle of the loop,
because the two files were initialized with \%non\(hyidentical content;
thus,
the first cycle
.EM "must always"
be completed,
and loop termination
.EM cannot
occur before the file comparison is performed
at the start of the
.EM second
cycle).
.
.IP \(bu
On commencement of a new loop cycle,
when the preceding loop termination condition has
.EM not
been satisfied,
if loop execution has entered its
.EM fourth
cycle,
a warning message is written to the
.CW stderr
stream,
and the loop is terminated
.EM without
complete resolution of references;
(this is a safety measure,
to prevent
.CW pdfroff
becoming stuck in an interminable loop).
.
.IP \(bu
When loop execution is allowed to continue into a new cycle,
the content of the file represented by the
.CW REFCOPY
variable,
whether defined by initialization,
or as carried forward from the immediately preceding cycle,
is discarded,
and the content of the corresponding file represented by the
.CW REFFILE
variable is moved into its place;
thus,
at commencement of each new reference resolution cycle,
the
.CW REFCOPY
file represents the content of the
.CW REFFILE
file,
as it stood at the end of the
.EM "immediately preceding"
cycle,
(or as initialized,
if executing the
.EM first
cycle).
.
.IP \(bu
Following the update of the
.CW REFCOPY
file content,
loop execution continues by running
.CW groff ,
processing all specified input files,
in their specified order,
to collect analytical data relating to the eventual structure
of the finished document.
The required analytical data is written to
.CW groff 's
.CW stderr
output stream,
as directed by the
.CW pdfhref
macro,
either via
.CW tm
requests,
or by exploitation of
.CW groff 's
extended
.CW \(rsO \(cq \(oq
capability,
as originally developed for use by the
.CW grohtml
processors,
to map the page \%co\(hyordinates for
.CW pdfhref
link bounding boxes;
.CW stderr
output is captured in the file designated by the
.CW WRKFILE
variable,
simply overwriting any content which was collected
during preceding loop execution cycles;
.CW groff 's
intermediate
.CW stdout
stream data is discarded,
.EM without
further processing by the
.CW grops
\%post\(hyprocessor.
.
.IP \(bu
Still within the loop execution cycle,
the file designated as
.CW WRKFILE
is reprocessed,
using a simple
.CW awk
filter to extract pertinent reference dictionary content,
redirecting it into the file named by the
.CW REFFILE
variable.
.
.IP \(bu
Although
.EM not
strictly necessary for reference resolution\Z','\|\**
.FS
Releases of
.CW pdfroff ,
\%pre\(hydating
.CW \%groff-pdfmark-20230317.1 ,
performed this hint evaluation
.EM after
completion of the reference resolution loop;
however,
to the extent that such hints
.EM may
result in propagation of dynamically generated document content
through the
.CW WRKFILE ,
which
.EM may
impact the reference resolution process,
(e,g.\& due to references embedded in a dynamically generated
table of contents),
the effect of this early evaluation may become significant.
.FE
if executing the
.EM first
cycle\*[em]and
.EM not
repeated in any subsequent cycle\*[em]of the reference resolving loop,
the working file designated by
.CW WRKFILE
is further reprocessed,
to facilitate extraction,
and evaluation,
of optional
.CW pdfroff
processing hints,
as described in
.XR-NO-PREFIX pdfroff-hints .
.
.IP \(bu
As the final step,
within each execution cycle of the reference resolving loop,
the content of the
.CW WRKFILE
is reprocessed one final time\Z','\|\**
.FS
This final step,
within the reference resolution loop,
was not performed in any release of
.CW pdfroff
\%pre\(hydating
.CW \%groff-pdfmark-20230317.1 ;
in earlier releases,
a new cycle of the loop was initiated
.EM immediately
following the update of
.CW REFFILE
content.
.FE
extracting dynamically propagated document content,
and redirecting it into designated files,
as identified by hints from the preceding step.
On completion of this final step,
execution of the reference resolving loop continues
with the commencement of a new cycle.
.QE
.sp -\n[PD]u
.LP
On normal termination of the preceding loop,
one further processing step is required to complete
the resolution of
.EM internal
cross references,
and to compile the final reference dictionary:
.QS
.sp -\n[PD]u
.IP \(bu
The
.CW WRKFILE
is processed one final time,
using a further
.CW awk
filter to extract any
.CW grohtml
records,
which have been generated due to the placement of \%zero\(hywidth markers,
inserted by the
.CW pdfhref
macro,
to mark the position of link \%\(lqhot\(hyspots\(rq,
within the document;
the
.CW awk
filter extracts the page number,
and page \%co\(hyordinate references from these records,
and reformats them as
.CW pdfhref\h'0.5n'Z \(cq \(oq
records,
which are then appended to the
.CW REFCOPY
file,
for subsequent use during the later phases of final document production.
.sp -\n[PD]u
.QE
.
.LP
Of the three working files,
created during this phase of
.CW pdfroff
processing,
the
.CW WRKFILE
is not required in any later processing phase;
the
.CW REFFILE
.EM may
be exported as a permanent
.EM external
reference dictionary,
otherwise it too is of no further use;
only the
.CW REFCOPY
file,
which incorporates
.EM both
the
.EM external ,
and the
.EM internal
constituents of the reference dictionary,
is reused in later phases of the publishing process.
Nonetheless,
all three remain in place until the
.CW pdfroff
process itself terminates,
when
.EM all
temporary files,
which the process has created,
are normally\**
.FS
Temporary files,
created by
.CW pdfroff ,
are normally deleted on process termination,
.EM unless
the
.CW \%\-\-keep\-temporary\-files
option has been specified.
.FE
deleted.
.
.NH 3
.XN -S -N pdfroff-hints -- Using \%In\(hyDocument Hints to Control\#
 \F[C]pdfroff\F[] Processing Options
.LP
Although it has been informally supported since the release of
.CW \%groff-1.22.3 ,
when the
.CW \%spdf.tmac
binding macros for
.CW ms
added the request:
.DS I
.CW ".tm pdfroff-option:set toc_relocation=enabled"
.DE
within the implementation of their
.CW TC
macro,
and
.CW pdfroff
added code to retrieve the resultant output from the reference resolving
.CW WRKFILE ,
to interpret the implied hint,
such that the effect of the
.CW \%\-\-no\-toc\-relocation
option is assumed,
.EM unless
the associated hint is actually present in the
.CW WRKFILE
data stream,
this feature was not formally implemented until the
.CW \%groff-pdfmark-20230317.1
release of
.CW pdfroff .
.
.LP
The formal implementation,
of this feature now depends on the use of the new
.CW pdfroff
macro\Z','\|\**
.FS
The
.CW pdfroff
macro is defined in the new macro file,
.CW \%pdfroff.tmac ;
this is loaded each time
.CW pdfroff
invokes
.CW groff ,
and is not intended to be used in any other context;
doing so may produce unpredictable results.
.FE
with the hint in
.CW \%spdf.tmac
now being specified as:
.DS I
.CW ".if d pdfroff .pdfroff option toc_relocation=enabled"
.DE
More generally,
usage of the
.CW pdfroff
macro,
to specify optional processing hints,
takes the form:
.DS I
.CW ".pdfroff option \%<\f(CIvariable-name\fP>=<\f(CIvalue\fP>"
.DE
with
.CWI variable-name > \%<
(currently) being restricted\**
.FS
The
.CW pdfroff
implementations,
released with
.CW \%groff-1.22.3
(and later),
and in
.CW \%groff-pdfmark
up to, and including,
.CW \%groff-pdfmark-20230317.1 ,
did
.EM not
impose this restriction;
consequently,
these earlier
.CW pdfroff
releases may be vulnerable to
an arbitrary code execution attack,
when processing untrusted document mark\(hyup.
.FE
to either of
.CW \%toc_file ,
or
.CW \%toc_relocation ,
the effects of which will be considered further,
in
.XR-NO-PREFIX toc-generation ,
or alternatively, the variable
.CW preserve_blank_pages ,
which accepts a value of
.CW toc ,
.CW body ,
or
.CW all,
to control how
.EM entirely
blank pages are processed during collation of tables of contents,
within the body of the document,
or in both of these contexts,
respectively,
thus providing an \%in\(hydocument alternative to the use of the
.CW \%\-\-no\-kill\-null\-pages
option;
.XR document-assembly ). (
.
.NH 3
.XN -S -N use-stylesheet -- Using a \F[C]pdfroff\F[] \%Style\(hySheet\#
 to Specify Document \%Front\(hyMatter
.LP
Of the six
.CW pdfroff
processing phases,
identified in
.XR-NO-PREFIX pdfroff-operation ,
.EM three
perform document formatting,
producing three separate output document components
in \*[PostScript] format,
in preparation for collation,
and final assembly of the finished document,
either as a finished \*[PostScript] document, or,
more commonly,
as a finished PDF document.
In the first of these,
which
.pdfhref F SECREF
.XR pdfroff-operation
identifies as phase no.\|3 in the enumeration of processing phases,
.CW pdfroff
applies a specified \%style\(hysheet,
in conjunction with \%meta\(hydata abstracted from
the primary document source file, or files\Z','\|\**
.FS
In this context,
\(lqprimary document source files\(rq refers to the aggregate
of all input files,
which are
.EM explicitly
specified on the
.CW pdfroff
command line,
read in the order in which they are so specified.
.FZ ,
to format the document \%front\(hymatter;
this is saved,
in its own individual (temporary) \*[PostScript] component file,
to be collated,
and subsequently assembled into the finished document,
becoming the
.EM first
component of the finished document output file.
.
.LP
As already noted,
.ds SECREF.BEGIN "in section\"
.XR pdfroff-operation ,
\%style\(hysheet processing is performed only if
.CW pdfroff
is invoked with a command,
such as that which may have been used to format this document itself,
which includes an
.EM explicit
formal specification for the
.CWI filename > \-\-stylesheet=< \(rq \%\(lq
option,
in the form:
.DS I
.fam C
pdfroff -mspdf --stylesheet=cover.ms pdfmark.ms > pdfmark.pdf
.DE
This causes
.CW pdfroff
to perform a
.EM single
.CW groff
formatting pass,
in which the input file
.CW cover.ms \(rq \(lq
is read,
in its
.EM entirety ,
followed by \%front\(hymatter specific \%meta\(hydata extracted from
.CW pdfmark.ms \(rq, \(lq
to produce an intermediate \*[PostScript] \%front\(hymatter component file,
which is saved only until it has been collated into the finished document,
as described in
.pdfhref F
.XR-NO-PREFIX document-assembly .
.
.LP
The input file,
which is nominated as the
.CWI filename > < \(rq \%\(lq
argument of the
.CWI filename > \-\-stylesheet=< \(rq \%\(lq
option,
.CW cover.ms \(rq \%(\(lq
in the example above),
.EM must
be provided by the document author.
In the simplest practicable scenario,
this could be a basic
.CW groff
input file specifying the content for
the \%front\(hymatter section of the single document,
which is the designated output of a single particular invocation of
.CW pdfroff ;
such a \%\(lqstyle\(hysheet\(rq file is simple,
and requires no additional \%meta\(hydata input from
the primary document source files,
.CW pdfmark.ms \(rq \%(\(lq
in the preceding example),
but it does suffer from the disadvantage that it is
specific to just
.EM one
document,
(and thus,
barely merits description as
a \%front\(hymatter \%\(lqstyle\(hysheet\(rq).
.
.LP
Although the simple \%front\(hymatter formatting technique,
alluded to in the previous paragraph,
is compatible with the operation of
.CW pdfroff ,
a more sophisticated,
generic \%style\(hysheet handling capability is also supported,
and may be preferred;
its principal advantage is that a single,
generic \%front\(hymatter \%style\(hysheet,
may be suitable for use with more than one document,
with \%document\(hyspecific content being specified within,
and conveyed from,
a \%meta\(hydata section within the primary document source files.
This generic \%style\(hysheet technique has been adopted
for formatting of the \%front\(hymatter of this document,
and usage examples may be drawn from its accompanying
.CW cover.ms
\%style\(hysheet file,
and the \%meta\(hydata specification within its primary
.CW pdfmark.ms
source files.
.
.LP
When designing a generic \%front\(hymatter \%style\(hysheet,
careful consideration should be given to
the interaction between the \%style\(hysheet itself,
and the \%meta\(hydata section, or sections,
which are extracted from the primary input files;
in particular,
it should be noted that the \%style\(hysheet will have been read,
in its entirety,
before
.EM any
\%meta\(hydata is encountered.
Thus,
while it is reasonable that the \%style\(hysheet should
specify any \%\(lqboiler\(hyplate\(rq text,
which is to be reproduced within the \%front\(hymatter
of any dependent document,
within the \%style\(hysheet itself,
such \%\(lqboiler\(hyplate\(rq text should normally
be encapsulated within macro, or string definitions,
so that its eventual output may be deferred until called out,
on request from within the document \%meta\(hydata.
.
.LP
The \%meta\(hydata,
which specifies the \%document\(hyspecific variant content
of the \%front\(hymatter,
and directs the formatting activity of the \%style\(hysheet,
is
.EM always
read from the primary document source files;
it is identified by its placement between a pair of macro calls,
to the nominally named\**
.FS
The macro names,
.CW CS
and
.CW CE ,
are the defaults assumed by
.CW pdfroff ,
to mark the start,
and the end of a \%meta\(hydata section,
respectively.
These defaults may be overridden,
by assignment of alternative macro names to the
.CW CS_MACRO
and
.CW CE_MACRO
environment variables respectively;
however,
unless there is some particularly compelling reason for it,
such reassignment of the macro names is strongly discouraged.
.FE
macros,
.CW CS
at the start of each \%meta\(hydata section\Z','\|\**
.FS
It is permissable for the primary document source files
to specify more than one \%meta\(hydata section,
and
.CW pdfroff
will interpret them all;
however,
the processing of multiple \%meta\(hydata sections,
and in particular the execution of more than one instance of the
.CW CE
macro,
introduces additional complexity to the design of the \%style\(hysheet,
so it is recommended that
.EM "no more than one"
such section should be specified.
.FZ ,
and
.CW CE
at the end,
thus:
.DS I
.fam C
\&.CS
\&.\(rs\(dq ... document-specific meta-data appears here ...
\&.CE
.DE
It may be observed that
.CW CS
and
.CW CE
are not defined as standard
.CW groff
macros;
thus the onus is placed on the document author,
and the \%front\(hymatter \%style\(hysheet designer,
to ensure that appropriate definitions are provided;\**
.FS
.pdfhref M spdf-CS-CE-defined
.nr spdf-CS-CE-defined \n[fn*text-num]
The
.CW spdf.tmac
macro package
.EM does
provide definitions of
.CW CS
and
.CW CE ,
with
.CW CS
having an effect equivalent to that of
.CW .ig \~\c \(lq
.CW CE \(rq,
and
.CW CE
serving as a \%do\(hynothing macro,
(albeit with the addition of diagnostic checks in both,
to ensure that
.CW CS
and
.CW CE
are correctly paired at point of use),
for marking the end of the ignored block.
The effect of these definitions is that \%meta\(hydata sections
will not be interpreted,
in any way,
during normal document processing,
which may be suitable for many documents;
however,
alternative definitions
.EM will
surely be required,
within any \%front\(hymatter \%style\(hysheet.
.FE
furthermore,
.EM different
definitions of each macro will normally be required,
when processing a \%style\(hysheet for formatting \%front\(hymatter,
and when formatting normal document content.
.
.LP
From the foregoing,
it may be inferred that the \%style\(hysheet should be implemented
as a collection of macro, string, and possibly numeric register definitions,
including, as a bare minimum, implementations of the
.CW CS
and
.CW CE
macros, which will drive the formatting of the document \%front\(hymatter,
while the document source should arrange for provision of alternative
definitions for this pair of macros,
to handle embedded \%meta\(hydata sections appropriately,
while formatting the remainder of the document.
.
.LP
In the case of normal document formatting,
other than within the \%front\(hymatter context,
appropriate handling of \%meta\(hydata may be as simple as ignoring it.
For users of
.CW groff 's
.CW ms \(rq \(lq
macros,
when these are used in conjunction with
.CW \%groff-pdfmark 's
.CW spdf.tmac
binding macros,
as previously noted in
.pdfhref L -D spdf-CS-CE-defined -P footnote\Z',' -- \*{\n[spdf-CS-CE-defined]\*}
suitable definitions for
.CW CS
and
.CW CE ,
to achieve this behaviour,
are provided,
.EM without
the need for any specific provision by the document author;
for those who do not wish to,
or simply cannot,
use
.CW spdf.tmac ,
equivalent behaviour\*[em]without error handling\*[em]may be achieved
by providing macro definitions similar to:
.DS I
.fam C
\&.de CS
\&.   ig CE
\&..
\&.de CE
\&..
.DE
Conversely,
the \%front\(hymatter \%style\(hysheet
.EM must
implement alternative definitions for
.EM both
.CW CS
and
.CW CE ,
together with definitions for any other macros which
are intended to be called out from the document's \%meta\(hydata section,
(or sections);
the aggregate effect of calling such \%style\(hysheet macros,
from the document's \%meta\(hydata sections,
beginning with the first
.CW CS
call, and ending with the
.EM last \**
.FS
While the first
.CW CS
call is trivially easy to identify,
it is the difficulty of recognizing the last
.CW CE
call which complicates the handling
multiple \%meta\(hydata sections,
and hence,
why use of multiple such sections
is not recommended.
.FE
.CW CE
call,
and ignoring all other content of the document source files,
should result in formatting, and output of
the \%front\(hymatter component of
the finished document.
Typically,
the \%style\(hysheet should define the
.CW CS
macro,
initially,
to set up the page layout controls
for formatting the cover sheet,
(if any),
and any such controls which may also apply
throughout the document's \%front\(hymatter;
for example,
a \%style\(hysheet for use in conjunction with
.CW groff 's
.CW ms
macros\*[em]based on the implementation of the \%style\(hysheet
for this document itself\*[em]might define the
.CW CS
macro to be something like:
.DS I
.fam C
\&.de CS
\&.   nr HM  0
\&.   nr PO  2.1c
\&.   nr LL 17.1c
\&.   nr HY  0
\&.   nr PS 24
\&.   nr VS 30
\&.   nop \&
\&.   sp |5.9c
\&.   CD
\&.   fam T
\&..
.DE
anticipating that the first \%meta\(hydata section encountered
will commence with a specification of text,
which is to be set as a centred 24pt title block,
in \%Times\(hyRoman font,
and which is to be placed 5.9cm below the top edge of
the first page of the \%front\(hymatter,
(which will take the form of a cover sheet).
.
.LP
To complement the
.CW CS
macro definition,
a definition for the
.CW CE
macro is also required.
Continuing the preceding example,
and again with reference to the usage within this document itself,
(which uses only one embedded \%meta\(hydata section),
the
.CW CE
macro picks up the \%front\(hymatter formatting
towards the bottom of the cover sheet,
.ne 16v+\n(PDu
adding an image, the stipulated \%front\(hycover text,
and ultimately, proceeding to incorporate a copyright assignment page:
.DS I
.fam C
\&.de CE
\&.   DE
\&.   sp |17.5c
\&.   PSPIC gnu.eps
\&.   nr PS 19
\&.   CD
\&.   fam H
\&.   tkf HR 10z 2p 20z 4p
\&.   nop \(rsH'-4z'A GNU MANUAL\(rsH'0'
\&.   DE
\&.   \(rs\(dq ... additional macro code follows here ...
\&.   \(rs\(dq ... this may, for example, add a copyright assignment page ...
\&.   \(rs\(dq ... or any other appropriate front-matter content ...
\&..
.DE
Notice that,
in this particular example,
the
.CW CS
macro ends,
leaving an open
.CW CD
display block,
(i.e.\~a standard
.CW ms
centred display);
the complementary
.CW CE
macro assumes that this will have remained open,
and immediately closes it,
.EM before
proceeding with the image output.
Any \%meta\(hydata content,
which has been specified between the opening
.CW CS
call,
and its corresponding
.CW CE ,
will be processed
.EM after
completion of the
.CW CS
call,
and
.EM before
commencement of the
.CW CE .
This may include directly specified text,
to be formatted within the open display block,
or other macro calls,
which will be executed as encountered;
if any of this \%meta\(hydata content causes
the initial centred display block to be closed,
then it is assumed that a new display block\*[em]not
necessarily centred\*[em]will have been opened,
.EM before
control passes to
.CW CE ;
any \%meta\(hydata content,
which is to be formatted
.EM after
control has been passed to
.CW CE ,
.EM must
be saved\*[em]in string space,
for example\*[em]so that it may be reinterpreted
.EM during
execution of
.CW CE .
.
.LP
An examination of the source \%mark\(hyup for this document,
which is provided in the accompanying
.CW pdfmark.ms
(primary source),
and
.CW cover.ms
\%(style\(hysheet) example files,
will reveal that the embedded \%meta\(hydata does, indeed,
depend on additional macros,
beyond the required
.CW CS
and
.CW CE
implementations.
All of these additional macros,
(including some which replace standard
.CW ms
implementations),
are defined within
.CW cover.ms ;
it may be observed that all,
.EM both
in implementation
.EM and
in usage,
comply with the requirements laid out in the preceding paragraphs.
.
.NH 3
.XN -S -N toc-generation -- How \F[C]pdfroff\F[] Collates Tables of Contents
.LP
When formatting documents with
.CW troff ,
and directing output to a \%hard\(hycopy typesetting device,
a traditional method of generating tables of contents
is to collect copies of the section headings,
and their corresponding page numbers,
in a diversion,
which is printed at the
.EM end
of the document,
whence it is then physically separated,
and
.EM manually
moved to its natural position,
immediately following the \%front\(hymatter.
This technique can be readily supported by
.CW groff ,
and remains useful for generation of
tables of contents;
although awkward to automate,
and alternative techniques,
such as those which will be described in
.XR-NO-PREFIX toc-alternatives ,
may offer better performance,
it
.EM does
serve as the default basis for table of contents collation,
used by
.CW pdfroff .
.
.LP
To facilitate separation of the formatted table of contents
from the formatted document body,
.CW pdfroff
invokes
.CW groff
.EM "twice more" ,
after completion of the reference resolution phase,
.XR pdfroff-xref ), (
to format,
and temporarily save,
.EM two
intermediate \*[PostScript] copies of the complete document;
the first of these will ultimately become the table of contents component,
to be assembled together with, and preceding the second,
which will become the main document body,
with both preceded by the \%front\(hymatter (if any),
to create the finished document,
.XR document-assembly ). (
.
.LP
As previously noted, in
.XR-NO-PREFIX pdfroff-operation ,
where it is enumerated as phase no.\|4 in the sequence of operations,
.CW pdfroff 's
default table of contents generation procedure is
.EM automatically
executed,
.EM unless
steps are taken to disable it.
It may be disabled:
.QS
.sp -\n[PD]u
.IP \(bu 2n
.EM Explicitly,
by specifying the
.CW \%\-\-no\-toc\-relocation
option,
when the
.CW pdfroff
command is invoked.
.
.IP \(bu
.EM Implicitly \Z','\|\**
.FS
Implicit control of
.CW toc_relocation
was first introduced for the
.CW \%groff-1.22.3
release;
it is unsupported in earlier releases.
.FZ ,
if no
.CW \%toc_relocation=enabled
hint is detected,
when resolving references;
(however,
it is implicitly assumed that this hint is present,
if the
.CW \%\-\-no\-reference\-dictionary
option is specified,
in which case,
no reference resolution is performed).
.QE
When
.CW pdfroff
runs
.CW groff ,
to generate a separate table of contents component,
which will eventually be combined with
the \%front\(hymatter component (if any),
and the document body component,
to assemble the document in its finished form,
it indicates the intent of this phase of operation by passing a
.CW \-rPHASE=1 \(rq \%\(lq
register assignment option.
The effect of running
.CW groff ,
in the absence of any special consideration of this
.CW PHASE
assignment,
might be expected to be
the production of a formatted copy of the complete document,
with the table of contents placed
.EM "at the end" ,
whereas,
what is required for final document assembly,
is to discard the entire document body,
which precedes the table of contents in this formatted component,
leaving
.EM only
the formatted table of contents,
as its effective residual substance.
.
.LP
To facilitate the eventual removal of document body content,
from the table of contents component,
.CW pdfroff
expects the document author to make arrangements to place
.CW groff
in its \%\(lqpen\(hyup\(rq output state,
(selected by placing a
.CW \(rsO[0]
escape in the input stream),
.EM before
the body content,
and to restore the \%\(lqpen\(hydown\(rq state,
(by complementary placement of a
.CW \(rsO[1]
escape),
at the start of the table of contents,
when the
.CW PHASE
register is defined,
with a value of one.
Such arrangements may be made,
conveniently,
within a macro package which controls the overall document format,
(for example,
.CW spdf.tmac
handles the arrangements automatically,
without any requirement for further intervention by the document author,
when the table of contents entries are specified using the
.CW XS ,
.CW XA ,
and
.CW XE
macros,
and the table of contents, itself,
is eventually output using the
.CW TC
macro).
.
.LP
Of course,
.CW pdfroff
does
.EM not
impose a requirement for the exclusive selection of
.CW spdf.tmac
as the primary macro package for document formatting.
It may be practicable to adapt
.EM any
primary macro package,
of the document author's choice,
to emulate
.CW spdf.tmac 's
behaviour;
alternatively,
if the document author deems it impractical to adapt the chosen macro package,
the required emulation may be achieved
.EM directly
within any document's input data stream.
In either case,
some basic ground rules
.EM must
be respected:
.QS
.sp -\n[PD]u
.IP \(bu 2n
Neither any macro package,
nor any document's input data stream,
is permitted to interfere with
.CW pdfroff 's
assignment of the
.CW PHASE
register;
it should
.EM never
be set,
or modified in any way,
other than as a result of direct assignment by
.CW pdfroff
itself.
.
.IP \(bu
Initialization of
.CW groff 's
output state controls
.EM must
be completed,
.EM before
commencement of the output of the first page of the formatted document;
this initialization may be achieved,
most conveniently,
by inclusion of \%mark\(hyup\**
.FS
This example \%mark\(hyup depends on the
.CW opmode.tmac
helper macro package,
which is distributed as an integral component of
.CW \%groff-pdfmark-20230317.1 ,
and later releases;
it is backwardly compatible with earlier
.CW groff
releases of
.CW pdfroff .
.FE
similar to:
.DS I
.sp -\n[PD]u
.fam C
\&.mso opmode.tmac
\&.
\&.nr PDF-TOC-ONLY   1
\&.nr PDF-BODY-TEXT  2
\&.
\&.OP \(rsn[PDF-BODY-TEXT]
.DE
.sp -\n[PD]u
early in the document input data stream,
or better still,
within a macro package,
such that it will be executed soon after the start of
.CW groff
processing,
and in particular,
.EM before
any output is generated;
this ensures that
.CW groff
starts in the correct output state,
with respect to
.CW pdfroff 's
.CW PHASE
register,
for collection of table of contents data,
within its own diversion,
based on \%mark\(hyup within the body of the input data stream.
.
.IP \(bu
When the input data stream has been fully processed,
the table of contents diversion should be closed, and,
in preparation for flushing it to the output,
a new page should be started,
and the output state should be adjusted,
by execution of:
.DS I
.fam C
.sp -\n[PD]u
\&.OP \(rsn[PDF-TOC-ONLY]
.DE
.sp -\n[PD]u
after which,
the substance of the table of contents diversion should be written,
together with any desired page headings,
and footers,
to the document output stream.
For convenience,
consideration should be given to encapsulation of this entire sequence of steps,
which is required to prepare for,
and to complete the output of the table of contents,
in a macro which is analogous to
.CW spdf.tmac 's
.CW TC ;
this may then simply be invoked at the end of the input data stream.
Such consideration is particularly recommended
when writing a primary macro package,
or a binding macro package,
which is intended to be used in conjunction with
.CW pdfroff .
.QE
The effect of the
.CW OP
macro,
as used in the foregoing,
is to insert a
.CW \(rsO[1]
escape into the input stream,
when the value of its single argument is equal to the value of
.CW pdfroff 's
.CW PHASE
register\Z','\|\**
.FS
If the
.CW PHASE
register is not defined,
the
.CW OP
macro simply records an effective output state
.CW 1 , of\~
in
.CW OPMODE ,
but
.EM "does not"
insert any
.CW \(rsO \~\c
escape sequence,
into the input data stream,
and thus,
does not change
.CW groff 's
actual output state.
.FZ ,
and a
.CW \(rsO[0]
escape otherwise,
while recording the effective output state in a register called
.CW OPMODE .
Thus,
within
.CW pdfroff 's
table of contents collation phase,
the initial
.CW OP
invocation,
with an argument value which is equivalent
.CW 2 , to\~
generates the required
.CW \(rsO[0]
escape\*[em]which does not actually eliminate the document body,
but causes
.CW groff
to emit one
.EM entirely
blank page for each page of body content\*[em]while the second invocation,
with an argument value equivalent
.CW 1 , to\~
inserts a
.CW \(rsO[1]
escape,
resulting in output of the formatted table of contents;
the initial blank pages are subsequently removed during final document assembly,
.XR document-assembly ). (
.
.NH 3
.XN -S -N body-formatting -- How \F[C]pdfroff\F[] Formats a Document Body
.LP
To format the body of any document,
.CW pdfroff
repeats the default
.CW groff
process that it uses for collation of a table of contents,
(as described in
.XR-NO-PREFIX toc-generation ),
.EM except
that the
.CW PHASE
register is set to a value of two,
(rather than the value of one,
which is used when generating a table of contents),
by the assignment
.CW -rPHASE=2 \(rq, \%\(lq
which is passed as a command line argument when
.CW pdfroff
invokes
.CW groff ,
and the ensuing
.CW groff
output is written to a differently named intermediate output file.
The effect of changing the
.CW PHASE
register assignment,
assuming that the
.CW OPMODE
controls are implemented,
and managed as previously
.pdfhref F SECREF
.ds SECREF.BEGIN "described in section\"
.XR toc-generation ,
.pdfhref F
is to place
.CW groff
in its \%\(lqpen\(hydown\(rq output state
when formatting the document body,
and then to switch to the \%\(lqpen\(hyup\(rq state,
only if processing ultimately progresses to the output of
an appended table of contents.
.
.LP
An important consideration,
for authors writing documents to be formatted by
.CW pdfroff ,
or for those implementing macro packages to facilitate this,
is that the default formatting process expects
a single input data stream,
in which the document body will be processed
.EM first ,
and a table of contents will be appended,
.EM "at the end" .
This input data stream will be read
.EM twice ,
to produce
.EM two
separate intermediate output files,
which will eventually be conjoined,
.XR document-assembly ), (
to produce
.EM "a single"
final output document file.
.
.LP
If the document author,
or the macro package implementor,
neglects the interpretation of
.CW pdfroff 's
.CW PHASE
register assignment,
or the implementation of the associated
.CW OPMODE
handling
.pdfhref F SECREF
.ds SECREF.BEGIN "described in section\"
.XR toc-generation ,
the two intermediate output files will exhibit
.EM identical
content,
and their conjunction will result in a finished document
which contains
.EM two
copies of the formatted document body,
each of which will be followed by a copy of
the formatted table of contents.
.
.LP
.tkf \n[.fn] 10 -0.01p 12 -0.01p
Conversely,
when
.CW pdfroff 's
.CW PHASE
register interpretation,
and
.CW OPMODE
handling
.EM have
been appropriately addressed,
.tkf \n[.fn] 10 0 12 0
the intermediate output with
.CW PHASE=1 ,
as already noted in
.XR toc-generation ,
.pdfhref F
will comprise a sequence of entirely blank pages,
followed by the formatted table contents,
while that for
.CW PHASE=2
will contain the desired formatted document body,
which will then be followed by a further sequence of blank pages,
with one corresponding to each and every \%non\(hyblank page of
the table of contents.
Conjunction of this pair of intermediate files
will result in the desired content,
in the final document file,
but it will be padded by a (possibly very large) number of blank pages;
these blank pages are normally unwanted;
they will be removed in the final document assembly process,
.XR document-assembly ). (
.
.LP
An interesting possibility,
when formatting a document body,
is that, even when the input stream has been configured
to generate the document body output,
with appended table of contents,
and a sequence of blank pages,
corresponding to the pages of the document body,
.EM is
required at the beginning of the table of contents intermediate file,
it is
.EM not
actually necessary to emit the sequence of appended blank pages
which would correspond to the pages of the table of contents,
when generating the document body intermediate file.
In fact,
it is fairly straightforward to test the effective value of the
.CW PHASE
register,
and to omit the formatting of the appended table of contents,
when the register value is two, or greater.
This optimization\**
.FS
These examples assume that the table of contents
should
.EM always
be output,
.EM except
within the scope of
.CW pdfroff 's
document body formatting procedure,
when they may be optimized out.
Notice that there is no check for existence of the
.CW PHASE
register,
before testing its value,
(as might be considered desirable to avoid
.CW groff
warnings);
no such check is necessary,
because
.CW pdfroff
.EM guarantees
that the register will have been defined,
in
.EM "any context"
in which a \%user\(hyvisible warning could be raised,
so checking for
.CW pdfroff
alone is sufficient.
.FE
may be performed,
either within,
and at the end of,
the document source:
.DS I
.fam C
.sp -\n[PD]u
\&.ie d pdfroff \(rs{\(rs
\&.   ie \(rsn[PHASE]>1 .nr DO-TOC 1
\&.   el .nr DO-TOC 0
\&.\(rs}
\&.el .nr DO-TOC 1
\&.if \(rsn[DO-TOC] \(rs{\(rs
\&.\(rs\(dq ... code to emit formatted table of contents goes here ...
\&.\(rs}
.DE
.sp -\n[PD]u
or, perhaps more conveniently,
within a table of contents formatting macro,
such as, for example, in
.CW spdf.tmac 's
implementation of its
.CW TC \~macro:
.DS I
.fam C
.sp -\n[PD]u
\&.de TC
\&.if d pdfroff .if \(rs\(rsn[PHASE]>1 .return
\&.\(rs\(dq ... code to emit formatted table of contents goes here ...
\&..
.DE
.sp -\n[PD]u
which then requires only that the document source ends by calling this
.CW TC
macro.
.
.NH 3
.XN -S -N document-assembly -- How \F[C]pdfroff\F[] Assembles a Finished Document
.LP
After
.CW pdfroff
has completed each of the processing phases,
enumerated as phase\~no.\|1 to phase\~no.\|5 in
.XR-NO-PREFIX pdfroff-operation ,
.EM "at least one" ,
and
.EM "at most three"
intermediate \*[PostScript] output files will have been created,
(in addition to the temporary files designated by the
.CW WRKFILE ,
.CW REFFILE ,
and
.CW REFCOPY
shell variables).
If only one intermediate output file is created, it
.EM must
be the document body component;
if more than one such file is created, one
.EM must
be the document body component,
while any others may be
.EM "either one"
of, or
.EM both
of a \%front\(hymatter component,
and a table of contents component.
In this final phase of
.CW pdfroff
processing,
the entire complement of created intermediate output files is conjoined,
in the order:
.QS
.sp -\n[PD]u
.IP \(bu 2n
\%Front\(hymatter component (if present);
.IP \(bu
Table of contents component (if present);
.IP \(bu
Document body component
.QE
to assemble the finished output document,
either merging all component content into a single \*[PostScript] document,
(if the
.CW \%\-\-emit\-ps
option has been specified),
or normally,
merging all content,
and simultaneously converting to PDF.
.
.LP
Depending on the particular complement
of intermediate output files which have been created,
document assembly proceeds as follows:
.QS
.sp -\n[PD]u
.IP \(bu 2n
If a \%front\(hymatter intermediate output file has been created,
its content is simply copied, without change,
to the beginning of the final output file.
.
.IP \(bu
As has been noted previously, in
.XR-NO-PREFIX toc-generation ,
if a table of contents intermediate output file has been created,
it
.EM will
contain the formatted table of contents,
but this will be preceded by a sequence of blank pages,
with one blank page for each page in the document body;
these blank pages will (usually) not be wanted in the finished document,
so, before merging this intermediate file content,
it is passed through a
.CW sed
filter,
to remove them;
the residual comtent is then copied into the final output file,
either following the \%front\(hymatter, if present,
or otherwise, at its beginning.
.
.IP \(bu
Finally,
the content of the document body is read
from its respective intermediate output file,
and merged into the final output file,
following any content which had previously been merged
from \%front\(hymatter and table of contents intermediate output files;
as in the case of table of contents intermediate output,
this document body output is also passed, by default,
through the same blank page removal
.CW sed
filter.
.QE
It may be observed that,
by default,
.CW pdfroff
will filter
.EM both
the table of contents intermediate output, if any,
and the document body intermediate output,
to remove blank pages.
While the intent of this is to discard
.EM phantom
blank pages,
which precede the actual table of contents,
and which follow the document body,
it must be understood that it will actually remove
.EM all
blank pages\*[em]\c
.EM both
those which promote this intent,
.EM and
any others which may appear
.EM within
the table of contents,
and the document body.
This may, or may not, be desirable behaviour\*[em]it probably
.EM is ,
within the table of contents,
but is less so within the document body,
especially if the trailing blank pages,
resulting from \%\(lqpen\(hyup\(rq formatting
of an appended table of contents,
have been optimized out,
as suggested in
.XR-NO-PREFIX body-formatting .
.
.LP
Some control of blank page removal
may be achieved by specification of the
.CW \%\-\-no\-kill\-null\-pages
option\*[em]or
.CW \%\-\-no\-kill\-null\-pages[=< \c
.CWI whence >] \& ,
from the
.CW \%groff-pdfmark-20230406.1
release onwards\*[em]on the
.CW pdfroff
command line, or alternatively,
and once again, only from the release of
.CW \%groff-pdfmark-20230406.1
onwards,
by use of the
.CW \%preserve_blank_pages=< \c
.CWI whence >
\%in\(hydocument hint.
When supported, the
.CWI whence > <
argument may take a value of
.CW toc \(rq, \(lq
.CW body \(rq, \(lq
or
.CW all \(rq, \(lq
with
.CW all \(rq \(lq
being the default,
and equivalent to the original behaviour;
its effect is to suppress removal of
.EM all
blank pages originating from the
table of contents intermediate output file,
.EM and
from the document body intermediate output,
which is probably not the desired effect.
More useful behaviour may be to retain the default
removal of blank pages originating from
the table of contents intermediate output,
while suppressing it for those originating within the document body;
this may be achieved by invoking
.CW pdfroff
with a command such as:
.QS
.CW "pdfroff --no-kill-blank-pages=body ..."
.QE
or by including the equivalent \%in\(hydocument hint:
.QS
.CW ".pdfroff option preserve_blank_pages=body"
.QE
within the document source file,
(perhaps making it conditional on some appropriate condition,
such as selection of a duplex printing configuration,
for example).
.
.NH 2
.XN -S -N output-prep -- Preparing Documents for On\(hyScreen Reading\#
 versus Hard\(hyCopy Printing
.LP
When preparing a PDF document,
which is to be optimized for reading on a video display screen,
it is reasonable to make formatting choices such as:
.QS
.sp -\n[PD]u
.IP \(bu 2n
Set up of the page layout,
such that the \%left\(hyhand and \%right\(hyhand margins are of equal width,
and remain unchanged between formatting of recto \%(odd\(hynumbered) pages,
and verso \%(even\(hynumbered) pages;
such a layout may be conveniently,
and simply,
achieved by assignment of suitable,
and invariant,
values for
.CW groff 's
page offset,
and line length settings.
.
.IP \(bu
Elimination of
.EM entirely
blank pages.
These,
(especially in the case of blank verso pages),
may be inserted when formatting for printing
on a \%duplex\(hycapable \%hard\(hycopy output device,
to ensure that new chapters,
or major sections,
commence on a new recto page;
however,
they serve little purpose,
and can be distracting,
when reading a document \%on\(hyscreen.
The elimination of such blank pages is performed
.EM automatically ,
by
.CW pdfroff ,
.EM unless
this capability is disabled
.EM explicitly ,
by the user.
.QE
.
Conversely,
when preparing a PDF document
which is suitable for subsequent printing on a \%hard\(hycopy
typesetting device,
different formatting choices may be more appropriate;
for example:
.QS
.sp -\n[PD]u
.IP \(bu 2n
A wider page margin may be desired,
on whichever side of each page will lie adjacent to the spine,
to provide a \(lqbinding allowance\(rq,
when the document is to be bound;
any such \(lqbinding allowance\(rq should be
.EM "added to"
the nominal page offset,
on recto pages,
and
.EM "deducted from"
it,
on verso pages.
.
.IP \(bu
When the typesetting device supports
.EM duplex
printing,
(i.e. printing on
.EM both
recto and verso pages),
.EM and
this mode of printing is to be used,
then any blank (normally verso) pages which have been inserted,
to force the following content to appear on a particular side
of the printed page,
.EM must
be preserved within the PDF document structure.
When using
.CW pdfroff ,
to format the PDF document,
such blank pages will normally be eliminated;
the
.CW \%--no-kill-null-pages
option,
or its corresponding
.CW \%preserve_blank_pages
\%in\(hydocument hint
must be specified,
to override
.CW pdfroff 's
default behaviour.
.sp -\n[PD]u
.QE
.
.NH 3
.XN -S -N on-screen-layout -- Establishing a Page Layout for \%On\(hyScreen Reading
.LP
When preparing a PDF document,
which is ultimately intended for reading on a video display screen,
the page layout will normally be characterized by arrangement of text
between equal width margins,
on
.EM both
\%left\(hyhand and \%right\(hyhand sides of the page;
these margins will,
typically,
be defined at the start of document processing,
and, aside from local internal variations in indentation,
will remain unchanged throughout the document,
without regard to whether any individual page would be printed
as a recto \%(odd\(hynumbered) page,
or a verso \%(even\(hynumbered) page.
.
.LP
The mechanics of setting the \%left\(hyhand and \%right\(hyhand page margins
depend on the user's choice,
if any,
of document formatting macro package.
Fundamentally,
the \%left\(hyhand margin is equivalent to whatever page offset
may have been set,
by invocation of
.CW troff 's
.CW .po \(rq \(lq
request,
the text width is set by invocation of
.CW troff 's
.CW .ll \(rq \(lq
request,
(with an alternative width for \%three\(hypart titles,
set by the
.CW .lt \(rq \(lq
request),
and the \%right\(hyhand margin is simply
the remnant of the physical page width\Z','\|\**
.FS
Traditional
.CW troff
provides no \%user\(hyvisible indication of the physical page width.
GNU
.CW troff
.EM does
define a page width,
at \%start\(hyup,
based on standard paper size specifications,
but it does not make this
.EM directly
visible to the user;
it may be
.EM indirectly
inferred,
.EM immediately
after \%start\(hyup,
.EM before
any subsequent
.CW .ll \(rq \(lq
request has been invoked,
by adding two inches to the initial value stored in the
.CW .l \(rq \(lq
register.
.FZ ,
after deduction of the page offset and text width.
Typically,
users do not invoke these fundamental
.CW troff
requests directly,
but rely on the features of a higher level macro package
to invoke them when appropriate,
to apply \%user\(hydefined settings,
which are established in numeric registers;
for example,
the
.CW ms
macro package will invoke the
.CW .po \(rq \(lq
request,
to achieve the effect of
.DS I
.CW .po\ \(rsn(POu
.DE
at the start of every new page,
thus setting the effective \%left\(hyhand margin for the page,
to whatever value the user has assigned to the
.CW PO
register;
similarly,
it will invoke the
.CW .ll \(rq \(lq
request,
with the effect of
.DS I
.CW .ll\ \(rsn(LLu
.DE
on each paragraph transition,
(in conjunction with other local adjustments,
based on the settings of other layout control registers)\Z','\|\**
.FS
Details of all page layout control registers,
as used by the
.CW ms
macros,
may be found in the
.pdfhref W -D https://manned.org/groff_ms.7 -- \F[C]groff_ms(7)\F[]
manual page.
Similar details,
relating to other macro packages,
should be available in their respective documentation.
.FZ ,
to maintain the fundamental text width at whatever value
the user has assigned to the
.CW LL
register.
.
.LP
It may be observed,
from the foregoing,
that setting up an overall page layout,
which is suitable for \%on\(hyscreen reading,
is normally a \%one\(hytime process;
once established,
at the start of the document formatting process,
other than when making localized temporary indentation adjustments,
there is usually no need to change it.
.
.NH 3
.XN -S -N printer-layout -- Establishing a Page Layout for \%Hard\(hyCopy Typesetting
.LP
For the most part,
when it is ultimately intended that a PDF document will be printed,
on some \%hard\(hycopy typesetting device,
the mechanics of establishing the overall page layout are
identical to those which have been described already, in
.XR-NO-PREFIX on-screen-layout ;
a fundamental difference arises,
only in the case where it is desired to add a \(lqbinding\ allowance\(rq
to either the \%left\(hyhand,
or the \%right\(hyhand page margin.
.
.LP
When such a \(lqbinding\ allowance\(rq is desired,
the adjustment to the \%set\(hyup of the page layout may be trivial,
or relatively more complex,
depending on whether:
.QS
.sp -\n[PD]u
.IP \(bu 2n
The ultimate output is to be printed \%one\(hysided,
(typically as \%recto\(hyonly pages, each with blank verso):
in this case,
the \(lqbinding\ allowance\(rq will be added to
the \%left\(hyhand page margin
.EM only ,
requiring no more than a trivial increment,
equivalent to the width of the \(lqbinding\ allowance\(rq,
in the initial assignment of the page offset,
(which
.EM automatically
results in a corresponding reduction in the width of
the \%right\(hyhand page margin);
as in the case of the \%on\(hyscreen layout,
this \%one\(hysided printing layout requires no subsequent adjustment.
.
.IP \(bu
The ultimate output is destined for \%two\(hysided printing,
(on
.EM both
recto
.EM and
verso pages):
in this case,
the \%set\(hyup of the page layout becomes relatively more complex,
because the \(lqbinding\ allowance\(rq must be
.EM "added to"
the underlying page offset,
to set a wider \%left\(hyhand margin on recto pages,
but must be
.EM "deducted from"
it,
to set a correspondingly narrower \%left\(hyhand margin on verso pages;
consequently,
the page offset must be adjusted,
at the start of
.EM every
page,
to achieve the desired alternation of \%left\(hyhand
and \%right\(hyhand margin widths.
.IP
Neither traditional
.CW troff ,
nor
.CW groff ,
provide a standard method for configuration of
the required margin width alternation;
it is achievable,
however,
through page traps,
which must be appropriately specified by the user.
.rn PDFHREF.SECTREF XX
.ds PDFHREF.SECTREF "Section \\$1\"
.XR-NO-PREFIX duplex-layout
.rn XX PDFHREF.SECTREF
provides an illustration of how this may be implemented,
when using the
.CW ms
macros,
by exploiting the existing \%bottom\(hyof\(hypage trap
to adjust the
.CW PO
register setting at the
.EM bottom
of every page,
such that it will take effect,
to adjust the page offset as required,
at the start of the
.EM following
new page;
this technique should be adaptable for use with other macro packages,
or even within a \%user\(hydefined trap,
should the user choose to rely on basic
.CW groff
requests alone.
.sp -\n[PD]u
.QE
.
.NH 3
.XN -N force-recto-verso -- Ensuring that Content is Printed\#
 on a Particular Side of the Page
.LP
When printing a document,
in a duplex format,
style conventions may dictate that certain sections,
such as tables of contents,
body content,
and also any appendices,
any collected bibliographic references,
and any index entries,
which may be present,
should
.EM always
begin on a particular side of the page,
(usually the recto);
such conventions may,
or may not,
be extended to require that indiviual chapter headings,
or major section headings,
should also be placed on a particular side (again,
usually the recto)
of a new page.
When such conventions are applied,
the usual practice is to insert a page break
.EM immediately
before the content which is to be so placed;
however,
if the content which immediately precedes this page break
is already being printed on the side of the page,
on which it is desired to place the following content,
then one page break will not suffice;
it will be necessary to add a second,
so as to insert a blank page,
and thus ensure that printing resumes on the appropriate side
of the next available new page.
.
.LP
.float begin
As we've already seen, in
.XR-NO-PREFIX duplex-layout ,
.CW groff 's
.CW ".if\h'\w!\0!u/2u'o" \(rq \%\(lq
request may be used to detect
when document output is currently being directed to a recto page,
(and conversely, the
.CW ".if\h'\w!\0!u/2u'e" \(rq \%\(lq
request may be used to detect output to a verso page);
thus, we may define specialized page break macros similar to:
.DS I
.fam C
\&.de NEW-RECTO-PAGE
\&.\(rs" Insert a page break, resuming output at the top of the
\&.\(rs" next available new recto (i.e. odd numbered) page.
\&.\(rs"
\&.   ADVANCE-TO-NEW-PAGE o
\&..
.DE
and:
.DS I
.fam C
\&.de NEW-VERSO-PAGE
\&.\(rs" Insert a page break, resuming output at the top of the
\&.\(rs" next available new verso (i.e. even numbered) page.
\&.\(rs"
\&.   ADVANCE-TO-NEW-PAGE e
\&..
.DE
.float end
.float needs 1v+\n(.Vu
.float release
.float begin
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the passed argument, (which MUST be either
\&.\(rs" of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.   if \(rs\(rs$1 .bp  \(rs" need to skip an entire page
\&.   bp \h'\w!\(rs\(rs$1 .bp!u'  \(rs" advance to desired new page
\&..
.DE
.float end
Each of these page break macros simply delegates its operation
to the generalized
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
helper macro, passing either
.CW groff 's
.CW o \(rq, \%\(lq
or
.CW e \(rq \%\(lq
page number property comparison operator,
as argument,
to specify whether output should resume on a new recto page,
(odd numbered page),
or a new verso page, (even numbered page), respectively.
.float needs 1v+\n(.Vu
A tentative, and perhaps a na\(:ively simplistic,
implementation for such a generalized
helper macro might be defined as simply as:
.float release
.
Depending of the behaviour of any suite of macros,
(whether standard, or \%user\(hydefined),
which has been chosen to control the document layout,
this simplistic
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro implementation may require some refinement.
For example,
when the
.CW ms
macros are being used,
this na\(:ively simplistic implementation will
.EM not
result in the intervening verso page being skipped over,
when the
.CW NEW-RECTO-PAGE \(rq \%\(lq
macro is invoked while
.CW groff
is already processing output which is to be printed,
or otherwise displayed,
on a recto page.
.
.LP
It may seem surprising that the preceding trivial implementation of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro should fail,
in the manner described,
when used in conjunction with the
.CW ms
macros, under the circumstances as described;
however,
given a basic understanding of the operation of page transition traps, in
.CW ms ,
the failure may be anticipated,
and moreover, it is readily explained:
.QS
.sp -\n[PD]u
.IP \(bu 2n
When the
.CW NEW-RECTO-PAGE \(rq \%\(lq
macro is invoked,
during processing of a recto page,
interpretation is redirected to the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro, with the
.CW o \(rq \%\(lq
argument specified.
.
.IP \(bu
On entering the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro, the expression
.CW .if\h'\w!0!u/5u*3u'\(rs\(rs$1\h'\w!0!u/5u*3u'.bp \(rq \%\(lq
is interpreted as
.CW .if\h'\w!0!u/5u*3u'o\h'\w!0!u/5u*3u'.bp \(rq; \%\(lq
since this is being evaluated within
the processing context of a recto page,
(which has an odd page number),
the
.CW .if\h'\w!0!u/5u*3u'o \(rq \%\(lq
condition evaluates as
.CW true \(rq, \%\(lq
so the conditional
.CW .bp \(rq \%\(lq
request
.EM is
invoked.
.
.IP \(bu
Invocation of the conditional
.CW .bp \(rq \%\(lq
request causes the output position to advance to
the bottom of the current recto page,
(thus invoking any intervening traps,
from the initial output position down to, and including,
the \%bottom\(hyof\(hypage trap),
and thence onwards to the top of the following verso page,
whence
.CW ms
arranges for activation of
.CW groff 's \%
\%\(lqno\(hyspace\(rq mode.
.
.IP \(bu
Following invocation of the conditional
.CW .bp \(rq \%\(lq
request, the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro then issues a further
.EM unconditional
.CW .bp \(rq \%\(lq
request,
with the intent of advancing the output position
further towards the bottom of the new verso page,
and beyond,
ultimately placing it at the top of
the immediately following recto page.
Unfortunately,
by the time this unconditional
.CW .bp \(rq \%\(lq
request is issued,
\%\(lqno\(hyspace\(rq mode has already been activated,
and consequently, since this
.CW .bp \(rq \%\(lq
request is issued
.EM without
any explicitly specified new page number argument,
it is ignored\Z','\|\**
.FS
This is
.EM not
a defect in the
.CW ms
macros;
rather, it is a natural consequence of the design decision
to activate \%\(lqno\(hyspace\(rq mode at the top of each new
\*[em page a] perfectly legitimate design choice,
which is intended to eliminate the output of
any block of redundant vertical space,
immediately following a transition to a new page.
Furthermore,
although this issue has been identified in the context
of interoperation of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro, as defined, and the
.CW ms
macros,
similar behaviour will be observed in
.EM any
context in which \%\(lqno\(hyspace\(rq mode is activated,
following page transitions.
.FE
and the output position remains at the top of the verso page,
whence normal output will eventually resume.
.QE
.
Having established that the preceding,
na\(:ively simplistic implementation of an
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro may be vulnerable to failure,
when \%\(lqno\(hyspace\(rq mode may become active during its execution,
(and furthermore, having established that this vulnerability is
.EM not
specific to use in conjunction with the
.CW ms
macros, or indeed with
.EM any
particular macro suite),
it behooves us to refine the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro implementation,
in order to eliminate the vulnerability.
To achieve this,
we might consider refinements such as:
.QS
.sp -\n[PD]u
.IP \(bu 2n
Following invocation of the conditional
.CW .bp \(rq \%\(lq
request, which implements the first of two page advances,
in any case when two are required,
insert an explicit
.CW .rs \(rq \%\(lq
request, to explicitly deactivate \%\(lqno\(hyspace\(rq mode
.EM before
the second
.CW .bp \(rq \%\(lq
request is invoked,
thus ensuring that this is
.EM not
ignored.
.
.IP \(bu
As an alternative to the preceding option,
.EM implicitly
deactivate \%\(lqno\(hyspace\(rq mode,
following the first of the two
.CW .bp \(rq \%\(lq
request invocations,
and prior to the second,
by writing some arbitrary,
but invisible output to the intermediate output page;
implicitly, this has the same effect as insertion of the
.CW .rs \(rq \%\(lq
request, but it is less elegant, more cumbersome to implement,
and its intent is less obvious,
so it may be a less favourable method
of achieving the desired effect.
.
.IP \(bu
Rather than attempting to manipulate \%\(lqno\(hyspace\(rq mode,
as both of the preceding options do,
modify the form of the second,
(i.e.\h'0.5n'the
.EM unconditional ,
or maybe even both), of the internal
.CW .bp \(rq \%\(lq
requests, such that the form becomes
.CW .bp\h'\w!0!u/5u*3u' \c \%\(lq
.CWI page-number > < \(rq;
unlike the form of the
.CW .bp \(rq \%\(lq
request without arguments,
this form,
with the
.CWI page-number > < \(rq \%\(lq
argument, is
.EM not
ignored, whether \%\(lqno\(hyspace\(rq mode is active, or not.
.QE
.
Any one of these modifications will offer an effective solution
to the identified \%\(lqno\(hyspace\(rq mode failure of our original
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro implementation;
of the three, the first is the most convenient,
and perhaps also the most obvious to adopt;
the second would require a more cumbersome,
yet a less obvious implementation,
but it offers no particular advantage over the first,
so it probably merits no further consideration.
Conversely,
although it will necessitate a significantly more complex
implementation\*[em]keeping track of suitable page numbers,
for use as arguments to the
.CW .bp\h'\w!0!u/5u*3u' \c \%\(lq
.CWI page-number > < \(rq
requests,
may present something of a \*[em challenge the]
third option for refinement of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro implementation may offer some behavioural advantages,
over the features accorded by the simpler first option;
we will explore some of these potential advantages,
with particular reference to document formatting using the
.CW ms
macros, in
.XR-NO-PREFIX ms-page-advance .
.
.LP
.KS
Notwithstanding that adoption of the third of the preceding
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro refinement options may be advantageous,
the simplicity and elegance of the first option
may still offer a compelling reason for considering it.
The refined implementation is straightforward:
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the passed argument, (which MUST be either
\&.\(rs" of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.   if \(rs\(rs$1 \(rs{\(rs
\&.   \(rs" Current page faces as does the desired output target,
\&.   \(rs" so we need to skip an entire opposing page.
\&.   \(rs"
\&.      bp  \(rs" advance to new opposing page
\&.      rs  \(rs" get out of "no-space" mode
\&.   \(rs}
\&.   bp     \(rs" advance to desired new page
\&..
.DE
and, with this modified implementation in place, the original
.CW NEW-RECTO-PAGE \(rq \%\(lq
and
.CW NEW-VERSO-PAGE \(rq \%\(lq
macros will each introduce either one or two page breaks,
as required, to resume output on the respectively appropriate side
of the next available, and suitably facing, new page.
.KE
.
.NH 4
.XN -S -N ms-page-advance -- Recto\(hyVerso Page Break Handling\#
 when Using the \F[C]ms\F[] Macros
.LP
Provided that the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro refinement, to correctly handle \%\(lqno\(hyspace\(rq mode effects,
has been incorporated,
the simple
.CW NEW-RECTO-PAGE \(rq \%\(lq
and
.CW NEW-VERSO-PAGE \(rq \%\(lq
macros, as developed in
.pdfhref L -D force-recto-verso -A , -- the preceding section
.EM will
correctly introduce the appropriate number of page breaks,
such that output resumes on the next available new recto page,
or new verso page, respectively;
why then, might we wish to consider adoption
of a more complex technique for introduction of such page breaks?
.
.LP
One reason why we may wish to adopt the more complex technique is that,
when two page breaks are required to advance to the appropiately facing page,
any traps which are specified on the intervening page
.EM will
be processed,
as the output position advances down that page;
when such traps result in the output of page headers, or footers, or both,
as will be the norm when formatting with a macro suite such as
.CW ms ,
these headers, or footers, or both
.EM will
be printed on the otherwise blank page.
Thus, this intervening page will
.EM not
be
.EM completely
blank, so will
.EM not
be identified as a candidate for
.CW pdfroff 's
blank page removal procedure;
it may become a distraction when formatting for \%on\(hyscreen viewing.
.
.LP
.float begin
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the passed argument, (which MUST be either
\&.\(rs" of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.   nr \(rs\(rs$0.% \(rs\(rsn%    \(rs" save current page number
\&.   if \(rs\(rs$1 \(rs{\(rs
\&.   \(rs" Current page faces as does the desired output target,
\&.   \(rs" so we need to skip an entire opposing page.
\&.   \(rs"
\&.      nr \(rs\(rs$0.% +1   \(rs" update to skipped page number
\&.      bp 1 \h'\w!\0!u*8u'  \(rs" skip, numbering as page one
\&.   \(rs}
\&.   bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
\&.   rr \(rs\(rs$0.% \h'\w!\0!u*7u' \(rs" clear saved page number
\&..
.DE
.float end
By default,
.CW ms
does
.EM not
specify page footers; it
.EM does
specify a \%single\(hyline page header,
displaying the page number at the \%centre\(hytop of each page,
.EM except
that this header is omitted,
.EM "in its entirety" ,
on any page having a page number of one,
(unless such header omission is
.EM explicitly
overridden).
This suggests a possible technique,
suitable for use with
.CW ms
when its default page header and footer policy is in effect\Z','\|\**
.FS
The default page header and footer policy ceases to be in effect,
if the (effectively irreversible)
.CW .P1 \(rq \(lq
macro has been called,
thus overriding the omission of page one headers,
and so causing the page header to be printed
on any subsequent page numbered one,
(which would include those introduced by the conditional page break,
within the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro),
or if any of the page header or page footer trap macros have been redefined,
or if any page footer text has been defined.
If any such policy changes
.EM are
in effect,
the modified
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro would need to take steps to nullify them;
such steps could significantly add to the required complexity of the macro.
Details of the additional complexity,
which would be necessary,
depend on the precise nature of the departure from the default policy,
within each individual document,
and thus are left to the ingenuity of the publisher of the document to devise.
.FE
by manipulating the
.EM effective
page numbers around the page break,
to ensure that any intervening blank page remains
.EM "entirely blank" ;
this might be achieved,
within a modified variant of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro,
by initially saving the
.EM actual
page number prior to the page break,
followed by a temporary change of
.EM effective
page number, to one, when issuing the first (conditional)
page break request,
and ultimately,
.float needs 1v+\n(.V
restoring the original
.EM actual
page numbering sequence,
when issuing the second (unconditional) page break request:
.float release
.
.float begin
.DS I
.fam C
\&.   nr \(rs\(rs$0.% \(rs\(rsn%    \(rs" save current page number
.DE
(which itself requires the page number to be expressed in
decimal numeric format),
within an extended sequence of requests, such as:
.DS I
.fam C
\&.   af \(rs\(rs$0.% \(rs\(rsg%    \(rs" save page number format
\&.   af % 0 \h'\w!\0!u*10u' \(rs" interpret as decimal numeric...
\&.   nr \(rs\(rs$0.% \(rs\(rsn%    \(rs" to save its current value
\&.   af % \(rs\(rsg[\(rs\(rs$0.%]  \(rs" restore its original format
.DE
.float end
Notice that,
with this modification,
it is unnecessary to explicitly cancel \%\(lqno\(hyspace\(rq mode
after the conditional page break,
because the following unconditional
.CW .bp\h'\w!0!u/5u*3u'\(rs\(rsn+[\(rs\(rs$0.%] \(rq \%\(lq
request will cause a further page break,
even when \%\(lqno\(hyspace\(rq mode is in effect.
However, there
.EM is
a potential pitfall with this modification: it
.EM "will not work"
if the effective format for the page number register has been
assigned as anything other than decimal numerals!
.ne 15v+\n[PD]u
To avoid this pitfall,
it is necessary to temporarily force the page number register
to exhibit a decimal numeric format,
.float needs 1v+\n(.Vu
within the scope of execution of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro, for example, by encapsulating the simple request:
.float release
.KS
Furthermore, when the subsequent request:
.DS I
.fam C
\&.   bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
.DE
is eventually interpreted, the
.EM saved
page number
.EM must
be expressed in decimal numeric format;
thus, it is convenient to further extend the request sequence,
for saving the original page number format and value,
completing it by appending the additional request:
.DS I
.fam C
\&.   af \(rs\(rs$0.% 0 \h'\w!\0!u*5u' \(rs" keep saved value as decimal
.DE
.KE
.KS
Thus, the modified form of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro becomes:
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the passed argument, (which MUST be either
\&.\(rs" of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.   af \(rs\(rs$0.% \(rs\(rsg%    \(rs" save page number format
\&.   af % 0 \h'\w!\0!u*10u' \(rs" interpret as decimal numeric...
\&.   nr \(rs\(rs$0.% \(rs\(rsn%    \(rs" to save its current value
\&.   af % \(rs\(rsg[\(rs\(rs$0.%]  \(rs" restore its original format
\&.   af \(rs\(rs$0.% 0 \h'\w!\0!u*5u' \(rs" keep saved value as decimal
\&.   if \(rs\(rs$1 \(rs{\(rs
\&.   \(rs" Current page faces as does the desired output target,
\&.   \(rs" so we need to skip an entire opposing page.
\&.   \(rs"
\&.      nr \(rs\(rs$0.% +1   \(rs" update to skipped page number
\&.      bp 1 \h'\w!\0!u*8u'  \(rs" skip, numbering as page one
\&.   \(rs}
\&.   bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
\&.   rr \(rs\(rs$0.% \h'\w!\0!u*7u' \(rs" clear saved page number
\&..
.DE
.KE
.
As it now stands, when used with the
.CW ms
macros, with their default page header and footer policies in effect,
this implementatation of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro will advance the output position to the top of the next available,
appropriately facing new page;
if an additional intervening page is inserted,
it will remain
.EM completely
blank, and page numbering will resume on the new output page.
.
.LP
A further option,
which is not supported by the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro, as it now stands,
may be worthy of consideration:
instead of inserting a page header,
and thus resuming page numbering immediately,
on the page where output itself resumes following
.CW ADVANCE-TO-NEW-PAGE \(rq, \%\(lq
also omit the header of this page,
then reinstate it to resume numbering only on the next following page.
Once again, assuming that
.CW ms
is being used, with its default page header and footer policies in effect,
this additional feature may be readily supported,
in a similar manner to the suppression of
.EM all
output on intervening pages,
by replacing the unconditional statement:
.DS I
.fam C
\&.   bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
.DE
within the current
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
implementation, with the alternative unconditional statements:
.DS I
.fam C
\&.   bp 1 \h'\w!\0!u*12u' \(rs" advance, without numbering the page
\&.   pn \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" restore numbering on following page
.DE
.KS
or make it conditional,
for example on having passed\**
.FS
To achieve this, the
.CW NEW-RECTO-PAGE \(rq \%\(lq
and
.CW NEW-VERSO-PAGE \(rq \%\(lq
macros would also require modification,
to pass their own arguments on to
.CW ADVANCE-TO-NEW-PAGE \(rq, \%\(lq
following the
.CW o \(rq \(lq
and
.CW e \(rq \(lq
arguments, which they already pass,
respectively.
.FE
a second argument of
.CW no \(rq \(lq
(say), to suppress immediate resumption of page numbering,
otherwise, resume it immediately:
.DS I
.fam C
\&.   ie \(aq\(rs\(rs$2\(aqno\(aq \(rs{\(rs
\&.   \(rs" Page numbering is to be suppressed, on the first page
\&.   \(rs" on which output is resumed.
\&.   \(rs"
\&.      bp 1 \h'\w!\0!u*13u' \(rs" advance, without numbering the page
\&.      pn \(rs\(rsn[\(rs\(rs$0.%]+1   \(rs" restore numbering on following page
\&.   \(rs}
\&.   \(rs" Otherwise, page numbering is to be resumed immediately.
\&.   \(rs"
\&.   el .bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
.DE
.KE
.KS
Thus,
the refined set of page break macros,
for advancing the output position to a new recto page,
or to a new verso page, becomes the complementary pair:
.DS I
.fam C
\&.de NEW-RECTO-PAGE
\&.\(rs" Insert a page break, resuming output at the top of the
\&.\(rs" next available new recto (i.e. odd numbered) page.
\&.\(rs"
\&.   ADVANCE-TO-NEW-PAGE o \(rs\(rs$@
\&..
.DE
.KE
.KS
and its complement:
.DS I
.fam C
\&.de NEW-VERSO-PAGE
\&.\(rs" Insert a page break, resuming output at the top of the
\&.\(rs" next available new verso (i.e. even numbered) page.
\&.\(rs"
\&.   ADVANCE-TO-NEW-PAGE e \(rs\(rs$@
\&..
.DE
.KE
.KS
together with their common helper macro:
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the first passed argument, (which MUST be
\&.\(rs" either of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o [no]  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e [no]  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.\(rs" The second argument is optional; if specified as "no", the
\&.\(rs" ms page header, (incorporating the page number), will not
\&.\(rs" be printed on the first page, on which output is resumed.
\&.\(rs"
\&.   af \(rs\(rs$0.% \(rs\(rsg% \h'\w!\0!u*6u' \(rs" save page number format
\&.   af % 0 \h'\w!\0!u*14u' \(rs" interpret as decimal numeric...
\&.   nr \(rs\(rs$0.% \(rs\(rsn% \h'\w!\0!u*6u' \(rs" to save its current value
\&.   af % \(rs\(rsg[\(rs\(rs$0.%] \h'\w!\0!u*4u' \(rs" restore its original format
\&.   af \(rs\(rs$0.% 0 \h'\w!\0!u*9u' \(rs" keep saved value as decimal
\&.   if \(rs\(rs$1 \(rs{\(rs
\&.   \(rs" Current page faces as does the desired output target,
\&.   \(rs" so we need to skip an entire opposing page.
\&.   \(rs"
\&.      nr \(rs\(rs$0.% +1 \h'\w!\0!u*5u' \(rs" update to skipped page number
\&.      bp 1 \h'\w!\0!u*12u'  \(rs" skip, numbering as page one
\&.   \(rs}
\&.   ie \(aq\(rs\(rs$2\(aqno\(aq \(rs{\(rs
\&.   \(rs" Page numbering is also to be suppressed, on the first page
\&.   \(rs" on which output is resumed.
\&.   \(rs"
\&.      bp 1 \h'\w!\0!u*13u' \(rs" advance, without numbering the page
\&.      pn \(rs\(rsn[\(rs\(rs$0.%]+1   \(rs" restore numbering on following page
\&.   \(rs}
\&.   \(rs" Otherwise, page numbering is to be resumed immediately.
\&.   \(rs"
\&.   el .bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
\&.   rr \(rs\(rs$0.% \h'\w!\0!u*11u' \(rs" clear saved page number
\&..
.DE
.KE
.KS
Another optional refinement,
which may be considered,
could be to assign the page number format,
for use on pages following any page break which is introduced by either
.CW NEW-RECTO-PAGE \(rq, \%\(lq
or
.CW NEW-VERSO-PAGE \(rq, \%\(lq
by passing the desired formatting code as a macro argument,
rather than preserving the prevailing format internally, within the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro.
A possible implementation of such a refinement may be achieved
by defining a new \%internal\(hyuse macro:
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE.af
\&.\(rs" Helper macro, to be called ONLY by ADVANCE-TO-NEW-PAGE;
\&.\(rs" assign page number format for use on subsequent pages, as
\&.\(rs" specified by passed argument, or default to decimal.
\&.\(rs"
\&.   if \(aq\(rs\(rs$2\(aqno\(aq .shift  \(rs" ignore "no" argument
\&.   af % \(rs\(rs$2 0 \h'\w!\0!u*8u' \(rs" assign as specified, or default
\&..
.DE
.KE
.KS
This new \%internal\(hyuse macro would then be called,
normally exclusively in practice, by a further modified variant of the
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
macro:
.DS I
.fam C
\&.de ADVANCE-TO-NEW-PAGE
\&.\(rs" Insert page breaks, as required, to resume output at the
\&.\(rs" top of the next available new recto page, or new verso page,
\&.\(rs" as determined by the first passed argument, (which MUST be
\&.\(rs" either of groff's conditional operators, "o" or "e").
\&.\(rs"
\&.\(rs" Usage: .ADVANCE-TO-NEW-PAGE o [<arg> ...]  \(rs" NEW-RECTO-PAGE
\&.\(rs"        .ADVANCE-TO-NEW-PAGE e [<arg> ...]  \(rs" NEW-VERSO-PAGE
\&.\(rs"
\&.\(rs" The second, and subsequent arguments are optional; if the
\&.\(rs" second is specified as "no", the ms page header, (in which
\&.\(rs" the page number is normally included), will not be printed
\&.\(rs" on the first page, on which output is resumed, and a third
\&.\(rs" argument, if present, will be interpreted as specifying a
\&.\(rs" page number format for use on subsequent pages.
\&.\(rs"
\&.\(rs" Otherwise, if a second argument is specified, and it is
\&.\(rs" not "no", it will be interpreted as the specification of
\&.\(rs" the page number format for use on subsequent pages.
\&.\(rs"
\&.   af % 0 \h'\w!\0!u*14u' \(rs" make page number decimal...
\&.   nr \(rs\(rs$0.% \(rs\(rsn% \h'\w!\0!u*6u' \(rs" to save its current value
\&.   \(rs\(rs$0.af \(rs\(rs$@ \h'\w!\0!u*8u' \(rs" select, and apply new format...
\&.   af \(rs\(rs$0.% 0 \h'\w!\0!u*9u' \(rs" keeping saved value as decimal
\&.   if \(rs\(rs$1 \(rs{\(rs
\&.   \(rs" Current page faces as does the desired output target,
\&.   \(rs" so we need to skip an entire opposing page.
\&.   \(rs"
\&.      nr \(rs\(rs$0.% +1 \h'\w!\0!u*5u' \(rs" update to skipped page number
\&.      bp 1 \h'\w!\0!u*12u'  \(rs" skip, numbering as page one
\&.   \(rs}
\&.   ie \(aq\(rs\(rs$2\(aqno\(aq \(rs{\(rs
\&.   \(rs" Page numbering is also to be suppressed, on the first page
\&.   \(rs" on which output is resumed.
\&.   \(rs"
\&.      bp 1 \h'\w!\0!u*13u' \(rs" advance, without numbering the page
\&.      pn \(rs\(rsn[\(rs\(rs$0.%]+1   \(rs" restore numbering on following page
\&.   \(rs}
\&.   \(rs" Otherwise, page numbering is to be resumed immediately.
\&.   \(rs"
\&.   el .bp \(rs\(rsn[\(rs\(rs$0.%]+1  \(rs" advance, restoring page number
\&.   rr \(rs\(rs$0.% \h'\w!\0!u*11u' \(rs" clear saved page number
\&..
.DE
.KE
It is worth noting that
each of the page break macros,
developed above, is implemented
.EM exclusively
using fundamental
.CW groff
requests;
none of them is
.EM explicitly
dependent on
.CW ms .
However, they
.EM do
exhibit an
.EM implicit
dependency on default
.CW ms
behavioural \*[em traits specifically] that
no page headers are printed on any page with a page number of one,
and page footers are normally
.EM entirely
blank.
Thus, they should work equally effectively with
.EM any
macro suite which mimics,
or can be made to mimic,
these
.CW ms
behavioural traits.
.
.LP
There is at least one potentially detrimental consequence
of depending on these
.CW ms
behavioural traits,
which will become apparent in any reference to the
.CW \(rsn% \(rq \%\(lq
page number register on any page on which an effective page number of one
has been substituted for the real page number,
to suppress printing of the page header on the page where output is resumed,
following a page break.
The detrimental effect of page number substitution
will be particularly noticeable when collecting of references
for inclusion in a table of contents;
such references would be expected to reflect the real page number,
but the
.CW \(rsn% \(rq \%\(lq
register will reflect only the effective page number of one.
This effect,
and a mechanism for neutralizing it,
will be explored in
.\"pdfhref L -D toc-alternatives -A . -- the following section
.XR-NO-PREFIX toc-alternatives .
.
.LP
As a final observation,
on the handling of \%recto\(hyverso page breaks:
the
.CW NEW-RECTO-PAGE \(rq, \%\(lq
.CW NEW-VERSO-PAGE \(rq, \%\(lq
and their supporting
.CW ADVANCE-TO-NEW-PAGE \(rq \%\(lq
and
.CW ADVANCE-TO-NEW-PAGE.af \(rq \%\(lq
macro variants,
as they have been developed above,
are intended only as examples;
depending on their individual requirements,
users are invited to adapt,
and consolidate the techniques which they illustrate,
as may be deemed appropriate.
A practical illustration may be found in the
.CW pdfmark.ms
source file, for this document;
this never uses the
.CW NEW-VERSO-PAGE \(rq \%\(lq
macro, and it
.EM always
suppresses the printing of page headers
on the first output page following any use of its
.CW NEW-RECTO-PAGE \(rq \%\(lq
macro; thus, rather than implementing them separately,
as illustrated above, it consolidates the implementations of both the
.CW ADVANCE-TO-NEW-PAGE \(rq, \%\(lq
and the
.CW ADVANCE-TO-NEW-PAGE.af \(rq \%\(lq
macros, with
.EM unconditional
page header suppression,
into a \%free\(hystanding
.CW NEW-RECTO-PAGE \(rq \%\(lq
macro implementation,
within which it also incorporates a mechanism for propagation of
.EM real
page numbers, when constructing table of contents references,
.
.NH 2
.XN -N do-xref -- Considerations for Working with Document References
.LP
The provisions made by the
.CW pdfmark
macros,
for creation of,
and linking to,
\%in\(hydocument reference marks is described in
.XR-NO-PREFIX pdfhref .
.
.LP
In general,
when producing any PDF document using the
.CW pdfroff
program,
adoption of the techniques described in
.pdfhref F SECREF
.pdfhref L -D pdfhref
.pdfhref F
is sufficient for creation of,
and linking to,
document reference marks,
.EM without
the need for any further user intervention,
.EM provided
that
.EM all
of the reference marks,
and
.EM all
references to them,
are encapsulated within the one document
which is being produced.
.
However,
if it is desired that any created reference mark
should be accessible for referencing from other documents,
or any reference is made to a reference mark within another document,
then it may be helpful to specify such reference marks
in association with one or more
.CW pdfmark
.EM "reference dictionaries" .
.
.NH 3
.XN -N create-map -- Creating a Document Reference Dictionary
.LP
When any PDF document is produced by
.CW pdfroff ,
a reference dictionary is created
.EM automatically ;
however,
this is normally created within a temporary file,
which is deleted when
.CW pdfroff
completes processing of each particular document,
so it will not be readily available for exposure of
any reference marks which it specifies,
for subsequent use within other documents.
.
.ne 6v+(u;2*\n[DD])
This limitation may be overcome,
by specifying the
.CW \-\-reference\-dictionary \(rq \%\(lq
option when invoking
.CW \%pdfroff ,
in conformance with the synoptic model:
.DS I
.fam C
\&pdfroff \c
\&\-\-reference\-dictionary=\f(CIfilename\fP.ref [\f(CIoption\fP ...\&] \(rs
\&   \f(CIinput\-file\fP ...\& > \f(CIfilename\fP.pdf
.DE
which instructs
.CW \%pdfroff
to save,
to the user nominated file,
.CWI filename .ref \& \(rq, \%\(lq
any reference dictionary content which it generates,
rather than deleting it on completion of processing,
as it normally would.
.
.LP
In addition to adoption of the foregoing recommendation,
to ensure that a reference dictionary is saved,
.ig
it is advisable to give careful consideration to
the scope of the reference context information,
as determined by the
.CW \%PDFHREF.INFO
specification,
.XR export-map ), (
which will be stored in the resultant reference dictionary.
..
consideration should also be given to
the creation of individual reference dictionary records,
and the scope of the reference context information
which is stored in each.
.
.LP
Each individual reference dictionary record takes the form of a
.CW \%pdfhref
macro call:
.DS I
.fam C
\&.pdfhref D \-N <\f(CI\,name\/\fP> \c
[[<\f(CI\,keyword\/\fP> <\f(CI\,value\/\fP>] ...] \c
[<\f(CI\,text\/\fP> ...]
.DE
and is associated with
.EM "exactly one"
named reference mark;
each such record may be added to the dictionary,
at the time when the reference mark itself is created,
by use of a defining macro call in the form:\**
.FS
The equivalent form,
.CWB \-X \0[\-D .pdfhref\0M\0 \c \%\(lq
.CWI \,name\/ >]\0[[\-E] \0< \c
.CWI \,text\/ >] \&\0< \(rq,
may be used,
if preferred;
the
.CWI \,name\/ > \-D\0< \(rq \%\(lq
option is provided for consistency with its use in the
.CW .pdfhref\0L\0... \(rq \%\(lq
macro form,
while the
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option is defined for consistency with
.CW .pdfhref\0D\0... \(rq \%\(lq
syntax,
and exhibits
.EM identical
behaviour in
.CW .pdfhref\0M\0... \(rq \%\(lq
usage.
.FE
.DS I
.fam C
\&.pdfhref M \f(CB\-X\fP [\-N <\f(CIname\fP] [[\-E] [\-\-] <\f(CItext\fP> ...]
.DE
.ne 2v+\n[.V]u
When the
.CW ".pdfhref M ..." \(rq \%\(lq
macro is invoked thus,
with the
.CW \-X \(rq \%\(lq
option in effect,
if the
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option is
.EM explicitly
specified,
either in this,
or in its equivalent
.CWI \,name\/ > \-D\0< \(rq \%\(lq
form\Z','\|\**
.FS
If the equivalent
.CWI \,name\/ > \-D\0< \(rq \%\(lq
form of this option is specified,
it is internally convert to the
.CWI \,name\/ > \-N\0< \(rq \%\(lq
form,
and explicitly interpreted as such.
.FE
then a corresponding reference dictionary record is instantiated,
with a verbatim copy of the specified
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option incorporated,
.EM immediately
following the
.CW .pdfmark\0D \(rq \%\(lq
preamble.
.
Conversely,
if
.EM neither
the
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option,
.EM nor
the equivalent
.CWI \,name\/ > \-D\0< \(rq \%\(lq
option is specified,
then
.EM "at least one"
\%space\(hydelimited word of the otherwise optional
.CWI \,text\/ >\0... < \(rq \%\(lq
sequence of arguments
.EM must
be specified;
from this,
a
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option is
.EM implicitly
derived,
for incorporation into the instantiated reference dictionary entry.
.
In either case,
the remaining
.CWI \,keyword\/ >\0 [< \c \%\(lq
.CWI \,value\/ >]\0...\& < \(rq
and
.CWI \,text\/ >\0...\& < \(rq \%\(lq
components of this dictionary entry are determined in accordance with
the currently active specification of the
.CW PDFHREF.INFO \(rq \%\(lq
template string,
as defined by the user.
.LP
In general,
it is better to specify
.CW PDFHREF.INFO \(rq \%\(lq
such that the reference dictionary will record
.EM more
context than is deemed to be strictly necessary;
unwanted context can simply be ignored,
at the ultimate point of use,
but anything which has not been recorded
.EM cannot
be inferred on subsequent demand.
.
Typical context information,
which may be recorded,
includes:
.QS
.sp -\n[PD]u
.IP \(bu
The reference mark name;
(this is
.EM always
recorded,
due to the incorporation of the
.CWI \,name\/ > \-N\0< \(rq \%\(lq
option,
whether
.EM explicitly
assigned,
or
.EM implicitly
inferred from the
.CWI \,text\/ >\0...\& < \(rq \%\(lq
reference mark description).
.
.IP \(bu
A file name reference;
this is processed according to the
.CW PDFHREF.FILEREF \(rq \%\(lq
formatting specification,
when a
.CWI \,filename\/ > file\0< \(rq \%\(lq
tuple is included within the
.CWI \,keyword\/ >\0 [[< \c \%\(lq
.CWI \,value\/ >]\0...\&] < \(rq
region of the
.CW PDFHREF.INFO \(rq \%\(lq
template specification,
and any link to the associated reference mark
is subsequently interpolated.
.
.IP \(bu
A page number reference;
ultimately processed in accordance with the
.CW PDFHREF.PAGEREF \(rq \%\(lq
formatting specification,
when subsequently interpolating any
.\"CW .pdfhref\0L\0...\& \(rq \%\(lq
link to the associated reference mark,
this will be recorded when a
.CW page\0\(rs\(rsn% \(rq \%\(lq
tuple is included within the
.CWI \,keyword\/ >\0 [[< \c \%\(lq
.CWI \,value\/ >]\0...\&] < \(rq
region of the
.CW PDFHREF.INFO \(rq \%\(lq
template specification.
.
.IP \(bu
A section number reference,
(if applicable);
when recorded,
by inclusion of a
.CWI \,SN\/ \& section\0\(rs\(rs*( \(rq \%\(lq
tuple within the
.CWI \,keyword\/ >\0 [[< \c \%\(lq
.CWI \,value\/ >]\0...\&] < \(rq
region of the
.CW PDFHREF.INFO \(rq \%\(lq
template specification,
this will be processed in accordance with the
.CW PDFHREF.SECTREF \(rq \%\(lq
formatting specification,
when any link to the associated reference mark
is subsequently interpolated.
.
.IP \(bu
Any reference data
which may be associated with \%user\(hyspecified keywords;
such keywords
.EM must
be defined in each individual document (file) processing context
in which they may be referenced,
wherein they will be processed in accordance with
the formatting specification which
the user has associated with each particular keyword.
Considerations for the use of such formatting specifications
will be discussed further, in
.XR-NO-PREFIX keyword-map .
.QE
.sp -\n[PD]u
.LP
All such data,
which has been recorded within a saved reference dictionary,
will be available for interpolation into \%inter\(hydocument references,
formatted as described in
.XR-NO-PREFIX set-format ,
within any document in which this reference dictionary is deployed,
as described in
.pdfhref L -D import-map -A . -- "the following section"
.
.NH 3
.XN -N import-map -- Deploying a Document Reference Dictionary
.LP
When
.CW pdfroff
is used to drive the
.CW groff
PDF formatting process,
for any given document,
then the reference dictionary for that document,
itself,
will be
.EM automatically
incorporated into the document input stream;
this is required to accommodate the resolution of
.EM \%intra\(hydocument references,
and occurs
.EM irrespective
of whether the reference dictionary is designated
to be committed to persistent file storage,
as described in
.pdfhref L -D create-map -A , "the preceding section"
or is to persist only
.EM temporarily ,
and will be deleted on completion of the
.CW pdfroff
processing run.
.
.LP
Conversely,
if any
.EM \%inter\(hydocument
references,
to locations within any other,
.EM external
PDF files are specified,
the corresponding reference dictionaries will
.EM not
be automatically incorporated into the
.CW pdfroff
input stream.
The onus for incorporation of such reference dictionaries rests
.EM entirely
with the document author;
this may be accomplished,
most readily,
by inclusion of a
.CW .so \h'\w"l"u'\c \%\(lq
.CW filename.ref \(rq
request,
within the referring document source.
.
.LP
Additionally,
when such reference dictionaries are included,
the document author should be aware of the possibility
that these may introduce conflicting reference names,
and should assume responsibility for resolving
any such conflicts which may arise;
techniques for doing so will be introduced in
.XR-NO-PREFIX map-conflicts .
.
.NH 3
.ne 3.2v+\n[PD]u
.XN -N keyword-map -- Using Custom Reference Formatting Keywords
.LP
When a reference dictionary comprises records which incorporate
.EM exclusively
default
.CW \%pdfmark.tmac
formatting keywords,
then it may be safely assumed that these keywords will have been defined,
by the simple expedient of including
.CW \%pdfmark.tmac
within the
.CW \%pdfroff
input data stream.
However,
no such assumption may be made,
in the case of any reference dictionary
in which \%user\(hydefined custom formatting keywords
may be present,
and thus,
the document author must accept the responsibility
of ensuring that any such custom keywords have been defined,
.EM before
referring to any named location
for which the reference dictionary entry includes them.
.
.LP
For use within
.EM \%intra\(hydocument
references,
any custom formatting keywords which are to be incorporated
should be defined in the document source stream,
using the
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW K \h'\w"l"u'\c
.CW ... \(rq\&
capability,
.XR custom-format ), (
.EM \%before
placement of any reference which may require them\Z'.'\|\**
.FS
When using an implementation of
.CW \%pdfmark.tmac
from the 25.04,
or any later release of
.CW \%groff-pdfmark ,
the
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW K \h'\w"l"u'\c
.CW ... \(rq\&
definitions will be duplicated in the generated reference dictionary,
thus ensuring early definition in each
.CW \%pdfroff
processing pass,
with the exception of the first \%pre\(hyprocessing pass.
.FZ .
Additional custom keyword definitions,
as may be required to support
.EM \%inter\(hydocument
references,
.ne 2v
may also be defined within the document source,
alongside
.EM \%intra\(hydocument
keywords;
however,
it may be more convenient to emulate the behaviour of
.CW \%pdfmark.tmac
release 25.04 and later,
manually editing any reference dictionaries
which may have been generated using an earlier
.CW \%pdfmark.tmac
release,
to include any custom keyword definitions
which they may require.
.
.LP
It may be noted that provision of a
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW K \h'\w"l"u'\c
.CW ... \(rq\&
definition alone is insufficient
to ensure appropriate handling of custom formatting keywords;
the onus remains on the document author,
to ensure that each such definition is accompanied
by a suitable template string definition
for the designated,
named format string itself\Z'.'\|\**
.FS
Prior to
.CW \%pdfmark.tmac
release 25.04,
this onus rests
.EM entirely
on the document author;
in the absence of any \%pre\(hyexisting format string definition,
the
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW K \h'\w"l"u'\c
.CW ... \(rq\&
implementation within
.CW \%pdfmark.tmac
release 25.04,
and later,
will supply a default definition,
in the form
.CW .ds \h'\w"l"u'\c \%\(lq
.CWI format\-name > < \h'\w"l"u'\c
.CWI keyword > \(dq< \h'\w"l"u'\c
.CWI $* \(rs\(dq \(rs\(rs \(rq,
which the document author may choose to adopt,
or to override,
as preferred.
.FZ .
.
.NH 3
.XN -N map-conflicts -- Avoiding Reference Name Conflicts
.LP
Within any single PDF document,
each
.CW \%pdfhref
reference destination
.EM must
be
.EM uniquely
named.
The onus for ensuring this lies with the document author;
to facilitate honouring the obligation,
it is recommended that:
.sp -\n[PD]u
.QS
.IP \(bu
.EM Every
reference destination is
.EM explicitly
named,
by specifying the
.CW \-N \h'\w"l"u'\c \%\(lq
.CWI name > < \(rq
option,
(as described in
.XR-NO-PREFIX mark-dest ),
when each destination reference mark is placed,
by use of the
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW M \h'\w"l"u'\c
.CW ... \(rq
macro call.
.
.IP \(bu
Additionally,
to help keep track of reference names
which have already been allocated,
and the destinations to which they refer,
it is suggested that the
.CW \-X \(rq \%\(lq
option should be applied,
for each invocation of the
.CW .pdfhref \h'\w"l"u'\c \%\(lq
.CW M \h'\w"l"u'\c
.CW ... \(rq
macro,
and the
.CW \-\-reference\-dictionary= \c \%\(lq
.CWI filename > < \(rq
option should be specified when running the
.CW pdfroff \(rq \%\(lq
command;
this allows for consultation of the nominated
reference dictionary file,
both as a reminder of allocated reference destination names,
and the document locations to which they refer,
(which may be helpful when constructing subsequent reference links).
.QE
.
Unfortunately,
while the foregoing advice may help the author to avoid
reference name conflicts within
.EM any
.EM single
PDF document,
it cannot guard against the possibility of such conflicts arising
when referring to locations within
.EM external
documents,
.EM especially \& (
when such external documents originate from a
.EM different
author,
and the chosen reference names are beyond the control
of the referring document author).
.
.LP
A technique which could be considered,
to mitigate potential reference name conflicts across document boundaries,
might be to assign a distinct
.EM local
\(lqnamespace\(rq for each individual document.
Such a technique is
.EM not ,
currently\Z','\|\**
.FS
Although the current
.CW \%pdfmark.tmac
implementation does not,
directly,
support any technique,
such as that described here,
for avoiding reference name collisions,
it is anticipated that \%built\(hyin support may be incorporated
in a \%near\(hyfuture release of
.CW \%groff-pdfmark .
.FZ ,
supported by
.CW \%pdfmark.tmac ,
so document authors are free to implement a suitable mechanism,
at their own discretion;
a suitable strategy may be to:
.sp -\n[PD]u
.
.QS
.IP \(bu
Edit the reference dictionary files,
which are associated with each external file to be referenced,
(using a stream editor such as
.CW sed ,
for example),
to prefix a suitably chosen
.EM distinct
\(lqnamespace\(rq identifier
to each reference name which is defined.
.
.IP \(bu
Within the local document source,
register each chosen \(lqnamespace\(rq,
associating each with the appropriate set of
.CW \%pdfhref
external filename reference options,
which should be included in any
.CW pdfhref \h'\w"l"u'\c \%\(lq
.CW L \h'\w"l"u'\c
.CW ... \(rq;
macro call,
to resolve references within the designated \(lqnamespace\(rq.
.
.IP \(bu
Also within the local document input data stream,
implement a wrapper macro,
which is to be used in place of
.CW pdfhref \h'\w"l"u'\c \%\(lq
.CW L \h'\w"l"u'\c
.CW ... \(rq;
this wrapper macro should examine each specified destination name,
.EM remove
any registered \(lqnamespace\(rq prefix,
then redirect the call to
.CW pdfhref \h'\w"l"u'\c \%\(lq
.CW L \h'\w"l"u'\c
.CW ... \(rq
itself,
while adding the appropriate external file name reference options,
within the scope of the redirected call.
.QE
.sp -\n[PD]u
.LP
Until such time as capabilities,
similar to those described above,
are formally integrated into
.CW \%groff-pdfmark ,
details of a suitable substitute implementation
are left to the discretion,
and ingenuity,
of the document author.
.
.
.bp
.NH 2
.XN -N toc-alternatives -- An Alternative Technique for Generating Tables of Contents
.LP
Although
.CW \%pdfroff
offers \%built\(hyin support for the traditional
.CW \%troff
technique of printing tables of contents
.EM after
the body of each document,
and subsequently relocating them,
.EM \%manually ,
to their normal position
.EM \%before
the document body,
this technique is not particularly well suited
to the publication of PDF documents,
and the implementation is decidedly kludgey.
In particular,
when employing the traditional
.CW ms
macro technique of collecting table of contents entries using the
.CWB \%.XS ,
.CWB \%.XA ,
and
.CWB \%.XE
macros,
and subsequently using the
.CWB \%.TC
macro to print the collected table of contents,
for relocation by
.CW \%pdfroff ,
it has been found to be extremely challenging,
if not actually impossible,
to specify
.CW \%pdfhref
links between the table of contents entries
and corresponding reference marks within the document body.
Consequently,
while early editions of this publication
.EM did
use the traditional
.CW ms
technique for collation of the table of contents,
this technique has now been abandoned,
in favour of a more streamlined,
and flexible collation technique,
based on the
.CW \%groff_toc
macro framework,
which is provided as a supplementary component of the
.CW \%groff\(hypdfmark
distribution.
.
.NH 3
.XN -S -N toc-usage -- Using the Basic \F[C]groff_toc\F[] Macro Framework
.LP
The basic
.CW \%groff_toc
macro framework is provided by the
.CW \%groff
macro file,
.CW \%toc\-base.tmac ;
this defines the
.CWB \%.toc
macro,
with \%built\(hyin support for the following set of basic operations:
.
.QS
.sp -\n[PD]u
.char & \F[]\h'\w";"u'\FC
.IP \FC\fB.toc&file\fP&[\fIfilename\fP]\F[]
Specify the path name for a file,
into which collected table of contents data is to be written.
Any previously active data collection stream is closed,
before opening the specified
.CWI \%filename
stream.
.IP
Omission of the optional
.CWI \%filename
argument causes subsequently collected table of contents data
to be directed to the
.CW \%stderr
output stream.
.IP
Specification of any named data collection stream,
other than
.CW \%stderr ,
may require
.CW \%groff
to be invoked in \(lqunsafe\(rq mode,
(i.e.\~with the \%\(lq\f(CB\-U\fP\(rq option specified).
This limitation
.EM "does not"
apply,
in the case of document processing by
.CW \%pdfroff .
.
.IP \FC\fB.toc&put\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]
Write a request,
of the form
\%\(lq\FC\fB.toc\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq\Z','\|\**
.FS
Strictly,
the request is written in the form
\%\(lq\FC\fB\(rs*[TOC.REQUEST]\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq,
with the default assignment for
.CW \%TOC.REQUEST
being specified as
.CW \%.toc \(rq; \(lq
in normal use,
changing this default assignment for
.CW \%TOC.REQUEST
is
.EM not
recommended;
thus the default form of the request,
as written,
becomes
\%\(lq\FC\fB.toc\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq,
as stated.
.FE
to the currently active table of contents data collection stream,
as specified by a prior call
to \%\(lq\FC\fB.toc&file\fP&[\fIfilename\fP]\F[]\(rq,
or in the absence of any such prior call,
to the \FCstderr\F[] output stream.
.
.IP
\%\(lq\FC\fB.toc&put\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq
macro calls may be freely interspersed,
throughout any document source,
to export reference data,
in the form of further
\%\(lq\FC\fB.toc\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq
macro calls,
whence a table of contents itself may be generated,
when the resultant recorded
\%\(lq\FC\fB.toc\fP&\fIopcode\fP&[\fIdata\fP&...]\F[]\(rq
macro calls are imported,
and interpreted at the point where the table of contents should appear.
.
.IP \%\FC\fB.toc&error\fP&\fIdiagnostic&message\fP&...\F[]
Write the text of \%\(lq\FC\fIdiagnostic&message\fP&...\F[]\(rq to the
.CW \%stderr
output stream,
identifying it as originating from within the
.CW \%groff_toc
macro framework.
.rchar &
.QE
.
Since the
.CW \%groff_toc
macro framework is implemented within a
.CW \%groff
macro file,
which is expected to reside within the default macro file path,
(possibly augmented by assignment of the
.CWB \%GROFF_TMAC_PATH
environment variable),
it
.EM may
be incorporated into the document publication process by adding the
.CWB \-mtoc\-base \& \& \(rq \%\(lq
option to the
.CW \%groff ,
or the
.CW \%pdfroff
command line.
However,
since it will usually be necessary to furnish a collection of binding macros,
it may be more convenient to load the framework using
the \%\(lq\f(CB.\^mso\fP\h'\w"t"u'\f(CBtoc\-base.tmac\fP\(rq request,
and to delegate this request to a suitable binding macro package,
(for example,
.XR mspdf-toc-binding ).
.
.LP
.KS
Following the incorporation of the
.CW \%groff_toc
framework into the document publishing process,
.EM and
the definition of any supplementary macros
which may be required to service the specified
\%\(lq\f(CB.toc\fP\h'\w"t"u'\f(CIopcode\fP\h'\w"t"u'\c
\FC[\fIdata\fP\F[]\h'\w"t"u'\f(CR...]\fP\(rq requests,
the table of contents itself may be incorporated into the document,
by interpretation of
.CW \%groff
markup code similar to:
.DS I
.fam C
\&.ce 1
\&.\(rs" Place a centred one-line heading over the table of contents;
\&.\(rs" default is \(aqTable of Contents\(aq, but allow for prior definition,
\&.\(rs" e.g. to support translation to alternative languages.
\&.\(rs"
\&.if !dTOC .ds TOC "Table of Contents\(rs"
\&.pdfhref O 1 \(rs*[TOC]
\&\(rsfB\(rss\(aq+2z\(aq\(rs[TOC]\(rss\(aq-2z\(aq\(rsfP
\&.sp 2v
\&.
\&.\(rs" Import the reference data, interpret it, and format the table
\&.\(rs" of contents itself; notice that, only AFTER importing the data,
\&.\(rs" is it safe to reset the reference data collector, because the
\&.\(rs" action of resetting the file stream, (e.g. refdata.toc here),
\&.\(rs" will obliterate its data content, which we wish to import.
\&.\(rs"
\&.so refdata.toc
\&.toc file refdata.toc
.DE
.
whereafter,
\%\(lq\f(CB.toc\fP\h'\w"t"u'\f(CBput\fP\h'\w"t"u'\f(CIopcode\fP\h'\w"t"u'\c
\FC[\fIdata\fP\F[]\h'\w"t"u'\f(CR...]\fP\(rq macro calls may be inserted
into the document source,
as required,
to specify table of contents page references,
and their associated descriptions.
.KE
.
.NH 3
.XN -N toc-interpretation Generating and Interpreting \#
Table of Contents Reference Data
.LP
In the preceding example,
as presented in
.pdfhref F SECREF L -D toc-usage -A ,
it should be implicitly apparent that multiple
.CW \%groff
processing passes will be required,
for generation,
and for interpretation of the table of contents reference data:
.
.QS
.sp -\n[PD]u
.IP \(bu
One initial pass will be required to establish
the early content of the
.CW \%refdata.toc
file,
(as it is named in the example);
this may not even exist at the outset,
and thus it will not be available for import,
much less for interpretation,
during this initial processing pass,
but it will be created,
if necessary,
during this pass,
and its content will then become available for import,
and refinement during subsequent passes.
.
.IP \(bu
During subsequent passes,
the
.CW \%refdata.toc
file will be imported,
and its content will be interpreted,
to tentatively format the table of contents;
its content will then be cleared,
and then rewritten,
for refined reinterpretation during further subsequent passes.
.QE
.
Such multiple pass processing is an inherent feature of the
.CW \%pdfroff
program,
which will,
thus,
be particularly well suited to this task\Z'.'\|\**
.FS
An additional,
possibly less obvious,
advantage of the choice of
.CW \%pdfroff
for this task is that any
.CW \%groff
error message,
resulting from an attempt to import a non\(hyexistent reference data file,
will be filtered from the
.CW \%stderr
data stream,
captured by
.CW \%pdfroff ,
within its temporary working data set,
subsequently discarded,
and consequently hidden from the user.
.FZ .
.
.LP
It should be noted that the choice of reference data file name,
.CW refdata.toc \(rq, \%\(lq
as illustrated in the example presented in
.XR toc-usage ,
is entirely arbitrary;
users are free to choose any alternative name,
which may be better suited to their publishing conventions.
.
.LP
A further observation might be that
.XR toc-usage
.pdfhref F
offers absolutely no insight regarding particulars
for the specification of any \%\(lq\f(CI\,opcode\/\fP\(rq symbolic names,
nor for any of their associated
\%\(lq\f(CIdata\fP\h'\w"t"u'\f(CR...\fP\(rq arguments,
which may be used within
\%\(lq\f(CB.toc\fP\h'\w"t"u'\f(CBput\fP\h'\w"t"u'\f(CIopcode\fP\h'\w"t"u'\c
\FC[\fIdata\fP\F[]\h'\w"t"u'\f(CR...]\fP\(rq macro calls.
This apparent omission is,
in fact,
intentional:
the
.CW \%groff_toc
macro framework does not stipulate any such
\%\(lq\f(CI\,opcode\/\fP\(rq symbolic names;
nor does it impose any restrictions on the syntax,
or on the content of any associated
\%\(lq\f(CIdata\fP\h'\w"t"u'\f(CR...\fP\(rq arguments.
.
Thus,
users are free to make their own choices regarding the representation,
and the ultimate interpretation of table of contents reference data;
.ne 3v+\n[PD]u
such choices are subject only to a few restrictions,
namely:
.
.QS
.sp -\n[PD]u
.IP \(bu
Any number of \%user\(hydefined \%\(lq\f(CI\,opcode\/\fP\(rq names
may be specified; at least one is required.
.
.IP \(bu
Each \%user\(hydefined \%\(lq\f(CI\,opcode\/\fP\(rq
.EM must
be represented by a valid
.CW \%groff
symbolic name.
.
.KS
.IP \(bu
The \%\(lq\f(CI\,opcode\/\fP\(rq names,
\%\(lq\f(CBfile\fP\(rq,
\%\(lq\f(CBput\fP\(rq,
and \%\(lq\f(CBerror\fP\(rq,
are
.EM reserved ,
and therefore,
may
.EM not
be chosen as \%user\(hydefined \%\(lq\f(CI\,opcode\/\fP\(rq names;
any attempt to do so may compromise the integrity of the
.CW \%groff_toc
macro framework.
.KE
.
.KS
.IP \(bu
Each \%user\(hydefined \%\(lq\f(CI\,opcode\/\fP\(rq name
.EM must
be supported by an implementation,
in the form of a \%user\(hydefined macro
named \%\(lq\f(CBtoc.\fP\f(CI\,opcode\fP\(rq,
to correspond to the chosen \%\(lq\f(CI\,opcode\/\fP\(rq name.
This macro will become integrated into the
.CW \%groff_toc
macro framework,
within which it will serve as the handler for table of contents
reference data generated by macro calls of the form:
\%\(lq\f(CB.toc\fP\h'\w"t"u'\f(CBput\fP\h'\w"t"u'\f(CIopcode\fP\h'\w"t"u'\c
\FC[\fIdata\fP\F[]\h'\w"t"u'\f(CR...]\fP\(rq,
with matching \%\(lq\f(CI\,opcode\/\fP\(rq name.
.KE
.QE
.
While it may be evident that the implementation of the
.CW \%groff_toc
macro framework is fundamentally incomplete,
and the burden of completion is placed on the user,
the extensible design does accord,
to the user,
considerable latitude in the choice of exactly
how table of contents reference data should be recorded,
and ultimately presented,
in any given publication;
essentially,
this may be viewed as a choice between
adoption of a comparatively trivial implementation,
or the pursuit of a more sophisticated solution,
such as an adaptation of the extended framework
which has been developed for use in this publication itself,
is discussed further in
.XR-NO-PREFIX mspdf-toc-binding ,
and ultimately,
has been implemented as documented in
.XR-NO-PREFIX toc-compilation .
.
.LP
Should the user choose to adopt a trivial implementation,
this may be as simple as provision of a macro similar to:
.DS I
.fam C
\&.de toc.pageref
\&.\(rs" Format and emit a single table of contents entry, which has
\&.\(rs" previously been recorded by a macro call of the form:
\&.\(rs"
\&.\(rs"   .toc put pageref \(rsn% <reference text> ...
\&.\(rs"
\&.\(rs" \(rs$1 is expected to represent a page number reference; capture
\&.\(rs" it, together with leader and tab, for relocation to the end of
\&.\(rs" the formatted entry, then move it out of the way.
\&.\(rs"
\&.   ds \(rs\(rs$0-% "\(rsh\(aq\(rsw!00!u\(aq\(rsa\(rst\(rs\(rs$1\(rs"
\&.   shift
\&.
\&.\(rs" Emit the remaining reference text, followed by the captured
\&.\(rs" page number, and then, clean up temporary working storage.
\&.\(rs"
\&.   nop \(rs\(rs$*\(rs\(rs*[\(rs\(rs$0-%]
\&.   rm \(rs\(rs$0-%
\&..
.DE
.
With a macro such as this in place,
beforehand,
the example illustrated in
.pdfhref F SECREF L -D toc-usage -A ,
for incorporation of the table of contents into the published document,
should be adapted,
(omitting embedded comments),
to something like:
.
.DS I
.fam C
\&.ce 1
\&.ll 17.0c
\&.ta (u;\(rsn[.l]-\(rsw\(aq00000\(aq)R \(rsn[.l]uR
\&.if !dTOC .ds TOC "Table of Contents\(rs"
\&.pdfhref O 1 \(rs*[TOC]
\&\(rsfB\(rss\(aq+2z\(aq\(rs[TOC]\(rss\(aq-2z\(aq\(rsfP
\&.sp 2v
\&.
\&.so refdata.toc
\&.toc file refdata.toc
.DE
.
while the actual content,
complete with associated page number references,
which is to be incorporated as table of contents entries,
would be specified by inserting reference marks,
in the form of macro calls of the form:
.
.DS I
.fam C
.char _ \F[]\h'\w"t"u'\FC
.char < \v'+0.5p'<\h'1p'\v'-0.5p'
.char > \v'+0.4p'>\v'-0.4p'
\&.toc put pageref \(rsn% <\fI\,text_for_table_of_contents_entry\/\fP>
.rchar < _ >
.DE
.
at strategic points within the \%marked\(hyup document source,
(possibly by encapsulation of such calls within
a further \%user\(hydefined macro,
to facilitate reproduction of the same reference text
as a heading within the document body,
in addition to incorporating it into the table of contents;
a technique for implementing this,
and also for reproducing the same reference text
as a PDF document outline link,
will be introduced in
.XR mspdf-toc-binding ).
.pdfhref F
.
.NH 3
.ne 3v+\n[PSINCR]u+\n[PD]u
.XN -S -N mspdf-toc-binding Binding the \F[C]groff_toc\F[] Macro Framework \#
with the \F[C]ms\F[] and \F[C]pdfmark\F[] Macros
.LP
As noted in
.XR-NO-PREFIX pdf-layout ,
the formatting of this document is directed by the
.CW \%groff
.CW ms
macros;
its early editions used the \%built\(hyin table of contents generation macros,
with the assistance of the associated collation features of
.CW \%pdfroff .
This
.EM did
create a visually acceptable table of contents;
however,
it was found to be functionally lacking,
insofar as it did not exhibit any capability for linking
to the associated reference locations,
and the challenge of providing this capability seemed insurmountable.
Hence,
the decision to develop,
and deploy the
.CW \%groff_toc
macro framework,
as described here,
was taken;
the outcome has proven to be very successful.
.
.LP
Development of the
.CW \%groff_toc
macro framework itself was quite straightforward,
and effective bindings between the
.CW ms
and
.CW \%pdfmark
macros already exist,
courtesy of the supplementary macro package
.CW \%spdf.tmac ;
thus,
development of further bindings,
between
.CW \%groff_toc
and
.CW \%spdf.tmac
alone,
should suffice to bind all of
.CW ms ,
.CW \%pdfmark ,
and
.CW \%groff_toc ,
to form a logically integrated macro suite.
.
.LP
A primary objective,
in the development of a binding macro package,
is that it should modify the behaviour of the underlying implementation,
upon which it depends,
but it should remain separate from that implementation,
and should not
.EM physically
alter it
.EM "in any way" .
With this in mind,
in this section we will explore the principles of development of
a binding package for the
.CW ms ,
.CW pdfmark ,
and
.CW groff_toc
macros,
while keeping the bindings separate,
by placing them in the additional
.CW \%spdf\-toc.tmac
binding macro file\Z'.'\|\**
.FS
This binding macro file is included with the
.CW \%groff\-pdfmark
distribution,
but it does not promise to deliver a fully developed implementation;
it should be considered as an example,
which users may wish to adapt
to suit their own requirements.
.FZ .
Moreover,
we will focus,
primarily,
on meeting only the requirements of this document,
so the collection of binding macros,
as discussed here,
may require further development to complete their implementation
for more generalized use.
.
.LP
To begin construction of the
.CW \%spdf\-toc.tmac
binding macro file,
we will insert conventional file header commentary,
together with a guard test\**
.FS
Guard tests are typically included
.EM early
in macro files,
to avoid the overhead of reading them more than once,
in the event of them being included from more than one location.
Such tests are predicated on the prior existence of some definition
which is expected to be unique to the included file;
we have chosen to test for a definition of the
.CW \%end.toc
macro,
which is
.EM not
required by the
.CW \%groff_toc
macro framework,
but which we plan to implement,
as part of our binding macro set.
.FE
to avoid unintentional repeated interpretation:
.DS I
.fam C
\&.\(rs" spdf\-toc.tmac
\&.\(rs"
\&.\(rs" Binding macros for use of the groff_toc macro framework,
\&.\(rs" in conjunction with the ms, and pdfmark macros.
\&.\(rs"
\&.if d toc.end .nx  \(rs" load this macro file only once
\&.ig
\&... specify copyright and licensing terms here ...
\&..
.DE
.
Following this file header,
and its repeat inclusion guard,
we may wish to test that certain prerequisite document processing
conditions will be satisfied.
For example,
it is common practice for
.CW \%groff
macro files to check that
.CW \%groff
is actually used as the document processing engine;\**
.FS
This particular test will be performed,
in any case,
when we include
.CW \%spdf.tmac ,
so we may simply delegate it thence.
.FE
however,
since we intend to use
.CW \%pdfroff
as the
.CW \%groff
driver,
we
.EM may \**
.FS
While the choice to use
.CW \%pdfroff
is a
.EM sufficient
condition to ensure that the document processing engine will be
.CW \%groff ,
this may not actually be a
.EM necessary
prerequisite for using our
.CW \%spdf-toc.tmac
binding macros;
the specification of this prerequisite test
should be considered as illustrative,
and may require review.
.FE
wish to enforce this:
.DS I
.fam C
\&.if !d pdfroff .ab aborting: please use pdfroff to format this document
.DE
.
After completing any such desired prerequisite condition checks,
the next step is to ensure that the macro packages,
to which
.CW \%spdf\-toc.tmac
specifies bindings,
are loaded:
.DS I
.fam C
\&.mso spdf.tmac       \(rs" incorporate the "ms" and "pdfmark" macros
\&.mso toc\-base.tmac   \(rs" augmented by the "groff_toc" framework
.DE
.EM before
proceeding to implement the required binding macros.
.
.LP
Considering the particular requirements for this document alone,
it may be noted that all of its table of contents entries
are derived from numbered section headings,
each of which is defined by calling
.CW \%spdf.tmac 's
.CWB XN
macro.
Thus,
to provide a minimal implementation which will meet our immediate requirements,
it should be sufficient to modify the behaviour of this particular macro.
.
.LP
As we've already seen,
in
.XR-NO-PREFIX xh-xn-macros ,
the
.CW XN
macro,
(and its companion,
the
.CW XH
macro),
each performs
.EM three
separate,
but related functions:
.QS
.sp -\n[PD]u
.IP \(bu
Each specifies text,
which is to be incorporated into the document body,
as a section heading.
.
.IP \(bu
The text of each such section heading is inserted into
the PDF document outline,
as a
.CW \%pdfhref
linked reference to the location,
within the document body,
of the section heading itself.
.
.IP \(bu
The text of each section heading is also made available
for inclusion into a table of contents,
under the control of the (possibly) \%user\(hydefined
.CW \%XH\-UPDATE\-TOC
callback macro.
.QE
.
Of these three functions,
we wish to modify
.EM only
the last.
Fortunately,
due to the design of the
.CW XH ,
and the
.CW XN
macros,
this may be readily accomplished,
by providing an appropriate replacement for
.CW \%spdf.tmac 's
implementation of the
.CW \%XH-UPDATE-TOC
macro;
noting that,
when it is called,
the first argument passed to this macro will
.EM always
represent a document outline nesting level,
while the second\Z','\|\**
.FS
In addition to representing some part of the substance
of a table of contents entry,
in the particular case of
.CW \%XH\-UPDATE\-TOC
having been called by the
.CW XN
macro,
(as is
.EM always
the case,
when formatting
.EM this
document),
the second argument represents a section heading number;
as such,
it may merit special handling
within the substantive scope of the table of contents entry.
.FE
and all remaining arguments,
represent the substance of the ensuing table of contents entry,
a tentative\*[em]albeit na\(:ive\*[em]replacement implementation
might look something like:
.DS I
.fam C
\&.de XH\-UPDATE\-TOC
\&.\(rs" Record data for construction of a table of contents entry
\&.\(rs"
\&.   toc put outline \(rs\(rs$1  \(rs" record outline nesting level ...
\&.   shift             \Z'  '    \(rs" ... and move it out of the way
\&.   toc put refmark \(rs\(rs$*  \(rs" record reference context ...
\&.   toc put pageref \(rs\(rsn%  \(rs" ... and location
\&..
.DE
.
It may be noted that,
unlike the simplistic example presented in
.pdfhref F SECREF L -D toc-interpretation -A ,
.pdfhref F
this tentative implementation of
.CW \%XH\-UPDATE\-TOC
requires
.EM three
supplementary \%user\(hydefined macros,
namely
.CW toc.outline \(rq, \%\(lq
.CW toc.refmark \(rq, \%\(lq
and
.CW toc.pageref \(rq, \%\(lq
serving as extensions to the
.CW \%groff_toc
framework;
the implementation of these will be discussed later,
with a separate section devoted to each.
.
However,
the na\(:ivety of this tentative implementation
does raise a number of issues:
.QS
.sp -\n[PD]u
.IP \(bu
If the proposed prerequisite for use of
.CW \%pdfroff
is honoured,
then the included
.char ^ \h'0.4n'
.char _ \h'0.8n'
.CW .toc_put^... \(rq \%\(lq
.rchar _ ^
macro calls will produce a potentially considerable quantity of visible,
and not particularly useful,
noise on the
.CW \%stdout
diagnostic stream,
during
.CW \%pdfroff 's
final document publication phase;
this may be avoided by checking for the existence of
.CW \%pdfroff 's
.CWB PHASE \& \& \(rq \%\(lq
register,
when
.CW \%XH\-UPDATE\-TOC
is first invoked,
and when this register has been defined,
with any positive \%non\(hyzero value,
redefine
.CW \%XH\-UPDATE\-TOC
itself,
to do nothing on subsequent invocations,
and then immediately exit,
without doing anything more;
this may be achieved,
for example,
by modifying the preceding tentative definition of
.CW \%XH\-UPDATE\-TOC
as follows:
.DS I
.fam C
\&.de XH\-UPDATE\-TOC
\&.\(rs" Record data for construction of a table of contents entry
\&.\(rs"
\&.\(rs" If pdfroff's PHASE register is defined, with any positive
\&.\(rs" non-zero value, this macro has nothing to do, for this or
\&.\(rs" any subsequent call; redefine it as empty, for subsequent
\&.\(rs" calls, then immediately exit.
\&.\(rs"
\&.   if r PHASE \(rs{.if \(rs\(rsn[PHASE] \(rs{.de \(rs\(rs$0 return
\&.      return
\&.   \(rs}\(rs}
\&.
\&.\(rs" If we get this far, record the requisite reference data.
\&.\(rs"
\&.   toc put outline \(rs\(rs$1  \(rs" record outline nesting level ...
\&.   shift             \Z'  '    \(rs" ... and move it out of the way
\&.   toc put refmark \(rs\(rs$*  \(rs" record reference context ...
\&.   toc put pageref \(rs\(rsn%  \(rs" ... and location
\&..
.DE
.sp -\n[PD]u
.IP \(bu
The tentative implementation provides no mechanism for exploiting the
.CW \%pdfhref
feature of the
.CW \%pdfmark
macros,
to create any links between the table of contents
and the material to which it refers.
To rectify this omission,
if we arrange for our
.CW toc.refmark \(rq, \%\(lq
and
.CW toc.pageref \(rq \%\(lq
macro calls to assemble,
and ultimately emit the constructed table of contents entry,
in the form of a
.DS I
.fam C
\&.pdfhref L \-D <\fIcollected-reference-data\fP>
.DE
macro call,
and recognizing that,
within the
implementation of the
.CW XN
macro,
as provided by
.CW \%spdf.tmac ,
the
.CW \%XH\-UPDATE\-TOC
macro call is
.EM always
preceded by a
.CW .pdfhref\h'0.7n'O\h'0.4n'... \(rq \%\(lq
call,
then we might choose to replace the
.DS I
.fam C
\&.toc put refmark \(rs\(rs$*  \(rs" record reference context ...
\&.toc put pageref \(rs\(rsn%  \(rs" ... and location
.DE
macro calls,
within our tentative
.CW \%XH\-UPDATE\-TOC
implementation,
with something like:
.DS I
.fam C
\&.\(rs" Record the table of contents reference context ...
\&.\(rs"
\&.   toc put refmark \(rs\(rs*[PDFBOOKMARK.NAME] \-\- \(rs\(rs$*
\&.
\&.\(rs" ... and corresponding page number reference.
\&.\(rs"
\&.   toc put pageref \(rs\(rsn%
.DE
.
Alternatively,
we may wish to incorporate some structural layout controls,
as employed in this document,
into the development of our
.CW \%XH\-UPDATE\-TOC
replacement\Z','\|\**
.FS
Notice that,
in this discussion of
.CW \%XH\-UPDATE\-TOC
macro replacements,
it is implicitly assumed that
.EM all
table of contents entries are to be derived from numbered section headings,
each of which has been specified using the
.CW XN
macro,
in conjunction with the
.CW NH
macro;
this limitation may be particularly relevant,
in the case of the implementation which is currently under discussion.
.FE
and accompanying
.CW \%groff_toc
extension macros.
.
For example,
to emulate the indentation and vertical spacing style
of the table of contents in this document,
in which
.EM all
entries are specified by calling the
.CW XN
macro,
and all are linked to the material to which they refer,
we might rewrite the
.CW \%XH\-UPDATE\-TOC
macro,
beginning with the
.CW \%stdout
noise suppression preamble,
as suggested above:
.DS I
.fam C
\&.de XH\-UPDATE\-TOC
\&.\(rs" Record data for construction of a table of contents entry
\&.\(rs"
\&.\(rs" If pdfroff's PHASE register is defined, with any positive
\&.\(rs" non-zero value, this macro has nothing to do, for this or
\&.\(rs" any subsequent call; redefine it as empty, for subsequent
\&.\(rs" calls, then immediately exit.
\&.\(rs"
\&.   if r PHASE \(rs{.if \(rs\(rsn[PHASE] \(rs{.de \(rs\(rs$0 return
\&.      return
\&.   \(rs}\(rs}
\&.
.DE
.KS
We then follow this with a modified implementation of
the reference data recording sequence;
the initial step,
which is responsible for recording the outline nesting level,
remains functionally unchanged,
.EM except
that we
.EM "do not"
immediately discard the associated macro argument:
.DS I
.fam C
\&.\(rs" If we get this far, record the requisite reference data,
\&.\(rs" beginning with the outline nesting level ...
\&.\(rs"
\&.   toc put outline \(rs\(rs$1
\&.
.DE
.KE
.KS
In the next step,
we see the predominant functional changes;
we need to embed not only the associated reference name,
but also font size,
font style,
and spacing controls into the assembled reference text,
which will ultimately be entered into the table of contents,
using a
.CW pdfhref\h'0.7n'L\h'0.7n'\-D\h'0.4n'... \(rq \%\(lq
macro call:
.DS I
.fam C
\&.\(rs" ... following up with the outline reference name, and
\&.\(rs" document section number, as established by a prior .NH
\&.\(rs" macro call ...
\&.\(rs"
\&.   ds toc@refmark.text "\(rs\(rs*[PDFBOOKMARK.NAME] \-\- \(rs"
\&.   ie \(rs\(rs$1=1 \(rs{\(rs
\&.   \(rs" ... with font size increment, emboldening, and spacing
\&.   \(rs" adjustment, as appropriate for top level headings ...
\&.   \(rs"
\&.      as toc@refmark.text "\(rss'+1z'\(rsfB\(rsZ'\(rs\(rs$2'\(rsfP\(rss'-1z'\(rs"
\&.      as toc@refmark.text "\(rsh'1.5n+\(rsw!0.!u'\(rss'+1z'\(rsfB\(rs"
\&.   \(rs}
\&.   \(rs" ... while maintaining normal font size, and style, for
\&.   \(rs" all levels of sub\-headings.
\&.   \(rs"
\&.   el .as toc@refmark.text "\(rs\(rs$2\(rsh'1.5n'\(rs"
\&.
\&.\(rs" Discard the two arguments, which have been interpreted
\&.\(rs" already, append all remaining arguments to the assembled
\&.\(rs" reference data record, export it, and clean up.
\&.\(rs"
\&.   shift 2
\&.   toc put refmark \\*[toc@refmark.text]\\$*\h'0.5n'
\&.   rm toc@refmark.text
\&.
.DE
.KE
.KS
Finally, we complete the amended
.CW \%XH\-UPDATE\-TOC
macro definition,
with one more functionally unchanged step,
to record the page number reference:
.DS I
.fam C
\&.\(rs" Finally, append a page number reference, to wrap up
\&.\(rs" this table of contents entry record.
\&.\(rs"
\&.   toc put pageref \(rs\(rsn%
\&..
.DE
.KE
.sp -\n[PD]u
.IP \(bu
In every variant of the tentative
.CW \%XH\-UPDATE\-TOC
replacement macro,
which has been discussed up to this point,
it has been assumed that the page number,
to be included within the recorded table of contents reference data,
is
.EM always
represented by the value of the
.CW \(rsn% \(rq \%\(lq
register.
.
While this may be a reasonable assumption,
in a majority of cases,
it
.EM "cannot be guaranteed"
to be valid in
.EM every
case.
.
For example,
in this document the value of the
.CW \(rsn% \(rq \%\(lq
register,
as set by a
.CW .pn \(rq, \%\(lq
or a
.CW .bp \(rq \%\(lq
request,
is occasionally,
and artificially reset to one,
while tracking the progression of the
.EM true
page number in a \*[em supplementary but] not persistently
.CW \(rsn[%%] \(rq \%\*[em updated \(lq]
register,
in order to take advantage of an
.CW ms
feature,
whereby page headers are not
.EM normally \^\**
.FS
This \(lqnormal\(rq behaviour of
.CW ms
printing control may be disabled,
by invocation of the
.CW .P1
macro;
unfortunately,
the effect of this is \*[em irreversible without] delving into
the undocumented internals of the
.CW ms
macros.
.FE
printed on any page which has an
.EM effective
page \*[em number as] represented by the
.CW \(rsn% \(rq \(lq
\*[em register of] one.
.
However,
since this document's
.CW \(rsn[%%] \(rq \%\(lq
register is defined
.EM only
when the
.EM true
and
.EM effective
page numbers differ,
.ne 8v+\n[DD]u
the required behaviour may be readily accommodated
by adaptation of the final step in the
.CW \%XH\-UPDATE\-TOC
replacement macro:
.DS I
.fam C
\&.\(rs" Finally, append a page number reference, to wrap up
\&.\(rs" this table of contents entry record.
\&.\(rs"
\&.   ie r %% .toc put pageref \(rs\(rsn(%%
\&.   el .toc put pageref \(rs\(rsn%
\&..
.DE
.sp -\n[PD]u
.IP \(bu
Notwithstanding that the replacement
.CW \%XH\-UPDATE\-TOC
macro implementation,
as discussed up to this point,
should deliver satisfactory results
when invoked via any call to the
.CW XN
macro,
it must be recognized that this
.EM same
macro can also be invoked via calls to the
.CW XH
macro,
in the event of which its behaviour may be less satisfactory.
.
.IP
Adaptation of the replacement implementation,
as illustrated thus far,
to deliver satisfactory behaviour when invoked via
.CW XH
macro calls,
.EM exclusively ,
should be fairly straightforward,
and is left as an exercise for the reader.
.
Adaptation to interoperate with
.EM both
.CW XH
and
.CW XN
macro calls
.EM interchangeably ,
while delivering a consistent layout,
is a work in progress;
in the meantime,
this too is left as an exercise for the reader\Z'.'\|\**
.FS
The appendices to this document do,
in fact,
use the
.CW XH
macro to introduce section headings,
in a manner which
.EM appears
to be compatible with this implementation of
.CW \%XH\-UPDATE\-TOC ;
this is made possible
.EM only
by ensuring that,
when
.CW XH
is called,
the argument which is specified immediately following its
.CWI outline\-level > \%<
argument,
resembles a section number,
and thus appears,
to
.CW \%XH\-UPDATE\-TOC ,
as if it had been called by
.CW XN .
.FE
.
.IP \(bu
The replacement
.CW \%XH\-UPDATE\-TOC
macro,
as illustrated,
neither uses,
nor does it offer any mechanism for supporting,
the
.CW XS ,
.CW XA ,
or
.CW XE
macros,
which are central to the traditional
.CW ms
table of contents collation technique;
neither does this
.CW \%groff_toc
based implementation offer any method
for specifying table of contents entries,
other than those which are derived from section headings
which have been interpolated by the \%GNU\(hyspecific
.CW XN
macro,
or\*[em]to some extent\*[em]by the similarly \%GNU\(hyspecific
.CW XH
macro.
.
Thus,
users who require such capabilities
would need to extend the implemention,
to satisfy their own needs;
once again,
development of such an extended implementation
is left as an exercise for the reader.
.QE
.
Based on a combination of appropriate macro fragments,
abstracted from the preceding discussion,
and with the addition of some logic to control its interaction with
.CW \%groff
diversions,
a listing of the complete implementation for a replacement
.CW \%XH\-UPDATE\-TOC
macro,
as used in the production of this publication,
may be found in
.XR-NO-PREFIX toc-collector .
.
.NH 4
.XN -S -N toc-side-effects -- Managing \%Side\(hyEffects of \#
 \FCgroff_toc\F[] Macro Bindings
.LP
In general,
any \%side\(hyeffects exhibited by a suite of binding macros,
which have been developed along the lines discussed in
.pdfhref F SECREF L -D mspdf-toc-binding -A ,
will be innocuous.
There is,
however,
one noteworthy exception:
the use of the
.CW .pdfhref \ \c \%\(lq
.CW L \ \c
.CW ... \(rq
macro call,
to format each,
and every page reference entry,
will result in the entire text of the table of contents\*[em]with
the exception of any initial heading\*[em]being
rendered in whatever colour is specified for
.CW \%PDFHREF.TEXT.COLOUR .
.
.LP
While some authors may be willing to accept this text colour effect\Z','\|\**
.FS
Note that this colour effect is caused by the use of the
.CW .pdfhref \ \c \%\(lq
.CW L \ \c
.CW ... \(rq
macro,
which is introduced by binding with the
.CW \%pdfmark
macro package.
Thus,
it will be observed for any bindings which incorporate this package;
it is
.EM not
restricted to bindings with the
.CW ms
macro package,
as illustrated in
.pdfhref L -D mspdf-toc-binding -A .
.FE
many will find it undesirable,
and distracting.
Fortunately,
the effect may be readily mitigated,
by temporary reassignment of the
.CW \%PDFHREF.TEXT.COLOUR
specification\Z','\|\**
.FS
Note that,
.EM before
simply reassigning the value of
.CW \%PDFHREF.TEXT.COLOUR ,
its default assignment
.EM must
be removed;
this is necessary,
to avoid implicit reassignment of its associated
.CW \%PDFHREF.TEXT.COLOR
alias,
in which it is desired to retain the default setting.
.FE
.EM before
scheduling the output the table of contents:
.DS I
.fam C
\&.\(rs" Break PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR equivalence,
\&.\(rs" then reassign PDFHREF.TEXT.COLOUR, (which is given precedence),
\&.\(rs" to match the normal running text colour.
\&.\(rs"
\&.rm PDFHREF.TEXT.COLOUR
\&.ds PDFHREF.TEXT.COLOUR "\(rsn(.m\(rs"
\&.\(rs"
\&.\(rs" Insert instructions for incorporation of the TOC, here ...
.DE
and subsequently,
delete this temporarily assigned specification,
allowing the next invocation of
.CW .pdfhref \ \c \%\(lq
.CW L \ \c
.CW ... \(rq
to
.EM automatically
reinstate the default
.CW \%PDFHREF.TEXT.COLOR
equivalence:
.DS I
.fam C
\&.\(rs" Discard our overriding PDFHREF.TEXT.COLOUR assignment, thus
\&.\(rs" scheduling automatic reinstatement of the normal equivalence
\&.\(rs" of PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR by pdfhref
\&.\(rs"
\&.rm PDFHREF.TEXT.COLOUR
.DE
.pdfhref F
Bracketting of the instructions,
for formatting of the table of contents,
between a pair of request fragments such as those illustrated above,
will produce page references in the default body text colour;
for convenience,
the functionality which is provided by these two request fragments
may be encapsulated within a further binding macro,
.ne 3v
such as that suggested in
.XR-NO-PREFIX toc-colour ,
which may be incorporated into
the \%user\(hyprovided binding macro package.
.
.NH 3
.XN -N selective-toc -- Classification and Selective Processing \#
of Table of Contents Entries
.LP
While many documents will require only a single table of contents listing,
usually placed before the running text of the document body,
and the capabilities of the
.CW \%toc\-base.tmac
macro package are generally sufficient
to produce such a listing,
some documents\*[em]notably those of a technical nature\*[em]may
benefit from the inclusion of more than one such listing\*[em]all
similar in style,
but each logically distinct in terms of context.
For example,
in addition to the normal table of contents,
.ne 2v
it may be desirable to include a separate list of figures,
or a list of equations,
list of data tables,
or other similar entities,
or indeed,
any combination of such entities.
.
.LP
In any case where only a single table of contents listing is required,
then this may be produced by adopting the techniques described in earlier
subsections of
.pdfhref F SECREF L -D toc-alternatives -A ;
.pdfhref F
for those cases where the production of additional listings,
in the style of a table of contents
but logically distinct in context,
is required,
then the extended capabilities of the
.CW \%toc\-class.tmac
variant of the
.CW \%groff_toc
macro framework may be found to be useful\Z'.'\|\**
.FS
Although this document,
itself,
does not incorporate any such contextually distinct listings,
in the style of a table of contents,
it
.EM does
use this extended variant of the
.CW \%groff_toc
framework,
to isolate selected subdivisions of the table of contents itself,
and to reproduce them within its appendices.
.FZ .
.
.LP
The
.CW \%toc\-class.tmac
extension to the
.CW \%groff_toc
macro framework may be activated
by specification of the
.CWB \-m \& \& \ \c \%\(lq
.CWB toc\-class \& \& \(rq
command line option,
when invoking
.CW \%groff ,
(either directly,
or via a driver program such as
.CW \%pdfroff ).
Alternatively\*[em]perhaps more conveniently\*[em]the
same effect may be achieved,
by including the request:
.DS I
.CW .mso\ toc\-class.tmac
.DE
in a binding macro file,
which is provided by the user.
.
In either case,
as a side effect,
the
.CW \%toc\-base.tmac
macro framework file will also be activated\*[em]it
is unnecessary to load it separately.
.
.LP
In addition to the basic features supported by the
.CW \%toc\-base.tmac
macro framework,
as described in
.pdfhref F SECREF L -D toc-usage -A ,
.pdfhref F
activation of the
.CW \%toc\-class.tmac
extension makes the following
.CWB .toc
macro operations available:
.QS
.sp -\n[PD]u
.char & \F[]\h'\w";"u'\FC
.IP \FC\fB.toc&activate\fP&[\fIclass\fP&...]\F[]
Typically used
.EM only
internally,
during table of contents reference data collection,
to propagate table of contents entry classification requests,
from any document input data stream,
through the collected data interpolation procedure,
to the resultant document output data stream.
.
.IP \FC\fB.toc&classify\fP&[\fIclass\fP&...]\F[]
Insert a
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB activate \& \& \h'\w!r!u'\c
.CWI class \& [ \h'\w!r!u'\c
.CW ...] \(rq
request into the table of contents reference data collection stream,
specifying that each subsequently recorded reference is to be classified
such that it becomes associated with each of the specified,
arbitrarily named
.CW class
arguments,
(if any).
.IP
If
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB classify \& \& \(rq
is invoked
.EM without
specifying any
.CW class
arguments,
any subsequently recorded references will be considered to be
.EM unclassified ,
(as are any which are recorded before the first of any invocations of
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB classify \& \& \h'\w!r!u'\c
.CWI class \& \& \h'\w!r!u'\c
.CW ... \(rq,
which
.EM does
specify
.CW class
arguments);
this unclassified state prevails until any subsequent invocation of
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB classify \& \& \h'\w!r!u'\c
.CWI class \& \& \h'\w!r!u'\c
.CW ... \(rq,
.EM with
.CW class
arguments.
.IP
Successive invocations of
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB classify \& \& \h'\w!r!u'\c
.CWI class \& \& \h'\w!r!u'\c
.CW ... \(rq,
each of which specifies one,
or more
.CW class
arguments,
will result in a complete
.EM replacement
of the
.CW class
associations for any subsequently recorded
table of contents references;
the classification effect is
.EM not
cumulative.
.
.IP \FC\fB.toc&classified\fP&\fIopcode\fP&...\F[]
Attach a classification filter to each of the
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \(rq
service macros,
associated with each specified
.CWI opcode
argument;
each of these associated service macros
.EM must
have been fully defined,
.EM before
calling
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB classified \& \& \(rq
with its
.CWI \%opcode
as an argument.
.IP
Internally,
each associated
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \(rq
macro is renamed as
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \c
.CWB .classified \& \& \(rq,
and
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \(rq
is redefined as an alias for an internal
classification filter macro;
this filter intercepts calls to the original
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \(rq
macro,
and forwards them to
.CWB .toc. \& \& \c \%\(lq
.CWI opcode \& \& \c
.CWB .classified \& \& \(rq,
.EM only
when interpolating a table of contents reference which is
.EM not
classified as being a member of an actively excluded reference class,
and then is
.EM either
a member of an actively selected reference class,
.EM or
there is no actively selected reference class.
.
.IP \FC\fB.toc&exclude\fP&[\fIclass\fP&...]\F[]
Specify zero,
or more table of contents reference classes,
the member records of each of which are to be actively
excluded from the ensuing output data stream,
when table of contents reference data is interpolated.
.IP
Each successive call to
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB exclude \& \& \h'\w!r!u'\c
.CWI class \& \& \h'\w!r!u'\c
.CW ... \(rq
.EM replaces
any previously active list of excluded classes;
if called
.EM without
.CW class
arguments,
.EM all
active exclusions are
.EM cancelled .
.
.IP \FC\fB.toc&select\fP&[\fIclass\fP&...]\F[]
Specify zero,
or more table of contents reference classes,
the member records of each of which are to be actively
.EM included
in the ensuing output data stream,
when table of contents reference data is interpolated.
.IP
Each successive call to
.CWB .toc \& \& \h'\w!r!u'\c \%\(lq
.CWB select \& \& \h'\w!r!u'\c
.CWI class \& \& \h'\w!r!u'\c
.CW ... \(rq
.EM replaces
any previously active class selections;
if called
.EM without
.CW class
arguments,
.EM all
active selections are
.EM cancelled .
.IP
If the collected table of contents reference data includes
.EM unclassified
records,
these will be included in the output data stream,
.EM only
if there is no active class selection,
when the reference data is interpolated.
.rchar &
.QE
.
Having adopted the
.CW \%toc-class.tmac
extension of the
.CW \%groff_toc
macro framework,
in order to use its extended features
.EM effectively ,
calls to any \%user\(hydefined macro which participates in
the ultimate interpolation of table of contents reference data,
into the output data stream,
should be redirected through the classification filter.
In the case of the trivial example,
as illustrated in
.XR-NO-PREFIX toc-interpretation ,
this may be accomplished by invoking:
.DS I
.fam C
\&.toc classified pageref
.DE
.EM after
the
.CW toc.pageref \(rq \%\(lq
macro has been defined,
whereas,
in the more complex example illustrated in
.XR-NO-PREFIX mspdf-toc-binding ,
it becomes necessary to invoke:
.DS I
.fam C
\&.toc classified outline refmark pageref
.DE
after
.EM all
of the
.CW toc.outline \(rq, \%\(lq
.CW toc.refmark \(rq, \%\(lq
and
.CW toc.pageref \(rq \(lq
macros have been defined.
Then,
to ensure that each recorded table of contents reference
is appropriately classified,
interpose:
.DS I
.fam C
\&.toc classify \fIclass\fP ...
.DE
or:
.DS I
.fam C
\&.toc classify
.DE
macro calls,
at appropriate locations throughout the document input file(s),
to activate,
or respectively\*[em]assuming that unclassified records are used
to define the basic table of contents\*[em]to cancel classification,
as may be necessary.
.LP
After completion of the foregoing steps,
to classify the recorded table of contents reference data,
and to ensure that the classified entries can be appropriately filtered,
the collected reference data may be
.EM selectively
interpolated into the document output stream,
.EM before
completing the:
.DS I
.fam C
\&.toc file \fIrefdata.toc\fP
.DE
assignment.
For example,
if the objective is to produce a conventional table of contents,
followed by a separate list of figures,
the conventional table of contents references may be collected
.EM without
classification,
while those references which are to be incorporated into
the list of figures may be identified by association with
a class name such as
.CW figrefs \(rq, \%\(lq
which may be assigned by the use of code similar to:
.DS I
.fam C
\&.toc classify figrefs
\&.\(rs" Code to generate figure goes here...
\&.toc put pageref \(rsn% "Caption for figure ..."
\&.toc classify
.DE
to encapsulate each figure,
at the point where it appears
within the document input file(s).
.
.LP
Having specified the
.EM unclassified
table of contents entries,
and appropriately
.EM classified
list of figures entries,
within the collected
.CW \%refdata.toc
file\Z','\|\**
.FS
Note that this concept is
.EM not
restricted to segregation of just the two
tables of content reference categories;
.EM any
arbitrary number of additional reference classes may be specified,
and reference entries may then be distributed amongst them,
to achieve any desired segregation of reference categories
into separate arbitrarily identified tables.
.FE
as described above,
the content of this file may be interpreted
.EM twice \*[em]or
even more often,
if more than two distinct tables of content types are required\*[em]subject
to distinct constraints in each case,
in order to interpolate,
for example,
a table of contents,
followed by a
.EM separate
list of figures;
a typical interpolation sequence might be:
.
.RS
.nr ITEM 0 1
.nr LL -\n[QI]u
.ITEMIZE
Apply mitigation for any undesired text colour effects,
as previously discussed in
.XR-NO-PREFIX toc-side-effects .
.
.ITEMIZE
Ensuring that the following output will commence at
the top of a new page\*[em]typically,
this would be a new recto page\*[em]emit
a \(lqTable of Contents\(rq heading,
specify a
.CW toc \ \c \(lq
.CW class \ \c
.CW ... \(rq
exclusion list,
for entries of
.EM all
reference categories which are
.EM not
intended to appear
within the primary table of contents\*[em]for example,
the
.CW figrefs \(rq \%\(lq
class\*[em]and process the
.CW \%refdata.toc
file,
to interpolate those
.EM unclassified
reference entries which comprise the table of contents:
.DS I
.fam C
\&.\(rs" Assume that the output position is at the top of page;
\&.\(rs" disable filling, set tabs to mark the beginning, and the
\&.\(rs" end of the page number field, emit a centred heading for
\&.\(rs" the "Table of Contents", and interpolate the associated
\&.\(rs" references, excluding those for the "List of Figures".
\&.nf
\&.ta (u;\(rsn[.l]-\(rsw\(aq00000\(aq) \(rsn[.l]uR
\&.ce 1
\&.nop \(rsfB\(rss\(aq+2z\(aqTable of Contents\(rss\(aq-2z\(aq\(rsfP
\&.sp 2v
\&.toc exclude figrefs
\&.so refdata.toc
.DE
and then,
finish this step in the sequence,
by cancelling the
.CW toc \ \c \(lq
.CW class \ \c
.CW ... \(rq
exclusion list,
which was responsible for selection of
.EM only
those reference entries which
.EM do
belong in the table of contents:
.DS I
.fam C
\&.\(rs" Cancel exclusion of all reference classes which
\&.\(rs" were not to be included in the table of contents;
\&.\(rs" in the example above, this was just the figrefs
\&.\(rs" class.
\&.\(rs"
\&.toc exclude
.DE
.
.ITEMIZE
Move forward to another new page,
emit a suitable heading for an alternative class
of content category references\*[em]for example,
a \(lqList of Figures\(rq\*[em]specifying
a corresponding
.CW toc \ \c \(lq
.CW class \ \c
.CW ... \(rq
selection list,
and process the
.CW \%refdata.toc
file one further time,
to interpolate the reference table for
the corresponding content category:
.DS I
.fam C
\&.\(rs" Advance to another new page, emit a centred heading for
\&.\(rs" the "List of Figures", and interpolate the reference data
\&.\(rs" once again, selecting ONLY those references which are to
\&.\(rs" be included within the list of figures.
\&.bp
\&.ce 1
\&.nop \(rsfB\(rss\(aq+2z\(aqList of Figures\(rss\(aq-2z\(aq\(rsfP
\&.sp 2v
\&.toc select figrefs
\&.so refdata.toc
.DE
.
.ITEMIZE
.nr PREVIOUS-STEP \n[ITEM]-1
Repeat step \s'-2z'(\n[PREVIOUS-STEP])
.NL
as often as may be required,
substituting appropriate alternative headings,
and corresponding
.CW toc \ \c \(lq
.CW class \ \c
.CW ... \(rq
selection list specifications,
in order to interpolate any other desired
tables of classified content references,
such as lists of equations,
lists of data tables,
etc.
.
.ITEMIZE
When all of the desired tables of content categories have been interpolated,
the reference data interpolation context may be cleaned up,
any mitigation for undesirable text colour effects may be cancelled,
and the reference data collector may be initialized:
.DS I
.fam C
\&.\(rs" Clean up table of contents interpolation context,
\&.\(rs" cancelling all currently active toc class selections,
\&.\(rs" and any active text colour effect mitigation, then
\&.\(rs" initialize the reference data collection stream.
\&.\(rs"
\&.toc select
\&.rm PDFHREF.TEXT.COLOUR
\&.toc file refdata.toc
.DE
.
.ITEMIZE
Finally,
prepare for formatting of the document body;
typically,
this would also commence on yet another new page\Z','\|\**
.FS
Normal printing conventions dictate that
the start of the document body should be placed on a new
.EM recto
page;
a technique for ensuring this,
which may be adopted in place of the simple
.CW .bp
request of the above example,
is discussed in
.XR-NO-PREFIX force-recto-verso .
.FE
without any residual need for
the tabulation settings of the table of contents,
and with text filling enabled:
.DS I
.fam C
\&.\(rs" Finally, advance to another new page, where output of
\&.\(rs" the document body content is to begin, reset tabs, and
\&.\(rs" enable text filling.
\&.bp
\&.ta
\&.fi
.DE
.nr LL +\n[QI]u
.RE
.
In practice,
the preceding sequence of operations would be incorporated
into the document source file\Z','\|\**
.FS
Notice that this strategy results in attempted interpolation of
the content of the
.CWI refdata.toc \& \& \^\(rq \%\(lq\h'-\w!\^!u'
file,
.EM before
its content has been collected.
Since this content is collected during processing by
.CW groff ,
at least one preliminary pass\*[em]and preferably two,
since page numbers may be offset from their ultimately correct values,
after just one pass\*[em]through
.CW groff \h'\w!r!u'\c \%\(lq
.CW \-z \(rq,
to prepare the
.CWI refdata.toc \& \& \^\(rq \%\(lq\h'-\w!\^!u'
file for ultimate
.CW \%groff
output processing.
All such necessary preliminary processing passes
will be performed automatically,
if
.CW \%pdfroff
is chosen as the
.CW \%groff
process driver program.
.FE
.EM after
any desired \%front\(hymatter content has been specified\Z','\|\**
.FS
In the unlikely event that any table of contents references
are to be incorporated into the \%front\(hymatter,
it will be necessary to implement some strategy
to defer recording of the associated reference data,
until
after the
.CW .toc \h'\w!r!u'\c \%\(lq\h'-\w!\^!u'
.CW file \h'\w!r!u'\c
.CWI refdata.toc \& \& \^\(rq
assignment has been completed.
.FE
but
.EM before
commencing the specification of the document body content\Z'.'\|\**
.FS
The
.CW .toc \h'\w!r!u'\c \%\(lq\h'-\w!\^!u'
.CW file \h'\w!r!u'\c
.CWI refdata.toc \& \& \^\(rq
assignment
.EM must
have been completed
.EM before
the first of any table of contents reference data collection requests
appears in the document body specification;
since execution of the
.CW .toc \h'\w!r!u'\c \%\(lq\h'-\w!\^!u'
.CW file \h'\w!r!u'\c
.CWI refdata.toc \& \& \^\(rq
assignment effectively clobbers all previously existing content in the
.CWI refdata.toc \& \& \^\(rq \%\(lq\h'-\w!\^!u'
file,
the effect of any attempt to interpolate
the table of contents reference data again,
.EM after
this file assignment has been completed,
is undefined;
however,
this limitation will
.EM not
be observed,
if
.CW \%pdfroff
is employed as the
.CW \%groff
process driver program.
.FE
.
.
.mso appendix.tmac
.mso fdl-setup.tmac
.
.XH-APPENDIX-NUMBER-FORMAT A i
.ds FDL-APPENDIX-TITLE "GNU Free Documentation License\"
.ds FDL-APPENDIX-CONTEXT "The \*[FDL-APPENDIX-TITLE]\"
.XH-APPENDIX \*[FDL-APPENDIX-CONTEXT]
.
.ds XH-APPENDIX-CONTEXT "Appendix \\n[XH-APPENDIX-NUMBER], \(lq\\$*\(rq\"
.ds FDL-APPENDIX-CONTEXT "\*[XH-APPENDIX-CONTEXT \*[FDL-APPENDIX-CONTEXT]]\"
.ds FDL-APPENDIX-NUMBER "\n[XH-APPENDIX-NUMBER]\"
.ds FDL-APPENDIX-LINK "\*[PDFBOOKMARK.NAME]\"
.
.so fdl-v1.3.ms
.
.TC-DEFINE HS1 "1.5n-\w!.\ !u"
.als PDFHREF.INFO PDFHREF.INFO.APPENDIX
.
.nr XH-APPENDIX-SP 1i
.ds FDL-TYPESETTING "Typesetting the \*[FDL-APPENDIX-TITLE]\"
.XH-APPENDIX \*[FDL-TYPESETTING]
.ds FDL-TYPESETTING "appendix \n[XH-APPENDIX-NUMBER] \*[FDL-TYPESETTING]\"
.pdfhref D -N \*[PDFBOOKMARK.NAME] \*[FDL-TYPESETTING]
.ds FDL-TYPESETTING-LINK "\*[PDFBOOKMARK.NAME]\"
.rm FDL-TYPESETTING
.LP
This appendix discusses,
and documents the procedure which has been adopted to typeset
the \*[FDL-APPENDIX-TITLE],
as it is presented in
.pdfhref L -D \*[FDL-APPENDIX-LINK] -A ; -- Appendix \*[FDL-APPENDIX-NUMBER]
the discussion is developed under the headings:
.toc classify Appendix-\n[XH-APPENDIX-NUMBER]
.sp \n[DD]u
.ns
.LP
.ll -\n[QI]u
.toc load -select Appendix-\n[XH-APPENDIX-NUMBER] pdfmark.toc
.sp \n[XH-APPENDIX-SP]u
.ll
.so fdl-typesetting.ms
.toc classify
.
.XH-APPENDIX Working Macros used for Typesetting this Publication
.LP
This appendix provides reference listings
for each of those macros which have been developed,
specifically to facilitate the production
of this publication.
Implemented on the basis that
the document is to be typeset using the
.CW \%pdfroff
program,
in conjunction with the
.CW ms
and
.CW \%pdfmark
macros,
(as they have been integrated,
and augmented,
within the
.CW \%spdf.tmac
implementation),
these \%document\(hylocal macros may be categorized
by section headings:
.
.toc classify Appendix-\n[XH-APPENDIX-NUMBER]
.sp \n[DD]u
.ns
.LP
.ll -\n[QI]u
.toc load -select Appendix-\n[XH-APPENDIX-NUMBER] pdfmark.toc
.sp \n[XH-APPENDIX-SP]u
.ll
.
.KS
.XH-APPENDIX-NH 1 text-style-macros \#
 Controlling the Style of Formatted Text
.LP
In addition to the standard
.CW ms
font styling macros,
this document uses a number of locally defined variants.
First,
for emphasis,
the text may be italicized,
with a 0.3 point increment in size,
using this variant of the
.CW I \(rq \(lq
macro:
.DS I
.fam C
\&.de EM
.char ' \(aq
\&.   I "\(rss'+0.3z'\(rs\(rs$1\(rss'-0.3z'" "\(rs\(rs$2" "\(rs\(rs$3"
.rchar '
\&..
.DE
Furthermore,
each of the following three variants of the
.CW CW \(rq \(lq
macro:
.DS I
.fam C
\&.de CWB
\&.   nop \(rs\(rs$5\(rsf(CR\(rs\(rs$3\(rsfP\(rsf(CB\(rs\(rs$1\(rsfP\c
.     nop \(rsf(CR\(rs\(rs$2\(rsfP\(rs\(rs$4
\&..
\&.de CWI
\&.   nop \(rs\(rs$5\(rsf(CR\(rs\(rs$3\(rsfP\(rsf(CI\(rs\(rs$1\(rsfP\c
.     nop \(rsf(CR\(rs\(rs$2\(rsfP\(rs\(rs$4
\&..
\&.de CWBI
\&.   nop \(rs\(rs$5\(rsf(CR\(rs\(rs$3\(rsfP\(rsf[CBI]\(rs\(rs$1\(rsfP\c
.     nop \(rsf(CR\(rs\(rs$2\(rsfP\(rs\(rs$4
\&..
.DE
will format the text of their first argument in
.EM "constant width bold" ,
.EM "constant width italic" ,
and
.EM "constant width \%bold\(hyitalic" ,
respectively;
in each case,
the text of the second and third arguments will be formatted
in the regular
.EM "constant width"
font,
as suffix and prefix respectively,
bracketting the text of the first argument,
.EM without
intervening space,
and the entire construct will be bracketted by
the text of the fourth and fifth arguments,
in the font of the running text,
again
.EM without
intervening space,
and again,
as suffix and prefix respectively.
.
.LP
Finally,
the variant string:
.DS I
.fam C
\&.ds = \(rsf(CB\(rs\(rs$1\(rsf(CR\(rs\(rs$4\(rsf[CBI]\c
.  nop  \(rs\(rs$2\(rsf(CR\(rs\(rs$3
.DE
offers a convenient mechanism for interpolating the
.CWI tag > < \(rq \(lq
argument to a
.CW .IP \(rq \(lq
macro call,
setting the text of the first string argument in the
.EM "constant width bold"
font,
followed by the second,
if specified,
in the
.EM "constant width \%bold\(hyitalic"
font,
bracketted by the third argument as suffix,
and the fourth argument as prefix,
each in the regular
.EM "constant width"
font,
and
.EM without
intervening space between
.EM any
of these interpolated string arguments.
.KE
.
.KS
.XH-APPENDIX-NH 1 new-recto-page \#
 Starting a Section on a New Recto Page\*[em]the \#
 \FCNEW\-RECTO\-PAGE\F[] Macro
.LP
Occasionally,
publishing convention will demand that a document section
should commence on the right hand (recto) page,
when the publication is printed,
and bound;
the
.CW \%NEW\-RECTO\-PAGE
macro,
which relies on features of the
.CW ms
macros,
and is implemented as defined below,
facilitates conformance with this convention:
.DS I
.fam C
\&.de NEW-RECTO-PAGE
\&.\(rs" Usage: .NEW\-RECTO\-PAGE <register\-name> [<page\-number\-format>]
\&.\(rs"
\&.\(rs" Advance to the next available odd\-numbered page, record
\&.\(rs" its page number in <register\-name>, set its effective page
\&.\(rs" number to one, and apply any <page\-number\-format> which
\&.\(rs" may have been specified, on this and subsequent pages.
\&.\(rs"
\&.\(rs" Initially, to facilitate comparison of page numbers, arabic
\&.\(rs" numeral formatting is required; assignment of an alternative
\&.\(rs" format, if specified by the optional second argument, must be
\&.\(rs" deferred until later.
\&.\(rs"
\&.   af % 0
\&.   af \(rs\(rs$1 0
\&.   ie \(rs\(rsn[\(rs\(rs$1] .nr \(rs\(rs$1 +1
\&.   el .nr \(rs\(rs$1 \(rs\(rsn%+1
\&.   if o \(rs{\(rs
\&.   \(rs" The current page number is odd, so advancing one page will
\&.   \(rs" make the page number even.  However, we want to advance to
\&.   \(rs" to the next available odd numbered page, so we must insert
\&.   \(rs" an additional blank page; we set this artificially to page
\&.   \(rs" number one, so that ms will not print the page number, but
\&.   \(rs" we do increment the true recorded number, so that this may
\&.   \(rs" be correctly restored later.
\&.   \(rs"
\&.      nr \(rs\(rs$1 +1
\&.      bp 1
\&.   \(rs}
\&.\(rs" Having guaranteed that we will land on an odd numbered page,
\&.\(rs" advance one page, once again setting the effective landing page
\&.\(rs" number to one, to suppress printing of the page number, while
\&.\(rs" arranging for correct numbering to resume on the immediately
\&.\(rs" following page.
\&.\(rs"
\&.   bp 1
\&.   pn 1+\(rs\(rsn[\(rs\(rs$1]
\&.
\&.\(rs" Only now, may an alternative page number format be assigned.
\&.\(rs"
\&.   af \(rs\(rs$1 \(rs\(rs$2 0
\&.   af % \(rs\(rs$2 0
\&..
.DE
.KE
It may be observed that,
as defined,
this implementation of the
.CW \%NEW\-RECTO\-PAGE
macro represents a consolidated adaptation of
the concepts developed in
.XR-NO-PREFIX force-recto-verso ,
(and in particular,
.XR-NO-PREFIX ms-page-advance ).
It does
.EM not
support the complementary
.CW \%NEW\-VERSO\-PAGE
capability,
(although it could be adapted to do so);
it
.EM does
set the
.EM effective
page number,
on the page to which it advances,
to
.EM one ,
to take advantage of the
.CW ms
macro feature which suppresses the printing of page headers
on any page which is so numbered,
while using a \%user\(hynominated backup register,
to record the
.EM real
page number\*[em]the user
.EM must
specify a suitable alternative
(i.e.\&
.EM not
.CW % \(rq) \(lq
page number register name for the
.CWI register\-name > \%<
argument,
(such as the
.CW %% \(rq \(lq
register which is used for this purpose,
in this publication),
to fulfil this requirement.
.
.LP
A practical
.EM disadvantage ,
which may arise from the use of a backup page number register
to record the real page number,
is that this register
.EM must
be updated for
.EM every
change of page number,
.EM if \/
it is to remain valid as a basis for page number references,
(such as those which are required when constructing a table of contents).
To avoid the burden of maintaining the progression of the
.CW %% \(rq \(lq
register,
in this publication,
it is defined
.EM only
when the
.CW % \(rq \(lq
has been assigned an artificial value of one,
and is subsequently destroyed when normal progression of the
.CW % \(rq \(lq
register is restored.
The
.CW %% \(rq \(lq
register is used as the basis for table of contents references,
when it exists;
its destruction is accomplished by adaptation of the
.CW HD
macro:
.DS I
.fam C
\&.am HD
\&.   if r%% \(rs{\(rs
\&.   \(rs" The "%%" register exists; it needs to remain, while the "%"
\&.   \(rs" register is artifically set to zero, or one, and be removed
\&.   \(rs" only after "%" has resumed its normal sequential progression;
\&.   \(rs" as within NEW-RECTO-PAGE, we need "%" to exhibit the arabic
\&.   \(rs" numeral format, to facilitate comparison, but must revert
\&.   \(rs" to any alternative which is borne by the "%%" register.
\&.   \(rs"
\&.      af % 0
\&.      if \(rs\(rsn%>1 \(rs{\(rs
\&.         af % \(rs\(rsg(%%
\&.         rr %%
\&.      \(rs}
\&.   \(rs}
\&..
.DE
which is invoked by an
.CW ms
page position trap,
at the start of
.EM every
new page;
after such destruction of the
.CW %% \(rq \(lq
register,
the basis for table of contents page number references
reverts to the
.CW % \(rq \(lq
register.
.
.bp
.XH-APPENDIX-NH 1 toc-compilation \#
 Generating and Typesetting the Table of Contents
.LP
The macros presented below
offer a (mostly) transparent replacement for
the standard capabilities of the
.CW ms
macros,
for the collection,
and subsequent collation of table of contents reference data,
which has been specified using either the
.CW XH ,
or the
.CW XN
macro;
(it has been designed,
primarily,
to support the latter).
.
.LP
When this implementation is deployed,
it will
.EM automatically
assume responsibility for collection
of table of contents reference data,
.EM without
any user intervention;
however,
it neither relies on,
nor supports,
.EM any
use of the
.CW XS ,
.CW XA ,
or
.CW XE
macros,
which are traditionally used in
.CW ms ,
for collation of tables of contents.
Furthermore,
it is incompatible with the traditional
.CW ms
technique of printing the table of contents
.EM after
the document body,
and relocating it later;
thus,
instead of using the
.CW TC
macro for this purpose,
.float needs 3v+\n(.Vu
the document source should incorporate code,
(illustrated with reference to the actual file name used for
.EM this
publication),
similar to:
.DS I
.fam C
\&.ce 1
\&\(rsfB\(rss\(aq+2z\(aqTable of Contents\(rss\(aq-2z\(aq\(rsfP
\&.sp 1.5v
\&.so pdfmark.toc
\&.toc file pdfmark.toc
\&.toc end
.DE
at the point where the table of contents is to appear,
in the ultimate document output.
.
.XH-APPENDIX-NH 2 toc-collector Table of Contents \#
 Reference Data Collection\*[em]the \FCXN\-UPDATE\-TOC\F[] Macro
.LP
Operating in conjunction with the
.CW ms
macros,
this replacement implementation of the
.CW \%XH\-UPDATE\-TOC
macro intercepts table of contents data collection calls,
originating from the
.CW XH ,
or the
.CW XN
macro calls,
thus overriding the standard
.CW ms
table of contents handling mechanism,
by redirecting the effects of such calls to corresponding handlers,
which have been implemented in terms of the
.CW \%groff_toc
macro framework.
.
.LP
The actual implementation of the
.CW \%XH\-UPDATE\-TOC
macro,
as it appears within the example
.CW \%spdf-toc.tmac
file,
distributed with
.CW \%groff\-pdfmark
and deployed in the production of
.EM this
publication,
is defined in two distinct parts;
.float needs 3v+\n(.Vu
the first of these,
which is a \%self-replacing stub,
and is invoked
.EM "at most"
once,
the first time
.CW \%XH\-UPDATE\-TOC
is called,
whether by
.CW XH
or by
.CW XN ,
is:
.DS I
.fam C
\&.de XH\-UPDATE\-TOC
\&.\(rs" Record data for construction of a table of contents entry
\&.\(rs"
\&.\(rs" If pdfroff's PHASE register is defined, with any positive
\&.\(rs" non-zero value, this macro has nothing to do, for this or
\&.\(rs" any subsequent call; redefine it as empty, discarding its
\&.\(rs" ultimate replacement, for all subsequent calls, and then
\&.\(rs" immediately exit ...
\&.\(rs"
\&.   if r PHASE \(rs{.if \(rs\(rsn[PHASE] \(rs{.rm \(rs\(rs$0\-ULTIMATE
\&.      de \(rs\(rs$0 return
\&.      return
\&.   \(rs}\(rs}
\&.
\&.\(rs" ... but, when the PHASE register is either not defined, or
\&.\(rs" if it is defined, but it does not have a positive non\-zero
\&.\(rs" value, then install the ultimate replacement for this stub
\&.\(rs" implementation of the XH\-UPDATE\-TOC macro, then continue
\&.\(rs" execution, by passing control on to it.
\&.\(rs"
\&.   rn \(rs\(rs$0\-ULTIMATE \(rs\(rs$0
\&.   \(rs\(rs$0 \(rs\(rs$@
\&..
.DE
.
.float begin
.DS I
.fam C
\&.de XH\-UPDATE\-TOC\-ULTIMATE
\&.\(rs" If we get this far, record the requisite reference data,
\&.\(rs" ensuring that the actual data is captured at the point of
\&.\(rs" ultimate output, (not when recording a diversion) ...
\&.\(rs"
\&.   if \(aq\(rs\(rsn(.z\(aq\(aq \(rs{\(rs
\&.   \(rs" ... beginning with the outline nesting level ...
\&.   \(rs"
\&.      toc put outline \(rs\(rs$1
\&.
\&.   \(rs" ... following up with the outline reference name, and
\&.   \(rs" document section number, as established by a prior .NH
\&.   \(rs" macro call ...
\&.   \(rs"
\&.      ds \(rs\(rs$0.text "\(rs\(rs*[PDFBOOKMARK.NAME] \-\- \(rs"
\&.      ie \(rs\(rs$1=1 \(rs{\(rs
\&.      \(rs" ... with font size increment, emboldening, and spacing
\&.      \(rs" adjustment, as appropriate for top level headings ...
\&.      \(rs"
\&.         as \(rs\(rs$0.text "\(rss\(aq+1z\(aq\(rsfB\c
.           nop \(rsZ\(aq\(rs\(rs$2\(aq\(rsfP\(rss\(aq-1z\(aq\(rs"
\&.         as \(rs\(rs$0.text "\(rsh\(aq\(rs\(rs*[TC-HS0]+\(rsw!0.!u\c
.           nop \(aq\(rss\(aq+1z\(aq\(rsfB\(rs"
\&.      \(rs}
\&.      \(rs" ... while maintaining normal font size, and style, for
\&.      \(rs" all levels of sub\-headings.
\&.      \(rs"
\&.      el .as \(rs\(rs$0.text "\(rs\(rs$2\(rsh\(aq\c
.            nop \(rs\(rs*[TC-HS1]\(aq\(rs"
\&.
\&.   \(rs" Discard the two arguments, which have been interpreted
\&.   \(rs" already, append all remaining arguments to the assembled
\&.   \(rs" reference data record, export it, and clean up.
\&.   \(rs"
\&.      shift 2
\&.      toc put refmark \(rs\(rs*[\(rs\(rs$0.text]\(rs\(rs$*\c
.        nop \(rsh\(aq\(rs\(rs*[TC-HS2]\(aq
\&.      rm \(rs\(rs$0.text
\&.
\&.   \(rs" Finally, append a page number reference, to wrap up
\&.   \(rs" this table of contents entry record.
\&.   \(rs"
\&.      ie r %% .toc put pageref \(rs\(rsn(%%
\&.      el .toc put pageref \(rs\(rsn%
\&.   \(rs}
\&.
\&.\(rs" ... but, if a diversion is being recorded, reschedule
\&.\(rs" this macro call for reprocessing, when the diversion is
\&.\(rs" eventually flushed to the output stream.
\&.\(rs"
\&.   el \(rs!.\(rs\(rs$0 \(rs\(rs$@
\&..
.DE
.float end
It may be noted
that this initial implementation of the
.CW \%XH\-UPDATE\-TOC
macro does not actually provide
any data collection capability.
Rather,
it assumes that the formatting process is controlled by
.CW \%pdfroff ,
(or a compatible process,
which makes similar use of a register named
.CW \%PHASE ),
and evaluates the state of this register,
to determine whether
table of contents data collection is necessary,
or not;
if not,
it redefines itself to do nothing,
when it is called subsequently;
.float needs 2v+\n(.Vu
otherwise,
it installs,
and ultimately replaces itself with,
an alternative
.CW \%XH\-UPDATE\-TOC
data collection handler,
which is implemented as follows:
.float release
.
After this ultimate table of contents data collector macro
.EM has
been installed,
by the initialization stub,
it will be called
.EM immediately ,
to complete the handling of the initial
.CW \%XH\-UPDATE\-TOC
macro call,
which caused it to be installed;
it will also be called
.EM directly ,
to handle each subsequent
.CW \%XH\-UPDATE\-TOC
macro call.
.
.LP
A detailed inspection of this ultimate
.CW \%XH\-UPDATE\-TOC
data collection implementation
will reveal that it introduces dependencies on
.EM three
supplementary
.CW \%groff_toc
framework extension macros.
Each of these must be supplied by the user;
suitable implementations are presented
in the following sections
of this appendix.
.
.XH-APPENDIX-NH 2 toc-outline Establishing a \#
 Table of Contents Layout\*[em]the \FCtoc.outline\F[] Macro
.LP
When table of contents data collection is performed by a
.CW \%XH\-UPDATE\-TOC
macro,
which has been implemented as shown in
.XR-NO-PREFIX toc-collector ,
the
.EM first
of the supplementary macros,
which will be called when each table of contents entry is to be output,
is
.EM always
invoked by a call of the form
.CW .toc \ \c \%\(lq
.CW outline \ \c
.CWI level > < \(rq;
each such call is serviced by the
.CW \%toc.outline
macro,
which is implemented as follows:
.DS I
.fam C
\&.de toc.end de
\&.de toc.outline
\&.   ie \(rs\(rs$1>1 \(rs{\(rs
\&.   \(rs" Entries at outline-levels greater than one are indented
\&.   \(rs" by an adjustable computed offset for each level; this is
\&.   \(rs" controlled by assignment of a value to the "TC-HS1" string,
\&.   \(rs" which is evaluated when executing the "XH-UPDATE-TOC" macro.
\&.   \(rs" Additionally, on any increase of indentation level from that
\&.   \(rs" of the preceding entry, which has been recorded in the local
\&.   \(rs" register, "toc#outline.current", additional vertical space
\&.   \(rs" equal to "TC-VS2" is inserted, while on decreasing to any
\&.   \(rs" level which remains greater than one, similar additional
\&.   \(rs" vertical space equal to "TC-VS3" is inserted.
\&.   \(rs"
\&.      nr toc#indent (\(rsw\(aq0.\(aqu+1.5n)*(\(rs\(rs$1-1)
\&.      if \(rs\(rs$1>2 .nr toc#indent +\(rsw\(aq0.\(aqu\c
.        nop *(\(rs\(rs$1-1)*(\(rs\(rs$1-2)/2
\&.      if !r toc#outline.current .nr toc#outline.current \(rs\(rs$1
\&.      ie \(rs\(rs$1>\(rs\(rsn[toc#outline.current] \c
.        nop \&.sp \(rs\(rs*[TC-VS2]
\&.      el .if \(rs\(rsn[toc#outline.current]>\(rs\(rs$1 \c
.        nop \&.sp \(rs\(rs*[TC-VS3]
\&.      nop \(rsh\(aq\(rs\(rsn[toc#indent]u\(aq\(rsc
\&.
\&.   \(rs" After emitting the appropriate indentation space, the
\&.   \(rs" tab-stop settings must be adjusted to compensate.
\&.   \(rs"
\&.      nr toc#indent \(rs\(rsn[.l]-\(rs\(rsn[.i]-\(rs\(rsn[toc#indent]
\&.      ta (u;\(rs\(rsn[toc#indent]-\(rs\(rsn[TC-MARGIN]) \c
.        nop (u;\(rs\(rsn[toc#indent])R
\&.      rr toc#indent
\&.   \(rs}
\&.   el \(rs{\(rs
\&.   \(rs" Entries at outline-level one are not indented, but each
\&.   \(rs" except the first, (identified by not yet having defined
\&.   \(rs" the "toc#outline.current" register), will be preceded by
\&.   \(rs" vertical space equal to "TC-VS1"; in any case, any open
\&.   \(rs" "KS" block is closed, (by calling "toc.end"), to permit
\&.   \(rs" insertion of a conditional page break prior to the next
\&.   \(rs" level one TOC entry, tab-stops are reset to comply with
\&.   \(rs" "ms" convention, and a further "KS" block is opened, in
\&.   \(rs" preparation for output of any level one TOC entry.
\&.   \(rs"
\&.      toc.end
\&.      if r toc#outline.current .sp \(rs\(rs*[TC-VS1]
\&.      ta (u;\(rs\(rsn[.l]-\(rs\(rsn[.i]-\(rs\(rsn[TC-MARGIN]) \c
.        nop (u;\(rs\(rsn[.l]-\(rs\(rsn[.i])R
\&.      als toc.end KE
\&.      KS
\&.   \(rs}
\&.\(rs" After initialization for the first TOC entry, tracking of the
\&.\(rs" current outline-level is persistently maintained, by recording
\&.\(rs" of the "toc#outline.current" register.
\&.\(rs"
\&.   nr toc#outline.current \(rs\(rs$1
\&..
.DE
.ne 2v
Irrespective of the particular text,
which is to appear within each table of contents entry,
this
.CW \%toc.outline
macro is responsible for controlling the layout of all such entries,
on the table of contents output page.
.
Notice that,
in addition to the \%user\(hyredefinable layout specification strings,
.CW TC\-HS0 \(rq, \%\(lq
.CW TC\-HS1 \(rq, \%\(lq
and
.CW TC\-HS2 \(rq, \%\(lq
(which are actually interpreted by,
and the effect of which is propagated from,
the
.CW \%XH\-UPDATE\-TOC
macro),
together with the further layout specification strings,
namely
.CW TC\-VS1 \(rq, \%\(lq
.CW TC\-VS2 \(rq, \%\(lq
and
.CW TC\-VS3 \(rq, \%\(lq
(each of which is interpreted by the
.CW \%toc.outline
macro itself),
this implementation of the
.CW \%toc.outline
macro introduces a further dependency,
on the supplementary
.CW \%toc.end
macro;
initially defined as an empty macro,
and subsequently redefined as an alias for
.CW KE ,
this
.EM should
be called by the user,
(in the form of a
.CW .toc \h'\w!t!u'\c \%\(lq
.CW end \(rq
macro call,
as illustrated in the introduction to
.XR-NO-PREFIX toc-generation ),
.EM after
any inclusion of a collected table of contents specification file.
.
.LP
For convenience,
and to ensure that there is no infiltration
of extraneous trailing space into their respective definitions,
the
.CW \%TC\-DEFINE
macro,
which is defined as:
.DS I
.fam C
\&.\(rs" The following TC-DEFINE macro provides a convenient mechanism
\&.\(rs" for defining strings, WITHOUT propagating trailing spaces into
\&.\(rs" the value assigned to the "TC-" prefixed named string.
\&.\(rs"
\&.de TC-DEFINE
\&.   ds TC-\(rs\(rs$1 "\(rs\(rs$2\(rs"
\&..
.DE
may be used to define,
or to redefine,
each of the
.CW TC\-HS0 \(rq, \%\(lq
.CW TC\-HS1 \(rq, \%\(lq
.CW TC\-HS2 \(rq, \%\(lq
.CW TC\-VS1 \(rq, \%\(lq
.CW TC\-VS2 \(rq, \%\(lq
and
.CW TC\-VS3 \(rq \%\(lq
layout specification strings;
for example,
their initial definitions are:
.DS I
.fam C
\&.TC-DEFINE VS1 1.30v   \(rs" leading for top level
\&.TC-DEFINE VS2 0.15v   \(rs" leading at nesting level increment
\&.TC-DEFINE VS3 0.25v   \(rs" leading following nested group
\&.
\&.TC-DEFINE HS0 1.50n   \(rs" indentation adjustment at top level
\&.TC-DEFINE HS1 1.50n   \(rs" space between section number and text
\&.TC-DEFINE HS2 0.50n   \(rs" space between text and following leader
.DE
.
With the exception of
.CW TC\-HS1 \(rq, \%\(lq
each of these layout control strings retains its initial setting,
throughout the processing of this publication;
as the sole exception,
the setting of
.CW TC\-HS1 \(rq \%\(lq
is changed to:
.DS I
.fam C
\&.TC-DEFINE HS1 "1.5n-\(rsw!.\(rs !u"
.DE
after formatting of the main document body,
and
.pdfhref L -D \*[FDL-APPENDIX-LINK] -A , -- \*[FDL-APPENDIX-CONTEXT]
but before,
and throughout the formatting of all of the remaining appendices,
to compensate for a change in the method which has been adopted
to generate section numbers within these appendices,
and the manner in which space is allocated,
on the output line,
for incorporation of such section numbers
into their respective table of contents entries.
.
.XH-APPENDIX-NH 2 toc-refmark Specifying \#
 Table of Contents Entry Context\*[em]the \FCtoc.refmark\F[] Macro
.LP
Following each invocation of
.CW .toc \h'\w!t!u'\c \%\(lq
.CW outline \h'\w!t!u'\c
.CWI level > < \(rq,
as described in the preceding section,
.XR-NO-PREFIX toc-outline ,
the contextual content of the entry is specified,
by calling
.CW .toc \h'\w!t!u'\c \%\(lq
.CW refmark \h'\w!t!u'\c
.CWI refname > < \h'\w!t!u'\c
.CW -- \h'\w!t!u'\c
.CWI section > < \h'\w!t!u'\c
.CWI context > < \h'\w!t!u'\c
.CW ... \(rq;
this call is serviced by the
.CW \%toc.refmark
macro,
which is implemented as follows:
.DS I
.fam C
\&.\(rs" Called immediately after toc.outline ...
\&.\(rs"
\&.de toc.refmark
\&.\(rs" ... this simply stores the destination tag name and the text
\&.\(rs" for the TOC pageref entry, within the toc@refmark.tag and the
\&.\(rs" toc@refmark.text strings respectively, whence they are ...
\&.\(rs"
\&.   ds toc@refmark.tag \(rs\(rs$1
\&.   ie \(aq\(rs\(rs$2\(aq--\(aq .shift 2
\&.   el .shift
\&.   ds toc@refmark.text \(rs\(rs$*
\&..
.DE
.ne 2v
The effect of calling
.CW \%toc.refmark
is to collect the section number reference,
and its associated contextual information,
conditioned by some layout control information
which has been propagated from the initiating invocation of
.CW \%XH\-UPDATE\-TOC ,
.ne 2v
into local string storage buffers,
in preparation for eventual completion,
formatting,
and writing to the document output stream,
as explained in
.pdfhref L -D toc-pageref -A . -- the following section
.
.XH-APPENDIX-NH 2 toc-pageref Specifying \#
 Page Number References\*[em]the \FCtoc.pageref\F[] Macro
.LP
Although the preceding sequence of two macro calls,
the first invoking
.CW .toc \h'\w!t!u'\c \%\(lq
.CW outline \h'\w!t!u'\c
.CWI level > < \(rq,
and the second invoking
.CW .toc \h'\w!t!u'\c \%\(lq
.CW refmark \h'\w!t!u'\c
.CWI refname > < \h'\w!t!u'\c
.CW -- \h'\w!t!u'\c
.CWI section > < \h'\w!t!u'\c
.CWI context > < \h'\w!t!u'\c
.CW ... \(rq,
may have established the page layout,
and the contextual content,
for any individual table of contents entry,
this pair of macro calls,
alone,
is insufficient to completely prepare that entry for output;
it still lacks a page number reference!
.
Thus,
to complete the sequence,
a further macro call,
of the form
.CW .toc \h'\w!t!u'\c \%\(lq
.CW pageref \h'\w!t!u'\c
.CWI pagenum > < \(rq,
is required;
this is serviced by the
.CW \%toc.pageref
macro,
for which the implementation is:
.DS I
.fam C
\&.\(rs" Completing a sequence of "toc.outline" and "toc.refmark"
\&.\(rs" macro calls, a call to the following "toc.pageref" macro
\&.\(rs" causes the prepared table of contents entry layout, and
\&.\(rs" associated contextual information ...
\&.\(rs"
\&.de toc.pageref
\&.\(rs" ... to be incorporated into an active pdfhref link, along
\&.\(rs" with the appropriate page number reference, and emitted to
\&.\(rs" the document output stream.
\&.\(rs"
\&.   ie \(rs\(rsn[toc#outline.current]>1 .as toc@refmark.text \c
.        nop "\(rsa\(rst\(rs\(rs$*\(rs"
\&.   el .as toc@refmark.text "\(rsf[]\(rss\(aq-1z\(aq\c
.        nop \(rsa\(rss\(aq+1z\(aq\(rsfB\(rst\(rs\(rs$1\(rsf[]\c
.        nop \(rss\(aq-1z\(aq\(rs"
\&.   pdfhref L -D \(rs\(rs*[toc@refmark.tag] -- \c
.        nop "\(rs\(rs*[toc@refmark.text]"
\&.   rm toc@refmark.tag toc@refmark.text
\&.   br
\&..
.DE
.
.XH-APPENDIX-NH 2 toc-colour \#
 Avoiding Excessive Use of \FCpdfhref\F[] Link Colour in Tables of Contents
.LP
As has been noted,
in
.pdfhref F SECREF L -D toc-side-effects -A ,
.pdfhref F
given the implementation as detailed
in the preceding sections of this appendix,
with the exception of the heading on its initial page,
the table of contents will comprise
.EM exclusively
.CW \%pdfhref
links.
If the default style is applied to these,
the table of contents,
almost in its entirety,
will be rendered it the
.CW \%pdfhref
link colour;
this may be perceived to exhibit
an unnecessarily distracting appearance!
.
This potential distraction may be avoided by
.EM manually
overriding the default
.CW \%PDFHREF.TEXT.COLOUR
style,
.EM immediately
before scheduling output of the table of contents:
.DS I
.fam C
\&.\(rs" Break PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR equivalence,
\&.\(rs" then reassign PDFHREF.TEXT.COLOUR, (which is given precedence),
\&.\(rs" to match the normal running text colour.
\&.\(rs"
\&.rm PDFHREF.TEXT.COLOUR
\&.ds PDFHREF.TEXT.COLOUR "\(rsn(.m\(rs"
.DE
and subsequently reinstate it,
.EM either
by
.EM explicitly
restoring the original equivalence:
.DS I
.fam C
\&.\(rs" Restore normal PDFHREF.TEXT.COLOUR handling, by reinstating
\&.\(rs" PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR equivalence.
\&.\(rs"
\&.als PDFHREF.TEXT.COLOUR PDFHREF.TEXT.COLOR
.DE
.EM or
by delegating
.EM automatic
reinstatement to
.CW \%pdfhref :
.DS I
.fam C
\&.\(rs" Discard our overriding PDFHREF.TEXT.COLOUR assignment, thus
\&.\(rs" scheduling automatic reinstatement of the normal equivalence
\&.\(rs" of PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR by pdfhref
\&.\(rs"
\&.rm PDFHREF.TEXT.COLOUR
.DE
.EM after
completion of table of contents output.
.
.LP
While it may be reasonable to
.EM manually
override
.CW \%PDFHREF.TEXT.COLOUR ,
for \%\(lqone\(hyshot\(rq
table of contents output,
it may be found to be more convenient to encapsulate
this override capability within a macro,
as part of a
.CW \%groff_toc
framework implementation;
a suitable macro implementation might be:
.DS I
.fam C
\&.de toc.color als
\&.als toc.colour toc.color
\&.\(rs" This implementation is common to both ".toc colour" usage,
\&.\(rs" and ".toc color" usage; either may be used, interchangeably,
\&.\(rs" according to individual user preference.
\&.am toc.colour
\&.\(rs" Usage:
\&.\(rs"   .toc colour [<colour-specification>]
\&.\(rs"   .toc color [<colour-specification>]
\&.\(rs"
\&.\(rs" Break PDFHREF.TEXT.COLOUR and PDFHREF.TEXT.COLOR equivalence;
\&.\(rs" it will be restored automatically, by pdfhref, if no altenative
\&.\(rs" <colour-specification> argument is specified ...
\&.\(rs"
\&.   rm PDFHREF.TEXT.COLOUR
\&.\(rs"
\&.\(rs" ... but, when such an argument IS specified, then assign it, so
\&.\(rs" that it may take precedence over PDFHREF.TEXT.COLOR
\&.\(rs"
\&.   if \(rs\(rsn(.$ .ds PDFHREF.TEXT.COLOUR "\(rs\(rs$1\(rs"
\&..
.DE
.LP
This \(lqconvenience\(rq macro may then be called,
immediately
.EM before
table of contents output,
to substitute the normal running text colour
as an override for the default
.CW \%PDFHREF.TEXT.COLOUR
assignment:
.DS I
.fam C
\&.\(rs" Override the default PDFHREF.TEXT.COLOUR assignment, with
\&.\(rs" the normal running text colour.
\&.\(rs"
\&.toc colour \(rsn(.m
\&.so pdfmark.toc
.DE
and then again,
.EM after
completion of this table of contents output,
to schedule automatic,
\%\(lqon\(hydemand\(rq reinstatement of the default
.CW \%PDFHREF.TEXT.COLOUR
interpretation:
.DS I
.fam C
\&.\(rs" Delegate reinstatement of default PDFHREF.TEXT.COLOUR handling
\&.\(rs" to pdfhref, on the next occasion of it being required.
\&.\(rs"
\&.toc colour
.DE
.
.XH-APPENDIX-NH 2 toc-extras \#
 Additional Convenience Macros for Formatting Tables of Contents
.LP
Although the macros,
as presented in the preceding sections of this appendix,
are sufficient to prepare,
and to emit,
a table of contents,
some additional macros may be helpful;
the added convenience will become particularly apparent,
when the collected table of contents reference data
is to be interpreted selectively,
usually more than once,
as described in
.XR-NO-PREFIX selective-toc .
.
.LP
Some additional \(lqconvenience\(rq functionality,
which may be found to be useful,
might include:
.QS
.sp -\n[PD]u
.IP \(bu
Output of a suitably formatted table of contents heading,
optionally with variants to place this at the top of a new page,
and possibly to ensure that this will be a recto page.
.
.IP \(bu
Restoration of layout controls to their default initial state,
prior to reinterpretation of the collected
table of contents reference data,
(perhaps with a modified set of selection criteria).
.
.IP \(bu
Reading in,
and interpretation of the table of contents reference data file,
with integral reinitialization of the layout control parameters,
and management of the recommended
.CW \%PDFHREF.TEXT.COLOUR
override,
.XR toc-colour ). (
.QE
.
.KS
Of these three suggested additional \(lqconvenience\(rq features,
the current publication does not implement the first;
rather,
it simply uses \%in\(hyline requests to set up a new page,
and emit a centred \(lqTable of Contents\(rq heading.
If it is desired to encapsulate this functionality within macros,
a suitable implementation might look something like:
.DS I
.fam C
\&.de toc.heading
\&.\(rs" Usage: .toc heading [<heading text> ...]
\&.\(rs"
\&.\(rs" Print an emboldened, centred "Table of Contents" heading.
\&.\(rs"
\&.ie \(rs\(rsn(.$ \(rs{.ce 1
\&.   ft B
\&.   nop \(rss\(aq+2z\(aq\(rs\(rs$*\(rss\(aq-2z\(aq
\&.   ft
\&.   sp 2v
\&.\(rs}
\&.el .\(rs\(rs$0 \(rs\(rs*[TOC]
\&..
\&.if !dTOC .ds TOC "Table of Contents\(rs"
.DE
.KE
.float begin
.DS I
.fam C
\&.bp [<page-number>]
\&.toc heading [heading text ...]
.DE
or,
(as will often be the case),
to ensure that the table of contents starts on a recto page:\|\**
.FS
.ds PDFHREF.PREFIX See
.XR new-recto-page .
.ds PDFHREF.PREFIX see
.FE
.DS I
.fam C
\&.NEW\-RECTO\-PAGE %%
\&.toc heading [heading text ...]
.DE
.float end
Notice that the preceding macro will simply
place the \(lqTable of Contents\(rq heading at
the current output position,
on the current output page;
it will
.EM not
ensure that this placement is at the top of a page.
In practice,
such placement at the top of a page will be desirable;
this may be achieved,
.float needs 1v+\n(.Vu
if either a recto,
or a verso page is acceptable,
by simply preceding a
.CW .toc \h'\w!t!u'\c \%\(lq
.CW heading \h'\w!t!u'\c
.CW ... \(rq
macro call with a
.CW .bp \(rq \%\(lq
request:
.float release
.float begin
.DS I
.fam C
\&.de toc.reset
\&.\(rs" Usage: .toc reset
\&.\(rs"
\&.\(rs" Restore the toc.end macro to its initial "do-nothing" state,
\&.\(rs" by first defining a new empty macro, with a temporary name, and
\&.\(rs" then renaming this, to replace any current implementation of
\&.\(rs" the toc.end macro itself.
\&.\(rs"
\&.   de \(rs\(rs$0.tmp rn
\&.   rn \(rs\(rs$0.tmp toc.end
\&.
\&.\(rs" Furthermore, when beginning to format any new table of contents,
\&.\(rs" the internal toc#outline.current register should be undefined.
\&.\(rs"
\&.   rr toc#outline.current
\&..
.DE
which may then be invoked by macro calls of the form:
.CW .toc \h'\w!t!u'\c \%\(lq
.CW reset \(rq.
.float end
The principal advantage of implementing
.EM any
of the recommended \(lqconvenience\(rq macro features
is that they facilitate repeated interpretation of
the collected table of contents reference data,
(for example,
to compile separate tables of contents,
lists of figures,
lists of equations,
etc.);
before any such reinterpretation of
the table of contents reference data is performed,
.float needs 2v+\n(.Vu
the internal state of the
.CW .toc \h'\w!t!u'\c \%\(lq
.CW outline \(rq
layout controls must be restored
to their initial condition;
this may be facilitated by adoption of the second recommendation,
implemented\**
.FS
Assuming that the preceding implementations of the
.pdfhref L -D toc-collector -A , -- \%\f(CRXH\-UPDATE\-TOC\fP
.pdfhref L -D toc-outline -A , -- \%\f(CRtoc.outline\fP
.pdfhref L -D toc-refmark -A , -- \%\f(CRtoc.refmark\fP
.pdfhref L -D toc-pageref -A , -- \%\f(CRtoc.pageref\fP
and\p
.pdfhref L -D toc-outline -- \%\f(CRtoc.end\fP
macros have been adopted.
.FE
as the convenience macro:
.float release
.float begin
.DS I
.fam C
\&.de toc.load
\&.\(rs" Usage: .toc load <file-name>
\&.\(rs"
\&.\(rs" Load, and interpret the named table of contents reference
\&.\(rs" data file, after reinitialization of the .toc outline state,
\&.\(rs" and overriding PDFHREF.TEXT.COLOUR, to match the colour of
\&.\(rs" the running document text, (as set at the time when this
\&.\(rs" macro is DEFINED, and NOT when it is EVALUATED).
\&.\(rs"
\&.   toc reset
\&.   toc colour \(rsn(.m
\&.   so  \(rs\(rs$1
\&.
\&.\(rs" Restore normal PDFHREF.TEXT.COLOUR handling, and wrap up.
\&.\(rs"
\&.   toc colour
\&.   toc end
\&..
.DE
.float end
.LP
When the table of contents reference data
.EM is
to be interpreted more than once,
then it is likely that,
not only will it be necessary to restore the initial
.CW .toc \h'\w!t!u'\c \%\(lq
.CW outline \(rq
state,
but the author may also favour application of the recommended
.CW \%PDFHREF.TEXT.COLOUR
override during each successive interpretation,
.float needs 1v+\n(.Vu
as suggested in the third convenience recommendation;
a suitable macro,
for implementation of this recommendation,
may be:
.float release
.
.XH-APPENDIX-NH 1 appendix-macros \#
 Macros for Laying Out the Content of Appendicies
.LP
Although the standard page layout,
and paragraph styling macros,
which are provided by the author's choice
of basic document formatting macro package,
will be found to be generally sufficient
for laying out the content of appendices,
some additional macros,
which are specifically tailored for the purpose,
may be helpful for the specification of appendix titles,
and appendix section headings.
.
In the case of this publication,
which has been formatted using
.CW groff 's
.CW ms
macro suite,
these capabilities are supported by the provision of
.EM three
additional macros,
namely
.CW \%XH\-APPENDIX ,
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT ,
and
.CW \%XH\-APPENDIX\-NH ,
the implementations of which may be found
within the supplementary
.CW \%appendix.tmac
file;
formulated as a complement to the
.CW spdf.tmac
extended variant of
.CW groff 's
.CW ms
macros,
the respective implementation,
and usage,
of each of these macros
is discussed in the following subsections of this appendix.
.
.LP
When using this trio of macros,
to lay out the content of appendicies,
the
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT
macro is,
typically,
called first,
and just once,
.EM immediately
before the first use of the
.CW \%XH\-APPENDIX
macro,
to begin the first appendix,
(which will be serially identified as appendix number
.EM one ,
although this may commonly be represented
as an element of an alphabetic sequence).
.
Thereafter,
each subsequent invocation of
.CW \%XH\-APPENDIX ,
if any,
will begin a further (new) appendix,
with serially incrementing identification numbers,
at an incremental interval of one.
.
.LP
.EM Explict
use of the
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT
macro is
.EM optional ;
however,
.EM if
it is
.EM not
called
.EM before
the first use of the
.CW \%XH\-APPENDIX
macro,
then it will be called
.EM implicitly ,
and the serialization of appendix numbers,
together with page numbers within the appendices,
will be repersented by arabic numerals,
which may not be the desired effect.
.
This is discussed further,
in
.de XH-APPENDIX-SUBREF
.   while \\n(.$ \{\
.      ie '\\$1'appendix' .shift 2
.      el .ie '\\$1'section' \{.ds PDFHREF.TEXT "\\$1 \\$2,
.         shift 2
.      \}
.      el \{.as PDFHREF.TEXT " \(lq\\$*\(rq\"
.            break
.      \}
.   \}
..
.pdfhref F XH-APPENDIX-SUBREF L -D xh-appendix-numbering -A .
.
.LP
Following any specific invocation of the
.CW \%XH\-APPENDIX
macro,
the effective scope of the call extends\^\**
.FS
This concept,
of the extended scope of any
.CW \%XH\-APPENDIX
macro invocation,
is significant
.EM only
insofar as it affects the operation of the
.CW \%XH\-APPENDIX\-NH
macro;
in all other respects,
the content of each appendix is formatted
in accordance with the convertions which apply
throughout the publication.
.FE
.EM either
until the
.CW \%XH\-APPENDIX
macro is called a subsequent time,
.EM or
to the end of the document.
.
Within this extended scope of each
.CW \%XH\-APPENDIX
call,
numbered subsection headings,
each of which is specific to the containing appendix,
may be introduced by calling the
.CW \%XH\-APPENDIX\-NH
macro,
which is discussed in
.pdfhref L -D xh-numbered-headings -A .
.
.LP
A discussion of the implementation,
and the usage,
of the
macro itself,
may be found in
.pdfhref L -D xh-appendix-macro -A .
.pdfhref F
.
.KS
.XH-APPENDIX-NH 2 xh-appendix-macro \#
 Specifying an Appendix Title\*[em]the \FCXH\-APPENDIX\F[] Macro
.LP
The
.CW \%XH\-APPENDIX
macro may be used to introduce each of any arbitrary number
of individual,
serially numbered,
appendicies to the publication;
with its implementation defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.de XH-APPENDIX
\&.\(rs" Usage: .XH-APPENDIX <title-text> ...
\&.\(rs"
\&.\(rs" Start a document appendix, numbering sequentially from Appendix 1,
\&.\(rs" with numbering style, applied by 'af', as specified by a prior call
\&.\(rs" to XH-APPENDIX-NUMBER-FORMAT, (defaults to arabic numerals).
\&.\(rs"
\&.   af % 0
\&.   if !r XH-APPENDIX-NUMBER .XH-APPENDIX-NUMBER-FORMAT
\&.   ie r\(rs\(rs$0.PSINCR .nr PSINCR \(rs\(rsn[\(rs\(rs$0.PSINCR]
\&.   el .nr \(rs\(rs$0.PSINCR \(rs\(rsn[PSINCR]
\&.\(rs"
\&.\(rs" Printing of each appendix should start on a new recto page.
\&.\(rs"
\&.   NEW-RECTO-PAGE %% \(rs\(rsg[appendix.page.number.format]
\&.\(rs"
\&.\(rs" Print a centred level 1 "Appendix #" page heading, with associated
\&.\(rs" PDF outline, and table of contents entries.
\&.\(rs"
\&.   SH 1
\&.   ce 999
\&.   ds \(rs\(rs$0.title "Appendix \(rs\(rsn+[XH-APPENDIX-NUMBER]\(rs"
\&.   pdfhref O 1 \(rs\(rs*[\(rs\(rs$0.title]. \(rs\(rs$*
\&.   XH-UPDATE-TOC 1 \(rs& \(rsh\(aq-(\(rsw!0.!u+1.5n)\(aq\(rs\c
.     nop \(rs*[\(rs\(rs$0.title].\(rsh\(aq1.5n\(aq\(rs\(rs$*
\&.   nop \(rs\(rs*[\(rs\(rs$0.title]
\&.\(rs"
\&.\(rs" Further heading output will be suppressed, if the XH-APPENDIX-SP
\&.\(rs" register is not defined...
\&.\(rs"
\&.   if r XH-APPENDIX-SP \(rs{\(rs
\&.   \(rs" ...but when not suppressed, print the macro arguments as a
\&.   \(rs" centred, possibly multi-line, level 2 heading, followed by
\&.   \(rs" downward space equivalent to the value of XH-APPENDIX-SP.
\&.   \(rs"
\&.      SH 2
\&.      ce 999
\&.      nop \(rs\(rs$*
\&.      sp \(rs\(rsn[XH-APPENDIX-SP]u
\&.   \(rs}
\&.\(rs" Reset section numbering, so that it restarts at one, for section
\&.\(rs" headings at the top level, in each successive appendix.
\&.\(rs"
\&.   rr \(rs\(rs$0-NH-h1
\&.\(rs"
\&.\(rs" Adjust type size scaling, for subsequent subheadings, clean up
\&.\(rs" temporary storage, reset the pending centred line count, and we
\&.\(rs" are done.
\&.\(rs"
\&.   nr PSINCR \(rs\(rsn[PSINCR]*2/3
\&.   rm \(rs\(rs$0.title
\&.   ce
\&..
.sp \n[PD]u-\n[DD]u
.DE
.KE
it begins by ensuring that the appendix numbering sequence
has been properly initialized,
with assigned formats for the appendix number itself,
and also for any page numbers
which are to be displayed within the appendices,
(by calling the
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT
macro,
if necessary);
it then synchronizes the incremental point size,
which is to be used for typesetting of the appendix title block,
with that of top level section headings within the document body,
and advances to the next available recto page,
which will become the first page of the appendix.
.
.LP
After initialization,
and advancing to the new page,
an appendix identifier of the form \[lq]Appendix\ #\(rq\h'-0.3n'\*[em]in
which the \(lq#\(rq represents the next sequentially
available appendix serial number,
(which,
following assignment,
becomes available in the
.CW \%XH\-APPENDIX\-NUMBER
register),
beginning with
.EM one
for the first appendix,
and incrementing by
.EM one
for each successive
.CW \%XH\-APPENDIX
macro call\*[em]is generated,
and then typeset as a centred page heading,
in a type size which corresponds to that of a level one section heading,
within the body of the containing publication,
and with the appendix serial number expressed in
the format specified by a preceding call\*[em]whether
.EM explicit ,
or
.EM implicit \*[em]of
the
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT
macro;
this appendix identifier is also incorporated,
together with with any specified
.CW \%<title-text>
arguments,
into a corresponding entry within the document's table of contents,
in addition to the PDF document outline.
.
.LP
In addition to typesetting the appendix identifier,
as a level one centred page heading,
.EM if
the author has defined a register named
.CW \%XH\-APPENDIX\-SP \Z','\|\**
.FS
The
.CW \%XH\-APPENDIX\-SP
register is
.EM not
defined by default;
the effect of leaving it unspecified is to omit
typesetting of any default second level appendix page heading.
This is designed to accommodate the typesetting of
the \*[FDL-APPENDIX-TITLE],
\O0[kludge]\O1\c\" kludge to correct misplacement of link bounding box
.pdfhref L -D \*[FDL-TYPESETTING-LINK] -P \h'-\w![kludge]!u'( -A ),
during which an alternative strategy has been adopted
for specification of a second level appendix page heading.
.FE
the aggregate content of any specified
.CW \%<title-text>
arguments is typeset,
in a type size which corresponds to that of
a level two heading within the document body,
as a further centred page heading,
followed by vertical space equivalent to the value,
in
.CW groff 's
basic measurement units,
which has been assigned to
.CW \%XH\-APPENDIX\-SP ,
offsetting the body of the appendix from the page heading.
.
.LP
Finally,
in preparation for typesetting the body of the appendix,
the subheading numbering sequence is reset to one,
at heading level one,
with the heading type size increment scaled to two thirds
of that which applies within the document body,
(and when typesetting the appendix page heading),
before cleaning up all temporary storage which is used locally,
within the scope of execution of the
.CW \%XH\-APPENDIX
macro.
.
.ig
.LP
After the
.CW \%XH\-APPENDIX
macro has been called,
the appendix serial number which has been assigned
may be found in the
.CW \%XH\-APPENDIX\-NUMBER
register.
..
.KS
.XH-APPENDIX-NH 2 xh-appendix-numbering \#
 Appendix Numbering Styles\*[em]the \FCXH\-APPENDIX\-NUMBER\-FORMAT\F[] Macro
.LP
With the intention that it should be called
.EM before
the
.EM "first use"
of the
.CW \%XH\-APPENDIX
macro,
.EM if
expression of appendix serial numbers,
and\^/or page numbers within the subsequent appendicies,
is desired to exhibit any style other than arabic numerals,
the implementation of the
.CW \%XH\-APPENDIX\-NUMBER\-FORMAT
is defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.de XH-APPENDIX-NUMBER-FORMAT
\&.\(rs" .XH-APPENDIX-NUMBER-FORMAT <appendix-num-fmt> <page-num-fmt>
\&.\(rs"
\&.\(rs" Establish the format for appendix numbers, and optionally, the
\&.\(rs" style to be used for page numbers within appendices.
\&.\(rs"
\&.   ie \(rs\(rsn(.$>1 \(rs{\(rs
\&.   \(rs" Two arguments are required, for assignment of the appendix
\&.   \(rs" number style (\(rs\(rs$1), and page number style (\(rs\(rs$2).  Moreover,
\&.   \(rs" the appendix number register must exist, with initial value
\&.   \(rs" of zero, and auto-increment of one.
\&.   \(rs"
\&.      af appendix.page.number.format \(rs\(rs$2
\&.      if !r XH-APPENDIX-NUMBER .nr XH-APPENDIX-NUMBER 0 1
\&.      af XH-APPENDIX-NUMBER \(rs\(rs$1
\&.   \(rs}
\&.\(rs" If fewer than two arguments are specified, recurse to provide
\&.\(rs" arabic numerals as defaults for those which are missing.
\&.\(rs"
\&.   el .\(rs\(rs$0 \(rs\(rs$* 1 1
\&..
.sp \n[PD]u-\n[DD]u
.DE
.KE
Within the current publication,
this is invoked by the call:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.XH-APPENDIX-NUMBER-FORMAT A i
.sp \n[PD]u-\n[DD]u
.DE
thus selecting a progression of \%upper\[hy]case alphabetic characters
as the desired style for expression of appendix serial numbers,
and \%lower\[hy]case roman numerals for numbering
their associated content pages.
.
.XH-APPENDIX-NH 2 xh-numbered-headings \#
 Appendix Subsection Numbering\*[em]the \FCXH\-APPENDIX\-NH\F[] Macro
.LP
When typesetting a document,
using the
.CW ms
macros,
.EM unnumbered
section headings,
within appendices,
may be specified using the
.CW SH
macro,
just as they would be throughout
the document body.
.
However,
if
.EM numbered
section headings,
in which the appendix number is included as a section number prefix,
are to be specified,
then any use of the standard
.CW NH
macro may be found to be
.EM much
less convenient;
thus,
the
.CW \%XH-APPENDIX-NH
macro is provided,
in order to mitigate the potential attendant inconvenience.
.
.LP
The implementation of the
.CW \%XH-APPENDIX-NH
macro is somewhat lengthy;
thus,
it will be presented,
and discussed,
as an incremental series of separate\^\**
.FS
Although presented here,
in the style of an incrementally defined macro,
the actual implementation of the
.CW \%XH-APPENDIX-NH
macro is defined as a single integrated whole.
.FE
fragments;
the first of these is defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.de XH-APPENDIX-NH
\&.\(rs" Usage: .XH-APPENDIX-NH <level> [<dest-name> <heading-text> ...]
\&.\(rs"
\&.\(rs" Modelled on the behaviour of ms\(aq "NH" macro, assign a section
\&.\(rs" number, at any particular heading level, for use in appendices;
\&.\(rs" the generated section number comprises the appendix number, in
\&.\(rs" its specified format, followed by a sequence of arabic numeral
\&.\(rs" section numbers, in the same style as an "NH" section number,
\&.\(rs" appropriate to the specified heading level, then terminated
\&.\(rs" by the character sequence, ".\(rs&\(rs ".
\&.\(rs"
\&.\(rs" Unlike ms\(aq "NH" macro, this DOES NOT support the "S <n> ..."
\&.\(rs" style for specifying heading levels; it DOES, however, support
\&.\(rs" the specification, as additional arguments, of a ".pdfhref L"
\&.\(rs" destination name, followed by text which is to be assigned as
\&.\(rs" the numbered heading text, and also propagated to a document
\&.\(rs" table of contents, and to a PDF document outline.
\&.\(rs"
\&.\(rs" A persistent register, named \(rs\(rs$0-hl, is used to track the
\&.\(rs" most recently assigned heading level, while temporary register,
\&.\(rs" \(rs\(rs$0-hl-local, is used in internal manipulations based on this,
\&.\(rs" in association with \(rs\(rs$1, which may leave it unchanged, or may
\&.\(rs" increase it in intremental steps of one, or decrease it by any
\&.\(rs" arbitrary decremental step size, (subject to a limitation that
\&.\(rs" it cannot be reduced to less than a value of one).
\&.\(rs"
\&.   af \(rs\(rs$0-hl 0
\&.   if \(rs\(rs$1-\(rs\(rsn[\(rs\(rs$0-hl]-1 \(rs{\(rs
\&.   \(rs" The heading level, specified by \(rs\(rs$1, is greater than, but
\&.   \(rs" not contiguous with the level currently assigned to \(rs\(rs$0-hl;
\&.   \(rs" this creates an unwelcome gap in the level progression.
\&.   \(rs"
\&.      tmc troff:\(rs\(rsn(.F:\(rs\(rsn(.c:\(rs\(rs$0: warning: \(rs"
\&.      tm  \(rs\(rs$0 heading level \(rs\(rs$1 follows level \(rs\(rsn[\(rs\(rs$0-hl]
\&.   \(rs}
\&..
.sp \n[PD]u-\n[DD]u
.DE
Following its introductory header comment block,
this initial fragment performs a sanity check on the value
of the mandatory first,
.CWI level > < \(rq, \%\(lq
argument;
if this exceeds any currently assigned heading level,
by an increment of more than one,
then a warning diagnostic message is displayed,
advising of a discontinuity in heading level progression.
.
.float begin
.LP
Following the initial sanity check,
for continuity of incremental heading level progression,
the next fragment of the
.CW \%XH-APPENDIX-NH
macro implementation is defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.am XH-APPENDIX-NH
\&.\(rs" Usage: .XH-APPENDIX-NH <level> [<dest-name> <heading-text> ...]
\&.\(rs"
\&.\(rs" If \(rs\(rs$1 is less than \(rs\(rs$0-hl, then all sub-section numbers,
\&.\(rs" for heading levels greater than \(rs\(rs$1, become defunct; discard
\&.\(rs" each of these in turn.
\&.\(rs"
\&.   nr \(rs\(rs$0-hl-local 1+\(rs\(rsn[\(rs\(rs$0-hl] 1
\&.   while \(rs\(rsn-[\(rs\(rs$0-hl-local]-\(rs\(rs$1 .rr \(rs\(rs$0-h\(rs\(rsn[\(rs\(rs$0-hl-local]
\&..
.sp \n[PD]u-\n[DD]u
.DE
.float end
.float needs 2v+\n(.Vu
.float release
This has no effect,
.EM if
the specified
.CWI level > <
argument has the
.EM "same value"
as,
.EM or
a
.EM "greater value"
than,
the currently active heading level;
conversely,
if the specified
.CWI level > <
argument has a
.EM "lesser value"
than the currently active heading level,
.ne 2v
then the
.CW while
loop will take effect,
resulting in the deletion,
and consequent reset,
of all numeric registers
which are associated with \%sub\[hy]section numbers,
at greater depth than that specified by the
.CWI level > <
argument.
.
.LP
Note that,
the effective
.EM minimum
value which is permitted for the
.CWI level > <
argument is
.EM one ;
specification of any lesser value will
.EM not
be diagnosed,
but the
.EM effective
value will be silently adjusted to this permitted minimum.
.
.float begin
.LP
After validation of the
.CWI level > <
argument,
and cleaning up of any redundant internal section number counters,
the
.CW \%XH-APPENDIX-NH
macro progresses to construction of a section number record
relating to the ensuing numbered section heading;
the implementation for this phase of execution is defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.am XH-APPENDIX-NH
\&.\(rs" Usage: .XH-APPENDIX-NH <level> [<dest-name> <heading-text> ...]
\&.\(rs"
\&.\(rs" Increment the sub-section number at the heading level which
\&.\(rs" is specified by \(rs\(rs$1; (if this is a newly started level, then
\&.\(rs" the starting point is initialized to a default value of zero,
\&.\(rs" which is then incremented to one).
\&.\(rs"
\&.   af \(rs\(rs$0-h\(rs\(rs$1 0
\&.   nr \(rs\(rs$0-h\(rs\(rs$1 +1
.ig
\&..
.sp \n[PD]u-\n[DD]u
.DE
.
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.am XH-APPENDIX-NH
\&.\(rs" Usage: .XH-APPENDIX-NH <level> [<dest-name> <heading-text> ...]
..
\&.\(rs"
\&.\(rs" Construct a string representation of the corresponding
\&.\(rs" sub-section number, for use as a prefix to the eventual text
\&.\(rs" of the sub-section heading, then simulate the effect of .NH,
\&.\(rs" using an equivalent level .SH call.
\&.\(rs"
\&.   nr \(rs\(rs$0-hl-local 0 1
\&.   ds XH-APPENDIX-SN-NO-DOT "\(rs\(rsn[XH-APPENDIX-NUMBER]\(rs"
\&.   while \(rs\(rs$1-\(rs\(rsn[\(rs\(rs$0-hl-local] \(rs{\(rs
\&.      as XH-APPENDIX-SN-NO-DOT ".\(rs\(rsn[\(rs\(rs$0-h\(rs\(rsn+[\(rs\(rs$0-hl-local]]\(rs"
\&.   \(rs}
\&.   nr \(rs\(rs$0-HL 1+\(rs\(rs$1
\&.   SH \(rs\(rsn[\(rs\(rs$0-HL]
\&.\(rs"
\&.\(rs" Update \(rs\(rs$0-hl for use during the next, if any, invocation
\&.\(rs" of this macro, append a "." to the constructed sub-section
\&.\(rs" number, and clean up temporary internal storage.
\&.\(rs"
\&.   nr \(rs\(rs$0-hl \(rs\(rs$1
\&.   ds XH-APPENDIX-SN-DOT "\(rs\(rs*[XH-APPENDIX-SN-NO-DOT].\(rs"
\&.   rr \(rs\(rs$0-hl-local
\&..
.sp \n[PD]u-\n[DD]u
.DE
.float end
.float needs 2v+\n(.Vu
.float release
which begins by incrementing the internal record
of the particular constituent element of the \%sub\[hy]section number,
which is associated with the current heading
.CWI level >, <
before assembling it,
together with the appendix number,
and each of the lower level section number elements,
in sequence,
to create a pair of publicly visible string representations of
the composite section number\*[em]analogous to,
but not bound to,
the
.CW \%SN-DOT
and
.CW \%SN-NO-DOT
strings,
which are defined when the
.CW NH
macro is called.
.
In addition,
it computes a suitable,
publicly visible numeric register value\*[em]with no
.CW NH
analogue\*[em]which is suitable
for use as the heading level argument value,
in the GNU extended variant of the
.CW SH
macro call;
it also invokes this call,
in preparation for output of
the ensuing section heading,
and it also records the value of its own
.CWI level > <
argument,
.ne 2v+\n(.Vu
in a persistent \%internal\[hy]use register,
for subsequent use in the sanity checking phase of the
.EM next
invocation\*[em]if any\*[em]of the
.CW \%XH-APPENDIX-NH
macro.
.
.LP
It may be observed that,
on the basis of just the fragments which have been presented thus far,
this implementation of the
.CW \%XH-APPENDIX-NH
macro provides a fairly complete analogue for the
.CW NH
macro;
however,
it is
.EM not
compatible with the subsequent use of the
.CW XN
macro\Z','\^\**
.FS
The
.CW XH
macro
.EM may
be used,
in place of
.CW XN ,
following any invocation of
.CW \%XH-APPENDIX-NH ,
but the required argument values,
which must be specified,
may not bear an entirely obvious relationship to the
.CW \%XH-APPENDIX-NH
call itself.
.FE
which may be used following
.CW NH ,
to specify the text of the section heading,
such that it will also be incorporated into the table of contents,
and possibly a PDF document outline.
.
In order to work around this incompatibility,
rather than definining a complementary
.CW \%XH-APPENDIX-XN
macro,
it has been chosen to add a further fragment
to the implementation of the
.CW \%XH-APPENDIX-NH
macro,
such that it will process additional optional
.CWI dest-name > \%<
and
.CWI heading-text > \%<
arguments,
to achieve an effect which is analogous to the sequence:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.NH <\fIlevel\fP>
\&.XN -S -N <\fIdest-name\fP> <\fIheading-text\fP> ...
.sp \n[PD]u-\n[DD]u
.DE
The implementation of this final,
optional argument processing fragment of the
.CW \%XH-APPENDIX-NH
macro,
using
.CW XH
to emulate an effect which is analogous to that of
.CW XN \Z','\^\**
.FS
It should be noted that this analogue,
as illustrated here,
is based on the
.CW spdf.tmac
implementations of the
.CW XN ,
and
.CW XH
macros;
it is dependent on use of the
.CW -S ,
and
.CW -N \~\c
.CWI dest-name > \%<
options,
.EM neither
of which is
supported by the default implementation of either macro,
as defined in
.CW s.tmac .
.FE
is defined as:
.DS I
.fam C
.sp \n[PD]u-\n[DD]u
\&.am XH-APPENDIX-NH
\&.\(rs" Usage: .XH-APPENDIX-NH <level> [<dest-name> <heading-text> ...]
\&.\(rs"
\&.\(rs" Check if the optional extra arguments have been specified...
\&.\(rs"
\&.   if \(rs\(rsn(.$-2 \(rs{\(rs
\&.   \(rs" ...and, when they have, assemble them, together with the
\&.   \(rs" assigned section number, into a form which may be processed
\&.   \(rs" through the "XH" macro...
\&.   \(rs"
\&.      ne \(rs\(rsn[PD]u+3v
\&.      ds \(rs\(rs$0-ARGV "\(rs\(rs$2 \(rs\(rs*[\(rs\(rs$0-HL] \c
.        nop \(rs\(rs*[XH-APPENDIX-SN-DOT]\(rs"
\&.      shift 2
\&.      XH -S -N \(rs\(rs*[\(rs\(rs$0-ARGV]\(rs&\(rs \(rs& \(rs\(rs$@
\&.   \(rs"
\&.   \(rs" ...and ultimately, clean up the assembled argument list,
\&.   \(rs" (which is no longer required).
\&.   \(rs"
\&.      rm \(rs\(rs$0-ARGV
\&.   \(rs}
\&..
.sp \n[PD]u-\n[DD]u
.DE
.
Regardless of whether it has been called
.EM with ,
or
.EM without
the optional
.CWI dest-name > \%<
and
.CWI heading-level > \%<
arguments,
the
.CW \%XH-APPENDIX-NH
macro will
.EM always
leave the publicly visible
.CW \%XH-APPENDIX-NH-SN-DOT ,
and
.CW \%XH-APPENDIX-NH-SN-NO-DOT
string representations of the resultant section number\*[em]analogous
to the
.CW NH
macro's
.CW \%SN-DOT
and
.CW \%SN-NO-DOT
strings,
respectively\*[em]for any possible subsequent use
at the discretion of the document's author;
it also exposes the
.CW \%XH-APPENDIX-NH-HL
numeric register\*[em]for which the
.CW NH
macro offers no
.EM "publicly visible" \^\**
.FS
The
.CW NH
macro
.EM does
have an \%internal\[hy]use analogue for the
.CW \%XH-APPENDIX-NH-HL
register;
however,
this is
.EM undocumented ,
and thus,
.EM cannot
be considered to be publicly visible.
.FE
analogue\*[em]representing the effective value of
the heading level argument,
as passed internally,
to the
.CW SH
macro,
in order to control the type size used for the ensuing heading text.
.
.toc classify
.
.\" Local Variables:
.\" mode: nroff
.\" End:
.\" vim: filetype=groff
.\"
.\" $RCSfile: pdfmark.ms,v $: end of file
