groff: Page Location Traps

 
 5.24.1 Page Location Traps
 --------------------------
 
 "Page location traps" perform an action when 'gtroff' reaches or passes
 a certain vertical location on the page.  Page location traps have a
 variety of purposes, including:
 
    * setting headers and footers
 
    * setting body text in multiple columns
 
    * setting footnotes
 
  -- Request: .vpt flag
  -- Register: \n[.vpt]
      Enable vertical position traps if FLAG is non-zero, or disables
      them otherwise.  Vertical position traps are traps set by the 'wh'
      or 'dt' requests.  Traps set by the 'it' request are not vertical
      position traps.  The parameter that controls whether vertical
      position traps are enabled is global.  Initially vertical position
      traps are enabled.  The current setting of this is available in the
      '.vpt' read-only number register.
 
      Note that a page can't be ejected if 'vpt' is set to zero.
 
  -- Request: .wh dist [macro]
      Set a page location trap.  Non-negative values for DIST set the
      trap relative to the top of the page; negative values set the trap
      relative to the bottom of the page.  Default scaling indicator is
      'v'; values of DIST are always rounded to be multiples of the
      vertical resolution (as given in register '.V').
 
      MACRO is the name of the macro to execute when the trap is sprung.
      If MACRO is missing, remove the first trap (if any) at DIST.
 
      The following is a simple example of how many macro packages set
      headers and footers.
 
           .de hd                \" Page header
           '  sp .5i
           .  tl 'Title''date'
           '  sp .3i
           ..
           .
           .de fo                \" Page footer
           '  sp 1v
           .  tl ''%''
           '  bp
           ..
           .
           .wh 0   hd            \" trap at top of the page
           .wh -1i fo            \" trap one inch from bottom
 
      A trap at or below the bottom of the page is ignored; it can be
      made active by either moving it up or increasing the page length so
      that the trap is on the page.
 
      Negative trap values always use the _current_ page length; they are
      not converted to an absolute vertical position:
 
           .pl 5i
           .wh -1i xx
           .ptr
               => xx      -240
           .pl 100i
           .ptr
               => xx      -240
 
      It is possible to have more than one trap at the same location; to
      do so, the traps must be defined at different locations, then moved
      together with the 'ch' request; otherwise the second trap would
      replace the first one.  Earlier defined traps hide later defined
      traps if moved to the same position (the many empty lines caused by
      the 'bp' request are omitted in the following example):
 
           .de a
           .  nop a
           ..
           .de b
           .  nop b
           ..
           .de c
           .  nop c
           ..
           .
           .wh 1i a
           .wh 2i b
           .wh 3i c
           .bp
               => a b c
           .ch b 1i
           .ch c 1i
           .bp
               => a
           .ch a 0.5i
           .bp
               => a b
 
  -- Register: \n[.t]
      A read-only number register holding the distance to the next trap.
 
      If there are no traps between the current position and the bottom
      of the page, it contains the distance to the page bottom.  In a
      diversion, the distance to the page bottom is infinite (the
      returned value is the biggest integer that can be represented in
      'groff') if there are no diversion traps.
 
  -- Request: .ch macro [dist]
      Change the location of a trap.  The first argument is the name of
      the macro to be invoked at the trap, and the second argument is the
      new location for the trap (note that the parameters are specified
      in opposite order as in the 'wh' request).  This is useful for
      building up footnotes in a diversion to allow more space at the
      bottom of the page for them.
 
      Default scaling indicator for DIST is 'v'.  If DIST is missing, the
      trap is removed.
 
  -- Register: \n[.ne]
      The read-only number register '.ne' contains the amount of space
      that was needed in the last 'ne' request that caused a trap to be
      sprung.  Useful in conjunction with the '.trunc' register.  See
      Page Control, for more information.
 
      Since the '.ne' register is only set by traps it doesn't make much
      sense to use it outside of trap macros.
 
  -- Register: \n[.trunc]
      A read-only register containing the amount of vertical space
      truncated by the most recently sprung vertical position trap, or,
      if the trap was sprung by an 'ne' request, minus the amount of
      vertical motion produced by the 'ne' request.  In other words, at
      the point a trap is sprung, it represents the difference of what
      the vertical position would have been but for the trap, and what
      the vertical position actually is.
 
      Since the '.trunc' register is only set by traps it doesn't make
      much sense to use it outside of trap macros.
 
  -- Register: \n[.pe]
      A read-only register that is set to 1 while a page is ejected with
      the 'bp' request (or by the end of input).
 
      Outside of traps this register is always zero.  In the following
      example, only the second call to 'x' is caused by 'bp'.
 
           .de x
           \&.pe=\\n[.pe]
           .br
           ..
           .wh 1v x
           .wh 4v x
           A line.
           .br
           Another line.
           .br
               => A line.
                  .pe=0
                  Another line.
 
                  .pe=1
 
    An important fact to consider while designing macros is that
 diversions and traps do not interact normally.  For example, if a trap
 invokes a header macro (while outputting a diversion) that tries to
 change the font on the current page, the effect is not visible before
 the diversion has completely been printed (except for input protected
 with '\!' or '\?') since the data in the diversion is already formatted.
 In most cases, this is not the expected behaviour.