Imported Upstream version 1.22.4
[platform/upstream/groff.git] / tmac / pdf.tmac
1 .ig
2
3 pdf.tmac
4
5  Copyright (C) 2011-2018 Free Software Foundation, Inc.
6       Written by Deri James <deri@chuzzlewit.myzen.co.uk>
7
8 This file is part of groff.
9
10 groff is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 groff is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23 Author's Note
24 =============
25
26 Much of the code in this macro has come from the excellent original work by
27 Keith Marshall (see attribution in the pdfmark.tmac file). I, however,
28 am solely responsible for any bugs I may have introduced into this file.
29 ..
30 .mso ps.tmac
31 .
32 .de pdf:SS
33 .       char \\$1 \\S'16'\\$1\\S'0'
34 ..
35 .pdf:SS \[+h]
36 .pdf:SS \[ts]
37 .pdf:SS \[*a]
38 .pdf:SS \[*b]
39 .pdf:SS \[*x]
40 .pdf:SS \[*d]
41 .pdf:SS \[*e]
42 .pdf:SS \[*f]
43 .pdf:SS \[*g]
44 .pdf:SS \[*y]
45 .pdf:SS \[*i]
46 .pdf:SS \[+f]
47 .pdf:SS \[*k]
48 .pdf:SS \[*l]
49 .pdf:SS \[*m]
50 .pdf:SS \[*n]
51 .pdf:SS \[*o]
52 .pdf:SS \[*p]
53 .pdf:SS \[*h]
54 .pdf:SS \[*r]
55 .pdf:SS \[*s]
56 .pdf:SS \[*t]
57 .pdf:SS \[*u]
58 .pdf:SS \[+p]
59 .pdf:SS \[*w]
60 .pdf:SS \[*c]
61 .pdf:SS \[*q]
62 .pdf:SS \[*z]
63 .char \[lh] \X'pdf: xrev'\[rh]\X'pdf: xrev'
64 .nr pdf:bm.nl 1
65 .de pdfmark
66 . nop \!x X ps:exec [\\$* pdfmark
67 ..
68 .de pdf:warn
69 . tm \\n(.F:\\n(.c: macro warning: \\$*
70 ..
71 .de pdf:error
72 . tm \\n(.F:\\n(.c: macro error: \\$*
73 ..
74 .de pdfinfo
75 .\" -------------------------------------------------------------------
76 .\" Usage:
77 .\"   .pdfinfo /FieldName field content ...
78 .\" Examples:
79 .\"   .pdfinfo /Title   A PDF Document
80 .\"   .pdfinfo /Author  Keith Marshall
81 .\" -------------------------------------------------------------------
82 .\"
83 .ds pdf:meta.field \\$1
84 .shift
85 .ie '\\n(.z'' .pdfmark \\*[pdf:meta.field] (\\$*) /DOCINFO
86 .el \!.pdfmark \\*[pdf:meta.field] (\\$*) /DOCINFO
87 .rm pdf:meta.field
88 ..
89 .de pdfview
90 .\" -------------------------------------------------------------------
91 .\" Usage:
92 .\"   .pdfview view parameters ...
93 .\" Examples:
94 .\"   .pdfview /PageMode /UseOutlines
95 .\"   .pdfview /Page 2 /View [/FitH \n(.p u]
96 .\" -------------------------------------------------------------------
97 .\"
98 .ie '\\n(.z'' .pdfmark \\$* /DOCVIEW
99 .el \!.pdfmark \\$* /DOCVIEW
100 ..
101 .\" =====================================================================
102 .\" Module PDFNOTE: Insert "Sticky Note" Style Comments in a PDF Document
103 .\" =====================================================================
104 .\"
105 .\" "PDFNOTE.WIDTH" and "PDFNOTE.HEIGHT" set the preferred size for
106 .\" display of the "sticky note" pane, when opened.  Acrobat Reader
107 .\" seems not to honour these -- perhaps GhostScript doesn't encode
108 .\" them correctly!  Anyway, let's set some suitable default values,
109 .\" in case the user has a set up which does work as advertised.
110 .\"
111 .nr PDFNOTE.WIDTH  3.5i
112 .nr PDFNOTE.HEIGHT 2.0i
113 .\"
114 .\" "pdf:bbox" defines the expression used to set the size and location
115 .\" of the bounding rectangle for display of notes and link "hot-spots".
116 .\" This is defined, such that a note is placed at troff's current text
117 .\" position on the current page, with its displayed image size defined
118 .\" by the "PDFNOTE.WIDTH" and "PDFNOTE.HEIGHT" registers, while the
119 .\" bounds for a link "hot-spot" are matched to the text region which
120 .\" defines the "hot-spot".
121 .\"
122 .ds pdf:bbox \\n[pdf:llx] u \\n[pdf:lly] u \\n[pdf:urx] u \\n[pdf:ury] u
123 .\"
124 .\" Getting line breaks into the text of a PDFNOTE is tricky -- we need
125 .\" to get a "\n" into the Postscript stream, but three levels of "\" are
126 .\" swallowed, when we invoke "pdfnote".  The following definition of "PDFLB",
127 .\" (for LineBreak), is rather ugly, but does allow us to use
128 .\"
129 .\"    .pdfnote  Some text.\*[PDFLB]Some more text, on a new line.
130 .\"
131 .ds PDFLB \\\\\\\\\\\\\\\\n
132 .\"
133 .de pdfnote
134 .\" ----------------------------------------------------------------------
135 .\" Usage:
136 .\"   .pdfnote [-T "Text for Title"] Text of note ...
137 .\" ----------------------------------------------------------------------
138 .\"
139 .\" First, compute the bounding rectangle,
140 .\" for this PDFNOTE instance
141 .\"
142 .   mk pdf:ury
143 .   nr pdf:llx \\n(.k+\\n(.o+\\n[.in]
144 .   nr pdf:lly \\n[pdf:ury]-\\n[PDFNOTE.HEIGHT]
145 .   nr pdf:urx \\n[pdf:llx]+\\n[PDFNOTE.WIDTH]
146 .   ds pdf:note.instance /Rect [\\*[pdf:bbox]]
147 .\"
148 .\" Parse any specified (recognisable) PDFNOTE options
149 .\"
150 .   while dpdf:note\\$1 \{\
151 .      pdf:note\\$1 \\$@
152 .      shift \\n[pdf:note.argc]
153 .      \}
154 .\"
155 .\" Emit the note, and clean up
156 .\"
157 .   pdfmark \\*[pdf:note.instance] /Subtype /Text /Contents (\\$*) /ANN
158 .   rm pdf:note.instance
159 .   rr pdf:note.argc
160 ..
161 .de pdf:note-T
162 .nr pdf:note.argc 2
163 .as pdf:note.instance " /Title (\\$2)
164 ..
165 .\" =====================================================================
166 .\" Module PDFBOOKMARK: Add an Outline Reference in the PDF Bookmark Pane
167 .\" =====================================================================
168 .\"
169 .\" "PDFBOOKMARK.VIEW" controls how the document will be displayed,
170 .\" when the user selects a bookmark.  This default setting will fit
171 .\" the page width to the viewing window, with the bookmarked entry
172 .\" located at the top of the viewable area.
173 .\"
174 .ds PDFBOOKMARK.VIEW /FitH \\n[PDFPAGE.Y] u
175 .\"
176 .\" "PDFOUTLINE.FOLDLEVEL" controls how the document outline will be
177 .\" displayed.  It is a number, defining the maximum heading level
178 .\" which will be visible, without outline expansion by the user, in
179 .\" the initial view of the document outline.  Assuming that no sane
180 .\" document will ever extend to 10,000 levels of nested headings,
181 .\" this initial default value causes outlines to be fully expanded.
182 .\"
183 .nr PDFOUTLINE.FOLDLEVEL 10000
184 .\"
185 .\" The actual job of creating an outline reference
186 .\" is performed by the "pdfbookmark" macro.
187 .\"
188 .de pdfbookmark
189 .\" ------------------------------------------------------------------
190 .\" Usage:
191 .\"   .pdfbookmark [-T tag] level "Text of Outline Entry"
192 .\"
193 .\"   $1 = nesting level for bookmark (1 is top level)
194 .\"   $2 = text for bookmark, (in PDF viewer bookmarks list)
195 .\" ------------------------------------------------------------------
196 .\"
197 .ie '\\n(.z'' \{\
198 .\"
199 .\" When we are at the top diversion level, i.e. actually emitting text
200 .\" to the output device stream, then we compute the location of, and
201 .\" plant this bookmark immediately.
202 .\"
203 .   \" Make the bookmark name "untagged" by default,
204 .   \" then parse any specified options, to set a "tag", if required
205 .   \"
206 .      ds pdf:href-T
207 .      while dpdf:href.opt\\$1 \{\
208 .         pdf:href.opt\\$1 \\$@
209 .         shift \\n[pdf:href.argc]
210 .         \}
211 .      rr pdf:href.argc
212 .   \"
213 .   \" If we found "--" to mark the end of the options, discard it
214 .   \"
215 .      if '\\$1'--' .shift
216 .   \"
217 .      nr pdf:bm.lev 0+\\$1
218 .      if \\n[pdf:bm.lev]==0 .nr pdf:bm.lev 1
219 .      if \\n[pdf:bm.lev]-1==\\n[PDFOUTLINE.FOLDLEVEL] .nr pdf:bm.lev \\n[pdf:bm.lev]*-1
220 .      nr pdf:bm.abslev 0+\\n[pdf:bm.lev]
221 .      if \\n[pdf:bm.lev]<0 .nr pdf:bm.abslev 0+\\n[pdf:bm.abslev]*-1
222 .      if \\n[pdf:bm.abslev]>\\n[pdf:bm.nl] .nr pdf:bm.nl \\n[pdf:bm.nl]+1
223 .      ie \\n[pdf:bm.abslev]>\\n[pdf:bm.nl] \{\
224 .        pdf:warn adjusted level \\n[pdf:bm.abslev] bookmark; should be <= \\n[pdf:bm.nl]
225 .        nr pdf:bm.abslev 0+\\n[pdf:bm.nl]
226 .        if \\n[pdf:bm.abslev]-1==\\n[PDFOUTLINE.FOLDLEVEL] .nr pdf:bm.lev \\n[pdf:bm.abslev]*-1
227 .      \}
228 .      el .nr pdf:bm.nl \\n[pdf:bm.abslev]
229 .      if \\n[pdf:bm.lev]<0 .nr pdf:bm.abslev \\n[pdf:bm.abslev]*-1
230 .      nr pdf:bm.lev 0+\\n[pdf:bm.abslev]
231 .      rr pdf:bm.abslev
232 .      shift
233 .   \"
234 .   \" Increment the bookmark serialisation index
235 .   \" in order to generate a uniquely serialised bookmark name,
236 .   \" ( which we return in the string "PDFBOOKMARK.NAME" ),
237 .   \"
238 .      nr pdf:bm.nr +1
239 .      ie '\\*[pdf:href-T]'' .ds PDFBOOKMARK.NAME pdf:bm\\n[pdf:bm.nr]
240 .      el .ds PDFBOOKMARK.NAME \\*[pdf:href-T]
241 .      pdf:href.sety
242 .         ds pdf:cleaned \\$*
243 .         ev pdfcln
244 .         tr \[em]-
245 .         nf
246 .         box pdf:clean
247 .         nop \\$*
248 .         fl
249 .         box
250 .         chop pdf:clean
251 .         asciify pdf:clean
252 .         length pdf:clean:len \\*[pdf:clean]
253 .         ds pdf:cleaned \\*[pdf:clean]
254 .         rm pdf:clean
255 .         ev
256 .         tr \[em]\[em]
257 .      ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\*[pdf:cleaned]
258 .      if dPDF.EXPORT .tm .ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\*[pdf:cleaned]
259 .      pdfmark /Dest /\\*[PDFBOOKMARK.NAME] /View [\\*[PDFBOOKMARK.VIEW]] /DEST
260 .      nop \!x X ps:exec [/Dest /\\*[PDFBOOKMARK.NAME] /Title (\\*[pdf:cleaned]) /Level \\n[pdf:bm.lev] /OUT pdfmark
261 .\".      pdfmark /Dest /\\*[PDFBOOKMARK.NAME] /Title "(\\*[pdf:cleaned])" /Level \\n[pdf:bm.lev] /OUT
262 .      pdf:href.options.clear
263 .      rr PDFPAGE.Y
264 .      rm pdf:cleaned
265 .      rm pdf:clean
266 .      \}
267 .   \}
268 .el \{\
269 .\"
270 .\" But when we are collecting a diversion which will be written out later,
271 .\" then we must defer bookmark placement, until we emit the diversion.
272 .\" (don't rely on $0 == pdfbookmark here; it may be a volatile alias).
273 .\"
274 .   nop \!.pdfbookmark \\$@
275 .   \}
276 ..
277 .
278 .de pdfclean
279 .  ie '\\n(.z'' \{\
280 .         ds pdfcleaned \\$*
281 .         ev pdfcln
282 .         tr \[em]-
283 .         nf
284 .         box pdf:clean
285 .         nop \\*[\\*[pdfcleaned]]
286 .         fl
287 .         box
288 .         chop pdf:clean
289 .         asciify pdf:clean
290 .         ev
291 .         ds \\*[pdfcleaned] "\\*[pdf:clean]
292 .         rm pdf:clean
293 .         tr \[em]\[em]
294 .  el .nop \!.pdfclean \\$@
295 ..
296 .\"
297 .\" =============================================================
298 .\" Module PDFHREF: Create Hypertext References in a PDF Document
299 .\" =============================================================
300 .\"
301 .\" "PDFHREF.VIEW" controls how the document will be displayed,
302 .\" when the user follows a link to a named reference.
303 .\"
304 .ds PDFHREF.VIEW     /FitH \\n[PDFPAGE.Y] u
305 .\"
306 .\" This default setting will fit the page width to the viewing
307 .\" window, with the bookmarked entry located close to the top
308 .\" of the viewable area.  "PDFHREF.VIEW.LEADING" controls the
309 .\" actual distance below the top of the viewing window, where
310 .\" the reference will be positioned; 5 points is a reasonable
311 .\" default offset.
312 .\"
313 .nr PDFHREF.VIEW.LEADING  5.0p
314 .\"
315 .\" Yuk!!!
316 .\" PDF view co-ordinates are mapped from the bottom left corner,
317 .\" of the page, whereas page printing co-ordinates are mapped
318 .\" conventionally, from top left.
319 .\"
320 .\" Macro "pdf:href.sety" transforms the vertical position of the
321 .\" last printed baseline, from the printing co-ordinate domain to
322 .\" the PDF view domain.
323 .\"
324 .de pdf:href.sety
325 .\" ----------------------------------------------------------------
326 .\" Usage:
327 .\"   .pdf:href.sety
328 .\" ----------------------------------------------------------------
329 .\"
330 .\" This computation yields the vertical view co-ordinate
331 .\" in groff's basic units; don't forget to append grops' "u"
332 .\" conversion operator, when writing the pdfmark!
333 .\"
334 .nr PDFPAGE.Y (\\n[PDFHREF.VIEW.LEADING]-\\n(nl)
335 ..
336 .\" When we create a link "hot-spot" ...
337 .\" "PDFHREF.LEADING" sets the distance above the top of the glyph
338 .\" bounding boxes, in each line of link text, over which the link
339 .\" hot-spot will extend, while "PDFHREF.HEIGHT" sets the hot-spot
340 .\" height, PER LINE of text occupied by the reference.
341 .\"
342 .\" Since most fonts specify some leading space within the bounding
343 .\" boxes of their glyphs, a better appearance may be achieved when
344 .\" NEGATIVE leading is specified for link hot-spots;  indeed, when
345 .\" the default 10pt Times font is used, -1.0 point seems to be a
346 .\" reasonable default value for "PDFHREF.LEADING" -- it may be
347 .\" changed, if desired.
348 .\"
349 .\" "PDFHREF.HEIGHT" is initially set as one vertical spacing unit;
350 .\" note that it is defined as a string, so it will adapt to changes
351 .\" in the vertical spacing.  Changing it is NOT RECOMMENDED.
352 .\"
353 .nr PDFHREF.LEADING  2.0p
354 .ds PDFHREF.HEIGHT   1.0v
355 .\"
356 .\" PDF readers generally place a rectangular border around link
357 .\" "hot-spots".  Within text, this looks rather ugly, so we set
358 .\" "PDFHREF.BORDER" to suppress it -- the three zeroes represent
359 .\" the border parameters in the "/Border [0 0 0]" PDFMARK string,
360 .\" and may be changed to any valid form, as defined in Adobe's
361 .\" PDFMARK Reference Manual.
362 .\"
363 .ds PDFHREF.BORDER   0 0 0
364 .\"
365 .\" "PDFHREF.COLOUR" (note British spelling) defines the colour to
366 .\" be used for display of link "hot-spots".  This will apply both
367 .\" to borders, if used, and, by default to text; however, actual
368 .\" text colour is set by "PDFHREF.TEXT.COLOUR", which may be reset
369 .\" independently of "PDFHREF.COLOUR", to achieve contrasting text
370 .\" and border colours.
371 .\"
372 .\" "PDFHREF.COLOUR" must be set to a sequence of three values,
373 .\" each in the range 0.0 .. 1.0, representing the red, green, and
374 .\" blue components of the colour specification in the RGB colour
375 .\" domain, which is shared by "groff" and the PDF readers.
376 .\"
377 .ds PDFHREF.COLOUR   0.35 0.00 0.60
378 .defcolor pdf:href.colour rgb \*[PDFHREF.COLOUR]
379 .\"
380 .\" "PDFHREF.TEXT.COLOUR", on the other hand, is simply defined
381 .\" using any "groff" colour name -- this default maps it to the
382 .\" same colour value as "PDFHREF.COLOUR".
383 .\"
384 .ds PDFHREF.TEXT.COLOUR  pdf:href.colour
385 .\"
386 .\" Accommodate users who prefer the American spelling, COLOR, to
387 .\" the British spelling, COLOUR.
388 .\"
389 .als PDFHREF.COLOR       PDFHREF.COLOUR
390 .als PDFHREF.TEXT.COLOR  PDFHREF.TEXT.COLOUR
391 .\"
392 .\" All PDF "Hypertext" reference capabilities are accessed
393 .\" through the "pdfhref" macro
394 .\"
395 .de pdfhref
396 .\" -----------------------------------------------------------------
397 .\" Usage:
398 .\"   .pdfhref <subcommand [options ...] [parameters ...]> ...
399 .\" -----------------------------------------------------------------
400 .\"
401 .\"
402 .\" Loop over all subcommands specified in the argument list
403 .\"
404 .   while \\n(.$ \{\
405 .   \"
406 .   \" Initially, assume each subcommand will complete successfully
407 .   \"
408 .      nr pdf:href.ok 1
409 .   \"
410 .   \" Initialise -E and -X flags in the OFF state
411 .   \"
412 .      nr pdf:href-E 0
413 .      nr pdf:href-X 0
414 .   \"
415 .   \" Handle the case where subcommand is specified as "-class",
416 .   \" setting up appropriate macro aliases for subcommand handlers.
417 .   \"
418 .      if dpdf*href\\$1       .als pdf*href      pdf*href\\$1
419 .      if dpdf*href\\$1.link  .als pdf*href.link pdf*href\\$1.link
420 .      if dpdf*href\\$1.file  .als pdf*href.file pdf*href\\$1.file
421 .   \"
422 .   \" Repeat macro alias setup
423 .   \" for the case where the subcommand is specified as "class",
424 .   \" (without a leading hyphen)
425 .   \"
426 .      if dpdf*href-\\$1      .als pdf*href      pdf*href-\\$1
427 .      if dpdf*href-\\$1.link .als pdf*href.link pdf*href-\\$1.link
428 .      if dpdf*href-\\$1.file .als pdf*href.file pdf*href-\\$1.file
429 .   \"
430 .   \" Process one subcommand ...
431 .   \"
432 .      ds pdf*href.class \\$1
433 .      ie dpdf*href \{\
434 .      \"
435 .      \" Subcommand "class" is recognised ...
436 .      \" discard the "class" code from the argument list,
437 .      \" set the initial argument count to swallow all arguments,
438 .      \" and invoke the selected subcommand handler.
439 .      \"
440 .         shift
441 .         nr pdf:argc \\n(.$
442 .         pdf*href \\$@
443 .      \"
444 .      \" When done,
445 .      \" discard all arguments actually consumed by the handler,
446 .      \" before proceeding to the next subcommand (if any).
447 .      \"
448 .         shift \\n[pdf:argc]
449 .      \}
450 .      el \{\
451 .      \"
452 .      \" Subcommand "class" is not recognised ...
453 .      \" issue a warning, and discard the entire argument list,
454 .      \" so aborting this "pdfhref" invocation
455 .      \"
456 .         pdf:warn \\$0: undefined reference class '\\$1' ignored
457 .         shift \\n(.$
458 .         \}
459 .   \"
460 .   \" Clean up temporary reference data,
461 .   \" to ensure it doesn't propagate to any future reference
462 .   \"
463 .      rm pdf*href pdf:href.link pdf:href.files
464 .      rr pdf:href-E
465 .      pdf:href.options.clear
466 .      \}
467 .   rr pdf:href.ok
468 ..
469 .\"
470 .\" Macros "pdf:href.flag" and "pdf:href.option"
471 .\" provide a generic mechanism for switching on flag type options,
472 .\" and for decoding options with arguments, respectively
473 .\"
474 .de pdf:href.flag
475 .\" ----------------------------------------------------------------------
476 .\" ----------------------------------------------------------------------
477 .nr pdf:href\\$1 1
478 .nr pdf:href.argc 1
479 ..
480 .de pdf:href.option
481 .\" ----------------------------------------------------------------------
482 .\" ----------------------------------------------------------------------
483 .ds pdf:href\\$1 \\$2
484 .nr pdf:href.argc 2
485 ..
486 .\"
487 .\" Valid PDFHREF options are simply declared
488 .\" by aliasing option handlers to "pdf:href.option",
489 .\" or to "pdf:href.flag", as appropriate
490 .\"
491 .als pdf:href.opt-A pdf:href.option   \" affixed text
492 .als pdf:href.opt-D pdf:href.option   \" destination name
493 .als pdf:href.opt-E pdf:href.flag     \" echo link descriptor
494 .als pdf:href.opt-F pdf:href.option   \" remote file specifier
495 .als pdf:href.opt-N pdf:href.option   \" reference name
496 .als pdf:href.opt-P pdf:href.option   \" prefixed text
497 .als pdf:href.opt-T pdf:href.option   \" bookmark "tag"
498 .als pdf:href.opt-X pdf:href.flag     \" cross reference
499 .\"
500 .\" For references to another document file
501 .\" we also need to support OS dependent file name specifiers
502 .\"
503 .als pdf:href.opt-DF pdf:href.option  \" /DOSFile specifier
504 .als pdf:href.opt-MF pdf:href.option  \" /MacFile specifier
505 .als pdf:href.opt-UF pdf:href.option  \" /UnixFile specifier
506 .als pdf:href.opt-WF pdf:href.option  \" /WinFile specifier
507 .\"
508 .\" Macro "pdf:href.options.clear" ensures that ALL option
509 .\" argument strings are deleted, after "pdfhref" has completed
510 .\" all processing which depends on them
511 .\"
512 .de pdf:href.options.clear
513 .\" -----------------------------------------------------------------
514 .\" Usage:
515 .\"   .pdf:href.options.clear [option ...]
516 .\" -----------------------------------------------------------------
517 .\"
518 .\" When an option list is specified ...
519 .\"
520 .ie \\n(.$ \{\
521 .   \"
522 .   \" then loop through the list,
523 .   \" deleting each specified option argument string in turn
524 .   \"
525 .   while \\n(.$ \{\
526 .      if dpdf:href-\\$1 .rm pdf:href-\\$1
527 .      shift
528 .      \}
529 .   \}
530 .\"
531 .\" ... but when no list is specified,
532 .\" then recurse, to clear all known option argument strings
533 .\"
534 .el .pdf:href.options.clear A D F N P T DF MF UF WF
535 ..
536 .\"
537 .\" Macro "pdf*href-M" is the handler invoked by "pdfhref", when
538 .\" called with the "M" reference class specifier, to create a
539 .\" named cross reference mark, and to emit a cross reference
540 .\" data record, as specified by "PDFHREF.INFO".
541 .\"
542 .de pdf*href-M
543 .\" -----------------------------------------------------------------
544 .\" Usage:
545 .\"   .pdfhref M [-N name | -D name] [-E] descriptive text ...
546 .\" -----------------------------------------------------------------
547 .\"
548 .\" Initially, declare the -D and -N string options as empty,
549 .\" so we avoid warning messages when we try to use them, and find
550 .\" that they are undefined.
551 .\"
552 .ds pdf:href-D
553 .ds pdf:href-N
554 .\"
555 .\" Parse, interpret, and strip any specified options from the
556 .\" argument list.  (Note that only options with a declared handler
557 .\" will be processed; there is no provision for detecting invalid
558 .\" options -- anything which is not recognised is assumed to start
559 .\" the "descriptive text" component of the argument list).
560 .\"
561 .while dpdf:href.opt\\$1 \{\
562 .   pdf:href.opt\\$1 \\$@
563 .   shift \\n[pdf:href.argc]
564 .   \}
565 .\"
566 .\" If we found "--", to mark the end of the options,
567 .\" then we should discard it.
568 .\"
569 .if '\\$1'--' .shift
570 .\"
571 .\" All PDF reference markers MUST be named. The name may have been
572 .\" supplied using the "-N Name" option, (or the "-D Name" option);
573 .\" if not, deduce it from the first "word" in the "descriptive text",
574 .\" if any, and set the marker -- if we still can't identify the name
575 .\" for the destination, then this marker will not be created.
576 .\"
577 .ds PDFBOOKMARK.NAME "\\*[pdf:href-N]\\*[pdf:href-D]
578 .pdf*href.set \\*[PDFBOOKMARK.NAME] \\$1
579 .ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\$*
580 .if dPDF.EXPORT .tm .ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\$*
581 .\"
582 .\"
583 .\" Irrespective of whether this marker is created, or not,
584 .\" the descriptive text will be copied to the groff output stream,
585 .\" provided the "-E" option was specified
586 .\"
587 .if \\n[pdf:href-E] \&\\$*
588 ..
589 .de pdf*href-F
590 .\"do nothing
591 ..
592 .\"
593 .de pdf*href.set
594 .\" ----------------------------------------------------------------------
595 .\" ----------------------------------------------------------------------
596 .ie \\n(.$ \{\
597 .   \"
598 .   \" a marker name has been supplied ...
599 .   \" if we are formatting for immediate output,
600 .   \" emit PDFMARK code to establish the associated view
601 .   \"
602 .   ie '\\n(.z'' \{\
603 .      pdf:href.sety
604 .      pdfmark /Dest /\\$1 /View [\\*[PDFHREF.VIEW]] /DEST
605 .      ds PDFHREF.NAME \\$1
606 .      rr PDFPAGE.Y
607 .      \}
608 .   \"
609 .   \" but, when formatting a diversion ...
610 .   \" delay output of the PDFMARK code, until the diversion
611 .   \" is eventually written out
612 .   \"
613 .   el \!.\\$0 \\$@
614 .   \"
615 .   \}
616 .el \{\
617 .   \" marker is unnamed ...
618 .   \" issue error message; do not emit reference data
619 .   \"
620 .   pdf:warn pdfhref destination marker must be named
621 .   \}
622 ..
623 .\"
624 .de pdf*href
625 .\" ------------------------------------------------------------------
626 .\" Usage:
627 .\"   .pdf*href class [options ...] [link text ...]
628 .\" ------------------------------------------------------------------
629 .\"
630 .\" First, we initialise an empty string, which will be affixed to
631 .\" the end of the "link text".  (This is needed to cancel the effect
632 .\" of a "\c" escape, which is placed at the end of the "link text"
633 .\" to support the "-A" option -- any text supplied by the user, when
634 .\" the "-A" option is specified, will replace this empty string).
635 .\"
636 .ds pdf:href-A
637 .\"
638 .\" Now we interpret, and remove any specified options from the
639 .\" argument list.  (Note that only options with a declared handler
640 .\" will be processed;  there is no provision for detecting invalid
641 .\" options -- anything which is not recognised is assumed to start
642 .\" the "link text" component of the argument list).
643 .\"
644 .while dpdf:href.opt\\$1 \{\
645 .   pdf:href.opt\\$1 \\$@
646 .   shift \\n[pdf:href.argc]
647 .   \}
648 .\"
649 .\" If we found "--", to mark the end of the options, then we should
650 .\" discard it.
651 .\"
652 .if '\\$1'--' .shift
653 .\"
654 .\" All PDF link classes REQUIRE a named destination.  This may have
655 .\" been supplied using the "-D Name" option, but, if not, deduce it
656 .\" from the first "word" in the "link text", if any -- if we still
657 .\" can't identify the destination, then set "pdf:href.ok" to zero,
658 .\" so this link will not be created.
659 .\"
660 .if !dpdf:href-D .pdf:href.option -D \\$1
661 .if '\\*[pdf:href-D]'' \{\
662 .   pdf:error pdfhref has no destination
663 .   nr pdf:href.ok 0
664 .   \}
665 .\"
666 .\" Now, initialise a string, defining the PDFMARK code sequence
667 .\" to create the reference, using the appropriate type indicators.
668 .\"
669 .ds pdf:href.link /Subtype /Link \\*[pdf*href.link]
670 .\"
671 .\" And now, we have no further use for "pdf*href.link".
672 .\"
673 .rm pdf*href.link
674 .\"
675 .\" If the user specified any "link prefix" text, (using the "-P text"
676 .\" option), then emit it BEFORE processing the "link text" itself.
677 .\"
678 .if dpdf:href-P \&\\*[pdf:href-P]\c
679 .ie \\n[pdf:href.ok] \{\
680 .   \"
681 .   \" This link is VALID (so far as we can determine) ...
682 .   \" Modify the "link text" argument specification, as required,
683 .   \" to include any pre-formatted cross reference information
684 .   \"
685 .   ie \\n(.$ \{\
686 .      \"
687 .      \" One or more "link text" argument(s) are present,
688 .      \" so, set the link description from the argument(s) ...
689 .      \"
690 .      ds PDFHREF.DESC \\\\$*
691 .      \}
692 .   el \{\
693 .      ie dpdf:look(\\*[pdf:href-D]) .ds PDFHREF.DESC \\*[pdf:look(\\*[pdf:href-D])]
694 .      el .ds PDFHREF.DESC Unknown
695 .      \}
696 .   \" Apply border and colour specifications to the PDFMARK string
697 .   \" definition, as required.
698 .   \"
699 .   if dPDFHREF.BORDER .as pdf:href.link " /Border [\\*[PDFHREF.BORDER]]
700 .   if dPDFHREF.COLOUR .as pdf:href.link " /Color  [\\*[PDFHREF.COLOUR]]
701 .   \"
702 .   \" Emit the "link text", in its appropriate colour, marking the
703 .   \" limits of its bounding box(es), as the before and after output
704 .   \" text positions.
705 .   \"
706 \#.   if dPDFHREF.COLOUR .defcolor pdf:href.colour rgb \\*[PDFHREF.COLOUR]
707 .   nr pdf:bm.width \\w'\\*[PDFHREF.DESC]'
708 .   nop \&\m[\\*[PDFHREF.TEXT.COLOUR]]\c
709 .   device pdf: markstart \\n[rst] \\n[rsb] \\n[PDFHREF.LEADING] \\*[pdf:href.link]
710 .   nop \&\\*[PDFHREF.DESC]\X'pdf: markend'\m[]\c
711 .   \"
712 .   \" Clean up the temporary registers and strings, used to
713 .   \" compute the "hot-spot" bounds, and format the reference,
714 .   \"
715 .   rm PDFHREF.DESC PDFHREF.TEXT
716 .   \}
717 .\"
718 .\" But when we identify an INVALID link ...
719 .\" We simply emit the "link text", with no colour change, no border,
720 .\" and no associated "hot-spot".
721 .\"
722 .el \&\\$*\c
723 .\"
724 .\" And then, if the user specified any affixed text, (using the
725 .\" "-A text" option), we tack it on at the end.
726 .\"
727 .nop \&\\*[pdf:href-A]
728 ..
729 .\" Macro "pdf*href-I" is used for one time initialisation of special
730 .\" "pdfhref" features; (currently, only the above page trap hook is
731 .\" supported, but it is implemented with one level of indirection, to
732 .\" accommodate possible future expansion).
733 .
734 .de pdf*href-I
735 .\" ----------------------------------------------------------------------
736 .\" Usage:
737 .\"   .pdfhref I -<option> <optarg> [-<option> <optarg>] ...
738 .\" ----------------------------------------------------------------------
739 .\"
740 .\" Loop over all arguments, in pairs ...
741 .
742 .while \\n(.$ \{\
743 .   \"
744 .   \" handing them off to their respective initialisers,
745 .   \" when suitable initialisers exist, or complaining otherwise.
746 .   \"
747 .   ie dpdf*href\\$1.init .pdf*href\\$1.init \\$2
748 .   el .pdf*error pdfhref:init: unknown feature '\\$1'
749 .   shift 2
750 .   \}
751 ..
752 .\" Before we can use the page break "hook", we need to initialise it
753 .\" as an addendum to a regular page break trap. To ensure that we don't
754 .\" compromise the user's page trap setup, we leave the onus for this
755 .\" initialisation with the user, but we provide the "pdf*href-PT.init"
756 .\" macro, (invoked by ".pdfhref I -PT <macro-name>"), to implement a
757 .\" suitable initialisation action.
758 .\"
759 .\"
760 .\" "pdf*href-L" is the generic handler for creating references to
761 .\" named destinations in PDF documents.  It supports both local
762 .\" references, to locations within the same document, through its
763 .\" "pdf*href-L.link" attribute, and also references to locations
764 .\" in any other PDF document, through "pdf*href-L.file".
765 .\"
766 .als pdf*href-L      pdf*href
767 .ds  pdf*href-L.link /Dest /\\\\*[pdf:href-D]
768 .ds  pdf*href-L.file /Action /GoToR \\\\*[pdf:href.files] \\*[pdf*href-L.link]
769 .\"
770 .\" "pdf*href-O" is the "official" handler for creating PDF
771 .\" document outlines.  It is simply an alias to "pdfbookmark",
772 .\" which may also be invoked directly, if preferred.  Neither
773 .\" a "pdf*href-O.link" nor a "pdf*href-O.file" attribute is
774 .\" required.
775 .\"
776 .als pdf*href-O      pdfbookmark
777 .\"
778 .\" "pdf*href-W" is the generic handler for creating references to
779 .\" web resources, (or any resource specified by a uniform resource
780 .\" identifier).  Such resource links are fully specified by the
781 .\" "pdf*href-W.link" attribute.
782 .\"
783 .als pdf*href-W      pdf*href
784 .ds  pdf*href-W.link /Action << /Subtype /URI /URI (\\\\*[pdf:href-D]) >>
785 .nr pdf:bm.nl 0
786 .\"
787 .\" "pdfmarksuspend" and "pdfmarkrestart" should be used in any page trap
788 .\" macros to prevent output from the page trap macro being considered part
789 .\" of a 'hot spot' when it crosses a page boundary.
790 .de pdfmarksuspend
791 .nop \!x X pdf: marksuspend
792 ..
793 .de pdfmarkrestart
794 .nop \!x X pdf: markrestart
795 ..
796 .de pdfpagename
797 .nop \!x X pdf: pagename \\$1
798 ..
799 .de pdfswitchtopage
800 .nop \!x X pdf: switchtopage \\$*
801 ..
802 .de pdfpause
803 .nop \!x X ps: exec %%%%PAUSE
804 ..
805 .de pdftransition
806 .nop \!x X pdf: transition \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
807 ..
808 .\" Local Variables:
809 .\" mode: nroff
810 .\" End:
811 .\" vim: filetype=groff:
812 .\" pdf.tmac: end of file